Docs / Specification
A-authority — Authority and enforcement decisions
Status: accepted
redaction-no-copy — Redacted material leaves no derived copy
Cited bystore.encrypt.redacted-indexstore.encrypt.redacted-indexAn index declared over a column redacted at write time raises StoreIndexOverRedactedColumn at manifest validation.run.emit.unredacted-errorrun.emit.unredacted-errorA non-null last_error write that has not passed address redaction raises DeriveUnredactedError.connector.attach.url-scrubbingconnector.attach.url-scrubbingBefore a URL enters an error message, log line or stored column, the host removes query, fragment and userinfo. Scheme, host, port and path remain.connector.attach.credential-in-a-urlconnector.attach.credential-in-a-urlA configured endpoint carrying userinfo raises SecretCredentialInUrl at validation, naming the source.
Redaction holds only when no derived artifact carries the pre-redaction value.
| Option | Lost on | Cost |
|---|
| Prepare before recording or refuse the copy path (chosen) | — | A redacted column is reachable only by full scan. |
| Encrypt the index or journal and permit it | At-rest completeness | The guarantee rests on key custody for content redaction exists to remove. |
| Build locally, strip at the sync edge | Failure points | The local tree is itself a copy target. |
| Redact in each adapter, or at read time | Uniformity | The guarantee is as strong as the least careful adapter. |
Revisit: an index structure provably independent of the indexed values.
body-projection — A closed body projection records canonical opaque groups
Cited byrun.journal.body-projectionrun.journal.body-projectionA registered body's closed effect labels, declared roots, types, transforms and normalization bind its owner before input or effect execution; a caller-supplied projection differing from that registration refuses.run.own.body-parentrun.own.body-parentPrepared body outputs require the unchanged parent execution and current in-flight, unstopped attempt at admission, staging and commit; a stopped parent reaches abandoned-work independently of the output table's stop policy.run.guard-secrets.recorded-bodyrun.guard-secrets.recorded-bodyRegistered body results pass through the same guard before shaping and canonical preparation; the engine reports per-column counts once per fresh paid preparation, excluding counts from the recorded wire and replay.authority.redact.prepared-effectsauthority.redact.prepared-effectsCanonical effect preparation produces opaque rewritten root and child groups; the paid record and staged group carry the same rewritten values and rewritten-identities.authority.redact.effect-scopeauthority.redact.effect-scopeA prepared effect binds canonical authority to its execution, row and effect entry key and composite projection identity; replay and staging require the independently issued scope, never authority inferred from decoded bytes.
Removal protects designated row values, not arbitrary schema labels.
| Option | Lost on | Cost |
|---|
| Closed projection and canonical opaque groups (chosen) | — | Authority changes refuse pending owners. |
| Record raw results, then rewrite outputs | At-rest completeness | The paid journal retains values removed from landed rows. |
| Accept caller-labelled prepared bytes | Authority | A caller claims preparation without canonical admission. |
| Rewrite recorded values on replay | Idempotence | A keyed digest becomes a digest of its own output. |
prepared-record — A prepared source record binds canonical authority before execution
Cited byrun.journal.redacting-sourcerun.journal.redacting-sourceA journaled source declaring removal without canonical prepared-recording admission raises JournalRedactionConflict before its first pull; a boolean removal assertion supplies no admission.run.journal.prepared-ownerrun.journal.prepared-ownerProtected recording binds the plan, shape, canonical declarations, normalization and pepper identities into owner pins before source execution; a changed identity follows pinned-plan-changed.run.journal.prepared-replayrun.journal.prepared-replayA protected journal hit admits the recorded rewritten payload against its canonical writer without repeating shaping, normalization or removal and without fetching the source again.run.select.journaled-pullrun.select.journaled-pullA derive pipeline configured to journal its pulls raises DeriveJournaledPull.authority.redact.write-timeauthority.redact.write-timeRedaction runs inside the writer before columnar encoding. Each rule drops its value or transforms it into a policy-defined substitute: keyed digest, token, prefix or generalized band.authority.redact.before-the-recordauthority.redact.before-the-recordA canonical source writer shapes, normalizes and removes values before recording an opaque admitted payload; neither its inline record nor its blob contains the removed source value.authority.redact.every-land-entryauthority.redact.every-land-entryA canonical project declaration binds direct and staged writers even when their callers omit its rules.authority.redact.relational-journalauthority.redact.relational-journalA protected relational source records its concrete rewritten root and child group, preserving declared root types, child lineage and rewritten-identities through prepared-replay.
The recorded wire differs from the source wire, and replay re-admits it without repeating transforms, so keyed hashes and source resumption stay stable.
| Option | Lost on | Cost |
|---|
| Canonical preparation and authority-bound replay (chosen) | — | Unrelated manifest edits also refuse a pending owner. |
| Repeat removal on replay | Idempotence | Keyed hashes change when applied to their own output. |
| Accept a source-supplied prepared flag | Authority | A connector labels raw rows as already protected. |
| Record raw rows, then rewrite parts | At-rest completeness | The journal retains the value its parts remove. |
span-union — Span iteration rewrites the union of all matches
Cited byauthority.redact.in-valueauthority.redact.in-valuePattern removal rewrites the union of all matches in one linear pass, merging overlapping matches into one span; whole-value removal rewrites one cell. JSON paths select object keys, array indices or every array item; unselected values remain unchanged.authority.redact.rewritten-identitiesauthority.redact.rewritten-identitiesRelational parent and child identities derive from rewritten source values; removed values contribute no retained identity digest.
One forward pass over a bounded Thompson NFA keeps the leftmost start per state, so work stays linear in the value’s length and no matched byte remains beside its substitute.
| Option | Lost on | Cost |
|---|
| Union of all matches in one pass (chosen) | — | Per-byte work grows with NFA states. |
| Earliest-ending search | Completeness | password=\S+ rewrites password=h and stores the rest of the secret. |
| Leftmost-first iterator search | Bounding | Repeated suffix searches have quadratic worst-case work. |
| Infer lineage from child names | Authority | A matching name establishes no source-column relationship. |
row-classes — Per-row classes resolve through registered masks
Cited byauthority.mask.row-classauthority.mask.row-classA row-class RawColumnPolicy declares class = { from = ... }, a strategies map naming registered classes, and fallback = "drop"; each row's sibling text selects its strategy, independently of other rows.authority.mask.row-class-dependencyauthority.mask.row-class-dependencyA row-class selector names another Utf8 column in the same table; absent-column checks its presence, and every mapped strategy retains typed-strategy and digest-alone.
Every branch compiles through the static policy’s mask checks, so a per-row class adds no weaker path.
| Option | Lost on | Cost |
|---|
| Registered strategy map with strict drop fallback (chosen) | — | Unknown classes lose their text. |
| One table per class | Utility | One heterogeneous value list becomes several reads. |
| Caller-chosen masks | Uniformity | One adapter omission exposes the original value. |
| Unknown classes left unmasked | Failure direction | A source-side typo grants weaker protection. |
acting-principal — The acting principal is provider-verified, normalized once, fixed per chain
Cited byauthority.identify.subject-tupleauthority.identify.subject-tupleA subject is a tuple of agent, host, on_behalf_of principal, task scope, inference zone and incognito flag. A credential binds the subset it names and admits under that combination alone.authority.identify.attestationauthority.identify.attestationEach member carries an attestation, verified or asserted. Agent, host, task and zone are asserted and render labeled as such; no surface presents an asserted member as identity.authority.identify.on-behalf-ofauthority.identify.on-behalf-ofon_behalf_of is verified at the mint against the issuing identity provider, and admission carries it forward as the reader's identity.authority.identify.value-hygieneauthority.identify.value-hygieneThe mint checks every subject value: non-empty, at most 256 B, no control character, no leading or trailing whitespace.authority.identify.malformed-valueauthority.identify.malformed-valueA value failing value-hygiene raises AuthoritySubjectMalformed, except that the command-line mint trims a padded value where the automated exchange refuses it.authority.identify.normalizationauthority.identify.normalizationThe verified tuple is normalized once, each value trimmed and each blank member dropped, before any consumer reads it. No point of use re-normalizes a value or interprets a scheme prefix.authority.identify.identity-linkauthority.identify.identity-linkAn identity link maps a source principal onto a subject over fields the identity provider verified, recording method and confidence. Confidence relaxes no check.authority.identify.unverified-linkauthority.identify.unverified-linkOnly scim_email and oidc_sub links authorize. An authorization join consuming an operator_asserted LinkMethod raises AuthorityLinkUnverified.authority.identify.directory-linkauthority.identify.directory-linkDirectory provisioning from the identity provider writes source-account links. A value a source's profile interface returns at request time is data, not a link.authority.identify.agent-ceilingauthority.identify.agent-ceilingA sub-agent's reachable set equals or narrows its parent's; no agent reads beyond the principal it acts for.authority.identify.incognitoauthority.identify.incognitoAdmission carries the caller's incognito flag unchanged, and a derivation turns it on and never off.authority.identify.subject-reboundauthority.identify.subject-reboundA derivation naming an on_behalf_of different from its parent's raises AuthoritySubjectRebound.authority.issue.principal-requiredauthority.issue.principal-requiredA mint granting write, execute or forget whose subject names no on_behalf_of raises IssuancePrincipalRequired.authority.issue.default-readauthority.issue.default-readA mint's default action set is read alone.
Only an identity provider makes a principal. A false identity match is a silent source-wide disclosure, so confidence relaxes no check.
| Option | Lost on | Cost |
|---|
| Verify at the provider, normalize at the mint, fix per chain (chosen) | — | Unprovisioned accounts read nothing. |
| Normalize at each point of use | Consistency | One padded identity behaves as two principals. |
| Authorize heuristic or operator-asserted links | Failure asymmetry | A false match discloses a whole source silently. |
| Rebinding within a parent-carried set | Offline forgery | The parent’s mint chooses whom every descendant impersonates. |
Revisit: a directory’s identifiers exceed 256 B; provisioning latency dominates why subjects read nothing.
delegation-profile — Delegation is a versioned profile over an attenuable-credential library
Cited byauthority.profile.delegation-profileauthority.profile.delegation-profileDelegated authority travels in one attenuable, chain-signed library format. The library owns serialization, signatures, block chaining and evaluation; a versioned profile names every fact, check and restriction the engine admits.authority.profile.owner-claimauthority.profile.owner-claimProfile 2 permits a signed owner store identity only in the root authority block; profile 1 and attenuation blocks reject it, and activation requires an unrestricted read grant over the selected store.authority.profile.reserved-factauthority.profile.reserved-factCurrent time, audience, resolved resources and authenticated request identity are reserved facts the engine supplies. A token block introducing one raises ProfileReservedFact.authority.profile.evaluator-boundauthority.profile.evaluator-boundThe evaluator runs with no third-party block, external function, recursion or regular-expression predicate. Input past fact-ceiling or iteration-ceiling raises ProfileEvaluationBudget.authority.profile.fact-ceilingauthority.profile.fact-ceilingOne authorization holds at most 1000 entries in its fact set.authority.profile.iteration-ceilingauthority.profile.iteration-ceilingOne authorization runs at most 100 iterations of the evaluator.authority.profile.appended-blockauthority.profile.appended-blockA block after the first contributes no authority fact to an allow decision; appending narrows a credential or adds nothing.authority.profile.declared-scopeauthority.profile.declared-scopeIntrospection reports the scope a credential declares without evaluating it. Table policy, source access lists, time bounds and revocation settle effective authority afterwards.authority.profile.scoped-sessionauthority.profile.scoped-sessionAuthorization yields a scoped session carrying every restriction the credential expressed. A statement over two tables needs both accesses in one coherent grant; actions and tables never flatten into independent allowlists.authority.attenuate.truncationauthority.attenuate.truncationThe chain-final proof advances an ephemeral key per block; a chain truncated to a broader prefix verifies as nothing.
The library is Biscuit; the engine owns only the profile. No wall-clock timeout enters admission, so slow hardware refuses nothing fast hardware admits.
| Option | Lost on | Cost |
|---|
| Library format, owned profile, evaluation ceilings (chosen) | — | The wire format tracks an upstream project. |
| A custom envelope beside the library token | Chain depth | Grandchildren are inexpressible; two formats need review. |
| A hand-rolled N-block format | Review cost | Its failure mode is silent forgery reviewed by nobody outside the project. |
| The library’s full language, unprofiled | Bounding | Evaluation cost and reachable facts are holder-controlled. |
Revisit: chain verification cost becomes measurable at real delegation depths.
offline-narrowing — Grants narrow offline, and admission re-checks the whole chain
Cited byauthority.grant.fieldsauthority.grant.fieldsA grant names actions, table patterns, and optionally a tenant scope, aggregate constraints, a template allowlist and a row ceiling. An absent constraint leaves its dimension unconstrained; an absent allowlist confers no template.authority.grant.actionsauthority.grant.actionsA grant's actions are Action: read for every row-returning surface, write to land rows, execute to fire a run, admin to mint, forget to erase subject data, and read-individual for per-individual-row.authority.grant.pattern-formsauthority.grant.pattern-formsA table pattern is , covering every table; a prefix ending in , covering every name beginning with that prefix; or any other string, matched exactly. A concrete pattern never covers .authority.grant.malformed-patternauthority.grant.malformed-patternA pattern with anywhere but its final position raises GrantPatternMalformed.authority.grant.starauthority.grant.staris an ordinary grant, bounded by the credential's actions, audience and expiry and visible in the audit record.authority.grant.tenant-scopeauthority.grant.tenant-scopeA tenant scope pairs a table with an opaque byte string bound to that table's outermost partition column.authority.grant.tenant-bytesauthority.grant.tenant-bytesThe grant's tenant value, the partition key on disk and the consumer's tenant identifier are identical bytes, compared by bound-parameter equality with no trimming, case folding, collation or Unicode normalization.authority.grant.tenant-unbindableauthority.grant.tenant-unbindableA tenant-scoped grant on a table declaring no bare outermost partition column raises GrantTenantUnbindable at admission.authority.grant.tenant-child-lifetimeauthority.grant.tenant-child-lifetimeA tenant-scoped child credential is derived per query with a lifetime of 15 min.authority.grant.aggregateauthority.grant.aggregateAn aggregate grant carries a minimum group size, a maximum single-contributor share, permitted functions, a groups-per-query ceiling and a row ceiling. A write-only or aggregate-only grant contributes no table to a raw read.authority.attenuate.offlineauthority.attenuate.offlineA holder derives a narrower child with no issuer round trip by appending a signed block. The parent's bytes stay unchanged, independently verifiable and independently withdrawable.authority.attenuate.narrowingauthority.attenuate.narrowingEvery dimension of a child obeys the narrowing table in Shapes, checked by the deriving holder and again across the whole chain at admission.authority.attenuate.widensauthority.attenuate.widensA child broader than its parent on actions, tables, templates, aggregate constraints, or a max_rows, max_duration_ms or max_response_bytes ceiling raises AttenuationWidens, naming the dimension.authority.attenuate.expiry-extendedauthority.attenuate.expiry-extendedA child whose expiry falls past its parent's raises AttenuationExpiryExtended.authority.attenuate.tenant-droppedauthority.attenuate.tenant-droppedA child dropping its parent's tenant scope or naming another tenant raises AttenuationTenantDropped. Adding a scope to an unscoped parent narrows.authority.attenuate.bearerauthority.attenuate.bearerDerivation proves the chain and not the new holder's identity. A hop authenticating its new actor runs through the exchange.authority.attenuate.per-sub-agentauthority.attenuate.per-sub-agentAn agent derives one child per sub-agent, each bound by its confirmation claim to that sub-agent's own key pair.authority.revoke.denylistauthority.revoke.denylistA checkpoint reads a denylist keyed on credential identifier. An entry ages out once its identifier verifies under no live key version.authority.revoke.revocation-idauthority.revoke.revocation-idEvery derivation carries its own revocation identifier, withdrawing one subtree without ending the root it descends from.authority.revoke.revokedauthority.revoke.revokedA credential on the denylist, or carrying an epoch below the current scoped epoch, raises AuthorityRevoked at the next effect boundary.
Three pattern forms keep containment decidable offline.
| Option | Lost on | Cost |
|---|
| Three-form patterns, double check, per-derivation revocation id (chosen) | — | Admission compares the whole chain per request. |
| Full glob or regular-expression patterns | Containment decidability | Derivation cannot decide offline whether a child lies within its parent. |
| Check at derivation alone, or the last block alone | Trust | A widened intermediate block passes unexamined. |
| One revocation id per root | Blast radius | Stopping one sub-agent stops every sibling. |
Revisit: chain comparison becomes measurable against request latency; a grant dimension carries a tenant set.
query-templates — Query templates are deny-by-default capabilities
Cited byauthority.grant.template-allowlistauthority.grant.template-allowlistA template allowlist denies by default: absent authorizes none, authorizes every template the manifest declares, and a child names only identifiers its parent named or covered.authority.grant.template-tablesauthority.grant.template-tablesA covered template reads the tables its statement names inside that template's session, under every other layer; its coverage adds no table to a raw read.authority.grant.template-not-allowedauthority.grant.template-not-allowedInvoking a template outside the allowlist raises GrantTemplateNotAllowed, and an uncovered template is absent from the projected tool listing.authority.grant.row-ceilingauthority.grant.row-ceilingA read's row ceiling is the least of the grant's, the request's, the template's, each touched table's published ceiling and face-ceiling; an undeclared component imposes none, and the face ceiling is always declared.authority.grant.group-ceilingauthority.grant.group-ceilingAn aggregate grant's groups-per-query ceiling is at least 1 entries; a query producing more groups than the ceiling is cut at it.authority.redact.after-normalizationauthority.redact.after-normalizationRedaction runs after relational normalization; a rule naming a parent column reaches values shredded into child tables.disclosure.template.single-statementdisclosure.template.single-statementA declaration holding more than one statement raises DisclosureTemplateMultiStatement.
A template runs exactly the reviewed statement, so identifier confinement is the sole protection on that surface.
| Option | Lost on | Cost |
|---|
| Deny-by-default allowlist, strict binding (chosen) | — | A parameter rename breaks callers with no window. |
| Restriction polarity like other dimensions | Blast radius | Long-lived credentials silently gain every later template. |
| Hidden from the listing, invocable by name | Enumeration | A guessed identifier reaches the read. |
| Templates through the statement guard | Expressiveness | The guard refuses exactly the reads templates exist for. |
Revisit: operators routinely grant star; a needed store feature requires a non-plain identifier.
issuance-ceiling — One persisted issuance ceiling bounds every lifetime
Cited byauthority.issue.ceilingauthority.issue.ceilingA project persists in version control an issuance policy naming the default audience and the longest lifetime any mint produces, at most 24 h.authority.issue.above-ceilingauthority.issue.above-ceilingAn explicitly requested lifetime above the persisted ceiling raises IssuanceLifetimeAboveCeiling; an exchange policy's lifetime clamps down to the ceiling instead.authority.issue.ceiling-loweringauthority.issue.ceiling-loweringLowering the ceiling records the previous value and its instant; rotation-grace validation uses the recorded value until the last credential minted under it lapses.authority.issue.out-of-tree-mintauthority.issue.out-of-tree-mintCeiling enforcement binds a mint run inside the project tree; a mint run outside it is bounded at the checkpoint by rotation-grace validation.authority.issue.bearer-cap-fixedauthority.issue.bearer-cap-fixedNo issuance policy, face or command setting raises the cap bearer-lifetime sets; a credential living longer admits over a network only bound to a holder key.authority.revoke.short-lifetimeauthority.revoke.short-lifetimeA short lifetime is the primary withdrawal: a credential's remaining lifetime bounds its exposure after a provider sign-out or before a denylist entry propagates.authority.revoke.epochauthority.revoke.epochA revocation epoch scoped on project, tenant and principal class invalidates that slice of outstanding authority.authority.revoke.compromiseauthority.revoke.compromiseSuspected compromise of signing material runs a project-wide epoch bump together with immediate retirement of the key version. Waiting out a grace window withdraws nothing.authority.revoke.rotation-graceauthority.revoke.rotation-graceA rotation policy declares a cadence and a grace window, validated against the persisted issuance policy, during which the retiring key version still verifies.authority.revoke.short-graceauthority.revoke.short-graceA declared or overridden grace window shorter than the effective issuance ceiling raises RotationGraceTooShort.authority.revoke.immediate-retireauthority.revoke.immediate-retireImmediate retirement removes a key version from the published set and every static pin; a checkpoint drops it at its next refresh.authority.revoke.format-withdrawnauthority.revoke.format-withdrawnFrom a declared cutover instant, every admission path raises CredentialFormatWithdrawn for a credential in a withdrawn format. Only an explicit declaration restores acceptance.authority.exchange.policyauthority.exchange.policyAn exchange policy declares RawPolicy; only expected_iss is required.authority.exchange.minted-grantsauthority.exchange.minted-grantsMinted grants come from role_grants and default_grants alone. A verified role matching no entry earns default_grants, which is empty unless declared.authority.exchange.lifetime-defaultauthority.exchange.lifetime-defaultA minted credential lives 900 s where the policy declares no ttl_secs.authority.exchange.lifetime-ceilingauthority.exchange.lifetime-ceilingA configured ttl_secs clamps down to 3600 s and never extends.
One number, versioned with the project, sets the longest lifetime any mint path produces, and every other window derives from it. Format withdrawal is therefore never immediate.
| Option | Lost on | Cost |
|---|
| One persisted ceiling; refuse explicit excess, clamp configured excess (chosen) | — | A ceiling change is a commit and deploy. |
| Per-mint flag or environment variable | Uniformity | The ceiling differs per host, invisible in review. |
| A policy service consulted at mint | Offline minting | Issuance inherits a network availability requirement. |
| Refuse a configured lifetime above the ceiling | Availability | A stale policy value becomes a total sign-in outage. |
Revisit: a verified need for lifetimes above 24 h; operators surprised by clamped exchange sessions.
pinned-keys — Verification trusts only pinned or injected keys
Cited byauthority.issue.signing-portauthority.issue.signing-portOne signing port signs every credential's authority block and every audit root and tip; no mint path reads a private key. Seed files, secret references resolved at mint time and remote signing oracles are its adapters.authority.issue.oracle-custodyauthority.issue.oracle-custodyUnder the oracle adapter the seed stays inside the custodian, which records each mint as a signing call.authority.issue.algorithmauthority.issue.algorithmA credential names Ed25519, the default, or ECDSA over P-256; the pinned key's scheme is authoritative.authority.issue.algorithm-mismatchauthority.issue.algorithm-mismatchA credential naming a scheme other than its pinned key's raises SignatureAlgorithmMismatch.authority.issue.key-rotationauthority.issue.key-rotationThe issuer signing key rotates every 90 d, and at once on suspected compromise.authority.verify.public-key-onlyauthority.verify.public-key-onlyA checkpoint holds public key material and no signing secret, and admits with no call to an issuer, identity provider or policy service.authority.verify.key-setauthority.verify.key-setA checkpoint accepts a set of issuer keys: comma-separated static pins, or a project-published unauthenticated key route returning the current and non-retired versions, opted into per key.authority.verify.key-set-refreshauthority.verify.key-set-refreshA published key set refreshes every 300 s, single-flight, plus one refresh on a signature failure, with failure-forced refreshes throttled.authority.verify.key-set-unavailableauthority.verify.key-set-unavailableA checkpoint opted into a published key set that obtains none, or holding a malformed pin, raises KeySetUnavailable: the engine declines to start and a gateway answers 503.authority.verify.key-set-staleauthority.verify.key-set-staleAfter a failed fetch the last-known-good set serves while its age since the last successful fetch stays under 1 h; past that the checkpoint raises KeySetStale.authority.exchange.injected-materialauthority.exchange.injected-materialVerifying material is operator-injected: a shared secret, an RS256 public key in PEM form, or a key-set document selected by the assertion's kid. The exchange makes no network call.
The deployment, never the credential, chooses the verifying key, and an absent answer about keys refuses. Retiring a key is an action, not an omission.
| Option | Lost on | Cost |
|---|
| Deployment-chosen keys (chosen) | — | Key-route availability is admission availability. |
| Dispatch on the credential’s algorithm claim | Downgrade | Every weaker supported routine is reachable by asking. |
| Fall back to static pins or last-known-good | Frozen keys | A retired key verifies while the route is down. |
| Provider discovery inside the exchange | Reproducibility | Verification depends on a remote document at that instant. |
Revisit: the port cannot express a needed adapter capability such as batch signing.
one-credential — A face admits one verified credential and carries authority as a value
Cited byauthority.issue.absent-authorauthority.issue.absent-authorAn absent authorship value on a landed row means no credential authorized the write: the uncredentialed owner or a timer-fired run.authority.issue.authoring-postureauthority.issue.authoring-postureEvery table write verb write-verbs runs under its manifest's authoring posture. session authors every write by one verified ambient credential's principal; per_request holds no ambient principal, leaving an unaccompanied write unauthored.authority.issue.posture-keyauthority.issue.posture-keyA manifest declares its authoring posture as a top-level authoring_posture of session or per_request. A table write verb reading a manifest whose key is absent or names another value raises AuthoringPostureUndeclared before its first effect.authority.issue.session-credentialauthority.issue.session-credentialUnder session, a table write verb run with no credential raises AuthoringCredentialMissing before its first effect.authority.issue.one-credentialauthority.issue.one-credentialA served face admits a verified capability credential, presented as a bearer or bound to a holder key, and nothing else: no static bearer, no gateway shared secret, no unauthenticated owner path.authority.verify.admitted-authorityauthority.verify.admitted-authorityVerification yields an admitted-authority value carrying the normalized subject tuple and its grants. Every read surface and row-landing effect takes that value as an argument; nothing downstream re-parses a credential or reads ambient state.authority.verify.no-bypass-constructorauthority.verify.no-bypass-constructorThe admitted-authority type has no constructor that produces a value without a verification.authority.verify.effect-boundaryauthority.verify.effect-boundaryA statement's start and each commit are effect boundaries. Each boundary re-reads expiry, revocation and policy version against the carried value; a lapse between boundaries stops the effect at the next one.authority.verify.format-interfaceauthority.verify.format-interfaceThe credential format sits behind one interface of issue, attenuate, verify and introspect; no enforcement call site names a credential type.authority.verify.expiredauthority.verify.expiredA credential whose expiry precedes the evaluation instant raises AuthorityExpired at admission and at each later effect boundary.authority.exchange.per-readerauthority.exchange.per-readerAn embedding application holds no project-wide credential; per request it exchanges its signed-in reader's assertion for that reader's short-lived credential and reads as them.authority.exchange.no-cross-readerauthority.exchange.no-cross-readerAn exchanged credential serves only the reader it was minted for.authority.refuse.drifted-scopeauthority.refuse.drifted-scopeA tenant value matching no partition reads empty, like a tenant that wrote nothing; the read path repairs no transformed scope value.
Authority enters through one verification and flows as an explicit value, never ambient state. A wrong authoring posture mis-authors silently, so the posture argument is the one review point.
| Option | Lost on | Cost |
|---|
| One admission path, authority as an argument (chosen) | — | Every embedding application needs an identity provider. |
| An opt-in perimeter secret or owner path | Attribution | A subjectless owner-equivalent path stands beside the credential. |
| Ambient environment or task-local authority | Attribution | Two callers through one daemon both take the process’s principal. |
| One application credential plus application-side filtering | Enforcement boundary | A filter bug is a disclosure, not a failed check. |
Revisit: per-request mint latency dominates reads.
sender-constrained — Credentials are sender-constrained, with a nonce replay window
Cited byauthority.verify.possession-bindingauthority.verify.possession-bindingA confirmation claim holds a client public-key thumbprint. Each request under a credential carrying one bears a proof signed by the matching private key over method, target, body digest, issue instant and nonce; a credential carrying none requires no proof.authority.verify.possession-invalidauthority.verify.possession-invalidA request whose proof does not verify against the confirmation thumbprint raises PossessionProofInvalid.authority.verify.replay-windowauthority.verify.replay-windowA proof issued more than 300 s before the checkpoint clock is refused as possession-invalid; the nonce cache retains each nonce for that window.authority.verify.clock-skewauthority.verify.clock-skewA proof issued more than 30 s after the checkpoint clock is refused as possession-invalid.authority.verify.replayed-nonceauthority.verify.replayed-nonceA proof whose nonce repeats inside the replay window raises PossessionProofReplayed.
Holding a key-bound credential admits nothing without proof of its key. The proof establishes key possession and claims nothing about what the client is.
| Option | Lost on | Cost |
|---|
| Confirmation thumbprint, per-request signature, local nonce window (chosen) | — | Every client signs each request. |
| Mutual TLS instead of a carried proof | Reach across intermediaries | The engine behind the gateway receives an unbound credential. |
| A monotonic counter per client | Concurrency | Parallel honest requests arrive out of order and refuse. |
| A replay store shared across checkpoints | Locality | Admission calls a shared service per request. |
Revisit: cross-checkpoint replay observed within a credential’s lifetime.
network-bearer — A network face admits a short-lived audience-bound bearer, and a key-bound credential only under proof
Cited byauthority.verify.write-verbsauthority.verify.write-verbscontext land, run start and pipeline run are the table write verbs. Each admits its accompanying credential before its first effect and stamps that credential's on_behalf_of as every landed row's _authored_by.authority.verify.write-commitauthority.verify.write-commitA credentialed table write reads its denylist afresh and checks expiry immediately before each commit; a credential revoked or lapsed since admission commits nothing, as revoked and expired.authority.verify.timestampsauthority.verify.timestampsEvery checkpoint decodes timestamps into UTC instants under one grammar and compares instants.authority.verify.malformed-timestampauthority.verify.malformed-timestampA timestamp that does not decode under that grammar raises TimestampMalformed at every checkpoint alike.authority.verify.network-bearerauthority.verify.network-bearerA network checkpoint admits a credential with no confirmation claim as a bearer when it names the checkpoint's declared audience and meets bearer-lifetime; the peer fallback never applies over a network.authority.verify.bearer-lifetimeauthority.verify.bearer-lifetimeA bearer whose expiry falls more than 3600 s after its issue instant raises BearerLifetimeExceeded at a network checkpoint and admits nothing; its holder refreshes through surface.authority.verify.connection-scopedauthority.verify.connection-scopedA local admission binds to the pipe or socket connection that presented the credential; a request on any other connection is refused as peer-mismatch until that connection presents the credential and admits itself.
MCP clients speaking Streamable HTTP send Authorization: Bearer and sign nothing, so a key-only network face serves none of them. Compatibility decided it over theft yield.
| Option | Lost on | Cost |
|---|
| Short-lived audience-bound bearer; proof when a confirmation claim is present (chosen) | — | A captured bearer replays against its audience until expiry. |
| A proof on every network request | MCP-client compatibility | A client holding no signing key reaches no network face. |
| A bearer at any lifetime under the issuance ceiling | Theft yield | A captured bearer replays for up to 24 h. |
Revisit: mainstream MCP clients sign per-request proofs; bearer replay is observed within a lifetime.
exchange-renewal — The exchange renews a credential, binding it to a proven holder key
Cited byauthority.exchange.surfaceauthority.exchange.surfacecontextful token exchange and POST /auth/exchange trade a verified external assertion for a capability credential, configured per project by .contextful/exchange/policy.toml and .contextful/exchange/verify.key. The command reads the assertion from --jwt or standard input, and a holder proof from --dpop.authority.exchange.tenantauthority.exchange.tenantThe assertion claim tenant_claim names becomes the tenant scope of every minted grant; no subject member carries tenancy.authority.exchange.audienceauthority.exchange.audienceA minted credential carries minted_aud, falling back to the project's persisted default audience.authority.exchange.material-missingauthority.exchange.material-missingAn exchange configured with no verifying material raises ExchangeMaterialMissing and mints nothing.authority.exchange.holder-bindingauthority.exchange.holder-bindingAn exchange request carrying a DPoP proof over POST /auth/exchange and its body mints a credential whose cnf.jkt is the proof key's thumbprint, the proof checked as possession-binding.authority.exchange.bearer-mintauthority.exchange.bearer-mintAn exchange request carrying no proof mints a credential with no confirmation claim, its lifetime clamped by lifetime-ceiling, so a network face admits it under bearer-lifetime.authority.exchange.refreshauthority.exchange.refreshA holder renews a served-face credential by exchanging a fresh assertion for a new credential with its own identifier and a full lifetime from the exchange instant.authority.exchange.no-extensionauthority.exchange.no-extensionNo surface extends a minted credential's expiry: a minted credential presented as the exchange assertion raises assertion-invalid, and expiry-extended bounds every derived child.
Theft yield decided the fixed cap. Identity-provider availability therefore bounds a bearer session past one hour.
| Option | Lost on | Cost |
|---|
| Bind on proof, bearer otherwise, fixed cap (chosen) | — | A bearer client re-exchanges hourly with a live assertion. |
| A face setting raising the bearer cap | Theft yield | A captured bearer admits for up to the 24 h ceiling. |
| A refresh token beside the credential | Surface | A second secret class to store, rotate and revoke. |
| Server-side expiry extension on use | Offline verification | The checkpoint writes state per request. |
Revisit: clients report hourly exchange as a sign-in outage.
exhaustible-digest — A digest over an exhaustible class needs generalizing truncation
Cited byauthority.mask.column-policyauthority.mask.column-policyA column under [pipeline.tables.policy.columns] declares RawColumnPolicy; an undeclared column carries no class.authority.mask.class-registryauthority.mask.class-registryclass takes a value from the class registry in Shapes. phi marks protected health data; ssn, phone, email and mrn are exhaustible, each carrying a registered domain size.authority.mask.unknown-classauthority.mask.unknown-classA class outside the registry raises EnforceUnknownClass at manifest check.authority.mask.strategiesauthority.mask.strategiesThe strategies are drop, hash (keyed), tokenize (format-preserving), truncate, bucket and range.authority.mask.dropauthority.mask.dropdrop nulls the cell, or yields an empty string for a string column.authority.mask.one-valueauthority.mask.one-valueA column mask is one value whose primary and combine halves are private; it drives both the write-time and query-time layers, and no consumer applies the primary alone.authority.mask.digest-aloneauthority.mask.digest-alonehash or tokenize standing alone over an exhaustible class raises EnforceDigestAloneOnExhaustibleClass.authority.mask.high-entropyauthority.mask.high-entropyA column of random identifiers or opaque tokens carries hash with no combine.authority.mask.combine-generalizesauthority.mask.combine-generalizesA bucket or range combine behind hash or tokenize raises EnforceCombineWithoutGeneralization; truncate is the one combine that generalizes a digest.authority.mask.in-placeauthority.mask.in-placeThe masked projection substitutes named columns where they stand; the caller receives the column set and order the unmasked statement produces, and expands to it.authority.mask.equalityauthority.mask.equalityAn equality filter on a drop column matches nothing; on a hash column it matches equal digests.authority.mask.aggregatesauthority.mask.aggregatesAggregation reads the masked column.authority.mask.summarize-onlyauthority.mask.summarize-onlysummarize_only is a flag, not a strategy: the value stays legible to grounding and citation.authority.mask.hash-widthauthority.mask.hash-widthhash emits 32 chars of hexadecimal.authority.mask.token-widthauthority.mask.token-widthtokenize emits 20 chars.authority.mask.cuts-nothingauthority.mask.cuts-nothingA truncate combine at or past its primary's output width raises EnforceTruncationCutsNothing.authority.mask.crowdauthority.mask.crowdA column's crowd, the fewest inputs one masked output covers, is at least 1000 values and defaults to that floor.authority.mask.truncation-ceilingauthority.mask.truncation-ceilingBehind a keyed digest over an exhaustible class, a truncate width above floor(log_b(domain ÷ crowd)), b being 16 for hash and 36 for tokenize, with domain from the class registry, raises EnforceTruncationTooWide.authority.mask.pepperauthority.mask.pepperOne environment variable supplies the key for hash and tokenize, read by both layers as one resolved value.authority.mask.development-pepperauthority.mask.development-pepperLeft unset, the pepper resolves to a constant in the source tree and the process emits one signal per run.authority.mask.pseudonymousauthority.mask.pseudonymoushash output is an HMAC-SHA-256 under the pepper and is pseudonymous; no surface labels a masked value anonymous.authority.mask.native-digestauthority.mask.native-digestBoth layers compute the keyed digest natively; the query layer calls a scalar function holding the pepper in process memory, and a value masked at either layer joins the other.authority.mask.key-materialauthority.mask.key-materialA compiled relation, query plan or session catalog entry carrying pepper-derived key state raises EnforceKeyMaterialInRelation.
Anyone computing a digest over an enumerable value space recovers identities by enumeration, so the digest ships only where exhaustive search returns a crowd. Sufficient narrowness stays unverified.
| Option | Lost on | Cost |
|---|
| Refuse a bare digest; admit it behind truncation (chosen) | — | A join on the column matches a crowd. |
| A bare digest relying on key secrecy | Recovery cost | Enumeration recovers every identity. |
| Refuse hashing for these classes | Utility | Equality filters and joins disappear. |
| A fixed width threshold | Honesty | One threshold fits one domain. |
Revisit: a per-person join over an exhaustible class becomes a requirement.
placement-breadth — Placement breadth is declared data-side, and resolution fails narrow
Cited byauthority.issue.zone-wildcardauthority.issue.zone-wildcardA mint whose subject declares a wildcard inference zone raises IssuanceZoneWildcard.authority.redact.pipeline-wideauthority.redact.pipeline-wideA rule set declared on a pipeline binds every table the pipeline lands, child tables included.authority.place.zone-stringauthority.place.zone-stringA zone string parses, after trimming, as local:device, on-prem:<id>, private-cloud:<id> or public-cloud:<id>; any other text is undeclared. The identifier is part of the value.authority.place.allow-set-entryauthority.place.allow-set-entryAn allow-set entry is , local:device, on-prem:, private-cloud:, public-cloud:, or a category carrying a concrete identifier.authority.place.disjunctiveauthority.place.disjunctiveA zone is admitted when any entry matches. A bare category matches every identifier in it; an entry carrying an identifier matches that identifier alone.authority.place.undeclaredauthority.place.undeclaredOnly admits an undeclared zone.authority.place.caller-zoneauthority.place.caller-zoneThe calling process declares its zone per request; the store carries none.authority.place.fail-closedauthority.place.fail-closedA table declaring no zone policy resolves to the fail-closed pair local:device and on-prem:, declared and discovered tables alike.authority.place.protected-floorauthority.place.protected-floorA phi column or table carries a floor at the fail-closed pair; a wider declared set resolves down to it at serve time unless the override names that class or column.authority.place.floor-widenedauthority.place.floor-widenedA manifest widening a protected-class surface past its floor without an override naming that class raises EnforceProtectedFloorWidened.authority.place.narrowest-grainauthority.place.narrowest-grainA column's set narrows its table's; a principal's set narrows both.authority.place.excluded-rowauthority.place.excluded-rowWhere the table's effective set omits the session's zone, the row leaves the result.authority.place.excluded-cellauthority.place.excluded-cellA cell whose effective set omits the session's zone arrives null, a mask exception notwithstanding.authority.place.per-principalauthority.place.per-principalA [[principal]] allow-set narrows every row whose _authored_agent or _authored_by equals its id, wherever the row lands; a row whose authors no principal lists keeps its table's set.authority.place.evidence-floorauthority.place.evidence-floorA synthesized row declaring a set wider than the intersection of its evidence tables' sets raises EnforceEvidenceFloorExceeded and resolves to that intersection.authority.place.incognitoauthority.place.incognitoIncognito pins the session to the fail-closed pair, the uncredentialed local owner's reads included. contextful mcp --incognito serves a credential signing no zone at local:device and refuses one signing a zone outside [local:device, on-prem:].authority.place.incognito-wideningauthority.place.incognito-wideningA session asserting a zone wider than the incognito pin, or an incognito contextful token mint signing one, raises EnforceIncognitoWidening.authority.place.team-defaultauthority.place.team-default[project.zone] declares default, users_may_widen and incognito_default; contextful token mint naming no --zone signs default, and under incognito_default = true mints incognito.authority.place.serve-outcomeauthority.place.serve-outcomeServing one row yields a drop flag and the list of zone-masked columns.authority.place.envelopeauthority.place.envelopeA response envelope carries the zone's removals, the asserted zone and the incognito flag in restriction-block, and no removed value.authority.place.symbolic-inclusionauthority.place.symbolic-inclusionInclusion against a floor is decided over every constructor and identifier, never by probing sample zones.authority.place.allow-set-entriesauthority.place.allow-set-entriesAn allow-set holds at most 32 entries.authority.place.identifier-lengthauthority.place.identifier-lengthA zone identifier holds at most 128 chars.
Only the data side widens inference placement, every widening shows in the manifest diff, and ambiguity resolves narrowest.
| Option | Lost on | Cost |
|---|
| Data-side breadth, intersection for synthesis (chosen) | — | A multi-zone batch mints per zone. |
| Subject-side wildcard as every zone | Widening side | A credential grants itself every zone. |
| Trust a synthesized row’s declared set | Laundering | The constrained path enforces its own constraint. |
| A vendor client behind a feature flag | Verifiability | The placement claim depends on a build the reader cannot see. |
Revisit: fragment-level provenance through synthesis becomes observable; per-zone minting dominates issuance.
redistribution — Redistribution ships an allowlist and never reaches backwards
Cited byauthority.redact.ruleauthority.redact.ruleA rule names a table, a column, one operation and that operation's argument.authority.bound-redistribution.withholdauthority.bound-redistribution.withholdA cleared redistribution flag withholds every object of the table at push and omits the table's name from the bucket manifest.authority.bound-redistribution.before-diffauthority.bound-redistribution.before-diffThe exclusion applies before the object diff is computed.authority.bound-redistribution.outranks-grantsauthority.bound-redistribution.outranks-grantsThe bound holds against a credential granted everything.authority.bound-redistribution.envelopesauthority.bound-redistribution.envelopesThe bound covers the table's columnar files and each pull's verbatim record.authority.bound-redistribution.root-allowlistauthority.bound-redistribution.root-allowlistWhile any table is withheld, a root-level object ships only when the allowlist in Shapes names it.authority.bound-redistribution.root-not-allowlistedauthority.bound-redistribution.root-not-allowlistedA root-level object absent from the allowlist raises EnforceRootObjectNotAllowlisted at push.authority.bound-redistribution.left-behindauthority.bound-redistribution.left-behindClearing the flag over a table an earlier push uploaded raises EnforceStaleRedistributedObjects, naming each object and the remedy, deleting none.authority.bound-redistribution.manifest-is-an-indexauthority.bound-redistribution.manifest-is-an-indexAn object stays fetchable by its key after the manifest stops naming it, until drop-first deletes it; a manifest authorizes nothing.authority.bound-redistribution.reportauthority.bound-redistribution.reportA left-behind report names at most 100 files and states the total found.authority.bound-redistribution.two-checksauthority.bound-redistribution.two-checksThe left-behind check runs before and after the upload loop; the guarantee holds for one bucket under one pushing configuration.authority.bound-redistribution.edge-filterauthority.bound-redistribution.edge-filterA serving edge in front of the bucket filters a materialized replica by the pulling credential's grants.
Redistribution fails toward not shipping, and a withheld table’s left-behind objects are the operator’s to delete.
| Option | Lost on | Cost |
|---|
| Enumerate what ships; name left-behind objects (chosen) | — | An operator deletes a withheld table’s left-behind objects by hand. |
| Name the objects that stay behind | Failure direction | A new object ships by default carrying withheld rows. |
| Inspect each root object at push | Soundness | Record-blob contents are not statically decidable. |
| Delete left-behind objects automatically | Bucket authority | Deletion is irreversible and can cut a replica from its readers. |
local-transport — Local transports bind possession to the holder key, then to the OS peer
Cited byauthority.verify.local-transportauthority.verify.local-transportA local transport is a stdio pipe the checkpoint inherited from the process that spawned it, or a Unix socket; every other transport is a network transport.authority.verify.local-holder-proofauthority.verify.local-holder-proofOn a local transport, a credential whose confirmation claim holds a thumbprint admits only with a proof as possession-binding; the peer fallback never applies to it, and a missing or failing proof is refused as possession-invalid.authority.verify.local-peer-fallbackauthority.verify.local-peer-fallbackOn a local transport, a credential with no confirmation claim admits only through the operating system's peer authentication: an inherited stdio pipe, or a socket peer whose kernel-reported uid equals the checkpoint process's uid.authority.verify.peer-mismatchauthority.verify.peer-mismatchA socket peer presenting a credential with no confirmation claim, whose kernel-reported uid differs from the checkpoint process's uid or which the platform cannot report, raises TransportPeerMismatch and admits nothing.
MCP hosts spawn a server over stdio or relay to a Unix socket, and many sign nothing. Theft yield decided the order.
| Option | Lost on | Cost |
|---|
| Holder proof first, peer uid otherwise (chosen) | — | Two local admission paths, one per-platform peer call. |
| Peer uid alone | Theft yield | A key-holding client gains nothing from its key. |
| Per-request proof on every transport | Host compatibility | Every local client needs a signing shim. |
| Peer process identity by pid | Portability | A pid is reusable. |
Revisit: stdio hosts sign per request; a portable call names the peer process.
horizon — The horizon is a grant dimension enforced through the existing egress hook
Cited byauthority.grant.horizonauthority.grant.horizonA grant may carry horizon, an instant bounding the availability time and since of every read its holder makes, under inherited-bound and exceeds-horizon; an absent horizon leaves availability unbounded.authority.attenuate.horizon-widensauthority.attenuate.horizon-widensA child whose horizon falls later than its parent's is broader on horizon and refuses as widens, naming that dimension; a child naming no horizon inherits its parent's.
A cutoff the agent passes per call is one it can omit or widen, so the horizon rides the credential. Tools beyond the read face reach the outside through one attachment point, so the horizon feeds the pre-send hook.
| Option | Lost on | Cost |
|---|
| Grant dimension, read face and pre-send hook (chosen) | — | A provider-hosted tool is unavailable under a horizon. |
A per-call available_as_of | Enforcement | The agent omits or widens it. |
| A per-tool horizon list | One home | A new tool slips past it. |
| A prompt instruction naming the cutoff | Enforcement | Models recall facts they are told to ignore. |
Revisit: a provider exposing hosted search through a client-side hook.