Files
cgalo5758 6dbce6140f Type the ConfigSpec seam and move the connect target to core
Register bool and duration ConfigSpec keys from the Default's type, move
fedwiki's four sync knobs and discourse's two into their integrations'
ConfigSpecs, and replace core's read of fedwiki-custom-domain-target
with a core domains-connect-target key resolved once and threaded
through server and worker config.

Generate init's optional-integration scaffold sections from each
registered ConfigSpec instead of the hand-maintained list, and reword
the Temporal boot warning generically.

Archives the integration-config-parity change; status bookkeeping and
the verify-skill doc follow with the test-stack commit.
2026-08-01 04:13:48 -05:00

3.5 KiB

integration-config-declaration Specification

Purpose

Keep configuration ownership aligned with code ownership: every key an integration consumes is declared by that integration's ConfigSpec and registered generically by the composition root, whatever its type, so core never hand-declares or reads an integration-namespaced key. Core capabilities configured by deployment get core-namespaced keys, and integrations that need a core-resolved value receive it as threaded data rather than reaching for viper themselves.

Requirements

Requirement: Integration config keys travel the ConfigSpec seam regardless of type

Every configuration key an integration consumes SHALL be declared in that integration's ConfigSpec, and the composition root SHALL register a matching CLI flag and default for each declared key generically, for all supported key types: string, string-slice, boolean, and duration. A key's type SHALL be carried by its declared Default value. Core SHALL NOT hand-declare flags or defaults for any integration-namespaced key.

Scenario: Boolean and duration keys register through the generic seam

  • WHEN an integration's ConfigSpec declares a key with a bool default and a key with a time.Duration default
  • THEN member-console start --help SHALL list both keys as flags of the matching type
  • AND their declared defaults SHALL apply when the keys are unset

Scenario: FedWiki's sync knobs are integration-declared

  • WHEN the composition root's flag declarations are inspected
  • THEN fedwiki-sync-enabled, fedwiki-sync-interval, fedwiki-sync-trigger-immediately, and fedwiki-swap-cooldown SHALL be declared only by fedwiki's ConfigSpec, not hand-declared in core

Scenario: Discourse's sync knobs are declared, not implicit

  • WHEN discourse's ConfigSpec is inspected
  • THEN discourse-sync-interval and discourse-sync-trigger-immediately SHALL be declared with defaults matching the integration's runtime fallbacks
  • AND unset keys SHALL produce the same behavior as before declaration

Requirement: Core reads no integration-namespaced configuration key

Core packages (cmd/, internal/server/, internal/workflows/) SHALL NOT read integration-namespaced configuration keys to configure core capabilities. Core capabilities configured by deployment SHALL use core-namespaced keys; where an integration needs a core-resolved value, the composition root SHALL resolve it once and thread it as data. Exception, tracked as existing debt: the composition root still reads Stripe's declared keys to construct core's payments baseline — that extraction is payments-provider-seam (issues.md), not this requirement's scope.

Scenario: The domains connect target is a core key

  • WHEN a deployment sets domains-connect-target
  • THEN the member Domains surface, the claim-verification worker probe, and fedwiki's create-flow gate SHALL all observe that value
  • AND no code SHALL read fedwiki-custom-domain-target (the key no longer exists)

Scenario: Empty core connect target disables external claims deployment-wide

  • WHEN domains-connect-target is unset
  • THEN external-claim creation SHALL be disabled everywhere the gate applies, matching the domains-registry gate requirement

Scenario: FedWiki receives the connect target as data

  • WHEN fedwiki's route registration constructs its external-claim gate
  • THEN the connect target SHALL arrive via server.Deps, not via a viper read inside the integration