Skip to content

docs(spec): resolve placeholders on every configuration entry point - #23

Draft
antstanley wants to merge 1 commit into
spec/apply-unmerged-change-spec-blocksfrom
spec/resolve-config-placeholders
Draft

docs(spec): resolve placeholders on every configuration entry point#23
antstanley wants to merge 1 commit into
spec/apply-unmerged-change-spec-blocksfrom
spec/resolve-config-placeholders

Conversation

@antstanley

@antstanley antstanley commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Note

Stacked PR 2 of 16 — part of stack #35, which targets main.
Base: #29 (spec/apply-unmerged-change-spec-blocks) · Followed by: #25

This PR's diff shows only its own change. Merge the stack bottom-up; do not merge this before its base.

Why it sits at position 2: Introduces the two-stage RawConfig/Config seam and the single resolve() every config entry point calls. #25 builds its closed-domain types on that seam and both modify 06-configuration.md's Loading order.

Scope of this PR

This PR currently carries the change spec. It will also carry the implementation plan and the build work for that spec — plan and code land as later commits on this same branch, so the spec, its plan, and its implementation review and merge as one unit.

Review order within the PR: spec first, then plan, then implementation.


Change spec proposing that every configuration entry point resolve ${VAR} placeholders.

Problem. parse_config in crates/server/src/bootstrap.rs is toml::from_str + validate() with no resolve step, so the napi Node binding, the PyO3 Python binding and the TypeScript @oidc-exchange/lambda package load configuration in which the documented secret placeholder survives as literal text. The internal-API shared secret is one of the values documented this way. The function's own doc comment currently claims a parity that does not exist.

Proposed delta. Route every entry point through one shared resolve step — source layering, then fail-closed ${VAR} resolution, OIDC_EXCHANGE__{section}__{key} overrides, then validation. Failure semantics are fixed for each case (unset variable, set-but-empty, unterminated ${, empty ${}, $${ escape) as startup errors, with a residual-placeholder post-condition and a requirement that no error or diagnostic ever echoes a resolved secret.

Adopts hardening Option 2's two-stage RawConfig/Config seam with a single resolve() plus the oidc-exchange config check subcommand pulled forward, and explicitly defers closed-domain field typing to a follow-on change.

Corrections to the original finding, from reading the code.

  • The Rust Lambda runtime is not affectedmain.rs selects Lambda mode after bootstrap::load_config(), which does resolve. The affected Lambda channel is the TypeScript @oidc-exchange/lambda package, which reaches config via the Node addon → FFI → parse_config.
  • parse_config also misses the OIDC_EXCHANGE__… override source, so binding runtimes silently drop policy overrides such as OIDC_EXCHANGE__REGISTRATION__MODE. Included in the delta.
  • There is no CLI subcommand that loads config todaymain.rs handles only --version/-V and crates/server has no argument-parsing dependency, so config check is a genuinely new surface.

Pre-existing divergence flagged, not fixed. changes/merged/2026-07-01-complete_config_loading.md is marked Merged, but its blocks were never applied to 06-configuration.md or 04-http-api.md. Merge-plan step 1 calls for completing that merge rather than superseding it.

Drafted with the spec-creator plugin from a deep security scan of the repository at 53cbdec9. Spec only — no source changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@antstanley
antstanley force-pushed the spec/resolve-config-placeholders branch from be38736 to 446249c Compare August 5, 2026 08:22
@antstanley
antstanley changed the base branch from main to spec/apply-unmerged-change-spec-blocks August 5, 2026 08:22
@antstanley
antstanley marked this pull request as draft August 5, 2026 08:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant