| Internet-Draft | PACT | September 2026 |
| Sharma | Expires 8 March 2027 | [Page] |
A growing family of specifications lets autonomous agents establish identity, delegate authority, record what they did, and move money. None of them makes one party financially answerable to another for a result that was not delivered. This document specifies PACT, which adds liability as a required, co-signed member of an agent contract and propagates it through a subcontract tree.¶
PACT defines the Verifiable Task Contract, a signed JSON object binding parties, scope, price, verification profile, and an explicit allocation of liability; the Delivery object that a contract is judged against; an escrowed settlement procedure whose release is conditioned on a stated assurance level rather than on elapsed time; and a subcontract tree in which a parent's Work Attestation commits to its children by Merkle root and liability cascades upward.¶
PACT does not define an identity format, an authorization model, an audit architecture, a transparency service, a payment rail, or a reputation system. It composes existing work for all of these. Its settlement loop is an instance of optimistic fair exchange, and its bond-sizing rule is the classical deterrence bound; both are cited rather than reintroduced.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 8 March 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
By late 2026 an autonomous agent can prove who it is, show whose authority it acts under, discover another agent, call it, record what happened in a tamper-evident receipt, and pay for the call. Each of those is the subject of active standardisation, and several are specified in more detail than this document specifies anything.¶
What no specification in that family states is who owes whom, and how much, when the work is wrong. Receipts record that an action occurred. Audit records establish whether behaviour matched intent. Payment schemes move value on the payer's instruction. None of them binds a party to a consequence.¶
That gap is not an oversight in those documents; it is outside their scope, and correctly so. It is the gap this document addresses.¶
PACT specifies exactly four things: liability as a required member of a co-signed contract object (Section 5.3); the Delivery object against which that contract is judged (Section 6); a settlement procedure whose release is conditioned on a declared assurance level (Section 7); and a subcontract tree through which liability cascades (Section 10).¶
Everything else PACT needs, it composes and cites. In particular this document does not specify, and implementations MUST obtain elsewhere: agent identity and key distribution; delegation of authority from a human or organisational principal; agent discovery; a transport; an audit or accountability architecture; a transparency service; a payment rail or settlement network; a general reputation system; or a dispute forum.¶
Two mechanisms present in [I-D.laxsharma-pact-00] have been removed rather than revised. Contract channels are withdrawn because the -00 text specified no channel state object, no sequence rule, and no termination condition, and payment channels for agent commerce are specified elsewhere. The sealed-bid second-price award procedure is withdrawn from this document because it is separable from settlement, is fully treated in the multi-agent systems literature, and made the -00 a document about two unrelated things. Neither removal is a judgement that the mechanism is wrong.¶
This document is Experimental. The question it tests is whether a settlement layer that makes liability a co-signed contract term, and conditions release on a declared detection probability rather than on elapsed time, can be implemented independently by more than one party and produce settlements each can verify. The experiment succeeds if two independent Facilitator implementations settle contracts whose Buyers and Sellers use different client implementations, through every terminal state in Figure 2, with attestations either can check. It fails, and that would itself be a result worth recording, if the constraint in Section 7.2 proves unworkable at the prices and verification costs real deployments exhibit. Experience should be reported to the author and to the repository named in Section 15.¶
This revision is a narrowing. The -00 attempted the surface area of a protocol suite in under five thousand words and did not close. Substantive changes:¶
on-verification replaces optimistic release as the default
and the only mode required of conformant implementations
(Section 7.3).¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
All JSON objects defined here are canonicalized with JCS [RFC8785] before hashing or signing. Implementations MUST order object keys by UTF-16 code unit as [RFC8785] Section 3.2.3 requires. Sorting by Unicode code point is a common substitution; it agrees with the required order throughout the Basic Multilingual Plane and diverges above it.¶
Version. The pact member carries a version of the form
major.minor; this document defines 0.1. Every object defined here is
hash-committed and signed, so a member an implementation does not
recognise is inside the commitment and cannot be ignored safely. An
implementation MUST reject an object whose pact version it
does not implement, and MUST reject an object carrying a member this
document does not define for it. Extension is by a new version, not
by adding members.¶
Time. Every timestamp is an RFC 3339 date-time [RFC3339] in UTC with the "Z" designator. The Facilitator's clock governs every deadline and window in this document: the instant at which the Facilitator records an object is the instant that counts, and parties SHOULD allow for skew when acting near a boundary.¶
Money. An amount is a decimal string with no exponent and a
fractional part of two to eighteen digits; comparisons are exact and
no rounding is implied. A currency is an asset identifier whose
namespace is defined by the settlement binding named in
price.settlement, and need not be an ISO 4217 code. A
network is a ledger identifier in the form the same binding defines;
the pact-escrow binding uses [CAIP-2] chain
identifiers.¶
A contract passes through four phases. Propose establishes terms. Agree co-signs them and funds the three value pools. Complete produces a Delivery and a Verdict on it. Trust records what happened in a Work Attestation. The ordering below is normative; in particular a Verdict precedes release under the default release mode.¶
Buyer Facilitator Seller Verifier | | | | |<== VTC negotiated and co-signed ===>| | | | | | |--- lock(P) ------>| | | | |<--- bond(B) ----| | | |<--- fund(F) ----| | | | | | | | [ Seller performs ] | | | | | | |<-- Delivery ----| | | | | | | |-- Delivery + criteria_hash ---->| | |<-- Verdict (signed) ------------| | | | | | |-- release(P) -->| | | | [ window ] [ children final ] | | |-- return(B,F) ->| | | | | | |<-- Attestation ---|-- Attestation ->| |
The challenge window opens when the Verdict is recorded under
on-verification release, and when the contract enters
DELIVERED under on-window and optimistic release; it
closes challenge.window_seconds later by the Facilitator's
clock. Under
on-verification the Buyer's price is released once the Verdict
is PASS; the Bond is not returned until the window closes and every
descendant contract is final (Section 10).¶
+------------+
| PROPOSED |
+------------+
| both signatures present
v
+------------+ deadline, +-----------+
| FUNDED |------------->| ABANDONED |
+------------+ no Delivery +-----------+
| Delivery accepted
v
+------------+
| DELIVERED |
+------------+
| Verdict recorded
+----------+----------+
PASS | | FAIL
v v
+------------+ +------------+
| RELEASING | | DISPUTED |
+------------+ +------------+
| |
window | | remedy applied
closed, | | (Section 7.4)
children v v
final +------------+ +------------+
| FINAL | | SETTLED |
+------------+ +------------+
Under optimistic release DELIVERED proceeds directly to
RELEASING and a Verdict, if one arrives, does so inside the window.
Under on-window release DELIVERED proceeds to RELEASING when
the window closes with no successful Challenge. Under
unsecured release DELIVERED proceeds to RELEASING and no
window opens. FINAL, SETTLED and ABANDONED are terminal, and each
produces a Work Attestation. The -00 had no path to either: expiry of
task.deadline had no stated consequence, so escrow could lock
permanently, and a negative outcome required the signature of the party
it convicted.¶
A VTC is a JSON object, media type
application/pact-contract+json, carrying the members below. A
VTC is valid only if every REQUIRED member is present, the parties are
distinct, and both the Buyer and the Seller have contributed at least
one signature that verifies against a key bound to its identifier. The
Facilitator and any Verifier do not sign the VTC; their assent is
expressed by acting on it, and a Facilitator that will not act on a
contract refuses it at Section 12.1.¶
pact:type:VerifiableTaskContract.¶
id:settlement.¶
parties:buyer,
seller and facilitator identifiers, and OPTIONAL
verifier. Buyer and seller MUST differ. Where
verifier is absent, the Verdict MUST come from a party
satisfying Section 9.1.¶
task:spec_hash,
deadline, and OPTIONAL spec_uri.¶
price:amount,
currency, settlement binding identifier, and
network.¶
verification:tier, profile (Section 9),
criteria_hash, and OPTIONAL arbiter.¶
assurance:mode
and q_min (Section 7.2).¶
release:on-verification.¶
liability:challenge:window_seconds, which MUST be greater than zero, and
max_dispute_seconds.¶
signatures:signatures member, per Section 13.¶
The settlement identifier, the network and the asset are all
carried inside price so that a co-signed VTC is bound to one
venue. The -00 omitted them, which made a signed contract replayable
against any facilitator, chain or token contract.¶
{
"pact": "0.1",
"type": "VerifiableTaskContract",
"id": "vtc_7f3a91",
"parties": {
"buyer": "did:web:acme.example",
"seller": "did:web:dataforge.example",
"facilitator": "did:web:settle.example",
"verifier": "did:web:audit.example"
},
"task": {
"spec_hash": "sha256:bb0e87ce522479b7c2f7bcfa26df7ecd7ff67aeb8b4
15bbd70c22d97c47adf35",
"deadline": "2026-11-14T00:00:00Z"
},
"price": {
"amount": "180.00",
"currency": "USDC",
"settlement": "pact-escrow",
"network": "eip155:8453"
},
"verification": {
"tier": "T0-reexec",
"profile": "acceptance",
"criteria_hash": "sha256:d9205d4f2922afd55c0a2dc4ab00d8ee5a5123
43430bcf5e9abf0c76d66c69f7"
},
"assurance": { "mode": "certain", "q_min": 1.0 },
"release": "on-verification",
"liability": {
"seller_bond": "18.00",
"verification_fund": "0.50",
"cap": "180.00",
"restitution_basis": "released"
},
"challenge": {
"window_seconds": 3600,
"max_dispute_seconds": 86400
},
"signatures": [ { "protected": "...", "signature": "..." },
{ "protected": "...", "signature": "..." } ]
}
Hash values are wrapped here for page width only; they are single JSON strings with no embedded whitespace.¶
Every URI carried inside hash-committed content MUST be accompanied
by a sibling hash over the dereferenced bytes. The -00 committed
harness_uri as a string while leaving the bytes at that URI
uncommitted, which permitted a Buyer to substitute the acceptance
instrument after signature, run the substituted instrument, and submit
the failure as a valid fraud proof.¶
Where the committed content is a bundle of files rather than a
single octet stream, the commitment MUST be computed as
SHA-256(JCS(M)) where M is an object mapping each file's
path, relative to the bundle root and expressed with "/" separators,
to SHA-256 of its bytes. A manifest of per-file digests is
specified rather than an archive digest because archive formats carry
ordering, timestamp and permission metadata that is not stable across
producers.¶
The content committed by spec_hash is a TaskSpec: a JSON
object, canonicalized per [RFC8785] before hashing,
with the members below.¶
description:inputs:schema_uri with its schema_hash, and where a
representative sample is published, sample_uri with its
sample_hash.¶
deliverable:schema_uri with schema_hash.¶
acceptance:thresholds and harness_hash
equal to the contract's criteria_hash.¶
constraints:The acceptance object MUST carry the members REQUIRED for
the contract's tier: harness_uri and harness_hash
for re-execution tiers, enclave and model policy for attestation
tiers, a proof statement with its verifying key for proving tiers, or
rubric_uri and rubric_hash for judgment tiers. An
empty acceptance object MUST be rejected. The -00's schema
permitted one, which made every fraud proof impossible and quietly
converted conditional release into unconditional payment.¶
Thresholds MUST be stated so that they cannot be satisfied by returning almost nothing. A threshold expressed only as a rate over returned rows is satisfied by returning one correct row out of millions; a completeness condition relative to the committed input is therefore REQUIRED wherever the deliverable is a transformation of that input.¶
The liability member is REQUIRED in a VTC. It states, in
advance and with both parties' signatures over it, what each party
owes the other when the contract is not performed. A contract that
does not allocate liability is not a PACT contract.¶
seller_bond:verification_fund:cap:cap from the
Seller under this contract.¶
restitution_basis:released, restoring the Buyer up to value already released,
or price, restoring the full price. Determines the second
rank of the waterfall in Section 7.4.¶
parent:vtc_id and vtc_hash
(Section 10.1).¶
remainder_to:buyer or sink. Absent, sink. A sink is a
Facilitator-designated destination that is not a party to the
contract. buyer is permitted but rewards a Buyer beyond its
loss, which is an incentive to manufacture challenges; the default
exists for that reason.¶
Liability under PACT is bounded by cap and is discharged in
the contract's own currency. This document creates no cause of action
and displaces no other remedy: consequential loss beyond cap,
and any obligation arising outside this contract, are out of band. A
specification that implied otherwise would be claiming to settle
questions it has no standing to settle.¶
A parent member is authenticated not by a separate
countersignature but by the rule in Section 10.1: the
child's Buyer must be the parent's Seller. Since liability is
inside the bytes the Buyer signs, the Buyer's signature on the child is
itself the authorisation to attach it.¶
The Delivery is the object a contract is judged against. The -00 specified none, with three consequences: a Seller that attached no evidence presented nothing that could be shown invalid, so absence of evidence was not a fraud proof; release fired on "delivery", an event the Facilitator had no defined way to observe; and non-delivery had no remedy at all, so escrow could lock permanently.¶
A Delivery is a JSON object, media type
application/pact-delivery+json.¶
pact, type:Delivery.¶
vtc_id, vtc_hash:vtc_hash is computed
over the JCS-canonical VTC including its signatures member,
so the commitment covers who agreed and not merely what was
written.¶
work_hash:work_uri:work_hash, never from the
transport.¶
input_hash:evidence:verification.tier. Its conformance to the tier
profile is a validity condition, not a quality judgement.¶
signature:A Facilitator MUST reject a Delivery whose evidence is
absent or does not conform to the profile named in the VTC, and MUST
apply Section 7.4 as though a FAIL Verdict had been
recorded. This is a conformance rejection, not a judgement on the work:
the Facilitator has checked shape, not substance, which is why it does
not breach the separation in Section 3. This is the rule that makes silence
expensive: under the -00 the cheapest attack was to deliver
nothing verifiable and be paid anyway.¶
Where task.deadline passes with no conformant Delivery
recorded, the Facilitator MUST move the contract to ABANDONED, return
the escrowed price to the Buyer, and slash the Bond to the extent of
liability.restitution_basis. No challenge window opens, because
there is nothing to challenge.¶
{
"pact": "0.1",
"type": "Delivery",
"vtc_id": "vtc_7f3a91",
"vtc_hash": "sha256:b2cccae00fc7b97ba2b6ef6356ff42c006ba661e0249
d7eaa8baff3de553870b",
"work_hash": "sha256:9c1f...",
"work_uri": "https://cdn.dataforge.example/o/9c1f",
"input_hash": "sha256:41ab...",
"evidence": {
"profile": "acceptance",
"instrument_hash":"sha256:d9205d4f...",
"results_hash": "sha256:7e02...",
"results_uri": "https://cdn.dataforge.example/o/7e02"
},
"signature": { "protected": "...", "signature": "..." }
}
A Buyer countersignature over the same canonical bytes constitutes a receipt and moves the contract to DELIVERED without waiting for the Facilitator's own conformance check. A Buyer is not obliged to countersign, and withholding a countersignature is not a Verdict.¶
A contract funds three pools, which the -00 conflated into one. The Escrow holds the Buyer's price. The Bond is Seller collateral and is the source of restitution. The Verification Fund pays for verification performed and for a successful Challenger's documented costs.¶
Separating the second and third is not tidiness. Under the -00 a Challenger was reimbursed from the slashed Bond, so reimbursement was capped by the Bond; for any re-execution profile the cost of producing a fraud proof approximates the cost of the work itself, which exceeds any plausible fraction of a Bond by roughly an order of magnitude. The -00's MUST to reimburse documented verification costs was therefore unsatisfiable in the ordinary case.¶
Escrow (P) Bond (B) Verification Fund (F)
buyer's price seller collateral pays for checking
| | |
1 |-- unreleased ----> Buyer |
2 | | costs <------|-> Challenger
3 | |-- restitution -> Buyer
4 | |-- bounty -----> Challenger
5 | |-- remainder --> remainder_to
A Facilitator MUST NOT permit cumulative release before a recorded Verdict to exceed the Bond. Value released before verification is value the mechanism can no longer recover, so releasing more than the Bond makes defection profitable by construction, independently of every other parameter.¶
Let P be the price, C the Seller's cost of performing honestly, B the Bond, E the cumulative amount released before a Verdict is recorded, and q the probability that a defection is detected, proven, and adjudicated within the contract's own time bounds. Honest performance is a Seller's best response exactly when:¶
q * ( (P - E) + B ) >= C
¶
A Facilitator cannot evaluate that directly, because C is private to the Seller. It can evaluate a sufficient condition. A Seller that bids rationally has C no greater than P, so requiring the expected recoverable exposure to cover P suffices, and gives a constraint in observable quantities alone:¶
B >= P * (1 - q) / q + E
¶
A Facilitator MUST evaluate this constraint against the contract's
declared assurance.q_min before locking funds, and MUST
refuse a contract that does not satisfy it.¶
Read as a requirement on q rather than on B, and with E set to zero, this is q at least P/(P+B). A Bond of ten percent of price, the conventional figure, is therefore a wager that better than nine in ten defections are detected and proven and adjudicated in time. The -00 stated no such requirement and funded no mechanism that would produce such a rate.¶
This inequality is not new and is not claimed as new. It is the classical deterrence bound, stated for public enforcement in [POLINSKY99], which traces it to Bentham, and for outsourced computation, with the fine posted in advance as a deposit held by the principal, in [BELENKIY08] Theorem 1. Its form for rollup validators is [MAMAGEISHVILI23]. The only term this document contributes is E. Every prior statement withholds the reward until checking has had its opportunity, so none of them has a notion of value released before verification concludes. Optimistic release both pays a defecting Seller and puts that payment beyond recovery, so the required Bond rises with it one for one. That is why a contract can satisfy the classical bound at Agree and violate it by the time judgment arrives.¶
The assurance.mode member states how q is produced:¶
certain:committed-sample:sample_rate, is verified. The draw MUST derive from a Buyer seed committed before
the Delivery is submitted, combined with the Delivery commitment, so
that neither party can bias which contracts are checked.¶
open:open as its sole
source of assurance. Open challenge is a backstop against verifier
failure, not a source of q: no party is obliged to look, and
Section 7.4 shows that a bounded reward is
dominated by silence.¶
The release member takes one of four values. A
conformant Facilitator MUST implement on-verification; the
others are OPTIONAL.¶
on-verification:on-window:optimistic:unsecured:The -00 made optimistic release the only mode. Its benefit to the Seller is the time value of the price over the challenge window; its cost is the carry on collateral sized to make it safe. On ordinary parameters the second exceeds the first by more than an order of magnitude, so correctly collateralized optimistic release is close to a null transaction and under-collateralized it is a transfer from Buyer to defecting Seller. It is retained as an option because some deployments will want it, and named honestly.¶
On a FAIL Verdict or a successful challenge, a Facilitator MUST apply the following in order, and MUST NOT proceed to a later rank while an earlier one is unsatisfied:¶
liability.restitution_basis.¶
liability.remainder_to.¶
Ranks 2 and 3 are the correction of the -00, whose waterfall paid the Challenger and then directed the remainder to a neutral sink "rather than to any party to the dispute". Since the Buyer is a party to the dispute, a defrauded Buyer recovered nothing. That mechanism binds work to punishment, not work to payment, and the words restitution, refund, compensation and damages appeared nowhere in it.¶
The bounty at rank 4 MUST NOT be capped at a fraction of the Bond chosen for tidiness. Let X be the Seller's exposure at judgment, the Bond plus unreleased price. A party that discovers a fraud and reports it receives the bounty; a Seller facing X will pay up to X to avoid judgment. Wherever the bounty is less than X there exists a private payment leaving both strictly better off than reporting, so silence dominates the designed mechanism. [BELENKIY08] Theorem 6 gives the corresponding lower bound in its own setting: a bounty of at least r/(1-a), where r is the reward and a is the accuracy a cheating contractor can reach by cheaper means, so never less than the reward itself. The symbol a is used here to avoid a collision with this document's q.¶
Raising the bounty to X is not the answer either, since that leaves nothing for rank 3 and maximises the incentive to manufacture challenges. Two mitigations are specified instead. The reward MUST be non-exclusive: where K parties independently discover the same fraud each receives the full bounty, so buying silence costs K times what reporting pays once. And the Buyer MUST be admissible as a Challenger in its own contract, since a Buyer that recovers restitution by challenging will not accept a bribe below the restitution it forgoes, which places a floor under any bribe a Seller must pay.¶
Buyer Facilitator Verifier Challenger
| | | |
| |<-- Verdict PASS | |
| |-- release(P) -> Seller |
| | [ window opens ] |
| |<------------- Challenge --------|
| |-- Challenge + Delivery -------->|
| |<-- Verdict FAIL | |
| | (supersedes PASS) |
|<- rank 1 ----| unreleased escrow |
| |-- rank 2 (from F) ------------->|
|<- rank 3 ----| restitution (from B) |
| |-- rank 4 (from B) ------------->|
| |-- rank 5 --> remainder_to |
| | SETTLED, Attestation issued |
A Challenge is a JSON object, media type
application/pact-challenge+json, by which any party submits a
fraud proof within the window. Members: pact, type
(the string Challenge), vtc_id,
delivery_hash, a proof object whose members are
profiled by verification.profile, and the Challenger's
signature. A Facilitator MUST reject a Challenge received
outside the window, one whose proof does not conform to the
profile, or one whose delivery_hash does not match the
recorded Delivery. A Challenge that is accepted is evaluated by a
party satisfying Section 9.1, whose finding is a
Verdict; the Challenger's own assertion is not.¶
The Challenger is the party identified by the kid of the
Challenge's signature. A Verdict issued on a Challenge supersedes any
earlier Verdict on the same Delivery, and a Facilitator MUST record
both. A Facilitator MAY require a deposit with each Challenge, stated
as challenge_deposit in its capability document
(Section 8), returned if the Challenge succeeds and
forfeited to the Verification Fund if it does not; this is the
protocol's defence against challenge spam, and
Section 16.12 discusses its limits.¶
{
"pact": "0.1",
"type": "Challenge",
"vtc_id": "vtc_7f3a91",
"delivery_hash": "sha256:5d7c...",
"proof": {
"profile": "acceptance",
"instrument_hash": "sha256:d9205d4f...",
"results_hash": "sha256:a91e...",
"results_uri": "https://watch.example/o/a91e",
"failing_checks": ["schema_valid_rate", "row_count_min"]
},
"signature": { "protected": "...", "signature": "..." }
}
The Bond enters the -00 in its Phase A and never leaves it: no rule anywhere returns it. A Facilitator MUST return the Bond, less any amount applied under Section 7.4, when the contract reaches FINAL or SETTLED, and MUST record the return. It MUST NOT return the Bond while any descendant contract remains non-final (Section 10), because cascading liability requires the parent's collateral to remain exposed until the subtree has settled.¶
Before a Buyer and Seller can co-sign a VTC they must agree on a Facilitator and know what it supports. This document registers one well-known URI for that purpose, per [RFC8615].¶
This is deliberately narrower than agent discovery, which is the subject of separate work and is not restated here. What is discovered is a settlement service's capabilities, not an agent's identity, skills, or endpoints.¶
A Facilitator SHOULD publish a JSON document, media type
application/pact-facilitator+json, at the path
/.well-known/pact-facilitator of its origin. The document MUST
be served over HTTPS. It MUST be signed, and the signature MUST verify
against a key bound to the identifier in facilitator. An
unsigned capability document is not usable for contract formation,
because the members below determine what a party is agreeing to when it
signs.¶
facilitator:parties.facilitator.¶
settlement_bindings:release_modes:on-verification.¶
verification_profiles:assurance_modes:max_contract_value:amount and currency.¶
challenge_deposit:amount and currency, required with each Challenge
(Section 7.5). Absent, no deposit is
required.¶
endpoints:signature:
{
"pact": "0.1",
"facilitator": "did:web:settle.example",
"settlement_bindings": [
{ "id": "pact-escrow",
"networks": ["eip155:8453"],
"assets": ["USDC"] }
],
"release_modes": ["on-verification", "on-window"],
"verification_profiles": ["acceptance", "bisection"],
"assurance_modes": ["certain", "committed-sample"],
"max_contract_value": { "amount": "50000.00",
"currency": "USDC" },
"endpoints": {
"contract": "https://settle.example/pact/v1/contracts",
"delivery": "https://settle.example/pact/v1/deliveries",
"verdict": "https://settle.example/pact/v1/verdicts",
"challenge": "https://settle.example/pact/v1/challenges",
"attestation": "https://settle.example/pact/v1/attestations"
},
"signature": { "protected": "...", "signature": "..." }
}
A client MUST NOT infer any capability from the absence of a member. A Facilitator that does not publish a capability document can still be named in a VTC by prior arrangement; discovery is a convenience, not a precondition.¶
A contract names both a tier, which says what class of
evidence is produced, and a profile, which says what is
actually done to check it. Four tier labels are used in this document:
T0-reexec, deterministic re-execution; T1-tee,
hardware attestation per [RFC9334]; T2-zkml, a
proof of inference; and T3-jury, staked arbitration. Tiers are
a vocabulary, not a registry; profiles are the registered quantity
(Section 18.3). The distinction matters because the tier name
does not determine the security of the contract and the profile
largely does.¶
Consider one task, a bulk data transformation, under two profiles at the same nominal tier. Re-executing the whole computation and comparing outputs costs approximately what performing it cost. Running a committed acceptance instrument against the delivered artifact costs a small fraction of a percent. Those two differ by more than two orders of magnitude in what verification costs relative to the price, and by Section 7.2 they give opposite answers about whether any Bond a Seller would post makes third-party challenge rational.¶
Three regimes follow, and the boundaries are consequences of
Section 7.2 rather than stipulations. Where verification
costs a small fraction of a percent of price, every Delivery can be
checked, assurance.mode of certain is affordable, and
the Bond need only cover harm. Where it is of order one percent,
sampling is efficient but the Bond required to sustain a low fraud rate
approaches the price. Where it exceeds roughly ten percent, no Bond a
Seller would rationally post makes third-party challenge worthwhile, and
a contract at that profile MUST NOT declare open assurance,
because it would be declaring a detection probability nothing
produces.¶
Implementations SHOULD select the cheapest profile that detects the failures they actually care about, rather than the strongest-sounding one. A committed acceptance instrument that is adequate is worth more than a re-execution profile that nobody can afford to run.¶
acceptance:criteria_hash against the Delivery. The fraud proof is a
failing evaluation. Deterministic by construction, since the
instrument is fixed before work begins.¶
bisection:full-reexec:Independence is a relation between the attesting party and the
parties to the contract. It MUST be derived by the evaluator and MUST
NOT be satisfied by a field in which a record declares itself
independent. Party identifiers MUST be normalized before comparison,
and the normalization MUST fold toward identifying the same party:
strip leading and trailing whitespace; lower-case the scheme and, for
did:web and https identifiers, the host; remove any
fragment (a "#" and everything after it) and any trailing "/" or
".". Percent-encoding
MUST NOT be decoded, since an open-ended decoder is its own attack
surface. An identifier that does not parse after normalization is not
evaluable and MUST NOT be treated as outside the parties.
An independence claim reaches exactly as far as the record's own
commitments; a settlement-scoped attestation carries no delivery or
acceptance evidence. These rules are stated for evaluation after the
fact in [X402COMPLIANCE]; PACT binds them at contract
formation, constraining who may be named as Verifier before work
begins.¶
An agent that accepts work may subcontract part of it. The subcontract is an ordinary PACT contract whose Buyer is the parent's Seller. What this section adds is the binding between the two, so that a failure below is recoverable above and cannot be hidden.¶
A (Buyer)
|
vtc_7f3a91 cap 180.00
|
B (Seller)
|
+-------------+-------------+
| |
vtc_c1a2 vtc_c2b7 cap 60.00 each
| |
C (Seller) D (Seller)
A subcontract carries liability.parent, an object with the
parent's vtc_id and vtc_hash. Because
liability is inside the bytes both parties sign, the child's
Buyer signature is itself the authorisation to attach that child to
that parent.¶
A Facilitator MUST verify, before accepting a child contract, that the child's Buyer is the parent's Seller:¶
child.parties.buyer == parent.parties.seller¶
after the normalization in Section 9.1, where
parent is the contract whose canonical form hashes to
liability.parent.vtc_hash. A Facilitator MUST reject a child
whose parent it cannot resolve and verify.¶
Without this check any party may name any contract as its parent.
The attack is cheap and asymmetric: name a competitor's contract as
parent, subcontract a trivial task to yourself, fail it, and cause the
competitor's Bond to be slashed and its Work Attestation to record a
loss. The -00 carried liability.parent as a bare string with
no hash and no check, so the attack cost one signature.¶
A Facilitator MUST reject a child whose parent chain already
contains the child's own vtc_id, and MUST enforce a maximum
tree depth. Absent explicit configuration that maximum is 8. Both
limits exist so that resolving a chain terminates.¶
Liability cascades upward as recovery. It does not cascade downward as discharge.¶
Concretely: when a child fails, its Bond is applied under Section 7.4 with the parent's Seller as the Buyer being restored. The parent's Seller may then be in a position to perform, or to settle its own contract from those proceeds. But a Facilitator MUST NOT reduce the parent Seller's obligation to the parent Buyer by reason of a subcontract's failure, and MUST NOT make the parent Buyer's recovery conditional on any child settling. The parent Buyer contracted with the parent Seller and has no privity below it.¶
A (parent Buyer)
^
| B still owes A the full parent remedy (Section 10.2)
|
B (parent Seller, child Buyer)
^
| C's Bond restores B under rank 3 (Section 7.4)
|
C (child Seller) -- fails --
This is the rule that stops subcontracting from being a liability laundry. Absent it, a Seller facing a large obligation could subcontract to a thinly capitalised identity it controls, let the child fail, and offer the child's small Bond as the whole remedy.¶
A parent Seller SHOULD ensure that the sum of its children's
cap values is at least its own exposure under the parent
contract. Where it is not, the parent Seller carries the difference
itself. This is stated as advice rather than a requirement because a
Seller is entitled to take that risk knowingly; what it is not
entitled to do is transfer it to its Buyer without consent.¶
A parent's Work Attestation MUST carry
children_merkle_root, a Merkle root over the attestation
hashes of its immediate children, computed as in
Section 11. A parent therefore cannot be attested
until its children have been.¶
The -00 required that same commitment while ordering only
task.deadline between parent and child. Challenge windows are
not deadlines, so a child whose window outlasted its parent's
finalised after the parent, and a conformant implementation deadlocked
on its own requirement: commit to an attestation that does not yet
exist, or violate the MUST.¶
PERMITTED BY -00 (deadlock):
parent |=== work ===|== window ==|
| ^ parent final, must commit
| to a child attestation that
child |==== work ====|== window ==| does not exist yet
^ child final
REQUIRED BY -01:
parent |=== work ===|===== window =====|
^ parent final
child |=== work ===|== window ==|
^ child final, in time
A Facilitator MUST reject a child contract unless the latest instant at which the child can become final precedes the earliest instant at which the parent's challenge window can close:¶
child.task.deadline
+ child.challenge.window_seconds
+ child.challenge.max_dispute_seconds
<
parent.task.deadline
+ parent.challenge.window_seconds
¶
A Facilitator MUST NOT move a contract to FINAL, and MUST NOT return a Bond under Section 7.6, while any descendant remains non-final. Cascading recovery requires the parent's collateral to remain exposed until the subtree has settled; releasing it earlier would make the cascade a rule about value that no longer exists.¶
These two requirements together mean a subcontract must be agreed early enough in the parent's life to finish inside it. That is a real constraint on how deep a tree can be with short windows, and it is stated here rather than discovered at runtime.¶
A Work Attestation records what a contract did. It is the input to any reputation system built on PACT, though this document defines no such system and takes no position on how the records should be weighed.¶
The -00's attestation recorded that money moved. It named no party, distinguished no role, carried no Facilitator signature, and committed no work product. Three attacks followed, each cheap: present another agent's attestations as your own, since nothing required the presenter to be a signer; present your Buyer records as Seller records, since no role label distinguished payer from performer; or manufacture a history outright with two identities you control, since nothing proved a Facilitator was ever involved.¶
vtc_id, vtc_hash:parties:subject:parties.¶
role:buyer or seller. A Buyer record and a Seller record
are different evidence and MUST NOT be interchangeable.¶
outcome:performed,
cured, slashed, abandoned.¶
work_hash:amounts:children_merkle_root:signatures:The Facilitator signature is what makes the record evidence. Without it an attestation is a claim by interested parties about themselves. With it, forging a settlement history requires a Facilitator's key rather than two identities, which is the property the economic argument for settlement-derived reputation assumed all along.¶
A Facilitator MUST issue an attestation for every terminal contract, including SETTLED and ABANDONED, and MUST NOT require the signature of a party whose loss the attestation records. Under the -00 a slashed Seller simply declined to co-sign its own conviction, which made the reputation layer structurally incapable of recording a negative outcome.¶
{
"pact": "0.1",
"type": "WorkAttestation",
"vtc_id": "vtc_7f3a91",
"vtc_hash": "sha256:b2cccae0...",
"parties": {
"buyer": "did:web:acme.example",
"seller": "did:web:dataforge.example",
"facilitator": "did:web:settle.example"
},
"subject": "did:web:dataforge.example",
"role": "seller",
"outcome": "slashed",
"work_hash": "sha256:9c1f...",
"amounts": {
"settled": "0.00",
"restituted": "18.00",
"slashed": "18.00",
"currency": "USDC"
},
"signatures": [
{ "protected": "...", "signature": "..." }
]
}
The example carries one signature, the Facilitator's. That is sufficient and is the point: the Seller did not consent to this record and its consent is not required.¶
Let D be the list of 32-byte SHA-256 digests of each immediate
child's Work Attestation in JCS-canonical form, sorted ascending as
byte strings. children_merkle_root is MTH(D) exactly as
defined in [RFC9162] Section 2.1.1, with SHA-256 as
the hash: a leaf is
SHA-256(0x00 || d), an interior node is SHA-256(0x01 || left ||
right), and for n greater than one the list is split at k, the
largest power of two smaller than n. The shape is therefore fixed by
n alone, and two implementations that agree on D agree on the
root.¶
The domain separation is not optional. Without distinct prefixes an attacker can present an interior node as though it were a leaf, and so claim an inclusion proof for a subtree that never existed.¶
Where a contract has no children the member is omitted. It MUST NOT be present with an empty or zero value, which would be indistinguishable from a tree whose children were withheld.¶
The -00 defined objects and no operations, so two independent
implementations of it could not exchange a single message. This section
specifies the operations a Facilitator exposes. Base URIs are not fixed
by this document; they are discovered from the endpoints member
of the capability document (Section 8), so a
Facilitator may mount them anywhere on its origin.¶
| Operation | Method | Target |
|---|---|---|
| Propose a contract | POST |
{contract}
|
| Retrieve a contract | GET |
{contract}/{id}
|
| Submit a Delivery | POST |
{delivery}
|
| Record a Verdict | POST |
{verdict}
|
| Open a challenge | POST |
{challenge}
|
| Retrieve an Attestation | GET |
{attestation}/{id}
|
All requests and responses use the media types defined in Section 18. All requests MUST be made over HTTPS, following the recommendations of [RFC9325]. Status codes are as defined in [RFC9110].¶
| Operation | Request body | Success | Response body |
|---|---|---|---|
| Propose | pact-contract+json | 201 | the VTC, plus state
|
| Retrieve contract | none | 200 | the VTC, plus state
|
| Submit Delivery | pact-delivery+json | 202 | the Delivery, plus state
|
| Record Verdict | pact-verdict+json | 201 | the Verdict |
| Open challenge | pact-challenge+json | 202 | the Challenge, plus state
|
| Retrieve Attestation | none | 200 | pact-attestation+json |
The state member in a response is the current value from
Figure 2; it is added by the Facilitator, is not
part of the signed object, and MUST NOT be included when the object is
canonicalized or hashed.¶
A Facilitator authenticates the sender of a POST by the signature on the body: it MUST reject a Delivery not signed by the contract's Seller, a Verdict not signed by a party admissible under Section 12.4, and a Challenge whose signer it cannot resolve. This document requires no additional HTTP-layer authentication; a Facilitator MAY require one. Retrieval by GET is unauthenticated by this document, and a Facilitator MAY restrict it to the parties of the contract.¶
The request body is a VTC carrying the signatures of every party required to sign it. A Facilitator MUST perform the checks in Section 13 and Section 7.2 before creating the resource, and MUST refuse otherwise.¶
Every object this protocol carries is committed by a hash of its
own canonical form, so no separate idempotency key is needed and none
is defined. A Facilitator MUST treat a POST whose body canonicalizes
to a hash it has already accepted as a request for the existing
resource, and MUST respond 200 (OK) with that resource rather
than creating a second one or reporting a conflict.¶
Where a POST carries the same object id as an existing
resource but a different hash, the Facilitator MUST respond
409 (Conflict). Retrying a submission is therefore always
safe, and altering one never is.¶
A Facilitator MUST report failures using
[RFC9457] problem details, media type
application/problem+json, with a type drawn from the
registry in Section 18. Error responses MUST name the rule
that was violated, because a conformance failure a caller cannot
locate in this document is a failure of this document.¶
The section member is REQUIRED on any problem arising from
a rule in this document and carries the section number stating that
rule.¶
A Verdict is a signed statement that a Delivery was evaluated against the committed acceptance instrument, and with what outcome. A Facilitator MUST reject a Verdict whose signer does not satisfy Section 9.1 for the contract named, and MUST NOT accept a Verdict for a contract that has no recorded Delivery.¶
{
"pact": "0.1",
"type": "Verdict",
"vtc_id": "vtc_7f3a91",
"delivery_hash": "sha256:5d7c...",
"outcome": "PASS",
"profile": "acceptance",
"instrument_hash": "sha256:d9205d4f...",
"results_hash": "sha256:7e02...",
"evaluated_at": "2026-11-10T09:14:22Z",
"signature": { "protected": "...", "signature": "..." }
}
The Verifier is the party identified by the kid of the
Verdict's signature. Where the contract names
parties.verifier, the Verdict MUST be signed by that party;
otherwise the Facilitator evaluates Section 9.1
against the signer.¶
A Verdict commits to the instrument it ran and to the results it
produced. Without instrument_hash a Verifier could run
something other than the committed instrument and the contract would
have no way to tell; that is the substitution attack described in
Section 5.1, arriving from the verification side rather
than the acceptance side.¶
Buyer/Seller Facilitator Verifier
| | |
|-- POST {contract} --->| |
|<-- 201 Created -------| |
| | |
|-- POST {delivery} --->| |
|<-- 202 Accepted ------| |
| | |
| |-- GET work_uri ----->|
| |<-- POST {verdict} ---|
| | |
|<-- 200 OK ------------| |
| | |
|-- GET {attestation} ->| |
|<-- 200 Attestation ---| |
A Delivery is answered 202 (Accepted) rather than
201 because acceptance of the bytes is not acceptance of the
work. The contract moves to DELIVERED; whether it moves on to
RELEASING depends on a substantive Verdict, which the Facilitator
does not itself produce.¶
Every rule a PACT conformance checker enforces is stated in this document as normative text. This section collects the rules that a schema language cannot express, so that an implementation built from this document alone passes a conformance suite built from it. A rule that lives only in a test suite is not a requirement, and an implementer who cannot find it in the specification will not implement it.¶
Every signature carried by a VTC, Delivery, Verdict, Challenge, Work Attestation, or capability document is a JWS [RFC7515] in the General JSON Serialization of Section 7.2.1 of that document, with the payload detached as its Appendix F describes. The payload is BASE64URL of the JCS-canonical bytes of the object with the signing member removed, so the JWS Signing Input is ASCII(BASE64URL(UTF8(protected)) || "." || BASE64URL(JCS(object))) exactly as Section 5.1 of [RFC7515] defines it. The payload is never transmitted; a verifier reconstructs it from the object it holds. The following constraints apply.¶
alg, kid and
typ.¶
alg MUST be ES256 or ES384
[RFC7518], or EdDSA [RFC8037]
with an Ed25519 key; a verifier MAY also accept Ed448. A verifier
MUST reject any other value, and MUST reject none. Absent an allowlist an attacker selects the
algorithm, which permits both unsigned acceptance and confusion of a
public key for a symmetric secret.¶
kid MUST appear inside the protected header and MUST
NOT be carried as a sibling of it. A key identifier outside the
signed bytes is rewritable in transit, which allows an attacker who
can publish a key document to re-attribute a genuine signature to
itself.¶
typ MUST be the full media type of the object signed,
including the application/ prefix, so that a signature
over one object type cannot be replayed as a signature over
another. Section 4.1.9 of [RFC7515] recommends
omitting the prefix; this document requires the full form so that
typ equals the registered media type character for
character. Explicit typing follows Section 3.11 of
[RFC8725].¶
A kid is a URI naming a public key. A verifier MUST
resolve it as follows, and MUST reject a signature whose
kid it cannot resolve.¶
did: identifier is a DID URL
[DID-CORE]. The verifier resolves the DID document
by the method the identifier names and selects the verification
method its fragment identifies. Examples in this document use
did:web [DID-WEB]; no method is
required or excluded.¶
https: identifier dereferences, over TLS, to a
JWK Set [RFC7517]; the verifier selects the key
whose kid member equals the fragment.¶
The part of a kid before its fragment MUST equal, after
the normalization in Section 9.1, the party
identifier the signature is attributed to. Verifying a signature
establishes that the holder of that key signed; that the key
belongs to the party is a property of the identity method, and this
document does not add to it.¶
parties.buyer and parties.seller MUST be
distinct after the normalization in
Section 9.1.¶
challenge.window_seconds MUST be greater than
zero.¶
harness_uri without harness_hash, or
rubric_uri without rubric_hash.¶
acceptance object MUST carry the members REQUIRED
for the contract's tier. An empty acceptance object MUST be
rejected, since it makes every fraud proof impossible and converts
conditional release into unconditional payment.¶
q_min.¶
Each rule above has an accepting and a rejecting form. A conformance suite built from this section alone, with no reference to any implementation, should reach the same verdicts. Rejecting vectors name the rule they violate.¶
| ID | Mutation from a valid object | Expect |
|---|---|---|
| V-01 | unmodified valid VTC | accept |
| V-02 |
alg set to none
|
reject |
| V-03 |
alg set to HS256
|
reject |
| V-04 |
kid moved outside the protected
header |
reject |
| V-05 |
typ of a Delivery on a VTC
signature |
reject |
| V-06 | buyer and seller set to the same identifier | reject |
| V-07 | buyer and seller differing only by trailing "/" | reject |
| V-08 | two signatures, both from the buyer | reject |
| V-09 |
window_seconds of 0 |
reject |
| V-10 |
acceptance as an empty object |
reject |
| V-11 |
harness_uri with
harness_hash removed |
reject |
| V-12 | B 18.00, P 180.00, q_min 0.90 | reject |
| V-13 | B 18.00, P 180.00, q_min 1.00 | accept |
| V-14 | Delivery with evidence absent |
reject as FAIL |
| V-15 | child whose buyer is not the parent's seller | reject |
| V-16 | child finalising after the parent's window closes | reject |
| V-17 | Verdict signed by the seller | reject |
| V-18 | object keys ordered by code point, with a supplementary-plane key | digest mismatch |
V-07 and V-18 are the two most often got wrong. V-07 fails wherever party comparison is a string equality on unnormalized identifiers. V-18 fails wherever canonicalization sorts keys by Unicode code point, which agrees with the required UTF-16 order for every ASCII key and so passes every vector an implementer would think to write.¶
The -00 carried no numeric example and no digest anywhere in its text. Every concrete value lived in a separate repository with no link from the document to it, so the specification made no verifiable claim about its own reference implementation. This section fixes that. The tables and digests below are the reference repository's. The object figures in earlier sections use short illustrative identifiers for page width; the repository examples carry the full ones, and the digests here are computed over those.¶
A buyer commissions a data transformation. The agreed price is 180.00 USDC and the seller posts a bond of 18.00, ten percent, which is the conventional figure.¶
| Quantity | Symbol | Value |
|---|---|---|
| Price | P | 180.00 USDC |
| Seller bond | B | 18.00 USDC |
| Verification fund | F | 0.50 USDC |
| Released before Verdict | E | 0.00 |
| Challenge window | 3600 s |
Apply Section 7.2. With E of zero the constraint B >= P(1-q)/q reduces to a requirement on q of at least P/(P+B):¶
q >= 180.00 / (180.00 + 18.00) = 0.9091¶
So this contract is only incentive-compatible if better than
ninety-one percent of defections are detected, proven and adjudicated
inside 3600 seconds. That is the whole argument against a ten percent
bond in one line, and it is why the example declares
assurance.mode of certain: at q of 1 the required bond
is zero and the bond covers harm rather than deterrence.¶
| q | Required B | 18.00 suffices? |
|---|---|---|
| 1.00 | 0.00 | yes |
| 0.9091 | 18.00 | exactly |
| 0.90 | 20.00 | no |
| 0.50 | 180.00 | no |
The digests carried by the reference TaskSpec and contract are:¶
spec_hash
sha256:bb0e87ce522479b7c2f7bcfa26df7ecd7ff67aeb8b415bbd70c22d
97c47adf35
criteria_hash
sha256:d9205d4f2922afd55c0a2dc4ab00d8ee5a512343430bcf5e9abf0c
76d66c69f7
¶
criteria_hash is the manifest digest of
Section 5.1 over the acceptance instrument bundle, and the
same value appears as acceptance.harness_hash inside the
TaskSpec, so the instrument is committed both by the contract and from
within the specification it belongs to.¶
And the contract's own commitment, computed over the signed contract per Section 6:¶
vtc_hash
sha256:b2cccae00fc7b97ba2b6ef6356ff42c006ba661e0249d7eaa8baff3d
e553870b
¶
This value differs from the one the -00 examples carried, and the
difference is semantic rather than incidental: the -00 excluded the
signature set from the commitment, so its digest proved what was
written and not who agreed to it. spec_hash and
criteria_hash are unchanged in construction.¶
This section records the status of known implementations of this document per [RFC7942], and is to be removed before publication as an RFC.¶
A reference implementation of the object schemas, the examples in Section 14, and a conformance validator is maintained at https://github.com/pact-spec/spec under the Revised BSD licence. As of the date of this document the validator runs sixty-six checks: schema conformance for every object, JCS canonicalization including the UTF-16 key-order vector of Section 13.3, every hash commitment in Section 14, the constraint of Section 7.2 on the worked figures, the Merkle construction of Section 11.1 against the definition in [RFC9162], and the vectors of Section 13.3. No Facilitator, Buyer or Seller exchanging messages over the endpoints of Section 12 is known to the author.¶
Most of what follows was found by adversarial review of [I-D.laxsharma-pact-00] rather than anticipated when it was written. Each subsection states the attack, why it worked, and the requirement in this document that closes it. Where a threat is only mitigated rather than closed, that is said.¶
A verification tier states how strongly work is checked. It does not state who checked it, and those fail separately. A re-execution transcript produced by the Seller and the same transcript produced by an independent Challenger are the same method and different evidence. Where a proof is generated and verified entirely inside one party, the tier is satisfied and the contract is unprotected.¶
Section 9.1 requires that independence be derived by the evaluator from the parties named in the contract, and forbids satisfying it with a self-asserted field. A criterion satisfiable by writing a string reproduces the defect it was meant to catch.¶
Absent an algorithm allowlist an attacker chooses the algorithm.
The two consequences are alg of none, which makes
every signature check vacuous, and presenting an ECDSA public key as
an HMAC secret, which lets anyone holding the public key forge.
Section 13.1 fixes the permitted set.¶
A kid carried as a sibling of the protected header rather
than inside it is outside the signed bytes and is rewritable in
transit. An attacker who can publish a key document can then
re-attribute a victim's genuine signature to an identifier it
controls, without breaking any cryptography.
Section 13.1 requires kid inside the protected
header.¶
A signature over one object type replayed as a signature over
another is prevented by the typ requirement in the same
section.¶
The -00 committed harness_uri as a string. The bytes at
that URI were covered by nothing. A Buyer could therefore sign a
contract, replace the acceptance instrument afterwards, run the
replacement, and submit its failure as a textbook-valid fraud proof:
the Seller's Bond is slashed, its attestation records a loss, and the
Buyer keeps the work. Cost of the attack: one file overwrite. The
mirror attack works against a Seller that hosts the input sample.¶
Section 5.1 requires a sibling hash over the dereferenced bytes for every URI inside committed content, and Section 12.4 requires a Verdict to commit to the instrument it actually ran, which closes the same attack from the verification side.¶
Naming a parent contract cost one signature in the -00 and was checked against nothing. An attacker could attach a failing child to a competitor's contract and cause that competitor's Bond to be slashed. Section 10.1 requires the child's Buyer to be the parent's Seller, verified against the parent's hash.¶
The converse abuse, a Seller subcontracting to an identity it controls in order to offer that identity's small Bond as the whole remedy, is addressed by Section 10.2: cascade is recovery for the parent Seller and never discharge of its obligation to the parent Buyer.¶
Where the reward for reporting a fraud is bounded below the defaulting Seller's exposure, there is always a private payment that leaves both the discoverer and the Seller better off than reporting, and silence dominates the mechanism the protocol designed. This is not closed by raising the bounty to the full exposure, which leaves nothing for restitution and maximises the incentive to manufacture challenges.¶
Section 7.4 mitigates rather than closes it, by making the reward non-exclusive so that buying silence scales with the number of independent discoverers while reporting pays once, and by admitting the Buyer as a Challenger in its own contract so that any bribe has a floor at the restitution the Buyer would forgo. Implementers should understand that a determined Seller facing a single discoverer can still buy silence.¶
Under the -00 a contract in which nothing was ever delivered had no remedy: the deadline carried no stated consequence, no challenge window opened because there was nothing to challenge, and escrow could remain locked indefinitely. This is the most common real failure in commerce and it had no code path.¶
Section 6 makes deadline expiry an automatic Buyer remedy producing the ABANDONED state. Note the asymmetry this creates: a Seller that delivers nothing is worse off than one that delivers something non-conformant only if the Bond exceeds the value of the work, which is a reason to size Bonds by harm rather than by a percentage of price.¶
A VTC that does not name its Facilitator, network and asset is a signed instrument replayable against any of them. The -00 carried none of the three. Section 5 requires all three inside the signed content.¶
Relatedly, a hash computed over a contract excluding its
signatures proves what was written and not who agreed to it, so
entries can be appended or stripped without invalidating the
commitment. Section 6 requires
vtc_hash to be computed over the contract including its
signature set.¶
A Delivery, Verdict or Challenge replayed against a different
contract fails because each carries vtc_id and a hash that
binds it to one contract and one Delivery, and the
typ rule of Section 13.1 stops a signature over
one object type standing for another.¶
A re-execution profile that does not state what determinism it assumes cuts both ways. An honest Seller doing model-assisted work is convicted by a re-execution that differs for ordinary reasons. A cheating Seller escapes any fraud proof by asserting nondeterminism, unfalsifiably. Registration under Section 18.3 requires a profile to state whether it is deterministic and what tolerance applies; a profile that does not should not be registered, and a contract naming one is not safely enforceable.¶
The economic argument for settlement-derived reputation is that faking a history requires funding real contracts. That argument fails if attestations do not name the parties, do not distinguish the payer from the performer, and carry no Facilitator signature, since two cooperating identities can then manufacture history at the cost of two signatures, and a party can present its Buyer records as Seller records. Section 11 requires all three.¶
It fails in the other direction too if a negative outcome requires the signature of the party it convicts. Reputation that is structurally incapable of recording a loss is not evidence of anything.¶
The Facilitator holds the price, the Bond and the Verification Fund of every contract it settles. Nothing in this protocol stops a Facilitator from keeping them. What the protocol does is make that theft attributable: every movement of value is recorded in a Work Attestation the Facilitator signs, every party holds a co-signed contract stating what should have happened, and a Facilitator that deviates has produced its own evidence. Whether that evidence has consequences is a matter of reputation, contract or law, all of which are outside this document. Deployments that cannot accept a single custodian should look to multi-party custody, which this document does not specify and does not preclude.¶
A signature here is a long-lived commitment, and a compromised key
signs contracts the party never agreed to. Rotation and revocation
belong to the identity method behind the kid
(Section 13.1.1), and this document does not restate them.
Two things it does require: a Facilitator MUST record, with each
object it accepts, the key material or its digest as resolved at the
time of acceptance, so that a later rotation does not make an earlier
signature unverifiable; and a Facilitator MUST NOT accept an object
whose kid resolves to a key the identity method marks as
revoked at the time of acceptance.¶
Every accepted Challenge costs an independent evaluation. Without a
cost to the Challenger, a party can exhaust the Verification Fund or
the Facilitator's capacity by challenging every Delivery. The
challenge_deposit of Section 7.5 is
the defence, and it is a MAY because a deposit also deters the honest
challenger the open model relies on. A Facilitator that requires no
deposit SHOULD rate-limit Challenges per Challenger and per contract,
and SHOULD publish that it does so.¶
PACT moves contracts and evidence about work, and both leak.¶
Publishing a representative input sample so that a counterparty can
price the work discloses production data to parties with whom no
contract exists and who may be in unknown jurisdictions. Samples
SHOULD be synthetic or de-identified. Where a real sample is
necessary, it SHOULD be disclosed only after a confidentiality
undertaking, and the constraints member SHOULD carry the
retention and deletion terms. This document cannot enforce any of
that and does not pretend to.¶
A Facilitator that publishes its log of locks, releases and slashes makes the contract graph public. From it a reader can reconstruct an organisation's suppliers, spend and cadence, which is commercially sensitive even when no individual is identifiable. Transparency and counterparty privacy are in genuine tension here, and this document resolves it in favour of neither: a Facilitator MAY publish aggregates, and SHOULD NOT publish per-contract records identifying both parties without their agreement.¶
Work Attestations leak the same graph by construction, since each names both parties and the counterparty retains a signed copy indefinitely. Selective disclosure over attestations, so that a holder can prove a settled contract without revealing the counterparty, is possible with the mechanisms cited in Section 11 and is not specified here.¶
An open challenge model requires that some party outside the
contract can obtain the deliverable and the input in order to build a
fraud proof. That is in direct conflict with confidentiality of both.
The conflict is real and this document does not dissolve it. What it
does is make the choice explicit: a contract whose content cannot be
disclosed to a Challenger MUST NOT declare open assurance,
because there is no population able to produce the detection
probability such a declaration asserts.¶
Retention duties stated for dispute purposes can conflict with erasure rights asserted by a data subject. Contracts SHOULD state a retention period, and implementers should be aware that a hash commitment survives deletion of the content it commits to, which is usually the property they want and occasionally the one they must explain.¶
This document asks IANA to register six media types, one well-known URI, and two registries. It defines problem types but does not ask for a registry of them (Section 18.5).¶
IANA is requested to register the following in the "Media Types" registry, per [RFC6838]. The template below is given once in full; the six registrations differ only in the subtype name and the object they carry.¶
application/json¶
| Subtype name | Object | Defined in |
|---|---|---|
| pact-contract+json | Verifiable Task Contract | Section 5 |
| pact-delivery+json | Delivery | Section 6 |
| pact-verdict+json | Verdict | Section 12.4 |
| pact-challenge+json | Challenge | Section 7.5 |
| pact-attestation+json | Work Attestation | Section 11 |
| pact-facilitator+json | Capability document | Section 8 |
IANA is requested to register the following in the "Well-Known URIs" registry, per [RFC8615].¶
IANA is requested to create a registry named "PACT Verification Profiles". The registration policy is Specification Required [RFC8126].¶
Instructions for the designated expert. A profile determines what a fraud proof consists of and, through Section 7.2, what a Bond must cover, so a registration that leaves either underdetermined is not usable. The expert SHOULD confirm that the submitted specification states, for the profile: what artifact is evaluated and what it is evaluated against; what constitutes a valid fraud proof, including whether absence of evidence is one; an order-of-magnitude estimate of verification cost relative to contract price, since that quantity and not the profile name determines whether any Bond makes third-party challenge rational; and whether the profile is deterministic, and if not, what tolerance applies. The expert SHOULD reject a profile whose fraud proof cannot be evaluated by a party other than the Seller, since such a profile cannot satisfy Section 9.1.¶
| Name | Description | Reference |
|---|---|---|
| acceptance | Run the committed instrument against the Delivery | This document |
| bisection | Interactive narrowing to a disputed step | This document |
| full-reexec | Re-execute and compare outputs byte for byte | This document |
IANA is requested to create a registry named "PACT Settlement Bindings", registration policy Specification Required. A binding determines how value is locked, released and reversed, so the expert SHOULD confirm that the submitted specification states how each of those three operations maps onto the underlying rail, and what happens when a reversal is requested after the rail's own finality. A binding whose rail cannot reverse MUST say so, since Section 7.4 then has no rank 1.¶
| Identifier | Description | Reference |
|---|---|---|
| pact-escrow | An x402 payment scheme carrying PACT escrow semantics | This document |
This document creates no registry for its problem types.
[RFC9457] Section 4.2 establishes the "HTTP Problem
Types" registry for types intended for reuse across applications;
the types below are specific to this protocol and are identified by
URIs in a namespace this document defines, which that specification
permits without registration. Each is the identifier in the table
appended to the prefix https://pact-spec.github.io/problem/.
Per Section 3.1.1 of [RFC9457] a consumer uses the
URI as an identifier and SHOULD NOT dereference it automatically;
dereferencing SHOULD yield human-readable documentation, which the
author maintains at that prefix. Each entry carries the identifier,
the HTTP status it accompanies, and the section stating the rule it
reports.¶
| Identifier | Status | Defined in |
|---|---|---|
| assurance-constraint-unsatisfied | 422 | Section 7.2 |
| evidence-nonconformant | 422 | Section 6 |
| parent-unresolvable | 422 | Section 10.1 |
| finality-ordering-violation | 422 | Section 10.3 |
| parties-not-distinct | 422 | Section 13.2 |
| algorithm-not-permitted | 400 | Section 13.1 |
| verifier-not-independent | 422 | Section 9.1 |
| release-exceeds-bond | 409 | Section 7.1 |
The UTF-16 key-ordering vector that exposed a latent canonicalization defect in the reference validator, and the formulation of verifier independence as a relation the evaluator derives rather than a field the record declares, came from Tersign (wowlegend) on x402-foundation/x402 issue 3065. The observation that verification tiers say how work is checked and never who checks it, which set off the adversarial review this revision rests on, came from msaleme on the same thread. Rich Smith's A2A Settlement Extension was the clearest instance of the pattern Section 7 corrects, and he engaged with the critique on a2aproject/A2A discussion 1576.¶