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.
Rotation and versioning
Every crypto key in KnoxCall is versioned. New encryptions always use the latest active version; old ciphertext keeps decrypting against whatever version originally produced it. Rotation moves the active pointer forward without breaking anything that’s already encrypted.The version lifecycle
active— used for new encryptions. Exactly one per key at any time.retired— kept around so old ciphertext under that version still decrypts. As many as you’ve rotated.destroyed— cryptographic erasure. The wrapped key bytes are wiped and the row stays as an audit marker. Ciphertext under a destroyed version is permanently unreadable.
Rotating a key
- A new 256-bit key is generated and wrapped with the tenant master key.
- The new version row is inserted as
active. - The previous active version is flipped to
retired. - The key’s
current_versionpointer is updated.
encrypt calls from this point forward emit knoxcall:v2:... ciphertext. decrypt calls handle either v1 or v2 ciphertext seamlessly.
When to rotate
| Reason | How often |
|---|---|
| Routine hygiene (compliance) | Every 90 days |
| After a personnel change with key access | Immediately |
| After a suspected compromise | Immediately + rewrap + destroy old version |
| Pre-emptive before destroying the active version | Always (you can’t destroy active) |
Rewrap: migrate ciphertext to a new version
Rotating doesn’t re-encrypt existing data. Old ciphertext keeps decrypting against retired versions. To migrate it:rewrap decrypts the old ciphertext with the retired version, re-encrypts with the active version, and returns the new ciphertext — the plaintext never crosses the wire. The operation runs entirely on KnoxCall’s side.
The typical migration loop:
Destroying a version (cryptographic erasure)
- Refuses if
deletion_allowed = falseon the parent key (the prod safety latch). - Refuses if the version is
active— rotate first. - Wipes the wrapped key bytes from the row, flips status to
destroyed, records who and when.
deletion_allowed
By default, new keys ship with deletion_allowed = false on production tenants. Flipping it to true is a deliberate, audit-logged action that says “I’m about to destroy a version on purpose.”
Pattern we recommend:
- Rewrap all data to the new active version.
- Confirm in a query that no row in your DB still has ciphertext at the version you’re about to destroy.
- Flip
deletion_allowed = true. DELETE /versions/<old>.- Flip
deletion_allowed = falseagain.
What rotation doesn’t do
- It doesn’t break existing decryption — old ciphertext keeps working until you destroy the old version.
- It doesn’t re-encrypt existing data — that’s
rewrap. - It doesn’t change the ciphertext format — same prefix, just a higher version number.
- It doesn’t propagate to bundled-mode agents instantly — they pick up the new version on their next session-bundle refresh.
Key cache behaviour
Unwrapped key versions are cached in memory for 5 minutes after first use. Rotation invalidates the previous active entry; destroy invalidates the destroyed entry. You don’t need to worry about the cache day-to-day — it’s an internal performance optimisation, not something you manage.Audit log markers
| Audit action | Means |
|---|---|
transit.key.create | A new key was minted (version 1 active) |
transit.key.rotate | New version became active |
transit.encrypt / transit.decrypt | Single op (records key version, not plaintext) |
transit.rewrap | Ciphertext was rewrapped from one version to another |
transit.key.destroy_version | Version was cryptographically erased |
See also
- Crypto Keys overview →
- Tenant master key → — the wrap chain that protects every transit key