ADR 0153 — DEPLOY_ENABLED: триггер, который упоминают десять документов и не создаёт ни один
Статус
Proposed. Ожидает решения владельца продукта об Этапе B (ниже), которое
не является инженерным выбором. Этот документ сам по себе не меняет status ни роли, ни
gate.
Контекст
DEPLOY_ENABLED — объявленный триггер всего, чего не хватает на уровне
платформы. Он упоминается в десяти документах:
- ADR 0091 и
ADR 0092, в самом
поле Status — «its activation stays synchronized with
DEPLOY_ENABLED, which doesn't exist»; - ADR 0089;
docs/fluxo.yml, в трёх местах —platform.ativacao(«sincronizada com DEPLOY_ENABLED»),area-infra.gate_saida(deployavel,status: planned, с комментарием# DEPLOY_ENABLED) и ДВА поставляемых пробелаsecops-runtime(resposta-a-incidenteиpostmortem-de-seguranca, оба сmotivo: exige tráfego de produção real (pós DEPLOY_ENABLED + platform ativo));docs/gates.yml, в gateoperavel(backlog: deploy (DEPLOY_ENABLED + Environments));- а также
business-rules.md,backlog.md,modelo-de-time.md,auditoria-fluxo-vs-codigo.md,historico-de-fases.mdиCLAUDE.md.
В коде он появляется дважды, оба раза как комментарий —
apps/api/src/domain/actions/external-effect.ts:144 («Estes não têm ação
tipada ainda (DEPLOY_ENABLED está no backlog)») и
apps/engine/lib/engine/harness/tools/listar_metricas_de_produto.ex:185.
Ни определения, ни чтения в apps/, docker/, deploy/,
scripts/, .env.example или Makefile.
Десять документов указывают на выключатель, у которого нет стены.
Что этим заблокировано
| заблокировано | где | последствие |
|---|---|---|
platform | fluxo.yml, status: planned | владельца обратного цикла не существует; у SLO, dashboard, runbook и postmortem нет автора |
gate operavel | gates.yml:312-321, status: planned | объявлен, никогда не оценивался |
gate deployavel | fluxo.yml:247 | отсутствует в реестре — см. находку ниже |
resposta-a-incidente и postmortem-de-seguranca | fluxo.yml:223-226 | два поставляемых пробела secops-runtime, который status: active |
Находка, которая не о deploy
Gate deployavel объявлен как gate_saida у area-infra в
docs/fluxo.yml:247 и не существует в docs/gates.yml.
ADR 0054 определяет реестр как
место, где объявляются существующие gates; gate, названный одной частью
модели команды и отсутствующий в другой, — ровно то несоответствие, которое поймал бы тест
перекрёстной проверки между agent-areas.ts, gates.yml и fluxo.yml, — а этот
тест — объявленный в CLAUDE.md backlog, а не то, что существует сегодня.
Это исправимо без решения о deploy, и это единственная часть этого документа, которая не зависит от того, купит ли кто-нибудь сервер.
Напряжение, которое упорядочивает решение
Включение флага без production-окружения с реальным трафиком не активирует роли:
оно создаёт gates, которые проходят вхолостую. Gate, одобряющий, потому что ему нечего
отклонять, хуже, чем gate, объявленный planned, потому что он учит читающего, что
цикл замкнулся. Это та же причина, по которой ADR 0091 и 0092 отказались создавать агента и
поставили скрипт по запросу, — и тот отказ остаётся верным.
Решение
Два этапа, с жёсткой границей между тем, что является инженерией, и тем, что нет.
Этап A — то, что решаемо сегодня, и это намеренно немного
Что уже применено в этой поставке: только пункт 1. Он чинит дыру в РЕЕСТРЕ и не зависит от решения о deploy — это единственная часть этого документа, которая имеет силу, даже если Этап B никогда не случится. Пункты 2 и 3 описывают, что влечёт принятие; пункт 3 (проза десяти документов) не применён, потому что изменение формулировок до решения было бы утверждением выбора, который ещё не сделан.
deployavelвходит вdocs/gates.ymlсstatus: planned,dono: area-infra,severidade: warnиaprovacao_humana: false, точно по образцуoperavel(gates.yml:312-321). Закрывает дыру в реестре.warn, а неblock, потому что правило реестра (RN-070/RN-071) требуетverificacao: scriptдля повышения, а скрипта нет.- Два заблаговременных скрипта не меняются.
apps/api/scripts/relatorio-telemetria.tsиapps/api/scripts/relatorio-seguranca-runtime.tsужеactive, уже работают по запросу и уже поставляют то, что обещали ADR 0091/0092. - Проза перестаёт трактовать
DEPLOY_ENABLEDкак переменную. Там, где сегодня читается «синхронизировано сDEPLOY_ENABLED», начинают называть веху, которую это выражение всегда означало, с объективным критерием: существует обслуживаемое целевое окружение, получающее реальный трафик, конвейер поставки которого кто-то поддерживает.
Этап B — заблокирован оператором, а не кодом
Production-окружение с трафиком. Только после этого platform выходит из
planned, operavel и deployavel перестают быть planned, и два
поставляемых пробела secops-runtime становятся возможными.
Инфраструктура уже готова и не является узким местом: deploy/k8s/ с
overlays local/staging/prod, четыре образа, опубликованные в GHCR по
digest со времён ADR 0119,
make imagens-do-release, bootstrap.sh, smoke.sh, rollout-test.sh и
test-restore.sh. Не хватает того, чтобы кто-то запускал и поддерживал — и ничто из этого
не делает deploy само.
Рассмотренная и отвергнутая альтернатива
Создать DEPLOY_ENABLED сейчас, как переменную окружения со значением по умолчанию false.
Это был первый дизайн, и он плохо окупается: переменная, которую не читает ни один код, —
то же пустое обещание, которое этот ADR существует, чтобы разоблачить, только теперь со
строкой конфигурации для его поддержки. В репозитории уже есть правило, которое
это решает: capability объявляется только когда доказана набором тестов; без доказательства
объявляется false и деградирует (ADR 0041/0042). Флаг рождается в PR, у которого будет
первый реальный потребитель, и этот PR — PR Этапа B.
Имя DEPLOY_ENABLED остаётся зарезервированным: десять документов уже его используют, и
переименование вехи сейчас лишь переместило бы долг.
Что этот ADR явно отвергает
- Создание агента
platformилиsecops-runtimeв engine. Это значило бы выдумать полномочия над циклом, который не замыкается, — отказ ADR 0091/0092, повторённый здесь, потому что вопрос возвращается. - Повышение
operavelилиdeployavelдоblockбез скрипта проверки (RN-070/RN-071). - Пометку «не измерено навсегда» того, что зависит лишь от окружения: MTTR и change failure rate остаются объявленными как пробел с причиной, а не как невозможность.
Последствия
- Реестр gates начинает содержать все gates, которые называет модель
команды, —
deployavelперестаёт существовать только с одной стороны. - В runtime ничего не меняется. Ни новой переменной, ни изменённого значения по умолчанию, ни оцениваемого gate, который не оценивался бы раньше.
- Уровень платформы по-прежнему стоит, и теперь честно говорит почему:
не хватает не флага, а окружения. Тот, кто читает
fluxo.yml, перестаёт искать в коде переменную, которой там никогда не было. - Зафиксировано, что расстояние между «объявленным» и «существующим» уже стоило однажды: десять документов договорились между собой о механизме, и договорённость выжила, потому что ничто не сверяло их с кодом. Тест перекрёстной проверки между тремя частями модели команды остаётся в backlog, и это вторая находка, которую он поймал бы.