ПОЧЕМУ стало ключевым словом, язык поднят до версии 2
- метка обоснования пишется заглавными и вошла в словарь набора: скелет правила теперь целиком из ключевых слов, а не смесь `**ДОЛЖЕН.**` и `**Почему.**`; в переводе на другой язык метка меняется как остальные слова (ПОЧЕМУ / WHY), 235 вхождений заменены - метки правила выделены из шкалы в отдельный перечень: ПОЧЕМУ и МЕХАНИЗИРОВАНО обязательности не задают, а размечают части, и стандартом не даются ни в одном языке — раньше МЕХАНИЗИРОВАНО висело строкой в таблице модальности - версия языка поднята до 2, потому что изменение формы меняет чтение уже написанного текста; строка о версии в двенадцати конвенциях перечисляет теперь и метки, а служебные слова сценария в неё по-прежнему не входят
This commit is contained in:
+24
-24
@@ -7,9 +7,9 @@ prefix: CONF
|
||||
Как устроена конфигурация: где лежит, как попадает в процесс, что с
|
||||
секретами и когда падает.
|
||||
|
||||
Ключевые слова ДОЛЖЕН, НЕ ДОЛЖЕН, СЛЕДУЕТ, НЕ СЛЕДУЕТ, ДОПУСКАЕТСЯ и отметка
|
||||
МЕХАНИЗИРОВАНО толкуются как описано в языке конвенций версии 1 — тогда и
|
||||
только тогда, когда написаны заглавными.
|
||||
Ключевые слова ДОЛЖЕН, НЕ ДОЛЖЕН, СЛЕДУЕТ, НЕ СЛЕДУЕТ, ДОПУСКАЕТСЯ и метки
|
||||
ПОЧЕМУ и МЕХАНИЗИРОВАНО толкуются как описано в языке конвенций версии 2 —
|
||||
тогда и только тогда, когда написаны заглавными.
|
||||
|
||||
## Область действия
|
||||
|
||||
@@ -25,7 +25,7 @@ prefix: CONF
|
||||
**ДОЛЖЕН.** Приложение читает параметры из файла конфигурации; переменные
|
||||
окружения источником конфигурации не служат.
|
||||
|
||||
**Почему.** Три довода, по убыванию веса:
|
||||
**ПОЧЕМУ.** Три довода, по убыванию веса:
|
||||
|
||||
- **Один типизированный источник.** Файл несёт секции, комментарии,
|
||||
единицы измерения и валидируется целиком. Окружение — плоский набор
|
||||
@@ -48,7 +48,7 @@ prefix: CONF
|
||||
|
||||
**СЛЕДУЕТ.** Конкретный формат (TOML, YAML) выбирается по стеку.
|
||||
|
||||
**Почему.** Комментарий у каждого поля (CONF-9) — часть того, ради чего конфиг
|
||||
**ПОЧЕМУ.** Комментарий у каждого поля (CONF-9) — часть того, ради чего конфиг
|
||||
вообще читают; формат, в котором комментарий негде разместить, делает CONF-9
|
||||
невыполнимым. Секции дают структуру, которую валидатор проверяет целиком, —
|
||||
плоский список пар такой возможности не даёт и возвращает нас к тем же
|
||||
@@ -59,7 +59,7 @@ prefix: CONF
|
||||
**СЛЕДУЕТ.** Имя по умолчанию ищется в рабочей директории процесса, а путь
|
||||
задаётся опцией командной строки.
|
||||
|
||||
**Почему.** Запуск без аргументов работает одинаково в разработке, в
|
||||
**ПОЧЕМУ.** Запуск без аргументов работает одинаково в разработке, в
|
||||
контейнере и на сервере, и способ запуска не приходится помнить отдельно
|
||||
для каждой среды. Опция нужна ровно для случаев, когда конфигов несколько
|
||||
(тесты, второй инстанс): без неё их разводят переменной окружения — тем
|
||||
@@ -71,7 +71,7 @@ prefix: CONF
|
||||
рабочей директории (CONF-3), приложение не стартует: сообщение называет
|
||||
искомый путь, код возврата ненулевой.
|
||||
|
||||
**Почему.** Конфиг — артефакт деплоя (CONF-12), и его отсутствие означает, что
|
||||
**ПОЧЕМУ.** Конфиг — артефакт деплоя (CONF-12), и его отсутствие означает, что
|
||||
развёртывание не довело работу до конца, а не что приложение попросили
|
||||
работать на умолчаниях. Умолчания (CONF-7) существуют, чтобы работал
|
||||
**неполный** файл, а не отсутствующий, — именно здесь читатель спотыкается
|
||||
@@ -89,7 +89,7 @@ prefix: CONF
|
||||
|
||||
**НЕ ДОЛЖЕН.** Реальный конфиг не коммитится; в репозитории — образец.
|
||||
|
||||
**Почему.** Рабочий конфиг содержит отрендеренные секреты (CONF-12), а секрет,
|
||||
**ПОЧЕМУ.** Рабочий конфиг содержит отрендеренные секреты (CONF-12), а секрет,
|
||||
попавший в историю, чинится ротацией, а не удалением файла. Кроме того,
|
||||
закоммиченный конфиг конкретной среды становится вторым источником истины:
|
||||
он расходится с тем, что реально развёрнуто, и расходится молча.
|
||||
@@ -99,7 +99,7 @@ prefix: CONF
|
||||
**ДОЛЖЕН.** Разбор — при старте, в одну типизированную структуру; чтения
|
||||
файла конфигурации в бизнес-коде нет.
|
||||
|
||||
**Почему.** Второе место чтения — это второй момент времени: две части кода
|
||||
**ПОЧЕМУ.** Второе место чтения — это второй момент времени: две части кода
|
||||
начинают видеть разные значения одного параметра, и расхождение не
|
||||
воспроизводится, потому что зависит от того, когда файл потрогали.
|
||||
Типизированная структура вдобавок переносит ошибку формата в старт (CONF-17),
|
||||
@@ -109,7 +109,7 @@ prefix: CONF
|
||||
|
||||
**ДОЛЖЕН.** Смена параметров — рестарт процесса.
|
||||
|
||||
**Почему.** Изменяемый конфиг делает поведение функцией момента: один
|
||||
**ПОЧЕМУ.** Изменяемый конфиг делает поведение функцией момента: один
|
||||
запрос обслуживается наполовину старыми, наполовину новыми значениями, а
|
||||
разбор инцидента требует знать хронологию правок файла, а не его текущее
|
||||
содержимое.
|
||||
@@ -121,7 +121,7 @@ prefix: CONF
|
||||
|
||||
**ДОЛЖЕН.** Значение по умолчанию задаётся в коде, файл его перекрывает.
|
||||
|
||||
**Почему.** Умолчание, живущее в образце, действует только для тех, кто
|
||||
**ПОЧЕМУ.** Умолчание, живущее в образце, действует только для тех, кто
|
||||
образец скопировал: конфиг без этого поля даёт другое поведение, и ни одно
|
||||
из двух значений не выглядит ошибкой. Умолчание в коде — одно определённое
|
||||
поведение для неполного конфига и одно место, где это значение меняется.
|
||||
@@ -131,7 +131,7 @@ prefix: CONF
|
||||
**ДОЛЖЕН.** В образце присутствуют все секции и все поля, включая те, у
|
||||
которых есть умолчание (CONF-7).
|
||||
|
||||
**Почему.** Поле, живущее только в коде, для читателя конфига не
|
||||
**ПОЧЕМУ.** Поле, живущее только в коде, для читателя конфига не
|
||||
существует: он не знает, что параметр вообще можно менять, и добивается
|
||||
нужного поведения обходным путём. Полнота образца — цена, которой CONF-7
|
||||
покупает себе видимость.
|
||||
@@ -145,7 +145,7 @@ prefix: CONF
|
||||
- **единицы измерения**, если применимо: секунды/миллисекунды, байты, доля
|
||||
`0–1`.
|
||||
|
||||
**Почему.** Так конфиг читается без открывания кода — этим он и полезен;
|
||||
**ПОЧЕМУ.** Так конфиг читается без открывания кода — этим он и полезен;
|
||||
без комментария читатель всё равно идёт в код, и образец перестаёт быть
|
||||
справочником. Единицы стоят отдельно: перепутанные секунды и миллисекунды
|
||||
дают валидное значение и работающий процесс, а ошибка обнаруживается по
|
||||
@@ -161,7 +161,7 @@ prefix: CONF
|
||||
| CONF-10.1 | поддерживаемое | обязательны поля этого варианта; поля прочих вариантов не требуются |
|
||||
| CONF-10.2 | неизвестное | ошибка на старте с перечислением поддерживаемых значений |
|
||||
|
||||
**Почему.** Фиксированный на секцию набор обязательных полей оставляет
|
||||
**ПОЧЕМУ.** Фиксированный на секцию набор обязательных полей оставляет
|
||||
выбор из двух плохих: заполнять поля бекенда, который не используется, или
|
||||
не проверять обязательность вовсе — то есть выключить валидацию ровно там,
|
||||
где вариантов много и ошибиться легче всего. Перечисление поддерживаемых
|
||||
@@ -174,7 +174,7 @@ prefix: CONF
|
||||
альтернативные — блоками-комментариями ниже, каждый со своим описанием
|
||||
полей.
|
||||
|
||||
**Почему.** Иначе набор вариантов виден только из кода валидации, и образец
|
||||
**ПОЧЕМУ.** Иначе набор вариантов виден только из кода валидации, и образец
|
||||
теряет свойство справочника (CONF-8, CONF-9) ровно на той секции, где выбор
|
||||
действительно есть. Закомментированный блок вдобавок переключается правкой
|
||||
на месте, а не сборкой секции с нуля по документации.
|
||||
@@ -184,7 +184,7 @@ prefix: CONF
|
||||
**ДОЛЖЕН.** Деплой рендерит значения секретов прямо в файл конфигурации;
|
||||
отдельного слоя секретов в приложении нет.
|
||||
|
||||
**Почему.** Источник истины секрета — внешнее хранилище деплоя, не
|
||||
**ПОЧЕМУ.** Источник истины секрета — внешнее хранилище деплоя, не
|
||||
репозиторий и не окружение. Любой второй канал — переменная окружения рядом
|
||||
с файлом, собственный клиент к хранилищу внутри приложения — возвращает
|
||||
вопрос «откуда взялось значение, которое сейчас в процессе». Приложение при
|
||||
@@ -196,7 +196,7 @@ prefix: CONF
|
||||
**ДОЛЖЕН.** Права `0600`, владелец — пользователь, от имени которого
|
||||
работает процесс.
|
||||
|
||||
**Почему.** После CONF-1 и CONF-12 файл конфигурации — единственная
|
||||
**ПОЧЕМУ.** После CONF-1 и CONF-12 файл конфигурации — единственная
|
||||
поверхность, на которой секреты лежат, и весь довод «файл вместо окружения»
|
||||
держится на его правах: конфиг, читаемый всеми на машине, раздаёт секреты
|
||||
шире, чем раздало бы окружение, — и тогда CONF-1 меняет одну утечку на
|
||||
@@ -207,7 +207,7 @@ prefix: CONF
|
||||
**ДОЛЖЕН.** Значение секретного поля в образце — пустая строка, а не
|
||||
пример.
|
||||
|
||||
**Почему.** Правдоподобная заглушка доезжает до продакшена как настоящее
|
||||
**ПОЧЕМУ.** Правдоподобная заглушка доезжает до продакшена как настоящее
|
||||
значение: шаблон отрендерился криво, поле осталось от образца, и проверка
|
||||
непустоты (CONF-15) его пропускает. Пустая строка делает недорендеренный конфиг
|
||||
механически отличимым от заполненного.
|
||||
@@ -216,7 +216,7 @@ prefix: CONF
|
||||
|
||||
**ДОЛЖЕН.** Непустота обязательных секретов проверяется на старте.
|
||||
|
||||
**Почему.** Это ловит криво отрендеренный шаблон до того, как он превратится
|
||||
**ПОЧЕМУ.** Это ловит криво отрендеренный шаблон до того, как он превратится
|
||||
в 401 от внешнего API через час работы, — то есть в момент, когда причина
|
||||
ещё очевидна и связана с деплоем.
|
||||
|
||||
@@ -225,7 +225,7 @@ prefix: CONF
|
||||
**НЕ ДОЛЖЕН.** Значение секретного поля не появляется в записи лога ни на
|
||||
одном уровне.
|
||||
|
||||
**Почему.** У логов круг доступа шире, чем у файла под `0600` (CONF-13): они
|
||||
**ПОЧЕМУ.** У логов круг доступа шире, чем у файла под `0600` (CONF-13): они
|
||||
собираются, пересылаются и попадают в бэкапы, где права исходного файла уже
|
||||
ничего не значат. Попавший в лог секрет чинится ротацией, а не удалением
|
||||
записи. Типичный источник утечки — отладочный дамп разобранного конфига при
|
||||
@@ -236,7 +236,7 @@ prefix: CONF
|
||||
**ДОЛЖЕН.** Невалидный конфиг — запись уровня `ERROR` и выход с ненулевым
|
||||
кодом; процесс не стартует «наполовину».
|
||||
|
||||
**Почему.** Наполовину стартовавший процесс проходит проверку живости и
|
||||
**ПОЧЕМУ.** Наполовину стартовавший процесс проходит проверку живости и
|
||||
падает позже — на первом запросе, который трогает испорченный параметр, — и
|
||||
падение выглядит дефектом кода, а не ошибкой деплоя. Ненулевой код нужен,
|
||||
чтобы неудачный старт увидел супервизор: без него он неотличим от штатного
|
||||
@@ -254,7 +254,7 @@ prefix: CONF
|
||||
| CONF-18.4 | строки, которые парсятся во что-то (длительности, зоны, URL, идентификаторы сущностей), реально парсятся | при первом обращении к тому, что за ними стоит |
|
||||
| CONF-18.5 | включённые секции консистентны: у включённой интеграции заданы все обязательные поля | при первом вызове интеграции, часто по расписанию |
|
||||
|
||||
**Почему.** Список минимальный и собран по одному признаку — правый
|
||||
**ПОЧЕМУ.** Список минимальный и собран по одному признаку — правый
|
||||
столбец: каждая из этих ошибок иначе всплывает там, где связь с деплоем уже
|
||||
потеряна, и диагностируется как дефект приложения. Проверка на старте
|
||||
сводит их все к одному моменту и одному сообщению.
|
||||
@@ -264,7 +264,7 @@ prefix: CONF
|
||||
**ДОЛЖЕН.** Валидация собирает все найденные проблемы и выводит их одним
|
||||
списком, а не падает на первой.
|
||||
|
||||
**Почему.** Иначе цикл «запуск — одна ошибка — правка» повторяется столько
|
||||
**ПОЧЕМУ.** Иначе цикл «запуск — одна ошибка — правка» повторяется столько
|
||||
раз, сколько в конфиге ошибок, а на сервере каждая итерация — это ещё и
|
||||
деплой. Криво отрендеренный шаблон обычно ломает не одно поле, а все поля
|
||||
одного источника: разом они читаются как одна причина, по одной — как
|
||||
@@ -280,7 +280,7 @@ prefix: CONF
|
||||
| CONF-21.1 | несекретное | имя поля, ожидание и полученное значение: «ожидалось 0–1, получено `1.5`» |
|
||||
| CONF-21.2 | секретное | имя поля и суть нарушения, без значения |
|
||||
|
||||
**Почему.** Сообщение без значения отправляет читателя в файл — сличать
|
||||
**ПОЧЕМУ.** Сообщение без значения отправляет читателя в файл — сличать
|
||||
глазами каждую строку списка CONF-19; ошибки вида «секунды вместо миллисекунд»
|
||||
или пробел в конце значения из такого сообщения не читаются вовсе. Значение
|
||||
секретного поля при этом печатать некуда: вывод старта уходит в лог
|
||||
|
||||
Reference in New Issue
Block a user