This map was written after v0.1.0 shipped — the release predates the parity map
itself, and a git tag is immutable — so it is a retrospective reading rather
than a document published at the time. It is drawn from the v0.1.0 tree:
- the 42 routes it registers (v0.2.0 registers 66),
- the crypto it implements (
internal/vault/crypto.go),
- the CI jobs it ran (
test only — no portal, no chain),
- which packages exist at all (no
internal/vault/parity.go, no portal/, no e2e/).
The shape of v0.1.0: the object model and the cryptography were already real
— secrets, RSA/EC keys doing real sign/verify/encrypt/decrypt/wrap, self-signed
X.509, soft-delete, the Entra challenge. What v0.2.0 added was the surface
around them: key import, RNG, release, rotation policy, backup/restore, and
the whole certificate CSR → CA → merge flow.
Row names deliberately match the current map so the
parity changelog can diff them.
| Meaning |
|---|
| 🟢 Real | Genuine work: real signed JWTs verified, real crypto, real X.509, real logic enforced — no pretending. |
| 🟡 Emulated | Faithful API contract + persisted state, but no engine — clock-derived or management-only. |
| 🟠 Bring-your-own-engine | Real when you attach a real external engine; contract-only otherwise. |
| 🔴 Not implemented | Absent (404). |
| Key Vault feature | Emulator | Type |
|---|
Entra bearer challenge (401 + WWW-Authenticate) | Full — the real challenge with AKV code AKV10000 | 🟢 Real |
| Token validation (RS256 / JWKS / issuer / audience / expiry) | Full — signature verified before any claim, on the controllable clock | 🟢 Real |
Principal derivation (oid → sub; idtyp=app → service principal) | Full | 🟢 Real |
| Multi-tenant / multiple trusted issuers | Exactly one issuer | 🔴 Not implemented |
| Key Vault feature | Emulator | Type |
|---|
| Set / get / list / list-versions, get by version | Full; real bytes persisted | 🟢 Real |
| Versioning (32-hex version per write) | Full | 🟢 Real |
Attributes enabled | Enforced | 🟢 Real |
Attributes nbf / exp | Informational only — deliberately not enforced | 🟡 Emulated |
| Backup / restore | Round-trips a JSON blob, not an opaque encrypted blob | 🟡 Emulated |
| Key Vault feature | Emulator | Type |
|---|
| Create key — RSA 2048/3072/4096, EC P-256/P-384/P-521 | Real keygen | 🟢 Real |
| Sign / verify — RS256/384/512, PS256/384/512, ES256/384/512 | Real, with Azure’s raw r‖s ECDSA encoding | 🟢 Real |
| Encrypt / decrypt — RSA1_5, RSA-OAEP, RSA-OAEP-256 | Real RSA | 🟢 Real |
| Wrap / unwrap key | Real — the same RSA path | 🟢 Real |
| Public JWK exposure (private material never leaves) | Full | 🟢 Real |
RSA-HSM / EC-HSM key types | Accepted, normalised to software keys | 🟡 Emulated |
| Import key (JWK) | — no PUT /keys/{name}; the importer does not exist yet | 🔴 Not implemented |
| Get random bytes | — no POST /rng | 🔴 Not implemented |
Secure Key Release (/release) | — no route | 🔴 Not implemented |
| Key rotation policy (get/set) | — no route | 🔴 Not implemented |
| Key backup / restore | — no route | 🔴 Not implemented |
Rotate key (POST /keys/{name}/rotate) | — | 🔴 Not implemented |
key_ops enforcement | Stored, not enforced | 🔴 Not implemented |
oct / oct-HSM symmetric keys | — | 🔴 Not implemented |
| AES algorithms (A128/192/256 CBC/CBCPAD/GCM, AESKW) | — | 🔴 Not implemented |
| BYOK (KEK-wrapped import) | — | 🔴 Not implemented |
| Key Vault feature | Emulator | Type |
|---|
| Create self-signed certificate | Real x509.CreateCertificate | 🟢 Real |
Certificate policy (key_props, x509_props, issuer) | Honoured | 🟢 Real |
| Import — PKCS#12 (PFX) and PEM (PKCS#8 / PKCS#1 / SEC1) | Real parsing | 🟢 Real |
| Linked key + secret materialised under the same name | Full on create | 🟢 Real |
| Certificate signing request (PKCS#10) for a named issuer | — no CSR generation exists at this tag | 🔴 Not implemented |
| Merge a signed chain | — no POST /certificates/{name}/pending/merge | 🔴 Not implemented |
| Issuance by a real CA | — the CSR/merge flow that enables it does not exist yet | 🔴 Not implemented |
| Delete cascade to the linked key/secret | Diverges from real Key Vault: creation cascades, deletion does not | 🟡 Emulated |
| Issuers / contacts | — no routes | 🔴 Not implemented |
| Certificate backup / restore | — no route | 🔴 Not implemented |
| Cancel / delete a pending certificate operation | — | 🔴 Not implemented |
| Key Vault feature | Emulator | Type |
|---|
| Soft-delete → list-deleted → recover → purge (secrets, keys, certificates) | Real state machine | 🟡 Emulated |
| Retention window expiry | Clock-driven, purged lazily on read/list | 🟡 Emulated |
Name reuse while soft-deleted → 409 Conflict | Enforced | 🟢 Real |
Purge protection / non-purgeable recoveryLevel | Always Recoverable+Purgeable | 🔴 Not implemented |
| Key Vault feature | Emulator | Type |
|---|
Host-routed vaults ({name}.vault.azure.net) | Full | 🟢 Real |
Canonical object IDs (https://{vault}.vault.azure.net/...) | Full | 🟢 Real |
TLS with a cert covering *.vault.azure.net | Real self-signed material | 🟢 Real |
Paging (maxresults, nextLink) | Full | 🟢 Real |
Key Vault error envelope + x-ms-request-id | Full | 🟢 Real |
api-version validation / version-differentiated behaviour | Never read | 🔴 Not implemented |
| Key Vault feature | Emulator | Type |
|---|
| Data-plane authorization | Per-principal operation allowlist (POST /_emulator/permissions) | 🟡 Emulated |
| RBAC data-plane roles (Key Vault Secrets User, …) | — | 🔴 Not implemented |
| Access policies (the classic vault access-policy document) | — | 🔴 Not implemented |
| Feature | Purpose |
|---|
Clock control (/_emulator/clock) | Freeze/advance — deterministic token expiry and retention |
Fault injection (/_emulator/faults) | Force 429/500 to exercise SDK retry paths |
Permissions (/_emulator/permissions) | The authorization allowlist above |
| Real client (pinned) | Surface exercised | Status |
|---|
azsecrets (Azure Go SDK) | Secrets, versions, soft-delete | 🟢 CI test |
azkeys (Azure Go SDK) | Keys, sign/verify, encrypt/decrypt, wrap/unwrap | 🟢 CI test |
azcertificates (Azure Go SDK) | Certificate create/import | 🟢 CI test |
azidentity (ClientSecretCredential) | The Entra challenge handshake against a real entra-emulator | 🟢 CI test |
| Three-emulator chain (vault secret → managed identity → Entra → Fabric) | — e2e/ does not exist at this tag | 🔴 Not wired in CI |
azure-keyvault-secrets / azure-identity (Python) | — | 🔴 Not wired in CI |
| .NET / JavaScript SDKs | — | 🔴 Not wired in CI |
| Azure feature | Why out of scope | Type |
|---|
ARM control plane (create/delete vaults, Microsoft.KeyVault/vaults) | A different plane; the emulator serves the data plane | 🔴 |
Managed HSM (managedhsm.azure.net) | A distinct service and a hardware trust boundary | 🔴 |
| Private endpoints / firewall / network ACLs | Network topology, not vault behaviour | 🔴 |
| Customer-managed-key encryption of the vault itself | Infrastructure-level | 🔴 |
| Real CA issuance (DigiCert / GlobalSign integrations) | Needs a real CA | 🔴 |
| Diagnostic logs / Event Grid notifications / metrics | Azure Monitor surface | 🔴 |