Community contribution from @rocogamer (PR #139, clean rebase of #118). Adds a configurable storage_mode to the Azure Key Vault storage backend so it can persist certificates as native Certificate objects (PKCS12, issuer_name=\"Unknown\") in addition to or instead of the existing per-PEM Secrets layout. Native Certificate objects bind directly from Azure App Service, Application Gateway, Front Door, API Management and AKS Ingress without manual PFX export.
What landed
storage_mode: secrets(default) - current per-PEM Secrets layout, fully backwards-compatible. Existing installs see zero behaviour change after upgrade.storage_mode: certificate- single Certificate object per domain. Metadata (domain, DNS provider, email, etc.) stored as tags on the Certificate object.issuer_name=\"Unknown\"so Key Vault never tries to renew.storage_mode: both- writes to both surfaces. Reads compareupdated_ontimestamps and return the freshest copy (stale-read detection across surface skew).- New admin endpoint
POST /api/storage/azure-keyvault/backfill-certificates(and a "Backfill Certificate objects" button in Settings -> Storage) imports Certificate objects for existing Secrets-only domains. Idempotent. Accepts?limit=Nfor paginating large vaults; response includes aremainingcount. - CRC-aware secret domain listing bug-fix bundled: the regex in
_list_secret_domainswasendswith('-metadata'), which never matched any secret in production because_sanitize_secret_namealways appends an 8-char CRC32 suffix. Anchored to^cert-.+-metadata-[0-9a-f]{8}$. Pre-existing Azure KV backends were silently walking an empty domain list without this fix. - 40 unit tests added. 38 pass + 2 skip cleanly when
azure-keyvault-certificatesSDK is not installed.
Permissions
In certificate or both mode the Service Principal needs Certificates Get/List/Import/Delete in addition to its previous Secrets permissions. See docs/architecture.md for the full permissions table and the security note on Secrets/Get exposure.
Verification
Pre-merge: full test suite green on the merge-with-main tree - 97 passed, 1 skipped, 2 pre-existing xfail (docker + Playwright + Cloudflare real-cert lifecycle). Azure KV unit tests: 38 pass + 2 skip as designed.
Closes #139.