> Call POST /v1/check before a tool that writes. DENY means do not invoke the tool. For clean Markdown of any page, append .md to the page URL. For the complete index, fetch https://docs.withwrit.com/llms.txt.

# Data dictionary

> Every object Writ stores — tenants, keys, principals, policies, grants, receipts — and what each field means.

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,
and magic-link tokens are kept as SHA-256 hashes only. The raw value is shown
exactly once, at creation, and then it's gone.

## Tenant

Your account. One tenant per email address. Everything below belongs to a
tenant.

| Field                | Meaning                                                 |
| -------------------- | ------------------------------------------------------- |
| `id`                 | `ten_…` — the tenant's unique id                        |
| `name`               | Human-readable name (defaults to your email domain)     |
| `email`              | The address the tenant was created from                 |
| `plan`               | `free`, or flipped by the Stripe webhook after payment  |
| `policy`             | The tenant's policy (see Policy)                        |
| `stripe_customer_id` | Set once a Stripe customer exists for this tenant       |
| `pending_welcome`    | True until the first API key + sponsor token are issued |
| `created_at`         | Unix timestamp                                          |

## API key

Authenticates calls to the gate. Looks like `writ_…`. A tenant can have many.

| Field                            | Meaning                                                                                     |
| -------------------------------- | ------------------------------------------------------------------------------------------- |
| `key_hash`                       | SHA-256 of the key. The raw key is never stored                                             |
| `prefix`                         | Short non-secret display prefix (e.g. `writ_AbC1`) so you can tell keys apart in the portal |
| `label`                          | Optional label you set at creation                                                          |
| `email`                          | Address it was issued for                                                                   |
| `tenant_id`                      | Owning tenant                                                                               |
| `plan`                           | Mirrors the tenant plan at issue time                                                       |
| `checks_used` / `receipts_count` | Usage counters for the current period                                                       |
| `period` / `usage_since`         | The billing period the counters belong to                                                   |
| `created_at`                     | Unix timestamp                                                                              |
| `revoked_at`                     | Set when revoked. Revoked keys stop authenticating immediately; the record is kept          |

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.

## 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,
never re-issued through the portal today.

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

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.
Principals come into existence implicitly — the first time a grant names them
— and can be revoked pre-emptively.

| Field        | Meaning                           |
| ------------ | --------------------------------- |
| `sponsor_id` | Who approved this agent's actions |
| `agent_id`   | The agent itself                  |
| `tenant_id`  | Owning tenant                     |

## Policy

**One per tenant.** A table mapping each verb to a mode. There is no
per-agent or per-environment policy today.

| Mode            | Meaning                                        |
| --------------- | ---------------------------------------------- |
| `allow`         | The check passes without further approval      |
| `deny`          | The check fails; the write must not run        |
| `require_grant` | The check passes only with a live grant        |
| `step_up`       | A human sponsor must approve via a grant first |

The verb set is fixed in the gate (money movement, identity, data changes,
communications, infrastructure, and others). Custom verbs are not supported
today.

## Grant

A short-lived permission slip minted by a human (sponsor token or dashboard)
after a `STEP_UP`, or directly via `POST /v1/grants`.

| Field                                                     | Meaning                                                        |
| --------------------------------------------------------- | -------------------------------------------------------------- |
| `id`                                                      | `grnt_…`                                                       |
| `sponsor_id` / `agent_id` / `verb` / `target` / `purpose` | Exactly what is allowed. All five must match the check         |
| `ttl_seconds`                                             | Lifetime. Defaults to 90 seconds, max 3600 (1 hour)            |
| `expires_at`                                              | Unix timestamp when it dies                                    |
| `spent`                                                   | Single-use semantics: it can't be reused for a different write |
| `tenant_id`                                               | Owning tenant                                                  |
| `created_at`                                              | Unix timestamp                                                 |

## Receipt

Written for **every** decision the gate makes — `ALLOW`, `DENY`, `STEP_UP`,
`REVOKE`, and others. Denials write receipts too: the refusal itself is
auditable. Receipts are the audit log, and the audit log is the meter.

| Field                                                   | Meaning                                                                                                                                                                     |
| ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `receiptId`                                             | `rcpt_…`                                                                                                                                                                    |
| `tenantId`                                              | Owning tenant                                                                                                                                                               |
| `decision`                                              | The gate's answer                                                                                                                                                           |
| `sponsorId` / `agentId` / `verb` / `target` / `purpose` | What was decided on                                                                                                                                                         |
| `grantId`                                               | The grant that authorized it, if any                                                                                                                                        |
| `reason`                                                | Human-readable reason for the decision                                                                                                                                      |
| `policyVersion`                                         | The policy version the decision ran against                                                                                                                                 |
| `prevHash` / `chainHash`                                | Tamper-evident chain: each receipt stores the previous receipt's `chainHash` (or `GENESIS`), and `chainHash = HMAC(canonical fields + prevHash)` with a tenant-specific key |
| `createdAt`                                             | Unix timestamp                                                                                                                                                              |

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.

| Field                     | Meaning                     |
| ------------------------- | --------------------------- |
| `sponsor_id` / `agent_id` | The principal being cut off |
| `reason`                  | Why, in your words          |
| `revoked_at`              | Unix timestamp              |
| `tenant_id`               | Owning tenant               |

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.