LearnNewsExamplesServices
Frontmatter
id16039
titleDeployment config defaults absorb the env-override surface: policy becomes AiConfig, env keeps only secrets and choices
stateOpen
labels
enhancement
assignees[]
createdAtJul 27, 2026, 3:19 AM
updatedAtJul 27, 2026, 3:34 PM
githubUrlhttps://github.com/neomjs/neo/issues/16039
authorneo-opus-grace
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[ ] 15798 Local Runtime Parity: local Agent OS adopts the cloud container topology
blocking[ ] 16040 Rewrite the deployment guides once parity lands: fewer steps the operator performs, not fewer lines

Deployment config defaults absorb the env-override surface: policy becomes AiConfig, env keeps only secrets and choices

neo-opus-grace
neo-opus-grace commented on Jul 27, 2026, 3:19 AM

Blocked until local/cloud runtime parity (#15798) completes. Filed now so the decision is captured while the evidence is fresh; the work must not start before parity lands, because parity is what makes the correct defaults knowable.

The problem

Every deployment-touching PR currently grows the environment-variable surface instead of moving a default. The surface is now the dominant cost of standing Neo up.

Measured against a live external-tenant deployment (sanitized docker inspect across its three services): 33 of 45 NEO_* keys the deployment sets are already declared config leaves with defaults. The pipeline sets them anyway. Of the 12 that are not leaves, only 2 belong in the environment at all:

group keys disposition
auto-* toggles NEO_AUTO_SYNC, NEO_AUTO_DREAM, NEO_AUTO_GOLDEN_PATH, NEO_AUTO_INGEST_FS, NEO_AUTO_SUMMARIZE, NEO_KB_AUTO_START_DATABASE, NEO_MEM_AUTO_START_DATABASE, NEO_MEM_AUTO_START_INFERENCE 8 — should become leaves
behavior flags NEO_MC_PRIMARY, NEO_REAL_TIME_MEMORY_PARSING 2 — should become leaves
secrets NEO_MCP_HEALTHCHECK_TOKEN, provider PAT 2 — correctly env-side, keep

The ratchet, caught live

PR #16038 is well-built work that still adds six NEO_AUTH_* overrides to the canonical parity profile:

NEO_AUTH_MODE: github-pat
NEO_AUTH_TRUST_PROXY_IDENTITY: "false"
NEO_AUTH_PIN_FIRST_PROVIDER_SUBJECT: "true"
NEO_AUTH_AUTO_PROVISION_IDENTITY_SOURCES: github-pat
NEO_AUTH_PROVIDER_BOOTSTRAP_PAT_FILE: /run/secrets/mcp-auth-token
NEO_MCP_HEALTHCHECK_TOKEN_FILE: *provider-bootstrap-pat-file

Exactly one is a genuine deployment decision — where the secret file lives. TRUST_PROXY_IDENTITY: false and PIN_FIRST_PROVIDER_SUBJECT: true are security posture that should be the default; AUTO_PROVISION_IDENTITY_SOURCES is derivable from the auth mode. Nothing is wrong with that PR — the ratchet is structural, and no individual PR is where it should be stopped.

Why this blocks on parity

Today local and deployed run differently, so no one can know which value is the default versus a local accommodation. Once the same topology runs both places, the default is observable rather than argued. Doing this first would encode today's divergence as tomorrow's defaults.

Target posture

A deployment supplies: tenant repos · GitLab or GitHub · chat + embedding model (only if changing) · secrets. Everything else is a default, overridable but not required.

Acceptance Criteria

  • Every non-secret key in the census above is either a config leaf with a defensible default, or has a recorded reason it must stay deployment-supplied.
  • Security-posture leaves default to the safe value (trustProxyIdentity false, pinFirstProviderSubject true) so a deployment opts out, never in.
  • Values derivable from another leaf are derived, not restated — autoProvisionIdentitySources from auth mode is the worked example.
  • A mechanical check fails when a compose profile sets a key whose declared default already matches the set value — the ratchet cannot silently resume. Extends the existing ai/scripts/lint/config-leaf-parity.json surface rather than adding a lane.
  • The census re-run against the same external-tenant inspect shows the required-key count reduced to secrets + tenant/provider choices.
  • ADR-0019 records the boundary rule: policy and posture are config; secrets and per-deployment identity are environment.

Evidence

Census method is re-runnable: each key greps against ai/configBase.mjs, ai/mcp/server/memory-core/configBase.mjs, ai/mcp/server/knowledge-base/configBase.mjs for a leaf declaration. Baseline recorded on #15798.

Related

#15798 parity epic (hard dependency) · #15800 data-plane placement election · #16038 the live example · ADR-0019 AiConfig reactive provider SSOT.

Filed by @neo-opus-grace (Grace, Claude Opus 5) on operator direction — capture now, start after parity.