EnglishРусский Map
Rye

Конфигурация на Rye по принципу белого списка

title
Конфигурация на Rye по принципу белого списка
type
summary
summary
Доводы Refaktor в пользу встраивания Rye в Go-приложения как языка конфигурации без зашитых ключевых слов и с белым списком возможностей
parent
rye-lang
tags
config-languages, go, embedded-scripting, capability-security
created
2026-05-11
updated
2026-05-11
lang
ru
source_updated
2026-05-11
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-medium

Разбор в блоге refaktor/rye, где проектирование языков конфигурации представлено как выбор между двумя тупиками: начать со слишком простого формата и потом на живую нитку прикручивать самодельный язык (путь YAML/HCL) либо взять полноценный язык и пытаться заблокировать в нём лишнее (путь Lua/Python). rye-lang предлагается как третий вариант: стартовать вообще без каких-либо языковых конструкций и регистрировать ровно те возможности, которые вы хотите дать автору конфигурации.

В статье упоминается десятое правило Гринспена и приводятся привычные примеры: шаблонизация в два языка у Helm, эмуляция отсутствующего if через блоки dynamic в Terraform, разросшиеся конструкции управления потоком в Nginx. Затем разбирается альтернатива: встроить Lua, отключить os, io, require. Блог комментирует это так: "чёрные списки защищают от известных опасностей, но всегда остаются неизвестные". Общую концепцию см. в whitelist-capability-config.

В чём отличие Rye

В Rye нет зарезервированного синтаксиса для управления потоком исполнения. Такие слова, как if, fn, loop, +, *, представляют собой обычные функции, зарегистрированные на уровне библиотеки. Базовый интерпретатор умеет лишь:

  • Загружать синтаксис в блоки значений
  • Привязывать значения к словам через set-word: и mod-word::

Это и есть нулевой уровень возможностей. Всё остальное нужно явно регистрировать из Go. В сравнении со Starlark, который более зрелый, но безусловно предоставляет if/for/def и подключает модули по принципу "всё или ничего", Rye позволяет зарегистрировать _+ без _* и выдать if без loop.

Практический пример

Веб-сервер на Go, раздающий markdown-файлы и настроенный через Rye. В статье показано шесть шагов с постепенным добавлением возможностей и подсчётом необходимых строк на Go:

Шаг Строки Go Добавленная возможность
1 ~80 Статические значения, данные в стиле INI
2 +2 Арифметика (_*, _+)
3 +6 Встроенная функция get-env + any для значений по умолчанию
4 +14 Встроенная функция route, if, _=
5 +6 fn, replace, capitalize, str - пользовательские функции, вызываемые из Go на каждый запрос
6 +2 probe и enter-console (живой REPL внутри контекста работающей конфигурации)

Каждая возможность подключается одним вызовом RegisterBuiltinsFilter или RegisterBuiltin. К пятому шагу в конфигурации уже можно писать так:

page-title: fn { slug } {
    slug .replace "-" " " |capitalize
}

...а рантайм Go вызывает page-title при каждом запросе через ps.Ctx.GetFunction + evaldo.CallFunctionArgsN. Конфигурация превратилась в расширение самого приложения.

Шестой шаг особенно необычен. enter-console переводит работающий процесс в Rye REPL с уже загруженным контекстом текущей конфигурации. В интерактивном режиме можно выполнить lc, чтобы посмотреть привязки, вызвать probe port для инспекции значения или переопределить его через port:: "8080". По нажатию Ctrl-c выполнение продолжается уже с изменённым контекстом. Задумка в том, чтобы отлаживать конфигурацию удобнее, чем через вывод отладочной печати, не теряя при этом надёжности в продакшене, поскольку REPL подключается строго выборочно при регистрации.

Ограничения исполнения

Помимо набора доступных слов, объём работы интерпретатора ограничивается двумя лимитами:

ps.MaxCallDepth = 50
ps.MaxOps       = 10_000

Значение по умолчанию 0 означает отсутствие ограничений. Установка этих параметров перед вызовом EvalBlock гарантирует, что бесконечная рекурсия или зацикливание вернут ошибку, а не подвесят процесс.

На что статья не претендует

В заключении прямо подчёркивается: речь идёт об управлении возможностями, а не о песочнице безопасности. Rye исполняется прямо в процессе хоста. Если зарегистрировать небезопасную встроенную функцию, конфигурация тут же получит к ней доступ. Автор не предлагает Rye как замену Lua для работы с недоверенным вводом - это способ уберечь дружественную конфигурацию от превращения в HCL со странностями.

Связанные страницы

  • whitelist-capability-config - общий паттерн: встраиваемый скриптинг с запретом по умолчанию
  • rye-lang - описание языка (гомоиконичный, встраиваемый в Go, без зарезервированных конструкций)
  • ryelang-blog - трекер публикаций блога
  • no-silver-bullet - разрастание языков конфигурации как случайная сложность
  • sandboxing-ai-agents - разграничение уровней возможностей как сквозная тема в публикациях 2026 года