custodian doctor
Read a whole vault's health from one page — key state, schema, searchable fields, devices and principals — and the warnings that otherwise pass unnoticed.
custodian doctor prints one read-only report on the health of a vault: its key
state, the schema across the four sensitivity levels, which
fields are searchable, the live devices with the guarantee
each one provides, and the principals with their live
grants and when each last read. It is built from metadata
alone — it reads no field value and decrypts nothing — so it is safe to run at any
moment.
Be signed in with an operator token first. doctor is an
operator command; a service or agent credential is refused before anything prints.
custodian doctor --vault acmeOptions:
--url <api>— select the deployment.--vault <slug>— select the vault.--json— emit the same report as machine-readable JSON.--key— also derive and print this device's master-key fingerprint (see below).--strict— exit non-zero if any warning is present (the report still prints).--stale-after <days>— how long a device may go unseen before it is warned as stale. Defaults to 90.
What it shows you
vault acme recovery envelope present · 2 live devices · healthy
collections 2 (policies, claims)
fields 7 (2 plain, 1 masked, 2 tokenised, 2 client_encrypted)
searchable fields 2
policies.policy_number — plain, no blind index
policies.holder_tax_id — client_encrypted, 16-bit index
devices
dev_3Kp9… ops-laptop secure_enclave enrolled 2026-08-20 last seen 2h ago
Secure Enclave — the device private key is generated in the enclave, is non-exportable, and every private-key operation happens inside it; the key never enters this tool's memory
dev_9Xy4… finance-laptop secure_enclave enrolled 2026-08-21 last seen 3d ago
Secure Enclave — the device private key is generated in the enclave, is non-exportable, and every private-key operation happens inside it; the key never enters this tool's memory
principals
agent-claims agent 2 grants last read 2026-08-21 14:02
ops-admin operator 4 grants last read 2026-08-21 09:15The header's last word is a one-word verdict: healthy when a recovery envelope
exists, the vault is redundant across live devices, and no rotation or destruction
is under way. Anything else names what is not true — no recovery envelope,
single device, no live devices, or destroyed.
A clean vault prints nothing after the principals. There is no "0 warnings" banner, so a warning stands out when it appears.
--key — confirm two machines hold the same key
--key is the only flag that touches key material. It derives and prints this
device's master-key fingerprint — a one-way value that identifies the key without
disclosing it — so two operators on two machines can confirm they hold the same
master key. Deriving it unwraps the master key on this device and may prompt the key
store; the default report never does.
custodian doctor --vault acme --keymaster key fingerprint sha256:9f2c…The same key in the same vault always fingerprints the same, and the key cannot be
recovered from the printed value. If no live device on this machine can unwrap the
key, --key says so and derives nothing:
No live device in vault "acme" holds this machine's key, so the master key cannot be unwrapped here and its fingerprint cannot be derived. Run --key on an enrolled machine.--strict and --stale-after
doctor exits zero even when it prints warnings, because they are advisory. Pass
--strict to make the presence of any warning exit non-zero, so a health check in a
pipeline fails on one — the report still prints in full.
--stale-after <days> sets how long a device may go unseen — how old its last seen
time must be — before the stale_device warning names it. It defaults to 90 days.
Warnings
doctor surfaces the misconfigurations that are legal but unwise — the ones nothing
refuses when you make them. They appear under a warnings heading, each as a !
line that already names what to do about it. Warnings about this machine appear
under a separate heading, because two operators reading the same vault can honestly
see them differently.
The codes below use the grant actions (read_plaintext, read_token, read_masked)
defined on custodian grants and the field sensitivities
(client_encrypted and the blind index) defined on
custodian schema.
| Code | What it means |
|---|---|
over_broad_grant | A service or operator has read_plaintext on a whole collection with no expiry. Narrow it to the fields the principal needs, add an expiry, or revoke it. |
grant_widened_by_schema_change | A collection-wide grant now also covers a plain or tokenised field that a later schema change added, which the grant's author never saw. Review whether the principal should read it, and re-scope the grant. |
unreferenceable_collection | No principal holds read_token on the collection, so no agent can reference a record in it — usually a setup someone did not finish. |
client_encrypted_searchable | A client_encrypted field is searchable. Anyone holding the database and the index key can enumerate the field's value space; doctor has not judged that space. Prefer a non-sensitive lookup key, or narrow the index. |
ineffective_grant | A grant that resolves to nothing — read_token on a plain or masked field (which carries no token), or read_masked on a client_encrypted field (which the server cannot render as a mask). Revoke it, or grant an action the field supports. |
stale_device | A live device has not been seen for longer than the --stale-after threshold. It still holds a wrapped copy of the master key, so revoke it if it is gone for good. |
expired_grant_on_record | A grant is past its expiry but still on record. It grants nothing, but the grant list no longer describes intent — remove it. |
no_recovery_envelope | The vault has no recovery envelope, so one lost device leaves the master key unrecoverable. Enrol another device so a single loss is not fatal. |
single_device | The vault has a single enrolled device; losing it means falling back to the recovery code. Enrol another so no single loss forces a recovery. |
memory_lock_refused | This machine could not lock key pages into memory, so key material may reach swap. This is a property of this machine, not the vault. |
--json
--json emits the whole report as one JSON object — the same data as the human
report, including a warnings array where each entry carries a stable code, so a
health check can alert on a specific one.
custodian doctor --vault acme --json