Admin API — everything under /api/ without the v1 prefix. The admin
application’s own API, authenticated with a session cookie and enforcing
per-user RBAC. Not versioned, and not what you build an integration against.
Alarm — a workspace rule that flags content problems without ever blocking a write: a content type, a saved records-list filter, and a severity. Its verdict about one entry is a finding.
API token — a long-lived bearer credential for the public API, minted in the
admin. Scoped read or full, and bucketed to a set of workspaces.
Bucket — the set of workspaces an API token may act in. A request picks one
with X-Workspace-Id.
Collection — a content type with many entries. Declared with collection().
Delivery — one attempt series to POST one event to one webhook endpoint.
Has its own id (X-Apograph-Delivery, new on every redelivery) and a status:
pending, delivering, succeeded, failed (another attempt is scheduled)
or dead.
Domain event — an immutable record that something happened, appended to the outbox in the same transaction as the change that raised it.
Envelope — the platform-owned columns every entry carries: id,
workspace_id, created_at, updated_at, plus the flag-gated status,
published_at, deleted_at, locale and locale_group_id. Also the JSON
body of a webhook delivery, which carries references to the record rather than
its values.
Event id — the outbox event’s id, carried on every webhook delivery as
X-Apograph-Event-Id and as eventId in the body. Stable across retries and
redeliveries, which is what makes it the key a receiver deduplicates on.
Finding — one alarm rule’s verdict about one entry. Keyed (rule, entry),
so a repeat evaluation is a no-op; firstSeenAt survives it resolving and
re-opening.
Host — the application shell that turns a plugin list into a running app. There are two, one per runtime, and they own no domain logic.
Locale group — the set of rows that are translations of each other, sharing
a locale_group_id. A record in one language is one row of a group.
Localized field — a field marked localized: true, whose value differs per
language. A field without the flag is shared across the whole group.
Mirrored relation — a relation on a localized type whose target is also localized, so a synced link resolves to the target’s row in each sibling’s own language.
Modified — an entry with live published content and unpublished edits on
top of it. Not a stored value: it is status = 'draft' with a non-null
published_at.
Outbox — the table domain events are appended to, inside the transaction of the change that raised them, then dispatched to subscribers after commit. Internal to the process.
Paranoid — a content type with soft delete. Deleting stamps deleted_at
rather than removing the row.
Plugin — a unit of capability. Admin plugins contribute routes and slot items; server plugins contribute a NestJS module and optionally schema and migrations.
Port — a Symbol token plus an interface, declared by the plugin that wants
extending and bound by the one providing the behaviour. The server-side
counterpart of a slot.
Propose tool — an agent tool that computes a change and hands it back rather than writing it. The run engine records the change and applies it.
Publish gate — the check run before an entry goes live: every required field present, every present value valid.
Protection rule — a per-content-type rule requiring a number of approvals
before an entry of that type may be published. One row per
(workspace, content type); with no row the type publishes as it always did.
Resolve-from-source — workspace packages are consumed straight from
src/index.ts with no build step.
Review approval — one person’s vote on one revision, not on the entry. A later save moves the head, so the approval stops counting without being deleted — the editor shows it struck through, naming the version it was given on.
Revision — an immutable snapshot of a whole entry, written inside the transaction of the save that produced it.
Saved view — a named slice of a collection’s list: filter, sort and
columns. Private to its author, or shared with the workspace by someone holding
views:share.
Segment — a named reader audience: a set of tags a reader may arrive carrying. An entry names the segments it admits and the segments it refuses; a deny wins, and an empty allow list means everyone. Decides who may read published content, never who may edit it.
Single — a content type with exactly one entry, declared with single().
Requires a path.
Skill — a named instruction packet for the copilot, with a description of when it applies. Reaches the model only through the system prompt.
Slot — a named UI extension point one plugin defines and others contribute into as data, wired once at boot.
Surfaces — which agent consumers a tool is offered to: copilot, mcp, or
both. Omitting it means both.
Tool — a named, permission-gated capability an agent can invoke, held in one registry shared by the copilot and the MCP endpoint.
Unit of work — the transaction boundary. A nested run joins the outer
transaction rather than opening a new one.
Webhook — an endpoint this installation POSTs to when an entry changes: a URL, a signing secret, and three filters (workspaces × event kinds × content types, where an empty set means everything). Queued from the outbox, sent by a worker, retried on a fixed ladder, and logged per delivery.
Workspace — a tenant or grouping. Content, media and copilot conversations belong to one. Membership is the M:N link deciding who can reach it.
Two terms that mislead
workspace_content is an access-control mapping — which content types a
workspace has been granted — and not content storage. Content lives in the
generated content_<name> tables.
MCP points in two directions and they are different features. Apograph is an MCP server: an external agent connects to it. The copilot being an MCP client of your systems is a separate, planned thing that does not exist.