sync_consumers_from_config

Function sync_consumers_from_config 

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