Home / Projects / Orchestrata Ultimate / Decisions / ADR index / ADR-0075

ADR-0075: The promote's infra stage proves the ADR-0066 secrets file holds every required env key before the tree moves

field value
Status Proposed — Proposed (recommendation: Accept)
Date 2026-10-07
Register factory (docs/adr, 4-digit ids)
Source docs/adr/0075-promote-infra-stage-proves-required-env-keys-before-the-tree-moves.md — permalink at 8289a531a (unchanged on master since that commit)
Wiki register entry ADR-0075 (wiki status: Proposed)

← ADR-0074 · ADR-0076 →

The record

Status: Proposed (recommendation: Accept) · Date: 2026-10-07

Context

The prod promote runs an authoritative env preflight: promoter.validate (promotion/promoter.py:132-137) invokes scripts/validate_env.py with the profile overlay as the process env, so its exact REQUIRED_KEYS contract gates the promote. The infra stage then proves reachability — Redis, the graph cluster (promotion/env_profile.py:132 probe_infra; promoter.py:152 "infra is not reachable — refusing"). Neither step ever reads the ADR-0066 secrets file (~/.config/orchestrata/.env, mode 0600), and validate_env.REQUIRED_KEYS deliberately excludes the two CONVERSATION_KG_* keys (core/infra_env_rule.py's docstring: "The conversation keys are deliberately NOT in validate_env's REQUIRED_KEYS … validate_env is a RUNTIME PREFLIGHT (these keys must be present before…)"), so no promote stage proves the one file that gates the conversation consumer.

Measured cost of that gap, three times over (all before today's manual fix):

Every failure happened at the END of the pipeline: the tree had moved, the units had restarted, and the promote then rolled back and restarted them again. The detection was a three-line file read the promote never did — proven today, 2026-10-07, when the operator appended the two keys (named in ADR-0072, ruled Accepted) and the consumer started on the first try (orchestrata-kg-ready OK, daemon consuming).

ADR-0074 (Accepted 2026-10-07) fixed this exact failure shape for the embedding provider: probe at infra, refuse before the tree moves, no rollback because nothing moved. This ADR is the env-keys counterpart: the promote's own preflight must prove the secrets-file contract it ships against, not rediscover it at verify.

Decision (proposed)

  1. The infra stage gains a required-env-keys probe, before the tree moves. It reads the ADR-0066 secrets file on the target host and checks every key in the required set is present and non-blank; a miss is [FAIL] infra env keys: missing CONVERSATION_KG_URI, CONVERSATION_KG_DATABASE and the promote is refused — no tree move, no restart, no rollback. The probe reads ~/.config/orchestrata/.env (the ADR-0066 source of truth), not /opt/orchestrata/.env, so a key added per a newly Accepted ADR is never refused merely because the installer's copy step has not run yet.
  2. The required set is the infra_env_rule registry. That module already documents it as validate_env.REQUIRED_KEYS plus KG_URI plus the two CONVERSATION_KG_* keys; the probe imports that same set (no second list), and a test asserts the probe and the registry cannot drift.
  3. Every addition is recorded by key name (ADR-0066's rule): the refusal message names the missing keys verbatim, and this ADR's register row records the CONVERSATION_KG_URI / CONVERSATION_KG_DATABASE pair as the keys the first enforcement names. The probe never writes the file and never proposes values (RUL-003: no literal infra defaults; secrets are operator-set).

Alternatives rejected

Consequences

On Accepted: packet P6d of plans/ast-daemon-deployment-plan.md (or folded into P6c, beside ADR-0074's provider probe) adds the probe to promotion/env_profile.probe_infra (reusing the check_env_contract-style file parsing), with real-file tests on the test fleet proving: a missing key refuses at infra with the key's name and no unit restarted; a blank value counts as missing; a present pair passes and changes nothing; and the registry-drift test fails if infra_env_rule's set and the probe's set diverge. The R16b promote-failure class (consumer unit exit → start-rate limit → verify fail → rollback) becomes unreachable: the promote refuses in seconds, naming the missing keys. ADR-0069 applies (@traces, RTM, docs, wiki, ≥90% coverage, one ship).

Provenance

ADR-0066 (Accepted 2026-09-24) item R16b — the endpoint value "still to be named by Mohamed", named in ADR-0072 (Accepted 2026-10-07). Orchestrator finding F-P6a-3, 2026-10-07, from the three promote attempts above and the manual resolution (keys appended to ~/.config/orchestrata/.env and /opt/orchestrata/.env, consumer active (running) at 14:36 EDT). Code: promotion/promoter.py:132-152, promotion/env_profile.py:33-34, 132, core/infra_env_rule.py, scripts/validate_env.py:27, knowledge_graph/conversation_consumer.py:92-99. Awaiting Mohamed's ruling; only he rules.

Rulings cited

Specs cited

None (or no spec page exists for the ones named).