pub fn sync_consumers_from_config(
store: &StateStore,
gateway: &Gateway,
pepper: Option<&[u8]>,
) -> Result<(), StoreError>Expand description
Bootstrap the store from the gateway config (DW-018 seeding, hashing per DW-019, peppered per #124).
Creates/updates every consumer found in the config (including its
groups, #124) and inserts a credential row for each config
credential that is not already present (matched by consumer +
selector, so re-syncing is idempotent).
Hashing: config API keys are hashed at seed time — the selector is
hex(sha256(key)) (never the plaintext key; this closes the DW-018
finding that seeded selectors were raw config values) and the stored
hash is hmac-sha256:<hex> when a pepper is configured (#124;
resolved by the CALLER through the SecretSource seam — this store
never touches the extension) or legacy sha256:<hex> otherwise.
Rows seeded by a pre-pepper sync keep verifying (legacy format) and
upgrade lazily on successful verification. JWT and mTLS config
credentials are BINDINGS, not secrets (tokens are verified
cryptographically; client certificates by subject/fingerprint), so
their rows keep a binding-marker hash and the issuer / match-value
selector.
Fail-closed skip (#46): a ${...} reference that no longer resolves
at seed time is skipped loudly, AND the row a previous generation of
the SAME reference seeded is revoked
(StateStore::revoke_credentials_by_source, linkage via
credentials.source_ref, schema v4) — with the store live the
registry serves rows rather than config, so a skip that left the old
row active would keep the OLD key authenticating, the opposite of
fail-closed. Rows without the linkage (pre-v4 databases, inline
keys, operator-managed rows) keep the upsert-only posture below.
Legacy cleanup: rows seeded by the pre-DW-019 build (plaintext api-key
selector + config:api_key: placeholder hash) are deleted on every
sync — see
StateStore::delete_legacy_config_placeholder_credentials.