Fuchs loads its secrets (connection strings, API keys, mailer tokens, ...)
from the shared Azure Key Vault pcwkeys at startup, with a DPAPI-encrypted
local cache as an offline fallback. The mechanism is shared, host-type-agnostic
infrastructure owned by the OCORE/OCORE_web submodules (0031);
this doc covers how Fuchs specifically wires into it and where to make
changes. The full mechanism reference (naming/encoding rules, DI wiring,
cache format) is maintained independently in
OCORE_web/.github_instructions/secretsmanagement.instructions.md.
How it works
Fuchs/Program.cs calls builder.AddSecretManagement()
(OCORE_web.Secrets.SecretManagementWebExtensions) as the first step in
ConfigureServices, before FuchsOcmsIntranet.Initialize(configuration)
or anything else reads IConfiguration.
That call, backed by OCORE.Secrets.Extensions.SecretManagementExtensions,
registers two configuration sources in order: the local DPAPI cache
(secrets.cache, offline fallback) first, then the live Azure Key Vault
(overrides the cache when reachable) using PrefixKeyVaultSecretManager
to filter to secrets named fuchs--... and map them onto
IConfiguration keys.
KeyVaultSyncService (a registered BackgroundService) periodically
re-pulls every key listed in Fuchs:SecretManagement:ManagedSecretKeys
from Key Vault, re-writes the DPAPI cache, and calls
IConfigurationRoot.Reload() so a running process picks up rotated
secrets without a restart.
A secret whose name is only known at runtime (not a fixed
IConfiguration key) — e.g. resolved from a DB job record — is instead
fetched directly via OCORE.Secrets.Extensions.SecretsOnDemandLoader,
bypassing ManagedSecretKeys and the periodic sync entirely.
In Development, appsettings.Development.json (git-ignored) can
override any of these values locally, bypassing Key Vault for that key;
AssembleConnectionStrings (Fuchs/Program.cs) additionally prefers
_Dev-suffixed credential keys so a reachable Key Vault can never hand a
dev machine production DB credentials.
Key files
Fuchs/Program.cs — builder.AddSecretManagement() call site and
AssembleConnectionStrings.
Fuchs/appsettings.json — SecretManagement block (VaultUri,
AppName: "fuchs", CacheFilePath, SyncIntervalHours,
ManagedSecretKeys) plus "MANAGED_BY_KEYVAULT" placeholders for every
managed key.
OCORE/Secrets/Extensions/SecretManagementExtensions.cs — shared
Key Vault + DPAPI wiring and DI registration, used by every host type.
OCORE/Secrets/Cache/DpapiSecretsCache.cs — DPAPI encrypt/decrypt of the
local cache file.
OCORE_web/Secrets/SecretManagementWebExtensions.cs — the
WebApplicationBuilder.AddSecretManagement() entry point Fuchs calls.
OCORE_web/.github_instructions/secretsmanagement.instructions.md —
canonical mechanism reference (naming/encoding rules, cache format,
"adding a new secret" steps), kept current independently of this doc.
.github/copilot-instructions.md ("Azure Key Vault — Secret Naming") —
the naming rules summarized for this repo, with the fuchs-- prefix.