@daski/x402-scheme 0.1.0

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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/dist/binding.d.ts +37 -0
  4. package/dist/binding.d.ts.map +1 -0
  5. package/dist/binding.js +74 -0
  6. package/dist/binding.js.map +1 -0
  7. package/dist/canonical.d.ts +12 -0
  8. package/dist/canonical.d.ts.map +1 -0
  9. package/dist/canonical.js +53 -0
  10. package/dist/canonical.js.map +1 -0
  11. package/dist/eip712.d.ts +72 -0
  12. package/dist/eip712.d.ts.map +1 -0
  13. package/dist/eip712.js +61 -0
  14. package/dist/eip712.js.map +1 -0
  15. package/dist/errors.d.ts +34 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +32 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/extensions.d.ts +29 -0
  20. package/dist/extensions.d.ts.map +1 -0
  21. package/dist/extensions.js +65 -0
  22. package/dist/extensions.js.map +1 -0
  23. package/dist/index.d.ts +22 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +22 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/lifecycle.d.ts +177 -0
  28. package/dist/lifecycle.d.ts.map +1 -0
  29. package/dist/lifecycle.js +345 -0
  30. package/dist/lifecycle.js.map +1 -0
  31. package/dist/policy.d.ts +113 -0
  32. package/dist/policy.d.ts.map +1 -0
  33. package/dist/policy.js +357 -0
  34. package/dist/policy.js.map +1 -0
  35. package/dist/recipe.d.ts +40 -0
  36. package/dist/recipe.d.ts.map +1 -0
  37. package/dist/recipe.js +61 -0
  38. package/dist/recipe.js.map +1 -0
  39. package/dist/register.d.ts +36 -0
  40. package/dist/register.d.ts.map +1 -0
  41. package/dist/register.js +12 -0
  42. package/dist/register.js.map +1 -0
  43. package/dist/scheme.d.ts +92 -0
  44. package/dist/scheme.d.ts.map +1 -0
  45. package/dist/scheme.js +182 -0
  46. package/dist/scheme.js.map +1 -0
  47. package/dist/signRequest.d.ts +30 -0
  48. package/dist/signRequest.d.ts.map +1 -0
  49. package/dist/signRequest.js +83 -0
  50. package/dist/signRequest.js.map +1 -0
  51. package/dist/signer.d.ts +38 -0
  52. package/dist/signer.d.ts.map +1 -0
  53. package/dist/signer.js +12 -0
  54. package/dist/signer.js.map +1 -0
  55. package/package.json +53 -0
@@ -0,0 +1,113 @@
1
+ /**
2
+ * §4 — the policy validator.
3
+ *
4
+ * The one rule: the server proposes, the bridge validates against its *own*
5
+ * expectations, recomputes what it can derive, and only then signs. Every
6
+ * expectation in `PolicyConfig` is config- or catalog-sourced. Nothing in
7
+ * here may be read out of the challenge being validated — that would be
8
+ * asking the counterparty to grade its own homework.
9
+ */
10
+ import { type Address, type Hex } from "viem";
11
+ import { type OrderBinding } from "./binding.js";
12
+ import { type TransferAuthorization, type TypedDataRequest } from "./eip712.js";
13
+ /** USDC and every asset this rail settles in carry 6 decimals. */
14
+ export declare const USDC_DECIMALS = 6;
15
+ /** Defaults for §4.1 check 6. Config may tighten these, never loosen them. */
16
+ export declare const DEFAULT_MAX_AUTHORIZATION_LIFETIME_SECONDS = 900;
17
+ export declare const DEFAULT_MIN_AUTHORIZATION_LIFETIME_SECONDS = 15;
18
+ export declare const DEFAULT_MAX_BACKDATE_SECONDS = 3600;
19
+ /**
20
+ * The splitter an outcome pays into, resolved independently of the challenge:
21
+ * once from `daski_get_outcome`, once from `.well-known/daski-chain.json`.
22
+ * Both must agree and both must name the address being paid (§4.1 check 4).
23
+ */
24
+ export interface SplitterEvidence {
25
+ /** `splitterAddress` / `payTo` from `daski_get_outcome`. */
26
+ fromOutcome: Address;
27
+ /** The matching outcome entry in `.well-known/daski-chain.json`. */
28
+ fromChainManifest: Address;
29
+ }
30
+ /** Resolves splitter evidence for a provider+outcome pair. Implementations
31
+ * cache with a TTL; the validator itself holds no cache. */
32
+ export type SplitterResolver = (providerAgentId: string, outcomeId: string) => Promise<SplitterEvidence>;
33
+ /**
34
+ * The running spend ledger. `@daski/pay` backs this with the on-disk order
35
+ * store; a host app may back it with anything, but it must be real — the
36
+ * session cap is meaningless if the total always reads zero.
37
+ */
38
+ export interface SessionLedger {
39
+ /** Atomic units already authorized in this session. */
40
+ spentAtomic(): Promise<bigint> | bigint;
41
+ /** True when an order already exists for this payment identifier. */
42
+ hasOrderFor(paymentIdentifier: string): Promise<boolean> | boolean;
43
+ }
44
+ /**
45
+ * The host-supplied policy. No config, no signing: both packages refuse to
46
+ * construct a signer without one.
47
+ *
48
+ * The three caps are human-owned (§4.2). Nothing at runtime may raise them:
49
+ * `@daski/pay` reads them only from `~/.daski/config.json`, and flags may
50
+ * lower them for a single invocation but never raise them.
51
+ */
52
+ export interface PolicyConfig {
53
+ /** The address that must appear as `message.from`. */
54
+ payerAddress: Address;
55
+ /** Pinned chain id for the active profile (sandbox: 84532). */
56
+ chainId: number;
57
+ /** Pinned canonical token for the active profile (sandbox USDC). */
58
+ canonicalToken: Address;
59
+ /** Human-owned per-order ceiling, as a decimal USDC string. */
60
+ maxPerOrderUsdc: string;
61
+ /** Human-owned session ceiling, as a decimal USDC string. */
62
+ sessionCapUsdc: string;
63
+ /** Independent splitter evidence. Required for purchase authorizations. */
64
+ resolveSplitter: SplitterResolver;
65
+ /** Running spend and prior-order lookup. */
66
+ session: SessionLedger;
67
+ /** Tighter-than-default authorization window bounds, if desired. */
68
+ maxAuthorizationLifetimeSeconds?: number;
69
+ minAuthorizationLifetimeSeconds?: number;
70
+ maxBackdateSeconds?: number;
71
+ }
72
+ /** The purchase-specific facts the validator checks a proposal against. */
73
+ export interface PurchaseExpectations {
74
+ providerAgentId: string;
75
+ outcomeId: string;
76
+ /** `accepts[].amount` from the challenge, in atomic units. */
77
+ challengeAmountAtomic: bigint;
78
+ /** `accepts[].asset` from the challenge. */
79
+ challengeAsset: Address;
80
+ /** `accepts[].payTo` from the challenge. */
81
+ challengePayTo: Address;
82
+ /** `accepts[].network` from the challenge. */
83
+ challengeNetwork: string;
84
+ /** The quote a human actually approved, in atomic units. */
85
+ approvedQuoteAtomic: bigint;
86
+ /** The `payment-identifier` id this purchase carries, if any. */
87
+ paymentIdentifier?: string | undefined;
88
+ /** The parsed order binding, when the challenge carried one. */
89
+ binding?: OrderBinding | undefined;
90
+ /** Seconds since epoch; injectable so tests are not clock-dependent. */
91
+ nowSeconds?: number;
92
+ }
93
+ export interface ValidatedPurchase {
94
+ authorization: TransferAuthorization;
95
+ binding: OrderBinding | undefined;
96
+ amountAtomic: bigint;
97
+ /** The nonce the bridge recomputed. Equal to the proposal's, or we refused. */
98
+ recomputedNonce: Hex;
99
+ }
100
+ declare function atomic(usdc: string, field: string): bigint;
101
+ declare function formatUsdc(value: bigint): string;
102
+ /**
103
+ * Validates a proposed purchase authorization against every §4.1 assertion,
104
+ * then recomputes the recipe nonce and requires equality.
105
+ *
106
+ * Returns the authorization the caller may sign. Throws `PolicyRefusal` —
107
+ * never a repaired payload — on any failure.
108
+ */
109
+ export declare function validatePurchaseAuthorization(config: PolicyConfig, proposal: TypedDataRequest, expectations: PurchaseExpectations): Promise<ValidatedPurchase>;
110
+ /** Parses the binding out of a challenge's extensions, refusing open shapes. */
111
+ export declare function bindingFromExtensions(extensions: Record<string, unknown> | undefined): OrderBinding | undefined;
112
+ export { formatUsdc, atomic as parseUsdcToAtomic };
113
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
package/dist/policy.js ADDED
@@ -0,0 +1,357 @@
1
+ /**
2
+ * §4 — the policy validator.
3
+ *
4
+ * The one rule: the server proposes, the bridge validates against its *own*
5
+ * expectations, recomputes what it can derive, and only then signs. Every
6
+ * expectation in `PolicyConfig` is config- or catalog-sourced. Nothing in
7
+ * here may be read out of the challenge being validated — that would be
8
+ * asking the counterparty to grade its own homework.
9
+ */
10
+ import { getAddress, parseUnits } from "viem";
11
+ import { parseOrderBinding } from "./binding.js";
12
+ import { AUTHORIZATION_FIELDS, isClosedTransferWithAuthorizationTypes, TRANSFER_WITH_AUTHORIZATION_PRIMARY_TYPE, } from "./eip712.js";
13
+ import { refuse } from "./errors.js";
14
+ import { deriveBindingNonce } from "./recipe.js";
15
+ /** USDC and every asset this rail settles in carry 6 decimals. */
16
+ export const USDC_DECIMALS = 6;
17
+ /** Defaults for §4.1 check 6. Config may tighten these, never loosen them. */
18
+ export const DEFAULT_MAX_AUTHORIZATION_LIFETIME_SECONDS = 900;
19
+ export const DEFAULT_MIN_AUTHORIZATION_LIFETIME_SECONDS = 15;
20
+ export const DEFAULT_MAX_BACKDATE_SECONDS = 3600;
21
+ const DOC = "https://github.com/daski-io/buyer/blob/main/docs/policy.md";
22
+ function atomic(usdc, field) {
23
+ try {
24
+ return parseUnits(usdc, USDC_DECIMALS);
25
+ }
26
+ catch {
27
+ return refuse({
28
+ check: "amount-and-caps",
29
+ code: "DASKI_POLICY_CAP_UNPARSEABLE",
30
+ expected: `${field} to be a decimal USDC amount, e.g. "25.00"`,
31
+ actual: `${field}=${usdc}`,
32
+ remediation: `Fix ${field} in ~/.daski/config.json; see ${DOC}#caps`,
33
+ });
34
+ }
35
+ }
36
+ function formatUsdc(value) {
37
+ const negative = value < 0n;
38
+ const magnitude = negative ? -value : value;
39
+ const unit = 10n ** BigInt(USDC_DECIMALS);
40
+ const whole = magnitude / unit;
41
+ const fraction = (magnitude % unit).toString().padStart(USDC_DECIMALS, "0").replace(/0+$/, "");
42
+ return `${negative ? "-" : ""}${whole}${fraction ? `.${fraction}` : ""} USDC`;
43
+ }
44
+ /**
45
+ * Validates a proposed purchase authorization against every §4.1 assertion,
46
+ * then recomputes the recipe nonce and requires equality.
47
+ *
48
+ * Returns the authorization the caller may sign. Throws `PolicyRefusal` —
49
+ * never a repaired payload — on any failure.
50
+ */
51
+ export async function validatePurchaseAuthorization(config, proposal, expectations) {
52
+ const now = expectations.nowSeconds ?? Math.floor(Date.now() / 1_000);
53
+ // -- §4.1.1 chain and verifying contract are pinned by profile ------------
54
+ if (proposal.domain.chainId !== config.chainId) {
55
+ refuse({
56
+ check: "chain-pinning",
57
+ code: "DASKI_POLICY_CHAIN_MISMATCH",
58
+ expected: `chainId ${config.chainId}`,
59
+ actual: `chainId ${String(proposal.domain.chainId)}`,
60
+ remediation: "The challenge targets a different chain than the active profile. " +
61
+ `Switch profiles or refuse the purchase; see ${DOC}#chain-pinning`,
62
+ });
63
+ }
64
+ const verifyingContract = safeAddress(proposal.domain.verifyingContract, "domain.verifyingContract");
65
+ if (verifyingContract !== getAddress(config.canonicalToken)) {
66
+ refuse({
67
+ check: "chain-pinning",
68
+ code: "DASKI_POLICY_TOKEN_NOT_CANONICAL",
69
+ expected: `verifyingContract ${getAddress(config.canonicalToken)}`,
70
+ actual: `verifyingContract ${verifyingContract}`,
71
+ remediation: "Only the profile's canonical USDC contract may be signed against. " +
72
+ `See ${DOC}#chain-pinning`,
73
+ });
74
+ }
75
+ const challengeAsset = safeAddress(expectations.challengeAsset, "accepts[].asset");
76
+ if (challengeAsset !== getAddress(config.canonicalToken)) {
77
+ refuse({
78
+ check: "chain-pinning",
79
+ code: "DASKI_POLICY_ASSET_NOT_CANONICAL",
80
+ expected: `asset ${getAddress(config.canonicalToken)}`,
81
+ actual: `asset ${challengeAsset}`,
82
+ remediation: `Non-canonical assets are never signed; see ${DOC}#chain-pinning`,
83
+ });
84
+ }
85
+ if (expectations.challengeNetwork !== `eip155:${config.chainId}`) {
86
+ refuse({
87
+ check: "chain-pinning",
88
+ code: "DASKI_POLICY_NETWORK_MISMATCH",
89
+ expected: `network eip155:${config.chainId}`,
90
+ actual: `network ${expectations.challengeNetwork}`,
91
+ remediation: `See ${DOC}#chain-pinning`,
92
+ });
93
+ }
94
+ // -- §4.1.2 the closed 6-field type set, and nothing else -----------------
95
+ if (proposal.primaryType !== TRANSFER_WITH_AUTHORIZATION_PRIMARY_TYPE) {
96
+ refuse({
97
+ check: "typed-data-shape",
98
+ code: "DASKI_POLICY_PRIMARY_TYPE_MISMATCH",
99
+ expected: TRANSFER_WITH_AUTHORIZATION_PRIMARY_TYPE,
100
+ actual: String(proposal.primaryType),
101
+ remediation: "This bridge signs exactly one purchase type. Anything else must be " +
102
+ `refused; see ${DOC}#typed-data-shape`,
103
+ });
104
+ }
105
+ if (!isClosedTransferWithAuthorizationTypes(proposal.types)) {
106
+ refuse({
107
+ check: "typed-data-shape",
108
+ code: "DASKI_POLICY_TYPES_NOT_CLOSED",
109
+ expected: "the closed 6-field TransferWithAuthorization type set",
110
+ actual: `types=${JSON.stringify(proposal.types)}`,
111
+ remediation: "An altered or extended type set changes what the signature means. " +
112
+ `See ${DOC}#typed-data-shape`,
113
+ });
114
+ }
115
+ const messageKeys = Object.keys(proposal.message).sort();
116
+ if (messageKeys.join(",") !== [...AUTHORIZATION_FIELDS].sort().join(",")) {
117
+ refuse({
118
+ check: "typed-data-shape",
119
+ code: "DASKI_POLICY_MESSAGE_OPEN_SHAPE",
120
+ expected: `exactly [${[...AUTHORIZATION_FIELDS].sort().join(", ")}]`,
121
+ actual: `[${messageKeys.join(", ")}]`,
122
+ remediation: `See ${DOC}#typed-data-shape`,
123
+ });
124
+ }
125
+ // -- §4.1.3 the payer is our own configured address -----------------------
126
+ const from = safeAddress(proposal.message.from, "message.from");
127
+ if (from !== getAddress(config.payerAddress)) {
128
+ refuse({
129
+ check: "payer-match",
130
+ code: "DASKI_POLICY_PAYER_MISMATCH",
131
+ expected: `from ${getAddress(config.payerAddress)}`,
132
+ actual: `from ${from}`,
133
+ remediation: "The challenge names a different payer than the active signer. Run " +
134
+ `\`daski doctor --json\` to see the active address; see ${DOC}#payer`,
135
+ });
136
+ }
137
+ // -- §4.1.4 the recipient is an allowlisted splitter ----------------------
138
+ const to = safeAddress(proposal.message.to, "message.to");
139
+ const challengePayTo = safeAddress(expectations.challengePayTo, "accepts[].payTo");
140
+ if (to !== challengePayTo) {
141
+ refuse({
142
+ check: "splitter-allowlist",
143
+ code: "DASKI_POLICY_PAYTO_MISMATCH",
144
+ expected: `to ${challengePayTo} (the challenge's accepts[].payTo)`,
145
+ actual: `to ${to}`,
146
+ remediation: `See ${DOC}#splitter-allowlist`,
147
+ });
148
+ }
149
+ const evidence = await config.resolveSplitter(expectations.providerAgentId, expectations.outcomeId);
150
+ const fromOutcome = safeAddress(evidence.fromOutcome, "daski_get_outcome payTo");
151
+ const fromManifest = safeAddress(evidence.fromChainManifest, "daski-chain.json payTo");
152
+ if (fromOutcome !== fromManifest) {
153
+ refuse({
154
+ check: "splitter-allowlist",
155
+ code: "DASKI_POLICY_SPLITTER_EVIDENCE_DISAGREES",
156
+ expected: "daski_get_outcome and .well-known/daski-chain.json to name one splitter",
157
+ actual: `outcome=${fromOutcome} manifest=${fromManifest}`,
158
+ remediation: "Two independent sources disagree about who gets paid. Do not sign; " +
159
+ `report this to the gateway operator. See ${DOC}#splitter-allowlist`,
160
+ });
161
+ }
162
+ if (to !== fromOutcome) {
163
+ refuse({
164
+ check: "splitter-allowlist",
165
+ code: "DASKI_POLICY_SPLITTER_NOT_ALLOWLISTED",
166
+ expected: `to ${fromOutcome} for ${expectations.providerAgentId}/${expectations.outcomeId}`,
167
+ actual: `to ${to}`,
168
+ remediation: "The challenge pays an address the catalog does not list for this " +
169
+ `outcome. Do not sign; see ${DOC}#splitter-allowlist`,
170
+ });
171
+ }
172
+ // -- §4.1.5 amount matches the challenge, the approved quote, and the caps -
173
+ const value = safeUint(proposal.message.value, "message.value");
174
+ if (value !== expectations.challengeAmountAtomic) {
175
+ refuse({
176
+ check: "amount-and-caps",
177
+ code: "DASKI_POLICY_VALUE_MISMATCH",
178
+ expected: `value ${expectations.challengeAmountAtomic} (accepts[].amount)`,
179
+ actual: `value ${value}`,
180
+ remediation: `See ${DOC}#amount`,
181
+ });
182
+ }
183
+ if (value !== expectations.approvedQuoteAtomic) {
184
+ refuse({
185
+ check: "amount-and-caps",
186
+ code: "DASKI_POLICY_QUOTE_NOT_APPROVED",
187
+ expected: `value ${expectations.approvedQuoteAtomic} (${formatUsdc(expectations.approvedQuoteAtomic)}, the approved quote)`,
188
+ actual: `value ${value} (${formatUsdc(value)})`,
189
+ remediation: "The price moved between approval and signing. Re-run the purchase to " +
190
+ `approve the new quote; see ${DOC}#amount`,
191
+ });
192
+ }
193
+ const maxPerOrder = atomic(config.maxPerOrderUsdc, "maxPerOrderUsdc");
194
+ if (value > maxPerOrder) {
195
+ refuse({
196
+ check: "amount-and-caps",
197
+ code: "DASKI_POLICY_PER_ORDER_CAP_EXCEEDED",
198
+ expected: `at most ${formatUsdc(maxPerOrder)} per order`,
199
+ actual: formatUsdc(value),
200
+ remediation: "Caps are human-owned: raise `maxPerOrderUsdc` in ~/.daski/config.json " +
201
+ `by hand, or buy something cheaper. See ${DOC}#caps`,
202
+ });
203
+ }
204
+ const sessionCap = atomic(config.sessionCapUsdc, "sessionCapUsdc");
205
+ const spent = BigInt(await config.session.spentAtomic());
206
+ if (spent + value > sessionCap) {
207
+ refuse({
208
+ check: "amount-and-caps",
209
+ code: "DASKI_POLICY_SESSION_CAP_EXCEEDED",
210
+ expected: `session total at most ${formatUsdc(sessionCap)}`,
211
+ actual: `${formatUsdc(spent)} already authorized plus ${formatUsdc(value)}`,
212
+ remediation: "Caps are human-owned: raise `sessionCapUsdc` in ~/.daski/config.json " +
213
+ `by hand. See ${DOC}#caps`,
214
+ });
215
+ }
216
+ // -- §4.1.6 the authorization window is sane ------------------------------
217
+ const validAfter = safeUint(proposal.message.validAfter, "message.validAfter");
218
+ const validBefore = safeUint(proposal.message.validBefore, "message.validBefore");
219
+ const maxBackdate = BigInt(config.maxBackdateSeconds ?? DEFAULT_MAX_BACKDATE_SECONDS);
220
+ const maxLifetime = BigInt(config.maxAuthorizationLifetimeSeconds ?? DEFAULT_MAX_AUTHORIZATION_LIFETIME_SECONDS);
221
+ const minLifetime = BigInt(config.minAuthorizationLifetimeSeconds ?? DEFAULT_MIN_AUTHORIZATION_LIFETIME_SECONDS);
222
+ const nowBig = BigInt(now);
223
+ if (validAfter !== 0n && (validAfter < nowBig - maxBackdate || validAfter > nowBig)) {
224
+ refuse({
225
+ check: "authorization-window",
226
+ code: "DASKI_POLICY_VALID_AFTER_OUT_OF_RANGE",
227
+ expected: `validAfter to be 0 or within [${nowBig - maxBackdate}, ${nowBig}]`,
228
+ actual: `validAfter ${validAfter}`,
229
+ remediation: "A back- or future-dated authorization is not one this bridge will " +
230
+ `sign; request a fresh challenge. See ${DOC}#window`,
231
+ });
232
+ }
233
+ const lifetime = validBefore - nowBig;
234
+ if (lifetime > maxLifetime) {
235
+ refuse({
236
+ check: "authorization-window",
237
+ code: "DASKI_POLICY_WINDOW_TOO_LONG",
238
+ expected: `validBefore at most ${maxLifetime}s out`,
239
+ actual: `${lifetime}s out`,
240
+ remediation: "A long-lived authorization is a long-lived liability; request a " +
241
+ `shorter challenge. See ${DOC}#window`,
242
+ });
243
+ }
244
+ if (lifetime <= minLifetime) {
245
+ refuse({
246
+ check: "authorization-window",
247
+ code: "DASKI_POLICY_WINDOW_TOO_SHORT",
248
+ expected: `validBefore more than ${minLifetime}s out`,
249
+ actual: `${lifetime}s out`,
250
+ remediation: "This challenge expires too soon to settle safely; request a fresh " +
251
+ `one. See ${DOC}#window`,
252
+ });
253
+ }
254
+ // -- §4.1.7 the payment identifier is ours, and unspent -------------------
255
+ if (expectations.paymentIdentifier !== undefined) {
256
+ if (await config.session.hasOrderFor(expectations.paymentIdentifier)) {
257
+ refuse({
258
+ check: "payment-identifier",
259
+ code: "DASKI_POLICY_IDENTIFIER_ALREADY_ORDERED",
260
+ expected: "an unused payment identifier",
261
+ actual: `identifier ${expectations.paymentIdentifier} already has a stored order`,
262
+ remediation: "An order already exists for this intent. Reconcile before re-signing: " +
263
+ `run \`daski order status <handle>\`. See ${DOC}#reconciliation`,
264
+ });
265
+ }
266
+ }
267
+ // -- §4.3 recompute the recipe nonce and require equality -----------------
268
+ const nonce = safeHex32(proposal.message.nonce, "message.nonce");
269
+ const binding = expectations.binding;
270
+ let recomputedNonce = nonce;
271
+ if (binding) {
272
+ if (BigInt(binding.expiresAt) < validBefore) {
273
+ refuse({
274
+ check: "authorization-window",
275
+ code: "DASKI_POLICY_WINDOW_OUTLIVES_BINDING",
276
+ expected: `validBefore at most the binding's expiresAt ${binding.expiresAt}`,
277
+ actual: `validBefore ${validBefore}`,
278
+ remediation: "The authorization would outlive the deal it is bound to; request a " +
279
+ `fresh challenge. See ${DOC}#window`,
280
+ });
281
+ }
282
+ recomputedNonce = deriveBindingNonce(binding, {
283
+ chainId: config.chainId,
284
+ canonicalToken: getAddress(config.canonicalToken),
285
+ payer: from,
286
+ splitter: to,
287
+ grossAmount: value,
288
+ });
289
+ if (recomputedNonce.toLowerCase() !== nonce.toLowerCase()) {
290
+ refuse({
291
+ check: "recipe-recompute",
292
+ code: "DASKI_POLICY_RECIPE_NONCE_MISMATCH",
293
+ expected: `nonce ${recomputedNonce} (recomputed from the ${binding.profile} binding)`,
294
+ actual: `nonce ${nonce}`,
295
+ remediation: "The proposed nonce does not commit to the deal we were shown. This " +
296
+ "is exactly the case blind signing would miss. Do not retry; report " +
297
+ `it to the gateway operator. See ${DOC}#recipe`,
298
+ });
299
+ }
300
+ }
301
+ return {
302
+ authorization: {
303
+ from,
304
+ to,
305
+ value: value.toString(),
306
+ validAfter: validAfter.toString(),
307
+ validBefore: validBefore.toString(),
308
+ nonce,
309
+ },
310
+ binding,
311
+ amountAtomic: value,
312
+ recomputedNonce,
313
+ };
314
+ }
315
+ /** Parses the binding out of a challenge's extensions, refusing open shapes. */
316
+ export function bindingFromExtensions(extensions) {
317
+ return parseOrderBinding(extensions?.["daski-order-binding"]);
318
+ }
319
+ function safeAddress(value, field) {
320
+ if (typeof value !== "string" || !/^0x[0-9a-fA-F]{40}$/.test(value)) {
321
+ refuse({
322
+ check: "typed-data-shape",
323
+ code: "DASKI_POLICY_MALFORMED_ADDRESS",
324
+ expected: `${field} to be a 20-byte hex address`,
325
+ actual: `${field}=${String(value)}`,
326
+ remediation: `Request a fresh challenge; see ${DOC}`,
327
+ });
328
+ }
329
+ return getAddress(value);
330
+ }
331
+ function safeUint(value, field) {
332
+ const raw = typeof value === "bigint" ? value.toString() : String(value);
333
+ if (!/^\d+$/.test(raw)) {
334
+ refuse({
335
+ check: "typed-data-shape",
336
+ code: "DASKI_POLICY_MALFORMED_UINT",
337
+ expected: `${field} to be a non-negative integer`,
338
+ actual: `${field}=${raw}`,
339
+ remediation: `Request a fresh challenge; see ${DOC}`,
340
+ });
341
+ }
342
+ return BigInt(raw);
343
+ }
344
+ function safeHex32(value, field) {
345
+ if (typeof value !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(value)) {
346
+ refuse({
347
+ check: "typed-data-shape",
348
+ code: "DASKI_POLICY_MALFORMED_BYTES32",
349
+ expected: `${field} to be a 32-byte hex string`,
350
+ actual: `${field}=${String(value)}`,
351
+ remediation: `Request a fresh challenge; see ${DOC}`,
352
+ });
353
+ }
354
+ return value;
355
+ }
356
+ export { formatUsdc, atomic as parseUsdcToAtomic };
357
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * §4.3 — local recipe recomputation, the verify-and-sign tier.
3
+ *
4
+ * The nonce of a Daski EIP-3009 authorization is not random: it is a
5
+ * commitment to the whole deal. Recomputing it locally is what lets the
6
+ * bridge sign a server-proposed authorization without trusting the server —
7
+ * if our nonce and theirs disagree, the deal we were shown is not the deal
8
+ * we would be signing, and we refuse.
9
+ *
10
+ * These two functions mirror the gateway's `recipeNonce` / `recipeNonceV2`
11
+ * byte for byte. Changing either is a protocol break, not a refactor.
12
+ */
13
+ import { type Address, type Hex } from "viem";
14
+ import type { OrderBinding, OrderBindingV1, OrderBindingV2 } from "./binding.js";
15
+ /** `keccak256("DaskiStandardExactOrderV1")` — the v1 recipe domain separator. */
16
+ export declare const RECIPE_NONCE_DOMAIN_V1: Hex;
17
+ /** `keccak256("DaskiStandardExactOrderV2")` — the v2 recipe domain separator. */
18
+ export declare const RECIPE_NONCE_DOMAIN_V2: Hex;
19
+ /**
20
+ * The five payment facts the recipe binds that do not come from the binding
21
+ * extension. Each is independently known to the bridge: the chain and token
22
+ * are pinned by profile, the payer is our own signer, and the splitter and
23
+ * amount are what the policy validator has already allowlisted and capped.
24
+ */
25
+ export interface RecipePaymentFacts {
26
+ chainId: number;
27
+ canonicalToken: Address;
28
+ payer: Address;
29
+ splitter: Address;
30
+ grossAmount: bigint;
31
+ }
32
+ export type RecipeNonceV1Input = RecipePaymentFacts & Pick<OrderBindingV1, "listingManifestHash" | "providerOfferHash" | "quoteHash" | "canonicalRequestHash" | "orderNonce">;
33
+ export type RecipeNonceV2Input = RecipePaymentFacts & Pick<OrderBindingV2, "runtimeCommitmentHash" | "providerIntentHash" | "quoteHash" | "canonicalRequestHash" | "orderNonce">;
34
+ /** `recipeNonce` — the v1 layout, for `recipe-bound-v1` listings. */
35
+ export declare function recipeNonce(input: RecipeNonceV1Input): Hex;
36
+ /** `recipeNonceV2` — the catalog-driven layout, for `recipe-bound-v2` listings. */
37
+ export declare function recipeNonceV2(input: RecipeNonceV2Input): Hex;
38
+ /** Recomputes the authorization nonce a binding commits to, at either version. */
39
+ export declare function deriveBindingNonce(binding: OrderBinding, facts: RecipePaymentFacts): Hex;
40
+ //# sourceMappingURL=recipe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipe.d.ts","sourceRoot":"","sources":["../src/recipe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAA+C,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAC3F,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEjF,iFAAiF;AACjF,eAAO,MAAM,sBAAsB,EAAE,GAAyD,CAAC;AAC/F,iFAAiF;AACjF,eAAO,MAAM,sBAAsB,EAAE,GAAyD,CAAC;AAE/F;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAyCD,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,GACjD,IAAI,CAAC,cAAc,EAAE,qBAAqB,GAAG,mBAAmB,GAAG,WAAW,GAC1E,sBAAsB,GAAG,YAAY,CAAC,CAAC;AAE7C,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,GACjD,IAAI,CAAC,cAAc,EAAE,uBAAuB,GAAG,oBAAoB,GAAG,WAAW,GAC7E,sBAAsB,GAAG,YAAY,CAAC,CAAC;AAE7C,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,KAAK,EAAE,kBAAkB,GAAG,GAAG,CAU1D;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,GAAG,CAU5D;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,kBAAkB,GAAG,GAAG,CAIxF"}
package/dist/recipe.js ADDED
@@ -0,0 +1,61 @@
1
+ /**
2
+ * §4.3 — local recipe recomputation, the verify-and-sign tier.
3
+ *
4
+ * The nonce of a Daski EIP-3009 authorization is not random: it is a
5
+ * commitment to the whole deal. Recomputing it locally is what lets the
6
+ * bridge sign a server-proposed authorization without trusting the server —
7
+ * if our nonce and theirs disagree, the deal we were shown is not the deal
8
+ * we would be signing, and we refuse.
9
+ *
10
+ * These two functions mirror the gateway's `recipeNonce` / `recipeNonceV2`
11
+ * byte for byte. Changing either is a protocol break, not a refactor.
12
+ */
13
+ import { encodeAbiParameters, keccak256, stringToHex } from "viem";
14
+ /** `keccak256("DaskiStandardExactOrderV1")` — the v1 recipe domain separator. */
15
+ export const RECIPE_NONCE_DOMAIN_V1 = keccak256(stringToHex("DaskiStandardExactOrderV1"));
16
+ /** `keccak256("DaskiStandardExactOrderV2")` — the v2 recipe domain separator. */
17
+ export const RECIPE_NONCE_DOMAIN_V2 = keccak256(stringToHex("DaskiStandardExactOrderV2"));
18
+ /** The eleven-slot ABI layout shared by both recipe versions. */
19
+ const RECIPE_ABI = [
20
+ { type: "bytes32" }, // domain separator
21
+ { type: "uint256" }, // chainId
22
+ { type: "address" }, // canonicalToken
23
+ { type: "address" }, // payer
24
+ { type: "address" }, // splitter
25
+ { type: "uint256" }, // grossAmount
26
+ { type: "bytes32" }, // deal slot 1: runtimeCommitmentHash / listingManifestHash
27
+ { type: "bytes32" }, // deal slot 2: providerIntentHash / providerOfferHash
28
+ { type: "bytes32" }, // quoteHash
29
+ { type: "bytes32" }, // canonicalRequestHash
30
+ { type: "bytes32" }, // orderNonce
31
+ ];
32
+ function encodeRecipe(domain, facts, dealSlot1, dealSlot2, quoteHash, canonicalRequestHash, orderNonce) {
33
+ return keccak256(encodeAbiParameters(RECIPE_ABI, [
34
+ domain,
35
+ BigInt(facts.chainId),
36
+ facts.canonicalToken,
37
+ facts.payer,
38
+ facts.splitter,
39
+ facts.grossAmount,
40
+ dealSlot1,
41
+ dealSlot2,
42
+ quoteHash,
43
+ canonicalRequestHash,
44
+ orderNonce,
45
+ ]));
46
+ }
47
+ /** `recipeNonce` — the v1 layout, for `recipe-bound-v1` listings. */
48
+ export function recipeNonce(input) {
49
+ return encodeRecipe(RECIPE_NONCE_DOMAIN_V1, input, input.listingManifestHash, input.providerOfferHash, input.quoteHash, input.canonicalRequestHash, input.orderNonce);
50
+ }
51
+ /** `recipeNonceV2` — the catalog-driven layout, for `recipe-bound-v2` listings. */
52
+ export function recipeNonceV2(input) {
53
+ return encodeRecipe(RECIPE_NONCE_DOMAIN_V2, input, input.runtimeCommitmentHash, input.providerIntentHash, input.quoteHash, input.canonicalRequestHash, input.orderNonce);
54
+ }
55
+ /** Recomputes the authorization nonce a binding commits to, at either version. */
56
+ export function deriveBindingNonce(binding, facts) {
57
+ return binding.profile === "recipe-bound-v2"
58
+ ? recipeNonceV2({ ...facts, ...binding })
59
+ : recipeNonce({ ...facts, ...binding });
60
+ }
61
+ //# sourceMappingURL=recipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipe.js","sourceRoot":"","sources":["../src/recipe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,WAAW,EAA0B,MAAM,MAAM,CAAC;AAG3F,iFAAiF;AACjF,MAAM,CAAC,MAAM,sBAAsB,GAAQ,SAAS,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC,CAAC;AAC/F,iFAAiF;AACjF,MAAM,CAAC,MAAM,sBAAsB,GAAQ,SAAS,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC,CAAC;AAgB/F,iEAAiE;AACjE,MAAM,UAAU,GAAG;IACjB,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,mBAAmB;IACxC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,UAAU;IAC/B,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,iBAAiB;IACtC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ;IAC7B,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,WAAW;IAChC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,cAAc;IACnC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,2DAA2D;IAChF,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,sDAAsD;IAC3E,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,YAAY;IACjC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,uBAAuB;IAC5C,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,aAAa;CAC1B,CAAC;AAEX,SAAS,YAAY,CACnB,MAAW,EACX,KAAyB,EACzB,SAAc,EACd,SAAc,EACd,SAAc,EACd,oBAAyB,EACzB,UAAe;IAEf,OAAO,SAAS,CAAC,mBAAmB,CAAC,UAAU,EAAE;QAC/C,MAAM;QACN,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;QACrB,KAAK,CAAC,cAAc;QACpB,KAAK,CAAC,KAAK;QACX,KAAK,CAAC,QAAQ;QACd,KAAK,CAAC,WAAW;QACjB,SAAS;QACT,SAAS;QACT,SAAS;QACT,oBAAoB;QACpB,UAAU;KACX,CAAC,CAAC,CAAC;AACN,CAAC;AAUD,qEAAqE;AACrE,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,OAAO,YAAY,CACjB,sBAAsB,EACtB,KAAK,EACL,KAAK,CAAC,mBAAmB,EACzB,KAAK,CAAC,iBAAiB,EACvB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,oBAAoB,EAC1B,KAAK,CAAC,UAAU,CACjB,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,KAAyB;IACrD,OAAO,YAAY,CACjB,sBAAsB,EACtB,KAAK,EACL,KAAK,CAAC,qBAAqB,EAC3B,KAAK,CAAC,kBAAkB,EACxB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,oBAAoB,EAC1B,KAAK,CAAC,UAAU,CACjB,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,kBAAkB,CAAC,OAAqB,EAAE,KAAyB;IACjF,OAAO,OAAO,CAAC,OAAO,KAAK,iBAAiB;QAC1C,CAAC,CAAC,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC;QACzC,CAAC,CAAC,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Registration helper.
3
+ *
4
+ * `x402Client.register(network, client)` maps one network to one handler, so
5
+ * registering the composite for a network is exactly how the wrap takes
6
+ * effect: Daski challenges take the validating path, everything else reaches
7
+ * the stock handler through the composite unchanged. We never register a
8
+ * second `exact` handler alongside the stock one, and we never rename the
9
+ * scheme.
10
+ */
11
+ import type { Address } from "viem";
12
+ import { DaskiExactEvmScheme, type SchemeNetworkClientLike } from "./scheme.js";
13
+ import type { PolicyConfig } from "./policy.js";
14
+ import type { PurchaseContextResolver } from "./scheme.js";
15
+ import type { SignerAdapter } from "./signer.js";
16
+ /** Minimal structural view of the host's `x402Client`. */
17
+ export interface X402ClientLike {
18
+ register(network: string, client: SchemeNetworkClientLike): unknown;
19
+ }
20
+ export interface RegisterOptions {
21
+ /** CAIP-2 network, e.g. `eip155:84532`. */
22
+ network: string;
23
+ signer: SignerAdapter;
24
+ payerAddress: Address;
25
+ policy: PolicyConfig;
26
+ /** The stock `ExactEvmScheme` instance to wrap. */
27
+ stock: SchemeNetworkClientLike;
28
+ resolvePurchaseContext: PurchaseContextResolver;
29
+ now?: () => number;
30
+ }
31
+ /**
32
+ * Wraps `stock` in the Daski composite and registers it for one network.
33
+ * Returns the composite so the caller can inspect or reuse it.
34
+ */
35
+ export declare function registerDaskiExactEvmScheme(client: X402ClientLike, options: RegisterOptions): DaskiExactEvmScheme;
36
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAmC,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACjH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,0DAA0D;AAC1D,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC;CACrE;AAED,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,YAAY,CAAC;IACrB,mDAAmD;IACnD,KAAK,EAAE,uBAAuB,CAAC;IAC/B,sBAAsB,EAAE,uBAAuB,CAAC;IAChD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,eAAe,GACvB,mBAAmB,CAKrB"}