Seven Layer
Authority Fabric

Decisions and refusals

Every outcome is a signed envelope with a stable code — and "we could not tell" is a third state that must never be reported as a denial.

The unit of output is a decision envelope. It is canonical CBOR, it is signed, and it is the same shape whether the operation completed or was refused.

Three terminal states, not two

This is the single most important distinction on the page, because collapsing it is how a system quietly lies to its operators.

TerminalityMeaningWhat a relying party may conclude
CompletedThe operation was authorized and its effect occurred.The effect happened.
RefusedThe rules were evaluated and the answer was no.The effect did not happen, and here is the reason.
IndeterminateTerminal knowledge was lost — a seat timed out, a network partition, a crash between commit and acknowledgement.Nothing. Neither that it happened nor that it did not.

Indeterminate must never be reported as a refusal. A refusal says we decided against this; an indeterminate outcome says we do not know what happened. Treating the second as the first invites a caller to retry an operation that may already have taken effect.

The type system enforces it: no refusal code is reachable from lost terminal knowledge. There is no path from "the seat did not answer" to a signed statement that policy denied the request.

Commit precedes release

An envelope reporting Completed without a transparency log inclusion proof is malformed — not merely suspicious. DecisionEnvelope::is_well_formed() says so, and the refusal code RELEASE_BEFORE_COMMIT (603) exists for the case where an executor tries it anyway.

The ordering matters because a log you can append to after releasing the secret is not evidence of anything. Commit first, then release.

Refusal codes

Codes are stable and grouped by the layer that decided. A code may be deprecated but never reused — an archived envelope must still mean in ten years what it meant when it was signed.

Protocol (1xx)

CodeNameMeaning
100MALFORMED_REQUESTInput was not canonical CBOR, or violated a schema rule.
101UNKNOWN_SCHEMA_VERSIONObject schema version is not supported by this deployment.
102UNSUPPORTED_CIPHERSUITENamed ciphersuite is not implemented or not permitted here.
103AMBIGUOUS_SEMANTICSThe request could be read more than one way; normalization refused rather than guessing.
104OBJECT_EXPIREDA carried object was past its expiry at evaluation time.

Policy (2xx)

CodeNameMeaning
200POLICY_DENIEDCompiled policy denied the operation.
201CONSTITUTION_VIOLATIONThe action would breach a constitutional invariant.
202REFINEMENT_FAILEDActive policy could not be shown to be no weaker than the constitution.
203ALGORITHM_FLOORRequested algorithms are below the configured floor; downgrade refused.
204DIVERSITY_FLOORQuorum met numerically but failed the independence requirement.
205UNILATERAL_AUTHORITYA single principal would have sufficed; the no-unilateral invariant refused it.
206MANDATE_EXCEEDEDAn agent's mandate does not cover this tool, resource, counterparty or limit.
207DELEGATION_AMPLIFIEDChild authority was not a subset of its parent.
208BUDGET_EXHAUSTEDA value, count, destination or time budget is spent.

Appraisal (3xx)

CodeNameMeaning
300EVIDENCE_MISSINGA required evidence family was absent.
301EVIDENCE_STALEEvidence was outside its freshness window.
302EVIDENCE_INVALIDEvidence failed cryptographic verification.
303MEASUREMENT_MISMATCHA running image's measurement did not match an approved reproducible build.
304REFERENCE_VALUE_UNKNOWNNo approved reference value covers the presented measurement.
305VERIFIER_DISAGREEMENTIndependent verifiers disagreed. Disagreement is failure, never an average.
306COLLATERAL_UNAVAILABLEVendor collateral could not be obtained, or had expired.
307ATTESTATION_REVOKEDPresented evidence is covered by a revocation.

State (4xx)

CodeNameMeaning
400NULLIFIER_SPENTThis nullifier was already reserved; the operation is a replay.
401RESERVATION_EXPIREDThe reservation lapsed before contributions completed.
402OPERATION_CANCELLEDCancelled before commit.
403GENERATION_RETIREDA contribution named an authority generation that is no longer live.
404EPOCH_MISMATCHA contribution named a refresh epoch other than the current one.
405QUORUM_UNAVAILABLENot enough eligible seats contributed before the deadline.
406STALE_WORKPolicy, evidence, generation or epoch changed after appraisal; prior work was invalidated.
407SEQUENCE_VIOLATIONAn event arrived out of order. Distinct from malformed: the object was well-formed, the sequencing was not.

Seat (5xx)

CodeNameMeaning
500SEAT_UNKNOWNThe contributing seat is not a registered member of this authority.
501SEAT_REVOKEDThe seat was revoked or quarantined.
502CONTRIBUTION_INVALIDThe contribution failed its correctness proof.
503CONTRIBUTION_REPLAYEDValid — for a different request, object, policy, executor or epoch.
504DUPLICATE_SEAT_INDEXTwo contributions claimed the same share index.
505SEAT_UNAVAILABLEThe seat did not respond within its deadline.

Executor (6xx)

CodeNameMeaning
600EXECUTOR_UNATTESTEDThe executor could not present acceptable evidence for its boundary.
601RECIPIENT_KEY_UNBOUNDThe ephemeral recipient key was not bound into the attestation evidence.
602CAPABILITY_MISMATCHThe presented capability did not authorize the attempted action.
603RELEASE_BEFORE_COMMITRelease was attempted before commit and log inclusion.
604OPERATION_NOT_PERMITTEDThe requested primitive is outside the executor's permitted set.

Transparency (7xx)

CodeNameMeaning
700INCLUSION_UNPROVENNo valid inclusion proof was available before the release deadline.
701LOG_INCONSISTENTA consistency proof between checkpoints failed.
702WITNESS_QUORUM_MISSINGToo few independent witnesses co-signed the checkpoint.

Two authorizations, never interchangeable

An envelope binds two distinct things, under separate context labels:

  • x_wrap — the stable wrapping authority. It says this key may be wrapped under this authority at all.
  • x_auth — a fresh, per-request authorization. It says this specific request, against this specific object, under this policy, at this moment.

Neither is replayable as the other. Tests assert that every field of both is bound and that swapping them fails. Collapsing them is how "the key is protected" turns into "anyone who once got a wrap can do anything forever."

Explaining a decision to a human

GET /v1/operations/{digest}/explain returns a JSON rendering intended for an operator: which rule fired, which evidence was consulted, which seats contributed, which floor was not met.

It is a convenience, not the signed representation. The envelope is the signed thing. If the JSON and the envelope ever disagreed, the envelope is right and the JSON is a bug.

On this page