ANAX STANDARD Raw markdown Feedback
v0.4.4 DRAFT

Draft for community review. Feedback welcome.

This is a working draft published for comment. It is not a ratified standard, and normative requirements may change before v1.0.  ·  Read the raw markdown →

Governed Crossing

An extension to the Agent2Agent (A2A) protocol for verifiable bilateral commitments between organizations.

Extension URI https://anaxstandard.ai/ext/governed-crossing/v1
Version v0.4.4 DRAFT
Date 2026-09-17
Licence CC BY 4.0 (CC-BY-4.0) for this text and its conformance vectors — attribution "ANAX Standard — anaxstandard.ai"; no licence is required to implement. Reference implementations: Apache-2.0. See §9A.
Trademarks Governed Crossing™, Crossing Seal™, Decision Passport™ — ANAX Standard. Operating a Registration Authority, Verification Authority or Centre is a service, not licensed by this document (§9A).
Publisher ANAX Standard — ANAX Institute
Contact contact@viccaone.com
Verification Authority verify.anaxstandard.ai

Status: Draft for community review. Feedback welcome.

This is a working draft published for comment. It is not a ratified standard. Normative requirements may change before v1.0. Implementers are welcome, and are asked to write to the contact address above — in particular where a requirement is unimplementable, ambiguous, or wrong.

⚠ Nothing in this specification is implemented or enforced.

v0.3 fixes a vocabulary and a wire contract. No component enforces either. The conformance vectors for the commitment-class rules and for the two methods both fail, completely, as of this publication — see §10 item 6. This is stated here, at the top, because a specification that reads as though it describes a running system is worse than one that says plainly that it does not.

Note on this document. Normative content is specification; implementation notes reflect the reference implementation.


0. Preliminaries

0.1 Normative references

Reference Used for
A2A — Agent2Agent protocol specification (Linux Foundation), a2a-protocol.org Core object model, TaskState, RPC method conventions, per-transport method naming
A2A extension mechanism — extensions documentation AgentExtension, activation header, extension types, constraints
AP2 — Agent Payments Protocol specification, ap2-protocol.org Mandate model, open/closed variants, SD-JWT basis, signing requirements
RFC 2119 / RFC 8174 Requirement keywords
RFC 8785 — JSON Canonicalization Scheme (JCS) Normative canonicalization for the Terms Document (§4.2, §5.8)
SD-JWT — Selective Disclosure JWT Agreement Mandate encoding

Informative. "Governance Gaps in Agent Interoperability Protocols: What MCP, A2A, and ACP Cannot Express", Kang & Diponegoro, arXiv 2606.31498, 30 June 2026 — the analysis this specification responds to.

0.2 Requirement status

Normative statements that describe capability not yet present in the reference implementation are marked IMPLEMENTATION PENDING. The specification defines the target; implementations catch up. Such a marker is not an admission of weakness — it is the point of writing a specification before code.

⚠ As of v0.3 that marker applies to the whole of §3.7 and to the class and magnitude rules of §4.1.3. See §10, item 11-16.

0.3 Positioning

AP2 proves the user paid. Governed Crossing proves the deal should have been made.

A2A standardizes how agents talk. AP2 standardizes how agents pay. Neither expresses whether a commitment was authorized, defensible, and auditable.

The SWIFT analogy. In 1973 banks already moved money by telex. SWIFT did not invent the message — it standardized trust in the message, and became mandatory infrastructure for fifty years. In 2026 agents already talk (A2A) and already pay (AP2); nobody has standardized trust in the agreement.

A SWIFT message is inherently bilateral — a sender institution and a receiver institution — and the whole value of the standard is that both ends can trust an instruction crossing between two organizations. Governed Crossing exists to give agent-to-agent commerce that shape.

1. Scope & Conformance

1.1 Purpose

This specification defines Governed Crossing, an extension to the Agent2Agent (A2A) protocol that allows two organizations, each represented by an agent, to make a verifiable joint commitment — and to prove afterwards that each side held authority to make it.

A2A standardizes how agents talk. AP2 standardizes how agents pay. Neither expresses whether a commitment was authorized, defensible, and auditable. That gap is independently documented.

Governed Crossing is that layer, expressed as an A2A extension so that it composes with the ecosystem rather than competing with it.

1.2 What is in scope

1.3 What is out of scope

1.4 Conformance classes

Two classes. An implementation MUST declare which it satisfies.

Class 1 — Verify-Only (minimal)

An implementation is Governed Crossing Verify-Only capable if it:

  1. MUST be able to retrieve a Crossing Seal from Artifact.metadata (§4.3) without failing on unknown keys.
  2. MUST be able to resolve a Crossing Seal against the Verification Authority (§2) and interpret the response.
  3. MUST NOT represent an unsealed commitment as sealed, or a seal it has not resolved as verified.
  4. MAY decline to participate in bilateral sealing.
  5. SHOULD declare the extension in its Agent Card with required: false.

Verify-Only exists so that an agent can be a credible counterparty in one direction — able to check what it is being shown — without operating a sealing infrastructure. It is the on-ramp, and it is deliberately cheap.

Class 2 — Full (bilateral sealing)

An implementation is Governed Crossing Full capable if it satisfies Class 1 and additionally:

  1. MUST be able to present a valid Open Agreement Mandate for its Principal and a Closed Agreement Mandate for each commitment it makes (§4.1).
  2. MUST verify the Counterparty's mandates before committing, and MUST NOT commit if verification fails (§5.4).
  3. MUST participate in joint sealing and MUST NOT treat a commitment as made until a Crossing Seal exists.
  4. MUST refuse rather than degrade: where a seal cannot be written, the implementation MUST NOT emit the commitment. (This mirrors existing ANAX behaviour:)
  5. MUST declare the extension in its Agent Card and SHOULD declare it with required: true for any skill that can produce a commitment.

⚖ DESIGN LAW (inherited): the gate must be the only path out. A Full implementation MUST NOT expose a commitment-emitting capability that is reachable without passing the sealing path.

1.5 Relationship to the ANAX tier model

Inherited design law. Normative for ANAX's own implementation; informative for third parties.

Tier Produces a Mandate? Produces a Crossing Seal? Tempo
T0 — explanation, context, guidance No No Instant. Unsealed by design; nothing here is a commitment.
T1 — commitments within standing authority Yes — Closed Mandate signed by the agent Yes. MUST. Synchronous hold-until-sealed at business tempo (~25s), surfaced as "verification in progress".
T2 — novel legal obligation Yes — Closed Mandate signed by an authorized human Yes. MUST. Human-gated.

⚖ DESIGN LAW (inherited): the tier decides the tempo. T0 never waits; T1 never sends before its seal exists. There is no third mode, and in particular no fast path for a T1 commitment judged low-risk — that judgement is itself a T1 output.


2. Terminology

2.1 RFC 2119 keywords

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC 2119 and RFC 8174, and appear in bold uppercase when used normatively. Where these words appear in lowercase they carry their ordinary English meaning and impose no requirement.

2.2 Defined terms

Governed Crossing™ : The A2A extension defined by this specification, and by metonymy a single instance of its use: one bilateral commitment made under verified mandates and sealed. This is the name used on the wire.

Crossing Seal™ : The sealed, verifiable record of a Governed Crossing. A cryptographic commitment over the bilateral record (§4.3), written into an append-only chain and resolvable at the Verification Authority. This is the name used on the wire for the sealed object.

Agreement Mandate : A signed, machine-checkable statement of authority to commit, in Open and Closed variants (§4.1). The wire form of the Mandate primitive: who holds it, what commitment class it covers, what magnitude limit applies, when it expires.

Principal : The organization on whose behalf an agent acts and which bears the commitment. A Principal is an organization, not a natural person. The Principal issues Open Agreement Mandates. * differs from AP2, whose mandates originate with a natural person via a Trusted Surface.)*

Counterparty : The other Principal in a Governed Crossing, and by extension its agent. The presence of a Counterparty is what distinguishes a Governed Crossing from today's unilateral Canal Crossing.

Verification Authority : The service that resolves a Crossing Seal and answers whether it is genuine and what it commits to. For this specification the Verification Authority is verify.anaxstandard.ai. The certificate registry is a separate surface and is NOT a Verification Authority for Governed Crossing.

Commitment Class : The category of obligation a commitment creates. Determines which Mandate applies and whether human signature is required. IMPLEMENTATION PENDING — the vocabulary is defined by the committing Principal's governance pack; ANAX's own vocabulary is the T0/T1/T2 tier model (§1.5).

Magnitude Limit : The ceiling — monetary, temporal, or scope-based — above which a Closed Mandate may not be signed under standing authority. IMPLEMENTATION PENDING.

Terms Document : The canonical serialization of what was agreed. Its hash is agreement_hash (§4.1.3). * ANAX MUST define this canonicalization; AP2 inherits one for free from a merchant-issued artifact and ANAX has no equivalent.)*

Bilateral Record : The complete object sealed by a Crossing Seal: two Agreement Mandates, a terms hash, participant identities, and timestamps (§4.4).

2.3 Naming — LOCKED

Inherited design law. The rationale below is reproduced verbatim, as required, because it is the reason the naming is locked and will be quoted when the naming is questioned.

On the wire: "Governed Crossing" and "Crossing Seal". Never "Passport" at protocol level.

What A2A's Secure Passport actually is. Measured: a contextual state-sharing extension. A Calling Agent voluntarily shares a structured subset of its context — user preferences, previously verified identity tokens, session history — with a Called Agent, without exposing its whole internal memory. It is a convenience and personalisation primitive, positioned as a middle ground between A2A's stateless design and the practical need for shared context.

Assessment: collision, not opportunity — at the level of the name. The two objects are close enough to be confused and far enough apart to be misleading in exactly the direction ANAX exists to prevent:

A2A Secure Passport ANAX Decision Passport
who asserts it the caller, about itself a third party, about the caller
what it is for personalisation attestation
verifiable by the called agent anyone, at a public URL

A prospect who hears "ANAX Passport" in an A2A context will read it as "the A2A one, extended" — i.e. as a self-asserted claim. And A2A's is the one with the Linux Foundation and 150+ organisations behind it. ANAX will not win that naming contest and should not enter it.

The real opportunity, stated honestly. The two compose. An A2A Secure Passport can carry, as one of its shared context items, a reference to a Governed Crossing seal. That is a strong story — "their passport says what I claim about myself; ours says what was verified about me" — and it is available precisely because the names differ. Renaming is not a concession; it is what makes the composition legible.

Normative consequence. An implementation MUST NOT use the term "Passport" for any object defined by this specification, in any protocol field, URI, method name, log line, or user-facing string emitted during a Governed Crossing. "Decision Passport" remains the correct name for the ANAX-side artifact and product at verify.anaxstandard.ai, and MAY be used there.


3. Extension Identity

3.1 Extension URI

A2A identifies an extension by a URI. Extensions hosted by the A2A project itself use https://a2a-protocol.org/extensions/{name}/v1; third parties publish under their own authority.

Extension URI — APPROVED (2026-08-09):

https://anaxstandard.ai/ext/governed-crossing/v1

Frozen on publication.

The URI is the permanent identifier of the extension and is subject to the same discipline as an issued identifier namespace:

⚖ DESIGN LAW (inherited): a namespace is FROZEN once published. Changing this URI after any counterparty has activated it breaks every prior activation and every stored reference. A version increment (/v2) is the only permitted change, and it MUST be additive — /v1 MUST remain resolvable.

anaxstandard.ai is used rather than .com for consistency with the Verification Authority (§2.2).

Backlog (§11-1): the URI MUST eventually serve the specification document itself. An extension URI that dereferences to nothing is a broken promise to every implementer who follows it, and A2A's whole discovery model assumes a reader can resolve an unfamiliar extension. Not required for this draft; required before publication.

3.2 Extension type

Per A2A's four extension types:

Type Used by Governed Crossing For
Data-only Yes Declaring the Principal's clearance envelope and trust basis on the Agent Card (§3.4).
Profile Yes Overlaying pre-commitment state requirements on core messages — mandates MUST be exchanged and verified before a commitment message is honoured.
Method (Extended Skills) Yes crossing:seal and crossing:verify (§3.5).
State Machine Yes, with a constraint An extension-scoped commitment state. This is NOT a new TaskState value —.5.

Governed Crossing is therefore a composite extension. This is permitted; the four types are descriptive categories, not mutually exclusive declarations [D — the extensions documentation presents them as things an extension "can add", not as an enumeration to choose from].

3.3 Declaration on the Agent Card

An agent declares support by including an AgentExtension object in AgentCapabilities.extensions.

AgentExtension fields: uri, description, required, params.

*(*CONFIRMED 2026-09-01. The rendered object list in specification.md showed only uri, description, required, while extensions.md documented params with a worked example. Checked against the normative definition: the A2A protocol buffers definition declares google.protobuf.Struct params = 4 on AgentExtension, and A2A v0.3.0 §5.5.2.1 gives params?: { [key: string]: any }. params is normative; this declaration stands as written and no move to a Data-only surface is needed.)

{
 "uri": "https://anaxstandard.ai/ext/governed-crossing/v1",
 "description": "Bilateral commitments under verified mandates, sealed and publicly verifiable.",
 "required": true,
 "params": {
 "conformance": "full", // "verify-only" | "full"
 "verification_authority": "https://verify.anaxstandard.ai/",
 "principal": {
 "id": "urn:anax:principal:<opaque>", // stable identifier of the Principal
 "clearance_id": "<envelope id>", // IMPLEMENTATION PENDING — see §3.4
 "trust_basis": "vicca_authority_sealed", // see §3.4
 "agc_level": 3
 },
 "mandate_formats": ["sd-jwt"],
 "commitment_classes": ["<class>", "..."] // classes this agent can commit within
 }
}

Normative requirements.

3.4 The clearance envelope, and what it maps to

params.principal carries the Principal's standing governance posture. Its fields map onto the existing ANAX System Clearance Envelope.

The envelope is already an onboarding gate in the existing implementation: without a clearance envelope, the onboarding gate returns a VICCA-required outcome and issues no passport. That gate is inherited: an agent without a clearance envelope MUST NOT be Full-conformant.

trust_basis values are the existing evidence trust hierarchy: self_declared, organisational_controls, third_party_audited, vicca_authority_sealed, nca_verified.

Clarification of a term the design analysis corrected. This is an evidence trust hierarchy — how good the evidence behind the Principal's posture is. It is not a trust relation between two parties, and MUST NOT be interpreted as one. A Counterparty's trust_basis says how well-evidenced its own governance posture is; it says nothing about whether you should trust it .

3.5 Activation, and a security note that cannot wait for §7

Activation is per-request, via the A2A-Extensions HTTP header carrying a comma-separated list of extension URIs. The responding agent echoes back, in the same header, the extensions it actually activated. Extensions default to inactive.

POST /message:send HTTP/1.1
A2A-Extensions: https://anaxstandard.ai/ext/governed-crossing/v1

⚠ This is the most consequential review finding, and it refines a security assumption in the design analysis.

A2A's required: true means an agent SHOULD reject requests from clients that have not activated a required extension. SHOULD, not MUST — and the rejection is the agent's choice, evaluated per-request. It follows that "simply do not send the header" is an available downgrade path by design of A2A. The anti-downgrade property cannot be inherited from the transport; this specification must impose it.

3.5.1 The normative pair — "no seal, no deal"

Because the transport cannot enforce this, the endpoints must. These two requirements are the load-bearing pair of the entire specification, and every other normative statement about downgrade derives from them:

OUTBOUND. A Class 2 implementation MUST NOT issue a commitment without a sealed Governed Crossing.

INBOUND. A Class 2 implementation MUST reject any inbound commitment that does not carry a valid Crossing Seal.

Defense lives at the endpoints, not the transport. The consequence is the point: an attempted downgrade stops being a silent path and becomes a detectable violation. A party that omits the header, or presents a commitment without a seal, is not quietly served a lesser service — it is refused, and the refusal is attributable. A protocol cannot prevent a peer from behaving badly; it can guarantee that behaving badly fails visibly.

3.5.2 Supporting requirements

  1. A Class 2 implementation MUST reject any request that would produce a commitment and that has not activated this extension. It MUST NOT fall back to an unsealed commitment. The correct response is a refusal, not a degraded success.
  2. A Class 2 implementation MUST treat the absence of the extension in the response header as a failed activation, and MUST NOT proceed to commit.
  3. An implementation MUST NOT infer that a commitment is governed from the presence of the header alone. The header proves activation was requested and acknowledged; only a resolvable Crossing Seal proves the commitment was governed (§6).
  4. A refusal under §3.5.1 MUST be recorded by the refusing party with sufficient detail to be auditable. A downgrade attempt that is refused but not recorded is a detection that was thrown away.

Full treatment, including the disclosure of the transport property that makes this necessary: §7.4.

3.6 Method extensions

Two new RPC methods. A2A's REST naming convention is a resource with a colon-verb — POST /message:send, POST /tasks/{id}:cancel; the JSON-RPC and gRPC forms differ — see the binding table below.

Method Shape Purpose
crossing:seal see binding table below Submit a Bilateral Record for joint sealing; returns a Crossing Seal.
crossing:verify see binding table below Resolve a Crossing Seal. Delegates to the Verification Authority.

Per-transport binding. A2A v0.3.0 fixes extension method naming per transport in three subsections: §3.5.5 (Extension Method Naming) requires JSON-RPC extension methods to follow {category}/{action} with a clear namespace (its own example: myorg.extension/action); §3.5.3 requires REST endpoints to use /v1/{resource}[/{id}][:{action}] with colon notation for non-CRUD actions; §3.5.2 requires gRPC methods to use PascalCase. §3.4.1 requires functional equivalence across transports.

Operation JSON-RPC method REST gRPC
seal anaxstandard.crossing/seal POST /v1/crossing:seal SealCrossing
verify anaxstandard.crossing/verify POST /v1/crossing:verify VerifyCrossing

The wire contract for both methods — params, result, errors, determinism — is §3.7.

3.7 Wire contract

Merged from Addendum A-3, which closed §11-6. §3.6 names the methods and binds them to transports; this section is what a caller and a responder must agree on to interoperate.

3.7.1 crossing:seal — params

All fields REQUIRED unless marked.

Field Type Meaning
record object The Bilateral Record (§4.4) with chain position excluded (prev_hash, chain_seq omitted) — the party-independent input to joint_seal.
initiator_closed_mandate string (SD-JWT) The initiator's Closed Mandate, by value — the responder verifies it (§5.4).
initiator_anchor_intent object {prev_hash, chain_seq} The initiator's own chain position, so the responder can check it is well-formed; NOT sealed into joint_seal.
idempotency_key string MUST equal record.crossing_id. Present explicitly so transports without a body-level convention still carry it.

Responder behaviour (normative). Verify the initiator's Closed Mandate and its own (§5.4, all checks); recompute agreement_hash from the Terms Document it holds (§4.2) and require equality with record.agreement_hash; check the class and magnitude rules L-1, M-2, M-3 and M-4 (§4.1.3) against both mandates; compute joint_seal (§4.4 req 4); write its own anchor into its chain; return the result. Idempotent on crossing_id (§5.6 req 3): a repeat returns the existing result and MUST NOT write a second anchor.

3.7.2 crossing:seal — result

{
 "crossing_id": "<uuid>",
 "joint_seal": "<sha256 hex>",
 "seal_id": "canal-<ts>-<rand>", // the responder's public identifier for the seal
 "sealed_at": "<RFC3339>",
 "responder_anchor": { "prev_hash": "<sha256|null>", "chain_seq": 42 },
 "verify_url": "https://verify.anaxstandard.ai/?id=canal-<ts>-<rand>",
 "artifact_block": { /* the exact §4.3.2 block, ready for Artifact.metadata[uri] */ }
}

Effector consumption — normative (v0.4 note, 2026-09-02). An effector is a party that performs crossing:seal on behalf of an agent whose Mandate it did not issue — a gateway, a broker, a second implementer's seal endpoint. When an effector consumes a unit of an agent's magnitude_limit at the issuing Registration Authority, the following are REQUIRED:

  1. Consumption is by possession, not by reference. The effector MUST present the exact Mandate token the agent presented to it. The RA MUST locate the Mandate by the digest of those bytes (token_sha256, unique at issuance) and MUST NOT accept an identifier in its place. Knowledge of a Mandate's id is not possession of the Mandate; a tampered token MUST be indistinguishable from one never issued.
  2. An effector spends only what no issuer may issue for. The RA MUST refuse, as SERVICE_HELD_MANDATE, any consumption by an effector of a Mandate whose subject is one that any registered issuer is permitted to issue for. Mandates held by services in their own right — a monitoring service's read grant, a provisioning service's issuance grant — are never spendable by an effector, even when the effector holds the token. This is the lock for the day a service-held token leaks: without it, a compromised or careless effector can drain a service's authority from outside.
  3. Roles do not blend. An effector MUST NOT be able to issue, and an issuer MUST NOT be able to consume by possession; a call on the wrong route is refused as ROLE_MISMATCH. A party configured with both capabilities is a party that governs other agents' authority and quietly holds its own.

⚠ A second implementer building an effector MUST honour rule 2 or it builds an effector that can drain service Mandates. The rule is stated here, and not only in the reference implementation's code, for exactly that reason. Conformance: the acceptance test presents a service-held token from the effector and requires SERVICE_HELD_MANDATE with nothing consumed (reference-implementation acceptance test).

3.7.3 crossing:verify — params and result

v0.4 (adopted 2026-09-06) — where the two methods live, and under which URI. crossing:seal and crossing:verify are methods of this extension — https://anaxstandard.ai/ext/governed-crossing/v1 — and no separate URI exists or is declared for them; the A2A-Extensions header names that one URI for both. crossing:seal is an act and is served by the responder (Centre-001). crossing:verify is a resolution and is served by the Verification Authority (§3.1, verify.anaxstandard.ai) as one more resolver branch of the single public verify surface — the single-portal rule: one portal resolves every ANAX identifier, structurally, without login. A responder MAY additionally answer crossing:verify for its own seals; the Verification Authority's answer is the public one and the conformance target (WC-5, WC-6).

params: exactly one of seal_id (string) or crossing_id (uuid). Optional record (object): if supplied, the verifier additionally checks §6.2 item 2 (recomputed seal equals stored seal).

result: the public projection — the §4.3.2 block fields crossing_state, seal_id, seal, prev_hash, chain_seq, is_genesis, seal_version, pack_id, pack_version, outcome, sealed_at, verify_url, plus verified_by (the VA identifier, e.g. VA-001) and checks: an object with one boolean per §6.2 check (resolves, seal_matches — null if no record supplied — chain_consistent, basis_present, not_superseded). clearance_id MUST NOT appear (§4.3.2). A non-resolving identifier returns a result with resolves:false and every other check null — a verdict, not an error (§6.2: a seal that does not resolve is a commitment that was not made).

crossing:verify is public: no activation header, no authentication. It is rate-limited and cacheable; a sealed record is immutable, so a resolves:true result MAY be cached for the seal's lifetime.

3.7.4 Error vocabulary

Errors are JSON-RPC error objects (A2A §6.12) with code in the range −40000 to −40099 — outside the JSON-RPC reserved range −32768…−32000 that A2A's own codes occupy — and data.error carrying the name below. Implementers switch on the name; the number exists for JSON-RPC compliance. REST maps to the HTTP status shown; gRPC to the equivalent status per A2A §3.2.2.

The Spec failure path column is the point of this table. A name without the rule that produces it is a string an implementer has to guess at; every error here is traceable to the requirement it enforces.

Name Code HTTP Spec failure path Raised by
EXT_NOT_ACTIVATED −40001 428 §3.5.2 req 1 seal
MANDATE_INVALID −40010 401 §5.4 (signature / structure) seal
MANDATE_EXPIRED −40011 401 F1 seal
MANDATE_AUDIENCE −40012 403 §5.4 aud seal
MANDATE_NONCE_REPLAY −40013 409 §7.1 seal
MANDATE_REVOKED −40014 401 §5.4 revocation at commit (the Mandate Object Specification, forthcoming, §2.4) seal
AGREEMENT_HASH_MISMATCH −40020 422 §4.2 seal
CLASS_EXCEEDED −40030 403 §4.1.3 L-1 (CM-2) seal
MAGNITUDE_EXHAUSTED −40031 403 §4.1.3 M-4 (CM-1) seal
NARROWING_VIOLATION −40032 403 §4.1.3 L-2 / M-3 (CM-3) seal
CURRENCY_MISMATCH −40033 422 §4.1.3 M-2 (CM-4) seal
MALFORMED_MANDATE −40034 400 §4.1.3 L-5 / M-2 (CM-5, CM-6) seal
MAGNITUDE_MISMATCH −40035 403 §5.4 magnitude equality — the record's magnitude_asserted must equal the Closed Mandate's asserted magnitude; two sealed documents disagreeing on the committed amount are refused, not sealed seal
COUNTERPARTY_NOT_PERMITTED −40040 403 §4.1.3 permitted_counterparties seal
ROLE_MISMATCH −40041 403 §3.7.2 effector rule 3 seal (RA)
SERVICE_HELD_MANDATE −40042 403 §3.7.2 effector rule 2 (acceptance test) seal (RA)
MANDATE_PARTY_MISMATCH −40043 403 §4.4 req 7 / §5.4 check 9 (v0.4) seal
CHAIN_POSITION_UNAVAILABLE −40050 503 §4.4 req 5 / F6 seal
SEAL_MISMATCH −40051 409 §4.4 req 6 initiator-side (reported, not returned)
RECORD_MALFORMED −40060 400 §4.4 reqs 1–3 seal, verify
VERIFY_PARAMS −40070 400 §3.7.3 (neither/both identifiers) verify
RATE_LIMITED −40090 429 §3.7.3 verify

3.7.5 Determinism

Both methods are deterministic for a given input and store state: two verifiers with the same seal store return the same crossing:verify result; two responders with the same mandates and record compute the same joint_seal (§4.2 fixes the bytes). This is truth-gate Π2 stated at the wire.

3.7.6 Versioning

Method-level evolution is governed by the extension URI (§3.1): additive changes — new optional params, new result fields, new error names — stay within /v1; any incompatible change is /v2 with /v1 remaining resolvable. Implementations MUST ignore unknown result fields.

3.7.7 Conformance vectors — series WC-

⚠ WC-1…WC-7 all fail as of 2026-09-01. Nothing implements either method — see §11-16.


4. Data Model

4.1 The Agreement Mandate

4.1.1 Format and basis

The Agreement Mandate MUST be an SD-JWT, following AP2's mandate pattern.

Normative: implementations MUST use a non-deterministic signature scheme (ECDSA over P-256 or stronger). Ed25519 and other deterministic schemes MUST NOT be used. (This requirement is inherited from AP2 rather than invented; its stated purpose there is to defeat rainbow-table attacks against SD-JWT disclosure salts.)

W3C Verifiable Credentials MUST NOT be assumed. (v0.1 of the design analysis described AP2 as three W3C VC mandates; that was the September-2025 launch model and is superseded

4.1.2 Open and Closed variants

Adopted from AP2:

AP2 Governed Crossing
Open mandate Created before a specific transaction. Carries the user's authorization and constraints on agent behaviour. Signed by the Trusted Surface on behalf of the user. Agent's public key appears as cnf. Created before any specific agreement. Carries the Principal's authorization and constraints on agent behaviour: commitment classes, magnitude limits, permitted counterparties, expiry. Signed by the Principal. Agent's public key appears as cnf.
Closed mandate Transaction-specific. Signed by the user (human-present) or by the shopping agent (autonomous), validated against the open mandate's constraints. Agreement-specific. Signed by an authorized human (T2) or by the agent (T1) under the standing Open Mandate, validated against its constraints.
Verification Verifiers evaluate whether a closed mandate satisfies all constraints from its corresponding open mandate before processing. Identical. A Counterparty MUST evaluate the Closed Mandate against the Open Mandate before committing.

A structural alignment worth recording. AP2's human-present / human-not-present distinction is isomorphic to ANAX's T2 / T1 tiers. A human-present closed mandate is a human committing — T2. An autonomous closed mandate is an agent committing within constraints its Principal signed — T1. T0 produces no mandate at all, because T0 makes no commitment.

This is not a coincidence to be noted in passing; it means the tier model has an existing, deployed cryptographic expression rather than needing one invented. It should be stated plainly in any external presentation of the standard.

4.1.3 Claims

Claims marked [AP2] are used with AP2's semantics. Claims marked [NEW] are additions specific to agreements and have no AP2 equivalent.

Claim Variant Source Meaning
vct both [AP2] Schema version. mandate.agreement.open.1 | mandate.agreement.closed.1
iss both [AP2] Issuer. Open: the Principal. Closed: the human or agent signing.
sub both [NEW] The agent the mandate authorizes.
aud both [AP2] Open: urn:anax:va:001 — the Verification Authority, as the Registration Authority issues it and as the Mandate primitive's verifier enforces it (audience). An Open's counterparty binding is permitted_counterparties (§5.2 item 5), never aud. Closed: the Counterparty — the party that will verify and act on it (§5.4 check 7). (v0.4 — reconciles the two conventions; the earlier wording "the Counterparty, or a wildcard for an unbounded Open" described the Closed and was read against the Open.)
cnf open [AP2] The authorized agent's public key. REQUIRED on an Open Mandate that permits autonomous (T1) closing.
exp both [AP2] Expiry. REQUIRED on both variants. See below.
iat both [AP2] Issued at.
nonce closed [AP2] Replay resistance.
sd_hash both [AP2] SD-JWT disclosure binding.
commitment_class both [NEW] Open: the highest class permitted (L-1 — actions of class ≤ this clear). Closed: the single class asserted. Ladder below.
commitment_act both [NEW] What act is committed, as distinct from how much is at stake. String; vocabulary is per profile/domain and is not fixed by this specification.
magnitude_limit open [NEW] The ceiling. Non-negative integer; unit fixed by class — below.
magnitude_asserted closed [NEW] The magnitude of this commitment — integer, same unit as the class (§4.1.3). MUST satisfy magnitude_limit.
permitted_counterparties open [NEW] Allowlist of Principal identifiers, or an explicit wildcard.
agreement_hash closed [NEW] Hash of the canonical Terms Document. AP2's checkout_hash analogue — but see §5.8.
open_mandate_hash closed [NEW] Binds this Closed Mandate to the Open Mandate it was issued under.
governance_basis closed [NEW] {pack_id, pack_version} — which governance rules were applied.
crossing_id closed [NEW] AP2's transaction_id analogue. Resolves on the Canal chain.
signer_role closed [NEW] human | agent. Distinguishes T2 from T1 at verification time.

Normative requirements on claims.

The commitment class ladder. commitment_class is one of five fixed values, ordered. Higher classes commit more; a Mandate's class is the highest class of action it authorises.

Order Value Meaning Examples
1 observe No effect outside the agent. Read, recommend, draft. reading a record; producing a recommendation
2 reversible An effect the Principal can undo unilaterally, without a counterparty's consent, within the Mandate's exp. placing a hold; creating a draft record another system can delete; sending an internal message
3 irreversible An effect that cannot be undone unilaterally, but carries no financial or legal commitment. sending an external email; publishing; provisioning access; deleting data
4 financial Moves or commits value. payment, transfer, order, refund
5 binding Creates a legal obligation for the Principal. signing, accepting terms, submitting a regulatory filing

commitment_act is a separate axis. commitment_class answers how much is at stake; it does not answer what act is being committed, and the two are orthogonal rather than two spellings of one thing. L-5 governs commitment_class alone and does not make an unrecognised commitment_act malformed; the act is bounded by the profile's act vocabulary at the seal (§5.4 check 9, v0.4.4), not by L-5.

magnitude_limit — a non-negative integer whose unit is fixed by the class:

Class Unit of magnitude_limit Example
observe count of read operations (0 = unlimited within exp) 0
reversible count of actions 50
irreversible count of actions 5
financial minor currency units (cents/pence), with currency REQUIRED alongside (ISO 4217) 250000 + "currency":"EUR" = €2,500.00
binding count of instruments (1 = exactly one signature/filing) 1

⚠ A Mandate is permission to ATTEMPT, not a guarantee of completion — note for v0.4. Consumption is recorded BEFORE the act it authorises, not after, and a unit spent on an attempt that then fails downstream is spent. This is deliberate and it is the only order that makes magnitude_limit a control: a counter decremented after the act has already happened is an audit trail, not a brake, and an effector that consumed on success alone would grant itself unlimited retries of an act it was authorised to perform a bounded number of times. The cost is that an attempt lost to an unrelated outage still counts against the grant. Implementations SHOULD emit a distinguishable event when this occurs — the reference deployment logs mandate_unit_burned_on_503 — so the loss is measured rather than silently absorbed into the count.

Conformance vectors — series CM-.

⚠ v0.4 note (2026-09-02): measured against the components that hold each rule — the Registration Authority for CM-3…CM-6 and the responder's crossing-path seam for CM-1/CM-2 — CM-1, CM-2, CM-3, CM-5 pass; CM-4 and CM-6 are conditional on M-TRANSACT being activated, because they exercise financial, which the operator's charter makes unreachable by design; CM-3 is restated at irreversible (see the A-2 addendum's v0.4 note). The sentence this replaces — all fail as of 2026-09-01 — was true of the harness that day and is retained in the change log. §11-16 still stands for the WIRE contract: WC-1…WC-7 remain unimplemented.

Relationship to Blast Radius. Blast Radius (the Authority Doctrine, forthcoming, §2.2) aggregates magnitude_limit per class over reachable effectors. This vocabulary makes that aggregation well-defined: sums are within a class, and within a currency for financial; the ladder gives the weighting order. (OQ-A1 answered: fixed ladder. A weight table for a single scalar exposure figure is deferred to Authority Doctrine v0.2 — this specification fixes vocabulary, not weights.)

4.1.4 THE MANDATE EXISTS — note for v0.4

⚠ This section said "the Mandate does not exist" until 2026-09-01. It does now. The Mandate primitive was built and exercised on that date, and the claim is recorded here with what was measured rather than what was intended:

⚠ WHAT THIS DOES NOT SAY. One effector, on one route, in one service. §4.1.3's rules still have no general enforcing component: CM-1…CM-6 remain 6 of 6 failing and §11-16 stands. (v0.4, 2026-09-09: both counts have since moved — CM-1…CM-6 are 4 pass / 2 conditional / 0 fail, and the §3.7 methods are implemented and live. The sentence is retained as the record of its date; the current measurement is the v0.4 note in §11-16, which also lists the three things still not enforced.) Delegation narrowing is enforced at the issuer only. A Mandate existing is not the same as this specification being implemented, and the distance between those two statements is exactly what §11 lists.

The prior state, retained — what existed before the Mandate primitive, and why neither half was a Mandate:

Field Nearest existing thing Why it is not a Mandate
principal an admin session record / an API-key record a person's email, or a bearer secret
scope the API key's scope list present on the machine side only
magnitude tier constants hardcoded constants, not issued authority
expiry — absent everywhere
commitment class — absent everywhere in code. The vocabulary is now fixed (§4.1.3) and nothing enforces it (§11-16)
verifiability — both are bearer secrets. A bearer secret proves possession, not authority, and cannot be shown to a counterparty.

That last row is why AP2's signed open/closed pattern is adopted rather than extended from what exists.

4.1.5 Who signs for an organization — answered once

AP2's mandates originate with a natural person, signed by a Trusted Surface on their behalf. A Governed Crossing Principal is an organization, and a T1 commitment may involve no human at all. The question "who may sign an Open Agreement Mandate for an organization?" therefore has no AP2 answer and must be ANAX's.

It is answered once, by the Mandate primitive — and the same answer serves the question of who may bind the organization.

This is not a coincidence to be tidied away; it is the reason the design analysis names the Mandate as a primitive rather than a protocol field. The same object answers three questions that look separate:

Question Asked by
What may this agent commit to, and up to what magnitude? Tiered autonomy, the design analysis
How does a counterparty verify that authority? This specification, §4.1
Who may bind the company — for humans and agents alike? the organizational control-map question

Normative consequence for this specification: the identity and authority of an Open Mandate's iss MUST be resolvable to the Principal by the Counterparty, and an implementation MUST NOT accept an Open Mandate whose issuer it cannot resolve to the claimed Principal (§5.3, failure path counterparty unverifiable). How that resolution works — a delegation chain, a registry, a signed Agent Card lineage — is the Mandate primitive's design and is IMPLEMENTATION PENDING there, not here. This specification states the requirement and consumes the answer; it does not fork it. Forking it is precisely how one mandate model becomes two, which is the state the design analysis found and is closing.

4.2 Terms Document and agreement_hash

ADOPTED 2026-09-01 — RFC 8785 (JCS). The adoption gate is passed; see §5.8 for how.

AP2's checkout_hash binds a mandate to a merchant-issued Checkout JWT — a third artifact, produced by one party, with a canonical serialization the protocol gets for free. A bilateral agreement has no such artifact. The Terms Document is jointly constructed, and if the two parties canonicalize it differently they will compute different hashes and the crossing will fail — or worse, appear to succeed against different documents.

Normative requirements:

  1. agreement_hash MUST be computed as SHA-256( JCS(terms_document) ), where JCS is the JSON Canonicalization Scheme of RFC 8785, applied to the Terms Document as a JSON value, producing a UTF-8 byte sequence. The digest is rendered as 64 lowercase hexadecimal characters.
  2. Both parties MUST compute it independently and MUST compare before sealing. A mismatch MUST abort the crossing; implementations MUST NOT proceed on either party's value.
  3. Implementations MUST use RFC 8785 as published; this specification does not restate it.

Constraints on Terms Documents, so canonicalisation is unambiguous:

Conformance vectors — series TD-. TD-1 minimal; TD-2 the same document with keys shuffled and whitespace added (MUST equal TD-1); TD-3 nested object with a non-ASCII string, emitted as UTF-8 rather than \u escapes; TD-4 array order significant (MUST differ from TD-1); TD-5 booleans and null. An implementation claiming conformance MUST reproduce all five byte-for-byte.

JCS is chosen over an ANAX-internal utility for one reason that outweighs familiarity: a bilateral hash must be computable by an implementer who has never seen ANAX code, from a published standard, in the language of their choice.

the existing single-party serialiser is noted as the current single-party utility, not the answer. It has the right instinct — deterministic key ordering, with an explicit ?? null discipline so an absent key and a null key stay distinguishable — but it is one implementation in one repository with no published test vectors, and it was written for a basis constructed by one party.

⚖ Adoption gate — PASSED 2026-08-31. The gate was: published test vectors, and two independent implementations producing byte-identical hashes over them. Both halves are met; §5.8 records exactly how, so a reader can check the claim rather than take it. Requirement 2 — both parties compute independently, mismatch MUST abort before sealing — stands regardless, and is what protects the crossing when an implementation is wrong.

4.3 The Crossing Seal, and where it attaches

4.3.1 Attachment point

The Crossing Seal attaches to Artifact.metadata, on the Artifact representing the agreement, and is echoed into Task.metadata on the terminal Task.Task, Message and Artifact each carry a metadata field, typed as a map of string to JSON values.A2A's extension constraints are explicit: an extension may not change the definition of core data structures and may not add values to enum types; "custom attributes belong in the metadata map present on core data structures", and the Timestamp extension's documented example places its data on Message and Artifact.

Why the Artifact and not the Message: Artifacts are the durable outputs A2A expects to be retained and referenced; a Message is transient. A seal that lives only on a transient object cannot serve post-hoc verification, which is the entire purpose (§6).

Message and Artifact additionally carry an extensions field. The extensions documentation does not describe its relationship to metadata. The division is that extensions declares which extension URIs apply to the object and metadata carries the data. CONFIRMED 2026-09-01 against the normative A2A definition: the A2A protocol buffers definition declares repeated string extensions = 7 on Message ("the URIs of extensions that are present or contributed to this Message") and repeated string extensions = 6 on Artifact ("…to this Artifact"), and both objects also carry metadata ("optional metadata for extensions; the key is an extension-specific identifier"). A2A v0.3.0 §6.4 and §6.7 give extensions?: string[] on both. The division above is the A2A design, not an inference. This specification populates both.

4.3.2 Structure

Artifact.extensions = ["https://anaxstandard.ai/ext/governed-crossing/v1"]

Artifact.metadata["https://anaxstandard.ai/ext/governed-crossing/v1"] = {
 "crossing_state": "committed", // extension-scoped. NOT a TaskState — see §4.5
 "seal_id": "canal-<ts>-<rand>",
 "seal": "<sha256 hex>", // over the Bilateral Record, §4.4
 "prev_hash": "<sha256 hex | null>",
 "chain_seq": 42,
 "is_genesis": false,
 "seal_version": 3, //
 "pack_id": "<pack>", // governance basis of the sealing party
 "pack_version": "1.2.0",
 "outcome": "CLEARED", // the outcome vocabulary
 "sealed_at": "<RFC3339>",
 "verify_url": "https://verify.anaxstandard.ai/?id=canal-<ts>-<rand>"
}

Every field in that block already exists in the current implementation. The projection an A2A counterparty needs is the projection GET /canal/verify/:seal_id already computes — including its deliberate stripping of clearance_id, the envelope access key, while retaining chain_seq, is_genesis and prev_hash as non-sensitive position context.

Normative requirements.

4.4 The Bilateral Record

The object the Crossing Seal is computed over. IMPLEMENTATION PENDING — this is the Bilateral Crossing, and it does not exist: today's Canal Crossing carries one ai_system, an owner reference, and no counterparty field anywhere in the contract, the transaction store, or the chain.

{
 "record": "anax-bilateral-crossing-v1",
 "crossing_id": "<uuid>",
 "created_at": "<RFC3339>",

 "parties": [ // exactly 2 — see normative note
 {
 "role": "initiator", // "initiator" | "responder"
 "principal_id": "urn:anax:principal:<opaque>",
 "agent_id": "<A2A agent identity>",
 "clearance_id_hash": "<sha256>", // HASH, never the key itself
 "trust_basis": "vicca_authority_sealed",
 "agc_level": 3,
 "open_mandate_hash": "<sha256>",
 "closed_mandate_hash": "<sha256>",
 "signer_role": "agent", // "human" | "agent" — T2 | T1
 "governance_basis": { "pack_id": "<pack>", "pack_version": "1.2.0" }
 }
 //... responder
 ],

 "agreement_hash": "<sha256>", // §4.2 — SHA-256(JCS(terms))
 "commitment_class": "<class>", // the §4.1.3 ladder: observe|reversible|irreversible|financial|binding
 "commitment_act": "<act>", // what act; per-profile vocabulary, §4.1.3
 "magnitude_asserted": 250000, // integer, unit fixed by class (§4.1.3)
 "currency": "EUR", // REQUIRED when commitment_class is financial (M-2)

 "a2a_context": {
 "task_id": "<A2A Task.id>",
 "context_id": "<A2A Task.contextId>",
 "artifact_id": "<A2A Artifact.artifactId>"
 },

 "timestamps": {
 "mandates_verified_at": "<RFC3339>",
 "terms_agreed_at": "<RFC3339>",
 "sealed_at": "<RFC3339>"
 },

 "prev_hash": "<sha256 | null>", // chain position, sealed IN — see below
 "chain_seq": 42
}

Normative requirements.

  1. parties MUST contain exactly two entries, with distinct principal_id values and exactly one of each role. (Multilateral crossings are out of scope for v1 and are noted as an open problem, not an omission.)
  2. Mandates are carried by hash, not by value. The record binds to them; it does not republish them. Mandates may carry commercially sensitive constraints, and the Bilateral Record is the input to a publicly resolvable seal.
  3. clearance_id_hash MUST be a hash. The raw clearance_id is an envelope access key and MUST NOT appear in the record.
  4. Two-level sealing, per the dual-anchoring decision (§4.4.1). A single seal cannot commit to two different prev_hash values, and a bilateral crossing has two clearance-envelope chains. The value is therefore split:
joint_seal = SHA-256( canonical(Bilateral Record, chain position EXCLUDED) ) // party-independent
anchor_i = SHA-256( joint_seal ‖ prev_hash_i ‖ chain_seq_i ) // one per party
// ‖ is NORMATIVE from v0.4 (adopted 2026-09-05):
// anchor_i = SHA-256( UTF-8( `${joint_seal}|${prev_hash ?? "genesis"}|${chain_seq}` ) )
// "|" is the literal 0x7C; genesis prev_hash is the string "genesis"; chain_seq is decimal, unpadded.
// Vectors AN-1 (genesis) and AN-2 (non-genesis) are published below; a second implementer MUST match both.

Conformance vectors — series AN- (folded into this section at v0.4.3; previously in an internal addendum). Fixtures are themselves SHA-256 of fixed strings so anyone can regenerate them: joint_seal = SHA-256("anax-an-vector:joint_seal"), prev_hash = SHA-256("anax-an-vector:prev_hash").

Vector prev_hash chain_seq Preimage anchor
AN-1 genesis null 0 e2cd3bbd…f270|genesis|0 0389b62946981d1155cb6ab1b70ad99f15f3f9b66cccdbdb477976948842d85e
AN-2 non-genesis 293e3037…4012 42 e2cd3bbd…f270|293e3037…4012|42 3d907220b49faf996328fe47102d8941929e38cf9232026349b54dcdfe53e2cd

Full fixture values: joint_seal = e2cd3bbdb71cbf699b3b554a7081c7a24e695c923437906b55fbc67aba30f270, prev_hash = 293e3037ba29ad930f1b9357aaff94d41e075a06c50efa99a9c40ee3f4a44012.

  1. A crossing whose chain position cannot be established MUST NOT be sealed. Refuse; do not degrade.
  2. Both parties MUST be able to independently recompute the seal from the record.
  3. Party binding (v0.4, adopted 2026-09-06). For each entry p in parties: p.agent_id MUST be the agent subject (sub) of the Mandate at p.closed_mandate_hash, and that Mandate's open_mandate_hash MUST equal p.open_mandate_hash. For an ANAX-derived subject, p.agent_id is urn:anax:agent:<sha256(lowercased owner)> and no other form. A record whose party does not satisfy this is not the record of that party's commitment. (Why: without it, any holder of a valid Closed Mandate for the agreement could seal as a party it is not — the hash in the record is whatever the initiator wrote. Req 7 makes the presented bytes, the record's hash, and the record's named agent one fact. principal_id stays opaque; agent_id is the join.)

4.4.1 Chain placement — ✅ DECIDED: Option A, dual anchoring

Today's chain is keyed per clearance envelope: one chain per clearance envelope, unique on (envelope, sequence), and the seal is computed over a basis that includes prev_hash. A bilateral crossing has two envelopes, and therefore two possible chain positions with two different prev_hash values.

⚠ This surfaces a genuine tension in §4.4 requirement 4. A seal cannot simultaneously commit to two different prev_hash values. Any option that anchors in both chains requires splitting one value into two levels.

✅ RESOLVED (2026-08-09): Option A — dual anchoring — is APPROVED. §4.4 requirement 4 is restated above in terms of the two-level split. The options analysis below is retained as the record of why.

The two-level split (required by Options A and D, not by B or C):

joint_seal = SHA-256( canonical(Bilateral Record without chain position) ) // party-independent
anchor_i = SHA-256( joint_seal ‖ prev_hash_i ‖ chain_seq_i ) // one per party

Both parties compute an identical joint_seal; each computes its own anchor. The existing property — a seal that commits to its own chain position — is preserved at the anchor level, and the new property — a seal both parties can independently derive — is satisfied at the joint level.

Option How it works For Against
A Dual anchoring (recommended) Each party appends to its own envelope chain; each anchor references the shared joint_seal; mutual cross-reference recorded in the Bilateral Record. Each party's own chain stays a complete record of its own commitments. Neither party depends on the other's infrastructure for its own evidence. Existing per-chain contention logic works unchanged — each anchor is an ordinary single-chain append. Requires the two-level split, i.e. reopens §4.4 req 4. Two writes, so a partial-write window exists (§5.6).
B Single designated chain The initiator anchors; the responder holds a reference only. Simplest. Preserves every existing invariant with no change. One write, no partial-write window. Asymmetric. The responder's own chain has a hole where its commitment should be, and it depends on the counterparty's infrastructure for its own audit trail. For a standard whose premise is that neither party need trust the other, this is the wrong shape.
C Third joint record A new chain keyed by crossing_id, independent of both envelopes. Clean symmetry; no two-level split needed. Neither party's own envelope chain shows its bilateral commitments, so a party auditing itself misses them. Needs a new UNIQUE key and new contention logic — the existing hardened path is not reused.
D Hybrid (C + A) Joint record on its own chain, plus per-party anchors referencing it. Most complete. Both the joint view and each party's self-audit are whole. Most work; three writes; two new failure modes to specify. Hard to justify before a first implementation exists.

✅ DECIDED: Option A — dual anchoring. The decisive fact is that the per-envelope audit endpoints already exist and are already per-envelope: an authenticated owner-scoped verify endpoint and its export counterpart. Under Option B or C, a party exporting its own chain for a regulator, insurer or court would produce a record with its bilateral commitments missing — which defeats the purpose those endpoints exist for. Option A preserves them, at roughly a third of the cost of D.

Option D remains additively reachable, and its natural future host is named. A joint chain can be added on top of Option A without migration: the joint_seal is already party-independent, so a central registry consumes exactly the value both parties already compute, and no existing anchor, chain or exported record changes. That registry's natural home is the central crossing registry of the FRYKTORIA Centre (roadmap). Recorded here so that the decision to start with A is understood as a first step rather than a ceiling.

Consequences applied in this draft:

4.4.2 Chain scoping — one chain per counterparty pair (v0.4, adopted 2026-09-06)

A party's anchors for bilateral crossings are not one undifferentiated chain. They are scoped per counterparty pair, so that no relationship leaks into another through prev_hash.

Normative.

  1. chain_id for a crossing is a deterministic function of the two parties' agent subjects (§4.4 req 7 agent_id), independent of role and order: chain_id = SHA-256( UTF-8( min(agent_id_A, agent_id_B) || "|" || max(agent_id_A, agent_id_B) ) ), where min/max are by byte-wise (code-point) comparison of the UTF-8 strings. Both parties compute the same chain_id for the same pair.
  2. Each party keeps its anchors per chain_id: chain_seq starts at 0 at the first crossing of the pair (prev_hash = null, the genesis of that relationship — the §4.4 anchor rule hashes it as the literal genesis) and increases by one per sealed crossing of the same pair. (chain_id, chain_seq) is unique per party.
  3. prev_hash MUST be the previous anchor of the same chain_id and nothing else. An anchor that references a prev_hash from a different pair's chain is malformed (CHAIN_POSITION_UNAVAILABLE at seal; chain_position_valid: false at verify). Consequently a verifier holding one relationship's chain learns nothing about the existence, count or timing of any other relationship of either party.
  4. crossing:verify reports chain_id alongside prev_hash, chain_seq, is_genesis (§3.7.3); it does not report the subjects the id was derived from.

(Why: a single chain per party would make every counterparty a witness to every other — the previous anchor of a crossing with B would be the prev_hash in a record shared with C. Envelope chains (§4.4.1) are already scoped per clearance_id; this is the same discipline for the bilateral case. The cost — a genesis per relationship — is no cost: genesis is a value, not a ceremony.)

4.5 Commitment state — and why it is not a TaskState

This is a forced deviation from an earlier draft.TaskState is a closed enumeration of eight values: TASK_STATE_SUBMITTED, TASK_STATE_WORKING, TASK_STATE_COMPLETED, TASK_STATE_FAILED, TASK_STATE_CANCELED, TASK_STATE_REJECTED, TASK_STATE_INPUT_REQUIRED, TASK_STATE_AUTH_REQUIRED.Extensions may not add new values to enum types.

the design analysis proposed "a State Machine extension adding a committed state". That proposal is not conformant as literally stated — and it is precisely the trap the design analysis itself warned about at §B4.1, now confirmed against the actual enum rather than anticipated. The resolution:

The core TaskState remains one of the eight. Commitment is an extension-scoped state, carried in Task.metadata under the extension URI.

Extension state Core TaskState Meaning
mandates_pending TASK_STATE_AUTH_REQUIRED Counterparty must present mandates. (A near-exact fit — this core state exists for precisely this shape of requirement.)
terms_proposed TASK_STATE_INPUT_REQUIRED Terms on the table, awaiting counter-signature.
sealing TASK_STATE_WORKING Mandates verified; seal being written.
committed TASK_STATE_COMPLETED Sealed. The Crossing Seal exists and resolves.
refused TASK_STATE_REJECTED A normative refusal — expired mandate, magnitude exceeded, counterparty unverifiable.
failed_unsealed TASK_STATE_FAILED Seal could not be written. No commitment was made.

⚖ Normative, and it is the most important rule in §4: A verifier MUST NOT infer commitment from TaskState alone. TASK_STATE_COMPLETED on a Governed Crossing task means the task finished — it does not mean a commitment was sealed. Only a resolvable Crossing Seal proves a commitment. An implementation that treats TASK_STATE_COMPLETED as commitment has implemented a downgrade attack against itself.The mapping above is a genuine gain rather than a workaround. TASK_STATE_AUTH_REQUIRED and TASK_STATE_REJECTED already exist and already mean approximately the right thing, so the failure paths land on core states that unextended A2A agents can interpret. An agent that does not implement Governed Crossing still sees "this task was rejected" — the correct impression — rather than an opaque state.


5. Protocol Flows

5.1 Overview

Five phases. Each MUST complete before the next begins; there is no pipelining, and in particular no phase may begin on the strength of a predicted outcome of an earlier one.

 P0 Discovery & activation Agent Cards read, extension activated (§3.5)
 │
 P1 Mandate exchange Open Mandates exchanged and screened (§5.2)
 │
 P2 Terms proposal Terms Document converged; agreement_hash (§5.3)
 │ computed INDEPENDENTLY by both parties
 │
 P3 Mutual mandate verification Closed Mandates issued, exchanged, and each (§5.4)
 │ verified against its own Open Mandate
 │
 P4 Joint sealing Bilateral Record built; joint seal computed (§5.5)
 │ by both; chain write(s) performed
 │
 P5 Seal distribution Seal attached to Artifact; both parties (§5.6)
 confirm resolvability at the VA

Extension states (§4.5) advance mandates_pending → terms_proposed → sealing → committed, with refused and failed_unsealed as terminal alternatives.

⚖ Governing rule for every phase: refuse, never degrade. Inherited from existing ANAX behaviour. At no point in this flow is a partial success an acceptable outcome. A commitment is made or it is not.

5.2 P1 — Mandate exchange

Each party sends its Open Agreement Mandate in Message.metadata under the extension URI.

Screening verification. On receipt, a party MUST check, before proceeding:

  1. Signature validates, under a non-deterministic scheme (§4.1.1).
  2. vct is mandate.agreement.open.1.
  3. exp is in the future.
  4. iss resolves to the claimed Principal (§4.1.5).
  5. permitted_counterparties includes this party, or explicitly states unbounded. (v0.4 note: at crossing v1 this claim is issued by nobody and verified by nobody, so item 5 is NOT enforced by the reference implementation. Accepted for v1 because the two bindings that matter already hold elsewhere: the Closed's aud names the counterparty (§5.4 check 7) and §5.4 check 9 binds each party's Mandates to the record by hash and subject. An Open's aud is the Verification Authority (§4.1.3) and is not a counterparty check; a responder MUST NOT refuse an Open on its aud. Hardening pass: issue the claim on Opens, verify it here.)
  6. commitment_class overlaps with the class this crossing concerns.
  7. If the counterparty intends autonomous (T1) closing, cnf is present.

Failure at P1 MUST terminate the crossing. A party MUST NOT proceed to negotiate terms it cannot lawfully be offered. Screening here is not an optimisation — negotiating first and checking authority afterwards is how a party ends up holding an agreement it knew, at the time it was made, could not be honoured.

Normative: a party MUST NOT disclose its magnitude_limit beyond what permitted_counterparties and commitment_class require.A counterparty that learns the exact ceiling learns exactly what to ask for; this is the pressure-negotiation surface of §7.5, and the mitigation begins here, at disclosure, not later at refusal.

5.3 P2 — Terms proposal

The parties converge on a Terms Document (§4.2). This specification does not govern negotiation content; it governs what happens to the result.

Normative:

  1. Both parties MUST independently compute agreement_hash over the canonical serialization.
  2. Both MUST exchange and compare the computed values before any Closed Mandate is issued.
  3. A mismatch MUST abort the crossing. Neither party may adopt the other's value, propose a tie-break, or proceed on the assumption that the difference is cosmetic.
  4. A party that cannot canonicalize the document MUST treat that as a mismatch, not as a pass.

Aborting on mismatch is not defensive tidiness. Two parties who seal against different documents have produced a record that proves a commitment neither of them made — the exact failure a Crossing Seal exists to make impossible.

5.4 P3 — Mutual mandate verification

Each party issues a Closed Agreement Mandate binding agreement_hash, open_mandate_hash, magnitude_asserted, crossing_id, nonce and signer_role, and sends it to the counterparty.

Binding verification. Each party MUST verify the counterparty's Closed Mandate against the counterparty's Open Mandate:

  1. Signature validates; if signer_role is agent, the signing key MUST match the Open Mandate's cnf.
  2. open_mandate_hash matches the Open Mandate received at P1.
  3. agreement_hash matches the value agreed at P2.
  4. commitment_class is one of the classes the Open Mandate permits.
  5. magnitude_asserted satisfies magnitude_limit (§4.1.3) — one integer against one integer, in the unit the class fixes. (v0.4: magnitude_asserted is record-level, one per crossing; it MUST satisfy both parties' Closed magnitude_limit and, through them, both Opens' declared limits — conjunctive across parties.) (v0.4.2: the magnitude is a single integer on the record and on each Closed Mandate (§4.1.2); the earlier "every dimension" wording described a per-dimension object no Mandate carries in this specification and is withdrawn.)
  6. exp on both mandates is in the future at the moment of verification, not merely at issuance.
  7. aud names this party — the Closed Mandate's aud. (v0.4: the Open's aud is the Verification Authority and is not checked here or at P1.)
  8. nonce has not been seen before for this crossing_id.
  9. Party binding (v0.4) — seven equalities (the seventh from v0.4.4), all MUST hold. For the initiator: SHA-256(initiator_closed_mandate) == parties[initiator].closed_mandate_hash, closed.sub == parties[initiator].agent_id, closed.open_mandate_hash == parties[initiator].open_mandate_hash, closed.commitment_act == record.commitment_act; and the same for the responder against its own stored Closed Mandate and parties[responder]. Failure on either party is MANDATE_PARTY_MISMATCH (§3.7.4). This check is pure verification and precedes any consumption. (v0.4.4, normative) A Closed Mandate MUST name the act it is drawn for (commitment_act, §4.1.3); the responder MUST refuse, as MANDATE_PARTY_MISMATCH, a Closed whose act is absent or differs from the record's, and, as MALFORMED_MANDATE, a record whose act is outside the profile's act vocabulary (§4.1.3).

Magnitude equality (v0.4.2, normative). The record's magnitude_asserted MUST equal the asserted magnitude of each party's Closed Mandate (§4.1.2 magnitude_asserted); a mismatch is refused MAGNITUDE_MISMATCH (§3.7.4). This is an integrity check distinct from the budget ceiling (MAGNITUDE_EXHAUSTED): the former means two sealed documents disagree on the amount, the latter means the amount exceeds the Mandate. It is pure verification and precedes any consumption.

Revocation at commit (v0.4.1, normative). A Mandate that was active when it was consumed may be revoked before the seal is written. The responder MUST re-read the status of both Closed Mandates inside the transaction that writes the seal, holding a read lock on both rows so that a concurrent revocation either lands before the read or waits for the write; if either Mandate is no longer active the seal MUST be refused MANDATE_REVOKED (§3.7.4), nothing is written, and the refusal is recorded with both consumptions marked as spent (§11-17, cost (b)). This is the bilateral form of the Mandate Object Specification (forthcoming) §2.4 (a revoked Mandate fails at commit even if it passed at start). The re-read is a read: consumption remains the Registration Authority's alone.

Normative: a verifier that cannot evaluate any check MUST treat it as failed. There is no "unable to determine, therefore accept" branch anywhere in this specification. (This mirrors the fail-closed discipline already in the reference implementation: an empty scope list denies rather than permits.)

5.5 P4 — Joint sealing

Normative:

  1. Both parties MUST construct the Bilateral Record (§4.4) and MUST independently compute the joint seal from it.
  2. The parties MUST compare computed seal values before any chain write. A mismatch aborts (as §5.3).
  3. Each party MUST write its own anchor into its own clearance-envelope chain (§4.4 req 4, §4.4.1 Option A). The joint_seal is shared and identical; the anchors are per-party. A party MUST NOT write an anchor before seal comparison (req 2) has succeeded.
  4. If the chain write fails, no commitment has been made. Both parties MUST enter failed_unsealed (core TASK_STATE_FAILED) and MUST NOT act on the agreement. Retry is permitted; silent acceptance is not.
  5. A party MUST NOT report a commitment as made before it holds a seal value it computed itself and confirmed identical to the counterparty's.

5.6 P5 — Seal distribution, and the delivery window

The Crossing Seal is attached to Artifact.metadata on the Artifact representing the agreement, and echoed into Task.metadata on the terminal Task (§4.3).

⚠ Open problem, stated rather than papered over. Between the chain write and the counterparty's receipt of the seal there is a window in which one party knows a commitment exists and the other does not. This is the two-generals problem and it is not solvable by adding another acknowledgement.

The mitigation is definitional, and it is the right one:

⚖ A commitment is defined as resolvable at the Verification Authority, not as delivered by message.

Consequences, all normative:

  1. A party that has not received the seal MUST NOT conclude that no commitment exists. It MUST resolve crossing_id at the Verification Authority (§6) before acting on that assumption.
  2. Seal distribution is therefore a convenience, not the commitment event. Losing the message loses nothing but time.
  3. crossing:seal MUST be idempotent on crossing_id. A retry after a lost response MUST return the existing seal, never mint a second one. (The estate already holds this discipline: the edu passport id is derived from the submission precisely so that a queue retry is a no-op by construction, after a defect in which a retry wrote a second attestation for one assessment. A second attestation of one commitment is the same failure at protocol scale.)

5.7 Failure paths

Every path below is a normative refusal, not an error to be recovered from by proceeding. In each, refused maps to core TASK_STATE_REJECTED (§4.5), except where noted.

# Failure Detected at Normative behaviour
F1 Expired mandate — exp on an Open or Closed Mandate is past at verification time P1 screening; re-checked at P3 MUST reject. MUST NOT commit. A mandate valid at P1 and expired at P3 MUST fail: expiry is evaluated at the moment of verification, never at issuance. The counterparty MAY be invited to present a re-issued mandate, which restarts at P1.
F2 Magnitude exceeded — magnitude_asserted exceeds magnitude_limit P3 MUST reject. MUST NOT commit. The refusal is structural, not discretionary: there is no override, no "approve anyway", and no human-in-the-loop path that rescues this mandate. The correct remedy is a new Open Mandate from the Principal, or a T2 human-signed Closed Mandate if the Principal's governance permits one for this class.
F3 Counterparty unverifiable — iss does not resolve to the claimed Principal, signature fails, or cnf does not match the signing key P1 or P3 MUST reject. MUST NOT commit. A party MUST NOT proceed on a self-asserted identity. (This is the §2.3 distinction made operational: a claim about oneself is not a verified fact about oneself.)
F4 Canonicalization mismatch — the two computed agreement_hash values differ P2 MUST abort before sealing. Neither party may adopt the other's value or tie-break. Both MUST treat the terms as not agreed.
F5 Downgrade attempt — a commitment is requested or presented without extension activation or without a valid Crossing Seal P0, or on any inbound commitment MUST reject (§3.5.1). The refusal MUST be recorded and MUST be auditable (§3.5.2 req 4). A downgrade attempt is a detectable violation, and detection that is not recorded is detection thrown away.
F6 Seal unwritable — chain write fails or chain position cannot be established P4 MUST NOT commit. State is failed_unsealed → core TASK_STATE_FAILED (not REJECTED: nothing was refused, something failed). Retry permitted; idempotent on crossing_id (§5.6).
F7 Seal mismatch — the parties' independently computed joint seals differ P4 MUST abort. Same discipline as F4.

Normative on refusal messaging. A refusal MUST state which failure path fired, at a granularity sufficient for the counterparty to correct a legitimate error. It MUST NOT disclose the refusing party's magnitude_limit, the contents of its Open Mandate beyond what was already exchanged, or any internal governance verdict. (The estate holds the analogous rule already, and holds it deliberately: unknown, revoked and expired engagement codes are distinct internally and identical externally, because distinguishing them "turns this into an enumeration oracle for anyone holding a list of guesses". F2 is exactly that shape: a counterparty that can probe until refusal stops has measured the ceiling.)

5.8 Named work item — Terms canonicalization

Terms canonicalization — CLOSED. Normative algorithm: RFC 8785, JSON Canonicalization Scheme (JCS). Adopted; §4.2. Not the answer: the existing single-party serialiser — the current single-party utility. Right instinct, one implementation, no published test vectors, and written for a basis constructed by one party. It remains in use for the unilateral Canal seal and is not the bilateral algorithm. ⚖ GATE PASSED 2026-08-31: vectors TD-1…TD-5 produced by a sort-keys / UTF-8 serialiser and reproduced byte-for-byte by an independent RFC 8785 implementation, with a negative control; two implementations, not one run twice. The negative control moved TD-1's digest from cccd1864… to 2b82efb6… on a single-integer change, so the comparison is known to bite rather than merely to pass. The verifier reads its expected values out of the published vector set rather than restating them, so a transcription error cannot present as conformance. Standing rule, independent of the algorithm: both parties compute independently; mismatch MUST abort before sealing (§5.3).

Rationale for preferring a published standard over an internal utility: a bilateral hash must be computable by an implementer who has never seen ANAX code, from a specification, in a language of their choosing. An internal utility cannot meet that bar however correct it is.


6. Verification

6.1 What verification is for

A Crossing Seal is only worth what a third party can do with it. This section defines the resolution path for a counterparty, and for the audiences the design analysis names: regulators, insurers, courts.

6.2 Public verification

The Verification Authority is verify.anaxstandard.ai (§2.2). Seal resolution is delegated to the Canal projection:

GET /canal/verify/:seal_id → public, unauthenticated
``` This endpoint already exists and already computes very close to what a
counterparty needs. Specifically, it **strips `clearance_id`** — the envelope access key — from both the
chain position and the returned basis, while **retaining `chain_seq`, `is_genesis` and `prev_hash`** as
non-sensitive position context. A richer authenticated owner-scoped projection
exists separately and refuses on owner mismatch.That split — public position without the key, private detail behind ownership — is exactly the
projection this specification needs, and it was built before this specification existed. It is the single
most transferable asset from the current implementation.

**What a verifier MUST check** on resolving a seal:

1. The seal resolves at all, and to the `crossing_id` in question.
2. The returned `seal` value equals the value the verifier computes from the Bilateral Record, if it holds
 one.
3. `prev_hash` and `chain_seq` are present and consistent with the chain's own verification endpoint
 (an authenticated owner-scoped endpoint, available to a party for its own
 chain).
4. `pack_id` / `pack_version` are present — the governance basis under which the commitment was judged.
5. The seal is not marked superseded.

**Normative:** a verifier **MUST NOT** treat a non-resolving seal as merely absent evidence. Under §5.6 a
commitment **is** its resolvability; a seal that does not resolve is a commitment that was not made.

**⚠ Note on the portal's input handling.** The passport portal performs **no prefix validation** — a
`canal-` prefixed input routes to the Canal API, a UUID-shaped input is looked up on `id`, and **anything
else is looked up verbatim**. This is convenient today and is
an attack surface tomorrow; it is logged in the internal security backlog and addressed at
§7.6.

### 6.3 Offline verification

Offline verification is **partial by nature**, and the partition matters:

| Property | Offline? | Why |
|---|---|---|
| Mandate signatures validate | **Yes**, given the issuer's public key | SD-JWT verification is self-contained. |
| `agreement_hash` matches the Terms Document | **Yes**, given the document | A hash recomputation. |
| Joint seal matches the Bilateral Record | **Yes**, given the record | A hash recomputation. |
| Closed Mandate satisfies its Open Mandate | **Yes**, given both | Constraint evaluation, no network. |
| **Chain position is genuine** | **No** | Requires the chain. `prev_hash` in hand proves only what was claimed at seal time. |
| **The mandate has not been revoked** | **No** | Revocation is state, and state is not in a JWT. See §7.2. |
| **The seal has not been superseded** | **No** | Same reason. |

⚖ **Normative:** offline verification establishes **integrity**, never **currency**. An implementation
**MUST NOT** describe an offline check as verification without qualification, and a party relying on one
**MUST** state that it did so.The honest formulation for a report or an audit is: *"internally
consistent as of the record held; not checked against the ledger."*

This is not a weakness peculiar to Governed Crossing — it is the same limit every offline credential check
has — but a governance specification that let an implementer blur it would be failing at precisely the
thing it exists to do.

---

## 7. Security Considerations

Each threat is mapped to a **mitigation** or is named as an **open problem**. Open problems are stated
plainly; a specification that presents unsolved problems as solved is worse than one that has fewer
features.

### 7.1 Replay

**Threat.** A captured Closed Mandate or sealed record is re-presented to obtain a second commitment.

**Mitigation — considered adequate.** Four independent binds: `nonce` unique per `crossing_id` (§5.4 check
8); `exp` evaluated at verification time, not issuance (F1); `agreement_hash` binding the mandate to one
specific Terms Document; and `aud` naming the intended counterparty. A replayed mandate therefore fails on
audience, freshness, and terms simultaneously. `crossing:seal` idempotency (§5.6 req 3) ensures that even a
successful replay of the *sealing* call returns the existing seal rather than minting a second.

### 7.2 Mandate theft

**Threat.** An attacker obtains a mandate and uses it to commit.

**Partially mitigated.** An **Open Mandate is holder-of-key, not bearer**: `cnf` binds it to the authorized
agent's public key, so an attacker holding the mandate but not the private key cannot issue a valid Closed
Mandate under it. This is a material improvement on what the estate has today, where authority is carried by
**bearer secrets in both populations** — an admin session on one side and an API key on the other — neither of which distinguishes possession from authority.

**Residual — a stolen Open Mandate still leaks.** It discloses `magnitude_limit`, `commitment_class` and
`permitted_counterparties`. That is a negotiating disadvantage, not an authority compromise, and it is why
§5.2 restricts disclosure at exchange time.

**🔴 OPEN PROBLEM — revocation.** SD-JWT carries no revocation mechanism. Today, a compromised agent key can
only be neutralised by waiting for `exp`. **Proposed direction**: a revocation projection at the
Verification Authority, keyed by `open_mandate_hash`, that a verifier **MUST** consult during P3 when
online — making revocation a currency check of exactly the kind §6.3 already says cannot be done offline.
This is not specified in this draft and **MUST** be resolved before v1.0. Until it is, `exp` **SHOULD** be
set to the shortest interval the business process tolerates.

### 7.3 Seal forgery

**Threat.** A fabricated seal is presented as genuine, or a genuine seal is altered.

**Mitigated for fabrication and alteration.** A seal is SHA-256 over a canonical serialization of the
Bilateral Record; a verifier holding the record recomputes it (§6.3). Chain insertion is constrained by
`UNIQUE(clearance_id, chain_seq)` and by each link committing to its predecessor's hash, so retroactive insertion breaks every subsequent
link and is detectable by a chain walk.

**🔴 OPEN PROBLEM — the Verification Authority is a single point of trust.** A compromised VA can assert
that a seal resolves when it does not, or fail to resolve one that does. Three partial mitigations exist
and none is complete: the seal is **independently recomputable** by any party holding the record; a full
chain **export** endpoint exists so a party can retain its own copy; and the chain's internal
consistency is checkable without the VA's assent once exported. What none of these gives is *detection by a
third party who holds neither the record nor an export.* Named, not solved.The eventual answer is
probably periodic publication of chain head hashes to an independent witness; that is out of scope for v1.

### 7.4 Downgrade to unsealed commitments

**Full disclosure first.**

A2A extensions **default to inactive**. Activation is requested per-request via the `A2A-Extensions` header,
and the responding agent echoes back what it activated. `required: true` on an Agent Card means the agent
**SHOULD** — not **MUST** — reject a client that has not activated a required extension.

It follows plainly, and this specification states it without softening: **omitting the header is an
available path, by design of the transport.** The A2A extension mechanism does not, and does not attempt
to, guarantee that a governance extension cannot be skipped. **The anti-downgrade property cannot be
inherited from the transport layer.**

**The conclusion this specification draws.**

This is the cleanest available proof of the argument the design analysis and arXiv 2606.31498 make independently:
**governance cannot live at the transport layer.** A transport's job is to move messages between
consenting parties, and a mechanism whose activation is negotiated per-request is exactly right for
capability discovery and exactly wrong for obligation. An obligation that either party may decline to
activate is not an obligation. **Endpoint enforcement is therefore required — not as a workaround for a
gap in A2A, but because it is the only layer at which the property can exist at all.** This is the
"missing architectural layer above current interoperability standards, not a missing feature within them", observed concretely rather than argued abstractly.

**Mitigation — the normative pair (§3.5.1), restated because this is where it earns its place:**

> **OUTBOUND.** A Class 2 implementation **MUST NOT** issue a commitment without a sealed Governed
> Crossing.
> **INBOUND.** A Class 2 implementation **MUST reject** any inbound commitment that does not carry a valid
> Crossing Seal.

**No seal, no deal.** The pair converts downgrade from a silent path into a **detectable violation**: a
downgrading party is refused, the refusal is recorded and auditable (§3.5.2 req 4), and the record of
refusals is itself evidence. The protocol cannot stop a peer from trying; it guarantees that trying fails
visibly and leaves a trace.

**Residual, stated honestly.** Two Class 2 implementations that *both* choose to ignore the pair can
transact ungoverned. No specification can prevent that, and none should claim to. What the specification
gives is that neither can later claim the commitment was governed — because no seal exists, and a seal is
the only thing that proves it.

### 7.5 Sycophancy and pressure negotiation

**Threat**. A counterparty — human or agent — pressures an agent into a commitment its
Principal would not sanction: flattery, urgency, incremental concession, appeals to a relationship, or
simply persistence.

**Mitigated for out-of-bounds commitments — and this is the strongest argument for the Mandate primitive.**

> **The Mandate converts a persuasion problem into a bounded, attributable one.**

An agent talked into exceeding its `magnitude_limit` **cannot close a mandate**. The refusal is F2, and F2
is **structural, not behavioural**: there is no override and no discretion to erode. Persuasion cannot
reach past a constraint the Principal signed, because the agent has no key that produces a valid Closed
Mandate outside it. This is a categorically stronger guarantee than instructing a model to be firm, and it
does not degrade with a longer conversation, a more sympathetic counterparty, or a better-crafted appeal.

Attribution follows: every commitment carries `signer_role` (§4.1.3), so *"an agent committed this under
standing authority"* and *"a human committed this"* are distinguishable at verification time, permanently.

**🔴 OPEN PROBLEM — bad deals within limits.** An agent persuaded into a commitment that is *within* its
magnitude limit but *against its Principal's interest* is **not prevented by this specification, and cannot
be.** The commitment is authorized; it is merely unwise. That is a governance-pack and evaluation-harness
problem, not a
protocol problem.

Naming this boundary precisely is itself a requirement: **this specification bounds authority, not
judgement.** An implementer who believes a Crossing Seal proves a deal was *wise* has misread it. It proves
the deal was *authorized* — which is what this specification's one-line claim says, and no more.

### 7.6 Enumeration at the Verification Authority

**Threat.** The public verification endpoint accepts arbitrary input and distinguishes hit from miss,
performing no prefix validation. That is an unauthenticated
oracle for the existence of identifiers.

**Partially mitigated.** Seal identifiers carry a CSPRNG suffix — `crypto.randomBytes`, 48 bits, adopted
specifically because `Math.random` state is recoverable from observed outputs and a shared PRNG stream
would let one tenant predict another's identifiers. Guessing is
therefore infeasible; the residual risk is confirmation of identifiers obtained elsewhere, and volumetric
probing.

**Open, and already owned.** Logged as a security backlog item in the design analysis, with the timing
deliberately chosen: closing it before the first pilot would cost that pilot its cheapness, and by launch
`ASELF-` will be a registered prefix in the passport namespace, at which point an allowlist
becomes cheap exactly when it becomes necessary. This specification adds one requirement: **a Verification
Authority SHOULD rate-limit unauthenticated resolution**, and **MUST NOT** return differential error detail
that distinguishes "malformed" from "not found".

### 7.7 Open problems — consolidated

| # | Open problem | Section | Required before |
|---|---|---|---|
| **OP-1** | Mandate revocation — SD-JWT has none | §7.2 | **spec v1.0** |
| **OP-2** | Verification Authority is a single point of trust | §7.3 | post-v1.0 |
| **OP-3** | Bad deals within magnitude limits — out of protocol scope | §7.5 | ANAX evaluation harness (out of protocol scope) |
| **OP-4** | Enumeration surface at the VA | §7.6 | Front Office launch |
| **OP-5** | Delivery window between sealing and receipt | §5.6 | mitigated definitionally; no further work required |

---

## 8. Relationship to Adjacent Specifications

Governed Crossing is designed to **compose**. It replaces nothing in the stack.

| Specification | Relationship | Detail |
|---|---|---|
| **A2A core** | **Extends** | Governed Crossing is an A2A extension (§3). It adds no core fields, adds no enum values, and carries all data in `metadata` maps — the three constraints A2A places on extensions. An unextended A2A agent interoperates normally and simply cannot make governed commitments. |
| **A2A Secure Passport** | **Composes — does not compete** | Different objects with different truth-conditions: Secure Passport carries **what the caller asserts about itself** (preferences, session context) for personalisation; a Crossing Seal carries **what a third party verified about a commitment**. A Secure Passport **MAY** carry a reference to a Crossing Seal as one of its shared context items. **The composition is legible precisely because the names differ** (§2.3). |
| **AP2** | **Composes — adjacent domain** | AP2 governs **payment**; Governed Crossing governs **agreement**. Governed Crossing **reuses AP2's open/closed mandate pattern and SD-JWT basis** (§4.1) rather than inventing a credential format. The boundary is exact: AP2's `checkout_hash` binds to a **cart** — a thing with a price. There is no hash target for a **term**. An agreement **MAY** reference a payment made under AP2; the payment remains AP2's. |
| **A2A Timestamp extension** | **Composes** | Both place data in `Message.metadata` / `Artifact.metadata`, namespaced by extension URI, so they coexist without collision. Governed Crossing's own `sealed_at` is authoritative for the seal; Timestamp's values are transport-level and **MUST NOT** be substituted for it. |
| **A2A Traceability extension** | **Composes — complementary** | Traceability records **how** a result was reached; Governed Crossing records **under what authority** a commitment was made. Neither substitutes for the other, and an implementation **MAY** activate both.They are the natural pair for an audit: trace plus mandate answers "what happened and who was entitled to do it". |
| **A2A Agent Gateway Protocol** | **Orthogonal** | Concerns routing and intermediation. A gateway **MUST** forward the `A2A-Extensions` header unmodified; a gateway that strips it induces the downgrade of §7.4 and **MUST** be treated as an untrusted intermediary. |
| **MCP** | **Orthogonal** | Agent ↔ tools. No interaction. |
| **UCP** | **Composes** | Commerce primitives (catalog, cart, checkout). An agreement **MAY** reference UCP artifacts within its Terms Document. |

**Positioning, stated once.** ANAX does not compete with the Linux Foundation ecosystem — it plugs into it,
as AP2 did for payments. That is the whole design intent of expressing this as an extension rather than as a
protocol.

---

## 9. Appendix — Worked Example

**Illustrative only. All values are fictional. IMPLEMENTATION PENDING throughout — no capability shown
below exists today.**

**Scenario.** ANAX's front-office agent issues an **engagement code** to a prospective client — the
accepted first-pilot scenario, here extended to its bilateral form.

> **Note on scope.** The **accepted spike is unilateral**: ANAX seals its own Decision Passport for code
> issuance, `ASELF-` prefix, ~1–2 days, no counterparty involved. This appendix shows what the **same
> commitment** looks like once the Bilateral Crossing exists. The two halves are shown together deliberately, because
> the example also demonstrates the §2.3 naming split in practice: **the Crossing Seal is the wire object;
> the Decision Passport is the ANAX-side artifact.** One commitment, two artifacts, two names, doing two
> different jobs.

**Parties.** *Initiator:* ANAX front-office agent, Principal `urn:anax:principal:anax-standards`.
*Responder:* a prospective client's procurement agent, Principal `urn:anax:principal:example-trust`.
**Commitment act:** `engagement_code_issuance`. **Commitment class:** `irreversible` (§4.1.3).
**Tier:** T1 — agent-signed under standing authority.

### P0 — Discovery and activation

```jsonc
// ANAX agent card, capabilities.extensions[0]
{
 "uri": "https://anaxstandard.ai/ext/governed-crossing/v1",
 "description": "Bilateral commitments under verified mandates, sealed and publicly verifiable.",
 "required": true,
 "params": {
 "conformance": "full",
 "verification_authority": "https://verify.anaxstandard.ai/",
 "principal": {
 "id": "urn:anax:principal:anax-standards",
 "clearance_id": "<withheld>", "trust_basis": "vicca_authority_sealed", "agc_level": 3
 },
 "mandate_formats": ["sd-jwt"],
 "commitment_acts": ["engagement_code_issuance", "proposal_within_tariff"],
 "commitment_classes": ["irreversible"] // the ladder value; acts are the separate axis
 }
}
POST /message:send
A2A-Extensions: https://anaxstandard.ai/ext/governed-crossing/v1

P1 — Open Mandates exchanged

// ANAX Open Mandate (SD-JWT payload, abbreviated)
{
 "vct": "mandate.agreement.open.1",
 "iss": "urn:anax:principal:anax-standards",
 "sub": "urn:anax:agent:front-office-01",
 "aud": "*",
 "cnf": { "jwk": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" } },
 "iat": 1786000000, "exp": 1788592000,
 "commitment_act": ["engagement_code_issuance", "proposal_within_tariff"],
 "commitment_class": "irreversible", // highest class authorised (L-1)
 "magnitude_limit": 1, // count of actions (irreversible unit, §4.1.3)
 // duration is `exp` above — the code's six-month validity window; scope (one party,
 // non-renewable) is a term of the agreement and lives in the Terms Document (§4.2).
 "permitted_counterparties": "*"
}

Both sides run the seven screening checks of §5.2. Both pass. State → mandates_pending (core TASK_STATE_AUTH_REQUIRED).

P2 — Terms and agreement_hash

Terms Document (canonicalized per §4.2): cohort <cohort-id>, one engagement code, six-month validity, no fee, assessment under <pack> <version>.

Both parties compute independently and compare:

agreement_hash = 9f2c…a1 (ANAX) agreement_hash = 9f2c…a1 (client) ✓ match

State → terms_proposed (core TASK_STATE_INPUT_REQUIRED).

P3 — Closed Mandates

// ANAX Closed Mandate (abbreviated)
{
 "vct": "mandate.agreement.closed.1",
 "iss": "urn:anax:agent:front-office-01",
 "aud": "urn:anax:principal:example-trust",
 "signer_role": "agent", // T1 — no human signature
 "iat": 1786000420, "exp": 1786004020, "nonce": "b7d1…",
 "open_mandate_hash": "4a10…",
 "agreement_hash": "9f2c…a1",
 "commitment_act": "engagement_code_issuance",
 "commitment_class": "irreversible",
 "magnitude_asserted": 1, // one action, irreversible unit (§4.1.3)
 "governance_basis": { "pack_id": "<pack>", "pack_version": "0.1.0" },
 "crossing_id": "d41e…"
}

Each party runs the eight binding checks of §5.4 against the counterparty's Open Mandate. All eight pass — note magnitude_asserted satisfies magnitude_limit. State → sealing (core TASK_STATE_WORKING).

P4 — Joint sealing

Bilateral Record built per §4.4 — mandates by hash, clearance_id by hash. Both parties compute the joint_seal; values match. Under dual anchoring (§4.4.1) each party then writes its own anchor into its own clearance-envelope chain, both referencing the shared joint_seal:

joint_seal = c8e4… (identical for both parties — this IS the commitment)
anchor_anax = H(c8e4… ‖ 77b0… ‖ 128) → anax-standards chain, seq 128
anchor_trust = H(c8e4… ‖ 2d51… ‖ 17) → example-trust chain, seq 17

Each party's own chain export now contains this commitment — which is the property Option A was chosen for.

P5 — Seal attached

Artifact.metadata["https://anaxstandard.ai/ext/governed-crossing/v1"] = {
 "crossing_state": "committed",
 "seal_id": "canal-<ts>-<rand>",
 "seal": "c8e4…",
 "prev_hash": "77b0…", "chain_seq": 128, "is_genesis": false, "seal_version": 3,
 "pack_id": "<pack>", "pack_version": "0.1.0",
 "outcome": "CLEARED",
 "sealed_at": "2026-08-09T21:15:00Z",
 "verify_url": "https://verify.anaxstandard.ai/?id=canal-<ts>-<rand>"
}

Core TaskState is TASK_STATE_COMPLETED. ⚖ A verifier MUST NOT read that as commitment (§4.5) — commitment is the resolvable seal.

The ANAX-side artifact

Separately, ANAX writes its own Decision Passport for the same action:

<passport-id> → https://verify.anaxstandard.ai/?id=<passport-id>

Deterministic in the submission, frozen namespace, idempotent on retry — the passport-id derivation discipline.

Two artifacts, one commitment. The Crossing Seal is what the counterparty holds and what a regulator resolves to see that a bilateral commitment was made under verified mandates. The Decision Passport is what ANAX publishes about its own governance of the action. Neither is called the other, at any layer — which is §2.3 working exactly as intended.

Verification

GET https://verify.anaxstandard.ai/?id=canal-<ts>-<rand>
 → resolves; chain position confirmed; clearance_id absent from the projection (§6.2)

9A. Licence, Marks and Services

Carried into the specification at v0.4.3 from the licence addendum of 2026-08-25, which the v0.3 merge did not include. Nothing in this section changes a requirement, a wire format or an error name; it states what the text grants, what the names are, and what the operator's services are not.

This specification, its conformance vectors, and the companion specifications published by ANAX Standard (Mandate Object Specification, Crossing Taxonomy, Sovereign Channel Message Contract — forthcoming) are licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). SPDX: CC-BY-4.0. Attribution: "ANAX Standard — anaxstandard.ai". No licence is required to implement this specification.

Reference implementations published by ANAX Standard are licensed under Apache License 2.0. SPDX: Apache-2.0.

Marks. Governed Crossing™, Crossing Seal™ and Decision Passport™ are trademarks of ANAX Standard. Governed Crossing™ designates the protocol and may be used by any conformant Implementer to describe conformance. The names ANAX, ANAX Standard, ANAX Institute, VICCA, VICCA ONE, FRYKTORIA, ANAX Canal and X-Layer are trademarks of their owner and are not licensed by this document.

Services. Operation of a Registration Authority, Verification Authority, or Centre by ANAX Standard is a service and is not licensed by this document.


10. Open Items Before v1.0

Everything this draft knowingly leaves open. Nothing here is a discovery for a later reader to make.

Required before spec v1.0

# Item Source
11-1 ✅ DONE (2026-08-09) — the extension URI serves the specification. Live at https://anaxstandard.ai/ext/governed-crossing/v1 (rendered) and https://anaxstandard.ai/ext/governed-crossing/v1.md (raw markdown). A sanitized publication copy is served; this file remains canonical. An implementer encountering the extension URI can now resolve it and read the spec, as A2A's discovery model assumes. —
11-2 ✅ CLOSED (2026-09-01) — confirmed against the A2A protocol buffers definition: AgentExtension.params is google.protobuf.Struct params = 4; Message.extensions is repeated string extensions = 7; Artifact.extensions is repeated string extensions = 6. PENDING CONFIRMATION markers removed from §3.3 and §4.3.1/§4.3.2. —
11-3 ✅ CLOSED — chain placement decided (Option A, dual anchoring) and §4.4 requirement 4 restated for the joint-seal / anchor split. Retained struck-through as record; not one of the outstanding items. —
11-4 ✅ CLOSED (2026-08-31) — RFC 8785 (JCS) adopted; the adoption gate passed with TD-1…TD-5 and two independent implementations producing byte-identical digests. §4.2, §5.8. —
11-5 Specify mandate revocation (OP-1). SD-JWT has none; today a compromised agent key can only be neutralised by waiting for exp. §7.2
11-6 ✅ CLOSED (2026-09-01) — §3.7 gives params, result, a 17-name error vocabulary with JSON-RPC and HTTP codes, determinism and versioning for both methods; §3.6 gives the per-transport binding. §3.6, §3.7
11-7 ✅ CLOSED (2026-09-01) — commitment_class fixed to the five-value ordered ladder with L-1…L-5; magnitude_limit fixed as a non-negative integer whose unit is set by class, cumulative per Mandate, with M-1…M-5; commitment_act added as the separate axis. §4.1.3
11-16 🔴 ⚠ v0.4 note, 2026-09-09 — what is enforced, and what is not. The 2026-09-01 wording below described a specification with no implementation and is retained as the record of that date; it is now wrong in both directions, and the direction that matters is that it understates what runs. Measured, and dated: crossing:seal and crossing:verify are implemented and conformant — the responder implementation and the Verification Authority's resolver; the first bilateral crossing was sealed and publicly verified on 2026-09-07 (joint_seal computed identically by both parties; genesis anchor written), with WC-2, WC-3, WC-5, WC-6 exercised live and WC-1, WC-4, WC-8, WC-8b, WC-9 green in the implementation's own suites. commitment_class IS enforced on the crossing path by the authority judge (L-1) and, for a bilateral crossing, by the full §5.4 check set including check 9 (party binding). magnitude_limit IS enforced atomically at the Registration Authority: a Closed Mandate is spent once, whole (M-4b), and its draw is booked against its Open at issuance (M-4a). CM-1…CM-6: 4 pass, 2 conditional, 0 fail — CM-4 and CM-6 are conditional because financial is unreachable under the operator's charter, and their reachable half is proven at issuance. STILL NOT ENFORCED — this item stays 🔴 until each of the three closes: (i) the mandated-act list is three acts (crossing:seal for both parties; one chain-verification read; one credential-provisioning act) and exists only in prose — there is no committed list and no parity check between the list and the code, so a gate can be removed or acquired without anything noticing. Canal's main path is Mandate-optional by charter, not by omission: the operator's charter names credential issuance as the one provisioned act. (ii) a commitment_class is a caller's declaration with no floor derived from the act, so the ladder is enforced against a self-declared number — the first live bilateral crossing declared observe for crossing_seal, an act that wrote an immutable anchor and spent two Mandates, and every check passed because every check compared the declaration to the declarer's own Mandate. (iii) the canonical WC suite has no live mode and therefore certifies nothing that runs: it now locates the implementation and still reports every vector as NOT IMPLEMENTED. ⚖ This specification MUST NOT be read as describing a fully enforced system. It MAY now be read as describing a system whose bilateral crossing path is implemented, conformant and live, and whose single-party path is governed only where the Charter says it is. Overclaiming the first half and underclaiming it are both refused. — The 2026-09-01 record follows. ⚠ ENFORCEMENT — the vocabulary and the wire contract are specified and NOTHING IMPLEMENTS OR ENFORCES EITHER. §4.1.3's rules have no enforcing component: the only envelope validator in the reference implementation reads jurisdiction, sector, decision type, automation level, special category, children's data and oversight, and contains no reference to commitment_class or magnitude_limit. §3.7's methods have no handler, route or method string anywhere. Measured 2026-09-01: CM-1…CM-6 fail 6 of 6; WC-1…WC-7 fail 7 of 7, the CM vectors by being silently accepted and the WC vectors by having nothing to call. This specification MUST NOT be read as describing an implemented system, and v0.3 MUST NOT claim enforcement or wire conformance, until both vector suites pass. Publishing a vocabulary as though it were a control is the failure this project has already paid for twice. §3.7, §4.1.3
11-17 🟡 The draw-at-issuance rule's two known costs, stated so nobody discovers them live (v0.4, 2026-09-06). (a) No release at v1. A Closed Mandate that expires unsealed leaves its draw booked against its Open (M-4a); nothing gives it back. The Open's own exp bounds the loss; a release primitive (or reserve-then-confirm) is surface the Registration Authority does not have and is not specified here. (b) A chain-write failure after the spend needs a fresh Closed. M-4b spends both Closed Mandates before the anchor write (a refused crossing is never anchored — the invariant); if the write then fails, §5.5 req 4 applies (failed_unsealed, retry permitted) but the spent Closed cannot be reused — the retry draws a new Closed from the Open. This is the cheap failure, accepted; the expensive one — an anchored crossing with no authority behind it — is impossible by construction. Closes when a release or two-phase spend is specified and implemented, or when v1.0 accepts both costs as final. §4.1.3 M-4a/M-4b, §5.5 req 4

Deferred beyond v1.0

# Item Source
11-8 Verification Authority as a single point of trust (OP-2). Probable direction: periodic publication of chain head hashes to an independent witness. §7.3
11-9 Multilateral crossings. v1 fixes parties at exactly two. More than two is out of scope, deliberately, and is an omission with a stated reason rather than an oversight. §4.4
11-10 Enumeration surface at the Verification Authority (OP-4). Already owned in the internal security backlog, with timing deliberately chosen: close before Front Office launch, when an allowlist becomes cheap exactly as it becomes necessary. §7.6
11-14 Multilateral Crossing — N-party joint commitments under a single joint_seal. The dual-anchoring model generalizes: joint_seal remains party-independent; anchor_i per party, N anchors. Natural fit with the central crossing registry (the Option D path at §4.4.1). Candidate for /v2 or a companion extension. (Expands 11-9, which records the v1 scope decision; this is the design sketch, that is the deferral.) §4.4, §4.4.1
11-15 Collective Mandate — mandates issued by group principals without a single representative: threshold/multisig issuance (k-of-n internal signatures) so the Verification Authority can verify quorum was met WITHOUT visibility into internal deliberation. Bridges this specification's authority layer to community-governance dimensions (deliberation, voting) that remain out of scope per §7.5. §4.1, §7.5

Owned elsewhere — recorded here so it is not lost

# Item Owner
11-11 The Mandate primitive — object, store, issuance, and the organizational delegation chain. This specification consumes it and MUST NOT fork it. ANAX platform — the Mandate primitive
11-12 The Bilateral Crossing — the second party in the Canal contract and seal basis, with a sequencing rule that keeps new crossings from appearing superseded. ANAX platform — the Bilateral Crossing
11-13 Bad deals within magnitude limits (OP-3). Out of protocol scope by construction — this specification bounds authority, not judgement. Belongs to the evaluation harness, which does not exist in any repository today. ANAX evaluation harness (out of protocol scope)

11. Change Log

v0.4.4 — 2026-09-17 — act binding (§5.4 check 9, seven equalities; unknown act refused)

Normative, additive (E-3): no name removed or renamed; MANDATE_PARTY_MISMATCH and MALFORMED_MANDATE each gain a case. §5.4 check 9 (party binding) now holds seven equalities: the seventh binds each party's Closed Mandate to the record's act — closed.commitment_act == record.commitment_act. Six equalities bound bytes, subjects and the Open and left the act loose, so a Closed drawn for one act could seal a record declaring another with every check green. Stated with it: a Closed Mandate MUST name the act it is drawn for; the responder MUST refuse, as MANDATE_PARTY_MISMATCH, a Closed whose act is absent or differs from the record's, and, as MALFORMED_MANDATE, a record whose act is outside the profile's act vocabulary (§4.1.3) — an unlisted act has no floor, and "no floor" may not mean "no floor check". §4.1.3's note that L-5 does not make an unrecognised act malformed stands: the act is bounded by the vocabulary at the seal, not by the class ladder. The v0.4 bullet below is corrected to the same count. Reference implementation: the seal binds the act to the record (the seventh equality of check 9) and refuses an unlisted act; the Registration Authority refuses to issue an act-less Closed; the row holds the same rule as a CHECK.

v0.4.3 — 2026-09-16 — Licence, marks and services (§9A); anchor vectors folded (§4.4)

Additive; no wire, rule or error-name change. New §9A Licence, Marks and Services carries the licence addendum of 2026-08-25 that the v0.3 merge did not include: the CC BY 4.0 / Apache-2.0 split (specification text and vectors / reference implementations), the trademark notice (Governed Crossing™, Crossing Seal™, Decision Passport™; the ANAX product names reserved), the statement that Governed Crossing™ may be used by any conformant Implementer to describe conformance, and the clause that operating a Registration Authority, Verification Authority or Centre by ANAX Standard is a service not licensed by this document. ™ added to the §2 definitions of Governed Crossing and Crossing Seal. §4.4: the anchor conformance vectors AN-1 and AN-2 are now published in the specification itself, with the two fixture preimages, instead of being cited from an addendum the public copy did not carry.

v0.4.2 — 2026-09-15 — MAGNITUDE_MISMATCH, magnitude equality, WC-11 (normative)

Normative addition. Added the error name MAGNITUDE_MISMATCH −40035 (HTTP 403, raised by seal) to §3.7.4, a magnitude equality rule in §5.4 (the record's magnitude_asserted MUST equal the asserted magnitude of each party's Closed Mandate; a mismatch is refused before any consumption), and conformance vector WC-11. This is an integrity check distinct from the budget ceiling: MAGNITUDE_EXHAUSTED means the amount exceeds the Mandate; MAGNITUDE_MISMATCH means two sealed documents disagree on the amount. Additive only — no name removed or renamed (E-3). Consistency edit in the same area: §5.4 check 5, the F2 failure row and the P3 walkthrough said magnitude_asserted satisfies "every dimension" of magnitude_limit; §4.1.2 has always defined it as a single integer in the unit the class fixes, and no Mandate in this specification carries a per-dimension object. The three passages now say "the magnitude"; the integer definition stands. The withdrawn wording is noted in place.

v0.4.1 — 2026-09-15 — MANDATE_REVOKED and WC-10 (normative)

Normative addition. Added the error name MANDATE_REVOKED −40014 (HTTP 401, raised by seal) to §3.7.4, a revocation-at-commit rule in §5.4 (the responder re-reads both Closed Mandates' status inside the seal-writing transaction under a read lock and refuses if either is no longer active; the re-read is a read, consumption stays with the Registration Authority), and conformance vector WC-10 (valid at consumption, revoked before commit → MANDATE_REVOKED, nothing sealed, refusal recorded with both consumptions spent). Closes the window between consumption and commit. Additive only — no name removed or renamed (E-3). The wire form of the Mandate Object Specification (forthcoming) §2.4 for the bilateral path. Two cross-references corrected before publication: the spent-cost cite resolves to §11-17 cost (b), and the Mandate Object Specification is cited as forthcoming, as the Authority Doctrine is.

v0.4 — 2026-09-15 — normative additions since v0.3, and a publication scrub

This is a normative revision, not an editorial one. Between the v0.3 publication (2026-09-01) and this version the following were added to the specification and are carried into the published copy for the first time:

Alongside those additions, the published copy was audited against the publication filter (Standard Doctrine §4ter) and the passages that carried operational detail were rewritten: a customer example (cohort and engagement) and live-issued identifiers (a passport id, seal ids) are replaced by placeholders; internal function, constant, endpoint and repository names are replaced by their role in prose; internal decision labels and test labels are replaced by the rule they name; product id-namespace prefixes are generalized; the certificate-registry host and the portal lookup-logic sentence are removed; the Authority Doctrine is cited by name as forthcoming. A licence line (CC BY 4.0) is added to the front matter. The publication projection enforces the same filter and refuses to write a public copy that carries any of these terms.

v0.3 — 2026-09-01 — Group A addenda merged

Four addenda, drafted separately and merged together in one step. Merging them one at a time would have left this document disagreeing with itself in the interval — §4.1.3 carrying an integer magnitude_limit while §4.4 still carried the object, or §3.6 naming a transport binding for methods whose error vocabulary had not landed.

Why v0.3 publishes at the /v1 extension URI, and why that satisfies §3.1. The URI identifies the extension, not the document; §3.1 freezes it and requires a version increment only for an incompatible change, with /v1 remaining resolvable. Everything in v0.3 is additive at the extension level: a new claim (commitment_act), a wire contract for methods §3.6 already named, new error names, and a canonicalisation that replaces a placeholder. §3.7.6 states the same rule for method evolution.

The one genuine break is named rather than glossed: magnitude_limit changes from an object to an integer. That is incompatible in principle — but the field it changes carried IMPLEMENTATION PENDING and was marked a proposal in v0.1, no implementation of it exists anywhere, and no counterparty has ever activated this extension, so there is no deployed reader whose parse it can break. A /v2 here would freeze a placeholder into the URI space and buy nothing. Recorded so that a later reader can judge the call rather than discover it.

⚠ What this release does not do. It specifies. Nothing in it is implemented or enforced: CM-1…CM-6 fail 6 of 6 and WC-1…WC-7 fail 7 of 7 as of 2026-09-01. See §11-16.

v0.1 — 2026-08-09 — initial draft

Nights 1–2. Nine design deviations raised and resolved during drafting (internal register). Published at the extension URI.


Feedback

This draft is published for community review. Comment, objection, and implementation experience are all welcome — in particular where a normative requirement is unimplementable, ambiguous, or wrong.

contact@viccaone.com


Governed Crossing v0.4.4 DRAFT · ANAX Standard — ANAX Institute · 2026-09-17 Extension URI: https://anaxstandard.ai/ext/governed-crossing/v1 · Verification Authority: verify.anaxstandard.ai