Skip to content

Concepts

Status: design draft for review · decided, not built

This page is the design's vocabulary, explained in reading order. Nothing is declared here: every concept below is decided on an owning page or ADR, and this page links it rather than restating it. Where a sentence here and an owning page disagree, the owning page wins. The fixed term-by-term table that binds every engineering page is ADR-0018 d4; the end of this page maps each concept to where it is decided.

Tenant

A tenant is one organization's isolated space in a deployment. Everything below — workareas, keys, claims, the journal — exists per tenant. Tenant identity is derived server-side from the API key, never taken from the request, and row-level security applies it to every table. No structure in this design crosses a tenant boundary; relating tenants into one "whole world" is an explicitly future federation item, not a latent feature.

Memory as claim

The stored unit is a memory, and a memory asserts a claim — something an agent believes, not something the system certifies. The whole design follows from treating it that way: a new memory is held until an identity that did not write it has reviewed it, and only then does it become visible to anyone else.

Claims come in versions. A claim_key groups the versions of one claim, and the version served to readers is the tip — exactly one per claim per workarea, changed only by a ratified promotion. Replacing the tip is supersession: a new version is submitted, held, and reviewed like any write, and its promotion is checked against the tip it claims to replace, so two racing supersessions cannot both win.

Claims also declare where they came from. A submission may carry derives_from edges naming the claims it was built from; the transitive closure over those edges and claim↔claim connections is the claim's lineage closure. That closure is load-bearing: a reviewer who appears anywhere in it may not judge the claim, and simulation taint travels along it. The honest boundary is stated wherever lineage is used: derivation is declared — a writer who omits derives_from produces a row the service cannot connect to its sources, and lineage exclusion is exactly as good as the declared graph.

The lifecycle of one version, simplified (the normative state machine is in admission):

stateDiagram-v2
    [*] --> held : write — scanned in the same call,<br/>visible only to its author
    held --> rejected : scan veto or rejecting verdict<br/>(journalled, reopenable by a non-author)
    held --> promoted : ratified by a non-author —<br/>now visible to readers in scope
    promoted --> demoted : demote — journalled,<br/>off every read surface, bytes kept
    promoted --> erased : erase — journalled crypto-shred
    demoted --> erased : erase

Demotion and erasure are different acts on purpose: demote removes a claim from every consumer surface and keeps the bytes; erase destroys the per-artifact encryption key so the bytes can never be read again, within a stated, inventoried boundary. Neither is silent — both are journalled, which is the constitution's R4.

Workarea

A workarea is a governed node in a tree — exactly one tree per tenant, rooted at that tenant's universe. The universe root exists to give paths and subtree grants a top: it is permanently committed, cannot be deleted or re-parented, and refuses direct claim writes. Claims live in the workareas beneath it.

A workarea exists to mirror an externally managed AI crew. OML records the crew — name, charter, external manager — but never operates it: it admits or refuses what the crew writes, nothing more. Besides the containment tree, workareas can be joined by related edges (relates_to, continues, derived_from, mirrors) — recorded structure for lineage and navigation that confers zero access, proposed and ratified like other governed changes.

Every workarea sits on a one-way status ladder:

  • development — review runs as everywhere; tenant policy may additionally permit marked self_signed rows, the constitution's one bounded exception — readable only inside that workarea, never promoted beyond it.
  • committed — full non-author review; the working state of a governed crew space.
  • validated (frozen) — no new writes, no promotions into it, no new children; it keeps serving reads, and the only mutations it admits are journalled demote, erasure, and crew-metadata update.

Transitions are forward only and each needs a proposer and a separate ratifier; there is no unfreeze. An area can become validated only when all its children already are, so a frozen node means a frozen subtree.

flowchart TD
    U["universe<br/>(committed, permanent — no direct writes)"]
    A["research-crew<br/>(committed)"]
    B["ops-crew<br/>(development)"]
    C["lit-review<br/>(validated — frozen)"]
    U --> A
    U --> B
    A --> C
    A -. "related edge: mirrors<br/>(zero access)" .-> B
    K["a key's grant names a node id —<br/>it covers that node's subtree,<br/>minus the grant's own deny masks"]
    K -. "grant on research-crew" .-> A

Roles and keys

Every caller holds an API key issued with exactly one of five roles:

  • reader — recall, search, fetch, graph reads; every read is logged.
  • writer — remember and learn (held on arrival), attachments, supersession proposals on its own claims; never a verdict.
  • dreamer — one role, two capability classes: propose (edits-as-proposals, connection proposals) and review (verdicts, ratifications). Which rows it may review is decided at promotion time: a dreamer anywhere in a row's lineage closure is refused.
  • admin — tenant governance: keys, workareas, reassignment, bans, erasure, simulations. Admin verdicts on content are refused — admin is never reviewer, and an admin who needs to write uses an ordinary writer-scoped key and waits on review like everyone else.
  • operator — provider level: creates tenants and issues each tenant's first admin key; never touches content.

Authority over where comes from grants: a grant binds a role (no higher than the key's) to a workarea node id and covers that node's subtree. A deny inside a grant masks a subtree within that grant only; a global per-key deny is a separate journalled object that wins over every grant. Effective access is the union of attenuated grants minus global denies, recomputed whenever a permission epoch bumps — so every access answer is reproducible from journalled records.

Keys are shown once at issuance, expire, and rotate by minting a journalled successor key (linked by rotated_from, with a bounded grace window on the old key) — there is no in-place re-key and no "show me the key again".

Admission

Admission is the pipeline every write crosses before anyone but its author can read it:

capture → quarantine → deterministic scan → non-author review → ratification → journal → release.

A write lands held: journalled, quarantined, scanned by deterministic rules in the same call (the scan can veto, never promote), and invisible to everyone but its author. It becomes visible exactly once, when a reviewer who is not the author — and not anywhere in the claim's lineage closure — records a verdict and the workarea's review policy is satisfied. The ratification event carries a snapshot of that policy, so any later audit reads the promotion against the rules that actually governed it.

Review capacity is external: the provider runs no model, and verdicts come from crews holding dreamer keys (humans through the CLI as the exception path). A verdict counts only against a valid serve — the server put that exact item, with all its attachments, in front of that reviewer under an expiring binding.

When review is unavailable, the pipeline fails closed: nothing promotes, held items wait and eventually dead-letter (journalled, never dropped), and no timeout relaxes the policy. The cost is availability under review starvation; the alternative — failing open — would convert a capacity problem into a trust problem.

Attachments

A claim can carry files — images, PDFs, arbitrary binaries. Attachments are content-addressed: named by the digest of their bytes, so they cannot be swapped after submission, and bound into the claim's envelope by those digests. They are stored encrypted under per-artifact keys, upload through the same quarantine regime as bodies, and a reviewer is served every attachment before a verdict counts. Where a file's text can be extracted deterministically, that text is scanned too; where it cannot, what was reviewed is honestly the file's origin, fingerprint and scan result.

Simulations

A simulation is a fenced provenance channel: the one door through which counterfactual memories may be injected to test a crew. Every simulation write carries an indelible provenance: simulation marker and its simulation_id, passes the full admission pipeline, and is served only to the simulation's audience — a journalled, closed set of keys. Only dreamers in the audience may review its writes; an audience with no dreamer promotes nothing.

Anything whose lineage closure touches a simulation row is tainted: it inherits the simulation id, can never enter a validated workarea, and is demoted or re-reviewed when the simulation ends. Taint never captures the default tip: for keys outside the audience, tip resolution ignores tainted versions entirely, so a promoted tainted supersession is only an audience-scoped overlay tip and the claim everyone else sees is bit-for-bit indifferent to the simulation's existence. Ending a simulation is a journalled act that demotes its rows and its tainted closure; exports list a simulation's content separately, forever.

The journal and evidence

Every state change is a journal event: signed by the deployment key, hash-chained per tenant, append-only, in PostgreSQL — the system of record. Payloads are digest-only: body plaintext never enters the journal, signatures cover digests and ciphertext references, which is why chain verification still succeeds after an erasure — the decisions survive, the content does not. Attribution (principal, key id, timestamp) rides every event in the clear.

The evidence export (oml audit export) folds the journal into a signed bundle: the per-memory decision trail, chain verification, grants history, the retention-scoped read log, reciprocal-approval statistics, and simulations listed separately. The sanctioned claim for all of it, everywhere in this documentation: the system produces the evidence an auditor asks for — never "compliant", never "audit-ready".

The lake

The Delta lake is derived, never serving: a lakehouse of lake-zone tables (bronze, silver, gold name lake zones and nothing else) fed exactly-once from the journal's outbox by a single keyless writer. It exists for reconciliation, lineage, analytics and future exports; no client read is ever answered from it, bodies in it are ciphertext, and when journal and lake disagree, the journal wins and the lake is repaired. Held bodies never reach it at all.

Where each concept is decided

Concept Owning page Decision record
Tenant and isolation architecture/security.md ADR-0007
The constitution (R1–R4, the development exception) architecture/overview.md §5 ADR-0001
Claim versions, the tip, lineage closure architecture/audit-and-lineage.md ADR-0005 (erasure), ADR-0002 (the record)
Workarea tree, grants, denies, edges architecture/workareas.md ADR-0008
The status ladder architecture/workareas.md ADR-0009
Roles, the dreamer split, key lifecycle architecture/roles-and-keys.md ADR-0010
The admission pipeline and review policies architecture/admission.md ADR-0012
Attachments architecture/storage.md ADR-0004
Simulations and taint architecture/simulations.md ADR-0011
The journal and the commit point architecture/storage.md ADR-0002
The evidence export and erasure architecture/audit-and-lineage.md ADR-0005
The lake and the outbox architecture/storage.md, data/delta-tables.md ADR-0003
Reads and the read log architecture/retrieval.md ADR-0013
The module shape and plugin points architecture/overview.md §3 ADR-0019
The vocabulary itself — ADR-0018 d4