Custodian
ReferenceCommand line

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 acme

Options:

  • --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:15

The 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 --key
master 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.

CodeWhat it means
over_broad_grantA 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_changeA 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_collectionNo 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_searchableA 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_grantA 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_deviceA 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_recordA grant is past its expiry but still on record. It grants nothing, but the grant list no longer describes intent — remove it.
no_recovery_envelopeThe 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_deviceThe 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_refusedThis 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

On this page