VAEP v1.0.0-rc3 · rev 14 Freeze candidate ↓ .md

VAEP Specification v1.0.0-rc3 — Consolidated Redline, revision 14 (freeze candidate)

Status: Freeze candidate. The normative text is complete. Freeze still requires the artifact items of the §13 checklist (OPEN-1, OPEN-2, OPEN-3 and the regenerated protocol/*.json files), which are not text.

Revision history: Revisions 2–11 each answered the freeze review of the revision before. Revision 12 answers the freeze review of revision 11 and the amendment set proposed against it. Revision 13 folds in the errata found while building the reference implementation (B1–B6, C1–C28) and four product decisions. Revision 14 folds in the errata found conforming to rev 13 and building the CR lifecycle engine (D1–D14) (§15).

Base: VAEP v1.0.0-rc2 (Oct 10, 2026). Supersedes: the earlier rc3 draft "Protocol, Authorization, Lifecycle and Evidence-Binding Amendment", in full. Date: 2026-10-12 (revision 14).

rc3 makes VAEP's execution model safe for money and other irreversible effects, and makes the agent interface machine-checkable. It does six things:

  • It corrects two unsafe rc2 rules immediately (§1).
  • It fixes how a business operation is identified, so two agents cannot execute the same refund twice.
  • It counts every unresolved obligation against monetary bounds.
  • It admits each external effect for transmission at most once.
  • It prevents an entity from claiming an external effect completed before the provider confirms it.
  • It defines every lifecycle, effect state and error code as data, not prose.

#0. How to read this document

0.1 Authority. rc3 = rc2 + this redline. Every rc2 requirement not listed in the §2 supersession index stays normative and unchanged. This document governs only the IDs listed there. Any other conflict with rc2 is an erratum and blocks freeze.

AMD-01 P Precedence (amends §0). The order of authority is:

  1. JSON Schemas and protocol state-machine files (Appendix A);
  2. VPL grammar and semantics;
  3. normative prose;
  4. informative material, including examples and the Agent Guide.

A contradiction among items 1–3 blocks release.

0.2 rc2 baseline. The rc2 text and its conformance package (vaep-conformance-1.0.0rc2) are normative inputs. Where this redline refers to an rc2 identifier (for example IDN-02, AUTH-06, §16.1, §5.3.1, RUN-03, §11.2, the E0–E3 effect classes), the rc2 definition applies unchanged unless §2 lists an amendment.

AMD-02 P Single source. Five tables in this document are generated from the same source as five protocol files:

Table File
CR lifecycle (§6) protocol/cr-lifecycle.json
Effect lifecycle (§5.4), including every expanded LR pair (EFS-07) protocol/effect-lifecycle.json
Error registry (§8) protocol/errors.json
Risk-floor registry (§9) protocol/risk-floors.json
Approval-class registry (AUTH-24) protocol/approval-classes.json

A table here that differs from its file is a defect.

AMD-03 P Fail closed. Sometimes VAEP cannot establish an authorization decision, an execution outcome, an artifact identity or a lifecycle transition. When that happens, it refuses the unsafe operation, records why, and reports the uncertainty through the protocol. An unestablished outcome is never treated as "did not execute."

VRF-01 P Verification method (amends CNF-01). Every normative requirement declares exactly one verification method:

  • suite S — an executable conformance test;
  • deployment D — evidence from the installation;
  • process P — an audit record.

Every suite requirement maps to at least one executable test. Every security-critical suite requirement also has a negative control (CNF-08). A requirement without a declared method is a defect in this specification.


#1. Immediate errata to rc2

These two corrections are issued now as rc2 errata under GOV-04, because rc2 as published is unsafe in both places.

  • Each takes effect on publication.
  • Implementations have 30 days to apply them, but the rc2 conformance claim is withheld from publication until an installation has applied both.
  • Until then, an installation MUST disable autonomous execution of actions with money effects, or document an equivalent compensating control in its conformance report.
  • Both errata are carried into rc3 unchanged.

#ERRATUM-1 — Access-token jti versus DPoP proof jti

Original (AUTH-02): "…every jti and DPoP proof jti MUST be rejected on reuse within the token lifetime."

Defect: Rejecting reuse of the access token's jti makes every grant single-use. That contradicts the 15-minute grant lifetime and RFC 9449, under which one DPoP-bound access token is presented on many requests, each with a fresh proof.

Replacement (AUTH-02, corrected): Grants MUST be sender-constrained with DPoP (RFC 9449) using server-issued nonces. The access token's jti identifies the token for revocation and audit. The gateway MUST NOT reject a request solely because the token's jti was seen before. Each DPoP proof's jti MUST be rejected on reuse within the replay-retention window (AUTH-16). The remaining AUTH-02 text is unchanged.

Fixtures:

  • add test access_token_multi_request_accepted;
  • add test dpop_proof_replay_rejected;
  • add a negative control: with the proof replay cache disabled, the replay test fails;
  • retire any rc2 fixture asserting rejection of access-token jti reuse.

Migration: Drop access-token jti entries from the replay cache and keep proof jti entries. No data migration.

#ERRATUM-2 — Budget reservation released on timeout

Original (AUTH-11): "…committed on success, and released on failure or after 10 minutes."

Defect: A reservation can be released while its effect has been dispatched or may have completed, for example with a slow provider or a crashed worker. The released amount can then be spent again, so cumulative caps such as total refunds can be exceeded.

Replacement (AUTH-11, last sentence), self-contained for rc2: A reservation is never released by elapsed time. It is:

  • committed on recorded success of its action;
  • released on a recorded rollback, or on a recorded provider response documented as non-executing;
  • otherwise held for human reconciliation.

In rc3, EXE-07 supersedes this sentence with the full reservation state machine.

Fixtures:

  • add test reservation_not_released_after_commit_timeout;
  • add fault-injection boundaries 5, 6 and 9 (CNF-09);
  • add a negative control: restoring the 10-minute release makes the cap-overspend test fail.

Migration: Before the erratum counts as applied, audit every reservation that was released by timeout while an outbox row or provider request existed. Re-reserve or reconcile each one.


#2. Supersession index

rc2 item Disposition By
AUTH-02 Corrected ERRATUM-1, AUTH-15, AUTH-16, AUTH-17
AUTH-11 (last sentence) Corrected ERRATUM-2, EXE-07
AUTH-03 Retained; delegation clarified AUTH-20
§7.2 approval column Amended AUTH-20, AUTH-21
CR-07 Retained; computation defined RSK-01 – RSK-05
§8 lead paragraph ("any failed gate sends it back to Draft") Replaced LC-10
LC-01 Amended: transitions are those in protocol/cr-lifecycle.json LC-08
LC-03 Replaced LC-13
LC-04 Amended LC-14
REV-03 Retained; "Held" now names only the reconciliation state LC-12
EFF-04 Retained; Halt also moves the CR to Suspended LC-12
CON-09 Amended EXE-02
EFF-01 Amended EXE-03, EXE-04
§5.3 aggregate example and Appendix A built-ins Amended (the example used a filter the grammar cannot express) CON-23
§5 business-request entities Amended: platform-managed quarantined state CON-24
IDN-02 kind set Amended IDN-10
MCP-01 Amended: cr.withdraw permitted MCP-14
MCP-02 Amended MCP-06, MCP-07, ERR-01 – ERR-05
§17 tool table Replaced §7
SEC-03 Amended ART-06
CNF-01 Amended VRF-01
§20 Amended GUA-02 – GUA-06
§18 conformance table, L3 row ("R2 auto") Amended to "R0–R1 automatic; R2 by delegated approval (AUTH-20)". Levels limit autonomy and never waive the §7.2 minimum AUTH-21
rc2 grant schema risk_max Retained (cap R3); R4 CRs are human-authored AUTH-25
LC-07 (escalation after three rejections) Amended: what counts, and one clearance per submission LC-22
REV-01..05 deployment model Amended: environments and cohorts declared LC-23
RP-4 and EFF-08 (restore) Amended: requests, effects and reservations are reconciled before dispatch resumes EXE-11, EXE-19
IDN-09 ("CR returns to Validated") Amended: transitions T8, T9, T12, T26 LC-08
AUTH-12 ("halts in-flight CRs at their next gate") Amended: revocation acts immediately LC-15, AUTH-22
LC-05 Amended: serialization also covers Suspended CRs T10 guard
§10.2 res claim Amended: res also names environments AUTH-18
§5.2 ("each transition names the Action that triggers it") Amended: platform-event transitions permitted CON-19, CON-20, CON-24
§8 (gate failure returns the CR to Draft; CR content editable) Replaced: CRs are immutable and failures are terminal. This is a substantive change to audit and recovery behavior, not a clarification LC-10, §13 step 5
LC-06 (approved advances at Live) Retained; LC-16 confirms a revert never moves it LC-16
AUD-02 Amended: rejection records carry a reason class (invalid_content or integrity_incident) ART-03
IDN-09 (Live CR whose evidence key is revoked) Amended: stays Live; incident and drift LC-14
§16.1 role table Amended (see the role changes below this table) EXE-01, EXE-13, EXE-17, CON-19, CON-24, EXE-11
EFF-04 ("pause outbox dispatch") Retained; implemented as deferral, never blocked EFS-06
§16.1 vaep_app grants Amended: no DELETE on vaep_obligation, vaep_invocation or effect rows CON-21
§11.2 adapter proxy Amended: the proxy admits a call only by a single-use transmission append against a ledger sent head, and never retries a forwarded call EXE-18
Agent Guide (rc2) Superseded; must be regenerated from rc3 schemas §13

§16.1 role changes.

  • vaep_ctl (new role). It may update vaep_invocation.state and fencing_token. It may write every effect-row state. It may write the obligation states confirmed and released and the obligation's quarantined flag. It may update managed_by: state_machine fields only for confirms_effect, on_effect_* and quarantine (CON-24) transitions. It is never present in app, worker or agent runtimes.
  • Restore job. It runs as vaep_owner.
  • Proxy ledger credential (new). It may append transmission records only (EXE-17).

rc3 adds no CR operation types. GOV-03 requires new ops to ship first as extensions in at least two installations (OPEN-4).


#3. Authorization (amends §10)

#3.1 Scopes and authority separation

AUTH-18 S Scope names. The scope names are exactly the rc2 names: read:contract, propose, read:cr, act:<action>, read:runtime. rc3 adds none.

  • propose never authorizes action.invoke.
  • An act:<action> grant's res claim MUST name the permitted action IDs, environments and resource scope. res is an array of strings, each of the form action:<action_id>, env:<environment>, tenant:<tenant_id> or entity:<entity_name>. Any other form is rejected with E_GRANT_INVALID. A grant permits a request only if it names the request's action, its environment, and (where the request is scoped) its tenant and entities. The entities of an action.invoke request are the action's business-request entity (CON-17) plus every entity the action writes, as declared in the contract revision; the grant must name each one. A cr.* request is scoped to the entities in the CR's computed affected set. The grammar is part of schemas/grant.schema.json.
  • Its obj claim binds the grant to one objective.
  • The execution budget stays in the server-side ledger and is never carried in the token (§10.2 unchanged).
  • Holding several scopes does not merge decisions. Each request is authorized only against the scope its tool requires (§7.2).

AUTH-19 S No production effect from authoring. No cr.* tool causes a production business action. Verification runs only in environments whose identifiers differ from production, against sandboxes or recorded fakes (EFF-06). A production invocation requires an act:<action> grant whose res names the production environment.

#3.2 Tokens and DPoP

AUTH-15 S Token reuse. An unexpired, unrevoked access token MAY authorize any number of requests within its scope, audience and objective. Token revocation and proof replay detection are separate mechanisms.

AUTH-16 S Proof uniqueness. Every DPoP proof carries a unique jti. The gateway validates:

  • htm and htu;
  • ath (the access-token hash);
  • the current server nonce;
  • iat within a declared clock skew of at most 60 s.

An accepted proof jti MUST be rejected for the replay-retention window, which is at least the token lifetime plus the skew.

Replay detection is atomic across all gateway replicas in one acceptance domain, meaning every replica that accepts tokens for the same aud value.

A new proof never creates a new business operation: business identity is fixed by EXE-02.

AUTH-17 S Replay-cache failure. If the gateway cannot determine whether a proof was already accepted, it rejects the request with E_INTERNAL_UNAVAILABLE. A cache outage never disables replay protection.

#3.3 Approval

AUTH-20 S Delegated R2 approval. Delegated auto-approval applies to R2 only.

  • Who. A named service principal (the delegate), declared in the human-signed objective together with its risk ceiling (R2) and the maximum number of CRs it may approve.
  • Who it cannot be. The delegate MUST NOT be:
    • any drafter of the CR (MCP-09 records every principal that drafted identical content);
    • any agent in the author's delegation chain;
    • any principal whose code, policy or configuration lies within the objective's declared entities, actions or policies.
  • Its policy. Changes to the delegate's policy are R4 under AUTH-09. The delegate's decision is a deterministic policy over the evidence bundle. It approves only when every check passed, computed risk is exactly R2, and there is no T or A element in the CR's assurance graph. The policy version is recorded in the approval record (ART-02).
  • Assurance graph. It is the set of elements introduced by the CR, plus, for every action in affected:
    • that action's declared effects;
    • the policy rules that permit it;
    • the invariants whose predicates read a field it writes;
    • the integration adapters its effects use.
  • Adapter class. Every adapter declares an enforcement class. An adapter is class M only when conformance tests against the provider (or its documented contract test suite) cover every one of its EXE-04 declarations, and the manifest records those tests. Otherwise it is class A. An adapter with no declared class is class A. So a CR whose assurance graph includes an adapter that is not class M always needs a human approval.
  • Fallback. Without a valid delegation, R2 needs one human approval.
  • Never for R3/R4. Delegation never satisfies R3 or R4.

AUTH-21 S Effective approval. The effective approval requirement is the strictest of:

  1. the computed risk class minimum (§7.2);
  2. the objective's restrictions;
  3. the conformance level's autonomy limit (§18);
  4. privileged-change rules (AUTH-09, CON-08, DJ-05);
  5. the incident rule: while an incident or drift finding is open that touches any entity in the CR's affected set, the requirement is at least one_human and delegated approval (AUTH-20) is not available. Incidents and drift on unrelated entities do not change the requirement. Every finding records the entities it touches. A finding whose entities cannot be determined (for example a budget reservation with no effect row) is recorded with an unknown scope, and an unknown scope counts as touching every entity.

A conformance level may permit an approval mechanism but never waives the §7.2 minimum. In particular, the rc2 §18 L3 entry means R2 by delegated approval, not R2 without approval.

The effective requirement is computed at the approval gate, from the facts current at that moment. The class cr.draft returns is a snapshot (MCP-09).

AUTH-24 S Approval classes. The approval classes are exactly those in protocol/approval-classes.json:

Class Satisfied by
automated No approval record (R0, and R1 where §7.2 permits)
delegate_or_human The AUTH-20 delegate, or one human approver
one_human One human approver
named_human One human approver named in the objective
two_humans_security Two human approvers, at least one holding the security role

Each class may carry the flag out_of_band (AUTH-09): the approvals must arrive through a channel the requesting principal cannot reach. Errors and cr.draft name the class by these identifiers (ERR-04), and the capability descriptor lists them (MCP-13).

AUTH-25 S R4 is human-authored. A CR whose computed risk is R4 is authored only by a human principal. A grant's risk_max never exceeds R3, so an agent's R4 draft is rejected with E_RISK_EXCEEDS_GRANT. An agent may describe a needed R4 change in an incident or in a CR's findings, but never drafts it.

Human authoring channel. Humans draft CRs (R4 or any other class) through the human authoring channel: an interface outside MCP, authenticated as a human principal with phishing-resistant authentication. A draft submitted there produces the same immutable CR record as cr.draft, with the human recorded as drafter, and passes the same validation. MCP never exposes this channel, and no agent credential can reach it (CNF-08 negative control).

#3.4 Revocation

AUTH-22 S Effect of revocation. Revocation takes effect within at most 5 s (AUTH-12). From then on, it blocks new admissions, lifecycle advancement and effect dispatch.

  • Recheck. Every dispatch rechecks authorization immediately before authorizing the send (F1b).
  • Refusing unsent effects. When revocation takes effect, the control plane appends refused for every effect under the revoked objective whose effective head (EXE-12) is any of: none, continued, send_revoked, pre_send or sent (F2, F2b, F2e). A refused appended against a sent head makes the proxy's transmission append fail (EXE-18). So revocation that lands before transmission admission always prevents the send.
  • Interrupted sweeps. The revocation is recorded before the sweep starts. If the sweep is interrupted, the repair scan (EXE-03) completes it for every revoked objective. Until then F1 and F1b refuse under the revoked objective, so an incomplete sweep never permits a send.
  • Already transmitted. Revocation does not undo an effect whose head is transmission or later. That effect continues through the §5.4 states and is reported truthfully.
  • Committed but unsent. Revocation after the business transaction commits but before transmission leaves the effect blocked. The business entity stays in its pending state (CON-19), so it never claims an execution that did not happen.

AUTH-23 S No resurrected authority. Workers act under the invocation's objective. Once that objective is revoked, no worker may dispatch, retry, compensate or cancel under it.

The recovery authority.

  • It is the objective's human owner, or a named human principal designated by a separately signed incident objective. It is always a human principal.
  • An agent working under an incident objective may propose recovery steps but can never act as recovery authority.
  • It is the only principal that can decide to continue, cancel or reconcile blocked, suspended or quarantined work, whether or not the objective is revoked.
  • Attesting a reconciliation_required outcome also requires the R3 approver role (F15, F16).
  • Its decisions are executed by the control plane (EXE-17).

Continuing a blocked effect (F17). When the recovery authority continues a blocked effect, the effect is re-bound to that authority. Its next F1b recheck then tests all of the following:

  • the designating incident objective (or the owner's objective) is active and unrevoked;
  • the recovery authority principal is still named in it;
  • the continued record is the predecessor of the dispatcher's pre_send.

No act: grant is involved: the human never invokes the action, and the platform dispatches a committed effect. Each such step's audit record names the deciding principal.


#4. Business requests and money (amends §5)

CON-17 S Business-request entity. Every action that declares an E2 or E3 effect MUST take as input the ID of a business-request entity declared in the contract (for example refund_request).

  • Separate creation. The request entity is created by a different action from the effecting action, and each requires its own act: scope. Whether one principal may hold both scopes is the objective's decision. An objective that grants both to one principal says so in its signed text (AUD-02 records it).
  • Own state machine. The request entity has its own state machine.
  • Executable state. The effecting action's precondition requires the request to be in an executable state.
  • Executed at most once. The effecting action's transition moves the request out of that state. Because the request state is managed_by: state_machine (CON-05), one request is executed at most once.

CON-18 S Uniqueness is declared, never inferred. Every business-request entity MUST declare uniqueness as one of:

  • A list of fields. The platform compiles it as a partial UNIQUE constraint (class M) over requests not in a failed, cancelled or declared withdrawn state. That scoping is the normative form, so a new request after a definitive failure is not a duplicate. A request in the platform quarantined state (CON-24) is inside the constraint.
  • The literal "none", with a one-line rationale.

Rules:

  • Omitting the declaration is a validation error at /entities/<entity>/uniqueness.
  • The contract summary lists every "none" declaration.
  • A declared uniqueness key is compiled as a block invariant with a stable ID.
  • Any change to the key other than removing fields from it is a weakening under CON-08 and is R4 (§9). That includes adding a field, adding any condition beyond the normative scoping above, and switching to "none".
  • A second legitimate partial refund on the same invoice is a distinct request with a distinct ID. It is bounded by CON-21, not by uniqueness.

CON-19 S Completion is confirmed, not assumed.

Confirmation states. A state may be marked confirms_effect: <effect_id>. A transition into such a state happens only through the platform's confirmation event when that effect reaches succeeded. Three changes are one database transaction (EFS-04):

  • the effect's move to succeeded;
  • the obligation record's move to confirmed (EXE-13);
  • the entity's transition.

No action, escape hatch, schedule or migration may write a confirmation state.

Pending states. An E2/E3 action moves its entity to a pending state that is not so marked.

  • The pending state's only outgoing transitions are the platform's confirmation event and the on_effect_failed and on_effect_cancelled events.
  • No action, schedule, escape hatch or migration may move an entity out of it.

Validator. It rejects:

  • an E2/E3 action whose own transition targets a confirms_effect state;
  • an E2/E3 action whose entity has no confirms_effect state for that effect;
  • any other transition out of a pending state.

CON-20 S Failure paths are declared. Every E2/E3 action MUST declare on_effect_failed and on_effect_cancelled transitions from its pending state.

  • Target. Each target MUST be a state the effecting action's precondition does not accept. A failed request is never re-executed; a retry is a new request (E_REQUEST_RETRY_NOT_PERMITTED).
  • Trigger. Only platform events trigger these transitions, under the platform service principal, and they are audited.
  • Validator. It rejects an action that omits either transition or whose target is executable.
  • Which effect. When an action declares several E2/E3 effects (for example a refund and a receipt email), these transitions follow the effect named by the entity's confirms_effect state. A failed or cancelled other effect makes the invocation partially_effected (EXE-10) and does not move the request.
  • Retry versus prior outcome. Re-invoking the effecting action under the same identity with the same input hash returns the durable prior outcome (EXE-02). E_REQUEST_RETRY_NOT_PERMITTED is returned only when no committed invocation exists for the request.

CON-21 S Pessimistic accounting.

Declaring the bound. Every business-request entity whose effecting action has a money(currency) effect MUST declare bounded_by as one of:

  • { relation: <relation to the bound owner>, bound: <field on the bound owner> };
  • the literal "none", with a rationale. The contract summary lists it.

A request carries exactly one money effect (EXE-13).

The generated invariant. When a bound is declared, the platform generates a block invariant with a stable ID over the monetary obligation records that reference the bound owner:

sum_where(owner.obligations, o, o.state != "released", o.amount) <= owner.<bound>

What the bound means. The bound field is the lifetime total the owner allows across all its requests. An example is invoice.refundable_amount, the amount originally refundable on the invoice.

  • It is not a running balance and is never reduced to reflect confirmed obligations. Confirmed obligations stay in the sum, so nothing is counted twice and nothing is omitted.
  • The validator rejects a contract in which any of these writes the bound field: a confirms_effect transition, an on_effect_* transition, the creating action, or the effecting action.
  • Any other write to the bound field is an ordinary contract-declared write, serialized by the lock protocol below. A decrease that would place the sum above the new bound is rejected by the invariant.

What counts. Every obligation not in released counts. That includes:

  • requested, reserved and confirmed obligations;
  • obligations whose reservation is held (EXE-07);
  • quarantined obligations (CON-24).

An obligation is released only by one of:

  • evidence of non-execution (EFS-02);
  • declared withdrawal before commit (EXE-13);
  • a recovery-authority attestation of non-creation (EXE-19).

A reversal of a confirmed obligation (for example a chargeback) is a separate request, with its own obligation against its own bound. The original stays confirmed.

The obligation record. It is a platform table in the application database (vaep_obligation), owned by vaep_owner.

Column Notes
tenant_id
bound_owner typed reference
request reference
amount
currency
state one of requested, reserved, confirmed, released
quarantined boolean
  • It is created in the same transaction as the business request, in state requested.
  • A request has exactly one obligation, and the obligation is in exactly one state, so it is counted at most once.
  • amount, currency, bound_owner, tenant_id and the request reference are immutable after creation, enforced by a vaep_owner trigger.
  • vaep_app holds no DELETE on vaep_obligation, vaep_invocation or effect rows (§16.1 amended). Deletion of these rows is impossible from any runtime role.
  • The invariant compiles only if the bound's currency matches; mixing currencies is a compile error (CON-03).
  • If sum_where's predicate yields null or the error value for a row, the row is counted (CON-23).

Tenancy. In a multi-tenant application, the aggregate is per tenant_id, and the bound owner is always within that tenant. An application that declares a cross-tenant bound is outside the rc3 conformance claim (OPEN-5).

Fail-closed blocking. This can block a legitimate refund while another refund is unresolved. That is the intended fail-closed behavior.

Coverage. The invariant compiles under §5.3.1, with trigger coverage on the request table, the obligation table and every table that writes the bound field (CON-14).

Lock protocol (normative for class M).

  1. Lock row. Each bound owner has one row in vaep_agg_lock, keyed by (tenant_id, bound owner). It is created in the transaction that creates the bound owner, so acquisition is always an UPDATE, never an insert race.
  2. Which transactions lock. Every transaction that inserts a counted obligation, or writes the bound field, executes UPDATE vaep_agg_lock … SET version = version + 1 for that bound. It then evaluates the invariant by a statement that starts after that UPDATE returns. Transactions that only confirm or release an obligation never increase the sum, and need not lock.
  3. Under READ COMMITTED. The aggregate read is a new statement with a new snapshot, so it observes every transaction that committed before the lock was granted.
  4. Under REPEATABLE READ and SERIALIZABLE. A concurrent transaction may have updated and committed the lock row after this transaction's snapshot was taken. In that case the UPDATE fails with a serialization failure, so a stale snapshot can never pass the check.
  5. Retries. Serialization failures, deadlocks and lock timeouts abort the business transaction. The Executor retries it under the same invocation attempt and fencing token, up to a declared limit. When the limit is exhausted, the attempt ends failed_without_effect with E_INTERNAL_UNAVAILABLE (retry class later). An aborted attempt is never treated as a commit.
  6. Commit. A commit succeeds only when the aggregate observed after acquiring the lock, including the new obligation, does not exceed the bound.

CNF-13 requires scripted interleavings that demonstrate this at all three isolation levels. Acquiring the lock is not sufficient evidence on its own: each schedule must show that the aggregate observed by every successful commit includes every concurrent committed write.

CON-22 S Two counters, both must pass. The objective ledger (AUTH-06, AUTH-11) and the contract invariants (CON-21) are independent.

  • An invocation proceeds only if both admit it.
  • A refusal returns the refusing counter's code: E_BUDGET_EXHAUSTED or E_INVARIANT_VIOLATION.
  • Nightly reconciliation compares the ledger's committed and held amounts with the effects they reference. Any mismatch is reported as drift (RUN-03) through incident.get.

CON-23 S VPL filtered aggregates. rc2's §5.3 example (sum(payments.amount where invoice=X)) cannot be expressed in the Appendix A grammar. rc3 adds two built-ins:

  • sum_where(v.rel, x, pred, x.field)
  • count_where(v.rel, x, pred)

They are ordinary call productions, so the grammar is unchanged. For sum_where, a row whose predicate is null or the error value is included (fail closed). The §5.3 example is rewritten with sum_where.

CON-24 S Platform quarantine state. The validator adds a platform-managed state quarantined to every business-request entity. A contract may not declare transitions into or out of it.

  • Not executable. A quarantined request is never executable. Invoking its effecting action returns E_BUSINESS_REQUEST_STATE with retry class after_reconciliation.
  • Still counted. It counts against uniqueness (CON-18), and its obligation (with quarantined = true) counts against its bound (CON-21).
  • Two exits. Its only exits are platform events executed by the control plane on a recovery-authority decision (EXE-19):
    • request_reconstructed moves it to the entity's declared created state. Its obligation stays requested, with quarantined = false.
    • request_voided moves it to the entity's declared withdrawn state, and its obligation is released.

Unmediated channels. A refund issued directly in the provider's own dashboard never passes through VAEP and is invisible to CON-21. That channel is unmediated (§11.2). The contract summary lists it under EV-03, and non-guarantee 4 of §20 applies.


#5. Execution model (new §11A; amends CON-09, EFF-01, AUTH-11)

#5.1 Invocation record

EXE-01 S Record before execution. The invocation record is a row in the application database (vaep_invocation, owned by vaep_owner).

What vaep_app may do. Column privileges and a constraint trigger, compiled under §5.3.1 and owned by vaep_owner, limit vaep_app to:

  • inserting a row in admitted;
  • moving admitted → committed, or admitted → failed_without_effect, by a CAS under the row's current fencing_token.

Setting state := abandoned, and any change to fencing_token, are permitted only to vaep_ctl. A vaep_app write that violates this fails at the database (CNF-08 negative control).

One live attempt per identity. A partial UNIQUE constraint on (application, environment, action, key) applies over rows not in abandoned or failed_without_effect. For E0/E1 actions, key is (objective, client key). This makes two live attempts under one identity impossible: the second insert fails, and the caller receives E_INVOCATION_IN_PROGRESS or the durable outcome.

Admission order.

  1. The gateway reserves budget (AUTH-11).
  2. The gateway appends an admitted ledger record. It carries the invocation ID, identity key, canonical input hash, action, environment, objective and reservation ID.
  3. The row is inserted, carrying the reservation ID.

The gateway's ledger credential is one vaep_app never holds. A row with no unvoided admitted ledger record is a forgery: it is reported as drift (RUN-03f) and never dispatches (F1). In particular, after the control plane voids an admitted record (admission-lease expiry, EXE-07), any later row carrying that reservation ID is a forgery.

Row contents. Before business execution begins, the row is recorded in its own transaction, in state admitted, with:

  • invocation_id, principal, objective, action and environment;
  • the business-request ID (E2/E3) or idempotency key (other actions);
  • the canonical input hash (JCS + SHA-256, §6);
  • the authorized resource scope, the expected contract revision and the execution status.

The reservation is keyed by invocation_id and carried in the inserted row. It is never written to the row afterwards.

#5.2 Identity and atomicity

EXE-02 S Idempotency identity. The identity is (application, environment, action, key).

  • For E2/E3 actions, key is the business-request ID (CON-17). It is never a value minted by the agent.
  • For E0/E1 actions, key is a client-supplied idempotency key, additionally scoped by objective.
  • The principal is never part of the identity, so any authorized agent retrying the same request resolves to the same invocation.
  • Same identity with the same input hash returns the durable prior outcome or the current status.
  • Same identity with a different input hash returns E_IDEMPOTENCY_CONFLICT.

Permanent input binding. The ledger keeps one identity chain per identity.

  • Every admitted append is a conditional append on that chain.
  • The first admitted record binds the identity to its canonical input hash, permanently.
  • The ledger rejects any later admitted record whose hash differs (E_IDEMPOTENCY_CONFLICT). This holds even after every prior attempt became abandoned or failed_without_effect.
  • Because the ledger is outside restore scope (EXE-14), the binding survives every restore.

The proof boundary. The identity names one logical operation. Every attempt under it is recorded permanently, including failed ones. A new attempt under the same identity is admitted only when every prior attempt is proven non-executed. That means:

  • no invocation row for the identity shows a commit;
  • the ledger holds no invocation_committed record for the identity;
  • the ledger holds no effect record beyond pre_send or void for the identity.

The ledger checks are keyed by the identity's key: the business_request_id for E2/E3 actions, and the idempotency key otherwise. They are never keyed by invocation_id.

Rollback alone is sufficient only because EXE-03 makes dispatch impossible before commit. Any attempt not meeting the proof is treated as in progress, and the caller receives E_INVOCATION_IN_PROGRESS or the durable outcome.

No second effect identity. effect_id is derived solely from (invocation_id, declared effect name), per EXE-04. A new invocation is admitted only on the proof above. So no permitted retry can mint a second effect_id for a logical operation whose first attempt may have executed.

EXE-03 S One transaction. For a given invocation, these happen in one database transaction:

  • the business mutation;
  • a compare-and-swap of the invocation row from admitted to committed under the attempt's fencing token (EXE-09). A row already abandoned, or carrying a newer token, aborts the transaction;
  • for an action with a money effect: a CAS of the request's obligation from requested to reserved (with quarantined = false), as an UPDATE that must affect exactly one row, or the transaction aborts. The effecting action's compiled precondition also requires such an obligation. A money request with no obligation row is therefore unexecutable. Non-money E2/E3 actions have no obligation and no monetary reservation (EXE-07);
  • the CON-21 lock protocol, when a money obligation is reserved;
  • creation of an effect record, in pending_dispatch, for every E2/E3 effect the action declares, and only those (EXE-15). An E0/E1 effect is the business write itself and has no effect record;
  • creation of an outbox row for every such effect record.

A committed mutation without these records is impossible by construction.

After commit. The Executor reports the commit, and the control plane appends an invocation_committed ledger record carrying the commit watermark (EXE-12). Until that record exists, the effects stay pending_dispatch and no F1 may run.

Repair scan. On every control-plane start, and at least every minute, the repair scan does the following:

  • For each committed invocation row lacking invocation_committed: if the row has an unvoided admitted record, it appends invocation_committed. Otherwise it raises drift and quarantines the row (CNF-09 boundary 5).
  • It voids orphaned pre_send records (F1c, F1d).
  • It appends send_revoked for sent heads whose lease has expired with no transmission (F39; boundary 12).
  • It completes any interrupted revocation sweep (AUTH-22) and any missing reservation append after a terminal record (EXE-07, EFS-04).

Restore job. The EXE-11 restore job runs as vaep_owner inside the Executor (§16.1). It is the only role that may insert invocation, effect, obligation or request rows outside the action decorator. Fixtures assert this under crash injection.

EXE-04 S Effect identity and adapter declarations.

Effect identity. Every external effect has effect_id = the IDN-02 identifier of kind eff over (invocation_id, declared effect name), with no nonce. The same logical effect therefore has the same ID in the application database, the ledger and any restore. When the provider supports idempotency keys, the adapter sends a provider key derived deterministically from effect_id.

Adapter declarations. Every adapter declares the following. All of it is part of the manifest digest (ART-01).

  • provider_idempotent: true | false — whether the provider deduplicates requests by the derived key. rc3 never re-dispatches an effect after transmission (EXE-05). This declaration therefore affects only reconciliation and the GUA-03 statement of provider-side execution count.

  • non_executing_responses — a closed set of response classes (status codes, error codes) the provider documents as meaning the operation did not execute.

  • lookup_finality: true | false — whether a not-found lookup by the derived key is final for that key. true requires that the provider contract documents one of:

    • key closure: a lookup that returns not-found closes the key, so the provider will never execute a request carrying that key that arrives later; or
    • request expiry: the provider rejects any request older than a documented expiry, and the adapter performs the lookup only after the transmission time plus that expiry plus the declared clock skew has passed.

    The adapter declares these as closes_key_on_lookup: true | false, request_expiry_s (seconds, absent if the provider enforces no expiry) and clock_skew_s (the maximum skew between the adapter's clock and the provider's). lookup_finality: true requires closes_key_on_lookup: true or a request_expiry_s value.

    Either way, a not-found answer also covers any request the provider accepted before the lookup. An adapter that cannot promise one of these declares false.

  • the deadlines in EFS-05.

A response outside non_executing_responses is never failed. It leads to outcome_unknown (F7) or provider_pending (F6).

EXE-05 S Ambiguous outcomes. Any transmitted effect whose outcome is not definitively established enters outcome_unknown (F7, F10).

  • No re-dispatch. VAEP never issues a new effect_id for the same logical effect. In rc3 it never re-dispatches an effect whose ledger chain contains a transmission record: no transition leads from transmission back to pre_send (EXE-12).
  • How it resolves. Only by provider evidence (F8, F9), by reconciliation lookup (F11, F12), or by human attestation (F15, F16).

Opening a lookup. Before any lookup, the reconciler appends an open_lookup record naming the effective head, which must be transmission or a prior open_lookup.

  • The ledger accepts that append only if the fencing token on the effect's sent record has no live lease. Either the lease expired, or the sender recorded its outcome.
  • A live lease proves only that no other worker may start a send under that token. It never proves that an already-transmitted request has finished.

What a lookup can prove.

  • Execution (F11). A provider confirmation by the derived key, or by the stored provider reference, establishes execution.

  • Non-execution (F12). This requires both:

    • the response class is in non_executing_responses; and
    • the adapter declares lookup_finality: true.

    A "not found", "not yet processed" or equivalent response is otherwise inconclusive.

Recording the verdict. The verdict is a terminal record naming the open_lookup head. A repeated lookup appends a new open_lookup naming the previous one.

After closing. An authenticated provider callback that arrives while the effect is reconciliation_required is evidence submitted to the recovery authority. It never triggers an automated transition: only F15 or F16 leaves that state.

Closing reconciliation. Inconclusive lookups may repeat until reconciliation_deadline. The control plane then appends lookup_closed, and the effect moves to reconciliation_required (F14). If the provider offers no lookup by key and no provider reference exists, lookup_closed is appended at once: the effect is never re-dispatched to find out.

EXE-06 P No exactly-once claim. VAEP claims exactly-once execution at the provider only where the provider's contract documents it. The default guarantee is GUA-03.

EXE-07 S Reservation states. Reservations move through reserved, committed, released and held. Reservation transitions are recorded in the ledger by the control plane, referencing the record that justifies them. A reservation is atomic: its count and monetary components share one state. A money invocation's reservation, count included, commits only when its money effect reaches succeeded.

Because the budget ledger lives outside the application database (EXE-14), a reservation transition is never part of an application-database transaction. On an effect terminal, the control plane appends the reservation transition after the terminal record and before the EFS-04 transaction, citing the terminal record. The append is idempotent, and the crash-repair scan completes it alongside LR (CNF-09 boundary 11).

From To When
reserved committed The invocation's money effect reaches succeeded. An invocation with no money effect reserves only a count, which commits when its business transaction commits.
reserved released The business transaction rolls back; or the invocation row is abandoned (idempotent repair); or the money effect reaches failed or cancelled while the reservation is still reserved.
reserved released No invocation row references the reservation when the admission lease (60 s) expires. If an admitted record exists, the control plane first appends a void naming it (identity-chain grammar, EXE-12), so a late row insert is a forgery under EXE-01 and never dispatches. If none exists (a crash between reservation and admitted, CNF-09 boundary 3), it releases with no void.
reserved held The money effect enters outcome_unknown, reconciliation_required or blocked. Non-money effects never move a reservation to held.
held committed The money effect reaches succeeded, by any evidence-backed path.
held released The money effect reaches failed or cancelled, by any evidence-backed path.

Rules:

  • A held reservation stays held through F17 (blocked → pending_dispatch) until its money effect terminates.
  • F39 (send_revoked) never moves a reservation: the effect was never transmitted.
  • Cumulative caps count reserved, held and committed.
  • A reservation's monetary component belongs to exactly one money effect (EXE-13), so settlement is never partial.
  • Every held reservation has an exit: its money effect terminates, or the invocation is proven non-executed.

EXE-08 S Retries are re-authorized. Every retry re-runs authentication, authorization, revocation and policy checks. Idempotency never bypasses authorization. A caller no longer authorized to see the result receives E_SCOPE_DENIED with execution_status: not_started for its own request, and nothing about the prior invocation (ERR-05).

EXE-09 S Fencing.

Tokens. Dispatchers and executors hold leases carrying a monotonically increasing fencing token. The control plane issues it, and it is stored on the invocation row (EXE-01). There is one dispatcher lease per invocation, covering every effect of that invocation. Wherever §5.4 says "the row's current token" (F1c, F1d, F39), it means the invocation row's token. Effect rows carry a copy of the token for audit only.

Lease storage. Leases are stored in the ledger cluster, in an implementation-defined lease table, so the ledger can judge lease liveness for open_lookup (EXE-05) and the proxy can judge it for admission (EXE-18). The lease duration is configuration, declared in the installation's [D] evidence (EXE-14).

  • Every durable write to the invocation row, every effect-state transition in the application database, and the EXE-03 commit itself are compare-and-swaps against that row's token. The database rejects a write whose token is older than the row's.
  • The control plane updates the row's token (and may mark it abandoned) only by a CAS of its own.
  • The fencing-token counter is outside application restore scope (EXE-14), so a post-restore lease never reissues a token.

What prevents a stale send. The decisive condition is at the ledger, not the application-database row. The dispatch-intent ledger is append-only and head-linked (EXE-12):

  • The pre_send → sent append names the dispatcher's own pre_send.
  • The proxy's transmission append names that sent record (EXE-18).
  • Any of void, send_revoked, refused or cancelled appended in between makes the later append fail, and the actor must not proceed.

Lease expiry alone is never sufficient.

#5.3 Invocation status

EXE-10 S Derived from effects. Invocation state is derived from the business transaction and its effects. When more than one row applies, the order of precedence is: reconciliation_required, then outcome_unknown, then executing, then the terminal states.

Invocation state Condition execution_status
admitted Recorded; business transaction not started not_started
abandoned Lease expired while admitted; fenced and terminal (ERRATUM-2) failed_without_effect
executing Business transaction running; or committed with any effect not yet terminal, including blocked in_progress
completed Committed; no effects, or every effect succeeded succeeded
failed_without_effect Business transaction rolled back; no local state changed and nothing was dispatched failed_without_effect
completed_external_failed Committed (local state and E0/E1 effects applied); every external effect failed or cancelled; declared failure transitions applied completed_external_failed
partially_effected Every effect terminal; some succeeded, others failed or cancelled partially_effected
outcome_unknown Any effect outcome_unknown unknown
reconciliation_required Any effect reconciliation_required unknown

EXE-12 S Dispatch-intent ledger.

What it is. The control plane keeps an append-only dispatch-intent ledger. It is restore-independent (EXE-14) and distinct from the audit log (§15), which it feeds.

Record kinds.

Group Kinds
Request request_created, request_committed, request_aborted, request_quarantined, request_reconstructed, request_voided, request_withdrawn
Invocation admitted, invocation_committed
Per-effect pre_send, sent, send_revoked, transmission, open_lookup, lookup_closed, refused, continued, void, and the terminals succeeded, failed, cancelled
Control dispatch_frozen, dispatch_unfrozen (per application, EXE-11)

Chains and the head CAS. Per-effect records form a chain per effect_id, and identity records form a chain per identity (EXE-02).

  • Each record names its predecessor record ID.
  • The ledger accepts an append only if the named record is still the chain's effective head. This is a true compare-and-swap on the head. State and token are carried in the record but are not the condition.

Effective head. The effective head is the latest record that is not void and has not been voided. On an effect chain, a void record may follow only a pre_send. It voids that pre_send, so the effective head reverts to the pre_send's predecessor (or to none). On an identity chain, a void may follow only an admitted record, with the same effect; the voided attempt stays recorded, and the input-hash binding (EXE-02) is never reverted.

Permitted per-effect sequences (normative).

Effective head May be followed by
none pre_send, refused, cancelled
pre_send sent, void, refused, cancelled
sent transmission, send_revoked, refused, cancelled
send_revoked pre_send, refused, cancelled
continued pre_send, refused, cancelled
refused continued, cancelled
transmission succeeded, failed, open_lookup, lookup_closed
open_lookup succeeded, failed, open_lookup, lookup_closed
lookup_closed succeeded, failed
succeeded, failed, cancelled nothing (terminal)

Permitted identity-chain sequences (normative). For E2/E3 actions the identity chain is keyed by business_request_id and carries both the request records and the invocation records:

Effective head May be followed by
none request_created
request_created request_committed, request_aborted, request_quarantined
request_quarantined request_reconstructed, request_voided
request_committed, request_reconstructed admitted, request_withdrawn
admitted invocation_committed, void
invocation_committed, request_aborted, request_voided, request_withdrawn nothing (terminal for the chain)

A void of an admitted record reverts the head to that record's predecessor, so a later attempt may append a new admitted. For E0/E1 actions the identity chain carries only admitted, void and invocation_committed, with the same rules.

Build check. The build check on protocol/effect-lifecycle.json rejects any path that leads from a transmission record to pre_send, sent, send_revoked, refused or cancelled. Once a transmission has been admitted, the effect resolves only by evidence. A later human attestation of definitive non-execution produces failed, never cancelled.

Ledger-first rule. Every effect-row transition except F6, F7 and F10 is first a conditional append to the ledger, and only then a row write that records the appended record's ID. F6, F7 and F10 are row-level refinements within a transmission head. Because each append is conditional on the effective head, two actors racing for one effect cannot both succeed: the second append fails, and its actor stops. Examples of such races:

  • a dispatcher sending while a recovery authority cancels;
  • the proxy admitting while the control plane revokes.

The row in the application database mirrors the ledger and is never the deciding record.

Record contents. Every record carries:

  • the idempotency identity key (business_request_id or idempotency key) and tenant_id;
  • where applicable: effect_id, invocation_id, the obligation (amount, currency, bound_owner, state), the request's uniqueness fields and declared pending state, and the provider idempotency key.

The ledger is authoritative for send state and for every decision that releases or confirms money.

Watermark. Every ledger record carries the application database's (timeline ID, WAL insert position) at the time it is appended. request_committed and invocation_committed carry the commit LSN of the transaction they record instead. A restore to point P on timeline history H defines a record as "after the restore point" if its position is later than P in H. This distinguishes records from an abandoned timeline after a second restore.

Request creation and commit. These are governed by EXE-19.

EXE-13 S One money effect. An action declares at most one effect whose amount is money(currency). Its reservation and obligation (CON-21) belong to that effect alone. Non-money effects never hold a reservation. A contract violating this is rejected with E_MULTIPLE_MONEY_EFFECTS.

Obligation lifecycle. The obligation record moves forward only:

State Reached
requested at request creation, or when a quarantined request is created (CON-24)
reserved in the EXE-03 transaction
confirmed in the EFS-04 transaction on succeeded
released by any of the paths below

An obligation is released when:

  • its effect reaches failed or cancelled (EFS-04);
  • its request leaves its executable state for a declared non-executable terminal state, with no invocation_committed for the request. The action commits the entity transition; the control plane then appends request_withdrawn and writes released as vaep_ctl, audited;
  • its quarantined request is voided (request_voided, EXE-19).

The permitted obligation transitions are exactly:

  • requested → reserved | released;
  • reserved → confirmed | released.

confirmed and released are terminal. A constraint trigger owned by vaep_owner rejects any other change.

Who may write what.

  • confirmed, released, the quarantined flag, and every effect state outside the vaep_app set are written only by vaep_ctl. Each such write records on the row the ID of the ledger record that justifies it.
  • vaep_app can write obligations only to requested (at creation) and reserved (in EXE-03).
  • vaep_app can write effect rows only to pending_dispatch, pre_send, dispatching and provider_pending.
  • Adapters run as vaep_app and report outcomes to the control plane, which performs every other write as vaep_ctl.

Both triggers are CNF-08 negative controls. The validator requires every business-request entity to declare at least one withdrawal transition.

EXE-14 D Restore-independent control state. The following are stored outside the application database and outside the scope of any application restore:

  • the dispatch-intent ledger, including the identity chains and transmission records;
  • the fencing-token counter and the lease table (EXE-09);
  • the budget ledger;
  • the DPoP proof-replay cache (AUTH-16), so an application restore cannot make the gateway forget an accepted proof.

An installation's conformance evidence names each store and shows that an application restore cannot roll it back.

EXE-15 S Only declared effects dispatch. An effect row is dispatchable only if (committed action, effect name) is an E2/E3 effect in the contract revision the invocation row names. An undeclared effect row is drift (RUN-03a) and never reaches pre_send. The EXE-03 constraint trigger rejects inserting an effect row whose name the action does not declare.

EXE-16 S Amount binding. For the money effect, a constraint trigger owned by vaep_owner enforces effect.amount = obligation.amount and effect.currency = obligation.currency, at insert and on every update.

  • The pre_send and sent records carry the amount.
  • F1b refuses to authorize a send if the amount differs from the obligation's.
  • The proxy refuses to admit a call whose amount differs (EXE-18).

CNF-08 negative control: a vaep_app write of a different amount must fail.

EXE-17 S Append authority and role separation.

Who may append each record kind.

Record kinds Appended only by
admitted gateway (gateway credential)
pre_send, sent dispatcher (worker credential), each naming its own fencing token
open_lookup reconciler (worker credential)
transmission adapter proxy (proxy credential)
invocation_committed, void, send_revoked, refused, continued, cancelled, lookup_closed, succeeded, failed, every request_* record, dispatch_frozen, dispatch_unfrozen control plane

Any other appender is refused (CNF-08 negative control). A worker therefore cannot release capacity, revoke a send or record an outcome: it can only move an effect toward sent, or open a lookup.

Three distinct roles for every terminal transition, and for every move of an obligation to confirmed or released:

  • Evidence producer. The adapter (provider responses) or the recovery authority (human attestation). It may only submit evidence or a decision request.
  • Decision-maker. The platform policy, or the recovery authority where §5.4 requires one (F3, F3b, F3c, F15, F16, F17, F18).
  • Durable transition executor. The control plane only. It verifies the evidence, conditionally appends the record naming that evidence, and only then applies the database state change (EFS-04).

No adapter, worker or recovery-authority credential may append a terminal record, write a terminal effect state, or write a confirmed or released obligation. A terminal record always names the evidence record it rests on: a provider response hash, a lookup response hash, or a human attestation.

EXE-18 S The proxy admits each effect for transmission at most once.

Admission conditions. The adapter proxy (§11.2) admits an outbound provider call only when all of the following hold:

  • the call carries a provider idempotency key derived from an effect_id whose effective head is sent;
  • that sent record's fencing token has a live lease;
  • the call's amount and currency equal the sent record's;
  • dispatch is not frozen for the application (EXE-11).

How admission works. Admission is the proxy's conditional append of a transmission record naming that sent record. The append succeeds only if sent is still the effective head.

  • On success, the proxy forwards the call exactly once. It never retries a forwarded call: transport-level retries in the proxy and its HTTP client are disabled, and a retry would be a second transmission.

  • On failure, it refuses and does not forward.

  • If it cannot determine whether its append succeeded (ledger unavailable, timeout, ambiguous response), it does not forward. Either outcome is then safe:

    • if the append failed, the head is still sent, and F39 later revokes it;
    • if the append succeeded, the head is transmission, and the effect is treated as possibly sent (F7).

    The proxy never forwards, and never admits again, on the basis of uncertainty.

Rules.

  • The transmission record is the only way into a transmission head.
  • From transmission, only the control plane (terminals, lookup_closed) or the reconciler (open_lookup) may append.
  • Cancellation and refusal are not permitted from transmission.
  • Because EXE-12 permits no path from transmission back to pre_send, each effect_id has at most one transmission record, ever.

Limit of the guarantee. This guarantees at most one admitted transmission per effect. It does not guarantee that the provider executed the effect at most once (GUA-03).

CNF-08 negative controls:

  • with the conditional append removed, two concurrent calls with identical arguments must be shown to produce two outbound transmissions;
  • with forwarding-on-uncertainty enabled, a fault-injected append timeout must be shown to produce an unrecorded transmission.

EXE-19 S Request creation, commit repair and quarantine.

1. Before commit. The transaction that creates a business request (CON-17) obtains its durable transaction identity. This is an identifier whose commit status the database can later report; the installation's [D] evidence names the mechanism (in PostgreSQL, for example, pg_current_xact_id() with pg_xact_status()).

The control plane then appends request_created, carrying:

  • the request ID and its contract revision;
  • a creation sequence number, monotonic and assigned by the control plane;
  • the transaction identity;
  • the canonical reconstruction payload: a JCS-canonical, SHA-256 content-addressed record of every immutable normative field of the request entity, its declared created state and uniqueness fields, and for a money request the obligation fields (amount, currency, bound_owner, tenant_id).

The transaction commits only after request_created is durable. If the append fails, the transaction aborts.

2. After commit. The control plane appends request_committed, naming the same transaction identity and carrying the commit watermark.

Request IDs and retries. A request ID is scoped to one database attempt. When the creating transaction aborts and is retried (for example under CON-21 step 5), the retry mints a new request ID; the aborted attempt's request_created resolves to request_aborted (rule c). Duplicate creation across attempts is prevented by the creating action's own identity (EXE-02), not by the request ID.

3. Repair scan. On every control-plane start, and at least every minute, the scan examines every request_created that has none of the resolution records request_committed, request_aborted, request_reconstructed or request_voided.

Read order. For each such record, the scan reads the transaction status before it reads the request row. A commit that the status reports is then visible to the row read, so "committed with no matching row" occurs only when the row is genuinely absent (for example after a restore). Reading in the other order can quarantine a request that committed between the two reads.

It applies the first rule that matches:

# Condition Action
a The database contains the request row, with a matching payload hash Append request_committed.
b An invocation_committed record names the request Append request_committed, citing that record. The row is re-created per EXE-11 step 2 if it is missing.
c The database reports the transaction identity as aborted (not used after a restore for transactions after the restore point) Append request_aborted.
d The database reports the transaction as in progress Wait.
e Otherwise: status unavailable, or the transaction lies after the restore point of a restore Append request_quarantined. The control plane (or, during restore, the restore job) creates the request row in quarantined (CON-24) from the payload, with its obligation requested and quarantined = true.

4. Resolution. A quarantined request is resolved only by a recovery-authority decision, citing evidence, which the control plane executes:

  • request_reconstructed — evidence that the request was genuinely created. The row moves to its declared created state, and the obligation stays requested with quarantined = false.
  • request_voided — an attestation of non-creation. The row moves to its declared withdrawn state, and the obligation is released.

Database transaction status read from an abandoned timeline is never evidence.

5. Never frees capacity. A quarantined request counts against uniqueness and against its bound at full amount until it is resolved. It is never silently discarded, and never reconstructed from partial data. Unresolved quarantine is reported as drift (RUN-03).

6. Completeness frontier. After a restore, dispatch does not resume (EXE-11 step 7) until every request_created record that meets either condition below has a resolution record or is represented in the database as quarantined:

  • it lies after the restore point;
  • it was outstanding at the restore point.

EXE-11 S Restores never re-send effects

After RP-4, or any restore or replication path that applies data with triggers disabled, the steps below run in order.

Step 1 — Freeze. The control plane appends dispatch_frozen for the application.

  • action.invoke returns E_RESTORE_RECONCILING.
  • No F1 may run.
  • The proxy refuses every admission for the application (EXE-18), including under leases issued before the restore.

Step 2 — Requests.

  • For every request_committed whose request row is missing, the row is re-created from its canonical reconstruction payload in its declared created state, with its obligation requested.
  • For every request_withdrawn, the entity is moved to its withdrawn state (actor platform, event restore), and the obligation is released.
  • request_reconstructed and request_voided records are replayed as in EXE-19 step 4.
  • Every unresolved request_created is classified by the EXE-19 repair scan.

Step 3 — Invocations. For every invocation_committed after the restore point:

  • The invocation row is re-created as committed, or an admitted row is CASed to committed, under a fresh fencing token.
  • Its business request is moved to the pending state the committed action declared (actor platform, event restore), so no agent can re-execute it.
  • Its obligation is moved requested → reserved. This is the only obligation write the restore job makes, and it is forward in the obligation's order.
  • Every effect the committed action declared is re-created in pending_dispatch, under its deterministic effect_id (EXE-04), with its outbox row.

A boundary-10 fixture asserts that the re-created ID equals the ledger's.

Step 4 — Normalize effect heads. For every effect_id with any ledger record, the control plane acts under a fresh fencing token:

  • it appends void for every effective head pre_send;
  • it appends send_revoked for every effective head sent.

No such send can still be admitted: the proxy is frozen, and its append against those heads now fails.

Step 5 — Replay effects. Every effect row is moved to the state its effective head maps to, by the ledger-replay transition (EFS-07). Obligations and reservations follow EFS-04 and EXE-07. A terminal row that disagrees with a terminal head is drift and keeps dispatch frozen.

Step 6 — Validate. Before dispatch is unfrozen, the restore job checks that:

  • every obligation's amount, currency, bound_owner, tenant_id and state match the ledger records for its request;
  • every CON-21 aggregate, including quarantined obligations, is within its bound;
  • every uniqueness constraint holds.

The EFF-08 invariant sweep runs. Any mismatch is drift and keeps dispatch frozen.

Step 7 — Resume. The control plane appends dispatch_unfrozen only when both hold:

  • steps 2–6 are complete, including the EXE-19 completeness frontier;
  • every effect that step 5 placed in outcome_unknown is terminal or reconciliation_required.

Reconciliation of a transmission record uses the provider idempotency key the ledger holds. Where the provider offers no lookup by that key and no provider reference exists, the effect goes directly to reconciliation_required (F14) for human resolution. It is never re-dispatched to find out.

#5.4 Effect lifecycle

EFS-01 S Exhaustive. The effect lifecycle below, mirrored in protocol/effect-lifecycle.json, is exhaustive. That includes every LR pair generated by EFS-07. Any other transition is rejected with E_LIFECYCLE_CONFLICT and logged as a security event.

Retired transition IDs are never reused: F1e, F2c, F2d, F13 and F19–F38. F19–F38 are replaced by the LR family.

States.

State Kind Effective head(s) Meaning Counts against caps
pending_dispatch initial none, continued, send_revoked Created in the business transaction with its outbox row (EXE-03); not authorized for sending. yes
pre_send active pre_send A dispatcher holds a fenced lease; the send is not yet authorized. yes
dispatching active sent or transmission Head sent: send authorized, not admitted by the proxy, provably not transmitted. Head transmission: admitted; the provider call may be in flight. yes
provider_pending active transmission The provider accepted the request; the final result is not yet known. yes
outcome_unknown active transmission or open_lookup The request may have executed; automated reconciliation is running. yes
reconciliation_required active lookup_closed Automated reconciliation is exhausted; a human decision is required. yes
blocked active refused Provably never transmitted; dispatch refused by revocation or policy denial (safety holds defer instead, EFS-06). yes
succeeded terminal succeeded The provider confirmed execution. yes
failed terminal failed The provider confirmed non-execution, or a human attested it. no
cancelled terminal cancelled Never transmitted; cancelled by the recovery authority. no

Transitions.

ID From To Event Decided by / executed by Guard and ledger record
F1 pending_dispatch pre_send lease acquired dispatcher Fencing token valid (EXE-09); dispatch not frozen; no deferral (EFS-06); unvoided admitted and invocation_committed records exist for this invocation; (invocation, effect name) declared by the committed action (EXE-15); effective head is none, continued or send_revoked; pre_send appended naming it, carrying the token and amount.
F1b pre_send dispatching send authorized dispatcher Effective head is this dispatcher's own pre_send; amount equals the obligation's (EXE-16); authorization recheck passes (AUTH-22); sent appended naming the pre_send. An append failure means the head moved, and the dispatcher stops. sent authorizes; only the proxy's transmission admits (EXE-18).
F1c pre_send pending_dispatch lease lost before send control plane Effective head is a pre_send whose token is not the row's current token, or whose lease expired; void appended naming it. Obligation and reservation unchanged (CNF-09 boundary 12).
F1d pending_dispatch pending_dispatch orphan intent voided control plane A pre_send head exists under a token that is not the row's current one (crash between ledger append and row CAS); void appended naming it; audited self-transition.
F2 pending_dispatch blocked dispatch refused platform policy / control plane Revocation or policy denial only; refused appended naming the effective head (none, continued or send_revoked) before the row write.
F2b pre_send blocked dispatch refused platform policy / control plane As F2, naming the pre_send head.
F2e dispatching blocked dispatch refused before admission platform policy / control plane As F2, naming a sent head; succeeds only if the proxy has not appended transmission.
F3 pending_dispatch cancelled cancellation decided recovery_authority / control plane cancelled appended naming the effective head (none, continued or send_revoked) before the row write; the row records that record ID (EXE-13).
F3b pre_send cancelled cancellation decided recovery_authority / control plane As F3, naming the pre_send head; any dispatcher append naming that pre_send then fails.
F3c dispatching cancelled cancellation decided before admission recovery_authority / control plane As F3, naming a sent head; succeeds only if the proxy has not appended transmission, whose append then fails.
F39 dispatching pending_dispatch unused send authorization revoked control plane Effective head is sent, and its token's lease has expired or is not the row's current token; send_revoked appended naming it; the proxy can no longer admit under it. Obligation and reservation unchanged.
F4 dispatching succeeded provider definitive success adapter evidence / control plane Effective head transmission; provider response stored by hash; control plane verifies it and appends succeeded naming it (EXE-17).
F5 dispatching failed provider definitive rejection adapter evidence / control plane Effective head transmission; response class is in non_executing_responses (EXE-04); control plane verifies it and appends failed. Any other response takes F6 or F7.
F6 dispatching provider_pending provider accepted (async) adapter Effective head transmission; provider reference stored. Row-only refinement.
F7 dispatching outcome_unknown timeout, transport error, crash or lease loss adapter report / control plane Effective head transmission: any case where the request may have been sent. Row-only refinement.
F8 provider_pending succeeded provider final success adapter evidence / control plane Authenticated callback or lookup; terminal appended naming the effective head (EXE-17).
F9 provider_pending failed provider final failure adapter evidence / control plane Authenticated callback or lookup whose class is in non_executing_responses; terminal appended naming the effective head. A weaker failure signal leaves the effect provider_pending until F10.
F10 provider_pending outcome_unknown provider_pending_deadline exceeded control plane Row-only refinement.
F11 outcome_unknown succeeded reconciliation confirms execution reconciler evidence / control plane open_lookup head (EXE-05); lookup evidence stored (EFS-02); succeeded appended naming it. A provider callback may also satisfy this, naming the current effective head.
F12 outcome_unknown failed reconciliation confirms non-execution reconciler evidence / control plane open_lookup head, accepted only if the sent token has no live lease (EXE-05); response class is in non_executing_responses and the adapter declares lookup_finality: true; failed appended naming the open_lookup. Otherwise the effect stays outcome_unknown until F14.
F14 outcome_unknown reconciliation_required reconciliation exhausted control plane reconciliation_deadline exceeded, lookup inconclusive, or no lookup possible; lookup_closed appended naming the effective head.
F15 reconciliation_required succeeded human attestation recovery_authority (R3 approver role) / control plane Evidence of execution recorded; succeeded appended naming lookup_closed and the attestation.
F16 reconciliation_required failed human attestation recovery_authority (R3 approver role) / control plane Evidence of non-execution recorded; failed appended naming lookup_closed and the attestation.
F17 blocked pending_dispatch continuation decided recovery_authority / control plane continued appended naming the refused head; effect re-bound to the deciding principal's authority; F1b then rechecks against that authority (AUTH-23).
F18 blocked cancelled cancellation decided recovery_authority / control plane cancelled appended naming the refused head, before the row write.
LR any non-terminal mapped state ledger replay control plane EFS-07.

EFS-02 S Evidence required.

  • Evidence for verdicts. outcome_unknown and reconciliation_required move to succeeded or failed only with a stored evidence record: a provider or lookup response (by hash), or a human attestation with evidence. A timeout, a missing callback or the passage of time is never evidence.
  • Proof of non-transmission. The only proof that an effect was never transmitted is an effect chain containing no transmission record. blocked and cancelled are reachable only from states whose effective head precedes transmission. The build check on protocol/effect-lifecycle.json rejects any other source state.
  • Justification. Each such transition is justified by a refused or cancelled ledger record, never by a row-level decision.

EFS-03 S What counts against caps. Every state except failed and cancelled counts against CON-21 invariants and ledger caps.

EFS-04 S Outcome transactions. In each case, the ledger's terminal record is appended first, then the reservation transition in the budget ledger (EXE-07). Then, in one application-database transaction, the platform applies:

  • On succeeded: the effect's succeeded state, the obligation's confirmed state and the entity's confirms_effect transition (CON-19). The reservation moves to committed.
  • On failed: the effect's failed state, the obligation's released state and on_effect_failed (CON-20). The reservation is released.
  • On cancelled: the effect's cancelled state, the obligation's released state and on_effect_cancelled (CON-20). The reservation is released.

No transaction spans the two clusters. A crash between the ledger appends and the application-database transaction is repaired on recovery: the reservation append is completed if missing, and the row is moved by the LR transition (EFS-07; CNF-09 boundary 11).

EFS-05 S Deadlines. Each adapter declares:

  • provider_pending_deadline (default 24 h);
  • reconciliation_deadline (default 4 h after entering outcome_unknown).

Fixtures drive both with injected time.

EFS-06 S Deferral is not blocking. A Held cohort (REV-03) or the EFF-02 canary rule withholds dispatch leases. The effect stays pending_dispatch with a recorded deferred_reason, its reservation stays reserved, and the platform clears the deferral when the condition lifts.

blocked is reserved for revocation and policy denial, which need a recovery-authority decision. This preserves rc2 EFF-04's "pause outbox dispatch" without creating per-effect human work.

EFS-07 S Ledger replay (LR). The control plane moves an effect row whose state is inconsistent with its effective head to the state the head maps to. Obligations and reservations follow EFS-04 and EXE-07.

Mapping from effective head to row state.

Effective head Consistent row states Mapped state
none, continued, send_revoked pending_dispatch pending_dispatch
refused blocked blocked
transmission dispatching, provider_pending, outcome_unknown outcome_unknown
open_lookup outcome_unknown outcome_unknown
lookup_closed reconciliation_required reconciliation_required
succeeded / failed / cancelled the same terminal the same terminal

pre_send and sent heads are never replayed. They are first voided or revoked: by EXE-11 step 4, or by F1c and F39.

When LR runs. Only in these cases:

  • during EXE-11, with dispatch frozen;
  • in the crash-repair scan, for a row lagging a head appended by the ledger-first rule (for example CNF-09 boundary 11).

Guards. An LR transition never moves a terminal row; a terminal row that disagrees with the head is drift. Its evidence is the head record itself.

Generated pairs. protocol/effect-lifecycle.json expands LR into one entry per (from, to) pair, with ID LR:<from>:<to>. A pair (S, map(h)) is generated only when some head consistent with row state S can reach head h under the EXE-12 grammar, with void reverting the head. So no generated pair moves a row from a state whose head follows transmission to blocked, cancelled or pending_dispatch, and every generated pair passes the EFS-02 build check.


#6. Change Request lifecycle (replaces §8 lead paragraph; amends LC-01, LC-03, LC-04)

LC-08 S The state machine is normative. The lifecycle in protocol/cr-lifecycle.json is normative. Each transition names its event, actor class, guard and audit record. Any transition not listed is rejected with E_LIFECYCLE_CONFLICT and logged as a security event (LC-01).

The successful path has seven states: Draft, Validated, Verifying, Verified, Approved, RollingOut, Live. Suspended interrupts a rollout. Rejected, Withdrawn, Superseded and Reverted are terminal for that CR identity.

States.

State Kind Meaning
Draft transient Recorded by cr.draft; validation pending.
Validated path Contract-valid against the current approved base.
Verifying path Submitted; V1–V10 running in the Verifier's trust domain.
Verified path All checks passed; signed evidence bundle exists; 72 h expiry running.
Approved path Approvals required by AUTH-21 recorded against this bundle and manifest.
RollingOut path The Executor is driving cohorts to the target revision.
Live terminal-success LC-06 convergence established in every environment and cohort.
Suspended interruption Rollout stopped for safety; awaits a human recovery or continuation decision.
ReVerifying interruption Re-verification of a Suspended CR against its unchanged manifest; its only exits return to Suspended, or lead to Superseded.
Rejected terminal Failed validation, verification, approval or artifact check. Successor CR required.
Withdrawn terminal Withdrawn by author or owner, or by objective revocation, before rollout.
Superseded terminal Approved base moved before rollout, or reconciled by a successor; evidence void. Successor CR required.
Reverted terminal Recovery returned every cohort to the base revision.

Transitions.

ID From To Event Actor Guard
T1 Draft Validated validation passed platform Contract schema valid; CON-01..13 and CR-01..08 pass (the V1 check set, run by the Change service, not the Verifier); base == approved, or base == the target of a Suspended CR that this CR declares reconciles: (LC-16)
T2 Draft Rejected validation failed platform Any blocking finding, including E_STALE_BASE
T3 Validated Verifying cr.submit author submission_key unused or same draft; objective active with CR budget (AUTH-11); no escalation pending (LC-22); for R2+: no open drift, mutation block or quarantined test on affected entities (RUN-04, VER-04, VER-05)
T4 Verifying Verified verification passed verifier V1–V10 pass; bundle signed and bound to manifest (ART-02)
T5 Verifying Rejected verification failed verifier Any required check failed
T6 Verified Approved approvals complete approver | platform AUTH-20/21 satisfied; evidence unexpired; approvals bind bundle + manifest. platform may fire T6 only when the effective approval class (AUTH-21, recomputed at the gate) is automated
T7 Verified Rejected approval denied approver A required approver denies
T8 Verified Validated evidence expired or signature invalidated platform 72 h after Verified (LC-14), or signing key revoked (IDN-09)
T9 Approved Validated evidence expired or signature invalidated platform As T8; recorded approvals void
T10 Approved RollingOut deployment started executor | recovery_authority base == approved, or the CR declares reconciles: a Suspended CR whose target is its base (LC-16); otherwise refused with E_STALE_BASE and T24 follows. ART-03 checks pass; no overlapping CR in RollingOut, Suspended or ReVerifying (LC-05). The one exception is the Suspended CR this CR declares reconciles:: then the recovery authority is the actor, and every cohort of the reconciled CR must have observed == its target (REV-02: at most base and target may run); otherwise the reconciling CR waits at Approved. No Held cohort and no open drift on affected entities; objective active
T11 RollingOut Live convergence established platform LC-06 in every environment and cohort
T12 RollingOut Suspended safety hold executor | monitor Any cohort Held (REV-03); EFF-04 Halt; objective revoked and the CR not re-bound by T33; or a signing key of its evidence or approval revoked (IDN-09)
T13 RollingOut Reverted certified recovery complete executor Certified matrix row (EFF-04); observed == base in all cohorts
T14 Suspended RollingOut continuation decided recovery_authority All cohorts Converged, each Held cohort repaired per LC-19 with its completion evidence recorded. ART-03 checks 2–7 pass against the current bundle for this manifest; a fresh bundle from T27 is acceptable; a check 5–7 mismatch is a security event forcing T15 or T27. The objective is active, or the CR has been re-bound to the recovery authority (LC-20). Authority valid (AUTH-23). If any check fails, the exits are T15 or T27
T15 Suspended Reverted recovery complete recovery_authority Observed == base in all cohorts (LC-16; REV-02 permits no other revision)
T27 Suspended ReVerifying re-verification ordered recovery_authority Same immutable CR and manifest; evidence expired or invalidated; deployed and observed identities preserved
T28 ReVerifying Suspended re-verification finished verifier Either a new bundle bound to the same manifest is recorded, or failure with reasons is recorded. Approvals against the new bundle are recorded while Suspended (LC-20) and gate T14, not T28
T29 ReVerifying Suspended approval denied or objective revoked platform A required approver denies, or the objective is revoked and the CR not re-bound by T33, during re-verification; verification job cancelled
T30 Suspended Superseded reconciled by successor platform A CR declaring reconciles: this CR reached Live (LC-16); its cohorts are now on the successor target
T31 ReVerifying Superseded reconciled by successor platform As T30; evaluated whenever the CR is Suspended or ReVerifying
T32 Suspended Suspended approval recorded approver An AUTH-21 approval against the bundle produced in ReVerifying is recorded (LC-20); audited self-transition
T33 Suspended Suspended re-bound to recovery authority recovery_authority The objective was revoked; the CR is re-bound to the deciding principal's authority (LC-20); audited self-transition
T26 Verifying Validated signature invalidated platform A signing key used in this verification revoked (IDN-09); verification restarts on resubmission
T16 Draft Withdrawn withdraw or objective revoked author | owner | platform –
T17 Validated Withdrawn withdraw or objective revoked author | owner | platform –
T18 Verifying Withdrawn withdraw or objective revoked author | owner | platform Verification job cancelled. A CR that has been RollingOut can never be in Verifying; it re-verifies in ReVerifying
T19 Verified Withdrawn withdraw or objective revoked author | owner | platform –
T20 Approved Withdrawn withdraw or objective revoked author | owner | platform Recorded approvals void
T21 Validated Superseded base moved platform Approved revision != CR base (LC-13), unless the CR declares reconciles: a Suspended CR whose target is its base
T22 Verifying Superseded base moved platform As T21
T23 Verified Superseded base moved platform As T21
T24 Approved Superseded base moved platform As T21
T25 Approved Rejected artifact mismatch executor ART-03 digest or manifest mismatch; rejection reason = integrity_incident (not invalid_content); logged as security event

A transition attempt whose guard fails is rejected with the code that guard names, and the CR stays where it was. For example, cr.submit during open drift returns E_BLOCKED_DRIFT and the CR stays Validated; a later resubmission can succeed.

Actor classes.

  • platform — the Change service;
  • author — the CR's authoring principal;
  • owner — the objective's human owner;
  • verifier;
  • approver — a human, or the AUTH-20 delegate for R2;
  • executor;
  • monitor — the runtime monitor;
  • recovery_authority — per AUTH-23.

LC-09 P rc2 mapping. rc2's lifecycle diagram (p. 15) is captioned "7 states, 2 failure exits," and its prose names only six states. rc3's table above is authoritative for rc3. OPEN-1 records confirmation of the diagram. If the diagram differs, §13 gains an explicit rc2 → rc3 state mapping, and the rc3 table does not change.

LC-10 S Immutability. A CR's normative content is fixed at cr.draft, and its ID is the content hash (IDN-02).

  • Failed validation, verification, approval or artifact checks move it to Rejected with recorded reasons. It is never edited back into Draft.
  • The author may create a successor citing supersedes: <cr_id>. The successor is validated and verified independently.

LC-11 S Withdrawal. The author or objective owner may withdraw a CR with cr.withdraw from Draft, Validated, Verifying, Verified or Approved (T16–T20).

  • Withdrawal voids recorded approvals and cancels any running verification.
  • Once RollingOut begins, withdrawal is rejected. The only paths out are Live or recovery (T12–T15).

LC-22 S Escalation counting (amends LC-07). Every entry into Rejected (T2, T5, T7, T25) by any CR of the objective counts as one rejection. After the third rejection since the objective's last clearance, T3 requires a clearance recorded by the objective's human owner. Each clearance admits exactly one submission and resets the count. Agents cannot record clearances.

LC-23 S Environments and cohorts. An installation declares its environments, each with an ordered list of cohorts. Every cohort is a durable record of (desired revision, deployed revision, observed revision, state). The Executor advances one cohort at a time. A cohort that has not converged within the REV-03 timeout (default 30 minutes) becomes Held. The declaration is part of the installation's [D] evidence; how artifacts reach a cohort is defined by ART-01 to ART-07.

LC-12 S Suspended versus Held. At CR level, interruption is called Suspended. Held refers only to the per-environment/cohort reconciliation state (REV-03).

  • Entry. A CR enters Suspended (T12) when any cohort is Held, on an EFF-04 Halt, or when its objective is revoked during rollout.
  • What is preserved. Suspended preserves the deployed and observed revision identities.
  • Exit. Suspended exits only by:
    • a recovery-authority decision: T14 to continue, T15 to revert to base, or T27 to re-verify; or
    • a reconciling successor reaching Live (T30).
  • ReVerifying. Re-verification happens in ReVerifying. Its only exits are back to Suspended (T28 on completion, T29 on denial or revocation) or to Superseded (T31). So a CR that has been RollingOut can never reach a pre-rollout exit such as Withdrawn, Rejected or Validated, and expired or invalidated evidence never traps a Suspended CR.
  • Serialization. A Suspended CR blocks overlapping CRs at T10, as RollingOut does (LC-05).

LC-13 S Rebase (replaces LC-03). When the approved revision moves past a CR's base before rollout, the CR becomes Superseded (T21–T24) and its evidence is void. A successor is drafted against the new base. A CR's base never changes in place.

LC-14 S Evidence expiry (amends LC-04). Evidence expires 72 hours after Verified, and the CR returns to Validated (T8, T9).

  • Approvals recorded against the expired bundle are void.
  • Re-verification produces a new bundle, and approval must be given again against it (ART-02).
  • Revocation of a key that signed a Live CR's evidence or approval leaves the CR Live (terminal), but raises an incident and is reported as drift (RUN-03), so that a reconciling CR can re-establish evidence.

LC-15 S Objective revocation.

  • Before rollout: the CR is Withdrawn (T16–T20, actor platform).
  • During rollout: the CR is Suspended (T12), and the recovery-decision process of EFF-04 applies.

Revocation never itself authorizes a rollback.

LC-16 S Rollout failure.

  • A certified automatic recovery that converges every cohort to base gives Reverted (T13).
  • Otherwise the CR is Suspended (T12).

The recovery revision is always the CR's base. REV-02 allows at most the base and target app revisions to run at once. So while a CR is Suspended with cohorts on both, no other CR can deploy and the approved revision cannot move.

Recovering to a different revision. A recovery that needs a different revision is not a revert. Instead:

  1. A reconciling CR declaring reconciles: <this CR> is drafted with base = this CR's target.
  2. For such a CR, T1 and T21 accept that base in place of approved.
  3. T10 admits it under recovery authority while this CR stays Suspended. This is the one exception to LC-05.
  4. When the reconciling CR reaches Live, approved advances to its target, and this CR becomes Superseded (T30).

A Reverted CR never advances the approved revision. Live is reached only through LC-06.

LC-17 S Concurrency. Every transition is a compare-and-swap on lifecycle_version. The losing actor receives E_LIFECYCLE_CONFLICT with after_reread.

LC-18 S Agent visibility. cr.status returns the state, lifecycle_version and permitted_next_actions for the calling principal.

  • permitted_next_actions is exactly the set of transitions in protocol/cr-lifecycle.json that meet all three conditions:
    • the principal holds the transition's actor class;
    • its guard currently holds;
    • the principal may invoke it through an MCP tool.
  • Transitions whose actor is recovery_authority, a non-delegated approver, or platform, and that have no corresponding tool (MCP-14), are omitted. They are reported separately as external_decisions_required when relevant.

Agents act only on permitted_next_actions.

LC-19 S Repairing a Held cohort. A cohort leaves Held only by one of:

  • (a) a certified automatic recovery step completing with observed == base for that cohort;
  • (b) a recovery-authority continuation step completing with observed == target;
  • (c) a recovery-authority decision to revert the whole CR (T15).

Each step writes a completion record naming the cohort, the before and after revisions, and the fingerprint evidence (REV-01). T14 requires such a record for every cohort that was Held.

LC-20 S Approvals and re-binding while Suspended.

  • Approvals required by AUTH-21 against a bundle produced in ReVerifying are recorded while the CR is Suspended, by the approver actor, as the audited self-transition T32. MCP-14 is unchanged: no tool records them.
  • The recovery authority may re-bind a Suspended CR whose objective was revoked to its own authority (T33), as F17 does for effects. T14 then proceeds without T12 re-firing on revocation.

#7. MCP interface (amends §17)

#7.1 Envelope and errors

MCP-05 S Schemas. Every tool has normative input and output JSON Schemas at mcp/<tool>.input.schema.json and mcp/<tool>.output.schema.json. Objects are closed (additionalProperties: false). Unknown fields are rejected with E_VALIDATION_FAILED.

Extension keys are the one exception. An extension key is any key beginning with x- (GOV-02). It is:

  • accepted, but never validated;
  • never stored in a normative artifact;
  • never read by an authorization or execution decision.

A minor protocol version may add optional fields only. A client that does not know a field receives it under its own name and may ignore it. These three rules are the single definition that MCP-12 and GOV-02 refer to.

MCP-06 S Response envelope. Every response has this shape:

{ "protocol_version": "1.0.0-rc3",
  "request_id": "<uuid>",
  "status": "success | accepted | rejected | failed | indeterminate",
  "result": {},
  "error": null }
status Meaning execution_status
success Completed synchronously; result present succeeded, or n/a for reads
accepted Durable request admitted; outcome via cr.status or invocation.status not_started or in_progress
rejected Refused before any business execution not_started only
failed Admitted, then ended with every effect terminal failed_without_effect, completed_external_failed or partially_effected
indeterminate Final outcome not established in_progress or unknown

Rules:

  • request_id is for correlation only and is never an idempotency key.
  • indeterminate MAY carry error with execution_status in {in_progress, unknown}; result then carries invocation_id. No other status carries an error with those execution statuses.
  • On rejected or failed, result MAY carry the IDs of durable records created (for example the draft_id of a Rejected draft). Otherwise it is null.
  • Failures before a tool call. Authentication and transport failures (AUTH-01, AUTH-02, AUTH-12, AUTH-14 to AUTH-17) are detected before any tool runs. They are returned at the transport layer: HTTP 401 with WWW-Authenticate: DPoP (and DPoP-Nonce when a nonce is required), or HTTP 503 for E_INTERNAL_UNAVAILABLE. The body is a JSON-RPC error whose data is the complete envelope above, with status: rejected.

MCP-07 S Error object. The error object contains:

  • code, requirement_id, message;
  • path (JSON Pointer);
  • retry_class, execution_status;
  • findings[], where each finding has code, requirement_id, path, message, and severity of error or warning;
  • details.

cr.draft returns every validation finding in one response. The top-level code is E_VALIDATION_FAILED whenever any finding has severity error.

MCP-08 S Pinned pagination.

  • contract.get resolves exactly one immutable revision. The literal approved resolves on the first page.
  • Every page returns revision, items, next_cursor and complete.
  • Cursors are bound to the revision, slice and authorization scope, and never advance to a newer revision. An invalid cursor returns E_CURSOR_INVALID.
  • On later pages, revision may be approved or the revision ID the first page resolved; either way the cursor's bound revision is served. Any other value returns E_CURSOR_INVALID.

MCP-09 S Content-addressed drafts. cr.draft returns a draft ID equal to the CR's content hash, so identical drafts get identical IDs. It also returns:

  • the computed affected set;
  • the computed risk and the risk-policy version;
  • the findings;
  • the base revision;
  • the required approval class.

Lifecycle, approvals, evidence and execution events are separate records that reference the immutable CR.

  • Drafters. Because the ID is the content hash, the author is not part of the CR's identity. The platform records every principal that drafts identical content as a drafter of that CR. No drafter, and no principal in a drafter's delegation chain, may record an approval for the CR (AUTH-03, AUTH-20). LC-07 counts rejections per objective; identical content implies the same objective, so recording several drafters does not change that count.
  • Content findings and call findings. A finding that depends only on the CR's content and base (validation, computed risk, affected set) belongs to the CR and decides T1 or T2. A finding that depends on the drafting principal's grant (for example E_RISK_EXCEEDS_GRANT, E_SCOPE_DENIED, E_OUT_OF_OBJECTIVE) belongs to that call only: the call is answered rejected, the principal is not recorded as a drafter, and no CR record is created or changed. So no principal can make content Rejected for others because of its own grant.
  • Approval class is a snapshot. The approval class cr.draft returns is computed at draft time. The approval gate recomputes the effective requirement (AUTH-21) from the facts current when approval is sought, and that recomputed class governs.

MCP-10 S Invocation input. action.invoke requires:

  • action, environment, resource scope and typed inputs;
  • business_request_id (E2/E3) or idempotency_key (others);
  • expected_revision.

The gateway rejects an invocation outside the grant's environment or resource scope.

MCP-11 S Durable status. Invocation status is retrievable independently of the original request, by invocation_id or by (action, key). It returns the §5.3 invocation state, execution_status, and per-effect states, with high-PII fields redacted.

MCP-12 S Versioning.

  • Every request and response carries protocol_version.
  • A minor version never changes the meaning of an existing field.
  • A server rejects an unsupported major version (E_PROTOCOL_VERSION).
  • Pre-release versions are mutually incompatible: a server accepts exactly the pre-release it implements (for example 1.0.0-rc3) and rejects every other pre-release of the same major with E_PROTOCOL_VERSION. Released versions within a major remain compatible.
  • In MCP, protocol_version is a required argument of every tool.
  • Clients discover features through MCP-13, never by parsing version strings.

MCP-13 S Discovery. Tools and their input schemas are exposed through standard MCP tool discovery. A capability descriptor (protocol/capabilities.schema.json) names the supported schema versions, the error-registry version, the CR-lifecycle version and the effect-lifecycle version.

MCP-14 S What no tool does (amends MCP-01). No tool does any of the following:

  • approve, deploy, roll back, or continue or revert a Suspended CR;
  • attest an effect outcome;
  • cancel or continue a blocked effect;
  • resolve a quarantined request.

Those are gate, human or recovery-authority decisions. cr.withdraw is permitted.

#7.2 Tools (ten; replaces the §17 table)

Tool Scope Required input Returns Possible status
contract.get read:contract revision (ID or approved), selector, page_size, cursor revision, items, next_cursor, complete success, rejected
contract.explain read:contract revision, element_id Ordered CR provenance chain with evidence references (AUD-05) success, rejected
cr.draft propose objective, base, intent, ops, expected_behavior, migration, recovery; optional affected, risk and reconciles (the ID of a Suspended CR, LC-16; part of the hashed content) Draft ID, computed affected set, risk, risk-policy version, findings, required approval class, lifecycle state success, rejected
cr.plan propose draft_id Implementation plan and migration plan with artifact digests, compatibility analysis, effect classification, recovery matrix row success, rejected
cr.submit propose draft_id, submission_key Lifecycle state (Verifying) and lifecycle_version accepted, rejected
cr.withdraw propose cr_id, lifecycle_version, reason Lifecycle state (Withdrawn) success, rejected
cr.status read:cr cr_id State, lifecycle_version, base and target, gate results, evidence and manifest references, approval requirements and status, reconciliation status, blocking reasons, permitted_next_actions, external_decisions_required success, rejected
action.invoke act:<action> Per MCP-10 invocation_id, invocation state, execution_status success, accepted, rejected, failed, indeterminate
invocation.status act:<action> of the original invocation, or read:runtime invocation_id, or action + key Per MCP-11 success, rejected
incident.get read:runtime incident_id or authorized filters Incident state, affected revisions and resources, drift findings (including quarantined requests), remediation references success, rejected

Further rules:

  • Repeating cr.submit with the same submission_key and draft returns the same result. Reusing the key with a different draft is rejected (E_IDEMPOTENCY_CONFLICT).
  • cr.withdraw is a compare-and-swap on lifecycle_version.
  • No tool returns hidden-oracle inputs or expected outputs (VER-06).
  • Creating a business request is an ordinary action.invoke of the declared creating action (CON-17). It needs no extra tool.

#8. Error registry

ERR-01 S Coverage. Every rejectable normative requirement maps to a code below, or to E_VALIDATION_FAILED with a finding that names the requirement. The registry is protocol/errors.json.

ERR-02 P Stable meaning. A code's meaning never changes within a major protocol version.

ERR-03 S Retry class from durable state. The registry gives each code a default retry_class, but the server derives the returned value from durable state. For example:

  • E_INVARIANT_VIOLATION returns after_reconciliation when unresolved or quarantined obligations hold the amount.
  • E_BUDGET_EXHAUSTED returns after_authorization with human_required only when committed plus held reservations alone exceed the cap.
  • E_BUSINESS_REQUEST_STATE returns after_reconciliation for a quarantined request.

A network timeout is never reported as failed_without_effect.

ERR-04 S Approval errors. An error that requires human approval names the approval class. It never names approvers or private approval channels.

ERR-05 S No leaks. Error messages and details never contain secrets, unredacted pii: high values, hidden-oracle content, or the existence of resources the caller cannot see. A request for a resource that does not exist, and a request for one the caller may not see, return the identical response: E_NOT_FOUND with the same message.

Retry classes.

retry_class The agent must
never Never resend: the identical request can never succeed.
after_revision Change the request content (new draft, corrected input), then send.
after_reread Re-fetch current state (cr.status, contract.get, invocation.status), then decide.
new_proof Resend with a fresh DPoP proof, using any nonce the error returned.
after_authorization Obtain a new or wider grant, or a human decision. Never retry under the same authority.
after_reverification Wait for the CR to pass verification again; this cannot succeed before then.
same_idempotency_key Query status, or resend with the SAME key. Never mint a new key.
after_reconciliation Wait until reconciliation resolves the named effect, request or cohort.
later Retry with backoff, keeping the same key: this is a transient platform condition.

Codes.

Code Req. Default retry execution_status Human Meaning
E_GRANT_MISSING AUTH-01 after_authorization not_started – No grant presented.
E_GRANT_EXPIRED AUTH-15 after_authorization not_started – Grant expired.
E_GRANT_INVALID AUTH-01 after_authorization not_started – Token presented but invalid: malformed, forged, signed by an untrusted issuer, lifetime above 15 minutes, or a res entry outside the AUTH-18 grammar.
E_REVOKED AUTH-22 after_authorization not_started, in_progress, failed_without_effect yes Grant, objective, principal or key revoked. A revoked objective needs a new human-signed objective, not a new grant.
E_DPOP_INVALID AUTH-16 new_proof not_started – Proof does not match method, URI, token hash or clock window.
E_DPOP_NONCE AUTH-16 new_proof not_started – Server nonce required or stale; the response carries a new nonce.
E_DPOP_REPLAY AUTH-16 new_proof not_started – Proof jti already accepted.
E_AUDIENCE AUTH-14 never not_started – Token presented to a service other than its aud.
E_SCOPE_DENIED AUTH-18 after_authorization not_started – Grant lacks the scope this tool requires.
E_OUT_OF_OBJECTIVE AUTH-07 after_revision not_started – CR touches entities outside the objective.
E_DELEGATION_WIDENS AUTH-04 after_authorization not_started – Delegation hop widens scope or exceeds depth 2.
E_FORBIDDEN_COMPOSITION AUTH-08 never not_started yes Sequence forbidden within this objective.
E_PRIVILEGED_CHANGE AUTH-09 after_authorization not_started yes Out-of-band human approval required.
E_APPROVAL_REQUIRED AUTH-21 after_authorization not_started yes Required approval missing; details name the approval class only (ERR-04).
E_POLICY_DENIED AUTH-13 after_reread not_started, in_progress, failed_without_effect – Policy denies at admission or at the execution-time recheck.
E_BUDGET_EXHAUSTED AUTH-11 later not_started – Objective ledger cannot reserve the cost now. The server returns after_authorization with human_required when committed plus held alone exceed the cap (ERR-03).
E_VALIDATION_FAILED CR-01 after_revision not_started – Contract or CR validation failed; every finding is listed in error.findings.
E_OP_UNKNOWN CR-08 after_revision not_started – Op not in the closed vocabulary.
E_CR_TOO_LARGE CR-06 after_revision not_started – More than 25 ops or 5 entities.
E_MULTI_OBJECTIVE CR-05 after_revision not_started – CR spans more than one objective.
E_RISK_UNDERSTATED CR-07 after_revision not_started – Declared risk below computed risk.
E_RISK_EXCEEDS_GRANT RSK-03 after_revision not_started – Computed risk above grant risk_max. Split the CR; widening the objective is a human decision.
E_AFFECTED_MISMATCH CR-02 after_revision not_started – Declared affected set differs from computed.
E_STALE_BASE LC-13 after_revision not_started – CR base is no longer the approved revision.
E_INVARIANT_NOT_COMPILABLE CON-06 after_revision not_started – Block invariant cannot compile to class M.
E_IDEMPOTENCY_CONFLICT EXE-02 never not_started – Same idempotency identity, different canonical inputs.
E_INVOCATION_IN_PROGRESS EXE-02 same_idempotency_key not_started, in_progress – Original invocation still executing or not proven non-executed.
E_BUSINESS_REQUEST_DUPLICATE CON-18 never not_started – Business request violates its declared uniqueness key.
E_BUSINESS_REQUEST_STATE CON-17 after_reread not_started, failed_without_effect – Business request is not in an executable state. Returns after_reconciliation if quarantined (ERR-03).
E_INVARIANT_VIOLATION CON-06 never not_started, failed_without_effect – Commit would violate a block invariant. Returns after_reconciliation when unresolved or quarantined obligations hold the amount (ERR-03).
E_MULTIPLE_MONEY_EFFECTS EXE-13 after_revision not_started – An action declares more than one money effect, or a non-money effect that holds a reservation.
E_INTEGRITY_INCIDENT ART-03 never not_started yes Artifact or manifest mismatch detected at T10; the CR is Rejected (T25) with reason integrity_incident; a successor may reuse the plan.
E_REQUEST_RETRY_NOT_PERMITTED CON-20 after_revision not_started – A failed or cancelled business request cannot be re-executed; create a new request.
E_RESTORE_RECONCILING EXE-11 after_reconciliation not_started – Dispatch frozen after a restore until requests and effects are reconciled.
E_EFFECT_OUTCOME_UNKNOWN EXE-05 after_reconciliation unknown – External effect outcome not established.
E_REVISION_MISMATCH MCP-10 after_reread not_started – expected_revision incompatible with the running revision.
E_CURSOR_INVALID MCP-08 after_reread not_started – Cursor invalid, expired or bound to another scope; restart pagination.
E_NOT_FOUND ERR-05 after_reread not_started – No such resource, or the caller may not see it. Both cases return this identical response.
E_LIFECYCLE_CONFLICT LC-17 after_reread not_started – Transition not permitted from the current state or version.
E_CR_TERMINAL LC-10 never not_started – CR is in a terminal state; create a successor.
E_EVIDENCE_EXPIRED LC-14 after_reverification not_started – Evidence older than 72 h.
E_ARTIFACT_MISMATCH ART-03 never not_started yes Artifact or manifest mismatch detected while the CR is Suspended (T14 checks 5–7, or a T28 bundle naming another manifest). Security event; the CR stays Suspended and only T15 or T27 may follow.
E_RECONCILIATION_HELD REV-03 after_reconciliation not_started – Affected cohort is Held.
E_BLOCKED_DRIFT RUN-04 after_reconciliation not_started – Open drift blocks R2+ CRs on these entities.
E_BLOCKED_MUTATION VER-04 later not_started – Mutation kill rate below 70% blocks R2+ CRs.
E_BLOCKED_FLAKY VER-05 later not_started – Quarantined test blocks R2+ CRs on its entities.
E_ESCALATION_REQUIRED LC-22 after_authorization not_started yes Three rejections in this objective since the last clearance; the owner must clear the next submission.
E_ROLLOUT_SERIALIZED LC-05 later not_started – An overlapping CR is RollingOut, Suspended or ReVerifying; this CR waits at Approved.
E_PROTOCOL_VERSION MCP-12 never not_started – Unsupported major protocol version.
E_INTERNAL_UNAVAILABLE AMD-03 later not_started, failed_without_effect, unknown – Required platform dependency unavailable, or serialization retries exhausted (CON-21); failed closed.

Codes marked Human cannot be resolved by the agent. The agent loop ends there.


#9. Risk classification (amends §7.2)

RSK-01 S Deterministic. Risk is a deterministic function of (CR content, base revision, risk-policy version). The risk-policy version is recorded in the plan, the evidence bundle and the approval record.

RSK-02 S Platform computes. The computed class is authoritative. The author may raise it but never lower it (CR-07).

RSK-03 S Formula. Computed risk = the maximum of the floors of every op in the CR and of every applicable modifier. The registry is protocol/risk-floors.json.

Op floors.

Op Floor Note
add_entity R0 New table, no behavior
add_field R0 Optional field; a required field without a default adds the migrate modifier
alter_field R2 Changes existing data shape; narrowing adds the contract modifier
deprecate_field R1 –
remove_field R3 Always a contract migration (CR-04)
add_relation R1 –
add_state R1 –
add_transition R2 Changes reachable behavior of an existing machine
alter_guard R2 –
add_action R1 Modifiers raise it for E3, money or high PII
alter_action R2 –
deprecate_action R2 Removes availability of existing behavior
add_invariant R0 alert / R2 block A new block invariant can reject existing production writes
strengthen_invariant R2 –
weaken_invariant R2 alert / R4 block CON-08
add_policy R2 R4 if widening (RSK-05)
alter_policy R2 R4 if widening (RSK-05)
add_schedule R2 Introduces autonomous recurring execution
add_integration R3 New external surface and dependency
register_escape_hatch R3 R4 with E3 effects or pii: high access (ESC-04)

Modifier floors.

Modifier Floor
E3 (irreversible) effect declared or touched R3
Money movement (any money(currency) effect) R3
Reads or writes a pii: high field R3
Migration class migrate R2
Migration class contract R3
New dependency (lockfile change) R3
Changes an adapter's provider_idempotent, non_executing_responses or lookup_finality declaration R3
Policy widening (RSK-05) R4
Removes, weakens or downgrades a block invariant (CON-08) R4
Changes a CON-21 bounded_by declaration, other than to a stricter bound R4
Disables a trigger or drops a block constraint (DJ-05) R4
Removes a business-request uniqueness declaration, adds a field to its key, or makes its constraint partial beyond the CON-18 normative scoping R4
Escape hatch with E3 effects or pii: high access R4

RSK-04 S Conformance doesn't lower risk. A conformance level never lowers the computed class. Levels govern autonomy, not hazard.

RSK-05 S Widening, defined. A policy change widens if, after the change, any (principal, action, resource, environment) tuple is permitted that was not permitted before.

  • Scope of the test. It is evaluated over the full before/after authorization relation, including principals, resource classes and actions introduced by the CR.
  • New principals and resource classes. A new principal or resource class is widening. Merely copying an existing principal's permission set to a new principal creates newly permitted tuples, and is therefore widening.
  • The delegation exception. It is the only exception, and requires all of:
    • an explicit, already-authorized delegation relationship, in which the new principal is a named delegate of an existing principal;
    • that existing principal's permitted set is a superset of the new principal's;
    • the delegation is itself recorded in the base revision, or in the same CR under AUTH-20 rules.
  • Actions introduced in the same CR. A grant of access to such an action is not widening only if every grantee could already perform the same reads and writes, on the same entities and fields, through actions in the base revision. Otherwise it is widening.

#10. Evidence-to-artifact binding (amends §6, §9, SEC-03)

The safety contract is normative now. Continuous runtime attestation is phased (ART-05).

IDN-10 S New kinds. The IDN-02 kind set adds:

  • mf (deployment manifest);
  • apr (approval record);
  • inv (invocation);
  • eff (effect).

Domain separation applies unchanged.

ART-01 S Deployment manifest. Every production deployment references an immutable manifest (schemas/deployment-manifest.schema.json) containing:

  • the CR ID, and the base and target contract IDs;
  • digests of every executable artifact, the lockfile, the SBOM, the generated migrations, the compiled constraints and triggers, and the policy module;
  • adapter identities and versions, with each adapter's EXE-04 declarations and its conformance_tests: a list of {id, covers, against, result} entries, where covers names the EXE-04 declarations the test exercises and against is provider or fake. Only passing tests with against: provider count toward class M (AUTH-20);
  • the target environment and compatibility constraints;
  • the config_envelope (ART-04).

Secrets appear only as versioned references, never as values.

ART-02 S Binding. The evidence bundle names the manifest ID it verified. An approval record (apr, schemas/approval.schema.json) binds and signs, per IDN-05:

  • the CR ID, evidence bundle ID and manifest ID;
  • the approver, approval-policy version and risk-policy version;
  • the timestamp.

ART-03 S Executor checks before deploy. The Executor verifies all of the following:

  1. the CR is Approved;
  2. the required approvals are valid;
  3. the evidence is unexpired and not invalidated;
  4. signatures and key windows are valid (IDN-07);
  5. the manifest equals the approved manifest;
  6. every artifact matches its digest;
  7. the target environment satisfies the compatibility constraints and the grant.

Any failure blocks deployment. A digest or manifest mismatch also:

  • moves the CR to Rejected (T25), with rejection reason integrity_incident;
  • returns E_INTEGRITY_INCIDENT;
  • is logged as a security event.

The CR is Rejected rather than held, because its evidence no longer describes any deployable artifact set. The reason class lets a successor CR reuse the content and the plan without pretending the incident did not happen.

ART-04 S Configuration envelope. Every configuration key the application reads is declared in the manifest as exactly one of:

  • pinned — its value is committed by hash;

  • ranged — it has a declared range or enumeration, and the evidence bundle records which values V3–V10 ran against. A ranged value is non-material only if either:

    • (a) the Verifier has established and recorded that the relevant behavioral properties are monotonic across the declared range, and both endpoints were verified; or
    • (b) every value that will be used in production is explicitly enumerated and verified.

    Otherwise any change between unverified values is material (ART-07);

  • non-behavioral — it is on an allowlist, for example replica count or autoscaling bounds.

Generated code reads configuration only through a typed accessor generated from the envelope. The accessor has no method for an undeclared key, so such code fails V2. A runtime read outside the accessor is reported as drift (RUN-03).

ART-07 S Material change, testably defined. A change is material if and only if it changes the manifest ID. That includes:

  • any digest;
  • any pinned value;
  • any range;
  • any value outside its declared range;
  • any key moved onto or off the allowlist;
  • any adapter declaration (EXE-04).

A material change requires new verification and approval.

  • Changing an allowlisted key is non-material.
  • Changing a ranged value within its range is non-material only under the conditions of ART-04.
  • A rebuilt artifact whose digest differs is material, even when built from the same source revision.

ART-05 D Runtime attestation (phased).

  • All levels: the REV-01 code-revision attribute MUST equal the manifest's artifact digest. A mismatch is drift (RUN-03).
  • L3: continuous measurement of executables and configuration against the manifest is required.
  • L2: reports MUST label deployments "bound at deploy; not attested at runtime" (CNF-12).

ART-06 D Offline verification (amends SEC-03). A third party with the audit log and public keys can verify the chain: objective → CR → evidence bundle → approval record → manifest → deployed artifact digests → audit record. The check must detect a substituted executable, migration or pinned configuration.


#11. Conformance (amends §18)

CNF-07 S Protocol suite. An installation passes the rc3 protocol suite before claiming rc3 compatibility. The suite covers at least:

  • Tokens and proofs:
    • multi-request token reuse;
    • proof replay, including across replicas, and replay-cache outage;
    • authoring/action scope separation.
  • Identity:
    • concurrent identical invocations;
    • cross-agent retry of one business request;
    • business-request uniqueness;
    • permanent idempotency input binding across abandoned attempts and restore (EXE-02);
    • a second attempt under the same business request from a different agent, at every CNF-09 boundary (at most one logical operation executes).
  • Money and completion:
    • confirms_effect enforcement;
    • pessimistic accounting under 40 concurrent requests;
    • a monetary invariant with confirmed obligations in the sum, with no double count (CON-21);
    • reservation reconciliation;
    • a request withdrawn before invocation (the obligation must release).
  • Dispatch and outcomes:
    • revocation after commit (the blocked state), and revocation racing the proxy admission (F2e);
    • fencing-token rejection;
    • ambiguous provider outcomes;
    • provider finality after lease expiry, with lookup_finality true and false (EXE-05, F12);
    • single-use proxy transmission, and no forwarding on append uncertainty (EXE-18);
    • unused send authorization revoked and re-dispatched exactly once (F39);
    • grammar: no path from transmission to pre_send, refused or cancelled (EXE-12);
    • control-plane-only terminal transitions (EXE-17);
    • revocation discovered in pre_send with the ledger still pre_send (must reach blocked).
  • Lifecycle:
    • pagination under concurrent revision change;
    • submission idempotency;
    • concurrent lifecycle transitions;
    • withdrawal;
    • revocation during rollout;
    • evidence expiry;
    • lease expiry before commit (the abandoned state).
  • Artifacts:
    • artifact substitution;
    • non-monotonic range verification (ART-04);
    • offline chain verification.
  • Restore and repair:
    • restore after dispatch (EXE-11);
    • request-commit repair, quarantine and resolution, including restore with outstanding request_created (EXE-19, CON-24).

CNF-08 S Negative controls. Every security-critical mechanism has a negative control showing that its test fails when the mechanism is removed. At minimum:

  • Authorization: the proof replay cache.
  • Money:
    • the reservation hold rule;
    • the CON-21 invariant;
    • the CON-21 lock: removing the vaep_agg_lock UPDATE overspends under CNF-13;
    • quarantine counting: excluding quarantined obligations overspends after a restore;
    • amount binding (EXE-16).
  • Identity and completion:
    • the business-request uniqueness constraint;
    • the confirms_effect guard;
    • the immutable identity binding (EXE-02);
    • the request reconstruction payload (EXE-19).
  • Database privileges:
    • the vaep_invocation privilege trigger: a vaep_app write of abandoned or of fencing_token must fail;
    • the obligation and effect forward-only triggers: a vaep_app write of released, confirmed or a terminal effect state must fail.
  • Ledger:
    • fencing tokens, and the fenced ledger append: a stale dispatcher's pre_send → sent must fail;
    • head-linked append: an append naming a stale head must fail;
    • append authority: a worker or adapter credential appending failed, or a worker appending transmission, must be refused.
  • Outcomes:
    • the non_executing_responses set: an undeclared response class must not reach failed;
    • the provider-finality requirement: with lookup_finality: false, a not-found lookup must not reach failed.
  • Proxy:
    • the single-use transmission append (EXE-18);
    • no forwarding on append uncertainty (EXE-18).
  • Grammar: inserting an edge from transmission, open_lookup or lookup_closed to pre_send must fail the build check.
  • Artifacts: the Executor digest check.

CNF-09 S Fault injection. The suite injects a crash at each of these durable boundaries:

  1. before the invocation record;
  2. after the invocation record;
  3. after budget reservation;
  4. after the business mutation, before commit;
  5. after commit, before invocation_committed;
  6. after provider success, before acknowledgement;
  7. during reconciliation;
  8. during lifecycle advancement or deployment, in two parts: (8a) effect-lifecycle advancement, between a control-plane ledger append and its row write; (8b) CR-lifecycle advancement and deployment;
  9. after transmission, before any provider response;
  10. a point-in-time restore taken before dispatch, applied after dispatch (EXE-11);
  11. between the ledger's terminal record and the EFS-04 transaction;
  12. between the ledger pre_send append and the row CAS, and between the row CAS and the sent append (dispatcher crash in pre_send). A second dispatcher takes over, and the stale one is woken afterwards and attempts to send. This is repeated after a restore, so that the stale token value could recur;
  13. between the request_created append and the request's database commit, and between commit and request_committed. This is repeated across a restore;
  14. between sent and the proxy's transmission append, racing F39, F2e and F3c;
  15. between the proxy's transmission append and forwarding; during forwarding; and with the append's acknowledgement lost;
  16. lease expiry while a provider request is in flight, with a lookup returning not-found before the request lands.

After each crash, the suite asserts the EFS, EXE and CON-21 invariants.

CNF-13 S Deterministic concurrency schedules. For the CON-21 invariant and lock protocol, the suite runs scripted interleavings, not only load. Each runs under READ COMMITTED, REPEATABLE READ and SERIALIZABLE:

  • two requests whose sum exceeds the bound, interleaved at every pair of statement boundaries;
  • a request interleaved with a decrease of the bound;
  • a request interleaved with a release;
  • a request interleaved with a confirmation.

Each schedule asserts two things: at most the bound is held by non-released obligations, and every successful commit observed every concurrent committed write that increases the aggregate or changes the bound (every lock-taking write). A release or confirmation may go unobserved, because that only makes the check more conservative. Serialization failures must be shown to retry as new transactions. The negative control removes the vaep_agg_lock UPDATE and shows the schedule overspends.

CNF-10 S Interoperability. Two independently implemented clients pass the protocol interoperability fixtures.

CNF-11 D Critical paths. L2 and L3 reports list security-critical, monetary and irreversible-effect paths separately from aggregate coverage.

  • A critical action never qualifies for autonomous execution because overall coverage exceeds 90%.
  • Each critical path itself needs class M mediation and authorization.

CNF-12 P Claim labels. Conformance reports label each of the following separately:

  • protocol conformance;
  • contract conformance;
  • deployment conformance (deploy-bound or runtime-attested);
  • runtime assurance;
  • business-intent attestation.

None is presented as another.


#12. Guarantees (amends §20)

The rc2 guarantees stand. The following clarifications are added.

GUA-02 P Authorization. "Mechanically enforced authorization" means that a request or effect crossing the declared authorization boundary cannot execute without valid authority. It says nothing about whether the objective was wise.

GUA-03 S External effects (M on mediated channels, C1).

  • Admission. Each effect_id is admitted for transmission by the proxy at most once, ever (EXE-18). After a transmission record exists, VAEP never issues another transmission for that effect.
  • Fail closed. The admission limit fails closed on uncertainty.
  • Provider-side count. Provider-side execution count is not guaranteed. Provider-side deduplication is exactly-once only where the adapter's provider contract documents idempotency by the derived key (EXE-06).
  • Admission is not execution. Admission is never equated with provider execution, and outcomes are resolved only by evidence (EFS-02).
  • Restores. A database restore never causes a re-send (EXE-11).

GUA-04 S Confirmed completion (M, C1). No entity is in a confirms_effect state unless that effect is succeeded.

GUA-05 S Bounded money (M, C1, within the stated boundary). Declared monetary bounds (CON-21) count every non-released obligation, including confirmed, held and quarantined ones. Through VAEP-mediated paths, a bound is never exceeded.

The enforcement boundary is:

  • writes through vaep_app or narrower (§16.1);
  • channels under complete mediation (§11.2);
  • restores handled by EXE-11 and EXE-19.

Worker compromise is inside the boundary, for three reasons:

  • EXE-17 limits a worker's appends;
  • EXE-16 binds amounts;
  • EXE-18 makes the proxy refuse any call the ledger has not authorized, and any second transmission.

The claim is class M only for an installation whose conformance evidence includes all of:

  • the deterministic schedules of CNF-13 at all three isolation levels;
  • the §11.2 negative probes;
  • fault-injection boundaries 1–16;
  • for every adapter used by a money effect, its EXE-04 declarations in the manifest digest.

Without that evidence, the claim is class T.

An adapter declaring lookup_finality: false never permits automated release of an obligation from a lookup. Such effects reach reconciliation_required.

GUA-06 P Truthful status. VAEP reports uncertain or partial outcomes as such. It never reports them as success, as failure without effect, or as a completed rollback without evidence.

New non-guarantees:

  • actions taken at a provider outside VAEP;
  • exactly-once execution at the provider, unless documented (EXE-06);
  • runtime attestation below L3 (ART-05);
  • the correctness of a uniqueness: "none" declaration;
  • the correctness of an adapter's EXE-04 declarations against the provider's actual behavior.

GUA-01 applies to every item above.


#13. Release criteria and migration

Freeze checklist. rc3 is frozen only when every item holds:

  1. ERRATUM-1 and ERRATUM-2 are published against rc2, with fixtures.
  2. All schemas in Appendix A are published and pass a mutual-consistency check.
  3. protocol/effect-lifecycle.json is regenerated for revision 13. That means:
    • retired IDs removed;
    • F2e, F3b, F3c and F39 added;
    • LR pairs expanded (EFS-07);
    • the EXE-12 grammar and its build checks encoded.
  4. protocol/risk-floors.json gains the revision 12 modifiers.
  5. protocol/errors.json reflects the revision 12 retry derivations and adds E_GRANT_INVALID, E_NOT_FOUND and E_ROLLOUT_SERIALIZED.
  6. requirements-rc3.tsv lists CON-24, EXE-14, EXE-17, EXE-18, EXE-19, EFS-07, AUTH-24, AUTH-25, LC-22 and LC-23, each with its verification method. 6a. protocol/approval-classes.json and protocol/cr-lifecycle.json are generated from §3.3 and §6, and the identity-chain grammar of EXE-12 is encoded with its build check.
  7. Every table in this document matches its protocol/*.json file (AMD-02), and the freeze reviewer has examined the files, not only the tables.
  8. OPEN-1, OPEN-2 and OPEN-3 are closed.
  9. Every rc3 suite requirement has an executable test, and every security-critical one has a negative control.
  10. The protocol suite and fault-injection suite pass on a real PostgreSQL installation.
  11. Two independent MCP clients pass the interoperability fixtures.
  12. The Agent Guide is regenerated from the rc3 schemas and checked against them.
  13. The release notes distinguish specification completion from demonstrated implementation conformance.

Migration from rc2. Implementations migrating from rc2:

  1. Apply ERRATUM-1 and ERRATUM-2.
  2. Add to every contract with E2/E3 actions: business-request entities, confirms_effect states, failure transitions, bounded_by declarations and CON-21 invariants. The validator will reject contracts without them.
  3. Add the invocation, effect, obligation and reservation records, fencing, the restore-independent ledger (EXE-14) and the proxy transmission append.
  4. Add the EXE-04 adapter declarations to every adapter.
  5. Implement the ten-tool interface and the envelope.
  6. Map existing CRs to rc3 states. Any CR that an rc2 installation had returned to Draft after a gate failure becomes Rejected, with a successor if needed.
  7. Bind evidence and approvals to manifests.
  8. Pass the rc3 suite.

rc2 applications do not inherit rc3 conformance.


#14. Open items

ID Blocks freeze Item
OPEN-1 Yes Confirm the rc2 page-15 lifecycle diagram against LC-08. In particular, check what its "2 failure exits" were.
OPEN-2 Yes Author the JSON Schemas for: the ten tools; the envelope; the manifest; approval, invocation, effect and obligation records; and every dispatch-intent ledger record kind of EXE-12.
OPEN-3 Yes Write the executable fixtures and negative controls for every [S] requirement (see requirements-rc3.tsv), including CNF-09 boundaries 13–16.
OPEN-4 No Removal ops and escape-hatch modification ship first as extensions under GOV-03. Meanwhile, re-registering an escape hatch under its existing ID is a modification, priced by ESC-04.
OPEN-5 No (claim excluded) CON-21 is per tenant in rc3. Applications needing a cross-tenant monetary bound are outside the rc3 conformance claim until a later revision defines it. Other rc2 §21.2 questions remain open.
OPEN-6 No Idempotent automated re-dispatch after transmission (the former F13), for adapters declaring both provider_idempotent: true and lookup_finality: true. Under GOV-03 it may return only as an extension shipped in two installations, with its own fault-injection boundaries.

#15. Revision history

#Revision 2 changes

Answers to the freeze review of revision 1. Items marked P0 were release blockers.

Review item Disposition Where
P0-1 duplicate execution after rollback Proof boundary stated; identity never released EXE-02, EXE-12
P0-2 multi-effect settlement One money effect per action EXE-13, EXE-07
P0-3 tombstones undefined Monetary obligation record replaces tombstones and is what CON-21 sums CON-21, EXE-13, EXE-11
P0-4 no dispatching → blocked New pre_send state; blocked reachable only from provable non-send §5.4, EFS-02, checker rule
P0-5 restore deadlock / atomicity Dispatch-intent ledger with watermark; request-creation boundary; no re-dispatch to discover outcome EXE-12, EXE-11
CON-19/EFS-04 atomicity One transaction; ledger-first ordering with boundary 11 CON-19, EFS-04
T1 validation boundary V1 check set run by the Change service at T1; Verifier runs V1–V10 T1 guard
Held repair before T14 LC-19 LC-19, T14
T25 Rejected vs hold Kept Rejected; reason class integrity_incident ART-03, AUD-02 row
Ranged config Verified values recorded; else material ART-04
AUTH-20 modified T/A Assurance graph AUTH-20
RSK-05 new principals Full before/after relation RSK-05
Extension fields Single definition MCP-05
EXE-10 misleading status completed_external_failed added EXE-10, MCP-06
GUA-05 stronger than evidence Boundary and required evidence stated; class T without it GUA-05, CNF-13
30-day errata window Claim withheld; monetary autonomy disabled until applied §1
"Delivered" artifacts not examined They are in the package; the freeze checklist now requires reviewing the files §13
OPEN-5 multi-tenant Per-tenant bound normative; cross-tenant excluded from claim CON-21, OPEN-5
Immutable CRs are substantive Indexed as a replacement of §8 behavior §2

#Revision 3 changes

Review item Disposition Where
Blocker 1: effect row and ledger disagree; cancel after send Ledger authoritative for send state; F1/F2/F3 guards read it; F2c/F2d to outcome_unknown EXE-12, §5.4
Blocker 2: restore re-executes a request invocation_committed ledger record; invocation row and pending state replayed; EXE-02 proof keyed by request EXE-11, EXE-12, EXE-02
Blocker 3: lease-expiry release races commit Invocation row in app DB; EXE-03 commit is a CAS on its token; release only after abandoned CAS EXE-01, EXE-03, EXE-09, ERRATUM-2
Held reservations stuck held → released on proven non-execution; non-money effects never hold EXE-07
No retry after definitive failure Failure targets non-executable; retry is a new request; partial uniqueness is normative CON-20, CON-18
Ledger LSN before commit; phantom obligations request_committed record; request_created alone ignored EXE-12, EXE-11
Requested obligation never released Released on declared withdrawal with no commit EXE-13
Suspended CR with dead evidence T27/T28 re-verification; reconciling CR may pass T10 §6, LC-12, LC-16
Risk modifier contradicts CON-18 Modifier reworded risk-floors.json
Restore needs transitions the machine lacks F19, F20, F21, F2c effect-lifecycle.json
No envelope status for in-progress errors indeterminate may carry error MCP-06
Untestable terms Standing and assurance graph defined; AMD-03 → [P] RSK-05, AUTH-20, AMD-03

#Revision 4 changes

Review item Disposition Where
Blocker 1: restore misses effects dispatched after P under an earlier commit Watermark on every record; step 4 iterates by effect; F1/F1b require no prior ledger record EXE-12, EXE-11, §5.4
Blocker 2: restored request becomes a bare obligation Request row re-created from ledger before effects; uniqueness fields carried in ledger EXE-11 step 2, EXE-12
Blocker 3: re-verification exposed pre-rollout exits ReVerifying state; only exit is back to Suspended §6, LC-12
Blocker 4: forward fix unreachable; no exit after successor Live reconciles: declaration admitted at T1/T21/T10; T30 Suspended → Superseded §6, LC-16
Boundary 5 and 11 repair paths Scan-and-append for invocation_committed; F22–F25 ledger replay EXE-03, EFS-04
Concurrent same-key E0/E1 Partial UNIQUE on live invocation rows EXE-01
Reservation leak after abandon CAS Idempotent release on abandoned ERRATUM-2, EXE-07
Reversal release undefined Reversal is a separate obligation CON-21
Untestable terms Acceptance domain defined; ledger placement is EXE-14 [D]; CON-17 listing moved to objective AUTH-16, EXE-12, CON-17
E_BUDGET_EXHAUSTED ends the loop spuriously Default later; after_authorization only when committed + held exceed cap ERR-03, errors.json

#Revision 5 changes

Review item Disposition Where
Blocker 1: dispatcher crash in pre_send strands the effect F1c/F1d recovery; void ledger records; pre_send → sent is a fenced CAS §5.4, EXE-09, EXE-12, CNF-09 boundary 12
Blocker 2: restore after commit, before dispatch, leaves no effect rows Step 3 re-creates declared effects in pending_dispatch EXE-11
T14 unreachable after re-verification T28 records the new bundle's approvals before returning §6
Reconciling CR violates REV-02 T10 requires every cohort on the reconciled CR's target §6, LC-16
vaep_invocation not DB-enforced vaep_ctl role; privilege trigger; negative control EXE-01, CNF-08, §2
ERRATUM-2 vs EXE-07 Erratum defers to EXE-07 §1
F1 vs F1b citations Corrected AUTH-22, AUTH-23
Step numbering in guards Corrected to step 4 effect-lifecycle.json
Objective missing from E0/E1 key Key is (objective, client key) EXE-01
Boundary 11 from outcome_unknown / reconciliation_required F28–F31 ledger replay §5.4, EFS-04

#Revision 6 changes

Review item Disposition Where
Blocker 1: effect_id undefined; restore mints a second ID Deterministic eff ID over (invocation, effect name) EXE-04, EXE-11
Blocker 2: ReVerifying has no exit on denial or revocation T28 on completion only; T29 denial/revocation; T31 superseded; approvals recorded while Suspended §6, LC-20
Money writes not DB-enforced vaep_ctl terminal writes; forward-only triggers; restore as vaep_owner EXE-13, EXE-11, CNF-08
"Documented as non-executing" untestable non_executing_responses declared, in manifest digest EXE-04, F5/F9/F12
Held/canary create per-effect human work Deferral, not blocked EFS-06, F2/F2b
ERRATUM-2 not implementable on rc2 Self-contained wording; EXE-07 supersedes in rc3 §1
EXE-07 contradictions Unreachable row removed; exits corrected EXE-07
T14 ping-pong on revoked objective; T30 missed in ReVerifying Re-binding (LC-20); T31 §6
Ledger "append-only" vs CAS; token reissue after restore Conditional append defined; counter outside restore scope; equal-token case EXE-09, F1c
T10 actor; EFS-02 checker claim; step-4 citations; LC-18 Corrected §6, EFS-02, EXE-11, LC-18

#Revision 7 changes

Review item Disposition Where
Blocker 1: cancel/refuse not fenced; send after cancel Ledger-first rule: blocked, cancelled, sent and terminals are conditional appends before any row write EXE-12, F2/F2b/F3/F18
Blocker 2: forged invocation laundered by repair scan; request without obligation Gateway admitted ledger record required by F1 and the scan; obligation CAS must affect one row; precondition requires obligation; only declared effects (EXE-15) EXE-01, EXE-03, EXE-15
No role for mandatory writes vaep_ctl grants completed; adapters report, control plane writes; withdrawal references request_withdrawn EXE-13, §2
Reservation stuck after F13 Held exits include post-re-dispatch terminals EXE-07
Error statuses for in-transaction failures failed_without_effect added; not_started on in-progress errors.json
LC-20 events absent from file T32, T33 self-transitions §6
EFS-02 check contradicts F18 cancelled sources include blocked; checker updated EFS-02
Unreachable held → released row and fixture Removed EXE-07, CNF-07
LSN ambiguity after second PITR (timeline, LSN) watermark EXE-12
blocked meaning; T10 wording Corrected effect-lifecycle.json, T10

#Revision 8 changes

Review item Disposition Where
Blocker 1: continued effect stuck behind refused head continued record; F1/F2/F3 accept absent or continued head EXE-12, §5.4
Blocker 2: re-dispatch races reconciliation Head-linked appends (true CAS on predecessor ID); open_lookup head; F13 refused while a lookup is open EXE-12, EXE-05, F11–F13
T12 vs T33 ping-pong T12 excludes re-bound CRs §6
T14 skips artifact checks ART-03 checks 2–7 §6
Non-money E2/E3 unexecutable Obligation CAS only for money actions EXE-03
Withdrawn request executable after restore; obligation moved backwards request_withdrawn replayed; obligation forward-only in restore EXE-11
Worker trust boundary Per-kind append authority (EXE-17); amount binding (EXE-16) EXE-17, EXE-16, GUA-05
Actor/role mismatches; refused kind; F13 sequence Actors |platform; record grammar completed §5.4, EXE-12
Admission ordering Reserve → admitted → row EXE-01
Restore of dispatching / provider_pending; F1c vs F21; EXE-09 placement; boundary 12 F32/F33; F21 removed; EXE-14; GUA-05 boundaries 1–12 §5.4, EXE-11, EXE-09, GUA-05

#Revision 9 changes

Review item Disposition Where
Blocker 1: vaep_app can delete or re-point an obligation No DELETE; bound_owner, tenant_id, request reference immutable CON-21, §2
Blocker 2: lookup opened during an in-flight send open_lookup accepted only when the sent token has no live lease EXE-05, F11/F12
Blocker 3: restore leaves refused / continued / cancelled heads unmatched F34–F38 replay transitions; step 4 bullets §5.4, EXE-11
Blocker 4: reservation without an invocation row Release after admission lease expiry, with the admitted record voided first EXE-07
Crash between F13's two appends F1e orphan void §5.4
Held exits enumerated incompletely Any terminal of the money effect EXE-07
T29 ping-pong on re-bound CR T33 exclusion §6
Worker sends unbound amounts via proxy EXE-18: proxy enforces the ledger EXE-18, GUA-05, §2
Actor mismatches; stale F21; undefined re-bound recheck Corrected; recheck defined §5.4, EFS-02, AUTH-23
Lookup grammar open_lookup → open_lookup; lookup_closed record EXE-12, EXE-05

#Revision 10 changes

Review item Disposition Where
P0-1: lease expiry ≠ provider finality Distinguish lease (no new send) from provider finality guarantee; F12 requires explicit provider contract property EXE-05, F12, GUA-05
P0-2: request commit-to-ledger crash window Request-commit repair scan (EXE-19); quarantine instead of silent discard EXE-19, EXE-12, EXE-11
P0-3: incomplete request reconstruction Canonical reconstruction payload required; recreate only from complete payload EXE-19, EXE-11
P1-4: RSK-05 new-principal exception Exception narrowed to explicit already-authorized delegation; copying permissions is widening RSK-05
P1-5: permanent idempotency input binding Immutable identity record with atomic check on every admission EXE-02
P1-6: endpoint-only range verification Require monotonicity proof or explicit enumeration; otherwise material ART-04, ART-07

#Revision 11 changes

Review item Disposition Where
P0-1: proxy does not enforce one outbound send Single-use transmission record at proxy; atomic append before forward; fail closed on uncertainty EXE-18, GUA-03, GUA-05
P0-2: reconstruction payload after commit Canonical payload in request_created before DB commit; unrecoverable classification when history lost EXE-19, EXE-12, EXE-11
P0-3: terminal transitions bypass ledger authority Explicit three-role separation; only the control plane appends terminals and writes terminal states EXE-17, F4/F5/F8/F9/F15/F16
P0-4: monetary invariant not proven across isolation levels Explicit transaction protocol (lock, snapshot, retry); CNF-13 must show observed aggregate CON-21, CNF-13
P1: late row after voided admission Explicit forgery rule EXE-01, EXE-07
P1: effect identity on retry Proof that permitted retries cannot mint a second effect_id EXE-02, EXE-04
P1: restore validation before unfreeze Obligation and aggregate validation required before dispatch resumes EXE-11
P1: refundable_balance double-count Definition excluding confirmed from sum CON-21
P1: permitted_next_actions vs MCP-14 Distinguish agent-invocable from external decisions LC-18

#Revision 12 changes

Answers to the freeze review of revision 11 and of the amendment set proposed against it.

Review item Disposition Where
P0: revision 11 refundable_balance still double-counts (the formula summed confirmed obligations against a balance that already subtracted them); generated columns cannot read other rows Bound is a lifetime field on the bound owner; confirmed obligations stay in the sum; no running balance; validator forbids effect-driven writes to the bound; proposed stored-column alternative rejected CON-21, EFS-04
P0: proposed grammar kept lookup_closed → pre_send, re-opening a second transmission after F13's removal lookup_closed → terminals only; build check forbids any path from transmission back to sending EXE-12, EFS-01
P0: CON-21 lock protocol relied on a snapshot guarantee REPEATABLE READ cannot give Mechanism-specific protocol: lock-row UPDATE, then a fresh-statement read; serialization failure on stale snapshot; bounded retries CON-21, CNF-13
P0: sent without transmission had no recovery transition (EFS-01 exhaustiveness) send_revoked record; F39; F2e/F3c refuse or cancel before admission EXE-12, §5.4, AUTH-22
Proposed amendment: transmission head, F13 removal (Option A), GUA-03 and EXE-18 honesty Accepted. F13, F1e, F2c, F2d retired; idempotent re-dispatch moved to OPEN-6; GUA-03 strengthened to one admission per effect_id, ever EXE-05, EXE-18, GUA-03, OPEN-6
Proposed amendment: completeness frontier and bound freeze refusing all admissions Accepted in substance, revised: quarantined requests become non-executable rows (CON-24) whose obligations count at full amount, so capacity is never freed, without refusing unrelated admissions; frontier defined on request_created records EXE-19, CON-24, EXE-11
"Durable transaction identity" and "authoritative evidence" undefined Transaction-status classification table; abandoned-timeline status is never evidence EXE-19
Identity record location unspecified (a database record would not survive restore) Identity chain in the ledger EXE-02, EXE-14
Finality guarantee implicit lookup_finality declared per adapter, in manifest; changing it is R3 EXE-04, ART-01, RSK-03
Append authority conflicts (invocation_committed by dispatcher vs control plane; transmission by control plane vs proxy; F7 written by vaep_app) Single authority table; F7/F10 executed by control plane EXE-17, §5.4
Proxy transport retries could duplicate a forwarded call Proxy never retries; no forward on append uncertainty EXE-18
continued successors inconsistent with F2/F3 guards Grammar completed EXE-12
Restore could be raced by a pre-restore lease dispatch_frozen honored by the proxy; heads normalized before replay EXE-11
F19–F38 per-pair enumeration fragile LR rule with head→state mapping, expanded in the JSON EFS-07
Failure-path atomicity unstated failed / cancelled outcome transactions are atomic EFS-04
EXE-14 referenced but not a requirement Promoted to [D] requirement EXE-14
Appendix A duplicate row; stale "Delivered" status Removed; statuses corrected Appendix A

#Revision 13 changes

Answers to the errata found while building the reference implementation (Phases 1–3, errata/rev13-errata.md), plus four product decisions made by the specification owner. Items marked as implemented confirm the interpretation the reference implementation already uses.

Erratum Disposition Where
B1: rc2 dependencies unavailable rc2 and its conformance package declared normative inputs; stand-ins retired §0.2
B2: void of admitted contradicted the grammar; identity chain undefined Identity-chain grammar added; void permitted after admitted; release with no admitted needs no void EXE-12, EXE-07
B3: fencing token per invocation or per effect One lease and token per invocation; "the row" means the invocation row (as implemented) EXE-09
B4: EFS-04 transaction spanned two clusters Reservation move is a ledger append before the app-DB transaction; no cross-cluster transaction EXE-07, EFS-04
B5: lookup finality unsafe for late-arriving requests lookup_finality: true requires key closure or enforced request expiry EXE-04
B6: CNF-13 assertion unsatisfiable for releases under RR/SERIALIZABLE Assertion scoped to lock-taking writes CNF-13
C1 Precedence: reconciliation_required, outcome_unknown, executing, terminal EXE-10
C2 LR pairs generated only when restore-reachable EFS-07
C3 Callback after lookup_closed is evidence for the recovery authority EXE-05
C4 Obligation transitions listed explicitly EXE-13
C5 Watermark is the WAL insert position; commit LSN for commit records EXE-12
C6 Leases stored in the ledger cluster; duration in [D] evidence EXE-09, EXE-14
C7 cr-lifecycle.json generated from §6 Appendix A, §13
C8 Reservations atomic; money reservations commit at succeeded EXE-07
C9 Effect and outbox rows only for E2/E3 (as implemented) EXE-03, EXE-15
C10 Request transitions follow the confirms_effect effect (as implemented) CON-20
C11 Request IDs scoped to one database attempt (as implemented) EXE-19
C12 Repair scan completes interrupted revocation sweeps (as implemented) AUTH-22
C13 Prior outcome takes precedence over the retry error (as implemented) CON-20
C14 Boundary 8 split into 8a (effects) and 8b (CR lifecycle, deployment) CNF-09
C15 Repair scan reads transaction status before the request row EXE-19
C16 E_GRANT_INVALID added §8, AUTH-18
C17 Pre-tool failures returned at the transport layer with the envelope in JSON-RPC data MCP-06
C18 Pre-release versions mutually incompatible MCP-12
C19 Approval-class registry AUTH-24, AMD-02
C20 Decision: only incidents touching the CR's affected entities raise the requirement AUTH-21
C21 res grammar defined AUTH-18
C22 Decision: R4 CRs are human-authored AUTH-25, §2
C23 Decision: adapters are class A unless provider conformance tests cover their declarations AUTH-20
C24 rc2 §18 L3 entry amended: R2 by delegated approval §2, AUTH-21
C25 E_NOT_FOUND; absence and invisibility identical ERR-05, §8
C26 Decision: every drafter of identical content is recorded and excluded from approving it MCP-09, AUTH-20
C27 Later pages may send approved or the resolved revision MCP-08
C28 cr.draft's approval class is a snapshot; the gate recomputes MCP-09, AUTH-21

#Revision 14 changes

Answers to the errata found conforming the reference implementation to rev 13 and building the CR lifecycle engine (errata/rev14-errata.md). Items marked as implemented confirm the interpretation the code already uses.

Erratum Disposition Where
D1: manifest had no field for adapter conformance tests conformance_tests added; only passing provider tests count (as implemented) ART-01, AUTH-20
D2: entity scope of action.invoke undefined Request entity plus every written entity (as implemented) AUTH-18
D3: findings with unknown entity scope Unknown scope touches every entity (as implemented) AUTH-21
D4: grant-dependent findings on shared content Changed from the implementation: grant-dependent findings belong to the call, never to the CR; such a call records nothing MCP-09
D5: "apply to every drafter" No drafter or delegation-chain member approves; LC-07 counts per objective (as implemented) MCP-09
D6: finality declarations unnamed closes_key_on_lookup, request_expiry_s, clock_skew_s (as implemented) EXE-04
D7: no channel for human authoring Human authoring channel outside MCP, phishing-resistant human authentication AUTH-25
D8: reconciles: missing from the CR input Optional reconciles, part of the hashed content (as implemented) §7.2
D9: no actor for automated T6 platform fires T6 only for class automated (as implemented) §6 T6
D10: T10 could deploy a stale base over Live work T10 requires base == approved or the LC-16 exception (as implemented) §6 T10
D11: overlapping artifact error codes Split by lifecycle state: T10 vs Suspended (as implemented) §8
D12: what LC-07 counts Every entry into Rejected; one clearance admits one submission (as implemented) LC-22
D13: no code for LC-05 waits E_ROLLOUT_SERIALIZED, retry later §8
D14: deployment model unspecified Environments with ordered cohorts, durable cohort records, 30-minute default timeout (as implemented) LC-23

#Appendix A additions

Artifact Path Status in this redline
CR lifecycle protocol/cr-lifecycle.json Generated from §6 by the reference implementation (Phase 1)
Approval-class registry protocol/approval-classes.json Generate from AUTH-24 (blocks freeze)
Grant schema, including the res grammar schemas/grant.schema.json Generated by the reference implementation (Phase 3)
Effect lifecycle protocol/effect-lifecycle.json Regenerate for revision 12 (blocks freeze)
Error registry and retry classes protocol/errors.json Update for revision 12 derivations (blocks freeze)
Risk-floor registry protocol/risk-floors.json Update for revision 12 modifiers (blocks freeze)
Requirement index (rc3 additions) requirements-rc3.tsv Update for revision 12 IDs (blocks freeze)
Dispatch-intent ledger records schemas/dispatch-intent.schema.json OPEN-2
Obligation record schemas/obligation.schema.json OPEN-2
Capability descriptor protocol/capabilities.schema.json OPEN-2
Envelope and error schemas protocol/response.schema.json, protocol/error.schema.json OPEN-2
Tool schemas mcp/<tool>.{input,output}.schema.json (×10) OPEN-2
Record schemas schemas/{deployment-manifest,approval,invocation,effect-execution}.schema.json Generated by the reference implementation; deployment-manifest gains conformance_tests (ART-01)
Fixtures tests/protocol/, tests/fault_injection/ OPEN-3

(End of revision 14 consolidated redline.)

Requirement index

104 requirements defined in this redline, by verification method (VRF-01): S suite (90) · D deployment (4) · P process (10). Requirements carried over from rc2 unchanged are not listed here.

IDMethodRequirementSection