Data model

Postgres schema, defined in src/lib/db/schema.ts with Drizzle and migrated by the SQL files in drizzle/. All timestamps are timestamptz stored as ISO-8601 strings. JSON columns are jsonb.

This is a reference for operators querying the database directly and for anyone extending the schema. For the events that populate the derived tables, see events.md.

Tables

agents — registry

One row per enrolled agent.

ColumnTypeNotes
aidvarchar(512) PKAgent identity
display_namevarchar(256)
handshake_endpointtextAgent's p2p handshake URL
offered_capsjsonb string[]GIN-indexed for @> capability discovery
manifest_jsontextRaw signed ManifestEnvelope bytes (the CP's cached copy)
manifest_expires_attimestamptzManifest TTL; the expiry sweep flips status when it lapses
statusvarchar(32)active | expired | deregistered (inactive is a legacy synonym)
registered_attimestamptzSet once at first enrollment
last_enrolled_attimestamptzUpdated on every (re-)register
last_seen_attimestamptzLast event reported by the agent
org, cloudvarchar(128)Optional labels (not set by the current enroll path)
namespacevarchar(128)Tenant scope, default default
metadatajsonbOperator-provided blob

Indexes: status, registered_at, namespace, GIN on offered_caps.

handshake_sessions — sessions projection

Projected from handshake.* events. The CP never sees handshake traffic; this is a reconstruction.

ColumnTypeNotes
session_idvarchar(255) PK
aid_a, aid_bvarchar(512)Participants
statusvarchar(32)started | complete | failed
grantsjsonb string[]From the completion event
run_idvarchar(255)Trace correlation
boundaryvarchar(32)Derived from payload
errortextSet when failed
started_at, completed_at, created_at, updated_attimestamptz

Indexes: status, aid_a, aid_b, run_id.

audit_events — append-only event store

Every ingested or CP-emitted event. Source of truth behind /api/events/history and SSE.

ColumnTypeNotes
iduuid PKDe-dupe key (ON CONFLICT DO NOTHING)
typevarchar(128)e.g. handshake.complete
tstimestamptzEvent time
aid_a, aid_bvarchar(512)
session_id, run_idvarchar(255)
grantsjsonb string[]
payloadjsonbEvent-specific body
sourcevarchar(128)cp, playground, an agent AID, etc.
created_attimestamptz

Indexes: type, ts, session_id, run_id, aid_a. Aged out after AUDIT_EVENTS_TTL_DAYS.

issued_tcts — observed TCTs

Projected from tct.issued / handshake.complete payloads. The CP observes; it never issues.

ColumnTypeNotes
jtiuuid PK
issuer_aid, subject_aid, audience_aidvarchar(512)All indexed
grantsjsonb string[]GIN-indexed
binding_cnfvarchar(128)cnf confirmation key
issued_attimestamptz
expires_attimestamptz
session_idvarchar(255)Indexed
revoked, revoked_atboolean / timestamptzMirrored from revocation_entries and tct.revoked

delegations — delegation chains

Parent→child TCT relationships — single-hop RFC-AITP-0006; multi-hop draft RFC-AITP-0011. ?root_jti= queries walk this tree via a recursive CTE.

ColumnTypeNotes
jtiuuid PKChild delegation
parent_jtiuuidIndexed; root of a chain walk
delegator_aid, delegatee_aidvarchar(512)Indexed
scopejsonb string[]Delegated capability subset
issued_at, expires_attimestamptz
revoked, revoked_atboolean / timestamptz
revoked_reasonvarchar(64)explicit | parent_revoked (cascade)

revocation_entries — revoked JTIs

Backs the signed /.well-known/aitp-revocation-list. Adding a row also flips issued_tcts.revoked.

ColumnTypeNotes
jtiuuid PK
revoked_attimestamptzDefaults to now
reasontextOptional
created_attimestamptz

webhooks — subscriptions

ColumnTypeNotes
iduuid PK
urltextSSRF-guarded at write time
eventsjsonb string[]Empty = all deliverable types
secretvarchar(255)HMAC-SHA256 signing key
activebooleanIndexed
created_at, updated_attimestamptz

webhook_deliveries — outbox

ColumnTypeNotes
iduuid PK
webhook_iduuid FKON DELETE CASCADE from webhooks
event_typevarchar(128)
payloadjsonbFull event envelope
bodytextCanonical bytes captured at enqueue for byte-stable retries
signaturevarchar(64)HMAC computed once at enqueue (survives secret rotation)
statusvarchar(32)pending | delivered | failed
attemptsintegerOptimistic-lock counter
status_code, errorinteger / textLast attempt result
delivered_at, next_retry_attimestamptzExponential backoff
created_attimestamptz

Indexes: webhook_id, status. Terminal rows aged out after WEBHOOK_DELIVERY_TTL_DAYS.

admin_audit_log — admin actions

Distinct from audit_events; records who hit the admin mutating endpoints.

ColumnTypeNotes
iduuid PK
actionvarchar(128)e.g. agent.register
actor_idvarchar(255)Indexed
target_idvarchar(512)Affected AID/JTI
detailsjsonb
request_idvarchar(255)Correlation
created_attimestamptzIndexed; aged out after ADMIN_AUDIT_TTL_DAYS

trust_anchors — OIDC issuer allowlist

OIDC identity mode (RFC-AITP-0002). Unique on (namespace, issuer_url).

ColumnTypeNotes
iduuid PK
namespacevarchar(128)Indexed
issuer_urltext
jwks_urltextOptional override of issuer's jwks_uri
jwks_cache, jwks_cached_atjsonb / timestamptzCP-refreshed keyset cache
label, added_byvarchar
created_at, updated_attimestamptz

pinned_keys — pinned-key allowlist

Pinned-key identity mode (RFC-AITP-0002). Composite PK (namespace, aid).

ColumnTypeNotes
namespacevarchar(128)PK part
aidvarchar(512)PK part; also indexed
pubkeyvarchar(128)Ed25519 public key
label, added_byvarchar
expires_attimestamptzOptional
created_at, updated_attimestamptz

idempotency_keys — request de-dupe

Caches the response of a mutating request keyed by (scope, key).

ColumnTypeNotes
scopevarchar(64)PK part — endpoint id (e.g. agents.register, events.ingest)
keyvarchar(255)PK part — the client Idempotency-Key value
response_statusintegerCached HTTP status
response_bodyjsonbCached body
created_attimestamptzIndexed; aged out after IDEMPOTENCY_KEY_TTL_DAYS

enrollment_jtis — one-time-token enforcement

A consumed enrollment-token jti lands here; a replay conflicts on the PK.

ColumnTypeNotes
jtivarchar(64) PK
expires_attimestamptzToken TTL; row aged out after it
created_attimestamptzIndexed

Migrations

Applied in order by npm run db:migrate (drizzle-kit). Each push to main that changes the schema adds a new file; run migrations against the target database from a checkout (the runtime image does not bundle drizzle-kit).

FileAdds
0000_init.sqlInitial schema: agents, sessions, audit_events, revocation_entries, webhooks, webhook_deliveries, admin_audit_log, issued_tcts, delegations, trust_anchors, pinned_keys
0001_plan_v0_2.sqlBackfill legacy inactivederegistered
0002_offered_caps_gin.sqlGIN index on agents.offered_caps
0003_webhook_delivery_body.sqlbody + signature on webhook_deliveries
0004_idempotency_keys.sqlidempotency_keys table
0005_aitp_depth.sqlDelegation-depth support
0006_trust_anchors_uniq.sqlUnique (namespace, issuer_url)
0007_enrollment_jtis.sqlenrollment_jtis table

Retention note: revocation_entries, issued_tcts, delegations, trust_anchors, and pinned_keys are not swept — they're authoritative records, not telemetry. Only audit_events, webhook_deliveries, admin_audit_log, idempotency_keys, enrollment_jtis, and long-deregistered agents are aged out. See operations.md.