> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tenant master key

> Every tenant has its own master key. It wraps everything else KnoxCall encrypts on your behalf — and it's the lever for cryptographic erasure.

# Tenant Master Key

Every KnoxCall tenant has its own **master key** — a 32-byte symmetric key that wraps every other piece of encrypted material the tenant owns. Secrets, database admin passwords, SSH keys, CA private keys, transit-key versions: all of it is wrapped (KCT1 envelope format) by the tenant master key.

This is the load-bearing isolation primitive in KnoxCall. A bug in the control plane, a stolen backup, or a malicious insider hitting the wrong row in the database can't leak data across tenants — every tenant's data is wrapped with **its** key, and you can't unwrap one tenant's blob with another tenant's key.

The Vault parallel: this is your unseal key, except per-tenant rather than per-cluster, and unwrapped on demand from a configurable backing store rather than at startup.

## How it's stored

The master key isn't stored in plaintext anywhere. It's stored **wrapped** in the `tenant_master_keys` table, and the wrapping method is configurable per tenant. There are three:

| Wrap method    | What wraps the master key                   | Where the wrapping key lives          | Sovereignty                                                 |
| -------------- | ------------------------------------------- | ------------------------------------- | ----------------------------------------------------------- |
| `global`       | `MASTER_KEY_B64` (the deployment's env var) | KnoxCall's process env                | Default — same as today, plus per-tenant isolation          |
| `operator_kms` | A KMS key in **KnoxCall's** cloud account   | AWS / GCP / Azure (KnoxCall-operated) | Strong (KMS audit, hardware-backed)                         |
| `customer_kms` | A KMS key in **your** cloud account         | AWS / GCP / Azure (yours)             | Strongest — [BYOK](/essentials/key-management/byok-and-kms) |

See the [BYOK & KMS guide](/essentials/key-management/byok-and-kms) for how to set up `operator_kms` or `customer_kms`. Without explicit configuration, every tenant uses `global` — same crypto today, plus per-tenant isolation.

## How it's used

Every per-tenant crypto operation goes through `TenantMasterKeyManager`. The flow:

1. Caller wants to encrypt or decrypt something for tenant `T`.
2. Manager checks its in-memory cache for `T`'s unwrapped master key.
3. **Cache hit** → use the cached key.
4. **Cache miss** → load the wrapped row, dispatch to the correct provider (global / AWS / future GCP / future Azure) to unwrap, cache for an hour.
5. Concurrent misses for the same tenant **deduplicate** — N parallel requests after a cache flush trigger one unwrap, not N.

The cache TTL is 1 hour by default for `global` and `operator_kms` wrap methods; customer-tunable in `[60, 3600]` seconds for those methods. **Exception: `customer_kms` (BYOK) tenants have a fixed 5-minute TTL** — this is not customer-tunable, and is intentional to bound plaintext exposure if the customer revokes KMS access.

Two practical implications:

* **First call after a cache miss is slow** (KMS round-trip). Subsequent calls are local.
* **You can revoke KnoxCall's KMS access mid-flight**, and the next cache flush makes the tenant immediately unable to unwrap anything. The tenant goes "sealed."

## Sealed state

If unwrapping fails (KMS access denied, KMS unreachable, key disabled), the manager records `tenant_kms_config.sealed_since`. For `customer_kms` (BYOK) tenants, the 5-minute cache TTL means the tenant becomes sealed within 5 minutes of losing KMS access. While sealed:

* New encrypts / decrypts for that tenant fail with a clear error.
* The cache still serves any unexpired entries — the tenant doesn't go dark instantly, only after the cache TTL.
* The admin UI's Key Management section shows the sealed state and the last KMS error.

The sealed state clears automatically on the next successful unwrap.

## Versioning

Master keys are versioned per tenant. Each rotation creates a new row at the next version, marks the previous one `retired`, and sets the new one `active`.

* **Active** — current version. New wraps use this. One per tenant.
* **Retired** — older but still usable for unwrap of legacy ciphertext.
* **Revoked** — explicitly destroyed. Cryptographic erasure: data wrapped by this version is **permanently unreadable**.

## Cryptographic erasure (the kill switch)

Revoking a tenant master key version is destructive. It's the right-to-be-forgotten primitive, and it cascades:

```text theme={"dark"}
Revoke tenant master key v1
   ↓
Every CA private key wrapped by v1 → unreadable
Every secret blob wrapped by v1   → unreadable
Every transit-key version wrapped by v1 → unreadable
Every database admin password wrapped by v1 → unreadable
```

The data **rows** stay in the database for audit, but the wrapped blobs can never be unwrapped again. Re-issuing a tenant master key won't bring them back — fundamentally different bytes.

The admin UI guards revocation with a confirm-by-typing-tenant-name dialog. The audit-log entry records who, when, and why.

## What never leaves KnoxCall

These never appear in any API response:

* The unwrapped master key bytes.
* The wrapped blob (visible in DB rows; not exposed to API).
* The KMS provider's response payload.

The Key Management endpoints return **metadata only** — version, wrap method, KMS key reference (the ARN, not the key), sealed state, timestamps. There is no `GET /admin/key-management/keys/{version}/material` and there never will be.

## Audit-trail markers

| Audit action                          | What it means                                                                                                        |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `tenant_master_key.create`            | New master key minted (rotation or initial provision)                                                                |
| `tenant_master_key.kms_config_update` | KMS config changed (e.g. switched from `global` to `customer_kms_aws`)                                               |
| `tenant_master_key.revoke`            | Cryptographic erasure of a version                                                                                   |
| `tenant_master_key.cache_clear`       | Operator forced an unwrap on next access (e.g. to verify KMS still works)                                            |
| `byok.kms.onboard`                    | Customer KMS provider onboarded (BYOK)                                                                               |
| `byok.kms.rotate`                     | Tenant master key rotated under BYOK config                                                                          |
| `byok.kms.unseal`                     | Tenant unsealed after KMS access restored (seal itself is not logged — only `sealed_since` is set on the config row) |

## What's shipped today

* ✅ Per-tenant master keys for all three wrap methods (rows, manager, cache, sealed-state).
* ✅ `global` wrap (the deployment-wide `MASTER_KEY_B64`).
* ✅ AWS KMS provider (`operator_kms_aws`, `customer_kms_aws`).
* ✅ GCP Cloud KMS provider (`operator_kms_gcp`, `customer_kms_gcp`) — Workload Identity Federation.
* ✅ Azure Key Vault provider (`operator_kms_azure`, `customer_kms_azure`) — Federated Credentials.
* ✅ Cryptographic erasure with audit trail.
* ✅ Tenant KMS dashboard — manage BYOK config at Settings → Security → Tenant Master Key → Customer KMS.
* ⏳ Bulk rewrap migration: when you rotate a master key, existing data stays wrapped under the retired version. A migration tool to rewrap everything to the new active version is on the roadmap (the manual escape valve is to do it via `rewrap` / per-resource update).

## See also

* [BYOK & KMS providers →](/essentials/key-management/byok-and-kms)
* [Crypto Keys overview →](/essentials/crypto-keys/crypto-keys-overview) — what `cloud-only` vs `bundled` means in the context of the master key
* [Certificate Authority overview →](/essentials/pki/pki-overview) — how the master key protects CA private keys
