Authorization boundaries
Most HTTP and MCP record handlers invoke the policy engine. Lower-level Rust storage repositories do not carry a request principal; an embedding application must authorize their use at its own boundary. REST and MCP space configuration operations requireread:space_config or
write:space_config, as appropriate, plus record authorization. A tenant token
can manage only its own named space. Wildcard operation scopes do not grant
access to another space. Updates that return a configuration also require read
access, and compare the authorized envelope at the storage write.
The Default MCP get_provenance handler authorizes the claim, each assertion,
revision, node and parent document before returning the chain. Missing, deleted,
foreign-space or inaccessible evidence fails the request without returning a
partial chain. Raw document authority is required for excerpts and node text.
REST work-item reads use read:work_item. Retrying a failed item additionally
requires write:work_item and record authorization. The retry compares the
observed state at the atomic write and preserves that check when reactivating
archived work. A concurrent status or security change returns a conflict.
Managed REST data routes enforce the current runtime mode in shared middleware.
In read_only, mutations are rejected even for wildcard and development bypass
principals. Existing searches, batch entity reads and authorized snapshot export
remain available. Runtime capabilities are separate from caller permissions.
The explicit local-development bypass disables record ABAC. Use it only with
isolated development data and loopback access.
Record security envelope
Each record’ssecurity object describes its policy and restrictions:
The strings are exact policy values. Naming a label
public or a caveat
trusted does not create special behavior by itself.
Principal clearance
The corresponding principal needs an operation scope such asread:entity
and a clearance for the record’s policy. This is an illustrative clearance,
not a complete JWT:
- The principal and record have the same
space_id. - The principal has the required operation scope.
- A clearance matches the record’s
policy_id. - The record’s
levelis withinmax_level. - Every record label is present in the clearance’s labels.
- Every handling caveat is present in
handling_allow. - Any subject restriction is satisfied.
- Any purposes required by the configured policy engine are present.
clearances in new tokens. The HTTP adapter retains a legacy
fallback that constructs clearances from flat security fields when the
clearance list is empty. Exact authentication claims are documented in the
API overview.
Subject restrictions
A principal can be restricted to a set of entity IDs withsubject_allowlist. A record also declares subjects and subjects_state:
For a restricted principal, the normal rule requires a complete, non-empty
subject list, with every subject in the allowlist. If a meeting record names
both Mara and Ivo, a principal restricted to Mara alone cannot read it.
The
handling:subjectless_ok caveat permits incomplete or empty subject
metadata when the clearance also allows that caveat. It does not exempt a
known subject from the allowlist.
An omitted or null subject_allowlist means no subject restriction. An
explicit empty array stays restricted to no subjects: it denies access to every
subject-bearing record, including entities, even with wildcard operation scopes.
The handling:subjectless_ok exception described above still applies to records
with no known subjects.
Entity security changes
Ordinary entity updates require read and write access to both the existing and proposed record, and preserve the completesecurity object: policy_id,
level, labels, and handling. Being cleared for both classifications does
not grant permission to reclassify an existing entity. This applies to REST
replacement, upsert, and batch writes and to MCP update_entity and
batch_entities, including restoration of deleted records.
Ordinary replacements also preserve record identity, the subject set and raw
subject completeness. They compare the authorized timestamp, lifecycle and
complete security/subject envelope at the atomic storage write, so a stale
content edit cannot undo a concurrent classification or subject change. A rejected update does not restore a
deleted entity. These ordinary interfaces expose no declassification permission;
trusted internal maintenance remains responsible for intentional security changes.
REST relationship replacement, upsert and batch writes use the same ordinary
security-envelope rule, requiring read/write authority on both versions. The
atomic write also compares the observed endpoints, lifecycle and timestamp.
Rejected replacements cannot revive protected tombstones. Trusted pipeline
writers retain their own contracts.
The REST timeline update, PUT /v1/timeline/{id}, also preserves the existing
security fields. A payload that changes them returns 403, even when the
caller is cleared for both classifications. If stored security changes after
authorization, the write returns 409; fetch the current event before retrying
a content edit.
Raw content and redaction
The policy vocabulary separates document metadata access from raw-text access. Withoutread:doc:raw, REST document projections clear text, sidecar_text
and media_attachments. This applies to get/search and legacy space document
routes, as well as returned mutation records. The existing REST response shape
is preserved. Document chunks require raw access to the parent document and
revision, and authorize each returned node.
MCP document response helpers clear doc.text without raw authority and return
a RedactionEnvelope listing affected fields. These receipts describe that
specific projection. Neither helper is a general scrubber for arbitrary
application-defined metadata; classify the whole record appropriately when
those fields contain sensitive information.
The current source handlers return authorized source records directly. Do not
assume the read:source:raw scope automatically hides source.uri or
source.path on every source API or MCP response. Protect sensitive source
locations through the record envelope and deployment access policy.
Derived answers retain restrictions
Truth slots are partitioned by a fingerprint of the security envelope. Claims in different envelopes are not combined into a shared conflict group. This prevents a restricted claim from silently changing an answer in a less restricted partition, but it also means contradictions across partitions are not detected by truth maintenance. Knowledge-view publication uses exact security-envelope matching. Its projection records retain the union of contributing subjects, including relationship endpoints and evidence. Source projections additionally requireread:doc:raw because they contain immutable document excerpts.
The managed Living Wiki has a separate service grant. Creating or compiling
that service requires explicit manage:wiki and unrestricted subject scope;
a wildcard operation scope alone does not grant it. See the
Living Wiki architecture for publication and
revocation behavior.
Development bypass
SKIP_AUTH=true injects a development principal and bypasses ABAC. The HTTP
server selects its space from X-Space-Id, falling back to default. This
makes loopback examples easy to run, but their successful requests do not
validate your production authorization policy.
For authenticated service startup, configure the supported HS256 JWT secret
and the intended issuer/audience constraints. MCP clients send their bearer
token on each request; a server-side fallback token is not used to authorize
an incoming caller. See deployment.
Next steps
- Spaces explains request scoping and per-space configuration.
- API authentication documents token claims.
- MCP overview explains transport and tool visibility.
