Skip to content

docs(spec): fail closed across config, adapters, and the installer - #25

Draft
antstanley wants to merge 1 commit into
spec/resolve-config-placeholdersfrom
spec/fail-closed-config-and-adapters
Draft

docs(spec): fail closed across config, adapters, and the installer#25
antstanley wants to merge 1 commit into
spec/resolve-config-placeholdersfrom
spec/fail-closed-config-and-adapters

Conversation

@antstanley

@antstanley antstanley commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Note

Stacked PR 3 of 16 — part of stack #35, which targets main.
Base: #23 (spec/resolve-config-placeholders) · Followed by: #24

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 3: Layers closed-domain config types onto #23's seam and replaces the Validation at load section #29 restored. Merges before #24, which then supersedes the audit defaults in its committed-default block.

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.


Cross-cutting change spec establishing a fail-closed principle and applying it to seven confirmed fail-open sites.

The rule. A security control that cannot be evaluated must deny; a configuration that cannot be validated must refuse to start; a control that could not run did not pass.

The sites.

  • registration.mode compared by string equality against a single literal, so an operator typo silently re-opens just-in-time registration and any anonymous client with a genuine IdP account provisions itself an account plus a 30-day session.
  • Empty issuer/audience defaults on validation-critical values.
  • Unvalidated algorithm strings on both the local-key and KMS signing paths.
  • Provider discovery that parses a body without reading the HTTP status.
  • A Postgres migration that degrades open on a probe weaker than the invariant it stands in for.
  • An installer that installs when it could not verify.
  • URL fields accepting http:// where TLS should be required.

Each gets a concrete rejection point — startup for everything configuration-shaped, plus a derived-from-key-material algorithm cross-check. The structural preventive is hardening Option 2: RawConfig/Config two-stage parse, one resolve() every entry point calls, typed enums and newtypes replacing bare strings, with string equality against a single literal named as the anti-pattern being removed.

Compatibility is stated as a table of exactly which deployments stop booting and what the operator does, with a two-phase permissive-warning rollout for the config half only.

Two judgment calls worth reviewing.

  • The open-registration default does not flip in this change — recorded as a Decision, with the flip left as an Open question. It is a product decision, not a safety one, and it did not belong inside a fail-closed sweep.
  • The lead Open question resolves a question the security scan left open: examples/aws-web/config/oidc-exchange.toml uses ECDSA_SHA_256 and examples/ecs-fargate/config/fargate.toml uses ECDSA_SHA256 — both AWS SigningAlgorithmSpec names that the adapter's closed match rejects. Either reference deployment boots, passes health checks, and 500s on every sign-in, which strongly suggests neither has been run end to end.

Pre-existing divergence found: changes/merged/2026-07-01-complete_config_loading.md is marked Merged, but its Validation at load section never reached 06-configuration.md — while the code does implement it. The spec treats Validation at load as an Add that folds in the shipped checks, resolving the divergence on merge.

Overlapping sites are cross-referenced to the parallel config-placeholder, admin-plane and runtime-parity specs rather than restated.

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>
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