diff --git a/README.md b/README.md index 9d6a974..63f4ad2 100644 --- a/README.md +++ b/README.md @@ -1,98 +1,105 @@ -# PACT — A Contract Layer for Autonomous Agent Commerce +# PACT: a contract layer for autonomous agent commerce **Propose · Agree · Complete · Trust** Today's agent protocols move tasks (A2A, unpriced), money (x402, -unconditional), and payment authorization (AP2, unverified) — but nothing -binds **work to money to proof**. PACT is a proposed contract layer that -closes that gap: - -- **Propose** — sealed-bid, second-price (Vickrey) task awards: truthful - bidding is the dominant strategy, so there is no LLM-vs-LLM negotiation - attack surface. -- **Agree** — a co-signed **Verifiable Task Contract (VTC)** binds parties - (DIDs), scope (hash-committed TaskSpec), price, verification method, and - liability; funds lock in escrow. -- **Complete** — settlement gated on verification, with a fraud-proof - challenge window and challengers paid from the slashed bond. - Verification is graded: re-execution → TEE attestation (RATS/EAT) → - zkML proof → staked jury. (The -00 makes release optimistic by default. - Two audit rounds found that this does not close economically, and -01 - changes the default. See Status below.) -- **Trust** — settlement emits co-signed **Work Attestations**: reputation - as the exhaust of settlement — unforgeable without funding real, bonded - contracts. Contracts compose into **Merkle contract trees** with - cascading liability; repeated dealings run over **contract channels**. +unconditional) and payment authorization (AP2, unverified). Nothing binds +work to money to proof. PACT is a proposed contract layer that closes that +gap, and it specifies exactly four things: + +- **liability** as a required member of a co-signed Verifiable Task + Contract (VTC): a seller bond, a verification fund, a cap and a + restitution basis, agreed before any work starts; +- a **Delivery** object against which the contract is judged; +- a **settlement** procedure whose release of escrow is conditioned on a + declared assurance level, with a challenge path that pays the challenger + from a fund the contract itself provisions; +- a **subcontract tree** through which liability cascades upward as + recovery and never downward as discharge. + +Everything else PACT needs (identity, delegation, discovery, transport, +audit, the payment rail, reputation, a dispute forum) it composes from +existing work and cites. Settlement emits a Work Attestation signed by the +Facilitator, so a seller cannot veto its own negative record. ## Status -- **Submitted to the IETF** (27 July 2026): - [draft-laxsharma-pact-00](https://datatracker.ietf.org/doc/draft-laxsharma-pact/) - is live on the Datatracker. -- Read it: [rendered HTML](https://pact-spec.github.io/spec/draft/draft-laxsharma-pact-00.html) - · [plain text](draft/draft-laxsharma-pact-00.txt) - · [XML source](draft/draft-laxsharma-pact-00.xml) -- This is a **-00 strawman, published for demolition.** Issues and PRs - welcome, especially "here is where this breaks." Feedback is collected - for the next revision in the - [-01 changelog issue](https://github.com/pact-spec/spec/issues/1). - -### Known defects in -00, and what -01 changes +- **Revision -01 is current.** Posted to the IETF Datatracker on + 4 September 2026, expires 8 March 2027: + [draft-laxsharma-pact](https://datatracker.ietf.org/doc/draft-laxsharma-pact/). +- Read it: [rendered HTML](https://www.ietf.org/archive/id/draft-laxsharma-pact-01.html) + · [plain text](draft/draft-laxsharma-pact-01.txt) + · [XML source](draft/draft-laxsharma-pact-01.xml) +- An individual submission with no formal standing in the standards + process. Not endorsed by the IETF. +- The -00 of 27 July 2026 is superseded. Its sources stay in `draft/` so + that citations of it remain checkable. The review that led from -00 to + -01, with dispositions, is in + [issue #1](https://github.com/pact-spec/spec/issues/1). + +### What -01 changed External review and two adversarial audit rounds found that the -00's -settlement economics do not close. Everything is logged in -[issue #1](https://github.com/pact-spec/spec/issues/1), with dispositions. -The three that matter most if you are reading the draft today: - -1. **A defrauded buyer recovers nothing from the bond.** The -00's Section 4.3 - directs the slashed bond to the challenger and then to a neutral sink - "rather than to any party to the dispute", and the buyer is a party to - the dispute. The bond is a fine, not collateral. -2. **Optimistic release exceeds the bond, so defection dominates.** - Honest performance requires roughly `q * ((P - E) + B) >= C`. On the - worked example's own numbers a 10 percent bond needs a 91 percent - detection rate, which nothing in -00 supplies. -3. **Challenger reimbursement is capped by the bond** while re-execution - verification costs about what execution costs, so the reimbursement - requirement in 4.3 is unsatisfiable in the common case. - --01 is targeted for mid-September 2026 and reworks the settlement core, -adds a Delivery object and a Verifier role, and corrects the x402, A2A -and AP2 bindings. The repository is being corrected ahead of it where a -fix does not depend on those design decisions. -- Not endorsed by the IETF; an individual submission with no formal - standing in the standards process. +settlement economics did not close. A defrauded buyer recovered nothing +from the bond, optimistic release let a seller walk away with more than +the bond, and challenger reimbursement was capped by a bond too small to +cover re-execution. The -01 reworks the settlement core around those +findings and narrows the document to what only PACT can specify: + +- The sealed-bid award procedure and contract channels are gone. How a + contract is awarded is out of scope. +- Release is no longer optimistic by default. A contract declares an + assurance mode and a release mode, and a Facilitator must refuse a + contract whose bond cannot cover the declared detection probability. +- Recovery follows a five-rank waterfall that pays the buyer's restitution + before anything is burned. +- A Delivery object and a Verifier role are defined; the Challenge object + the -00 named but never specified now exists. +- `vtc_hash` is computed over the contract including its signature set, + so the digest proves who agreed and not only what was written. +- The A2A and AP2 bindings are gone. The -00 carried an AP2 mandate binding + and an A2A skill identifier; -01 removes both, and the contract schema has + no member for an external task or mandate reference. Section 1.3 says only + that PACT is designed to be usable alongside the adjacent drafts that do + carry them. `price.settlement` names a settlement binding instead, and the + draft reserves one identifier, `pact-escrow`, in a registry it asks IANA to + create. The x402 scheme itself, its payload and its verify and settle + procedures, is not written and is the first item of future work. ## Repository layout | Path | Contents | |---|---| -| `draft/` | The Internet-Draft (XML source, plain-text, HTML) | -| `schemas/` | JSON Schema (2020-12) for every protocol object | -| `examples/` | Worked examples — **hashes really verify** (see below) | -| `tools/validate.py` | Validates examples against schemas and checks every hash commitment | +| `draft/` | The Internet-Draft, -01 and -00 (XML source, plain text, HTML) | +| `schemas/` | JSON Schema (2020-12) for every -01 protocol object | +| `examples/` | Worked examples whose hash commitments verify (see below) | +| `examples/legacy-00/` | The -00 call-for-bids, bid and capability objects, kept so the published -00 stays checkable; not part of the conformance surface | +| `tools/validate.py` | Validates the examples against the schemas and checks every rule the draft states | | `diagrams/` | Protocol diagrams | ## The examples are self-consistent `examples/` is not illustrative pseudo-JSON. The commitments verify: -- `cfb.json` / `vtc.json` `spec_hash` = SHA-256 over the - JCS-canonicalized (RFC 8785) `taskspec.json` -- `criteria_hash`, and `taskspec.acceptance.harness_hash`, = SHA-256 over +- `vtc.json` `spec_hash` is SHA-256 over the JCS-canonicalized (RFC 8785) + `taskspec.json`; +- `criteria_hash`, and `taskspec.acceptance.harness_hash`, is SHA-256 over the JCS-canonicalized manifest of `examples/acceptance-harness/`, which - maps each file's relative path to the SHA-256 of its bytes -- `bid.json` `commitment` = SHA-256 over the JCS-canonicalized reveal in - `bid-reveal.json` -- `attestation.json` `vtc_hash` = SHA-256 over the VTC minus its - `signatures` member - -The validator also checks the rules JSON Schema cannot express (parties -are distinct after normalization, one signature per named party, protected -headers carry `alg`/`kid`/`typ` with an allowed algorithm), evaluates the -assurance constraint of -01 Section 7.2 against the worked figures in -01 -Section 14, pins the canonical key order described below, and runs the -Section 13.3 conformance vectors. + maps each file's relative path to the SHA-256 of its bytes; +- `vtc_hash` in `delivery.json`, `verdict.json`, `challenge.json` and + `attestation.json` is SHA-256 over the JCS-canonicalized contract + **including** its `signatures` member (-01 Section 6); +- the Merkle root of the subcontract tree follows RFC 9162: leaves hashed + with a `0x00` prefix, nodes with `0x01`, split at the largest power of + two less than the count. + +The validator runs 66 checks: 7 schema, 2 canonicalization, 10 hash, +10 rule, 9 assurance-constraint, 6 Merkle, and 22 negative vectors from +the draft's conformance table. The rules JSON Schema cannot express are +checked in code: parties distinct after normalization, one signature per +named party, protected headers carrying `alg`, `kid` and `typ` with an +allowed algorithm, and the assurance constraint of -01 Section 7.2 against +the worked figures of Section 14. ``` pip install jsonschema referencing @@ -109,53 +116,35 @@ implementation. What it does get right, and pins with a vector, is the key order: RFC 8785 section 3.2.3 sorts object keys by UTF-16 code unit, which `json.dumps(sort_keys=True)` does not, the two agreeing throughout the Basic Multilingual Plane and diverging above it. What remains -unimplemented is the ECMAScript number serialization rules over the full -float range. +unimplemented is the ECMAScript number serialization over the full float +range. ## Building the draft ``` pip install xml2rfc -xml2rfc --text --html draft/draft-laxsharma-pact-00.xml +xml2rfc --text --html draft/draft-laxsharma-pact-01.xml ``` ## Relationship to other work -PACT composes A2A, x402 (as a proposed `pact-escrow` release-policy -profile over the merged `auth-capture` scheme, which the -00 text -inaccurately calls a payment scheme), AP2, OAuth token exchange -(RFC 8693), RATS/EAT (RFC 9334/9711), and JCS (RFC 8785). It differs from marketplace-mediated escrow (VCAP), transport -negotiation (AGTP), and passport formats (ATEP, ERC-8004) — and cites and -positions against each in Section 1.2 of the draft. Lineage: the Contract -Net Protocol (Smith, 1980), finally runnable among untrusting parties. +PACT composes JWS (RFC 7515) with keys resolved through DID Core, did:web +or a JWK Set, JCS (RFC 8785), the RFC 9162 Merkle tree, RATS/EAT evidence +formats (RFC 9334/9711) for the TEE verification tier, and RFC 9457 problem +details for errors. It names a settlement binding rather than assuming a +rail, so it is chain-agnostic, and it is designed to sit alongside the agent +transport and payment protocols rather than to bind them: -01 specifies no +binding to any of them. Its settlement is an optimistic fair exchange +in the sense of Asokan, Shoup and Waidner (1998). The bond-sizing rule it +relies on is prior art (Polinsky and Shavell; Belenkiy et al.; +Mamageishvili and Felten) that the draft cites rather than reintroduces. +The introduction relates PACT to the adjacent drafts on AP2 binding, +transport negotiation, action receipts, accountability composition, +delegation chains and contestability. Lineage: the Contract Net Protocol +(Smith, 1980), finally runnable among untrusting parties. ## License Code and schemas: Apache-2.0 (see `LICENSE`). The Internet-Draft is subject to the IETF Trust Legal Provisions (BCP 78/79); see `CONTRIBUTING.md`. - - -## -01 - -`draft/draft-laxsharma-pact-01.xml` is the current revision. It narrows the -document to liability, delivery, settlement and subcontract trees, and removes -the sealed-bid award procedure and contract channels (-01 Section 1.2). - -Three things changed that affect anyone checking digests against this -repository: - -- **`vtc_hash` now covers the contract including its signature set** (-01 - Section 6). The -00 excluded signatures, so its commitment proved what was - written and not who agreed to it. Values computed under the two definitions - differ. -- **`liability` gained required members**: `verification_fund`, `cap` and - `restitution_basis`, and the contract gained required `assurance` and - `release` members. An -00 contract does not validate against the -01 schema, - which is intended. -- **The CFB, Bid and agent capability examples moved to `examples/legacy-00/`**, - since -01 does not define those objects. They are kept so the published -00 - stays checkable and are not part of the conformance surface. - -New objects with schemas and examples: Delivery, Verdict, and the facilitator -capability document served at `/.well-known/pact-facilitator`. diff --git a/tools/validate.py b/tools/validate.py index 3372835..90d7473 100644 --- a/tools/validate.py +++ b/tools/validate.py @@ -12,7 +12,8 @@ instrument is committed from inside the TaskSpec as well as by the CFB and the VTC. 5. bid.commitment equals sha256(JCS(bid-reveal.reveal)). - 6. attestation.vtc_hash equals sha256(JCS(vtc without signatures)). + 6. vtc_hash in Delivery, Verdict, Challenge and Attestation equals + sha256(JCS(vtc)) with the signatures member included (-01 Section 6). 7. Rules the schemas cannot express: parties are distinct, one signature per named party, and every JOSE protected header carries alg, kid and typ with an allowed algorithm.