Data dictionary
The complete inventory of what Writ keeps about you and your agents. If an object isn’t listed here, Writ doesn’t store it.
A standing rule: raw secrets are never stored. API keys, sponsor tokens, magic-link tokens, and TOTP backup codes are kept as SHA-256 hashes only. The raw value is shown exactly once, at creation, and then it’s gone. The one exception is the TOTP secret itself, which must be stored reversibly to verify codes (DynamoDB encrypts it at rest).
Tenant
Your account. One tenant per email address. Everything below belongs to a tenant.
API key
Authenticates calls to the gate. Looks like writ_…. A tenant can have many.
Lost your key? While signed in to the portal you can mint a new one (API keys → + New key) and revoke the lost one. No need to delete anything. Portal issuance requires your authenticator code once you’ve enrolled one (fail-closed: no new keys until enrollment).
Sponsor token
The human half of the credential pair. Looks like writ_sp_…. One per
tenant, minted when the tenant is created, shown once, never recoverable.
Lost it? Rotate it from the portal (API keys → Rotate sponsor token):
a signed-in session mints a new token and the old one dies immediately,
with a ROTATE receipt in the audit log. The API key alone can never
rotate it.
It authorizes the human-side operations: creating grants, revoking and reinstating principals. The API key says which tenant is asking; the sponsor token says a human approved this.
Principal (kill switch)
Not to be confused with Principals (identity directory) below. This is the kill-switch principal: an agent acting on someone’s behalf — a sponsor (the human or system that approves) plus an agent (the software doing the work), within a tenant. Kill-switch principals come into existence implicitly — the first time a grant names them — and can be revoked pre-emptively, which denies everything they do.
Principals (identity directory)
Your tenant’s directory of identities — teams, services, agents. Every API
key is issued to exactly one directory principal and carries its
principal_id; every receipt snapshots the principal at write time. See
Principals.
Deletes are tombstones: a deleted principal stays resolvable by id, but no key can ever be issued to it again and its surviving keys are denied.
Policy
One tenant-default policy per tenant, plus optional per-environment
overrides (dev, staging, prod) and per-principal overrides (one
per identity-directory principal). Each policy object maps verbs to
modes and carries its own integer version (starting at 1, bumped on every
update). Overrides are sparse: a verb an override doesn’t name inherits
downward at check time — principal → environment → tenant default.
Resolution order (highest first): per-principal override → per-environment override → tenant default. An override on a disabled or deleted principal is inert — it never supplies a mode. There are no named policy sets yet.
The verb set starts with the built-ins fixed in the gate (money movement, identity, data changes, communications, infrastructure, and others) and grows with the tenant’s custom verbs — see Custom verbs. A policy may name a custom verb from the moment it is created; deprecated verbs — rename aliases and retired verbs — are rejected in new policies with the offending names listed, while environment- and principal-override maps keep entries for every registry name so a rename never silently drops a verb’s override.
Custom verb
One entry in the tenant’s verb registry (custom_verbs), created with
POST /v1/verbs. Renames and deletes are soft — the record is never
hard-deleted: the name stays reserved forever so old receipts keep their
meaning.
Grant
A short-lived permission slip minted by a human (sponsor token or dashboard)
after a STEP_UP, or directly via POST /v1/grants.
Receipt
Written for every decision the gate makes — ALLOW, DENY, STEP_UP,
REVOKE, PRINCIPAL_CREATE, PRINCIPAL_UPDATE, PRINCIPAL_DELETE,
VERB_CREATE, VERB_UPDATE, VERB_DELETE, and others. Denials write
receipts too: the refusal itself is auditable.
Receipts are the audit log, and the audit log is the meter.
Verify any receipt chain with GET /v1/receipts/verify or ./writ verify-chain.
Revocation
The kill switch. Revoking a principal denies every subsequent check for that sponsor/agent pair, immediately.
Reinstate undoes it; the principal can check again.
Magic-link token
Single-use sign-in token, emailed to you. Stored as a SHA-256 hash with a 15-minute expiry; the raw token travels in the URL fragment so it never lands in server logs. The account-creation variant works the same way and creates the tenant only when clicked.
Rate limits
Unauthenticated endpoints are bounded before any account lookup, so the limits themselves can’t be used to probe for accounts: 30 magic-link requests per hour per IP, a per-email cooldown on magic links, and per-tenant caps on key creation.