Enforce 10j's verified gaps (schema-hardening change): - Migration 00010: partial unique indexes for one default pool and one primary assignment per workspace, plus CHECKs pinning pool/provider/subscription vocabularies and provider lifecycle timestamps. - Workspace creation shares a transactional provisioning function; extension validates its target pool; last-tier deletion of a defaulted ladder is guarded; signup completes plan-less on a broken ladder. - Boot asserts integration slug parity and validates declared config enums; Stripe invoice amounts are range-checked; domain cancellation runs a final evidence probe; rule authoring is additive-only.
4.8 KiB
startup-configuration Specification
Purpose
TBD - created by archiving change boot-config-validation. Update Purpose after archive.
Requirements
Requirement: Boot-time configuration validation
The member-console start command SHALL validate its required configuration
before initializing any service (database, Temporal, or HTTP server), and SHALL
exit non-zero with an aggregated, actionable error when validation fails.
Validation SHALL run after configuration is resolved from flags, environment
variables, the config file, and any *-secret-file references, so that
file-backed secrets are validated by value. Each reported problem SHALL name the
offending configuration key and how to set it (its MC_* environment variable or
mc-config.yaml key), and a single run SHALL report every problem at once rather
than only the first.
The following core configuration SHALL be required unconditionally: db-dsn (a
valid PostgreSQL URL), valkey-addr, oidc-idp-issuer-url (a valid URL),
oidc-sp-client-id, base-url (a valid URL), and csrf-secret (exactly 32
bytes). oidc-sp-client-secret SHALL NOT be required (public PKCE clients have
none).
Core conditional requirements SHALL apply: when temporal-host is set,
temporal-namespace SHALL be present, and if any temporal-oauth-* field is set
then temporal-oauth-token-url, temporal-oauth-client-id, and
temporal-oauth-client-secret SHALL all be present.
Integration configuration SHALL be validated from the registered
integrations' declared config specs — key presence, secret-file resolution,
and required-together groups — with the same aggregation and error-message
conventions. Per-integration validation rules SHALL NOT be hardcoded in the
core validator; Stripe's rule (when stripe-mode is live or any Stripe
credential is present, both stripe-api-key and stripe-webhook-secret
SHALL be present) SHALL be expressed as the Stripe integration's declared
requirement.
Scenario: Missing required configuration fails fast with a clear message
- WHEN
member-console startruns with an emptydb-dsn - THEN the command SHALL exit non-zero before connecting to the database or running migrations
- AND the error SHALL name
db-dsnand how to set it (MC_DB_DSNor thedb-dsnkey inmc-config.yaml)
Scenario: All configuration problems reported together
- WHEN
member-console startruns with several required keys missing or malformed - THEN the command SHALL report every problem in a single aggregated error, not just the first
Scenario: Invalid CSRF secret is caught before service startup
- WHEN
csrf-secretis present but not exactly 32 bytes - THEN validation SHALL fail before database migrations run (rather than after migrations and Temporal scheduling, as before)
Scenario: Partially configured Stripe is rejected via its declaration
- WHEN
stripe-api-keyis set butstripe-webhook-secretis empty - THEN validation SHALL fail with a message that both are required to enable billing (or both omitted to disable it)
- AND the rule SHALL originate from the Stripe integration's config declaration, not from core validator code
Scenario: Partially configured Temporal OAuth is rejected
- WHEN
temporal-hostis set andtemporal-oauth-client-idis set buttemporal-oauth-token-urlis empty - THEN validation SHALL fail, requiring the OAuth token URL, client ID, and client secret to be set together
Scenario: Valid configuration passes
- WHEN all required keys are present and well-formed
- THEN validation SHALL succeed and startup SHALL proceed unchanged
Requirement: Declared enum values are validated at boot
For every registered configuration key that declares an enumerated value set, startup validation SHALL check that the resolved value (from flags, environment, or config file) is a member of the declared set, and SHALL report a violation in the same aggregated, actionable format as other validation failures — naming the key, the offending value, and the allowed values. Unset or empty values SHALL NOT fail this check (presence is governed by the existing required-key rules). The membership logic SHALL be shared with the operator-settings override validation so the two paths cannot diverge.
Scenario: Misspelled enum value stops the boot
- WHEN the environment sets a declared enum key to a value outside its set (for example an auto-create flag set to "yes" where the set is "true"/"false")
- THEN startup fails with an error naming the key, the bad value, and the allowed values, instead of booting with silently wrong behavior
Scenario: Valid and unset values pass
- WHEN every declared enum key is unset or holds a member of its set
- THEN validation passes exactly as before