agent-receipt-verify 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,81 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-changed-amount-silent-collapse",
11
+ "clause": "changed-request-different-artifact",
12
+ "encodes": "A changed amount kept under the same identity, so a price change disappears into a replay.",
13
+ "description": "The settle path carries an amount of 2000 where ingress saw 1000, and resolves the identity of the original request. The clause requires a different artifact. This is the case where a buyer is charged twice the quoted price and the record set still reads as one ordinary attempt.",
14
+ "input": {
15
+ "ingress": {
16
+ "snapshot": {
17
+ "method": "POST",
18
+ "path": "/api/paid/verify-ownership",
19
+ "query": "",
20
+ "body": {
21
+ "endpoint": "https://example.com/api/health",
22
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
23
+ "method": "dns-txt"
24
+ },
25
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
26
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
27
+ "network": "eip155:8453",
28
+ "amount": "1000",
29
+ "scheme": "exact"
30
+ },
31
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
32
+ },
33
+ "paths": [
34
+ {
35
+ "path": "challenge-quote",
36
+ "snapshot": {
37
+ "method": "POST",
38
+ "path": "/api/paid/verify-ownership",
39
+ "query": "",
40
+ "body": {
41
+ "endpoint": "https://example.com/api/health",
42
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
43
+ "method": "dns-txt"
44
+ },
45
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
46
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
47
+ "network": "eip155:8453",
48
+ "amount": "1000",
49
+ "scheme": "exact"
50
+ },
51
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
52
+ },
53
+ {
54
+ "path": "settle",
55
+ "snapshot": {
56
+ "method": "POST",
57
+ "path": "/api/paid/verify-ownership",
58
+ "query": "",
59
+ "body": {
60
+ "endpoint": "https://example.com/api/health",
61
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
62
+ "method": "dns-txt"
63
+ },
64
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
65
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
66
+ "network": "eip155:8453",
67
+ "amount": "2000",
68
+ "scheme": "exact"
69
+ },
70
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
71
+ }
72
+ ]
73
+ },
74
+ "expected": {
75
+ "outcome": "FAIL",
76
+ "reason_code": "CHANGED_REQUEST_SAME_IDENTITY"
77
+ },
78
+ "limits": [
79
+ "The vector shows the collapse. Whether the buyer was actually overcharged depends on the ledger and is not measured here."
80
+ ]
81
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-client-supplied-key-unverified",
11
+ "clause": "name-independent-but-bound",
12
+ "encodes": "An Idempotency-Key the client chooses and the facilitator never checks against the ingress snapshot.",
13
+ "description": "The clause allows any field name, on the condition that the field is bound to the ingress snapshot. Here the client supplies the value and nothing verifies it, so two different requests can claim one identity and a buyer can make his second request look like a replay of his first.",
14
+ "input": {
15
+ "identity_field": {
16
+ "name": "Idempotency-Key",
17
+ "bound_to": "ingress-snapshot",
18
+ "client_supplied": true,
19
+ "verified_against_snapshot": false
20
+ }
21
+ },
22
+ "expected": {
23
+ "outcome": "FAIL",
24
+ "reason_code": "CLIENT_SUPPLIED_IDENTITY_NOT_VERIFIED"
25
+ },
26
+ "limits": [
27
+ "This is about the binding, not about whether the key is otherwise well formed."
28
+ ]
29
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-countersignature-matches",
11
+ "clause": "countersignature-recompute-or-refuse",
12
+ "encodes": "The positive control for the countersignature clause: recomputed, equal, signed, settled.",
13
+ "description": "The counterparty recomputed the fingerprint from the bytes it observed, arrived at the ingress value, signed, and the interaction settled. Both negatives of this clause are refusals, so without this vector the clause would only ever be able to say no.",
14
+ "input": {
15
+ "countersignature": {
16
+ "ingress_value": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196",
17
+ "recomputed": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196",
18
+ "signed": true,
19
+ "settled": true
20
+ }
21
+ },
22
+ "expected": {
23
+ "outcome": "PASS"
24
+ },
25
+ "limits": [
26
+ "This says the recomputed value matched. It does not verify the signature itself; that is the issuing party own verifier."
27
+ ]
28
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-countersigned-despite-mismatch",
11
+ "clause": "countersignature-recompute-or-refuse",
12
+ "encodes": "A counterparty that recomputed, saw a different value, and signed anyway.",
13
+ "description": "The clause makes recomputation a verification obligation with a refusal attached. Here the recomputed fingerprint differs from the ingress value and the signature was produced regardless, which turns the countersignature into a second opinion about nothing.",
14
+ "input": {
15
+ "countersignature": {
16
+ "ingress_value": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196",
17
+ "recomputed": "b1b9009e0c9e7d66fc4e47a66303e8ccdddce8cc3462bc9de007abf524855bcb",
18
+ "signed": true,
19
+ "settled": false
20
+ }
21
+ },
22
+ "expected": {
23
+ "outcome": "FAIL",
24
+ "reason_code": "COUNTERSIGNED_DESPITE_MISMATCH"
25
+ },
26
+ "limits": [
27
+ "This cannot show whether the counterparty recomputed honestly, only that it reported a mismatch and signed."
28
+ ]
29
+ }
@@ -0,0 +1,122 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-derive-once-honoured",
11
+ "clause": "derive-once-at-ingress",
12
+ "encodes": "The positive control for the core clause: every path states it took the identity from the ingress snapshot.",
13
+ "description": "Four paths, and each one declares its identity came from the ingress snapshot rather than from a fresh read of the request. The negative twin of this vector has one path recomputing at settle time while arriving at the same value, which is why the declared origin is what gets checked and not only the value.",
14
+ "input": {
15
+ "ingress": {
16
+ "snapshot": {
17
+ "method": "POST",
18
+ "path": "/api/paid/verify-ownership",
19
+ "query": "",
20
+ "body": {
21
+ "endpoint": "https://example.com/api/health",
22
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
23
+ "method": "dns-txt"
24
+ },
25
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
26
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
27
+ "network": "eip155:8453",
28
+ "amount": "1000",
29
+ "scheme": "exact"
30
+ },
31
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
32
+ },
33
+ "paths": [
34
+ {
35
+ "path": "challenge-quote",
36
+ "snapshot": {
37
+ "method": "POST",
38
+ "path": "/api/paid/verify-ownership",
39
+ "query": "",
40
+ "body": {
41
+ "endpoint": "https://example.com/api/health",
42
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
43
+ "method": "dns-txt"
44
+ },
45
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
46
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
47
+ "network": "eip155:8453",
48
+ "amount": "1000",
49
+ "scheme": "exact"
50
+ },
51
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196",
52
+ "derived_from": "ingress-snapshot"
53
+ },
54
+ {
55
+ "path": "settle",
56
+ "snapshot": {
57
+ "method": "POST",
58
+ "path": "/api/paid/verify-ownership",
59
+ "query": "",
60
+ "body": {
61
+ "endpoint": "https://example.com/api/health",
62
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
63
+ "method": "dns-txt"
64
+ },
65
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
66
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
67
+ "network": "eip155:8453",
68
+ "amount": "1000",
69
+ "scheme": "exact"
70
+ },
71
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196",
72
+ "derived_from": "ingress-snapshot"
73
+ },
74
+ {
75
+ "path": "refusal",
76
+ "snapshot": {
77
+ "method": "POST",
78
+ "path": "/api/paid/verify-ownership",
79
+ "query": "",
80
+ "body": {
81
+ "endpoint": "https://example.com/api/health",
82
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
83
+ "method": "dns-txt"
84
+ },
85
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
86
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
87
+ "network": "eip155:8453",
88
+ "amount": "1000",
89
+ "scheme": "exact"
90
+ },
91
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196",
92
+ "derived_from": "ingress-snapshot"
93
+ },
94
+ {
95
+ "path": "replay-lookup",
96
+ "snapshot": {
97
+ "method": "POST",
98
+ "path": "/api/paid/verify-ownership",
99
+ "query": "",
100
+ "body": {
101
+ "endpoint": "https://example.com/api/health",
102
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
103
+ "method": "dns-txt"
104
+ },
105
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
106
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
107
+ "network": "eip155:8453",
108
+ "amount": "1000",
109
+ "scheme": "exact"
110
+ },
111
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196",
112
+ "derived_from": "ingress-snapshot"
113
+ }
114
+ ]
115
+ },
116
+ "expected": {
117
+ "outcome": "PASS"
118
+ },
119
+ "limits": [
120
+ "A declared origin is a claim by the implementation. This vector tests that a checker reads it; it cannot verify the claim from outside."
121
+ ]
122
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-idempotency-key-bound",
11
+ "clause": "name-independent-but-bound",
12
+ "encodes": "The positive control for the name-independence clause: a different field name that satisfies the discipline.",
13
+ "description": "An implementation using Idempotency-Key, bound to the ingress snapshot and verified against it, satisfies the invariant. The requirement is the discipline, not the field name.",
14
+ "input": {
15
+ "identity_field": {
16
+ "name": "Idempotency-Key",
17
+ "bound_to": "ingress-snapshot",
18
+ "client_supplied": true,
19
+ "verified_against_snapshot": true
20
+ }
21
+ },
22
+ "expected": {
23
+ "outcome": "PASS"
24
+ },
25
+ "limits": [
26
+ "Satisfying this clause says nothing about the other seven."
27
+ ]
28
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-key-order-changes-identity",
11
+ "clause": "own-identity-from-decoded-fields",
12
+ "encodes": "The first of the two inverse traps: an identity that moves when the key order moves, so it came from the bytes.",
13
+ "description": "Two arrivals of the same attempt, same decoded fields, different key order and whitespace, and two different identities. The clause says an attempt is the same attempt either way, and that this is exactly what makes settle and refusal agree. An implementation that hashes the raw body fails here.",
14
+ "input": {
15
+ "wire_variants": [
16
+ {
17
+ "note": "as received first",
18
+ "decoded": {
19
+ "method": "POST",
20
+ "path": "/api/paid/verify-ownership",
21
+ "query": "",
22
+ "body": {
23
+ "endpoint": "https://example.com/api/health",
24
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
25
+ "method": "dns-txt"
26
+ },
27
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
28
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
29
+ "network": "eip155:8453",
30
+ "amount": "1000",
31
+ "scheme": "exact"
32
+ },
33
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
34
+ },
35
+ {
36
+ "note": "same fields, keys in another order",
37
+ "decoded": {
38
+ "method": "POST",
39
+ "path": "/api/paid/verify-ownership",
40
+ "query": "",
41
+ "body": {
42
+ "endpoint": "https://example.com/api/health",
43
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
44
+ "method": "dns-txt"
45
+ },
46
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
47
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
48
+ "network": "eip155:8453",
49
+ "amount": "1000",
50
+ "scheme": "exact"
51
+ },
52
+ "identity": "8a48e6c49a7a94be4d657408c486532e0a141d5e1548e7fabf539afd5809f982"
53
+ }
54
+ ]
55
+ },
56
+ "expected": {
57
+ "outcome": "FAIL",
58
+ "reason_code": "IDENTITY_DERIVED_FROM_WIRE_BYTES"
59
+ },
60
+ "limits": [
61
+ "The two variants are asserted to carry the same decoded fields; a checker verifies that before judging, and reports not-measured when they differ."
62
+ ]
63
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-key-order-stable-identity",
11
+ "clause": "own-identity-from-decoded-fields",
12
+ "encodes": "The positive control for the same trap.",
13
+ "description": "Same decoded fields, different wire form, one identity. This is the behaviour the clause requires.",
14
+ "input": {
15
+ "wire_variants": [
16
+ {
17
+ "note": "as received first",
18
+ "decoded": {
19
+ "method": "POST",
20
+ "path": "/api/paid/verify-ownership",
21
+ "query": "",
22
+ "body": {
23
+ "endpoint": "https://example.com/api/health",
24
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
25
+ "method": "dns-txt"
26
+ },
27
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
28
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
29
+ "network": "eip155:8453",
30
+ "amount": "1000",
31
+ "scheme": "exact"
32
+ },
33
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
34
+ },
35
+ {
36
+ "note": "same fields, keys in another order",
37
+ "decoded": {
38
+ "method": "POST",
39
+ "path": "/api/paid/verify-ownership",
40
+ "query": "",
41
+ "body": {
42
+ "endpoint": "https://example.com/api/health",
43
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
44
+ "method": "dns-txt"
45
+ },
46
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
47
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
48
+ "network": "eip155:8453",
49
+ "amount": "1000",
50
+ "scheme": "exact"
51
+ },
52
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
53
+ }
54
+ ]
55
+ },
56
+ "expected": {
57
+ "outcome": "PASS"
58
+ },
59
+ "limits": [
60
+ "This says the identity is stable across wire forms. It does not say the right fields went into it."
61
+ ]
62
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-nothing-recorded-not-measured",
11
+ "clause": "all",
12
+ "encodes": "The fourth outcome: a vector that carries no observations is not conformant and not failing, it is unmeasured.",
13
+ "description": "An empty observation set must not pass and must not fail. Reporting PASS here would let an implementation claim conformance by showing nothing, and reporting FAIL would blame an implementation for a record that was never collected. This is the distinction the thread settled on for all four evidence layers.",
14
+ "input": {},
15
+ "expected": {
16
+ "outcome": "NOT_MEASURED"
17
+ },
18
+ "limits": [
19
+ "This is a property of the checker, not of any implementation."
20
+ ]
21
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-outcome-folded-into-identity",
11
+ "clause": "outcome-not-folded-into-identity",
12
+ "encodes": "Metering data from the outcome layer absorbed into the identity, so a partial delivery becomes a different attempt.",
13
+ "description": "The same attempt delivered in full and in part resolves two identities, because the delivered measurement was folded into the derivation. The clause wants the gap between full and partial delivery to stay visible in the outcome layer; absorbing it into identity makes an incomplete delivery look like an unrelated attempt, which is how a shortfall stops being arguable.",
14
+ "input": {
15
+ "outcome_variants": [
16
+ {
17
+ "note": "full delivery",
18
+ "delivered": 100,
19
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
20
+ },
21
+ {
22
+ "note": "partial delivery",
23
+ "delivered": 40,
24
+ "identity": "b1b9009e0c9e7d66fc4e47a66303e8ccdddce8cc3462bc9de007abf524855bcb"
25
+ }
26
+ ]
27
+ },
28
+ "expected": {
29
+ "outcome": "FAIL",
30
+ "reason_code": "OUTCOME_FOLDED_INTO_IDENTITY"
31
+ },
32
+ "limits": [
33
+ "This shows identity moving with the outcome. It does not say which of the two identities is the right one."
34
+ ]
35
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-outcome-kept-out-of-identity",
11
+ "clause": "outcome-not-folded-into-identity",
12
+ "encodes": "The positive control: delivery differs, identity does not.",
13
+ "description": "Full and partial delivery of one attempt resolve one identity, so the shortfall stays a question about the outcome and not about which attempt this was.",
14
+ "input": {
15
+ "outcome_variants": [
16
+ {
17
+ "note": "full delivery",
18
+ "delivered": 100,
19
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
20
+ },
21
+ {
22
+ "note": "partial delivery",
23
+ "delivered": 40,
24
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
25
+ }
26
+ ]
27
+ },
28
+ "expected": {
29
+ "outcome": "PASS"
30
+ },
31
+ "limits": [
32
+ "Identity being stable does not mean the delivery was acceptable; that is the work-acceptance layer."
33
+ ]
34
+ }
@@ -0,0 +1,81 @@
1
+ {
2
+ "schema_version": "3.0.0",
3
+ "verifies": "attempt-identity",
4
+ "requires_chain_read": false,
5
+ "provenance": [
6
+ "x402 specification v2 section 5.5, Settlement and Refusal Identity Invariant, as proposed in x402-foundation/x402 pull request 3776 on branch spec/settlement-refusal-identity-invariant and not on main",
7
+ "the gap these cover was named by ruiruii in erc-8004/erc-8004-contracts#99 on 18 October 2026: each of the four evidence layers depends on an attempt identity that none of them defines",
8
+ "section 5.5 closes by referring to \"the normative conformance tests in the specification repository for the required negative cases\"; at the time of writing those did not exist"
9
+ ],
10
+ "id": "attempt-identity-paths-disagree",
11
+ "clause": "all-paths-same-artifact",
12
+ "encodes": "Two paths of one unchanged request resolving different identities, which the clause forbids outright.",
13
+ "description": "The request is byte-for-byte the same on both paths, and the refusal path resolves a different identity than the challenge quote. A holder of two records about this attempt can no longer tell they are about the same attempt, which is the whole failure the clause exists to prevent.",
14
+ "input": {
15
+ "ingress": {
16
+ "snapshot": {
17
+ "method": "POST",
18
+ "path": "/api/paid/verify-ownership",
19
+ "query": "",
20
+ "body": {
21
+ "endpoint": "https://example.com/api/health",
22
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
23
+ "method": "dns-txt"
24
+ },
25
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
26
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
27
+ "network": "eip155:8453",
28
+ "amount": "1000",
29
+ "scheme": "exact"
30
+ },
31
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
32
+ },
33
+ "paths": [
34
+ {
35
+ "path": "challenge-quote",
36
+ "snapshot": {
37
+ "method": "POST",
38
+ "path": "/api/paid/verify-ownership",
39
+ "query": "",
40
+ "body": {
41
+ "endpoint": "https://example.com/api/health",
42
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
43
+ "method": "dns-txt"
44
+ },
45
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
46
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
47
+ "network": "eip155:8453",
48
+ "amount": "1000",
49
+ "scheme": "exact"
50
+ },
51
+ "identity": "2ed52a521f9762c3adc24c8048a4ee04a3796202a34c335585fc953e15c97196"
52
+ },
53
+ {
54
+ "path": "refusal",
55
+ "snapshot": {
56
+ "method": "POST",
57
+ "path": "/api/paid/verify-ownership",
58
+ "query": "",
59
+ "body": {
60
+ "endpoint": "https://example.com/api/health",
61
+ "ownerAddress": "0x1111111111111111111111111111111111111111",
62
+ "method": "dns-txt"
63
+ },
64
+ "payTo": "0x2888f36548a900b9b08d584524e1f73bc563ec26",
65
+ "asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
66
+ "network": "eip155:8453",
67
+ "amount": "1000",
68
+ "scheme": "exact"
69
+ },
70
+ "identity": "baaf0cfdbd04db77cacfea2dede2cf0c2bc2967a9f5c0fc52d7169d70eb7fa79"
71
+ }
72
+ ]
73
+ },
74
+ "expected": {
75
+ "outcome": "FAIL",
76
+ "reason_code": "PATHS_DISAGREE_ON_IDENTITY"
77
+ },
78
+ "limits": [
79
+ "This does not say which of the two paths is wrong, only that they cannot both be right."
80
+ ]
81
+ }