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

VAEP Specification v1.0.0-rc3 — Consolidated Redline, revision 12 (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 (§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-11.

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.

AMD-02 P Single source. Four tables in this document are generated from the same source as four 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

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
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.
  • 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:
    • the authoring agent;
    • 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.
  • 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. any incident or recovery rule.

A conformance level may permit an approval mechanism but never waives the §7.2 minimum.

#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.
  • 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.

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 every effect record the action declares, and only those, in pending_dispatch (EXE-15);
  • creation of every outbox row.

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).

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 the provider contract documents that a lookup by the derived key returns a final answer. "Final" includes any request the provider accepted before the lookup, whether or not it had finished processing.
  • 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.

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.

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. The control plane first appends a void naming the admitted record, so a late row insert is a forgery under EXE-01 and never dispatches. It then releases.
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).

  • 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. The order of precedence is: unknown, then partial, then terminal.

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. 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).

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)

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, commit LSN) at the time it is appended. 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).

It never moves backwards: a forward-only 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;
  • the budget ledger.

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 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.

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. 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, in one database transaction, the platform applies:

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

A crash between the ledger append and the transaction is repaired on recovery 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 that the table makes reachable, with ID LR:<from>:<to>.


#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-07); 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 AUTH-20/21 satisfied; evidence unexpired; approvals bind bundle + manifest
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 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-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.

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.

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.

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).
  • 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 and risk 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.

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_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; CR Rejected 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_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 differs from the approved, evidence-bound manifest. Security event.
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-07 after_authorization not_started yes Third rejection in this objective; the owner must clear the next submission.
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;
  • 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;
  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. 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 12. 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.
  6. requirements-rc3.tsv lists CON-24, EXE-14, EXE-17, EXE-18, EXE-19 and EFS-07, each with its verification method.
  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

#Appendix A additions

Artifact Path Status in this redline
CR lifecycle protocol/cr-lifecycle.json Delivered
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 OPEN-2
Fixtures tests/protocol/, tests/fault_injection/ OPEN-3

(End of revision 12 consolidated redline.)

Requirement index

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

IDMethodRequirementSection