@integraledger/agent-guard 0.9.0 → 0.10.1
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.
- package/CHANGELOG.md +69 -0
- package/README.md +28 -12
- package/dist/proposal-ack.js +3 -3
- package/dist/proposal-ack.js.map +1 -1
- package/dist/proposal-acp.d.ts +1 -1
- package/dist/proposal-acp.js +1 -1
- package/dist/proposal-ap2.d.ts +1 -1
- package/dist/proposal-ap2.d.ts.map +1 -1
- package/dist/proposal-ap2.js +2 -1
- package/dist/proposal-ap2.js.map +1 -1
- package/dist/proposal-mpp.d.ts +1 -1
- package/dist/proposal-mpp.js +1 -1
- package/dist/proposal-universal.d.ts +18 -31
- package/dist/proposal-universal.d.ts.map +1 -1
- package/dist/proposal-universal.js +10 -37
- package/dist/proposal-universal.js.map +1 -1
- package/package.json +21 -20
- package/src/proposal-ack.ts +3 -3
- package/src/proposal-acp.ts +1 -1
- package/src/proposal-ap2.ts +3 -2
- package/src/proposal-mpp.ts +1 -1
- package/src/proposal-universal.ts +31 -76
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,74 @@
|
|
|
1
1
|
# @integraledger/agent-guard
|
|
2
2
|
|
|
3
|
+
## 0.10.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5154cfb: Install one copy of the protocol packages, not two.
|
|
8
|
+
|
|
9
|
+
`lcp-mcp-server` pinned its `@integraledger/lcp-*` dependencies to an exact version while `agent-guard`
|
|
10
|
+
— which it depends on — declares the same packages as peers at a caret range. Those two declarations
|
|
11
|
+
cannot be satisfied by a single copy, so installing both packages resolved the protocol line **twice**:
|
|
12
|
+
once hoisted to satisfy the caret, and once nested under `lcp-mcp-server` to satisfy the exact pin. The
|
|
13
|
+
two halves of one install then read different protocol code, with `instanceof` failing across the seam
|
|
14
|
+
between them.
|
|
15
|
+
|
|
16
|
+
`lcp-mcp-server` now declares those dependencies as a caret at the minor line's zero patch, matching its
|
|
17
|
+
sibling. A tree holding both resolves a single copy, and `npx lcp-mcp` still installs standalone.
|
|
18
|
+
|
|
19
|
+
Nothing about either package's API, behaviour or guarantees changes. Both were correct in isolation; only
|
|
20
|
+
a tree holding both was affected.
|
|
21
|
+
|
|
22
|
+
- ccf4bb4: The runtime table is measured now, not argued.
|
|
23
|
+
|
|
24
|
+
It used to assert that this package works on Bun and Deno because of what the import graph implies — the
|
|
25
|
+
one Node built-in that arrives, `node:crypto`, is polyfilled on both. That was a sound argument and it was
|
|
26
|
+
only ever an argument; nothing ran.
|
|
27
|
+
|
|
28
|
+
Every release now drives the guard's whole decision on Node, Bun and Deno, against the packed tarball
|
|
29
|
+
installed the way you would install it, with the protocol line resolved from npmjs. Both halves are
|
|
30
|
+
asserted on each runtime, because a runtime where the guard refused everything would pass a check that only
|
|
31
|
+
looked for the halt: tampered terms must halt with the signer never reached, and matching terms must sign
|
|
32
|
+
with the signer reached exactly once.
|
|
33
|
+
|
|
34
|
+
Measured on this release: Node 24.19.0, Bun 1.4.0, Deno 2.9.5.
|
|
35
|
+
|
|
36
|
+
The table now separates what is measured from what is reasoned. Workers with `nodejs_compat` and the
|
|
37
|
+
bundler row remain arguments from the import graph and say so, rather than sitting in the same column as
|
|
38
|
+
the rows that ran.
|
|
39
|
+
|
|
40
|
+
## 0.10.0
|
|
41
|
+
|
|
42
|
+
### Minor Changes
|
|
43
|
+
|
|
44
|
+
- 06a25ac: Read the whole advertisement, and move to protocol 0.12.0.
|
|
45
|
+
|
|
46
|
+
The peer range was `^0.10.1`, which on a `0.x` version admits only patches — so this guard declared it did
|
|
47
|
+
not support the line every seller now writes, and a tree holding both resolved a second copy of the protocol
|
|
48
|
+
packages to satisfy it. The peers are `^0.12.0` and the build pins 0.12.0 exactly.
|
|
49
|
+
|
|
50
|
+
**The terms URL is no longer read by hand.** `PlacementManifest.termsUrlField` was singular and named one
|
|
51
|
+
path; it is now `termsUrlFields`, plural, and a slot that rides a container the placement owns is declared on
|
|
52
|
+
that container. Reading that by hand here would have been a second implementation of a manifest rule, so the
|
|
53
|
+
locator now comes from the placement's own `extract`, which reconciles every declared slot and refuses two
|
|
54
|
+
that disagree. The reference walk stays this package's own: "integrity carriers only" is a BUYER rule — a
|
|
55
|
+
discovery link locates a standing page and attests nothing — and the placement's reader does not apply it.
|
|
56
|
+
|
|
57
|
+
**`AdvertisedTermsUrl` loses a state, and could not keep it.** `undeclared-at-answering-carrier` existed
|
|
58
|
+
because the singular member could not reach the carrier a §C.4 challenge actually used: the hash answered
|
|
59
|
+
from `accepts[].extra` while the one declared path sat empty inside `extensions`, and reporting that as "no
|
|
60
|
+
terms advertised" would have asserted a silence this reader could not see. With every slot declared and
|
|
61
|
+
reconciled there is no such carrier, so the state is unreachable rather than merely unused, and the §C.4
|
|
62
|
+
challenge now simply reads its URL. `declared-field-empty` becomes `declared-fields-empty` and carries every
|
|
63
|
+
slot it looked at.
|
|
64
|
+
|
|
65
|
+
`lcp_place_reference` takes an optional `termsUrl` — required where the protocol declares a slot and the
|
|
66
|
+
reference is a digest, refused where it declares none — and `lcp_extract_reference` reports the locator
|
|
67
|
+
beside the reference, with its two absences distinguished: a protocol with no slot is not a seller who left
|
|
68
|
+
one empty.
|
|
69
|
+
|
|
70
|
+
Wire identities are unchanged apart from the protocol line itself.
|
|
71
|
+
|
|
3
72
|
## 0.9.0
|
|
4
73
|
|
|
5
74
|
**First public release** — Apache-2.0, free forever, no account and no token to install.
|
package/README.md
CHANGED
|
@@ -59,12 +59,20 @@ no DNS module at all. That much is enforced by the code and is the part worth re
|
|
|
59
59
|
ours: `@integraledger/lcp-evidence` re-exports its CAR support from its index, which pulls `multiformats`'
|
|
60
60
|
Node SHA-2 build, which statically imports `node:crypto`. So:
|
|
61
61
|
|
|
62
|
-
| Target | Works |
|
|
63
|
-
|
|
64
|
-
| Node | yes |
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
62
|
+
| Target | Works | How we know |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| Node | yes | **measured** — every release runs the guard's whole decision here |
|
|
65
|
+
| Bun | yes | **measured** — same run, same assertions |
|
|
66
|
+
| Deno | yes | **measured** — same run, same assertions |
|
|
67
|
+
| Workers with `nodejs_compat` | yes — `node:crypto` is polyfilled | reasoned from the import graph, not measured |
|
|
68
|
+
| A bundler honouring `multiformats`' `browser` export condition | yes — it maps to the browser SHA-2 build | reasoned from the export conditions, not measured |
|
|
69
|
+
| A plain unbundled ESM import in a browser or service worker | **no** | reasoned — `node:crypto` has nothing to resolve to |
|
|
70
|
+
|
|
71
|
+
The measured rows run against **the packed tarball**, installed the way you would install it, with the
|
|
72
|
+
protocol line resolved from npmjs — not against this repository's own tree. Both halves of the guarantee are
|
|
73
|
+
asserted on each runtime, because a runtime where the guard refused everything would pass a check that only
|
|
74
|
+
looked for the halt: tampered terms must halt with the signer never reached, and matching terms must sign
|
|
75
|
+
with the signer reached exactly once.
|
|
68
76
|
|
|
69
77
|
The guard needs `fetch` and Web Crypto and nothing else of its own. Removing the last hop is an upstream
|
|
70
78
|
change — a subpath export on `lcp-evidence` so importing one predicate does not drag CAR and `multiformats`
|
|
@@ -132,12 +140,20 @@ Four answers are worth stating plainly, because each is a place a friendlier lib
|
|
|
132
140
|
ACP/UCP one is contingent on the document, while `ap2`'s rule is a strict subset of `a2a`'s, so **every**
|
|
133
141
|
AP2 envelope matches both and none is reachable through `parseProposalUniversal`. AP2 is a detect-and-name
|
|
134
142
|
protocol here; `parseProposalFromAp2Envelope` exists and is called by name.
|
|
135
|
-
- **An
|
|
136
|
-
`no-field-declared`, `declared-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
143
|
+
- **An absent terms URL says WHICH absence it is.** `legalContextUrl` is a union — `read`,
|
|
144
|
+
`no-field-declared`, or `declared-fields-empty` — because a bare `undefined` conflates two different
|
|
145
|
+
facts. `no-field-declared` is a fact about the PROTOCOL: it has nowhere to put a locator, and no document
|
|
146
|
+
of that protocol can be faulted for lacking one. `declared-fields-empty` is a fact about THIS DOCUMENT:
|
|
147
|
+
the protocol has room and this seller left every declared slot empty. Reporting the second as the first
|
|
148
|
+
would blame a protocol for a seller's silence.
|
|
149
|
+
|
|
150
|
+
It used to carry a fourth state, `undeclared-at-answering-carrier`, and that state is gone because the
|
|
151
|
+
defect requiring it is fixed. The manifest's terms-URL member was singular, so x402 could declare only one
|
|
152
|
+
of its two slots: a §C.4-illustrated challenge advertising in `accepts[].extra` really does carry a terms
|
|
153
|
+
URL, while the single declared path sat empty inside `extensions` — and calling that "no terms advertised"
|
|
154
|
+
would have asserted a silence this reader could not see. The member is plural now, every declared slot is
|
|
155
|
+
read and reconciled, and a slot riding a container the placement owns is declared on that container. There
|
|
156
|
+
is no carrier a declaration fails to reach, so the state is unreachable rather than merely unused.
|
|
141
157
|
- **Carrier disagreement refuses.** Where a protocol declares more than one carrier, all of them are read
|
|
142
158
|
and compared. Two different hashes on one document would let a seller advertise different terms to
|
|
143
159
|
different readers of it, so this is deliberately stricter than the placement adapter's own `extract`,
|
package/dist/proposal-ack.js
CHANGED
|
@@ -77,8 +77,8 @@ export function parseAckReceipt(credential) {
|
|
|
77
77
|
const extracted = ackPlacement.extract(credential);
|
|
78
78
|
if (!("ok" in extracted))
|
|
79
79
|
throw new Error(`ACK receipt carries no readable LCP reference (${extracted.haltClass}/${extracted.code})`);
|
|
80
|
-
if (extracted.value.type !== "sha256")
|
|
81
|
-
throw new Error(`ACK legalContext must be a sha256 carrier, got "${extracted.value.type}" — a locator commits to nothing`);
|
|
80
|
+
if (extracted.value.ref.type !== "sha256")
|
|
81
|
+
throw new Error(`ACK legalContext must be a sha256 carrier, got "${extracted.value.ref.type}" — a locator commits to nothing`);
|
|
82
82
|
const owned = lcpKeys();
|
|
83
83
|
// `extract` above read the LCP key out of THIS map, so the map is an object and the narrowing cannot
|
|
84
84
|
// fail. Asserted rather than branched: a defensive `typeof` ternary here would ship an else-arm no input
|
|
@@ -86,7 +86,7 @@ export function parseAckReceipt(credential) {
|
|
|
86
86
|
const metadata = readAtPath(credential, "credentialSubject.metadata");
|
|
87
87
|
const siblingRefKeys = Object.keys(metadata).filter((k) => !owned.includes(k));
|
|
88
88
|
return {
|
|
89
|
-
atrHash: extracted.value.value,
|
|
89
|
+
atrHash: extracted.value.ref.value,
|
|
90
90
|
paymentRequestToken,
|
|
91
91
|
paymentOptionId,
|
|
92
92
|
payerDid,
|
package/dist/proposal-ack.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposal-ack.js","sourceRoot":"","sources":["../src/proposal-ack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAE/E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAEhF;;;;;;;GAOG;AACH,SAAS,OAAO;IACd,MAAM,IAAI,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7E,OAAO;QACL,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;QACzB,GAAG,CAAC,aAAa,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;KACnE,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc,EAAE,IAAY;IACjD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE;QAC3C,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,sCAAsC,CAAC,CAAC;IAC9E,OAAO,KAAK,CAAC;AACf,CAAC;AA0BD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAAC,UAAmB;IACjD,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC9C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QACvC,MAAM,IAAI,KAAK,CACb,sGAAsG;YACpG,wFAAwF,CAC3F,CAAC;IAEJ,MAAM,SAAS,GAAG,aAAa,CAC7B,UAAU,CAAC,UAAU,EAAE,WAAW,CAAC,EACnC,4FAA4F,CAC7F,CAAC;IACF,MAAM,QAAQ,GAAG,aAAa,CAC5B,UAAU,CAAC,UAAU,EAAE,sBAAsB,CAAC,EAC9C,sBAAsB,CACvB,CAAC;IACF,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7C,IACE,MAAM,KAAK,KAAK;QAChB,MAAM,KAAK,SAAS;QACpB,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC;QAEjC,MAAM,IAAI,KAAK,CACb,iBAAiB,QAAQ,oDAAoD,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC3G,CAAC;IACJ,MAAM,mBAAmB,GAAG,aAAa,CACvC,UAAU,CAAC,UAAU,EAAE,uCAAuC,CAAC,EAC/D,uCAAuC,CACxC,CAAC;IACF,MAAM,eAAe,GAAG,aAAa,CACnC,UAAU,CAAC,UAAU,EAAE,mCAAmC,CAAC,EAC3D,mCAAmC,CACpC,CAAC;IAEF,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,kDAAkD,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,GAAG,CAC3F,CAAC;IACJ,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ;
|
|
1
|
+
{"version":3,"file":"proposal-ack.js","sourceRoot":"","sources":["../src/proposal-ack.ts"],"names":[],"mappings":"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"}
|
package/dist/proposal-acp.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type { GateProposal, ProposalContext } from "./proposal.js";
|
|
|
6
6
|
* non-integer minor-unit amount.
|
|
7
7
|
*
|
|
8
8
|
* `legal_context_url` is required, and the ACP placement manifest DECLARES it as
|
|
9
|
-
* `
|
|
9
|
+
* `termsUrlFields: ["metadata.legal_context_url"]` — the field this parser demands is a field the placement
|
|
10
10
|
* names, which is what makes the round-trip compose. It is deliberately NOT read from ACP's native
|
|
11
11
|
* `links[type=terms_of_use]`: that link is the merchant's standing policy page, while this names the ATR
|
|
12
12
|
* terms document for this transaction, and falling back to it would substitute one for the other.
|
package/dist/proposal-acp.js
CHANGED
|
@@ -20,7 +20,7 @@ const AcpSessionSchema = z.object({
|
|
|
20
20
|
* non-integer minor-unit amount.
|
|
21
21
|
*
|
|
22
22
|
* `legal_context_url` is required, and the ACP placement manifest DECLARES it as
|
|
23
|
-
* `
|
|
23
|
+
* `termsUrlFields: ["metadata.legal_context_url"]` — the field this parser demands is a field the placement
|
|
24
24
|
* names, which is what makes the round-trip compose. It is deliberately NOT read from ACP's native
|
|
25
25
|
* `links[type=terms_of_use]`: that link is the merchant's standing policy page, while this names the ATR
|
|
26
26
|
* terms document for this transaction, and falling back to it would substitute one for the other.
|
package/dist/proposal-ap2.d.ts
CHANGED
|
@@ -81,7 +81,7 @@ export interface Ap2ProposalContext extends ProposalContext {
|
|
|
81
81
|
/**
|
|
82
82
|
* The terms document's locator.
|
|
83
83
|
*
|
|
84
|
-
* AP2's placement is INTEGRITY-ONLY: `AP2_PLACEMENT` declares no `
|
|
84
|
+
* AP2's placement is INTEGRITY-ONLY: `AP2_PLACEMENT` declares no `termsUrlFields`, because the A2A
|
|
85
85
|
* `Message.metadata` map holds the reference and AP2 models no terms-URL field anywhere. So unlike ACP
|
|
86
86
|
* (`metadata.legal_context_url`) and x402 (`extra.legalContextUrl`), the locator cannot come off the wire.
|
|
87
87
|
* It comes from LCP §2 discovery — the seller's `/.well-known/legal-context.json` — resolved by the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposal-ap2.d.ts","sourceRoot":"","sources":["../src/proposal-ap2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEnE;;;;;;;;GAQG;AACH,MAAM,MAAM,OAAO,GACf,uBAAuB,GACvB,uBAAuB,GACvB,+BAA+B,GAC/B,mBAAmB,GACnB,0BAA0B,CAAC;AAE/B,iGAAiG;AACjG,MAAM,WAAW,YAAY;IAC3B,kGAAkG;IAClG,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,6FAA6F;IAC7F,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,4FAA4F;IAC5F,QAAQ,CAAC,YAAY,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1C,oFAAoF;IACpF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wGAAwG;IACxG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,cAAc,EAAE,YAY5B,CAAC;AAEF,uGAAuG;AACvG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAM5D;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,OAAO,EACjB,GAAG,EAAE,kBAAkB,GACtB,YAAY,
|
|
1
|
+
{"version":3,"file":"proposal-ap2.d.ts","sourceRoot":"","sources":["../src/proposal-ap2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEnE;;;;;;;;GAQG;AACH,MAAM,MAAM,OAAO,GACf,uBAAuB,GACvB,uBAAuB,GACvB,+BAA+B,GAC/B,mBAAmB,GACnB,0BAA0B,CAAC;AAE/B,iGAAiG;AACjG,MAAM,WAAW,YAAY;IAC3B,kGAAkG;IAClG,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,6FAA6F;IAC7F,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,4FAA4F;IAC5F,QAAQ,CAAC,YAAY,EAAE,SAAS,OAAO,EAAE,CAAC;IAC1C,oFAAoF;IACpF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wGAAwG;IACxG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,cAAc,EAAE,YAY5B,CAAC;AAEF,uGAAuG;AACvG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAM5D;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,OAAO,EACjB,GAAG,EAAE,kBAAkB,GACtB,YAAY,CAqCd"}
|
package/dist/proposal-ap2.js
CHANGED
|
@@ -87,7 +87,8 @@ export function parseProposalFromAp2Envelope(envelope, ctx) {
|
|
|
87
87
|
const extracted = ap2Placement.extract(envelope);
|
|
88
88
|
if (!("ok" in extracted))
|
|
89
89
|
throw new Error(`AP2 envelope carries no readable LCP reference (${extracted.haltClass}/${extracted.code})`);
|
|
90
|
-
|
|
90
|
+
// AP2 declares no terms-URL slot, so the advertisement is the reference alone.
|
|
91
|
+
const ref = extracted.value.ref;
|
|
91
92
|
if (ref.type !== "sha256")
|
|
92
93
|
throw new Error(`AP2 legalContext must be a sha256 carrier, got "${ref.type}" — the gate compares the advertised ` +
|
|
93
94
|
"hash against a recomputed one, and a locator commits to nothing");
|
package/dist/proposal-ap2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposal-ap2.js","sourceRoot":"","sources":["../src/proposal-ap2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAiChE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,YAAY,EAAE,uBAAuB;IACrC,UAAU,EAAE,+BAA+B;IAC3C,YAAY,EAAE;QACZ,+BAA+B;QAC/B,mBAAmB;QACnB,0BAA0B;KAC3B;IACD,SAAS,EACP,gaAAga;IACla,OAAO,EACL,gRAAgR;CACnR,CAAC;AAEF,uGAAuG;AACvG,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,OAAO,cAAc,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAa;IACpD,IAAI,gBAAgB,CAAC,IAAI,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,wBAAwB,IAAI,0CAA0C,cAAc,CAAC,UAAU,KAAK;YAClG,kDAAkD,cAAc,CAAC,YAAY,MAAM,cAAc,CAAC,SAAS,EAAE,CAChH,CAAC;AACN,CAAC;AAkCD,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,mEAAmE;AAErG;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAAiB,EACjB,GAAuB;IAEvB,yGAAyG;IACzG,oDAAoD;IACpD,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEnC,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,mDAAmD,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,GAAG,CAC5F,CAAC;IACJ,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"proposal-ap2.js","sourceRoot":"","sources":["../src/proposal-ap2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAiChE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,YAAY,EAAE,uBAAuB;IACrC,UAAU,EAAE,+BAA+B;IAC3C,YAAY,EAAE;QACZ,+BAA+B;QAC/B,mBAAmB;QACnB,0BAA0B;KAC3B;IACD,SAAS,EACP,gaAAga;IACla,OAAO,EACL,gRAAgR;CACnR,CAAC;AAEF,uGAAuG;AACvG,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,OAAO,cAAc,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAa;IACpD,IAAI,gBAAgB,CAAC,IAAI,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,wBAAwB,IAAI,0CAA0C,cAAc,CAAC,UAAU,KAAK;YAClG,kDAAkD,cAAc,CAAC,YAAY,MAAM,cAAc,CAAC,SAAS,EAAE,CAChH,CAAC;AACN,CAAC;AAkCD,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,mEAAmE;AAErG;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAAiB,EACjB,GAAuB;IAEvB,yGAAyG;IACzG,oDAAoD;IACpD,wBAAwB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEnC,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,mDAAmD,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,GAAG,CAC5F,CAAC;IACJ,+EAA+E;IAC/E,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC;IAChC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ;QACvB,MAAM,IAAI,KAAK,CACb,mDAAmD,GAAG,CAAC,IAAI,uCAAuC;YAChG,iEAAiE,CACpE,CAAC;IACJ,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,UAAU,CAAC,UAAU,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;IAC3E,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;QACvC,MAAM,IAAI,KAAK,CACb,qDAAqD,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CACzE,CAAC;IAEJ,0GAA0G;IAC1G,sGAAsG;IACtG,kEAAkE;IAClE,OAAO;QACL,iBAAiB,EAAE,GAAG,CAAC,KAAsB;QAC7C,eAAe,EAAE,GAAG,CAAC,eAAe;QACpC,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,KAAK,EAAE;YACL,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM;YACxB,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI;SACrB;QACD,eAAe,EAAE,GAAG,CAAC,eAAe;KACrC,CAAC;AACJ,CAAC"}
|
package/dist/proposal-mpp.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ import type { GateProposal, ProposalContext } from "./proposal.js";
|
|
|
24
24
|
* restating its regex keeps one definition of what an ATR hash is.
|
|
25
25
|
*
|
|
26
26
|
* **`legalContextUrl` is the field the placement names.** `placement-mpp` declares
|
|
27
|
-
* `
|
|
27
|
+
* `termsUrlFields: ["methodDetails.legalContextUrl"]`, so the field this parser demands is the field the
|
|
28
28
|
* manifest names — which is what makes the seller's write and this buyer's read compose. There is no
|
|
29
29
|
* fallback to any other member: MPP defines none that means "these terms", and inventing one would gate the
|
|
30
30
|
* buyer against a document nobody pointed at.
|
package/dist/proposal-mpp.js
CHANGED
|
@@ -53,7 +53,7 @@ const BASE_UNIT_INT = /^[0-9]+$/;
|
|
|
53
53
|
* restating its regex keeps one definition of what an ATR hash is.
|
|
54
54
|
*
|
|
55
55
|
* **`legalContextUrl` is the field the placement names.** `placement-mpp` declares
|
|
56
|
-
* `
|
|
56
|
+
* `termsUrlFields: ["methodDetails.legalContextUrl"]`, so the field this parser demands is the field the
|
|
57
57
|
* manifest names — which is what makes the seller's write and this buyer's read compose. There is no
|
|
58
58
|
* fallback to any other member: MPP defines none that means "these terms", and inventing one would gate the
|
|
59
59
|
* buyer against a document nobody pointed at.
|
|
@@ -105,46 +105,34 @@ export declare function matchProtocols(wire: unknown): readonly ProtocolId[];
|
|
|
105
105
|
*/
|
|
106
106
|
export declare function detectProtocol(wire: unknown): ProtocolId | undefined;
|
|
107
107
|
/**
|
|
108
|
-
* The terms URL a document advertises at the
|
|
109
|
-
* stated rather than folded into an `undefined`.
|
|
110
|
-
*
|
|
111
|
-
* A UNION, because `string | undefined` conflated
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* `
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* change. Until it lands this type REPORTS the gap, because a reader that cannot tell two facts apart must say
|
|
122
|
-
* which one it cannot tell.
|
|
108
|
+
* The terms URL a document advertises at the slots its manifest declares — or the reason there is no
|
|
109
|
+
* answer, stated rather than folded into an `undefined`.
|
|
110
|
+
*
|
|
111
|
+
* A UNION, because `string | undefined` conflated facts and only some of them are absences.
|
|
112
|
+
*
|
|
113
|
+
* IT USED TO CARRY A FOURTH STATE, and the state is gone because the defect that required it is fixed.
|
|
114
|
+
* `PlacementManifest.termsUrlField` was SINGULAR, so x402 could declare only one of its two slots: read a
|
|
115
|
+
* §C.4 challenge and the hash answered from `accepts[].extra` while the single declared path — inside
|
|
116
|
+
* `extensions.legalContext.info` — held nothing. Reporting that as "the seller advertised no terms" would
|
|
117
|
+
* have asserted a silence this reader could not see, so it reported `undeclared-at-answering-carrier`
|
|
118
|
+
* instead. `termsUrlFields` is now plural and every slot is read and reconciled, and a slot riding a
|
|
119
|
+
* container the placement owns is declared on the container — so there is no carrier a declaration fails
|
|
120
|
+
* to reach, and the state is unreachable rather than merely unused.
|
|
123
121
|
*/
|
|
124
122
|
export type AdvertisedTermsUrl =
|
|
125
|
-
/** Read from
|
|
123
|
+
/** Read from a slot the manifest declares. Where several are declared they agreed. */
|
|
126
124
|
{
|
|
127
125
|
readonly kind: "read";
|
|
128
126
|
readonly url: string;
|
|
129
127
|
}
|
|
130
|
-
/** The manifest declares no terms-URL
|
|
128
|
+
/** The manifest declares no terms-URL slot at all: the protocol has no room for one. */
|
|
131
129
|
| {
|
|
132
130
|
readonly kind: "no-field-declared";
|
|
133
131
|
}
|
|
134
|
-
/**
|
|
132
|
+
/** Slots are declared and this document leaves every one of them empty. */
|
|
135
133
|
| {
|
|
136
|
-
readonly kind: "declared-
|
|
137
|
-
readonly
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* The manifest's terms-URL path lies INSIDE the canonical carrier's own object, and the reference answered
|
|
141
|
-
* from a declared alias instead — so the declaration never reached the carrier this document used. Whether
|
|
142
|
-
* the document advertises a terms URL is UNKNOWN to this reader, not answered.
|
|
143
|
-
*/
|
|
144
|
-
| {
|
|
145
|
-
readonly kind: "undeclared-at-answering-carrier";
|
|
146
|
-
readonly field: string;
|
|
147
|
-
readonly answeredAt: string;
|
|
134
|
+
readonly kind: "declared-fields-empty";
|
|
135
|
+
readonly fields: readonly string[];
|
|
148
136
|
};
|
|
149
137
|
/** What a protocol document advertises about the terms governing it. */
|
|
150
138
|
export type AdvertisedTerms = {
|
|
@@ -188,7 +176,6 @@ export type AdvertisedTerms = {
|
|
|
188
176
|
* throws from the registry rather than answering about some invented namespace.
|
|
189
177
|
*/
|
|
190
178
|
export declare function readAdvertisedTerms(protocol: ProtocolId, wire: unknown, deployment?: PlacementDeployment): AdvertisedTerms;
|
|
191
|
-
/** A parser from one protocol's wire document to the one `GateProposal` every parser produces. */
|
|
192
179
|
export type ProposalParser = (wire: unknown, ctx: ProposalContext) => GateProposal;
|
|
193
180
|
/**
|
|
194
181
|
* Every protocol this build can turn into a complete `GateProposal`, keyed by `ProtocolId`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposal-universal.d.ts","sourceRoot":"","sources":["../src/proposal-universal.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,UAAU,EAIhB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,eAAe,EAErB,MAAM,eAAe,CAAC;AAiCvB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAY/C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAGhD,CAAC;AAmDF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IACE,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,sGAAsG;IACtG,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IAC5C,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,GACD;IACE,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,oBAAoB,EA2FjE,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,UAAU,EAAE,CAOnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAGpE;AAMD
|
|
1
|
+
{"version":3,"file":"proposal-universal.d.ts","sourceRoot":"","sources":["../src/proposal-universal.ts"],"names":[],"mappings":"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"}
|
|
@@ -363,48 +363,21 @@ export function readAdvertisedTerms(protocol, wire, deployment) {
|
|
|
363
363
|
const ref = sole.ref;
|
|
364
364
|
if (ref.type !== "sha256")
|
|
365
365
|
throw new Error(`${protocol} advertises an lcp:${ref.type}: reference; the gate compares the advertised value against a recomputed record hash, which only a sha256 carrier can be`);
|
|
366
|
+
// The reference walk above is this package's own, because "integrity carriers only" is a BUYER rule:
|
|
367
|
+
// a discovery link locates a standing page and attests nothing, so it is never a candidate here even
|
|
368
|
+
// though the placement will happily read one. The TERMS URL is the placement's, because every rule about
|
|
369
|
+
// it — which slots a protocol declares, that a slot riding a container the placement owns is addressed
|
|
370
|
+
// through that container, that two slots disagreeing is a refusal rather than a preference — belongs to
|
|
371
|
+
// the manifest, and a second implementation here could only agree with it until the day it did not.
|
|
372
|
+
const advertised = placement.extract(wire);
|
|
373
|
+
if ("refused" in advertised)
|
|
374
|
+
throw new Error(`${protocol} document carries no readable advertisement (${advertised.code}): ${advertised.detail ?? ""}`);
|
|
366
375
|
return {
|
|
367
376
|
protocol,
|
|
368
377
|
advertisedAtrHash: ref.value,
|
|
369
|
-
legalContextUrl:
|
|
378
|
+
legalContextUrl: advertised.value.termsUrl,
|
|
370
379
|
};
|
|
371
380
|
}
|
|
372
|
-
/**
|
|
373
|
-
* The terms URL at the field the manifest DECLARES — or which of the three absences this is.
|
|
374
|
-
*
|
|
375
|
-
* `termsUrlField` is a plain dotted path on the manifest: it declares no container of its own, so it is read
|
|
376
|
-
* with `readAtPath` rather than through the reference carrier's container. A manifest that omits it (A2A, ACK,
|
|
377
|
-
* Visa TAP, Mastercard VI) is stating that its protocol has no room for one — a fact, not a gap.
|
|
378
|
-
*
|
|
379
|
-
* NOTHING AT THE DECLARED PATH IS TWO DIFFERENT FACTS, and which one it is turns on where the reference
|
|
380
|
-
* answered from. `termsUrlField` is declared once, beside the canonical `field`; a `readAlso` alias carries no
|
|
381
|
-
* terms-URL declaration of its own. So when the declared path is nested INSIDE the canonical field — x402's
|
|
382
|
-
* `extensions.legalContext.info.legalContextUrl` inside `extensions.legalContext.info` — and the reference
|
|
383
|
-
* answered from an alias instead, the manifest's declaration was scoped to a carrier this document did not
|
|
384
|
-
* use, and its emptiness says nothing about the document. When the declared path is a SIBLING of the canonical
|
|
385
|
-
* field (ACP's `metadata.legal_context_url`, MPP's `methodDetails.legalContextUrl`), it is reachable whichever
|
|
386
|
-
* carrier answered, and empty means empty.
|
|
387
|
-
*
|
|
388
|
-
* `answeredAt` is the path the reconciled reference was read from. `carrierSlots` puts the canonical field
|
|
389
|
-
* first and `integrityHits` preserves that order, so it differs from `manifest.field` exactly when the
|
|
390
|
-
* canonical carrier did not answer.
|
|
391
|
-
*/
|
|
392
|
-
function readTermsUrl(protocol, doc, manifest, answeredAt) {
|
|
393
|
-
const field = manifest.termsUrlField;
|
|
394
|
-
if (field === undefined)
|
|
395
|
-
return { kind: "no-field-declared" };
|
|
396
|
-
const raw = readAtPath(doc, field);
|
|
397
|
-
if (raw === undefined)
|
|
398
|
-
return answeredAt !== manifest.field &&
|
|
399
|
-
field.startsWith(`${manifest.field}.`)
|
|
400
|
-
? { kind: "undeclared-at-answering-carrier", field, answeredAt }
|
|
401
|
-
: { kind: "declared-field-empty", field };
|
|
402
|
-
if (typeof raw !== "string")
|
|
403
|
-
throw new Error(`${protocol} ${field} is not a string: ${JSON.stringify(raw)}`);
|
|
404
|
-
if (!raw.startsWith("https://"))
|
|
405
|
-
throw new Error(`legalContextUrl must be HTTPS: ${raw}`);
|
|
406
|
-
return { kind: "read", url: raw };
|
|
407
|
-
}
|
|
408
381
|
/**
|
|
409
382
|
* Every protocol this build can turn into a complete `GateProposal`, keyed by `ProtocolId`.
|
|
410
383
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposal-universal.js","sourceRoot":"","sources":["../src/proposal-universal.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EAMlB,UAAU,EACV,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAEL,YAAY,GACb,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,0BAA0B,GAC3B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAEjE,4GAA4G;AAC5G,2GAA2G;AAC3G,6GAA6G;AAC7G,2GAA2G;AAC3G,6DAA6D;AAC7D,4GAA4G;AAE5G,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,UAAU,CAAC,GAAY,EAAE,IAAY;IAC5C,OAAO,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,QAAQ,CAAC;AACnD,CAAC;AAED,SAAS,SAAS,CAAC,GAAY,EAAE,IAAY;IAC3C,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,eAAe,CACtB,GAAY,EACZ,IAAY,EACZ,SAA4B;IAE5B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACpC,4GAA4G;IAC5G,4GAA4G;IAC5G,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsB;IACnD,YAAY;IACZ,uBAAuB;IACvB,qBAAqB;IACrB,yBAAyB;IACzB,mBAAmB;IACnB,kBAAkB;IAClB,sBAAsB;IACtB,WAAW;IACX,UAAU;IACV,aAAa;IACb,SAAS;CACV,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAsB;IACpD,yBAAyB;IACzB,wBAAwB;CACzB,CAAC;AAEF,sGAAsG;AACtG,MAAM,qBAAqB,GAAsB;IAC/C,mCAAmC;IACnC,kCAAkC;CACnC,CAAC;AAEF,+GAA+G;AAC/G,MAAM,kBAAkB,GAAsB;IAC5C,oBAAoB;IACpB,kBAAkB;CACnB,CAAC;AAEF,+FAA+F;AAC/F,SAAS,SAAS,CAAC,GAAY;IAC7B,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,UAAU,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;AAClE,CAAC;AAED,4GAA4G;AAC5G,SAAS,YAAY,CAAC,GAAY;IAChC,OAAO,CACL,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC;QAC5B,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC,CACxB,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,GAAY;IACrC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,SAAS,KAAK,OAAO,CAAC,CAAC;QACpD,OAAO,CACL,QAAQ,CAAC,IAAI,CAAC;YACd,qBAAqB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAC9D,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAoCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAoC;IACrE;QACE,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CACf,OAAO,UAAU,CAAC,GAAG,EAAE,aAAa,CAAC,KAAK,QAAQ;YAClD,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC;QAC3B,IAAI,EAAE,qJAAqJ;KAC5J;IACD;QACE,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,iBAAiB;QACvB,MAAM,EACJ,s0BAAs0B;QACx0B,IAAI,EAAE,yNAAyN;KAChO;IACD;QACE,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,YAAY;QAClB,wGAAwG;QACxG,uGAAuG;QACvG,0DAA0D;QAC1D,EAAE;QACF,0GAA0G;QAC1G,sFAAsF;QACtF,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC;QAC7D,IAAI,EAAE,iSAAiS;KACxS;IACD;QACE,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACf,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YACtC,OAAO,CACL,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBACpB,KAAK,CAAC,QAAQ,CAAC,0BAA0B,CAAC;gBAC1C,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC,CAC/C,CAAC;QACJ,CAAC;QACD,IAAI,EAAE,2QAA2Q;KAClR;IACD;QACE,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CACf,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,kBAAkB,CAAC;YAClD,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC;YAC3B,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC;YACxB,SAAS,CAAC,GAAG,EAAE,YAAY,CAAC;QAC9B,IAAI,EAAE,iSAAiS;KACxS;IACD;QACE,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CACf,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAChC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC;YACrB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;YACzB,SAAS,CAAC,GAAG,EAAE,OAAO,CAAC;QACzB,IAAI,EAAE,6NAA6N;KACpO;IACD;QACE,QAAQ,EAAE,UAAU;QACpB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACf,MAAM,cAAc,GAAG,iBAAiB,CACtC,GAAG,EACH,EAAE,IAAI,EAAE,YAAY,EAAE,EACtB,yBAAyB,CAC1B,CAAC;YACF,OAAO,CACL,OAAO,cAAc,KAAK,QAAQ;gBAClC,kBAAkB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CACtE,CAAC;QACJ,CAAC;QACD,IAAI,EAAE,wMAAwM;KAC/M;IACD;QACE,QAAQ,EAAE,eAAe;QACzB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CACf,eAAe,CAAC,GAAG,EAAE,KAAK,EAAE,mBAAmB,CAAC;YAChD,SAAS,CAAC,GAAG,EAAE,aAAa,CAAC;QAC/B,IAAI,EAAE,0NAA0N;KACjO;IACD;QACE,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC;QACrD,IAAI,EAAE,6NAA6N;KACpO;CACF,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,sBAAsB,EAAE,CAAC;QACzC,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,IAAa;IAC1C,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;
|
|
1
|
+
{"version":3,"file":"proposal-universal.js","sourceRoot":"","sources":["../src/proposal-universal.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@integraledger/agent-guard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -28,28 +28,29 @@
|
|
|
28
28
|
"zod": "4.4.3"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@integraledger/lcp-authority": "^0.
|
|
32
|
-
"@integraledger/lcp-binding-core": "^0.
|
|
33
|
-
"@integraledger/lcp-discovery": "^0.
|
|
34
|
-
"@integraledger/lcp-evidence": "^0.
|
|
35
|
-
"@integraledger/lcp-kernel": "^0.
|
|
36
|
-
"@integraledger/lcp-placement-ack": "^0.
|
|
37
|
-
"@integraledger/lcp-placement-ap2": "^0.
|
|
38
|
-
"@integraledger/lcp-placements": "^0.
|
|
39
|
-
"@integraledger/lcp-verify": "^0.
|
|
31
|
+
"@integraledger/lcp-authority": "^0.12.0",
|
|
32
|
+
"@integraledger/lcp-binding-core": "^0.12.0",
|
|
33
|
+
"@integraledger/lcp-discovery": "^0.12.0",
|
|
34
|
+
"@integraledger/lcp-evidence": "^0.12.0",
|
|
35
|
+
"@integraledger/lcp-kernel": "^0.12.0",
|
|
36
|
+
"@integraledger/lcp-placement-ack": "^0.12.0",
|
|
37
|
+
"@integraledger/lcp-placement-ap2": "^0.12.0",
|
|
38
|
+
"@integraledger/lcp-placements": "^0.12.0",
|
|
39
|
+
"@integraledger/lcp-verify": "^0.12.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@integraledger/lcp-authority": "0.
|
|
43
|
-
"@integraledger/lcp-binding-core": "0.
|
|
44
|
-
"@integraledger/lcp-discovery": "0.
|
|
45
|
-
"@integraledger/lcp-evidence": "0.
|
|
46
|
-
"@integraledger/lcp-kernel": "0.
|
|
47
|
-
"@integraledger/lcp-placement-ack": "0.
|
|
48
|
-
"@integraledger/lcp-placement-acp": "0.
|
|
49
|
-
"@integraledger/lcp-placement-ap2": "0.
|
|
50
|
-
"@integraledger/lcp-placements": "0.
|
|
51
|
-
"@integraledger/lcp-verify": "0.
|
|
42
|
+
"@integraledger/lcp-authority": "0.12.2",
|
|
43
|
+
"@integraledger/lcp-binding-core": "0.12.2",
|
|
44
|
+
"@integraledger/lcp-discovery": "0.12.2",
|
|
45
|
+
"@integraledger/lcp-evidence": "0.12.2",
|
|
46
|
+
"@integraledger/lcp-kernel": "0.12.2",
|
|
47
|
+
"@integraledger/lcp-placement-ack": "0.12.2",
|
|
48
|
+
"@integraledger/lcp-placement-acp": "0.12.2",
|
|
49
|
+
"@integraledger/lcp-placement-ap2": "0.12.2",
|
|
50
|
+
"@integraledger/lcp-placements": "0.12.2",
|
|
51
|
+
"@integraledger/lcp-verify": "0.12.2",
|
|
52
52
|
"@types/node": "24.13.3",
|
|
53
|
+
"fast-check": "4.9.0",
|
|
53
54
|
"vitest": "4.1.10"
|
|
54
55
|
},
|
|
55
56
|
"license": "Apache-2.0",
|
package/src/proposal-ack.ts
CHANGED
|
@@ -129,9 +129,9 @@ export function parseAckReceipt(credential: unknown): AckReceiptFacts {
|
|
|
129
129
|
throw new Error(
|
|
130
130
|
`ACK receipt carries no readable LCP reference (${extracted.haltClass}/${extracted.code})`,
|
|
131
131
|
);
|
|
132
|
-
if (extracted.value.type !== "sha256")
|
|
132
|
+
if (extracted.value.ref.type !== "sha256")
|
|
133
133
|
throw new Error(
|
|
134
|
-
`ACK legalContext must be a sha256 carrier, got "${extracted.value.type}" — a locator commits to nothing`,
|
|
134
|
+
`ACK legalContext must be a sha256 carrier, got "${extracted.value.ref.type}" — a locator commits to nothing`,
|
|
135
135
|
);
|
|
136
136
|
|
|
137
137
|
const owned = lcpKeys();
|
|
@@ -147,7 +147,7 @@ export function parseAckReceipt(credential: unknown): AckReceiptFacts {
|
|
|
147
147
|
);
|
|
148
148
|
|
|
149
149
|
return {
|
|
150
|
-
atrHash: extracted.value.value as `0x${string}`,
|
|
150
|
+
atrHash: extracted.value.ref.value as `0x${string}`,
|
|
151
151
|
paymentRequestToken,
|
|
152
152
|
paymentOptionId,
|
|
153
153
|
payerDid,
|
package/src/proposal-acp.ts
CHANGED
|
@@ -23,7 +23,7 @@ const AcpSessionSchema = z.object({
|
|
|
23
23
|
* non-integer minor-unit amount.
|
|
24
24
|
*
|
|
25
25
|
* `legal_context_url` is required, and the ACP placement manifest DECLARES it as
|
|
26
|
-
* `
|
|
26
|
+
* `termsUrlFields: ["metadata.legal_context_url"]` — the field this parser demands is a field the placement
|
|
27
27
|
* names, which is what makes the round-trip compose. It is deliberately NOT read from ACP's native
|
|
28
28
|
* `links[type=terms_of_use]`: that link is the merchant's standing policy page, while this names the ATR
|
|
29
29
|
* terms document for this transaction, and falling back to it would substitute one for the other.
|
package/src/proposal-ap2.ts
CHANGED
|
@@ -114,7 +114,7 @@ export interface Ap2ProposalContext extends ProposalContext {
|
|
|
114
114
|
/**
|
|
115
115
|
* The terms document's locator.
|
|
116
116
|
*
|
|
117
|
-
* AP2's placement is INTEGRITY-ONLY: `AP2_PLACEMENT` declares no `
|
|
117
|
+
* AP2's placement is INTEGRITY-ONLY: `AP2_PLACEMENT` declares no `termsUrlFields`, because the A2A
|
|
118
118
|
* `Message.metadata` map holds the reference and AP2 models no terms-URL field anywhere. So unlike ACP
|
|
119
119
|
* (`metadata.legal_context_url`) and x402 (`extra.legalContextUrl`), the locator cannot come off the wire.
|
|
120
120
|
* It comes from LCP §2 discovery — the seller's `/.well-known/legal-context.json` — resolved by the
|
|
@@ -166,7 +166,8 @@ export function parseProposalFromAp2Envelope(
|
|
|
166
166
|
throw new Error(
|
|
167
167
|
`AP2 envelope carries no readable LCP reference (${extracted.haltClass}/${extracted.code})`,
|
|
168
168
|
);
|
|
169
|
-
|
|
169
|
+
// AP2 declares no terms-URL slot, so the advertisement is the reference alone.
|
|
170
|
+
const ref = extracted.value.ref;
|
|
170
171
|
if (ref.type !== "sha256")
|
|
171
172
|
throw new Error(
|
|
172
173
|
`AP2 legalContext must be a sha256 carrier, got "${ref.type}" — the gate compares the advertised ` +
|
package/src/proposal-mpp.ts
CHANGED
|
@@ -57,7 +57,7 @@ const BASE_UNIT_INT = /^[0-9]+$/;
|
|
|
57
57
|
* restating its regex keeps one definition of what an ATR hash is.
|
|
58
58
|
*
|
|
59
59
|
* **`legalContextUrl` is the field the placement names.** `placement-mpp` declares
|
|
60
|
-
* `
|
|
60
|
+
* `termsUrlFields: ["methodDetails.legalContextUrl"]`, so the field this parser demands is the field the
|
|
61
61
|
* manifest names — which is what makes the seller's write and this buyer's read compose. There is no
|
|
62
62
|
* fallback to any other member: MPP defines none that means "these terms", and inventing one would gate the
|
|
63
63
|
* buyer against a document nobody pointed at.
|
|
@@ -332,38 +332,29 @@ export function detectProtocol(wire: unknown): ProtocolId | undefined {
|
|
|
332
332
|
// ---------------------------------------------------------------------------------------------------------
|
|
333
333
|
|
|
334
334
|
/**
|
|
335
|
-
* The terms URL a document advertises at the
|
|
336
|
-
* stated rather than folded into an `undefined`.
|
|
337
|
-
*
|
|
338
|
-
* A UNION, because `string | undefined` conflated
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
* `
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
* change. Until it lands this type REPORTS the gap, because a reader that cannot tell two facts apart must say
|
|
349
|
-
* which one it cannot tell.
|
|
335
|
+
* The terms URL a document advertises at the slots its manifest declares — or the reason there is no
|
|
336
|
+
* answer, stated rather than folded into an `undefined`.
|
|
337
|
+
*
|
|
338
|
+
* A UNION, because `string | undefined` conflated facts and only some of them are absences.
|
|
339
|
+
*
|
|
340
|
+
* IT USED TO CARRY A FOURTH STATE, and the state is gone because the defect that required it is fixed.
|
|
341
|
+
* `PlacementManifest.termsUrlField` was SINGULAR, so x402 could declare only one of its two slots: read a
|
|
342
|
+
* §C.4 challenge and the hash answered from `accepts[].extra` while the single declared path — inside
|
|
343
|
+
* `extensions.legalContext.info` — held nothing. Reporting that as "the seller advertised no terms" would
|
|
344
|
+
* have asserted a silence this reader could not see, so it reported `undeclared-at-answering-carrier`
|
|
345
|
+
* instead. `termsUrlFields` is now plural and every slot is read and reconciled, and a slot riding a
|
|
346
|
+
* container the placement owns is declared on the container — so there is no carrier a declaration fails
|
|
347
|
+
* to reach, and the state is unreachable rather than merely unused.
|
|
350
348
|
*/
|
|
351
349
|
export type AdvertisedTermsUrl =
|
|
352
|
-
/** Read from
|
|
350
|
+
/** Read from a slot the manifest declares. Where several are declared they agreed. */
|
|
353
351
|
| { readonly kind: "read"; readonly url: string }
|
|
354
|
-
/** The manifest declares no terms-URL
|
|
352
|
+
/** The manifest declares no terms-URL slot at all: the protocol has no room for one. */
|
|
355
353
|
| { readonly kind: "no-field-declared" }
|
|
356
|
-
/**
|
|
357
|
-
| { readonly kind: "declared-field-empty"; readonly field: string }
|
|
358
|
-
/**
|
|
359
|
-
* The manifest's terms-URL path lies INSIDE the canonical carrier's own object, and the reference answered
|
|
360
|
-
* from a declared alias instead — so the declaration never reached the carrier this document used. Whether
|
|
361
|
-
* the document advertises a terms URL is UNKNOWN to this reader, not answered.
|
|
362
|
-
*/
|
|
354
|
+
/** Slots are declared and this document leaves every one of them empty. */
|
|
363
355
|
| {
|
|
364
|
-
readonly kind: "
|
|
365
|
-
readonly
|
|
366
|
-
readonly answeredAt: string;
|
|
356
|
+
readonly kind: "declared-fields-empty";
|
|
357
|
+
readonly fields: readonly string[];
|
|
367
358
|
};
|
|
368
359
|
|
|
369
360
|
/** What a protocol document advertises about the terms governing it. */
|
|
@@ -534,61 +525,25 @@ export function readAdvertisedTerms(
|
|
|
534
525
|
`${protocol} advertises an lcp:${ref.type}: reference; the gate compares the advertised value against a recomputed record hash, which only a sha256 carrier can be`,
|
|
535
526
|
);
|
|
536
527
|
|
|
528
|
+
// The reference walk above is this package's own, because "integrity carriers only" is a BUYER rule:
|
|
529
|
+
// a discovery link locates a standing page and attests nothing, so it is never a candidate here even
|
|
530
|
+
// though the placement will happily read one. The TERMS URL is the placement's, because every rule about
|
|
531
|
+
// it — which slots a protocol declares, that a slot riding a container the placement owns is addressed
|
|
532
|
+
// through that container, that two slots disagreeing is a refusal rather than a preference — belongs to
|
|
533
|
+
// the manifest, and a second implementation here could only agree with it until the day it did not.
|
|
534
|
+
const advertised = placement.extract(wire);
|
|
535
|
+
if ("refused" in advertised)
|
|
536
|
+
throw new Error(
|
|
537
|
+
`${protocol} document carries no readable advertisement (${advertised.code}): ${advertised.detail ?? ""}`,
|
|
538
|
+
);
|
|
539
|
+
|
|
537
540
|
return {
|
|
538
541
|
protocol,
|
|
539
542
|
advertisedAtrHash: ref.value as `0x${string}`,
|
|
540
|
-
legalContextUrl:
|
|
543
|
+
legalContextUrl: advertised.value.termsUrl,
|
|
541
544
|
};
|
|
542
545
|
}
|
|
543
546
|
|
|
544
|
-
/**
|
|
545
|
-
* The terms URL at the field the manifest DECLARES — or which of the three absences this is.
|
|
546
|
-
*
|
|
547
|
-
* `termsUrlField` is a plain dotted path on the manifest: it declares no container of its own, so it is read
|
|
548
|
-
* with `readAtPath` rather than through the reference carrier's container. A manifest that omits it (A2A, ACK,
|
|
549
|
-
* Visa TAP, Mastercard VI) is stating that its protocol has no room for one — a fact, not a gap.
|
|
550
|
-
*
|
|
551
|
-
* NOTHING AT THE DECLARED PATH IS TWO DIFFERENT FACTS, and which one it is turns on where the reference
|
|
552
|
-
* answered from. `termsUrlField` is declared once, beside the canonical `field`; a `readAlso` alias carries no
|
|
553
|
-
* terms-URL declaration of its own. So when the declared path is nested INSIDE the canonical field — x402's
|
|
554
|
-
* `extensions.legalContext.info.legalContextUrl` inside `extensions.legalContext.info` — and the reference
|
|
555
|
-
* answered from an alias instead, the manifest's declaration was scoped to a carrier this document did not
|
|
556
|
-
* use, and its emptiness says nothing about the document. When the declared path is a SIBLING of the canonical
|
|
557
|
-
* field (ACP's `metadata.legal_context_url`, MPP's `methodDetails.legalContextUrl`), it is reachable whichever
|
|
558
|
-
* carrier answered, and empty means empty.
|
|
559
|
-
*
|
|
560
|
-
* `answeredAt` is the path the reconciled reference was read from. `carrierSlots` puts the canonical field
|
|
561
|
-
* first and `integrityHits` preserves that order, so it differs from `manifest.field` exactly when the
|
|
562
|
-
* canonical carrier did not answer.
|
|
563
|
-
*/
|
|
564
|
-
function readTermsUrl(
|
|
565
|
-
protocol: ProtocolId,
|
|
566
|
-
doc: unknown,
|
|
567
|
-
manifest: PlacementManifest,
|
|
568
|
-
answeredAt: string,
|
|
569
|
-
): AdvertisedTermsUrl {
|
|
570
|
-
const field = manifest.termsUrlField;
|
|
571
|
-
if (field === undefined) return { kind: "no-field-declared" };
|
|
572
|
-
const raw = readAtPath(doc, field);
|
|
573
|
-
if (raw === undefined)
|
|
574
|
-
return answeredAt !== manifest.field &&
|
|
575
|
-
field.startsWith(`${manifest.field}.`)
|
|
576
|
-
? { kind: "undeclared-at-answering-carrier", field, answeredAt }
|
|
577
|
-
: { kind: "declared-field-empty", field };
|
|
578
|
-
if (typeof raw !== "string")
|
|
579
|
-
throw new Error(
|
|
580
|
-
`${protocol} ${field} is not a string: ${JSON.stringify(raw)}`,
|
|
581
|
-
);
|
|
582
|
-
if (!raw.startsWith("https://"))
|
|
583
|
-
throw new Error(`legalContextUrl must be HTTPS: ${raw}`);
|
|
584
|
-
return { kind: "read", url: raw };
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// ---------------------------------------------------------------------------------------------------------
|
|
588
|
-
// The universal gate parse
|
|
589
|
-
// ---------------------------------------------------------------------------------------------------------
|
|
590
|
-
|
|
591
|
-
/** A parser from one protocol's wire document to the one `GateProposal` every parser produces. */
|
|
592
547
|
export type ProposalParser = (
|
|
593
548
|
wire: unknown,
|
|
594
549
|
ctx: ProposalContext,
|