@reinconsole/mock-rails 0.1.0 → 0.1.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/README.md +1 -1
- package/dist/index.d.ts +178 -7
- package/dist/index.js +140 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The simulated payment world for **[Rein](https://github.com/bugiiiii11/rein)** — a fully offline twin of the real [x402](https://www.x402.org) rails. Try the whole guard loop — budgets, caps, kill switch, shadow-spend detection — with no accounts, no chain, no funds.
|
|
4
4
|
|
|
5
|
-
> **Status: v0.1 — early open-source infrastructure.** APIs may change before 1.0. See it running (the live console world runs on these rails): [Rein console](https://reinconsole
|
|
5
|
+
> **Status: v0.1 — early open-source infrastructure.** APIs may change before 1.0. See it running (the live console world runs on these rails): [Rein console](https://app.reinconsole.com).
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
package/dist/index.d.ts
CHANGED
|
@@ -132,8 +132,169 @@ declare const MockPaymentHeader: z.ZodObject<{
|
|
|
132
132
|
};
|
|
133
133
|
}>;
|
|
134
134
|
type MockPaymentHeader = z.infer<typeof MockPaymentHeader>;
|
|
135
|
+
/**
|
|
136
|
+
* The v2 envelope (PAYMENT-SIGNATURE header): scheme/network live inside
|
|
137
|
+
* `accepted` — the requirement the payer chose — around the SAME scheme
|
|
138
|
+
* payload. `.passthrough()` keeps resource/extensions intact.
|
|
139
|
+
*/
|
|
140
|
+
declare const MockPaymentHeaderV2: z.ZodObject<{
|
|
141
|
+
x402Version: z.ZodLiteral<2>;
|
|
142
|
+
accepted: z.ZodObject<{
|
|
143
|
+
scheme: z.ZodString;
|
|
144
|
+
network: z.ZodString;
|
|
145
|
+
amount: z.ZodString;
|
|
146
|
+
asset: z.ZodString;
|
|
147
|
+
payTo: z.ZodString;
|
|
148
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
149
|
+
scheme: z.ZodString;
|
|
150
|
+
network: z.ZodString;
|
|
151
|
+
amount: z.ZodString;
|
|
152
|
+
asset: z.ZodString;
|
|
153
|
+
payTo: z.ZodString;
|
|
154
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
155
|
+
scheme: z.ZodString;
|
|
156
|
+
network: z.ZodString;
|
|
157
|
+
amount: z.ZodString;
|
|
158
|
+
asset: z.ZodString;
|
|
159
|
+
payTo: z.ZodString;
|
|
160
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
161
|
+
payload: z.ZodObject<{
|
|
162
|
+
from: z.ZodString;
|
|
163
|
+
to: z.ZodString;
|
|
164
|
+
/** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */
|
|
165
|
+
value: z.ZodString;
|
|
166
|
+
asset: z.ZodString;
|
|
167
|
+
/**
|
|
168
|
+
* Rein linkage: the guard's payer stamps the intent id here, the facilitator
|
|
169
|
+
* memos it onto the ledger entry, and the indexer reconciles exactly. A real
|
|
170
|
+
* x402 transfer authorization carries a nonce that serves the same role.
|
|
171
|
+
*/
|
|
172
|
+
intentId: z.ZodOptional<z.ZodString>;
|
|
173
|
+
nonce: z.ZodOptional<z.ZodString>;
|
|
174
|
+
}, "strip", z.ZodTypeAny, {
|
|
175
|
+
from: string;
|
|
176
|
+
to: string;
|
|
177
|
+
value: string;
|
|
178
|
+
asset: string;
|
|
179
|
+
intentId?: string | undefined;
|
|
180
|
+
nonce?: string | undefined;
|
|
181
|
+
}, {
|
|
182
|
+
from: string;
|
|
183
|
+
to: string;
|
|
184
|
+
value: string;
|
|
185
|
+
asset: string;
|
|
186
|
+
intentId?: string | undefined;
|
|
187
|
+
nonce?: string | undefined;
|
|
188
|
+
}>;
|
|
189
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
190
|
+
x402Version: z.ZodLiteral<2>;
|
|
191
|
+
accepted: z.ZodObject<{
|
|
192
|
+
scheme: z.ZodString;
|
|
193
|
+
network: z.ZodString;
|
|
194
|
+
amount: z.ZodString;
|
|
195
|
+
asset: z.ZodString;
|
|
196
|
+
payTo: z.ZodString;
|
|
197
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
198
|
+
scheme: z.ZodString;
|
|
199
|
+
network: z.ZodString;
|
|
200
|
+
amount: z.ZodString;
|
|
201
|
+
asset: z.ZodString;
|
|
202
|
+
payTo: z.ZodString;
|
|
203
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
204
|
+
scheme: z.ZodString;
|
|
205
|
+
network: z.ZodString;
|
|
206
|
+
amount: z.ZodString;
|
|
207
|
+
asset: z.ZodString;
|
|
208
|
+
payTo: z.ZodString;
|
|
209
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
210
|
+
payload: z.ZodObject<{
|
|
211
|
+
from: z.ZodString;
|
|
212
|
+
to: z.ZodString;
|
|
213
|
+
/** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */
|
|
214
|
+
value: z.ZodString;
|
|
215
|
+
asset: z.ZodString;
|
|
216
|
+
/**
|
|
217
|
+
* Rein linkage: the guard's payer stamps the intent id here, the facilitator
|
|
218
|
+
* memos it onto the ledger entry, and the indexer reconciles exactly. A real
|
|
219
|
+
* x402 transfer authorization carries a nonce that serves the same role.
|
|
220
|
+
*/
|
|
221
|
+
intentId: z.ZodOptional<z.ZodString>;
|
|
222
|
+
nonce: z.ZodOptional<z.ZodString>;
|
|
223
|
+
}, "strip", z.ZodTypeAny, {
|
|
224
|
+
from: string;
|
|
225
|
+
to: string;
|
|
226
|
+
value: string;
|
|
227
|
+
asset: string;
|
|
228
|
+
intentId?: string | undefined;
|
|
229
|
+
nonce?: string | undefined;
|
|
230
|
+
}, {
|
|
231
|
+
from: string;
|
|
232
|
+
to: string;
|
|
233
|
+
value: string;
|
|
234
|
+
asset: string;
|
|
235
|
+
intentId?: string | undefined;
|
|
236
|
+
nonce?: string | undefined;
|
|
237
|
+
}>;
|
|
238
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
239
|
+
x402Version: z.ZodLiteral<2>;
|
|
240
|
+
accepted: z.ZodObject<{
|
|
241
|
+
scheme: z.ZodString;
|
|
242
|
+
network: z.ZodString;
|
|
243
|
+
amount: z.ZodString;
|
|
244
|
+
asset: z.ZodString;
|
|
245
|
+
payTo: z.ZodString;
|
|
246
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
247
|
+
scheme: z.ZodString;
|
|
248
|
+
network: z.ZodString;
|
|
249
|
+
amount: z.ZodString;
|
|
250
|
+
asset: z.ZodString;
|
|
251
|
+
payTo: z.ZodString;
|
|
252
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
253
|
+
scheme: z.ZodString;
|
|
254
|
+
network: z.ZodString;
|
|
255
|
+
amount: z.ZodString;
|
|
256
|
+
asset: z.ZodString;
|
|
257
|
+
payTo: z.ZodString;
|
|
258
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
259
|
+
payload: z.ZodObject<{
|
|
260
|
+
from: z.ZodString;
|
|
261
|
+
to: z.ZodString;
|
|
262
|
+
/** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */
|
|
263
|
+
value: z.ZodString;
|
|
264
|
+
asset: z.ZodString;
|
|
265
|
+
/**
|
|
266
|
+
* Rein linkage: the guard's payer stamps the intent id here, the facilitator
|
|
267
|
+
* memos it onto the ledger entry, and the indexer reconciles exactly. A real
|
|
268
|
+
* x402 transfer authorization carries a nonce that serves the same role.
|
|
269
|
+
*/
|
|
270
|
+
intentId: z.ZodOptional<z.ZodString>;
|
|
271
|
+
nonce: z.ZodOptional<z.ZodString>;
|
|
272
|
+
}, "strip", z.ZodTypeAny, {
|
|
273
|
+
from: string;
|
|
274
|
+
to: string;
|
|
275
|
+
value: string;
|
|
276
|
+
asset: string;
|
|
277
|
+
intentId?: string | undefined;
|
|
278
|
+
nonce?: string | undefined;
|
|
279
|
+
}, {
|
|
280
|
+
from: string;
|
|
281
|
+
to: string;
|
|
282
|
+
value: string;
|
|
283
|
+
asset: string;
|
|
284
|
+
intentId?: string | undefined;
|
|
285
|
+
nonce?: string | undefined;
|
|
286
|
+
}>;
|
|
287
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
288
|
+
type MockPaymentHeaderV2 = z.infer<typeof MockPaymentHeaderV2>;
|
|
289
|
+
/** A payment as the facilitator sees it, whichever dialect it arrived in. */
|
|
290
|
+
interface DecodedPayment {
|
|
291
|
+
version: 1 | 2;
|
|
292
|
+
scheme: string;
|
|
293
|
+
network: string;
|
|
294
|
+
payload: MockExactPayload;
|
|
295
|
+
}
|
|
135
296
|
declare function encodePaymentHeader(header: MockPaymentHeader): string;
|
|
136
|
-
declare function decodePaymentHeader(raw: string):
|
|
297
|
+
declare function decodePaymentHeader(raw: string): DecodedPayment;
|
|
137
298
|
/** What the facilitator returns on settle; the vendor base64s it into X-PAYMENT-RESPONSE. */
|
|
138
299
|
declare const SettlementResponse: z.ZodObject<{
|
|
139
300
|
success: z.ZodBoolean;
|
|
@@ -188,8 +349,9 @@ declare class MockFacilitator {
|
|
|
188
349
|
* the plug-in point the real x402 signer replaces.
|
|
189
350
|
*/
|
|
190
351
|
payerFor(fromAddress: string): Payer;
|
|
191
|
-
/** Verify
|
|
192
|
-
|
|
352
|
+
/** Verify a payment header (either dialect) against the requirement it
|
|
353
|
+
* claims to satisfy. */
|
|
354
|
+
verify(paymentHeader: string, requirement: PaymentRequirement): DecodedPayment;
|
|
193
355
|
/**
|
|
194
356
|
* Verify, then settle: write the transfer on the mock chain and return the
|
|
195
357
|
* settlement response the vendor relays via X-PAYMENT-RESPONSE.
|
|
@@ -263,6 +425,15 @@ interface MockVendorOptions {
|
|
|
263
425
|
scheme?: string;
|
|
264
426
|
/** JSON body served once payment settles. */
|
|
265
427
|
body?: unknown;
|
|
428
|
+
/**
|
|
429
|
+
* Which x402 dialect the vendor's 402s advertise. 'v1' (default) is the
|
|
430
|
+
* classic JSON body; 'dual' adds the v2 PAYMENT-REQUIRED header beside it;
|
|
431
|
+
* 'v2' advertises ONLY the header (the body is not x402) — a strict v2
|
|
432
|
+
* vendor for proving clients need no v1 fallback. Payments are ACCEPTED in
|
|
433
|
+
* both dialects (PAYMENT-SIGNATURE or X-PAYMENT) regardless of this option,
|
|
434
|
+
* mirroring the gate.
|
|
435
|
+
*/
|
|
436
|
+
advertise?: 'v1' | 'dual' | 'v2';
|
|
266
437
|
}
|
|
267
438
|
interface VendorCall {
|
|
268
439
|
url: string;
|
|
@@ -278,10 +449,10 @@ interface MockVendor {
|
|
|
278
449
|
}
|
|
279
450
|
/**
|
|
280
451
|
* An in-process x402 vendor wired to the mock facilitator: quotes a 402 with
|
|
281
|
-
* payment requirements until the request carries
|
|
452
|
+
* payment requirements until the request carries a payment, then settles
|
|
282
453
|
* through the facilitator (writing the transfer on the mock ledger) and serves
|
|
283
|
-
* the content with the settlement in
|
|
284
|
-
* mock rails — guard pays it, indexer watches the ledger behind it.
|
|
454
|
+
* the content with the settlement in the response headers. The third leg of
|
|
455
|
+
* the mock rails — guard pays it, indexer watches the ledger behind it.
|
|
285
456
|
*/
|
|
286
457
|
declare function createMockVendor(options: MockVendorOptions): MockVendor;
|
|
287
458
|
|
|
@@ -292,4 +463,4 @@ declare class FacilitatorError extends Error {
|
|
|
292
463
|
constructor(code: FacilitatorErrorCode, message: string);
|
|
293
464
|
}
|
|
294
465
|
|
|
295
|
-
export { type EngineEvents, FacilitatorError, type FacilitatorErrorCode, type LedgerEntry, MockExactPayload, MockFacilitator, type MockFacilitatorOptions, MockIndexer, type MockIndexerOptions, MockLedger, MockPaymentHeader, type MockVendor, type MockVendorOptions, type SettleResult, SettlementResponse, type ShadowSpend, type TransferInput, type VendorCall, createMockVendor, decodePaymentHeader, encodePaymentHeader, encodeSettlementHeader };
|
|
466
|
+
export { type DecodedPayment, type EngineEvents, FacilitatorError, type FacilitatorErrorCode, type LedgerEntry, MockExactPayload, MockFacilitator, type MockFacilitatorOptions, MockIndexer, type MockIndexerOptions, MockLedger, MockPaymentHeader, MockPaymentHeaderV2, type MockVendor, type MockVendorOptions, type SettleResult, SettlementResponse, type ShadowSpend, type TransferInput, type VendorCall, createMockVendor, decodePaymentHeader, encodePaymentHeader, encodeSettlementHeader };
|
package/dist/index.js
CHANGED
|
@@ -417,6 +417,81 @@ function requirementDecimals(requirement) {
|
|
|
417
417
|
const decimals = requirement.extra?.["decimals"];
|
|
418
418
|
return typeof decimals === "number" && Number.isInteger(decimals) && decimals >= 0 ? decimals : 6;
|
|
419
419
|
}
|
|
420
|
+
var CAIP2_ALIASES = {
|
|
421
|
+
base: "eip155:8453",
|
|
422
|
+
"base-sepolia": "eip155:84532",
|
|
423
|
+
polygon: "eip155:137",
|
|
424
|
+
"polygon-amoy": "eip155:80002",
|
|
425
|
+
bnb: "eip155:56",
|
|
426
|
+
bsc: "eip155:56",
|
|
427
|
+
solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
428
|
+
"solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
|
|
429
|
+
};
|
|
430
|
+
function caip2Of(network) {
|
|
431
|
+
const key = network.toLowerCase();
|
|
432
|
+
return CAIP2_ALIASES[key] ?? key;
|
|
433
|
+
}
|
|
434
|
+
function sameNetwork(a, b) {
|
|
435
|
+
return caip2Of(a) === caip2Of(b);
|
|
436
|
+
}
|
|
437
|
+
var PaymentRequirementsV2 = z2.object({
|
|
438
|
+
scheme: z2.string(),
|
|
439
|
+
/** CAIP-2, e.g. "eip155:84532". */
|
|
440
|
+
network: z2.string(),
|
|
441
|
+
/** Atomic units — v2's rename of v1's maxAmountRequired. */
|
|
442
|
+
amount: z2.string().regex(/^\d+$/, "atomic amount must be an integer string"),
|
|
443
|
+
asset: z2.string().min(1),
|
|
444
|
+
payTo: z2.string().min(1),
|
|
445
|
+
maxTimeoutSeconds: z2.number().optional(),
|
|
446
|
+
extra: z2.record(z2.unknown()).optional()
|
|
447
|
+
});
|
|
448
|
+
var ResourceInfoV2 = z2.object({
|
|
449
|
+
url: z2.string(),
|
|
450
|
+
description: z2.string().optional(),
|
|
451
|
+
mimeType: z2.string().optional()
|
|
452
|
+
});
|
|
453
|
+
var PaymentRequiredV2 = z2.object({
|
|
454
|
+
x402Version: z2.literal(2),
|
|
455
|
+
error: z2.string().optional(),
|
|
456
|
+
resource: ResourceInfoV2.optional(),
|
|
457
|
+
accepts: z2.array(PaymentRequirementsV2).min(1),
|
|
458
|
+
extensions: z2.record(z2.unknown()).optional()
|
|
459
|
+
});
|
|
460
|
+
function v2Requirements(requirement) {
|
|
461
|
+
return {
|
|
462
|
+
scheme: requirement.scheme,
|
|
463
|
+
network: caip2Of(requirement.network),
|
|
464
|
+
amount: requirement.maxAmountRequired,
|
|
465
|
+
asset: requirement.asset,
|
|
466
|
+
payTo: requirement.payTo,
|
|
467
|
+
...requirement.maxTimeoutSeconds !== void 0 ? { maxTimeoutSeconds: requirement.maxTimeoutSeconds } : {},
|
|
468
|
+
...requirement.extra ? { extra: requirement.extra } : {}
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function buildPaymentRequiredV2(requirement, error) {
|
|
472
|
+
return {
|
|
473
|
+
x402Version: 2,
|
|
474
|
+
error,
|
|
475
|
+
...requirement.resource ? {
|
|
476
|
+
resource: {
|
|
477
|
+
url: requirement.resource,
|
|
478
|
+
...requirement.description ? { description: requirement.description } : {},
|
|
479
|
+
...requirement.mimeType ? { mimeType: requirement.mimeType } : {}
|
|
480
|
+
}
|
|
481
|
+
} : {},
|
|
482
|
+
accepts: [v2Requirements(requirement)],
|
|
483
|
+
extensions: {}
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
function encodeBase64Json(value) {
|
|
487
|
+
return Buffer.from(JSON.stringify(value)).toString("base64");
|
|
488
|
+
}
|
|
489
|
+
var V1Envelope = z2.object({
|
|
490
|
+
x402Version: z2.literal(1),
|
|
491
|
+
scheme: z2.string(),
|
|
492
|
+
network: z2.string(),
|
|
493
|
+
payload: z2.record(z2.unknown())
|
|
494
|
+
});
|
|
420
495
|
|
|
421
496
|
// src/errors.ts
|
|
422
497
|
var FacilitatorError = class extends Error {
|
|
@@ -450,6 +525,17 @@ var MockPaymentHeader = z3.object({
|
|
|
450
525
|
network: z3.string(),
|
|
451
526
|
payload: MockExactPayload
|
|
452
527
|
});
|
|
528
|
+
var MockPaymentHeaderV2 = z3.object({
|
|
529
|
+
x402Version: z3.literal(2),
|
|
530
|
+
accepted: z3.object({
|
|
531
|
+
scheme: z3.string(),
|
|
532
|
+
network: z3.string(),
|
|
533
|
+
amount: z3.string().regex(/^\d+$/, "atomic amount must be an integer string"),
|
|
534
|
+
asset: z3.string().min(1),
|
|
535
|
+
payTo: z3.string().min(1)
|
|
536
|
+
}).passthrough(),
|
|
537
|
+
payload: MockExactPayload
|
|
538
|
+
}).passthrough();
|
|
453
539
|
function encodePaymentHeader(header) {
|
|
454
540
|
return Buffer.from(JSON.stringify(header)).toString("base64");
|
|
455
541
|
}
|
|
@@ -460,11 +546,37 @@ function decodePaymentHeader(raw) {
|
|
|
460
546
|
} catch {
|
|
461
547
|
throw new FacilitatorError("malformed_payment", "X-PAYMENT is not base64-encoded JSON");
|
|
462
548
|
}
|
|
549
|
+
if (json?.x402Version === 2) {
|
|
550
|
+
const parsed2 = MockPaymentHeaderV2.safeParse(json);
|
|
551
|
+
if (!parsed2.success) {
|
|
552
|
+
throw new FacilitatorError(
|
|
553
|
+
"malformed_payment",
|
|
554
|
+
`invalid v2 payment envelope: ${parsed2.error.message}`
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
if (parsed2.data.payload.value !== parsed2.data.accepted.amount) {
|
|
558
|
+
throw new FacilitatorError(
|
|
559
|
+
"malformed_payment",
|
|
560
|
+
`v2 envelope contradicts itself: accepted.amount ${parsed2.data.accepted.amount} vs payload value ${parsed2.data.payload.value}`
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
return {
|
|
564
|
+
version: 2,
|
|
565
|
+
scheme: parsed2.data.accepted.scheme,
|
|
566
|
+
network: parsed2.data.accepted.network,
|
|
567
|
+
payload: parsed2.data.payload
|
|
568
|
+
};
|
|
569
|
+
}
|
|
463
570
|
const parsed = MockPaymentHeader.safeParse(json);
|
|
464
571
|
if (!parsed.success) {
|
|
465
572
|
throw new FacilitatorError("malformed_payment", `invalid X-PAYMENT body: ${parsed.error.message}`);
|
|
466
573
|
}
|
|
467
|
-
return
|
|
574
|
+
return {
|
|
575
|
+
version: 1,
|
|
576
|
+
scheme: parsed.data.scheme,
|
|
577
|
+
network: parsed.data.network,
|
|
578
|
+
payload: parsed.data.payload
|
|
579
|
+
};
|
|
468
580
|
}
|
|
469
581
|
var SettlementResponse = z3.object({
|
|
470
582
|
success: z3.boolean(),
|
|
@@ -507,7 +619,8 @@ var MockFacilitator = class {
|
|
|
507
619
|
}
|
|
508
620
|
});
|
|
509
621
|
}
|
|
510
|
-
/** Verify
|
|
622
|
+
/** Verify a payment header (either dialect) against the requirement it
|
|
623
|
+
* claims to satisfy. */
|
|
511
624
|
verify(paymentHeader, requirement) {
|
|
512
625
|
const header = decodePaymentHeader(paymentHeader);
|
|
513
626
|
if (header.scheme.toLowerCase() !== "exact" || requirement.scheme.toLowerCase() !== "exact") {
|
|
@@ -516,7 +629,7 @@ var MockFacilitator = class {
|
|
|
516
629
|
`mock facilitator only settles "exact", got "${header.scheme}"/"${requirement.scheme}"`
|
|
517
630
|
);
|
|
518
631
|
}
|
|
519
|
-
if (header.network
|
|
632
|
+
if (!sameNetwork(header.network, requirement.network)) {
|
|
520
633
|
throw new FacilitatorError(
|
|
521
634
|
"network_mismatch",
|
|
522
635
|
`payment is on "${header.network}" but the requirement wants "${requirement.network}"`
|
|
@@ -675,6 +788,7 @@ function sameAddress(a, b) {
|
|
|
675
788
|
// src/vendor.ts
|
|
676
789
|
function createMockVendor(options) {
|
|
677
790
|
const calls = [];
|
|
791
|
+
const advertise = options.advertise ?? "v1";
|
|
678
792
|
const requirementFor = (url) => PaymentRequirement.parse({
|
|
679
793
|
scheme: options.scheme ?? "exact",
|
|
680
794
|
network: options.network ?? "base",
|
|
@@ -683,18 +797,27 @@ function createMockVendor(options) {
|
|
|
683
797
|
payTo: options.payTo,
|
|
684
798
|
asset: options.asset ?? "USDC"
|
|
685
799
|
});
|
|
686
|
-
const paymentRequired = (url, error) =>
|
|
687
|
-
|
|
688
|
-
{
|
|
689
|
-
|
|
800
|
+
const paymentRequired = (url, error) => {
|
|
801
|
+
const requirement = requirementFor(url);
|
|
802
|
+
const body = advertise === "v2" ? { error } : { x402Version: 1, accepts: [requirement], error };
|
|
803
|
+
return new Response(JSON.stringify(body), {
|
|
804
|
+
status: 402,
|
|
805
|
+
headers: {
|
|
806
|
+
"content-type": "application/json",
|
|
807
|
+
...advertise !== "v1" ? {
|
|
808
|
+
"PAYMENT-REQUIRED": encodeBase64Json(buildPaymentRequiredV2(requirement, error))
|
|
809
|
+
} : {}
|
|
810
|
+
}
|
|
811
|
+
});
|
|
812
|
+
};
|
|
690
813
|
const fetch = async (input, init) => {
|
|
691
814
|
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
692
815
|
const headers = new Headers(
|
|
693
816
|
init?.headers ?? (input instanceof Request ? input.headers : void 0)
|
|
694
817
|
);
|
|
695
|
-
const payment = headers.get("X-PAYMENT");
|
|
818
|
+
const payment = headers.get("PAYMENT-SIGNATURE") ?? headers.get("X-PAYMENT");
|
|
696
819
|
calls.push({ url, payment });
|
|
697
|
-
if (payment === null) return paymentRequired(url, "
|
|
820
|
+
if (payment === null) return paymentRequired(url, "payment is required");
|
|
698
821
|
let settled;
|
|
699
822
|
try {
|
|
700
823
|
settled = options.facilitator.settle(payment, requirementFor(url));
|
|
@@ -704,7 +827,13 @@ function createMockVendor(options) {
|
|
|
704
827
|
}
|
|
705
828
|
return new Response(JSON.stringify(options.body ?? { ok: true }), {
|
|
706
829
|
status: 200,
|
|
707
|
-
headers: {
|
|
830
|
+
headers: {
|
|
831
|
+
"content-type": "application/json",
|
|
832
|
+
// Both dialect names carry the same base64 settlement object; the
|
|
833
|
+
// strict v2 vendor sets ONLY the v2 name.
|
|
834
|
+
...advertise !== "v2" ? { "X-PAYMENT-RESPONSE": settled.header } : {},
|
|
835
|
+
"PAYMENT-RESPONSE": settled.header
|
|
836
|
+
}
|
|
708
837
|
});
|
|
709
838
|
};
|
|
710
839
|
return { fetch, calls, requirementFor };
|
|
@@ -716,6 +845,7 @@ export {
|
|
|
716
845
|
MockIndexer,
|
|
717
846
|
MockLedger,
|
|
718
847
|
MockPaymentHeader,
|
|
848
|
+
MockPaymentHeaderV2,
|
|
719
849
|
SettlementResponse,
|
|
720
850
|
createMockVendor,
|
|
721
851
|
decodePaymentHeader,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ledger.ts","../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/agent.ts","../../../packages/core/src/erc8004.ts","../../../packages/core/src/intent.ts","../../../packages/core/src/decision.ts","../../../packages/core/src/canonical.ts","../../../packages/core/src/session.ts","../../../packages/core/src/payment.ts","../../../packages/core/src/receipt.ts","../../../packages/core/src/gate-receipt.ts","../../../packages/core/src/policy.ts","../../../packages/core/src/reputation.ts","../../../packages/core/src/events.ts","../../../packages/sdk/src/errors.ts","../../../packages/sdk/src/client.ts","../../../packages/sdk/src/x402.ts","../../../packages/sdk/src/guard.ts","../src/errors.ts","../src/payload.ts","../src/facilitator.ts","../src/indexer.ts","../src/vendor.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\nimport { randomBytes } from 'node:crypto';\nimport { Chain, Asset, DecimalString } from '@reinconsole/core';\n\n/**\n * The simulated chain. One MockLedger plays every chain at once: entries carry\n * their `chain` tag instead of living on separate ledgers, which keeps the\n * mock world to a single object.\n *\n * Crucially, ANYONE can call `transfer()` directly — that is the bypass path.\n * An agent that pays a vendor without going through the guard still leaves a\n * ledger entry, and the indexer turns that into a `shadow.spend` event.\n */\nexport interface TransferInput {\n chain: Chain;\n asset: Asset;\n from: string;\n to: string;\n /** Human-unit decimal amount, e.g. \"0.01\". */\n amount: string;\n /** Opaque settlement memo; the mock facilitator writes the intent id here. */\n memo?: string;\n}\n\nexport interface LedgerEntry extends TransferInput {\n txHash: string;\n blockNumber: bigint;\n at: Date;\n}\n\nexport class MockLedger {\n private readonly log: LedgerEntry[] = [];\n private readonly bus = new EventEmitter();\n private height = 0n;\n\n /** Append a confirmed transfer (one entry == one tx in its own block). */\n transfer(input: TransferInput): LedgerEntry {\n const entry: LedgerEntry = {\n ...input,\n chain: Chain.parse(input.chain),\n asset: Asset.parse(input.asset),\n amount: DecimalString.parse(input.amount),\n txHash: `0x${randomBytes(32).toString('hex')}`,\n blockNumber: ++this.height,\n at: new Date(),\n };\n this.log.push(entry);\n this.bus.emit('entry', entry);\n return entry;\n }\n\n /** All transfers, oldest first. */\n entries(): readonly LedgerEntry[] {\n return this.log;\n }\n\n /** Subscribe to new transfers as they confirm (what the indexer watches). */\n onEntry(handler: (entry: LedgerEntry) => void): void {\n this.bus.on('entry', handler);\n }\n}\n","import { z } from 'zod';\n\n/**\n * Chains Rein observes/governs. x402 is multi-chain; Base and Solana ship\n * first, Polygon and BNB follow. The policy/ledger domain is rail-agnostic —\n * this enum is the only place chains are enumerated.\n */\nexport const Chain = z.enum(['base', 'solana', 'polygon', 'bnb']);\nexport type Chain = z.infer<typeof Chain>;\n\n/** Stablecoins settled over x402. */\nexport const Asset = z.enum(['USDC', 'USDT', 'EURC']);\nexport type Asset = z.infer<typeof Asset>;\n","import { z } from 'zod';\n\n/**\n * Monetary amounts in Rein are always non-negative **decimal strings**, never\n * floats. Float arithmetic silently loses precision on values like 0.1 + 0.2,\n * which is unacceptable for money. All comparison/aggregation goes through the\n * BigInt-backed helpers below.\n */\nexport const DecimalString = z\n .string()\n .regex(/^\\d+(\\.\\d+)?$/, 'must be a non-negative decimal string, e.g. \"5.00\"');\nexport type DecimalString = z.infer<typeof DecimalString>;\n\nconst DECIMAL_RE = /^\\d+(\\.\\d+)?$/;\n\nexport function isValidDecimal(value: string): boolean {\n return DECIMAL_RE.test(value);\n}\n\nfunction assertDecimal(value: string): void {\n if (!isValidDecimal(value)) {\n throw new TypeError(`invalid decimal string: ${JSON.stringify(value)}`);\n }\n}\n\nfunction fractionLength(value: string): number {\n const dot = value.indexOf('.');\n return dot === -1 ? 0 : value.length - dot - 1;\n}\n\n/** Scale a decimal string into an integer BigInt at a fixed number of fraction digits. */\nfunction toScaled(value: string, scale: number): bigint {\n const dot = value.indexOf('.');\n const intPart = dot === -1 ? value : value.slice(0, dot);\n const fracPart = dot === -1 ? '' : value.slice(dot + 1);\n const paddedFrac = (fracPart + '0'.repeat(scale)).slice(0, scale);\n return BigInt(intPart + paddedFrac);\n}\n\n/** Render a scaled BigInt back to a normalized decimal string (no trailing zeros). */\nfunction fromScaled(scaled: bigint, scale: number): string {\n if (scale === 0) return scaled.toString();\n const digits = scaled.toString().padStart(scale + 1, '0');\n const intPart = digits.slice(0, digits.length - scale);\n const fracPart = digits.slice(digits.length - scale).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/** Compare two decimal strings. Returns -1 (a<b), 0 (a==b), or 1 (a>b). */\nexport function compareDecimal(a: string, b: string): -1 | 0 | 1 {\n assertDecimal(a);\n assertDecimal(b);\n const scale = Math.max(fractionLength(a), fractionLength(b));\n const av = toScaled(a, scale);\n const bv = toScaled(b, scale);\n return av < bv ? -1 : av > bv ? 1 : 0;\n}\n\n/** Sum a list of decimal strings without floating-point error. */\nexport function sumDecimal(values: readonly string[]): string {\n if (values.length === 0) return '0';\n let scale = 0;\n for (const v of values) {\n assertDecimal(v);\n scale = Math.max(scale, fractionLength(v));\n }\n let total = 0n;\n for (const v of values) total += toScaled(v, scale);\n return fromScaled(total, scale);\n}\n\n/** Multiply two decimal strings exactly (e.g. median * \"3\" for price-sanity). */\nexport function mulDecimal(a: string, b: string): string {\n assertDecimal(a);\n assertDecimal(b);\n const scaleA = fractionLength(a);\n const scaleB = fractionLength(b);\n const product = toScaled(a, scaleA) * toScaled(b, scaleB);\n return fromScaled(product, scaleA + scaleB);\n}\n\n/** Convenience: a > b. */\nexport function gt(a: string, b: string): boolean {\n return compareDecimal(a, b) === 1;\n}\n\n/** Convenience: a < b. */\nexport function lt(a: string, b: string): boolean {\n return compareDecimal(a, b) === -1;\n}\n","/**\n * Minimal, safe glob matcher supporting only the `*` wildcard (matches any run\n * of characters, including none). Used for vendor host allowlists\n * (e.g. \"*.trusted.io\"), agent-id targeting (e.g. \"agt_research_*\"), and\n * Gate route pricing (e.g. \"/api/reports/*\").\n *\n * Deliberately NOT a regex from user input — the pattern is escaped so a\n * malicious policy value cannot inject regex behavior (ReDoS, etc.).\n */\nexport function globMatch(pattern: string, value: string): boolean {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // escape regex metachars\n const withWildcard = escaped.replace(/\\\\\\*/g, '.*'); // re-enable only `*`\n return new RegExp(`^${withWildcard}$`).test(value);\n}\n\n/** True if `value` matches any pattern in the list. */\nexport function globMatchAny(patterns: readonly string[], value: string): boolean {\n return patterns.some((p) => globMatch(p, value));\n}\n","/**\n * Minimal ULID generation, dependency-free. ULIDs are lexicographically\n * sortable (time-prefixed) and url-safe, which is why Rein uses them for all\n * primary keys instead of UUIDs. Works in Node 22 and modern browsers/edge via\n * the WebCrypto `globalThis.crypto`.\n */\n\n// Crockford's base32 alphabet (excludes I, L, O, U to avoid ambiguity).\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\nfunction encodeTime(now: number): string {\n let time = now;\n let out = '';\n for (let i = TIME_LEN - 1; i >= 0; i--) {\n out = ENCODING.charAt(time % 32) + out;\n time = Math.floor(time / 32);\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n let out = '';\n for (const byte of randomBytes(RANDOM_LEN)) {\n out += ENCODING.charAt(byte % 32);\n }\n return out;\n}\n\n/** Generate a 26-character ULID. */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime) + encodeRandom();\n}\n\n/** Generate a Stripe-style prefixed id, e.g. `newId('agt')` -> `agt_01J...`. */\nexport function newId<P extends string>(prefix: P): `${P}_${string}` {\n return `${prefix}_${ulid()}`;\n}\n","import { z } from 'zod';\n\n/** Crockford base32 ULID body (26 chars), as produced by `ulid()`. */\nconst ULID_BODY = '[0-9A-HJKMNP-TV-Z]{26}';\n\n/**\n * A zod schema for a Stripe-style prefixed ULID, e.g. `agt_01J7...`.\n * Centralizing this keeps id formats consistent across DB rows, API payloads,\n * and SDK types.\n */\nexport function prefixedId(prefix: string) {\n return z\n .string()\n .regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a \"${prefix}_\" prefixed id`);\n}\n\nexport const OrgId = prefixedId('org');\nexport const AgentId = prefixedId('agt');\nexport const PolicyId = prefixedId('pol');\nexport const IntentId = prefixedId('int');\nexport const DecisionId = prefixedId('dec');\nexport const ReceiptId = prefixedId('rcp');\nexport const SessionId = prefixedId('ses');\nexport const GateReceiptId = prefixedId('grc');\n\nexport type OrgId = z.infer<typeof OrgId>;\nexport type AgentId = z.infer<typeof AgentId>;\nexport type PolicyId = z.infer<typeof PolicyId>;\nexport type IntentId = z.infer<typeof IntentId>;\nexport type DecisionId = z.infer<typeof DecisionId>;\nexport type ReceiptId = z.infer<typeof ReceiptId>;\nexport type SessionId = z.infer<typeof SessionId>;\nexport type GateReceiptId = z.infer<typeof GateReceiptId>;\n","import { z } from 'zod';\nimport { AgentId, OrgId } from './ids.js';\nimport { Chain } from './chain.js';\n\n/**\n * Enforcement tier of a given agent wallet:\n * - `observed` — Rein sees spend on-chain but has no control (no SDK either).\n * - `sdk` — agent uses @reinconsole/sdk; advisory + observability (bypassable).\n * - `session-key` — signer-level scope; out-of-policy txs cannot be signed.\n */\nexport const EnforcementMode = z.enum(['observed', 'sdk', 'session-key']);\nexport type EnforcementMode = z.infer<typeof EnforcementMode>;\n\nexport const AgentWallet = z.object({\n chain: Chain,\n address: z.string().min(1),\n mode: EnforcementMode,\n});\nexport type AgentWallet = z.infer<typeof AgentWallet>;\n\nexport const AgentStatus = z.enum(['active', 'frozen']);\nexport type AgentStatus = z.infer<typeof AgentStatus>;\n\nexport const Agent = z.object({\n id: AgentId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** On-chain ERC-8004 identity, if the agent is registered. */\n erc8004Id: z.string().optional(),\n wallets: z.array(AgentWallet).default([]),\n status: AgentStatus.default('active'),\n createdAt: z.coerce.date(),\n});\nexport type Agent = z.infer<typeof Agent>;\n","import { z } from 'zod';\n\n/**\n * The canonical string form of an ERC-8004 agent identity:\n *\n * eip155:{chainId}:{identityRegistry}/{tokenId}\n *\n * The part before the `/` is the spec's registry reference verbatim (the\n * `agentRegistry` field of a registration file, CAIP-10 account form); the\n * tokenId is the ERC-721 id the Identity Registry minted (`agentId` in the\n * spec). This exact string is what `Agent.erc8004Id` / `Vendor.erc8004Id`\n * carry, AND the reputation-subject id a registered agent's evidence keys by.\n *\n * Casing is load-bearing: reputation subject keys for agent-kind ids are\n * case-sensitive unless they start with `0x` (see @reinconsole/graph\n * `normalizeSubject`), and an eip155 string does not. `formatErc8004Id`\n * therefore always emits the registry address in lowercase, and consumers must\n * never hand-build the string — parse then re-format to normalize.\n */\n\nexport interface Erc8004Ref {\n /** EIP-155 chain id (e.g. 8453 Base, 84532 Base Sepolia). */\n chainId: number;\n /** Identity Registry contract address, lowercase 0x-hex. */\n registry: string;\n /** ERC-721 tokenId — the spec's `agentId`. bigint: token ids exceed 2^53. */\n tokenId: bigint;\n}\n\nconst REGISTRY_PATTERN = /^0x[0-9a-fA-F]{40}$/;\nconst ID_PATTERN = /^eip155:(\\d+):(0x[0-9a-fA-F]{40})\\/(\\d+)$/;\n\n/** Build the canonical id string. Throws on a malformed ref (programmer error). */\nexport function formatErc8004Id(ref: Erc8004Ref): string {\n if (!Number.isSafeInteger(ref.chainId) || ref.chainId < 1) {\n throw new RangeError(`erc8004: bad chainId ${ref.chainId}`);\n }\n if (!REGISTRY_PATTERN.test(ref.registry)) {\n throw new RangeError(`erc8004: bad registry address ${ref.registry}`);\n }\n if (typeof ref.tokenId !== 'bigint' || ref.tokenId < 0n) {\n // The typeof guard matters for plain-JS callers: 1.5 < 0n is legal JS and\n // false, and would mint the unparseable \"…/1.5\".\n throw new RangeError(`erc8004: bad tokenId ${ref.tokenId}`);\n }\n return `eip155:${ref.chainId}:${ref.registry.toLowerCase()}/${ref.tokenId}`;\n}\n\n/**\n * Parse a canonical (or hand-written) id string. Accepts any address casing\n * and returns a lowercase ref, or undefined when malformed — so\n * `formatErc8004Id(parseErc8004Id(x)!)` is the normalization step.\n */\nexport function parseErc8004Id(value: string): Erc8004Ref | undefined {\n const match = ID_PATTERN.exec(value);\n if (!match) return undefined;\n const chainId = Number(match[1]);\n if (!Number.isSafeInteger(chainId) || chainId < 1) return undefined;\n return {\n chainId,\n registry: match[2]!.toLowerCase(),\n tokenId: BigInt(match[3]!),\n };\n}\n\n/** Strict boundary schema for the id string (the fields themselves stay free-form). */\nexport const Erc8004Id = z\n .string()\n .refine((value) => parseErc8004Id(value) !== undefined, {\n message: 'expected \"eip155:{chainId}:{registry}/{tokenId}\"',\n });\nexport type Erc8004Id = z.infer<typeof Erc8004Id>;\n","import { z } from 'zod';\nimport { AgentId, IntentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\n\nexport const Vendor = z.object({\n host: z.string().min(1),\n address: z.string().min(1),\n erc8004Id: z.string().optional(),\n});\nexport type Vendor = z.infer<typeof Vendor>;\n\n/**\n * The observability gold: links every micro-payment back to the task and run\n * that caused it, so finance teams can answer \"what was this spend for?\".\n */\nexport const TaskContext = z.object({\n taskId: z.string().optional(),\n parentRunId: z.string().optional(),\n purpose: z.string().max(500).optional(),\n});\nexport type TaskContext = z.infer<typeof TaskContext>;\n\n/**\n * A request to spend, submitted to the policy engine BEFORE any signature is\n * released. The `nonce` provides replay protection on the signer path.\n */\nexport const PaymentIntent = z.object({\n id: IntentId,\n agentId: AgentId,\n vendor: Vendor,\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n nonce: z.string().min(1),\n createdAt: z.coerce.date(),\n});\nexport type PaymentIntent = z.infer<typeof PaymentIntent>;\n","import { z } from 'zod';\nimport { DecisionId, IntentId } from './ids.js';\n\nexport const DecisionOutcome = z.enum(['allow', 'deny', 'escalate']);\nexport type DecisionOutcome = z.infer<typeof DecisionOutcome>;\n\n/**\n * The signed, hash-chained record of a single policy evaluation. Written BEFORE\n * any signature is released. `prevHash` + `hash` form a tamper-evident chain;\n * `signature` is the policy service's signing key over `hash`. The eventual\n * on-chain `txHash` is attached later by the indexer (see SettledPayment).\n */\nexport const Decision = z.object({\n id: DecisionId,\n intentId: IntentId,\n /**\n * sha256 of the intent's canonical content (see canonical.ts). Binds the\n * decision to the exact transfer it judged — amount, recipient, asset,\n * chain — so a signer can verify an {intent, decision} pair offline as a\n * self-contained spend voucher, not just a reference by id.\n */\n intentHash: z.string(),\n outcome: DecisionOutcome,\n /** Ids of the rules that fired, for explainability. */\n matchedRules: z.array(z.string()).default([]),\n /** Human-readable explanation surfaced in the dashboard. */\n reason: z.string().optional(),\n policyId: z.string(),\n policyVersion: z.string(),\n /** Hash of the previous decision in the chain (tamper-evident log). */\n prevHash: z.string(),\n /** Hash of this decision's canonical content. */\n hash: z.string(),\n /** Service signing-key signature over `hash`. */\n signature: z.string(),\n latencyMs: z.number().nonnegative(),\n decidedAt: z.coerce.date(),\n});\nexport type Decision = z.infer<typeof Decision>;\n","import type { PaymentIntent } from './intent.js';\nimport type { DecisionOutcome } from './decision.js';\n\n/**\n * Canonical byte forms shared by the policy engine (which hashes and signs\n * them) and the signer (which verifies them offline). Field order is fixed,\n * dates are ISO strings, and absent optionals are explicit nulls, so the same\n * parsed object always canonicalizes to the same bytes — including after a\n * JSON round-trip over HTTP.\n *\n * These builders are pure (no node:crypto) so @reinconsole/core stays loadable in a\n * browser; services hash the strings with whatever sha256 they have.\n */\n\n/** Canonical form of an intent — what `Decision.intentHash` commits to. */\nexport function canonicalIntent(intent: PaymentIntent): string {\n return JSON.stringify({\n id: intent.id,\n agentId: intent.agentId,\n vendor: {\n host: intent.vendor.host,\n address: intent.vendor.address,\n erc8004Id: intent.vendor.erc8004Id ?? null,\n },\n resource: intent.resource,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: {\n taskId: intent.taskContext.taskId ?? null,\n parentRunId: intent.taskContext.parentRunId ?? null,\n purpose: intent.taskContext.purpose ?? null,\n },\n nonce: intent.nonce,\n createdAt: intent.createdAt.toISOString(),\n });\n}\n\n/** The decision fields covered by `Decision.hash` (and thus its signature). */\nexport interface DecisionContent {\n intentId: string;\n intentHash: string;\n outcome: DecisionOutcome;\n matchedRules: string[];\n policyId: string;\n policyVersion: string;\n prevHash: string;\n decidedAt: Date;\n}\n\n/** Canonical form of a decision — what `Decision.hash` is computed over. */\nexport function canonicalDecision(d: DecisionContent): string {\n return JSON.stringify({\n intentId: d.intentId,\n intentHash: d.intentHash,\n outcome: d.outcome,\n matchedRules: d.matchedRules,\n policyId: d.policyId,\n policyVersion: d.policyVersion,\n prevHash: d.prevHash,\n decidedAt: d.decidedAt.toISOString(),\n });\n}\n","import { z } from 'zod';\nimport { AgentId, SessionId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * A session-key grant: the signer tier's unit of delegated authority. The\n * agent process holds only the bearer token — the wallet key never leaves the\n * signer — and the stored record keeps a hash of the token, never the token\n * itself (it is returned exactly once, at creation).\n *\n * Caps here are the signer-side backstop UNDER whatever policy says: a\n * signature is released only when the engine allowed the intent AND the\n * session has room. Amounts are decimal strings in the asset's human units.\n */\nexport const Session = z.object({\n id: SessionId,\n agentId: AgentId,\n /** sha256 hex of the bearer token. */\n tokenHash: z.string(),\n /** Cumulative ceiling across the session's lifetime. Absent = uncapped. */\n capAmount: DecimalString.optional(),\n /** Ceiling per individual signature. Absent = uncapped. */\n maxPerPayment: DecimalString.optional(),\n expiresAt: z.coerce.date(),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type Session = z.infer<typeof Session>;\n","import { z } from 'zod';\nimport { IntentId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * On-chain confirmation of a settled payment, reconciled by the indexer against\n * the originating intent (amount + recipient + nonce, or facilitator webhook).\n */\nexport const SettledPayment = z.object({\n intentId: IntentId,\n txHash: z.string(),\n chain: Chain,\n blockNumber: z.coerce.bigint(),\n facilitator: z.string().optional(),\n feePaid: DecimalString.optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettledPayment = z.infer<typeof SettledPayment>;\n","import { z } from 'zod';\nimport { ReceiptId, IntentId, DecisionId, AgentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { TaskContext } from './intent.js';\nimport { DecisionOutcome } from './decision.js';\n\n/**\n * What the SDK reports back after settlement: the `X-PAYMENT-RESPONSE` header\n * a vendor returns once payment clears. Mock facilitators fill this in v0.1;\n * the indexer reconciles it against on-chain truth later (see SettledPayment).\n */\nexport const ReceiptSettlement = z.object({\n txHash: z.string().optional(),\n networkId: z.string().optional(),\n /** Raw header payload, kept for forensics until the indexer confirms. */\n raw: z.string().optional(),\n});\nexport type ReceiptSettlement = z.infer<typeof ReceiptSettlement>;\n\n/**\n * The SDK-side record of one guarded payment attempt: which request triggered\n * it, what the engine decided, and (if allowed and paid) how it settled.\n * Receipts are the observability primitive — every 402 the guard touches\n * produces exactly one, whether the payment was allowed or blocked.\n */\nexport const Receipt = z.object({\n id: ReceiptId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n outcome: DecisionOutcome,\n /** The URL the agent actually fetched (the paywalled resource). */\n url: z.string(),\n method: z.string().default('GET'),\n vendorHost: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n /** Human-readable explanation copied from the decision. */\n reason: z.string().optional(),\n /** Present only once a payment was made and the vendor confirmed it. */\n settlement: ReceiptSettlement.optional(),\n createdAt: z.coerce.date(),\n});\nexport type Receipt = z.infer<typeof Receipt>;\n","import { z } from 'zod';\nimport { GateReceiptId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * The vendor-side twin of `Receipt`: one settled x402 payment as the GATE saw\n * it — who paid, for which priced route, and the settlement transaction. The\n * agent-side Receipt records what an agent tried to spend; a GateReceipt\n * records what a vendor actually earned.\n */\nexport const GateReceipt = z.object({\n id: GateReceiptId,\n at: z.coerce.date(),\n /** The route pattern that priced this request, e.g. \"/api/reports/*\". */\n route: z.string().min(1),\n /** The concrete resource paid for (URL path actually requested). */\n resource: z.string().min(1),\n method: z.string().min(1),\n /** The paying wallet address, as asserted by the settled payment. */\n payer: z.string().min(1),\n payTo: z.string().min(1),\n /** Human-unit decimal amount, e.g. \"0.05\". */\n amount: DecimalString,\n /** The same amount in the asset's atomic units, e.g. \"50000\". */\n amountAtomic: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n /** Token symbol or contract address, exactly as quoted in the requirement. */\n asset: z.string().min(1),\n network: z.string().min(1),\n /** Settlement transaction hash (mock ledger or on-chain). */\n transaction: z.string().min(1),\n});\nexport type GateReceipt = z.infer<typeof GateReceipt>;\n","import { z } from 'zod';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/** A rolling-window spec, e.g. \"24h\", \"1h\", \"30m\", \"7d\". */\nexport const Window = z\n .string()\n .regex(/^\\d+[smhd]$/, 'window must be like \"30s\", \"15m\", \"1h\", or \"7d\"');\nexport type Window = z.infer<typeof Window>;\n\n/** A relative multiplier, e.g. \"3x\" (used for price-sanity checks). */\nexport const Multiplier = z.string().regex(/^\\d+(\\.\\d+)?x$/, 'multiplier must be like \"3x\"');\nexport type Multiplier = z.infer<typeof Multiplier>;\n\n/**\n * The set of predicates a rule can test. Multiple predicates in one condition\n * are ANDed together. Each maps to an evaluator in the policy engine.\n */\nexport const Condition = z\n .object({\n /** Per-transaction amount exceeds this value. */\n amountGt: DecimalString.optional(),\n /** Sum of spend in a rolling window exceeds `gt`. */\n rollingSum: z.object({ window: Window, gt: DecimalString }).optional(),\n /** Transaction count in a rolling window exceeds `gt`. */\n txCount: z.object({ window: Window, gt: z.number().int().nonnegative() }).optional(),\n /** Vendor host matches one of these patterns (supports `*` globs). */\n vendorHostIn: z.array(z.string()).optional(),\n /** First time Rein has seen this vendor for the agent. */\n vendorFirstSeen: z.boolean().optional(),\n /** Vendor reputation score is below this threshold (Phase 3 hook). */\n vendorReputationLt: z.number().min(0).max(100).optional(),\n /** Amount is more than `gt`-times the observed median for this resource. */\n amountVsResourceMedian: z.object({ gt: Multiplier }).optional(),\n })\n .refine((c) => Object.values(c).some((v) => v !== undefined), {\n message: 'a condition must specify at least one predicate',\n });\nexport type Condition = z.infer<typeof Condition>;\n\n/**\n * A single rule: an id plus exactly one action (allow / deny / escalate) whose\n * value is the condition that triggers it.\n */\nexport const Rule = z\n .object({\n id: z.string().min(1),\n allow: Condition.optional(),\n deny: Condition.optional(),\n escalate: Condition.optional(),\n })\n .refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== undefined).length === 1, {\n message: 'a rule must specify exactly one of allow / deny / escalate',\n });\nexport type Rule = z.infer<typeof Rule>;\n\nexport const PolicyDefault = z.enum(['allow', 'deny']);\nexport type PolicyDefault = z.infer<typeof PolicyDefault>;\n\nexport const AppliesTo = z.object({\n /** Agent id patterns (supports `*` globs, e.g. \"agt_research_*\"). */\n agents: z.array(z.string()).optional(),\n chains: z.array(Chain).optional(),\n});\nexport type AppliesTo = z.infer<typeof AppliesTo>;\n\nexport const Escalation = z.object({\n approvers: z.array(z.string()).default([]),\n timeoutAction: PolicyDefault.default('deny'),\n timeoutMin: z.number().int().positive().default(15),\n});\nexport type Escalation = z.infer<typeof Escalation>;\n\n/**\n * A declarative, versioned, immutable-once-active policy. Evaluation order in\n * the engine is: explicit DENY > ESCALATE > ALLOW > `default`.\n */\nexport const Policy = z.object({\n policyId: z.string().min(1),\n version: z.string().default('1'),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n default: PolicyDefault.default('deny'),\n /** Below this amount, fail-open is permitted during a policy-service outage. */\n denyFloor: DecimalString.default('0.05'),\n escalation: Escalation.optional(),\n});\nexport type Policy = z.infer<typeof Policy>;\n","import { z } from 'zod';\n\nexport const ReputationSubject = z.object({\n kind: z.enum(['agent', 'vendor']),\n id: z.string(),\n});\nexport type ReputationSubject = z.infer<typeof ReputationSubject>;\n\nexport const ReputationComponents = z.object({\n volume: z.number(),\n longevity: z.number(),\n disputeRate: z.number(),\n counterpartyQuality: z.number(),\n settlementReliability: z.number(),\n});\nexport type ReputationComponents = z.infer<typeof ReputationComponents>;\n\n/**\n * A reputation score for an agent or vendor (Phase 3 — Graph). `confidence` is\n * first-class: a thin-history subject returns LOW confidence rather than a\n * misleadingly high score, so policy can avoid both false trust and unfair\n * freezing.\n */\nexport const ReputationScore = z.object({\n subject: ReputationSubject,\n score: z.number().min(0).max(100),\n components: ReputationComponents,\n confidence: z.number().min(0).max(1),\n asOf: z.coerce.date(),\n /** Hash-anchored attestation, optionally published on-chain (ERC-8004). */\n evidenceUri: z.string().optional(),\n});\nexport type ReputationScore = z.infer<typeof ReputationScore>;\n","import { z } from 'zod';\nimport { AgentId, DecisionId, IntentId, SessionId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { PaymentIntent } from './intent.js';\nimport { Decision } from './decision.js';\nimport { SettledPayment } from './payment.js';\nimport { GateReceipt } from './gate-receipt.js';\n\n/**\n * The canonical event envelope published on the bus (NATS in production).\n * `shadow.spend` is emitted when the indexer sees on-chain spend from a managed\n * wallet with NO corresponding ALLOW decision — the bypass signal that catches\n * SDK-mode evasion and drives the upgrade to the signer tier.\n * `signature.released` / `signature.refused` are that tier's heartbeat: every\n * time the signer does or does not put a key to work, the bus knows why.\n * `gate.*` is the vendor side of the wire: every quote a Gate issues, every\n * payment it accepts, every payment it turns away.\n */\nexport const ReinEvent = z.discriminatedUnion('type', [\n z.object({ type: z.literal('intent.created'), at: z.coerce.date(), intent: PaymentIntent }),\n z.object({ type: z.literal('decision.made'), at: z.coerce.date(), decision: Decision }),\n z.object({ type: z.literal('payment.settled'), at: z.coerce.date(), payment: SettledPayment }),\n z.object({\n type: z.literal('shadow.spend'),\n at: z.coerce.date(),\n agentId: AgentId,\n txHash: z.string(),\n chain: Chain,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.released'),\n at: z.coerce.date(),\n sessionId: SessionId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"decision_replayed\" (see @reinconsole/signer). */\n code: z.string(),\n reason: z.string(),\n sessionId: SessionId.optional(),\n agentId: AgentId.optional(),\n intentId: IntentId.optional(),\n }),\n z.object({\n type: z.literal('gate.quoted'),\n at: z.coerce.date(),\n resource: z.string(),\n method: z.string(),\n amount: DecimalString,\n asset: z.string(),\n network: z.string(),\n }),\n z.object({ type: z.literal('gate.settled'), at: z.coerce.date(), receipt: GateReceipt }),\n z.object({\n type: z.literal('gate.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"payment_replayed\" (see @reinconsole/gate). */\n code: z.string(),\n reason: z.string(),\n resource: z.string(),\n /** Known only when the payment header decoded far enough to name a payer. */\n payer: z.string().optional(),\n }),\n]);\nexport type ReinEvent = z.infer<typeof ReinEvent>;\n","import type { Decision, PaymentIntent, Receipt } from '@reinconsole/core';\n\n/** Base class for everything the SDK throws, so callers can catch broadly. */\nexport class ReinError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** The policy engine answered with a non-2xx status. */\nexport class EngineError extends ReinError {\n constructor(\n readonly status: number,\n readonly body: unknown,\n message = `policy engine responded ${status}`,\n ) {\n super(message);\n }\n}\n\n/**\n * The engine evaluated the intent and did NOT allow it (deny or escalate —\n * v0.1 blocks both; escalation approval flows land later). The payment was\n * never constructed, so no funds moved. Carries the full evidence trail.\n */\nexport class PaymentBlockedError extends ReinError {\n constructor(\n readonly intent: PaymentIntent,\n readonly decision: Decision,\n readonly receipt: Receipt,\n ) {\n super(\n `rein blocked payment of ${intent.amount} ${intent.asset} to ${intent.vendor.host}: ` +\n `${decision.outcome}${decision.reason ? ` (${decision.reason})` : ''}`,\n );\n }\n}\n\n/**\n * The vendor's 402 was x402-shaped but offered no requirement the guard can\n * govern (unknown scheme/network/asset). The guard fails closed rather than\n * letting an ungoverned payment through.\n */\nexport class UnsupportedRequirementError extends ReinError {\n constructor(readonly url: string) {\n super(`no supported x402 payment requirement in 402 from ${url}; failing closed`);\n }\n}\n","import { z } from 'zod';\nimport { Agent, Decision, PaymentIntent, Policy } from '@reinconsole/core';\nimport { EngineError } from './errors.js';\nimport type { IntentSubmission } from './x402.js';\n\n/** Any fetch-compatible function (global fetch, undici, or a test double). */\nexport type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;\n\nconst Health = z.object({ status: z.string(), publicKey: z.string() });\nconst EvaluateResponse = z.object({ intent: PaymentIntent, decision: Decision });\nexport type EvaluateResponse = z.infer<typeof EvaluateResponse>;\n\nexport interface EngineClientOptions {\n /** Base URL of the policy engine, e.g. \"http://localhost:8787\". */\n baseUrl: string;\n /** Override the transport (tests, custom agents). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\n/**\n * Thin typed client for the policy-engine HTTP API. Every response is parsed\n * through the @reinconsole/core schemas, so wire drift fails loudly at the boundary.\n */\nexport class EngineClient {\n private readonly baseUrl: string;\n private readonly fetchImpl: FetchLike;\n\n constructor(options: EngineClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n const f = options.fetch ?? globalThis.fetch;\n this.fetchImpl = (input, init) => f(input, init);\n }\n\n private async request<T>(\n method: string,\n path: string,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>,\n body?: unknown,\n ): Promise<T> {\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n headers: body === undefined ? undefined : { 'content-type': 'application/json' },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n if (!res.ok) {\n const payload = await res\n .clone()\n .json()\n .catch(() => res.text().catch(() => undefined));\n throw new EngineError(res.status, payload);\n }\n if (res.status === 204) return schema.parse(undefined);\n return schema.parse(await res.json());\n }\n\n health(): Promise<z.infer<typeof Health>> {\n return this.request('GET', '/health', Health);\n }\n\n registerAgent(input: {\n orgId: string;\n name: string;\n erc8004Id?: string;\n wallets?: Agent['wallets'];\n }): Promise<Agent> {\n return this.request('POST', '/v1/agents', Agent, input);\n }\n\n listAgents(): Promise<Agent[]> {\n return this.request('GET', '/v1/agents', z.array(Agent));\n }\n\n freeze(agentId: string): Promise<void> {\n return this.request('POST', `/v1/agents/${agentId}/freeze`, z.void());\n }\n\n unfreeze(agentId: string): Promise<void> {\n return this.request('POST', `/v1/agents/${agentId}/unfreeze`, z.void());\n }\n\n addPolicy(policy: z.input<typeof Policy>): Promise<Policy> {\n return this.request('POST', '/v1/policies', Policy, policy);\n }\n\n listPolicies(): Promise<Policy[]> {\n return this.request('GET', '/v1/policies', z.array(Policy));\n }\n\n /** The hot path: submit an intent, get the normalized intent + signed decision. */\n evaluate(submission: IntentSubmission): Promise<EvaluateResponse> {\n return this.request('POST', '/v1/evaluate', EvaluateResponse, submission);\n }\n\n decisions(): Promise<Decision[]> {\n return this.request('GET', '/v1/decisions', z.array(Decision));\n }\n}\n","import { z } from 'zod';\nimport { Chain, Asset, type TaskContext, type Vendor } from '@reinconsole/core';\n\n/**\n * x402 wire shapes (spec v1), mock-first: these schemas are what Rein's mock\n * facilitator and tests speak today, and they track the published x402 spec so\n * real vendors parse identically when the live integration lands.\n */\n\n/** One way to pay, as offered inside a 402 response body. */\nexport const PaymentRequirement = z.object({\n scheme: z.string(),\n network: z.string(),\n /** Amount in the asset's atomic units (e.g. \"10000\" = 0.01 USDC at 6 decimals). */\n maxAmountRequired: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n resource: z.string().optional(),\n description: z.string().optional(),\n mimeType: z.string().optional(),\n payTo: z.string().min(1),\n maxTimeoutSeconds: z.number().optional(),\n /** Token contract address — or, mock-first, a plain symbol like \"USDC\". */\n asset: z.string().min(1),\n extra: z.record(z.unknown()).optional(),\n});\nexport type PaymentRequirement = z.infer<typeof PaymentRequirement>;\n\n/** The full 402 body a paywalled vendor returns. */\nexport const PaymentRequired = z.object({\n x402Version: z.number(),\n accepts: z.array(PaymentRequirement).min(1),\n error: z.string().optional(),\n});\nexport type PaymentRequired = z.infer<typeof PaymentRequired>;\n\n/**\n * x402 network ids → the chains Rein governs. Testnets map to their mainnet.\n * Both v1 names (\"base-sepolia\") and v2 CAIP-2 ids (\"eip155:84532\") appear in\n * the wild, so the guard accepts either.\n */\nconst NETWORK_TO_CHAIN: Record<string, Chain> = {\n base: 'base',\n 'base-sepolia': 'base',\n 'eip155:8453': 'base',\n 'eip155:84532': 'base',\n solana: 'solana',\n 'solana-devnet': 'solana',\n polygon: 'polygon',\n 'polygon-amoy': 'polygon',\n bnb: 'bnb',\n bsc: 'bnb',\n};\n\n/** Canonical stablecoin contract addresses (EVM keys lowercased). */\nconst KNOWN_ASSET_ADDRESSES: Record<string, Asset> = {\n '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913': 'USDC', // USDC on Base\n '0x036cbd53842c5426634e7929541ec2318f3dcf7e': 'USDC', // USDC on Base Sepolia\n EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: 'USDC', // USDC on Solana\n};\n\nexport function networkToChain(network: string): Chain | undefined {\n return NETWORK_TO_CHAIN[network.toLowerCase()];\n}\n\n/**\n * Resolve a requirement's asset to a symbol Rein knows. Tries, in order: the\n * asset field as a literal symbol (mock-first), `extra.symbol`, then known\n * contract addresses (exact case for Solana, lowercased for EVM), then any\n * caller-supplied address map.\n */\nexport function resolveAsset(\n requirement: PaymentRequirement,\n extraAddresses: Record<string, Asset> = {},\n): Asset | undefined {\n const direct = Asset.safeParse(requirement.asset.toUpperCase());\n if (direct.success) return direct.data;\n\n const symbol = requirement.extra?.['symbol'];\n if (typeof symbol === 'string') {\n const fromExtra = Asset.safeParse(symbol.toUpperCase());\n if (fromExtra.success) return fromExtra.data;\n }\n\n return (\n extraAddresses[requirement.asset] ??\n extraAddresses[requirement.asset.toLowerCase()] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset.toLowerCase()]\n );\n}\n\n/**\n * Convert an atomic-unit amount to a normalized decimal string without floats,\n * e.g. (\"10000\", 6) -> \"0.01\". Stablecoins Rein supports all use 6 decimals;\n * a requirement can override via `extra.decimals`.\n */\nexport function atomicToDecimal(atomic: string, decimals: number): string {\n if (!/^\\d+$/.test(atomic)) throw new TypeError(`invalid atomic amount: ${atomic}`);\n if (decimals === 0) return atomic.replace(/^0+(?=\\d)/, '');\n const digits = atomic.padStart(decimals + 1, '0');\n const intPart = digits.slice(0, digits.length - decimals).replace(/^0+(?=\\d)/, '');\n const fracPart = digits.slice(digits.length - decimals).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/**\n * The inverse of {@link atomicToDecimal}: a human-unit decimal string to atomic\n * units without floats, e.g. (\"0.05\", 6) -> \"50000\". Throws if the value has\n * more fraction digits than the asset carries (sub-atomic precision is a\n * pricing bug, not something to round silently).\n */\nexport function decimalToAtomic(decimal: string, decimals: number): string {\n if (!/^\\d+(\\.\\d+)?$/.test(decimal)) throw new TypeError(`invalid decimal amount: ${decimal}`);\n const dot = decimal.indexOf('.');\n const intPart = dot === -1 ? decimal : decimal.slice(0, dot);\n const fracPart = dot === -1 ? '' : decimal.slice(dot + 1);\n if (fracPart.length > decimals) {\n throw new TypeError(`amount ${decimal} has more than ${decimals} fraction digits`);\n }\n const atomic = intPart + fracPart.padEnd(decimals, '0');\n return atomic.replace(/^0+(?=\\d)/, '');\n}\n\nexport function requirementDecimals(requirement: PaymentRequirement): number {\n const decimals = requirement.extra?.['decimals'];\n return typeof decimals === 'number' && Number.isInteger(decimals) && decimals >= 0 ? decimals : 6;\n}\n\n/** A requirement the guard fully understood, mapped into Rein's domain. */\nexport interface ResolvedRequirement {\n requirement: PaymentRequirement;\n chain: Chain;\n asset: Asset;\n /** Human-unit decimal amount, e.g. \"0.01\". */\n amount: string;\n}\n\n/**\n * Pick the first offer the guard can govern: scheme `exact`, a network that\n * maps to a supported chain, and a resolvable asset. Returns undefined when\n * no offer qualifies — callers must treat that as fail-closed.\n */\nexport function selectRequirement(\n accepts: readonly PaymentRequirement[],\n extraAddresses: Record<string, Asset> = {},\n): ResolvedRequirement | undefined {\n for (const requirement of accepts) {\n if (requirement.scheme.toLowerCase() !== 'exact') continue;\n const chain = networkToChain(requirement.network);\n if (!chain) continue;\n const asset = resolveAsset(requirement, extraAddresses);\n if (!asset) continue;\n const amount = atomicToDecimal(requirement.maxAmountRequired, requirementDecimals(requirement));\n return { requirement, chain, asset, amount };\n }\n return undefined;\n}\n\n/** What the guard submits to the policy engine (the `/v1/evaluate` shape). */\nexport interface IntentSubmission {\n agentId: string;\n vendor: Vendor;\n resource: string;\n amount: string;\n asset: Asset;\n chain: Chain;\n taskContext?: TaskContext;\n}\n\n/** Build the evaluate payload for a resolved offer on a given request URL. */\nexport function toIntentSubmission(\n resolved: ResolvedRequirement,\n url: string,\n agentId: string,\n taskContext: TaskContext | undefined,\n): IntentSubmission {\n const parsed = new URL(url);\n return {\n agentId,\n vendor: {\n host: parsed.host,\n address: resolved.requirement.payTo,\n },\n resource: resolved.requirement.resource ?? parsed.pathname,\n amount: resolved.amount,\n asset: resolved.asset,\n chain: resolved.chain,\n taskContext,\n };\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n AgentId,\n Receipt,\n newId,\n type Asset,\n type Decision,\n type PaymentIntent,\n type ReceiptSettlement,\n type TaskContext,\n} from '@reinconsole/core';\nimport { EngineClient, type FetchLike } from './client.js';\nimport { PaymentBlockedError, UnsupportedRequirementError } from './errors.js';\nimport {\n PaymentRequired,\n selectRequirement,\n toIntentSubmission,\n type PaymentRequirement,\n} from './x402.js';\n\n/**\n * Builds the `X-PAYMENT` header for an allowed intent. Mock payers and the\n * local EIP-3009 payer ignore the decision; the session-key signer tier\n * requires it — the {intent, decision} pair is the engine-signed voucher the\n * signer verifies before any key is put to work.\n */\nexport type Payer = (\n requirement: PaymentRequirement,\n intent: PaymentIntent,\n decision: Decision,\n) => string | Promise<string>;\n\nexport interface GuardOptions {\n /** Policy engine base URL, e.g. \"http://localhost:8787\". */\n engineUrl: string;\n /** The agent this guard speaks for (must be registered with the engine). */\n agentId: string;\n /** Base fetch the guard wraps by default (vendor-facing). Defaults to global fetch. */\n fetch?: FetchLike;\n /** Transport for talking to the policy engine. Defaults to global fetch. */\n engineFetch?: FetchLike;\n /** Task context attached to every intent unless overridden via withTask(). */\n taskContext?: TaskContext;\n /**\n * What a blocked payment looks like to the caller: 'throw' (default) raises\n * PaymentBlockedError; 'respond' returns a synthetic 402 JSON response, for\n * agent loops that prefer inspecting responses over catching.\n */\n onBlocked?: 'throw' | 'respond';\n /** If set, the guard settles allowed payments itself (pay + retry). */\n payer?: Payer;\n /** Extra token-address -> symbol mappings for asset resolution. */\n assetAddresses?: Record<string, Asset>;\n /** Called once per receipt, as it is recorded. */\n onReceipt?: (receipt: Receipt) => void;\n}\n\n/**\n * The Rein guard: wrap an agent's fetch once, and every x402 paywall it hits\n * is policy-checked before any payment exists, with a receipt either way.\n *\n * Layering: the guard wraps the BASE fetch, underneath any x402 payment\n * library. The first (unpaid) request surfaces the 402; the guard evaluates\n * it and either blocks — so the payment layer never sees the paywall — or\n * releases the 402 upward. The payment layer's `X-PAYMENT` retry then flows\n * back through the guard, which attaches the settlement to the receipt.\n * Alternatively, pass a `payer` and the guard completes the payment itself.\n */\nexport class Guard {\n readonly client: EngineClient;\n private readonly options: GuardOptions;\n private readonly baseFetch: FetchLike;\n private readonly task = new AsyncLocalStorage<TaskContext>();\n private readonly log: Receipt[] = [];\n /** Allowed-but-unsettled receipts awaiting the payment layer's retry, by URL. */\n private readonly pendingByUrl = new Map<string, Receipt>();\n\n constructor(options: GuardOptions) {\n AgentId.parse(options.agentId);\n this.options = options;\n const f = options.fetch ?? globalThis.fetch;\n this.baseFetch = (input, init) => f(input, init);\n this.client = new EngineClient({ baseUrl: options.engineUrl, fetch: options.engineFetch });\n }\n\n /** Every receipt this guard has recorded, oldest first. */\n receipts(): readonly Receipt[] {\n return this.log;\n }\n\n /** Run `fn` with a task context attached to every intent submitted inside it. */\n withTask<T>(context: TaskContext, fn: () => T): T {\n return this.task.run({ ...this.options.taskContext, ...context }, fn);\n }\n\n /**\n * The one-liner: returns a fetch-compatible function that enforces policy on\n * every x402 paywall. Wraps the guard's base fetch unless one is passed.\n */\n wrap(fetchImpl?: FetchLike): FetchLike {\n const inner: FetchLike = fetchImpl ? (input, init) => fetchImpl(input, init) : this.baseFetch;\n\n return async (input, init) => {\n const url = requestUrl(input);\n // A request that already carries a payment is the release leg of an\n // intent this guard allowed — pass it through and capture settlement.\n if (readHeader(input, init, 'X-PAYMENT') !== null) {\n const res = await inner(input, init);\n this.settlePending(url, res);\n return res;\n }\n\n const res = await inner(input, init);\n if (res.status !== 402) return res;\n\n const body = await res\n .clone()\n .json()\n .catch(() => undefined);\n const parsed = PaymentRequired.safeParse(body);\n // Not an x402 paywall — nothing to govern, hand it back untouched.\n if (!parsed.success) return res;\n\n const resolved = selectRequirement(parsed.data.accepts, this.options.assetAddresses);\n if (!resolved) throw new UnsupportedRequirementError(url);\n\n const taskContext = this.task.getStore() ?? this.options.taskContext;\n const submission = toIntentSubmission(resolved, url, this.options.agentId, taskContext);\n const { intent, decision } = await this.client.evaluate(submission);\n\n if (decision.outcome !== 'allow') {\n const receipt = this.record(intent, decision, url, init);\n if (this.options.onBlocked === 'respond') return blockedResponse(receipt);\n throw new PaymentBlockedError(intent, decision, receipt);\n }\n\n if (!this.options.payer) {\n // Advisory mode: release the 402 to the payment layer above us; its\n // X-PAYMENT retry will come back through and settle the receipt.\n const receipt = this.record(intent, decision, url, init);\n this.pendingByUrl.set(url, receipt);\n return res;\n }\n\n const paymentHeader = await this.options.payer(resolved.requirement, intent, decision);\n const retry = await inner(input, withHeader(input, init, 'X-PAYMENT', paymentHeader));\n this.record(intent, decision, url, init, parseSettlement(retry));\n return retry;\n };\n }\n\n private record(\n intent: PaymentIntent,\n decision: Decision,\n url: string,\n init: RequestInit | undefined,\n settlement?: ReceiptSettlement,\n ): Receipt {\n const receipt = Receipt.parse({\n id: newId('rcp'),\n agentId: intent.agentId,\n intentId: intent.id,\n decisionId: decision.id,\n outcome: decision.outcome,\n url,\n method: init?.method ?? 'GET',\n vendorHost: intent.vendor.host,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: intent.taskContext,\n reason: decision.reason,\n settlement,\n createdAt: new Date(),\n });\n this.log.push(receipt);\n this.options.onReceipt?.(receipt);\n return receipt;\n }\n\n private settlePending(url: string, res: Response): void {\n const receipt = this.pendingByUrl.get(url);\n if (!receipt || !res.ok) return;\n const settlement = parseSettlement(res);\n if (settlement) receipt.settlement = settlement;\n this.pendingByUrl.delete(url);\n }\n}\n\n/** Convenience factory mirroring the docs: `const guard = createGuard({...})`. */\nexport function createGuard(options: GuardOptions): Guard {\n return new Guard(options);\n}\n\nfunction requestUrl(input: string | URL | Request): string {\n if (typeof input === 'string') return input;\n if (input instanceof URL) return input.toString();\n return input.url;\n}\n\nfunction readHeader(\n input: string | URL | Request,\n init: RequestInit | undefined,\n name: string,\n): string | null {\n const source = init?.headers ?? (input instanceof Request ? input.headers : undefined);\n return source === undefined ? null : new Headers(source).get(name);\n}\n\nfunction withHeader(\n input: string | URL | Request,\n init: RequestInit | undefined,\n name: string,\n value: string,\n): RequestInit {\n const headers = new Headers(\n init?.headers ?? (input instanceof Request ? input.headers : undefined),\n );\n headers.set(name, value);\n return { ...init, headers };\n}\n\n/**\n * Decode the vendor's `X-PAYMENT-RESPONSE` header (base64 JSON per the x402\n * spec; plain JSON tolerated mock-first). Absent or undecodable -> undefined.\n */\nfunction parseSettlement(res: Response): ReceiptSettlement | undefined {\n const raw = res.headers.get('X-PAYMENT-RESPONSE');\n if (raw === null) return undefined;\n let payload: unknown;\n try {\n payload = JSON.parse(raw);\n } catch {\n try {\n payload = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n return { raw };\n }\n }\n const record =\n typeof payload === 'object' && payload !== null ? (payload as Record<string, unknown>) : {};\n return {\n txHash: typeof record['transaction'] === 'string' ? record['transaction'] : undefined,\n networkId: typeof record['network'] === 'string' ? record['network'] : undefined,\n raw,\n };\n}\n\nfunction blockedResponse(receipt: Receipt): Response {\n return new Response(\n JSON.stringify({\n error: 'payment_blocked_by_rein',\n outcome: receipt.outcome,\n reason: receipt.reason,\n intentId: receipt.intentId,\n decisionId: receipt.decisionId,\n receiptId: receipt.id,\n }),\n {\n status: 402,\n headers: { 'content-type': 'application/json', 'x-rein-outcome': receipt.outcome },\n },\n );\n}\n","export type FacilitatorErrorCode =\n | 'malformed_payment'\n | 'unsupported_scheme'\n | 'unsupported_network'\n | 'unsupported_asset'\n | 'network_mismatch'\n | 'amount_mismatch'\n | 'recipient_mismatch';\n\n/** A payment the facilitator refused to settle, with a machine-readable code. */\nexport class FacilitatorError extends Error {\n constructor(\n readonly code: FacilitatorErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'FacilitatorError';\n }\n}\n","import { z } from 'zod';\nimport { FacilitatorError } from './errors.js';\n\n/**\n * Wire codecs for the two x402 headers the mock rails speak: `X-PAYMENT`\n * (agent -> vendor -> facilitator) and `X-PAYMENT-RESPONSE` (vendor -> agent).\n * Both are base64-encoded JSON per the x402 spec.\n */\n\n/** The mock `exact` scheme payload carried inside X-PAYMENT. */\nexport const MockExactPayload = z.object({\n from: z.string().min(1),\n to: z.string().min(1),\n /** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */\n value: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n asset: z.string().min(1),\n /**\n * Rein linkage: the guard's payer stamps the intent id here, the facilitator\n * memos it onto the ledger entry, and the indexer reconciles exactly. A real\n * x402 transfer authorization carries a nonce that serves the same role.\n */\n intentId: z.string().optional(),\n nonce: z.string().optional(),\n});\nexport type MockExactPayload = z.infer<typeof MockExactPayload>;\n\n/** The full X-PAYMENT header body (x402 spec v1 envelope). */\nexport const MockPaymentHeader = z.object({\n x402Version: z.literal(1),\n scheme: z.string(),\n network: z.string(),\n payload: MockExactPayload,\n});\nexport type MockPaymentHeader = z.infer<typeof MockPaymentHeader>;\n\nexport function encodePaymentHeader(header: MockPaymentHeader): string {\n return Buffer.from(JSON.stringify(header)).toString('base64');\n}\n\nexport function decodePaymentHeader(raw: string): MockPaymentHeader {\n let json: unknown;\n try {\n json = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n throw new FacilitatorError('malformed_payment', 'X-PAYMENT is not base64-encoded JSON');\n }\n const parsed = MockPaymentHeader.safeParse(json);\n if (!parsed.success) {\n throw new FacilitatorError('malformed_payment', `invalid X-PAYMENT body: ${parsed.error.message}`);\n }\n return parsed.data;\n}\n\n/** What the facilitator returns on settle; the vendor base64s it into X-PAYMENT-RESPONSE. */\nexport const SettlementResponse = z.object({\n success: z.boolean(),\n /** The tx hash on the mock ledger (the guard surfaces this on the receipt). */\n transaction: z.string(),\n network: z.string(),\n payer: z.string().optional(),\n});\nexport type SettlementResponse = z.infer<typeof SettlementResponse>;\n\nexport function encodeSettlementHeader(response: SettlementResponse): string {\n return Buffer.from(JSON.stringify(response)).toString('base64');\n}\n","import type { Asset } from '@reinconsole/core';\nimport {\n atomicToDecimal,\n networkToChain,\n requirementDecimals,\n resolveAsset,\n type PaymentRequirement,\n type Payer,\n} from '@reinconsole/sdk';\nimport { FacilitatorError } from './errors.js';\nimport { MockLedger, type LedgerEntry } from './ledger.js';\nimport {\n decodePaymentHeader,\n encodePaymentHeader,\n encodeSettlementHeader,\n type MockPaymentHeader,\n type SettlementResponse,\n} from './payload.js';\n\nexport interface MockFacilitatorOptions {\n ledger: MockLedger;\n /** Recorded on settled payments (shows up in SettledPayment.facilitator). */\n name?: string;\n /** Extra token-address -> symbol mappings, mirroring the guard's option. */\n assetAddresses?: Record<string, Asset>;\n}\n\nexport interface SettleResult {\n response: SettlementResponse;\n /** Ready-made value for the vendor's X-PAYMENT-RESPONSE header. */\n header: string;\n /** The transfer as written on the mock chain. */\n entry: LedgerEntry;\n}\n\n/**\n * The mock x402 facilitator: verifies X-PAYMENT headers and \"settles\" them by\n * writing transfers onto the mock ledger. Plays the role Coinbase's hosted\n * facilitator plays in production — vendors call `settle()`, agents pay via\n * `payerFor()`, and nothing here is Rein-privileged: settlement happens\n * whether or not a policy engine ever saw the payment. Catching the ones it\n * didn't see is the indexer's job.\n */\nexport class MockFacilitator {\n readonly name: string;\n private readonly ledger: MockLedger;\n private readonly assetAddresses: Record<string, Asset>;\n\n constructor(options: MockFacilitatorOptions) {\n this.ledger = options.ledger;\n this.name = options.name ?? 'mock-facilitator';\n this.assetAddresses = options.assetAddresses ?? {};\n }\n\n /**\n * A `Payer` for the SDK guard: builds the X-PAYMENT header for an allowed\n * intent, stamping the intent id so settlement reconciles exactly. This is\n * the plug-in point the real x402 signer replaces.\n */\n payerFor(fromAddress: string): Payer {\n return (requirement, intent) =>\n encodePaymentHeader({\n x402Version: 1,\n scheme: requirement.scheme,\n network: requirement.network,\n payload: {\n from: fromAddress,\n to: requirement.payTo,\n value: requirement.maxAmountRequired,\n asset: requirement.asset,\n intentId: intent.id,\n nonce: intent.nonce,\n },\n });\n }\n\n /** Verify an X-PAYMENT header against the requirement it claims to satisfy. */\n verify(paymentHeader: string, requirement: PaymentRequirement): MockPaymentHeader {\n const header = decodePaymentHeader(paymentHeader);\n if (header.scheme.toLowerCase() !== 'exact' || requirement.scheme.toLowerCase() !== 'exact') {\n throw new FacilitatorError(\n 'unsupported_scheme',\n `mock facilitator only settles \"exact\", got \"${header.scheme}\"/\"${requirement.scheme}\"`,\n );\n }\n if (header.network !== requirement.network) {\n throw new FacilitatorError(\n 'network_mismatch',\n `payment is on \"${header.network}\" but the requirement wants \"${requirement.network}\"`,\n );\n }\n if (!networkToChain(header.network)) {\n throw new FacilitatorError('unsupported_network', `unknown network \"${header.network}\"`);\n }\n if (header.payload.value !== requirement.maxAmountRequired) {\n throw new FacilitatorError(\n 'amount_mismatch',\n `payment of ${header.payload.value} does not match required ${requirement.maxAmountRequired}`,\n );\n }\n if (header.payload.to !== requirement.payTo) {\n throw new FacilitatorError(\n 'recipient_mismatch',\n `payment pays \"${header.payload.to}\" but the requirement pays \"${requirement.payTo}\"`,\n );\n }\n return header;\n }\n\n /**\n * Verify, then settle: write the transfer on the mock chain and return the\n * settlement response the vendor relays via X-PAYMENT-RESPONSE.\n */\n settle(paymentHeader: string, requirement: PaymentRequirement): SettleResult {\n const header = this.verify(paymentHeader, requirement);\n const chain = networkToChain(header.network);\n if (!chain) throw new FacilitatorError('unsupported_network', `unknown network \"${header.network}\"`);\n const asset = resolveAsset(requirement, this.assetAddresses);\n if (!asset) {\n throw new FacilitatorError('unsupported_asset', `cannot resolve asset \"${requirement.asset}\"`);\n }\n const entry = this.ledger.transfer({\n chain,\n asset,\n from: header.payload.from,\n to: header.payload.to,\n amount: atomicToDecimal(header.payload.value, requirementDecimals(requirement)),\n memo: header.payload.intentId,\n });\n const response: SettlementResponse = {\n success: true,\n transaction: entry.txHash,\n network: header.network,\n payer: header.payload.from,\n };\n return { response, header: encodeSettlementHeader(response), entry };\n }\n}\n","import { EventEmitter } from 'node:events';\nimport {\n ReinEvent,\n compareDecimal,\n type Agent,\n type PaymentIntent,\n type SettledPayment,\n} from '@reinconsole/core';\nimport type { LedgerEntry, MockLedger } from './ledger.js';\n\n/** The slice of the policy engine the indexer subscribes to (NATS in prod). */\nexport interface EngineEvents {\n onEvent(handler: (event: ReinEvent) => void): void;\n}\n\nexport interface MockIndexerOptions {\n ledger: MockLedger;\n /**\n * Directory of managed agents and their wallets (the agents service in\n * prod). Called per ledger entry, so agents registered later are still seen.\n */\n agents: () => readonly Agent[];\n /** Recorded as SettledPayment.facilitator on reconciled payments. */\n facilitator?: string;\n}\n\n/** A `shadow.spend` event, extracted for convenience accessors. */\nexport type ShadowSpend = Extract<ReinEvent, { type: 'shadow.spend' }>;\n\n/**\n * The mock indexer: watches the ledger and classifies every transfer that\n * leaves a managed agent wallet.\n *\n * - Matches an allowed, unsettled intent -> `payment.settled` (reconciled).\n * - No ALLOW decision behind it -> `shadow.spend` — the bypass signal that\n * catches SDK-mode evasion and drives the upgrade to the signer tier.\n *\n * Reconciliation is memo-first (the facilitator stamps the intent id onto the\n * transfer), with a fallback match on chain+asset+amount+recipient for\n * transfers that arrive without a memo. A memo that does NOT resolve to an\n * allowed unsettled intent (denied, unknown, or already settled — a replay)\n * is never fuzzy-matched: it stays a shadow spend.\n */\nexport class MockIndexer {\n private readonly options: MockIndexerOptions;\n private readonly bus = new EventEmitter();\n private readonly emitted: ReinEvent[] = [];\n /** Every intent the engine has seen, by id (from `intent.created`). */\n private readonly intents = new Map<string, PaymentIntent>();\n /** Intents with an ALLOW decision, by id. */\n private readonly allowed = new Map<string, PaymentIntent>();\n private readonly settledIntents = new Set<string>();\n\n constructor(options: MockIndexerOptions) {\n this.options = options;\n options.ledger.onEntry((entry) => this.observe(entry));\n }\n\n /** Subscribe to a policy engine's event stream to learn which intents were allowed. */\n connectEngine(engine: EngineEvents): void {\n engine.onEvent((event) => {\n if (event.type === 'intent.created') {\n this.intents.set(event.intent.id, event.intent);\n } else if (event.type === 'decision.made' && event.decision.outcome === 'allow') {\n const intent = this.intents.get(event.decision.intentId);\n if (intent) this.allowed.set(intent.id, intent);\n }\n });\n }\n\n onEvent(handler: (event: ReinEvent) => void): void {\n this.bus.on('event', handler);\n }\n\n /** Everything the indexer has emitted, oldest first. */\n events(): readonly ReinEvent[] {\n return this.emitted;\n }\n\n settledPayments(): SettledPayment[] {\n return this.emitted.flatMap((e) => (e.type === 'payment.settled' ? [e.payment] : []));\n }\n\n shadowSpends(): ShadowSpend[] {\n return this.emitted.filter((e): e is ShadowSpend => e.type === 'shadow.spend');\n }\n\n private emit(event: ReinEvent): void {\n const parsed = ReinEvent.parse(event);\n this.emitted.push(parsed);\n this.bus.emit('event', parsed);\n }\n\n private agentFor(entry: LedgerEntry): string | undefined {\n for (const agent of this.options.agents()) {\n const owns = agent.wallets.some(\n (w) => w.chain === entry.chain && sameAddress(w.address, entry.from),\n );\n if (owns) return agent.id;\n }\n return undefined;\n }\n\n private observe(entry: LedgerEntry): void {\n const agentId = this.agentFor(entry);\n // Spend from a wallet Rein does not manage is someone else's problem.\n if (!agentId) return;\n\n const intent = this.reconcile(entry, agentId);\n if (intent) {\n this.settledIntents.add(intent.id);\n this.emit({\n type: 'payment.settled',\n at: entry.at,\n payment: {\n intentId: intent.id,\n txHash: entry.txHash,\n chain: entry.chain,\n blockNumber: entry.blockNumber,\n facilitator: this.options.facilitator,\n confirmedAt: entry.at,\n },\n });\n return;\n }\n\n this.emit({\n type: 'shadow.spend',\n at: entry.at,\n agentId,\n txHash: entry.txHash,\n chain: entry.chain,\n amount: entry.amount,\n });\n }\n\n private reconcile(entry: LedgerEntry, agentId: string): PaymentIntent | undefined {\n if (entry.memo !== undefined) {\n const intent = this.allowed.get(entry.memo);\n return intent && intent.agentId === agentId && !this.settledIntents.has(intent.id)\n ? intent\n : undefined;\n }\n for (const intent of this.allowed.values()) {\n if (this.settledIntents.has(intent.id)) continue;\n if (intent.agentId !== agentId) continue;\n if (intent.chain !== entry.chain || intent.asset !== entry.asset) continue;\n if (intent.vendor.address !== entry.to) continue;\n if (compareDecimal(intent.amount, entry.amount) !== 0) continue;\n return intent;\n }\n return undefined;\n }\n}\n\n/** EVM addresses compare case-insensitively; everything else compares exact. */\nfunction sameAddress(a: string, b: string): boolean {\n if (a === b) return true;\n return a.startsWith('0x') && b.startsWith('0x') && a.toLowerCase() === b.toLowerCase();\n}\n","import { PaymentRequirement, type FetchLike } from '@reinconsole/sdk';\nimport { FacilitatorError } from './errors.js';\nimport type { MockFacilitator } from './facilitator.js';\n\nexport interface MockVendorOptions {\n facilitator: MockFacilitator;\n /** Price in atomic units (e.g. \"10000\" = 0.01 USDC at 6 decimals). */\n atomicPrice: string;\n /** Where the vendor wants to be paid. */\n payTo: string;\n network?: string;\n asset?: string;\n scheme?: string;\n /** JSON body served once payment settles. */\n body?: unknown;\n}\n\nexport interface VendorCall {\n url: string;\n payment: string | null;\n}\n\nexport interface MockVendor {\n /** Drop-in fetch for the guard's vendor-facing side. */\n fetch: FetchLike;\n /** Every request the vendor saw, in order. */\n calls: VendorCall[];\n /** The payment requirement this vendor quotes for a given URL. */\n requirementFor(url: string): PaymentRequirement;\n}\n\n/**\n * An in-process x402 vendor wired to the mock facilitator: quotes a 402 with\n * payment requirements until the request carries X-PAYMENT, then settles\n * through the facilitator (writing the transfer on the mock ledger) and serves\n * the content with the settlement in X-PAYMENT-RESPONSE. The third leg of the\n * mock rails — guard pays it, indexer watches the ledger behind it.\n */\nexport function createMockVendor(options: MockVendorOptions): MockVendor {\n const calls: VendorCall[] = [];\n\n const requirementFor = (url: string): PaymentRequirement =>\n PaymentRequirement.parse({\n scheme: options.scheme ?? 'exact',\n network: options.network ?? 'base',\n maxAmountRequired: options.atomicPrice,\n resource: new URL(url).pathname,\n payTo: options.payTo,\n asset: options.asset ?? 'USDC',\n });\n\n const paymentRequired = (url: string, error: string): Response =>\n new Response(\n JSON.stringify({ x402Version: 1, accepts: [requirementFor(url)], error }),\n { status: 402, headers: { 'content-type': 'application/json' } },\n );\n\n const fetch: FetchLike = async (input, init) => {\n const url =\n typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;\n const headers = new Headers(\n init?.headers ?? (input instanceof Request ? input.headers : undefined),\n );\n const payment = headers.get('X-PAYMENT');\n calls.push({ url, payment });\n\n if (payment === null) return paymentRequired(url, 'X-PAYMENT header is required');\n\n let settled;\n try {\n settled = options.facilitator.settle(payment, requirementFor(url));\n } catch (err) {\n if (err instanceof FacilitatorError) return paymentRequired(url, err.message);\n throw err;\n }\n return new Response(JSON.stringify(options.body ?? { ok: true }), {\n status: 200,\n headers: { 'content-type': 'application/json', 'X-PAYMENT-RESPONSE': settled.header },\n });\n };\n\n return { fetch, calls, requirementFor };\n}\n"],"mappings":"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","names":["z","z","z","z","z","z","z","z","EventEmitter","EventEmitter"]}
|
|
1
|
+
{"version":3,"sources":["../src/ledger.ts","../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/agent.ts","../../../packages/core/src/erc8004.ts","../../../packages/core/src/intent.ts","../../../packages/core/src/decision.ts","../../../packages/core/src/canonical.ts","../../../packages/core/src/session.ts","../../../packages/core/src/payment.ts","../../../packages/core/src/receipt.ts","../../../packages/core/src/gate-receipt.ts","../../../packages/core/src/policy.ts","../../../packages/core/src/reputation.ts","../../../packages/core/src/events.ts","../../../packages/sdk/src/errors.ts","../../../packages/sdk/src/client.ts","../../../packages/sdk/src/x402.ts","../../../packages/sdk/src/x402v2.ts","../../../packages/sdk/src/guard.ts","../src/errors.ts","../src/payload.ts","../src/facilitator.ts","../src/indexer.ts","../src/vendor.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\nimport { randomBytes } from 'node:crypto';\nimport { Chain, Asset, DecimalString } from '@reinconsole/core';\n\n/**\n * The simulated chain. One MockLedger plays every chain at once: entries carry\n * their `chain` tag instead of living on separate ledgers, which keeps the\n * mock world to a single object.\n *\n * Crucially, ANYONE can call `transfer()` directly — that is the bypass path.\n * An agent that pays a vendor without going through the guard still leaves a\n * ledger entry, and the indexer turns that into a `shadow.spend` event.\n */\nexport interface TransferInput {\n chain: Chain;\n asset: Asset;\n from: string;\n to: string;\n /** Human-unit decimal amount, e.g. \"0.01\". */\n amount: string;\n /** Opaque settlement memo; the mock facilitator writes the intent id here. */\n memo?: string;\n}\n\nexport interface LedgerEntry extends TransferInput {\n txHash: string;\n blockNumber: bigint;\n at: Date;\n}\n\nexport class MockLedger {\n private readonly log: LedgerEntry[] = [];\n private readonly bus = new EventEmitter();\n private height = 0n;\n\n /** Append a confirmed transfer (one entry == one tx in its own block). */\n transfer(input: TransferInput): LedgerEntry {\n const entry: LedgerEntry = {\n ...input,\n chain: Chain.parse(input.chain),\n asset: Asset.parse(input.asset),\n amount: DecimalString.parse(input.amount),\n txHash: `0x${randomBytes(32).toString('hex')}`,\n blockNumber: ++this.height,\n at: new Date(),\n };\n this.log.push(entry);\n this.bus.emit('entry', entry);\n return entry;\n }\n\n /** All transfers, oldest first. */\n entries(): readonly LedgerEntry[] {\n return this.log;\n }\n\n /** Subscribe to new transfers as they confirm (what the indexer watches). */\n onEntry(handler: (entry: LedgerEntry) => void): void {\n this.bus.on('entry', handler);\n }\n}\n","import { z } from 'zod';\n\n/**\n * Chains Rein observes/governs. x402 is multi-chain; Base and Solana ship\n * first, Polygon and BNB follow. The policy/ledger domain is rail-agnostic —\n * this enum is the only place chains are enumerated.\n */\nexport const Chain = z.enum(['base', 'solana', 'polygon', 'bnb']);\nexport type Chain = z.infer<typeof Chain>;\n\n/** Stablecoins settled over x402. */\nexport const Asset = z.enum(['USDC', 'USDT', 'EURC']);\nexport type Asset = z.infer<typeof Asset>;\n","import { z } from 'zod';\n\n/**\n * Monetary amounts in Rein are always non-negative **decimal strings**, never\n * floats. Float arithmetic silently loses precision on values like 0.1 + 0.2,\n * which is unacceptable for money. All comparison/aggregation goes through the\n * BigInt-backed helpers below.\n */\nexport const DecimalString = z\n .string()\n .regex(/^\\d+(\\.\\d+)?$/, 'must be a non-negative decimal string, e.g. \"5.00\"');\nexport type DecimalString = z.infer<typeof DecimalString>;\n\nconst DECIMAL_RE = /^\\d+(\\.\\d+)?$/;\n\nexport function isValidDecimal(value: string): boolean {\n return DECIMAL_RE.test(value);\n}\n\nfunction assertDecimal(value: string): void {\n if (!isValidDecimal(value)) {\n throw new TypeError(`invalid decimal string: ${JSON.stringify(value)}`);\n }\n}\n\nfunction fractionLength(value: string): number {\n const dot = value.indexOf('.');\n return dot === -1 ? 0 : value.length - dot - 1;\n}\n\n/** Scale a decimal string into an integer BigInt at a fixed number of fraction digits. */\nfunction toScaled(value: string, scale: number): bigint {\n const dot = value.indexOf('.');\n const intPart = dot === -1 ? value : value.slice(0, dot);\n const fracPart = dot === -1 ? '' : value.slice(dot + 1);\n const paddedFrac = (fracPart + '0'.repeat(scale)).slice(0, scale);\n return BigInt(intPart + paddedFrac);\n}\n\n/** Render a scaled BigInt back to a normalized decimal string (no trailing zeros). */\nfunction fromScaled(scaled: bigint, scale: number): string {\n if (scale === 0) return scaled.toString();\n const digits = scaled.toString().padStart(scale + 1, '0');\n const intPart = digits.slice(0, digits.length - scale);\n const fracPart = digits.slice(digits.length - scale).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/** Compare two decimal strings. Returns -1 (a<b), 0 (a==b), or 1 (a>b). */\nexport function compareDecimal(a: string, b: string): -1 | 0 | 1 {\n assertDecimal(a);\n assertDecimal(b);\n const scale = Math.max(fractionLength(a), fractionLength(b));\n const av = toScaled(a, scale);\n const bv = toScaled(b, scale);\n return av < bv ? -1 : av > bv ? 1 : 0;\n}\n\n/** Sum a list of decimal strings without floating-point error. */\nexport function sumDecimal(values: readonly string[]): string {\n if (values.length === 0) return '0';\n let scale = 0;\n for (const v of values) {\n assertDecimal(v);\n scale = Math.max(scale, fractionLength(v));\n }\n let total = 0n;\n for (const v of values) total += toScaled(v, scale);\n return fromScaled(total, scale);\n}\n\n/** Multiply two decimal strings exactly (e.g. median * \"3\" for price-sanity). */\nexport function mulDecimal(a: string, b: string): string {\n assertDecimal(a);\n assertDecimal(b);\n const scaleA = fractionLength(a);\n const scaleB = fractionLength(b);\n const product = toScaled(a, scaleA) * toScaled(b, scaleB);\n return fromScaled(product, scaleA + scaleB);\n}\n\n/** Convenience: a > b. */\nexport function gt(a: string, b: string): boolean {\n return compareDecimal(a, b) === 1;\n}\n\n/** Convenience: a < b. */\nexport function lt(a: string, b: string): boolean {\n return compareDecimal(a, b) === -1;\n}\n","/**\n * Minimal, safe glob matcher supporting only the `*` wildcard (matches any run\n * of characters, including none). Used for vendor host allowlists\n * (e.g. \"*.trusted.io\"), agent-id targeting (e.g. \"agt_research_*\"), and\n * Gate route pricing (e.g. \"/api/reports/*\").\n *\n * Deliberately NOT a regex from user input — the pattern is escaped so a\n * malicious policy value cannot inject regex behavior (ReDoS, etc.).\n */\nexport function globMatch(pattern: string, value: string): boolean {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // escape regex metachars\n const withWildcard = escaped.replace(/\\\\\\*/g, '.*'); // re-enable only `*`\n return new RegExp(`^${withWildcard}$`).test(value);\n}\n\n/** True if `value` matches any pattern in the list. */\nexport function globMatchAny(patterns: readonly string[], value: string): boolean {\n return patterns.some((p) => globMatch(p, value));\n}\n","/**\n * Minimal ULID generation, dependency-free. ULIDs are lexicographically\n * sortable (time-prefixed) and url-safe, which is why Rein uses them for all\n * primary keys instead of UUIDs. Works in Node 22 and modern browsers/edge via\n * the WebCrypto `globalThis.crypto`.\n */\n\n// Crockford's base32 alphabet (excludes I, L, O, U to avoid ambiguity).\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\nfunction encodeTime(now: number): string {\n let time = now;\n let out = '';\n for (let i = TIME_LEN - 1; i >= 0; i--) {\n out = ENCODING.charAt(time % 32) + out;\n time = Math.floor(time / 32);\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n let out = '';\n for (const byte of randomBytes(RANDOM_LEN)) {\n out += ENCODING.charAt(byte % 32);\n }\n return out;\n}\n\n/** Generate a 26-character ULID. */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime) + encodeRandom();\n}\n\n/** Generate a Stripe-style prefixed id, e.g. `newId('agt')` -> `agt_01J...`. */\nexport function newId<P extends string>(prefix: P): `${P}_${string}` {\n return `${prefix}_${ulid()}`;\n}\n","import { z } from 'zod';\n\n/** Crockford base32 ULID body (26 chars), as produced by `ulid()`. */\nconst ULID_BODY = '[0-9A-HJKMNP-TV-Z]{26}';\n\n/**\n * A zod schema for a Stripe-style prefixed ULID, e.g. `agt_01J7...`.\n * Centralizing this keeps id formats consistent across DB rows, API payloads,\n * and SDK types.\n */\nexport function prefixedId(prefix: string) {\n return z\n .string()\n .regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a \"${prefix}_\" prefixed id`);\n}\n\nexport const OrgId = prefixedId('org');\nexport const AgentId = prefixedId('agt');\nexport const PolicyId = prefixedId('pol');\nexport const IntentId = prefixedId('int');\nexport const DecisionId = prefixedId('dec');\nexport const ReceiptId = prefixedId('rcp');\nexport const SessionId = prefixedId('ses');\nexport const GateReceiptId = prefixedId('grc');\n\nexport type OrgId = z.infer<typeof OrgId>;\nexport type AgentId = z.infer<typeof AgentId>;\nexport type PolicyId = z.infer<typeof PolicyId>;\nexport type IntentId = z.infer<typeof IntentId>;\nexport type DecisionId = z.infer<typeof DecisionId>;\nexport type ReceiptId = z.infer<typeof ReceiptId>;\nexport type SessionId = z.infer<typeof SessionId>;\nexport type GateReceiptId = z.infer<typeof GateReceiptId>;\n","import { z } from 'zod';\nimport { AgentId, OrgId } from './ids.js';\nimport { Chain } from './chain.js';\n\n/**\n * Enforcement tier of a given agent wallet:\n * - `observed` — Rein sees spend on-chain but has no control (no SDK either).\n * - `sdk` — agent uses @reinconsole/sdk; advisory + observability (bypassable).\n * - `session-key` — signer-level scope; out-of-policy txs cannot be signed.\n */\nexport const EnforcementMode = z.enum(['observed', 'sdk', 'session-key']);\nexport type EnforcementMode = z.infer<typeof EnforcementMode>;\n\nexport const AgentWallet = z.object({\n chain: Chain,\n address: z.string().min(1),\n mode: EnforcementMode,\n});\nexport type AgentWallet = z.infer<typeof AgentWallet>;\n\nexport const AgentStatus = z.enum(['active', 'frozen']);\nexport type AgentStatus = z.infer<typeof AgentStatus>;\n\nexport const Agent = z.object({\n id: AgentId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** On-chain ERC-8004 identity, if the agent is registered. */\n erc8004Id: z.string().optional(),\n wallets: z.array(AgentWallet).default([]),\n status: AgentStatus.default('active'),\n createdAt: z.coerce.date(),\n});\nexport type Agent = z.infer<typeof Agent>;\n","import { z } from 'zod';\n\n/**\n * The canonical string form of an ERC-8004 agent identity:\n *\n * eip155:{chainId}:{identityRegistry}/{tokenId}\n *\n * The part before the `/` is the spec's registry reference verbatim (the\n * `agentRegistry` field of a registration file, CAIP-10 account form); the\n * tokenId is the ERC-721 id the Identity Registry minted (`agentId` in the\n * spec). This exact string is what `Agent.erc8004Id` / `Vendor.erc8004Id`\n * carry, AND the reputation-subject id a registered agent's evidence keys by.\n *\n * Casing is load-bearing: reputation subject keys for agent-kind ids are\n * case-sensitive unless they start with `0x` (see @reinconsole/graph\n * `normalizeSubject`), and an eip155 string does not. `formatErc8004Id`\n * therefore always emits the registry address in lowercase, and consumers must\n * never hand-build the string — parse then re-format to normalize.\n */\n\nexport interface Erc8004Ref {\n /** EIP-155 chain id (e.g. 8453 Base, 84532 Base Sepolia). */\n chainId: number;\n /** Identity Registry contract address, lowercase 0x-hex. */\n registry: string;\n /** ERC-721 tokenId — the spec's `agentId`. bigint: token ids exceed 2^53. */\n tokenId: bigint;\n}\n\nconst REGISTRY_PATTERN = /^0x[0-9a-fA-F]{40}$/;\nconst ID_PATTERN = /^eip155:(\\d+):(0x[0-9a-fA-F]{40})\\/(\\d+)$/;\n\n/** Build the canonical id string. Throws on a malformed ref (programmer error). */\nexport function formatErc8004Id(ref: Erc8004Ref): string {\n if (!Number.isSafeInteger(ref.chainId) || ref.chainId < 1) {\n throw new RangeError(`erc8004: bad chainId ${ref.chainId}`);\n }\n if (!REGISTRY_PATTERN.test(ref.registry)) {\n throw new RangeError(`erc8004: bad registry address ${ref.registry}`);\n }\n if (typeof ref.tokenId !== 'bigint' || ref.tokenId < 0n) {\n // The typeof guard matters for plain-JS callers: 1.5 < 0n is legal JS and\n // false, and would mint the unparseable \"…/1.5\".\n throw new RangeError(`erc8004: bad tokenId ${ref.tokenId}`);\n }\n return `eip155:${ref.chainId}:${ref.registry.toLowerCase()}/${ref.tokenId}`;\n}\n\n/**\n * Parse a canonical (or hand-written) id string. Accepts any address casing\n * and returns a lowercase ref, or undefined when malformed — so\n * `formatErc8004Id(parseErc8004Id(x)!)` is the normalization step.\n */\nexport function parseErc8004Id(value: string): Erc8004Ref | undefined {\n const match = ID_PATTERN.exec(value);\n if (!match) return undefined;\n const chainId = Number(match[1]);\n if (!Number.isSafeInteger(chainId) || chainId < 1) return undefined;\n return {\n chainId,\n registry: match[2]!.toLowerCase(),\n tokenId: BigInt(match[3]!),\n };\n}\n\n/** Strict boundary schema for the id string (the fields themselves stay free-form). */\nexport const Erc8004Id = z\n .string()\n .refine((value) => parseErc8004Id(value) !== undefined, {\n message: 'expected \"eip155:{chainId}:{registry}/{tokenId}\"',\n });\nexport type Erc8004Id = z.infer<typeof Erc8004Id>;\n","import { z } from 'zod';\nimport { AgentId, IntentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\n\nexport const Vendor = z.object({\n host: z.string().min(1),\n address: z.string().min(1),\n erc8004Id: z.string().optional(),\n});\nexport type Vendor = z.infer<typeof Vendor>;\n\n/**\n * The observability gold: links every micro-payment back to the task and run\n * that caused it, so finance teams can answer \"what was this spend for?\".\n */\nexport const TaskContext = z.object({\n taskId: z.string().optional(),\n parentRunId: z.string().optional(),\n purpose: z.string().max(500).optional(),\n});\nexport type TaskContext = z.infer<typeof TaskContext>;\n\n/**\n * A request to spend, submitted to the policy engine BEFORE any signature is\n * released. The `nonce` provides replay protection on the signer path.\n */\nexport const PaymentIntent = z.object({\n id: IntentId,\n agentId: AgentId,\n vendor: Vendor,\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n nonce: z.string().min(1),\n createdAt: z.coerce.date(),\n});\nexport type PaymentIntent = z.infer<typeof PaymentIntent>;\n","import { z } from 'zod';\nimport { DecisionId, IntentId } from './ids.js';\n\nexport const DecisionOutcome = z.enum(['allow', 'deny', 'escalate']);\nexport type DecisionOutcome = z.infer<typeof DecisionOutcome>;\n\n/**\n * The signed, hash-chained record of a single policy evaluation. Written BEFORE\n * any signature is released. `prevHash` + `hash` form a tamper-evident chain;\n * `signature` is the policy service's signing key over `hash`. The eventual\n * on-chain `txHash` is attached later by the indexer (see SettledPayment).\n */\nexport const Decision = z.object({\n id: DecisionId,\n intentId: IntentId,\n /**\n * sha256 of the intent's canonical content (see canonical.ts). Binds the\n * decision to the exact transfer it judged — amount, recipient, asset,\n * chain — so a signer can verify an {intent, decision} pair offline as a\n * self-contained spend voucher, not just a reference by id.\n */\n intentHash: z.string(),\n outcome: DecisionOutcome,\n /** Ids of the rules that fired, for explainability. */\n matchedRules: z.array(z.string()).default([]),\n /** Human-readable explanation surfaced in the dashboard. */\n reason: z.string().optional(),\n policyId: z.string(),\n policyVersion: z.string(),\n /** Hash of the previous decision in the chain (tamper-evident log). */\n prevHash: z.string(),\n /** Hash of this decision's canonical content. */\n hash: z.string(),\n /** Service signing-key signature over `hash`. */\n signature: z.string(),\n latencyMs: z.number().nonnegative(),\n decidedAt: z.coerce.date(),\n});\nexport type Decision = z.infer<typeof Decision>;\n","import type { PaymentIntent } from './intent.js';\nimport type { DecisionOutcome } from './decision.js';\n\n/**\n * Canonical byte forms shared by the policy engine (which hashes and signs\n * them) and the signer (which verifies them offline). Field order is fixed,\n * dates are ISO strings, and absent optionals are explicit nulls, so the same\n * parsed object always canonicalizes to the same bytes — including after a\n * JSON round-trip over HTTP.\n *\n * These builders are pure (no node:crypto) so @reinconsole/core stays loadable in a\n * browser; services hash the strings with whatever sha256 they have.\n */\n\n/** Canonical form of an intent — what `Decision.intentHash` commits to. */\nexport function canonicalIntent(intent: PaymentIntent): string {\n return JSON.stringify({\n id: intent.id,\n agentId: intent.agentId,\n vendor: {\n host: intent.vendor.host,\n address: intent.vendor.address,\n erc8004Id: intent.vendor.erc8004Id ?? null,\n },\n resource: intent.resource,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: {\n taskId: intent.taskContext.taskId ?? null,\n parentRunId: intent.taskContext.parentRunId ?? null,\n purpose: intent.taskContext.purpose ?? null,\n },\n nonce: intent.nonce,\n createdAt: intent.createdAt.toISOString(),\n });\n}\n\n/** The decision fields covered by `Decision.hash` (and thus its signature). */\nexport interface DecisionContent {\n intentId: string;\n intentHash: string;\n outcome: DecisionOutcome;\n matchedRules: string[];\n policyId: string;\n policyVersion: string;\n prevHash: string;\n decidedAt: Date;\n}\n\n/** Canonical form of a decision — what `Decision.hash` is computed over. */\nexport function canonicalDecision(d: DecisionContent): string {\n return JSON.stringify({\n intentId: d.intentId,\n intentHash: d.intentHash,\n outcome: d.outcome,\n matchedRules: d.matchedRules,\n policyId: d.policyId,\n policyVersion: d.policyVersion,\n prevHash: d.prevHash,\n decidedAt: d.decidedAt.toISOString(),\n });\n}\n","import { z } from 'zod';\nimport { AgentId, SessionId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * A session-key grant: the signer tier's unit of delegated authority. The\n * agent process holds only the bearer token — the wallet key never leaves the\n * signer — and the stored record keeps a hash of the token, never the token\n * itself (it is returned exactly once, at creation).\n *\n * Caps here are the signer-side backstop UNDER whatever policy says: a\n * signature is released only when the engine allowed the intent AND the\n * session has room. Amounts are decimal strings in the asset's human units.\n */\nexport const Session = z.object({\n id: SessionId,\n agentId: AgentId,\n /** sha256 hex of the bearer token. */\n tokenHash: z.string(),\n /** Cumulative ceiling across the session's lifetime. Absent = uncapped. */\n capAmount: DecimalString.optional(),\n /** Ceiling per individual signature. Absent = uncapped. */\n maxPerPayment: DecimalString.optional(),\n expiresAt: z.coerce.date(),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type Session = z.infer<typeof Session>;\n","import { z } from 'zod';\nimport { IntentId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * On-chain confirmation of a settled payment, reconciled by the indexer against\n * the originating intent (amount + recipient + nonce, or facilitator webhook).\n */\nexport const SettledPayment = z.object({\n intentId: IntentId,\n txHash: z.string(),\n chain: Chain,\n blockNumber: z.coerce.bigint(),\n facilitator: z.string().optional(),\n feePaid: DecimalString.optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettledPayment = z.infer<typeof SettledPayment>;\n","import { z } from 'zod';\nimport { ReceiptId, IntentId, DecisionId, AgentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { TaskContext } from './intent.js';\nimport { DecisionOutcome } from './decision.js';\n\n/**\n * What the SDK reports back after settlement: the `X-PAYMENT-RESPONSE` header\n * a vendor returns once payment clears. Mock facilitators fill this in v0.1;\n * the indexer reconciles it against on-chain truth later (see SettledPayment).\n */\nexport const ReceiptSettlement = z.object({\n txHash: z.string().optional(),\n networkId: z.string().optional(),\n /** Raw header payload, kept for forensics until the indexer confirms. */\n raw: z.string().optional(),\n});\nexport type ReceiptSettlement = z.infer<typeof ReceiptSettlement>;\n\n/**\n * The SDK-side record of one guarded payment attempt: which request triggered\n * it, what the engine decided, and (if allowed and paid) how it settled.\n * Receipts are the observability primitive — every 402 the guard touches\n * produces exactly one, whether the payment was allowed or blocked.\n */\nexport const Receipt = z.object({\n id: ReceiptId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n outcome: DecisionOutcome,\n /** The URL the agent actually fetched (the paywalled resource). */\n url: z.string(),\n method: z.string().default('GET'),\n vendorHost: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n /** Human-readable explanation copied from the decision. */\n reason: z.string().optional(),\n /** Present only once a payment was made and the vendor confirmed it. */\n settlement: ReceiptSettlement.optional(),\n createdAt: z.coerce.date(),\n});\nexport type Receipt = z.infer<typeof Receipt>;\n","import { z } from 'zod';\nimport { GateReceiptId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * The vendor-side twin of `Receipt`: one settled x402 payment as the GATE saw\n * it — who paid, for which priced route, and the settlement transaction. The\n * agent-side Receipt records what an agent tried to spend; a GateReceipt\n * records what a vendor actually earned.\n */\nexport const GateReceipt = z.object({\n id: GateReceiptId,\n at: z.coerce.date(),\n /** The route pattern that priced this request, e.g. \"/api/reports/*\". */\n route: z.string().min(1),\n /** The concrete resource paid for (URL path actually requested). */\n resource: z.string().min(1),\n method: z.string().min(1),\n /** The paying wallet address, as asserted by the settled payment. */\n payer: z.string().min(1),\n payTo: z.string().min(1),\n /** Human-unit decimal amount, e.g. \"0.05\". */\n amount: DecimalString,\n /** The same amount in the asset's atomic units, e.g. \"50000\". */\n amountAtomic: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n /** Token symbol or contract address, exactly as quoted in the requirement. */\n asset: z.string().min(1),\n network: z.string().min(1),\n /** Settlement transaction hash (mock ledger or on-chain). */\n transaction: z.string().min(1),\n});\nexport type GateReceipt = z.infer<typeof GateReceipt>;\n","import { z } from 'zod';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/** A rolling-window spec, e.g. \"24h\", \"1h\", \"30m\", \"7d\". */\nexport const Window = z\n .string()\n .regex(/^\\d+[smhd]$/, 'window must be like \"30s\", \"15m\", \"1h\", or \"7d\"');\nexport type Window = z.infer<typeof Window>;\n\n/** A relative multiplier, e.g. \"3x\" (used for price-sanity checks). */\nexport const Multiplier = z.string().regex(/^\\d+(\\.\\d+)?x$/, 'multiplier must be like \"3x\"');\nexport type Multiplier = z.infer<typeof Multiplier>;\n\n/**\n * The set of predicates a rule can test. Multiple predicates in one condition\n * are ANDed together. Each maps to an evaluator in the policy engine.\n */\nexport const Condition = z\n .object({\n /** Per-transaction amount exceeds this value. */\n amountGt: DecimalString.optional(),\n /** Sum of spend in a rolling window exceeds `gt`. */\n rollingSum: z.object({ window: Window, gt: DecimalString }).optional(),\n /** Transaction count in a rolling window exceeds `gt`. */\n txCount: z.object({ window: Window, gt: z.number().int().nonnegative() }).optional(),\n /** Vendor host matches one of these patterns (supports `*` globs). */\n vendorHostIn: z.array(z.string()).optional(),\n /** First time Rein has seen this vendor for the agent. */\n vendorFirstSeen: z.boolean().optional(),\n /** Vendor reputation score is below this threshold (Phase 3 hook). */\n vendorReputationLt: z.number().min(0).max(100).optional(),\n /** Amount is more than `gt`-times the observed median for this resource. */\n amountVsResourceMedian: z.object({ gt: Multiplier }).optional(),\n })\n .refine((c) => Object.values(c).some((v) => v !== undefined), {\n message: 'a condition must specify at least one predicate',\n });\nexport type Condition = z.infer<typeof Condition>;\n\n/**\n * A single rule: an id plus exactly one action (allow / deny / escalate) whose\n * value is the condition that triggers it.\n */\nexport const Rule = z\n .object({\n id: z.string().min(1),\n allow: Condition.optional(),\n deny: Condition.optional(),\n escalate: Condition.optional(),\n })\n .refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== undefined).length === 1, {\n message: 'a rule must specify exactly one of allow / deny / escalate',\n });\nexport type Rule = z.infer<typeof Rule>;\n\nexport const PolicyDefault = z.enum(['allow', 'deny']);\nexport type PolicyDefault = z.infer<typeof PolicyDefault>;\n\nexport const AppliesTo = z.object({\n /** Agent id patterns (supports `*` globs, e.g. \"agt_research_*\"). */\n agents: z.array(z.string()).optional(),\n chains: z.array(Chain).optional(),\n});\nexport type AppliesTo = z.infer<typeof AppliesTo>;\n\nexport const Escalation = z.object({\n approvers: z.array(z.string()).default([]),\n timeoutAction: PolicyDefault.default('deny'),\n timeoutMin: z.number().int().positive().default(15),\n});\nexport type Escalation = z.infer<typeof Escalation>;\n\n/**\n * A declarative, versioned, immutable-once-active policy. Evaluation order in\n * the engine is: explicit DENY > ESCALATE > ALLOW > `default`.\n */\nexport const Policy = z.object({\n policyId: z.string().min(1),\n version: z.string().default('1'),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n default: PolicyDefault.default('deny'),\n /** Below this amount, fail-open is permitted during a policy-service outage. */\n denyFloor: DecimalString.default('0.05'),\n escalation: Escalation.optional(),\n});\nexport type Policy = z.infer<typeof Policy>;\n","import { z } from 'zod';\n\nexport const ReputationSubject = z.object({\n kind: z.enum(['agent', 'vendor']),\n id: z.string(),\n});\nexport type ReputationSubject = z.infer<typeof ReputationSubject>;\n\nexport const ReputationComponents = z.object({\n volume: z.number(),\n longevity: z.number(),\n disputeRate: z.number(),\n counterpartyQuality: z.number(),\n settlementReliability: z.number(),\n});\nexport type ReputationComponents = z.infer<typeof ReputationComponents>;\n\n/**\n * A reputation score for an agent or vendor (Phase 3 — Graph). `confidence` is\n * first-class: a thin-history subject returns LOW confidence rather than a\n * misleadingly high score, so policy can avoid both false trust and unfair\n * freezing.\n */\nexport const ReputationScore = z.object({\n subject: ReputationSubject,\n score: z.number().min(0).max(100),\n components: ReputationComponents,\n confidence: z.number().min(0).max(1),\n asOf: z.coerce.date(),\n /** Hash-anchored attestation, optionally published on-chain (ERC-8004). */\n evidenceUri: z.string().optional(),\n});\nexport type ReputationScore = z.infer<typeof ReputationScore>;\n","import { z } from 'zod';\nimport { AgentId, DecisionId, IntentId, SessionId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { PaymentIntent } from './intent.js';\nimport { Decision } from './decision.js';\nimport { SettledPayment } from './payment.js';\nimport { GateReceipt } from './gate-receipt.js';\n\n/**\n * The canonical event envelope published on the bus (NATS in production).\n * `shadow.spend` is emitted when the indexer sees on-chain spend from a managed\n * wallet with NO corresponding ALLOW decision — the bypass signal that catches\n * SDK-mode evasion and drives the upgrade to the signer tier.\n * `signature.released` / `signature.refused` are that tier's heartbeat: every\n * time the signer does or does not put a key to work, the bus knows why.\n * `gate.*` is the vendor side of the wire: every quote a Gate issues, every\n * payment it accepts, every payment it turns away.\n */\nexport const ReinEvent = z.discriminatedUnion('type', [\n z.object({ type: z.literal('intent.created'), at: z.coerce.date(), intent: PaymentIntent }),\n z.object({ type: z.literal('decision.made'), at: z.coerce.date(), decision: Decision }),\n z.object({ type: z.literal('payment.settled'), at: z.coerce.date(), payment: SettledPayment }),\n z.object({\n type: z.literal('shadow.spend'),\n at: z.coerce.date(),\n agentId: AgentId,\n txHash: z.string(),\n chain: Chain,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.released'),\n at: z.coerce.date(),\n sessionId: SessionId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"decision_replayed\" (see @reinconsole/signer). */\n code: z.string(),\n reason: z.string(),\n sessionId: SessionId.optional(),\n agentId: AgentId.optional(),\n intentId: IntentId.optional(),\n }),\n z.object({\n type: z.literal('gate.quoted'),\n at: z.coerce.date(),\n resource: z.string(),\n method: z.string(),\n amount: DecimalString,\n asset: z.string(),\n network: z.string(),\n }),\n z.object({ type: z.literal('gate.settled'), at: z.coerce.date(), receipt: GateReceipt }),\n z.object({\n type: z.literal('gate.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"payment_replayed\" (see @reinconsole/gate). */\n code: z.string(),\n reason: z.string(),\n resource: z.string(),\n /** Known only when the payment header decoded far enough to name a payer. */\n payer: z.string().optional(),\n }),\n]);\nexport type ReinEvent = z.infer<typeof ReinEvent>;\n","import type { Decision, PaymentIntent, Receipt } from '@reinconsole/core';\n\n/** Base class for everything the SDK throws, so callers can catch broadly. */\nexport class ReinError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** The policy engine answered with a non-2xx status. */\nexport class EngineError extends ReinError {\n constructor(\n readonly status: number,\n readonly body: unknown,\n message = `policy engine responded ${status}`,\n ) {\n super(message);\n }\n}\n\n/**\n * The engine evaluated the intent and did NOT allow it (deny or escalate —\n * v0.1 blocks both; escalation approval flows land later). The payment was\n * never constructed, so no funds moved. Carries the full evidence trail.\n */\nexport class PaymentBlockedError extends ReinError {\n constructor(\n readonly intent: PaymentIntent,\n readonly decision: Decision,\n readonly receipt: Receipt,\n ) {\n super(\n `rein blocked payment of ${intent.amount} ${intent.asset} to ${intent.vendor.host}: ` +\n `${decision.outcome}${decision.reason ? ` (${decision.reason})` : ''}`,\n );\n }\n}\n\n/**\n * The vendor's 402 was x402-shaped but offered no requirement the guard can\n * govern (unknown scheme/network/asset). The guard fails closed rather than\n * letting an ungoverned payment through.\n */\nexport class UnsupportedRequirementError extends ReinError {\n constructor(readonly url: string) {\n super(`no supported x402 payment requirement in 402 from ${url}; failing closed`);\n }\n}\n","import { z } from 'zod';\nimport { Agent, Decision, PaymentIntent, Policy } from '@reinconsole/core';\nimport { EngineError } from './errors.js';\nimport type { IntentSubmission } from './x402.js';\n\n/** Any fetch-compatible function (global fetch, undici, or a test double). */\nexport type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;\n\nconst Health = z.object({ status: z.string(), publicKey: z.string() });\nconst EvaluateResponse = z.object({ intent: PaymentIntent, decision: Decision });\nexport type EvaluateResponse = z.infer<typeof EvaluateResponse>;\n\nexport interface EngineClientOptions {\n /** Base URL of the policy engine, e.g. \"http://localhost:8787\". */\n baseUrl: string;\n /** Override the transport (tests, custom agents). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\n/**\n * Thin typed client for the policy-engine HTTP API. Every response is parsed\n * through the @reinconsole/core schemas, so wire drift fails loudly at the boundary.\n */\nexport class EngineClient {\n private readonly baseUrl: string;\n private readonly fetchImpl: FetchLike;\n\n constructor(options: EngineClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '');\n const f = options.fetch ?? globalThis.fetch;\n this.fetchImpl = (input, init) => f(input, init);\n }\n\n private async request<T>(\n method: string,\n path: string,\n schema: z.ZodType<T, z.ZodTypeDef, unknown>,\n body?: unknown,\n ): Promise<T> {\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n headers: body === undefined ? undefined : { 'content-type': 'application/json' },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n if (!res.ok) {\n const payload = await res\n .clone()\n .json()\n .catch(() => res.text().catch(() => undefined));\n throw new EngineError(res.status, payload);\n }\n if (res.status === 204) return schema.parse(undefined);\n return schema.parse(await res.json());\n }\n\n health(): Promise<z.infer<typeof Health>> {\n return this.request('GET', '/health', Health);\n }\n\n registerAgent(input: {\n orgId: string;\n name: string;\n erc8004Id?: string;\n wallets?: Agent['wallets'];\n }): Promise<Agent> {\n return this.request('POST', '/v1/agents', Agent, input);\n }\n\n listAgents(): Promise<Agent[]> {\n return this.request('GET', '/v1/agents', z.array(Agent));\n }\n\n freeze(agentId: string): Promise<void> {\n return this.request('POST', `/v1/agents/${agentId}/freeze`, z.void());\n }\n\n unfreeze(agentId: string): Promise<void> {\n return this.request('POST', `/v1/agents/${agentId}/unfreeze`, z.void());\n }\n\n addPolicy(policy: z.input<typeof Policy>): Promise<Policy> {\n return this.request('POST', '/v1/policies', Policy, policy);\n }\n\n listPolicies(): Promise<Policy[]> {\n return this.request('GET', '/v1/policies', z.array(Policy));\n }\n\n /** The hot path: submit an intent, get the normalized intent + signed decision. */\n evaluate(submission: IntentSubmission): Promise<EvaluateResponse> {\n return this.request('POST', '/v1/evaluate', EvaluateResponse, submission);\n }\n\n decisions(): Promise<Decision[]> {\n return this.request('GET', '/v1/decisions', z.array(Decision));\n }\n}\n","import { z } from 'zod';\nimport { Chain, Asset, type TaskContext, type Vendor } from '@reinconsole/core';\n\n/**\n * x402 wire shapes (spec v1), mock-first: these schemas are what Rein's mock\n * facilitator and tests speak today, and they track the published x402 spec so\n * real vendors parse identically when the live integration lands.\n */\n\n/** One way to pay, as offered inside a 402 response body. */\nexport const PaymentRequirement = z.object({\n scheme: z.string(),\n network: z.string(),\n /** Amount in the asset's atomic units (e.g. \"10000\" = 0.01 USDC at 6 decimals). */\n maxAmountRequired: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n resource: z.string().optional(),\n description: z.string().optional(),\n mimeType: z.string().optional(),\n payTo: z.string().min(1),\n maxTimeoutSeconds: z.number().optional(),\n /** Token contract address — or, mock-first, a plain symbol like \"USDC\". */\n asset: z.string().min(1),\n extra: z.record(z.unknown()).optional(),\n});\nexport type PaymentRequirement = z.infer<typeof PaymentRequirement>;\n\n/** The full 402 body a paywalled vendor returns. */\nexport const PaymentRequired = z.object({\n x402Version: z.number(),\n accepts: z.array(PaymentRequirement).min(1),\n error: z.string().optional(),\n});\nexport type PaymentRequired = z.infer<typeof PaymentRequired>;\n\n/**\n * x402 network ids → the chains Rein governs. Testnets map to their mainnet.\n * Both v1 names (\"base-sepolia\") and v2 CAIP-2 ids (\"eip155:84532\") appear in\n * the wild, so the guard accepts either.\n */\nconst NETWORK_TO_CHAIN: Record<string, Chain> = {\n base: 'base',\n 'base-sepolia': 'base',\n 'eip155:8453': 'base',\n 'eip155:84532': 'base',\n solana: 'solana',\n 'solana-devnet': 'solana',\n polygon: 'polygon',\n 'polygon-amoy': 'polygon',\n bnb: 'bnb',\n bsc: 'bnb',\n};\n\n/** Canonical stablecoin contract addresses (EVM keys lowercased). */\nconst KNOWN_ASSET_ADDRESSES: Record<string, Asset> = {\n '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913': 'USDC', // USDC on Base\n '0x036cbd53842c5426634e7929541ec2318f3dcf7e': 'USDC', // USDC on Base Sepolia\n EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: 'USDC', // USDC on Solana\n};\n\nexport function networkToChain(network: string): Chain | undefined {\n return NETWORK_TO_CHAIN[network.toLowerCase()];\n}\n\n/**\n * Resolve a requirement's asset to a symbol Rein knows. Tries, in order: the\n * asset field as a literal symbol (mock-first), `extra.symbol`, then known\n * contract addresses (exact case for Solana, lowercased for EVM), then any\n * caller-supplied address map.\n */\nexport function resolveAsset(\n requirement: PaymentRequirement,\n extraAddresses: Record<string, Asset> = {},\n): Asset | undefined {\n const direct = Asset.safeParse(requirement.asset.toUpperCase());\n if (direct.success) return direct.data;\n\n const symbol = requirement.extra?.['symbol'];\n if (typeof symbol === 'string') {\n const fromExtra = Asset.safeParse(symbol.toUpperCase());\n if (fromExtra.success) return fromExtra.data;\n }\n\n return (\n extraAddresses[requirement.asset] ??\n extraAddresses[requirement.asset.toLowerCase()] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset.toLowerCase()]\n );\n}\n\n/**\n * Convert an atomic-unit amount to a normalized decimal string without floats,\n * e.g. (\"10000\", 6) -> \"0.01\". Stablecoins Rein supports all use 6 decimals;\n * a requirement can override via `extra.decimals`.\n */\nexport function atomicToDecimal(atomic: string, decimals: number): string {\n if (!/^\\d+$/.test(atomic)) throw new TypeError(`invalid atomic amount: ${atomic}`);\n if (decimals === 0) return atomic.replace(/^0+(?=\\d)/, '');\n const digits = atomic.padStart(decimals + 1, '0');\n const intPart = digits.slice(0, digits.length - decimals).replace(/^0+(?=\\d)/, '');\n const fracPart = digits.slice(digits.length - decimals).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/**\n * The inverse of {@link atomicToDecimal}: a human-unit decimal string to atomic\n * units without floats, e.g. (\"0.05\", 6) -> \"50000\". Throws if the value has\n * more fraction digits than the asset carries (sub-atomic precision is a\n * pricing bug, not something to round silently).\n */\nexport function decimalToAtomic(decimal: string, decimals: number): string {\n if (!/^\\d+(\\.\\d+)?$/.test(decimal)) throw new TypeError(`invalid decimal amount: ${decimal}`);\n const dot = decimal.indexOf('.');\n const intPart = dot === -1 ? decimal : decimal.slice(0, dot);\n const fracPart = dot === -1 ? '' : decimal.slice(dot + 1);\n if (fracPart.length > decimals) {\n throw new TypeError(`amount ${decimal} has more than ${decimals} fraction digits`);\n }\n const atomic = intPart + fracPart.padEnd(decimals, '0');\n return atomic.replace(/^0+(?=\\d)/, '');\n}\n\nexport function requirementDecimals(requirement: PaymentRequirement): number {\n const decimals = requirement.extra?.['decimals'];\n return typeof decimals === 'number' && Number.isInteger(decimals) && decimals >= 0 ? decimals : 6;\n}\n\n/** A requirement the guard fully understood, mapped into Rein's domain. */\nexport interface ResolvedRequirement {\n requirement: PaymentRequirement;\n chain: Chain;\n asset: Asset;\n /** Human-unit decimal amount, e.g. \"0.01\". */\n amount: string;\n}\n\n/**\n * Pick the first offer the guard can govern: scheme `exact`, a network that\n * maps to a supported chain, and a resolvable asset. Returns undefined when\n * no offer qualifies — callers must treat that as fail-closed.\n */\nexport function selectRequirement(\n accepts: readonly PaymentRequirement[],\n extraAddresses: Record<string, Asset> = {},\n): ResolvedRequirement | undefined {\n for (const requirement of accepts) {\n if (requirement.scheme.toLowerCase() !== 'exact') continue;\n const chain = networkToChain(requirement.network);\n if (!chain) continue;\n const asset = resolveAsset(requirement, extraAddresses);\n if (!asset) continue;\n const amount = atomicToDecimal(requirement.maxAmountRequired, requirementDecimals(requirement));\n return { requirement, chain, asset, amount };\n }\n return undefined;\n}\n\n/** What the guard submits to the policy engine (the `/v1/evaluate` shape). */\nexport interface IntentSubmission {\n agentId: string;\n vendor: Vendor;\n resource: string;\n amount: string;\n asset: Asset;\n chain: Chain;\n taskContext?: TaskContext;\n}\n\n/** Build the evaluate payload for a resolved offer on a given request URL. */\nexport function toIntentSubmission(\n resolved: ResolvedRequirement,\n url: string,\n agentId: string,\n taskContext: TaskContext | undefined,\n): IntentSubmission {\n const parsed = new URL(url);\n return {\n agentId,\n vendor: {\n host: parsed.host,\n address: resolved.requirement.payTo,\n },\n resource: resolved.requirement.resource ?? parsed.pathname,\n amount: resolved.amount,\n asset: resolved.asset,\n chain: resolved.chain,\n taskContext,\n };\n}\n","import { z } from 'zod';\nimport { PaymentRequirement } from './x402.js';\n\n/**\n * x402 v2 wire dialect — CAIP-2 network ids, `PAYMENT-REQUIRED` /\n * `PAYMENT-SIGNATURE` / `PAYMENT-RESPONSE` headers, base64-JSON payloads.\n * Verified against the published spec (coinbase/x402\n * specs/x402-specification-v2.md + transports-v2/http.md, re-checked 2026-07)\n * and the live facilitator's /supported.\n *\n * Rein's internal requirement shape stays v1 (the zod contract in x402.ts);\n * v2 is a WIRE dialect converted at the edges. Inbound, the guard converts a\n * PAYMENT-REQUIRED quote into internal requirements. Outbound, it REWRAPS the\n * payer's v1 X-PAYMENT envelope into the v2 PaymentPayload: the scheme payload\n * (e.g. the signed EIP-3009 authorization) is byte-identical in both dialects,\n * so every Payer — mock, EIP-3009, session-signer — is v2-capable without\n * knowing v2 exists. The vendor side (@reinconsole/gate) re-exports these\n * helpers rather than owning its own copies.\n */\n\n/**\n * Known v1 network names → CAIP-2. EVM entries are chain-id math; the Solana\n * ids are what the live facilitator advertises. Unknown names pass through\n * lowercased, so two spellings of an UNKNOWN network still compare equal.\n */\nconst CAIP2_ALIASES: Record<string, string> = {\n base: 'eip155:8453',\n 'base-sepolia': 'eip155:84532',\n polygon: 'eip155:137',\n 'polygon-amoy': 'eip155:80002',\n bnb: 'eip155:56',\n bsc: 'eip155:56',\n solana: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n 'solana-devnet': 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n};\n\n/** The CAIP-2 id for a network name, or the lowercased name when unknown. */\nexport function caip2Of(network: string): string {\n const key = network.toLowerCase();\n return CAIP2_ALIASES[key] ?? key;\n}\n\n/** Do two network ids name the same chain, across the v1/CAIP-2 divide? */\nexport function sameNetwork(a: string, b: string): boolean {\n return caip2Of(a) === caip2Of(b);\n}\n\n/** x402 v2 PaymentRequirements (one entry of a 402's `accepts`). */\nexport const PaymentRequirementsV2 = z.object({\n scheme: z.string(),\n /** CAIP-2, e.g. \"eip155:84532\". */\n network: z.string(),\n /** Atomic units — v2's rename of v1's maxAmountRequired. */\n amount: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n asset: z.string().min(1),\n payTo: z.string().min(1),\n maxTimeoutSeconds: z.number().optional(),\n extra: z.record(z.unknown()).optional(),\n});\nexport type PaymentRequirementsV2 = z.infer<typeof PaymentRequirementsV2>;\n\n/** v2 ResourceInfo — resource facts move out of the requirement in v2. */\nexport const ResourceInfoV2 = z.object({\n url: z.string(),\n description: z.string().optional(),\n mimeType: z.string().optional(),\n});\nexport type ResourceInfoV2 = z.infer<typeof ResourceInfoV2>;\n\n/** v2 PaymentRequired — the decoded PAYMENT-REQUIRED header. */\nexport const PaymentRequiredV2 = z.object({\n x402Version: z.literal(2),\n error: z.string().optional(),\n resource: ResourceInfoV2.optional(),\n accepts: z.array(PaymentRequirementsV2).min(1),\n extensions: z.record(z.unknown()).optional(),\n});\nexport type PaymentRequiredV2 = z.infer<typeof PaymentRequiredV2>;\n\n/** Convert Rein's internal (v1-shaped) requirement to the v2 wire shape. */\nexport function v2Requirements(requirement: PaymentRequirement): PaymentRequirementsV2 {\n return {\n scheme: requirement.scheme,\n network: caip2Of(requirement.network),\n amount: requirement.maxAmountRequired,\n asset: requirement.asset,\n payTo: requirement.payTo,\n ...(requirement.maxTimeoutSeconds !== undefined\n ? { maxTimeoutSeconds: requirement.maxTimeoutSeconds }\n : {}),\n ...(requirement.extra ? { extra: requirement.extra } : {}),\n };\n}\n\n/**\n * The inverse: a v2 offer (plus the 402's shared ResourceInfo) as an internal\n * requirement. The CAIP-2 network id is kept verbatim — networkToChain and\n * chainIdForNetwork resolve both dialects, and sameNetwork compares across\n * them, so nothing downstream needs the v1 spelling back.\n */\nexport function requirementFromV2(\n offer: PaymentRequirementsV2,\n resource?: ResourceInfoV2,\n): PaymentRequirement {\n return PaymentRequirement.parse({\n scheme: offer.scheme,\n network: offer.network,\n maxAmountRequired: offer.amount,\n payTo: offer.payTo,\n asset: offer.asset,\n ...(resource !== undefined ? { resource: resource.url } : {}),\n ...(resource?.description !== undefined ? { description: resource.description } : {}),\n ...(resource?.mimeType !== undefined ? { mimeType: resource.mimeType } : {}),\n ...(offer.maxTimeoutSeconds !== undefined\n ? { maxTimeoutSeconds: offer.maxTimeoutSeconds }\n : {}),\n ...(offer.extra ? { extra: offer.extra } : {}),\n });\n}\n\n/** The full v2 PaymentRequired for one quoted requirement. */\nexport function buildPaymentRequiredV2(\n requirement: PaymentRequirement,\n error: string,\n): PaymentRequiredV2 {\n return {\n x402Version: 2,\n error,\n ...(requirement.resource\n ? {\n resource: {\n url: requirement.resource,\n ...(requirement.description ? { description: requirement.description } : {}),\n ...(requirement.mimeType ? { mimeType: requirement.mimeType } : {}),\n },\n }\n : {}),\n accepts: [v2Requirements(requirement)],\n extensions: {},\n };\n}\n\n/** The one codec every x402 header uses: base64 of compact JSON. */\nexport function encodeBase64Json(value: unknown): string {\n return Buffer.from(JSON.stringify(value)).toString('base64');\n}\n\n/** Base64 JSON → value, or undefined when the header is not decodable. */\nfunction decodeBase64Json(raw: string): unknown {\n try {\n return JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n return undefined;\n }\n}\n\n/**\n * Decode a PAYMENT-REQUIRED response header. Lenient by design: a missing,\n * undecodable, or non-v2 header returns undefined so callers fall back to the\n * v1 body — a garbled v2 advertisement must not break a dual-stack 402.\n */\nexport function parsePaymentRequiredHeader(raw: string | null): PaymentRequiredV2 | undefined {\n if (raw === null) return undefined;\n const parsed = PaymentRequiredV2.safeParse(decodeBase64Json(raw));\n return parsed.success ? parsed.data : undefined;\n}\n\n/** The v1 X-PAYMENT envelope, as far as the v2 rewrap needs to see it. */\nconst V1Envelope = z.object({\n x402Version: z.literal(1),\n scheme: z.string(),\n network: z.string(),\n payload: z.record(z.unknown()),\n});\n\n/**\n * Rewrap a payer's v1 X-PAYMENT header as a v2 PaymentPayload for the\n * PAYMENT-SIGNATURE header. The scheme payload transfers verbatim (what the\n * payer signed is envelope-independent); the chosen requirement rides along\n * as `accepted` per the v2 spec. A header that is already a v2 envelope\n * passes through unchanged. Throws TypeError on anything else — a payer\n * returning an unrecognizable header is a programming error, not wire input.\n */\nexport function wrapPaymentV2(\n paymentHeader: string,\n requirement: PaymentRequirement,\n resource?: ResourceInfoV2,\n): string {\n const decoded = decodeBase64Json(paymentHeader);\n if ((decoded as { x402Version?: unknown } | undefined)?.x402Version === 2) {\n return paymentHeader;\n }\n const v1 = V1Envelope.safeParse(decoded);\n if (!v1.success) {\n throw new TypeError(`cannot rewrap payment header as x402 v2: ${v1.error.message}`);\n }\n return encodeBase64Json({\n x402Version: 2,\n ...(resource !== undefined ? { resource } : {}),\n accepted: v2Requirements(requirement),\n payload: v1.data.payload,\n extensions: {},\n });\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n AgentId,\n Receipt,\n newId,\n type Asset,\n type Decision,\n type PaymentIntent,\n type ReceiptSettlement,\n type TaskContext,\n} from '@reinconsole/core';\nimport { EngineClient, type FetchLike } from './client.js';\nimport { PaymentBlockedError, UnsupportedRequirementError } from './errors.js';\nimport {\n PaymentRequired,\n selectRequirement,\n toIntentSubmission,\n type PaymentRequirement,\n type ResolvedRequirement,\n} from './x402.js';\nimport {\n parsePaymentRequiredHeader,\n requirementFromV2,\n wrapPaymentV2,\n type ResourceInfoV2,\n} from './x402v2.js';\n\n/**\n * Builds the `X-PAYMENT` header for an allowed intent. Mock payers and the\n * local EIP-3009 payer ignore the decision; the session-key signer tier\n * requires it — the {intent, decision} pair is the engine-signed voucher the\n * signer verifies before any key is put to work.\n */\nexport type Payer = (\n requirement: PaymentRequirement,\n intent: PaymentIntent,\n decision: Decision,\n) => string | Promise<string>;\n\nexport interface GuardOptions {\n /** Policy engine base URL, e.g. \"http://localhost:8787\". */\n engineUrl: string;\n /** The agent this guard speaks for (must be registered with the engine). */\n agentId: string;\n /** Base fetch the guard wraps by default (vendor-facing). Defaults to global fetch. */\n fetch?: FetchLike;\n /** Transport for talking to the policy engine. Defaults to global fetch. */\n engineFetch?: FetchLike;\n /** Task context attached to every intent unless overridden via withTask(). */\n taskContext?: TaskContext;\n /**\n * What a blocked payment looks like to the caller: 'throw' (default) raises\n * PaymentBlockedError; 'respond' returns a synthetic 402 JSON response, for\n * agent loops that prefer inspecting responses over catching.\n */\n onBlocked?: 'throw' | 'respond';\n /** If set, the guard settles allowed payments itself (pay + retry). */\n payer?: Payer;\n /** Extra token-address -> symbol mappings for asset resolution. */\n assetAddresses?: Record<string, Asset>;\n /** Called once per receipt, as it is recorded. */\n onReceipt?: (receipt: Receipt) => void;\n}\n\n/**\n * The Rein guard: wrap an agent's fetch once, and every x402 paywall it hits\n * is policy-checked before any payment exists, with a receipt either way.\n *\n * Layering: the guard wraps the BASE fetch, underneath any x402 payment\n * library. The first (unpaid) request surfaces the 402; the guard evaluates\n * it and either blocks — so the payment layer never sees the paywall — or\n * releases the 402 upward. The payment layer's `X-PAYMENT` retry then flows\n * back through the guard, which attaches the settlement to the receipt.\n * Alternatively, pass a `payer` and the guard completes the payment itself.\n */\nexport class Guard {\n readonly client: EngineClient;\n private readonly options: GuardOptions;\n private readonly baseFetch: FetchLike;\n private readonly task = new AsyncLocalStorage<TaskContext>();\n private readonly log: Receipt[] = [];\n /** Allowed-but-unsettled receipts awaiting the payment layer's retry, by URL. */\n private readonly pendingByUrl = new Map<string, Receipt>();\n\n constructor(options: GuardOptions) {\n AgentId.parse(options.agentId);\n this.options = options;\n const f = options.fetch ?? globalThis.fetch;\n this.baseFetch = (input, init) => f(input, init);\n this.client = new EngineClient({ baseUrl: options.engineUrl, fetch: options.engineFetch });\n }\n\n /** Every receipt this guard has recorded, oldest first. */\n receipts(): readonly Receipt[] {\n return this.log;\n }\n\n /** Run `fn` with a task context attached to every intent submitted inside it. */\n withTask<T>(context: TaskContext, fn: () => T): T {\n return this.task.run({ ...this.options.taskContext, ...context }, fn);\n }\n\n /**\n * The one-liner: returns a fetch-compatible function that enforces policy on\n * every x402 paywall. Wraps the guard's base fetch unless one is passed.\n */\n wrap(fetchImpl?: FetchLike): FetchLike {\n const inner: FetchLike = fetchImpl ? (input, init) => fetchImpl(input, init) : this.baseFetch;\n\n return async (input, init) => {\n const url = requestUrl(input);\n // A request that already carries a payment (either dialect's header) is\n // the release leg of an intent this guard allowed — pass it through and\n // capture settlement.\n if (\n readHeader(input, init, 'X-PAYMENT') !== null ||\n readHeader(input, init, 'PAYMENT-SIGNATURE') !== null\n ) {\n const res = await inner(input, init);\n this.settlePending(url, res);\n return res;\n }\n\n const res = await inner(input, init);\n if (res.status !== 402) return res;\n\n const paywall = await parse402(res, this.options.assetAddresses);\n // Not an x402 paywall — nothing to govern, hand it back untouched.\n if (!paywall) return res;\n\n const { resolved, wire, resource } = paywall;\n if (!resolved) throw new UnsupportedRequirementError(url);\n\n const taskContext = this.task.getStore() ?? this.options.taskContext;\n const submission = toIntentSubmission(resolved, url, this.options.agentId, taskContext);\n const { intent, decision } = await this.client.evaluate(submission);\n\n if (decision.outcome !== 'allow') {\n const receipt = this.record(intent, decision, url, init);\n if (this.options.onBlocked === 'respond') return blockedResponse(receipt);\n throw new PaymentBlockedError(intent, decision, receipt);\n }\n\n if (!this.options.payer) {\n // Advisory mode: release the 402 to the payment layer above us; its\n // X-PAYMENT retry will come back through and settle the receipt.\n const receipt = this.record(intent, decision, url, init);\n this.pendingByUrl.set(url, receipt);\n return res;\n }\n\n // The payer always produces the v1 envelope it knows; on a v2 paywall\n // the guard rewraps it (same signed payload, v2 PaymentPayload around\n // it) and pays on the v2 header. Every payer is v2-capable this way.\n const paymentHeader = await this.options.payer(resolved.requirement, intent, decision);\n const retry = await inner(\n input,\n wire === 2\n ? withHeader(\n input,\n init,\n 'PAYMENT-SIGNATURE',\n wrapPaymentV2(paymentHeader, resolved.requirement, resource),\n )\n : withHeader(input, init, 'X-PAYMENT', paymentHeader),\n );\n this.record(intent, decision, url, init, parseSettlement(retry));\n return retry;\n };\n }\n\n private record(\n intent: PaymentIntent,\n decision: Decision,\n url: string,\n init: RequestInit | undefined,\n settlement?: ReceiptSettlement,\n ): Receipt {\n const receipt = Receipt.parse({\n id: newId('rcp'),\n agentId: intent.agentId,\n intentId: intent.id,\n decisionId: decision.id,\n outcome: decision.outcome,\n url,\n method: init?.method ?? 'GET',\n vendorHost: intent.vendor.host,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: intent.taskContext,\n reason: decision.reason,\n settlement,\n createdAt: new Date(),\n });\n this.log.push(receipt);\n this.options.onReceipt?.(receipt);\n return receipt;\n }\n\n private settlePending(url: string, res: Response): void {\n const receipt = this.pendingByUrl.get(url);\n if (!receipt || !res.ok) return;\n const settlement = parseSettlement(res);\n if (settlement) receipt.settlement = settlement;\n this.pendingByUrl.delete(url);\n }\n}\n\n/** Convenience factory mirroring the docs: `const guard = createGuard({...})`. */\nexport function createGuard(options: GuardOptions): Guard {\n return new Guard(options);\n}\n\n/** What a 402 offered, in whichever dialect the guard could govern. */\ninterface ParsedPaywall {\n /** The offer the guard selected, or undefined when none qualifies. */\n resolved: ResolvedRequirement | undefined;\n /** Which wire dialect to pay on: 2 = PAYMENT-SIGNATURE, 1 = X-PAYMENT. */\n wire: 1 | 2;\n /** The v2 402's shared resource info, echoed into the payment envelope. */\n resource?: ResourceInfoV2;\n}\n\n/**\n * Read a 402 in both dialects. v2 (the PAYMENT-REQUIRED header) is preferred\n * when it carries an offer the guard can govern; otherwise the v1 body gets\n * its chance — a dual-stack vendor is served on whichever channel works.\n * Returns undefined when neither channel is x402 at all (not a paywall).\n */\nasync function parse402(\n res: Response,\n assetAddresses: Record<string, Asset> | undefined,\n): Promise<ParsedPaywall | undefined> {\n const v2 = parsePaymentRequiredHeader(res.headers.get('PAYMENT-REQUIRED'));\n if (v2) {\n const resolved = selectRequirement(\n v2.accepts.map((offer) => requirementFromV2(offer, v2.resource)),\n assetAddresses,\n );\n if (resolved) {\n return v2.resource !== undefined\n ? { resolved, wire: 2, resource: v2.resource }\n : { resolved, wire: 2 };\n }\n }\n\n const body = await res\n .clone()\n .json()\n .catch(() => undefined);\n const parsed = PaymentRequired.safeParse(body);\n if (parsed.success) {\n return { resolved: selectRequirement(parsed.data.accepts, assetAddresses), wire: 1 };\n }\n // A v2 header alone still marks this as a paywall — one the guard must\n // fail closed on if nothing in it was governable.\n return v2 ? { resolved: undefined, wire: 2 } : undefined;\n}\n\nfunction requestUrl(input: string | URL | Request): string {\n if (typeof input === 'string') return input;\n if (input instanceof URL) return input.toString();\n return input.url;\n}\n\nfunction readHeader(\n input: string | URL | Request,\n init: RequestInit | undefined,\n name: string,\n): string | null {\n const source = init?.headers ?? (input instanceof Request ? input.headers : undefined);\n return source === undefined ? null : new Headers(source).get(name);\n}\n\nfunction withHeader(\n input: string | URL | Request,\n init: RequestInit | undefined,\n name: string,\n value: string,\n): RequestInit {\n const headers = new Headers(\n init?.headers ?? (input instanceof Request ? input.headers : undefined),\n );\n headers.set(name, value);\n return { ...init, headers };\n}\n\n/**\n * Decode the vendor's settlement header — `X-PAYMENT-RESPONSE` (v1) or\n * `PAYMENT-RESPONSE` (v2); base64 JSON per the x402 spec, plain JSON\n * tolerated mock-first. Absent or undecodable -> undefined.\n */\nfunction parseSettlement(res: Response): ReceiptSettlement | undefined {\n const raw = res.headers.get('X-PAYMENT-RESPONSE') ?? res.headers.get('PAYMENT-RESPONSE');\n if (raw === null) return undefined;\n let payload: unknown;\n try {\n payload = JSON.parse(raw);\n } catch {\n try {\n payload = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n return { raw };\n }\n }\n const record =\n typeof payload === 'object' && payload !== null ? (payload as Record<string, unknown>) : {};\n return {\n // A failed v2 settle carries transaction: \"\" — no tx is no txHash.\n txHash:\n typeof record['transaction'] === 'string' && record['transaction'] !== ''\n ? record['transaction']\n : undefined,\n networkId: typeof record['network'] === 'string' ? record['network'] : undefined,\n raw,\n };\n}\n\nfunction blockedResponse(receipt: Receipt): Response {\n return new Response(\n JSON.stringify({\n error: 'payment_blocked_by_rein',\n outcome: receipt.outcome,\n reason: receipt.reason,\n intentId: receipt.intentId,\n decisionId: receipt.decisionId,\n receiptId: receipt.id,\n }),\n {\n status: 402,\n headers: { 'content-type': 'application/json', 'x-rein-outcome': receipt.outcome },\n },\n );\n}\n","export type FacilitatorErrorCode =\n | 'malformed_payment'\n | 'unsupported_scheme'\n | 'unsupported_network'\n | 'unsupported_asset'\n | 'network_mismatch'\n | 'amount_mismatch'\n | 'recipient_mismatch';\n\n/** A payment the facilitator refused to settle, with a machine-readable code. */\nexport class FacilitatorError extends Error {\n constructor(\n readonly code: FacilitatorErrorCode,\n message: string,\n ) {\n super(message);\n this.name = 'FacilitatorError';\n }\n}\n","import { z } from 'zod';\nimport { FacilitatorError } from './errors.js';\n\n/**\n * Wire codecs for the two x402 headers the mock rails speak: `X-PAYMENT`\n * (agent -> vendor -> facilitator) and `X-PAYMENT-RESPONSE` (vendor -> agent).\n * Both are base64-encoded JSON per the x402 spec.\n */\n\n/** The mock `exact` scheme payload carried inside X-PAYMENT. */\nexport const MockExactPayload = z.object({\n from: z.string().min(1),\n to: z.string().min(1),\n /** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */\n value: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n asset: z.string().min(1),\n /**\n * Rein linkage: the guard's payer stamps the intent id here, the facilitator\n * memos it onto the ledger entry, and the indexer reconciles exactly. A real\n * x402 transfer authorization carries a nonce that serves the same role.\n */\n intentId: z.string().optional(),\n nonce: z.string().optional(),\n});\nexport type MockExactPayload = z.infer<typeof MockExactPayload>;\n\n/** The full X-PAYMENT header body (x402 spec v1 envelope). */\nexport const MockPaymentHeader = z.object({\n x402Version: z.literal(1),\n scheme: z.string(),\n network: z.string(),\n payload: MockExactPayload,\n});\nexport type MockPaymentHeader = z.infer<typeof MockPaymentHeader>;\n\n/**\n * The v2 envelope (PAYMENT-SIGNATURE header): scheme/network live inside\n * `accepted` — the requirement the payer chose — around the SAME scheme\n * payload. `.passthrough()` keeps resource/extensions intact.\n */\nexport const MockPaymentHeaderV2 = z\n .object({\n x402Version: z.literal(2),\n accepted: z\n .object({\n scheme: z.string(),\n network: z.string(),\n amount: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n asset: z.string().min(1),\n payTo: z.string().min(1),\n })\n .passthrough(),\n payload: MockExactPayload,\n })\n .passthrough();\nexport type MockPaymentHeaderV2 = z.infer<typeof MockPaymentHeaderV2>;\n\n/** A payment as the facilitator sees it, whichever dialect it arrived in. */\nexport interface DecodedPayment {\n version: 1 | 2;\n scheme: string;\n network: string;\n payload: MockExactPayload;\n}\n\nexport function encodePaymentHeader(header: MockPaymentHeader): string {\n return Buffer.from(JSON.stringify(header)).toString('base64');\n}\n\nexport function decodePaymentHeader(raw: string): DecodedPayment {\n let json: unknown;\n try {\n json = JSON.parse(Buffer.from(raw, 'base64').toString('utf8'));\n } catch {\n throw new FacilitatorError('malformed_payment', 'X-PAYMENT is not base64-encoded JSON');\n }\n\n if ((json as { x402Version?: unknown } | null)?.x402Version === 2) {\n const parsed = MockPaymentHeaderV2.safeParse(json);\n if (!parsed.success) {\n throw new FacilitatorError(\n 'malformed_payment',\n `invalid v2 payment envelope: ${parsed.error.message}`,\n );\n }\n // A self-contradictory envelope (accepted terms vs transfer payload) is\n // malformed on its face — mirroring the gate's inspection.\n if (parsed.data.payload.value !== parsed.data.accepted.amount) {\n throw new FacilitatorError(\n 'malformed_payment',\n `v2 envelope contradicts itself: accepted.amount ${parsed.data.accepted.amount} vs payload value ${parsed.data.payload.value}`,\n );\n }\n return {\n version: 2,\n scheme: parsed.data.accepted.scheme,\n network: parsed.data.accepted.network,\n payload: parsed.data.payload,\n };\n }\n\n const parsed = MockPaymentHeader.safeParse(json);\n if (!parsed.success) {\n throw new FacilitatorError('malformed_payment', `invalid X-PAYMENT body: ${parsed.error.message}`);\n }\n return {\n version: 1,\n scheme: parsed.data.scheme,\n network: parsed.data.network,\n payload: parsed.data.payload,\n };\n}\n\n/** What the facilitator returns on settle; the vendor base64s it into X-PAYMENT-RESPONSE. */\nexport const SettlementResponse = z.object({\n success: z.boolean(),\n /** The tx hash on the mock ledger (the guard surfaces this on the receipt). */\n transaction: z.string(),\n network: z.string(),\n payer: z.string().optional(),\n});\nexport type SettlementResponse = z.infer<typeof SettlementResponse>;\n\nexport function encodeSettlementHeader(response: SettlementResponse): string {\n return Buffer.from(JSON.stringify(response)).toString('base64');\n}\n","import type { Asset } from '@reinconsole/core';\nimport {\n atomicToDecimal,\n networkToChain,\n requirementDecimals,\n resolveAsset,\n sameNetwork,\n type PaymentRequirement,\n type Payer,\n} from '@reinconsole/sdk';\nimport { FacilitatorError } from './errors.js';\nimport { MockLedger, type LedgerEntry } from './ledger.js';\nimport {\n decodePaymentHeader,\n encodePaymentHeader,\n encodeSettlementHeader,\n type DecodedPayment,\n type SettlementResponse,\n} from './payload.js';\n\nexport interface MockFacilitatorOptions {\n ledger: MockLedger;\n /** Recorded on settled payments (shows up in SettledPayment.facilitator). */\n name?: string;\n /** Extra token-address -> symbol mappings, mirroring the guard's option. */\n assetAddresses?: Record<string, Asset>;\n}\n\nexport interface SettleResult {\n response: SettlementResponse;\n /** Ready-made value for the vendor's X-PAYMENT-RESPONSE header. */\n header: string;\n /** The transfer as written on the mock chain. */\n entry: LedgerEntry;\n}\n\n/**\n * The mock x402 facilitator: verifies X-PAYMENT headers and \"settles\" them by\n * writing transfers onto the mock ledger. Plays the role Coinbase's hosted\n * facilitator plays in production — vendors call `settle()`, agents pay via\n * `payerFor()`, and nothing here is Rein-privileged: settlement happens\n * whether or not a policy engine ever saw the payment. Catching the ones it\n * didn't see is the indexer's job.\n */\nexport class MockFacilitator {\n readonly name: string;\n private readonly ledger: MockLedger;\n private readonly assetAddresses: Record<string, Asset>;\n\n constructor(options: MockFacilitatorOptions) {\n this.ledger = options.ledger;\n this.name = options.name ?? 'mock-facilitator';\n this.assetAddresses = options.assetAddresses ?? {};\n }\n\n /**\n * A `Payer` for the SDK guard: builds the X-PAYMENT header for an allowed\n * intent, stamping the intent id so settlement reconciles exactly. This is\n * the plug-in point the real x402 signer replaces.\n */\n payerFor(fromAddress: string): Payer {\n return (requirement, intent) =>\n encodePaymentHeader({\n x402Version: 1,\n scheme: requirement.scheme,\n network: requirement.network,\n payload: {\n from: fromAddress,\n to: requirement.payTo,\n value: requirement.maxAmountRequired,\n asset: requirement.asset,\n intentId: intent.id,\n nonce: intent.nonce,\n },\n });\n }\n\n /** Verify a payment header (either dialect) against the requirement it\n * claims to satisfy. */\n verify(paymentHeader: string, requirement: PaymentRequirement): DecodedPayment {\n const header = decodePaymentHeader(paymentHeader);\n if (header.scheme.toLowerCase() !== 'exact' || requirement.scheme.toLowerCase() !== 'exact') {\n throw new FacilitatorError(\n 'unsupported_scheme',\n `mock facilitator only settles \"exact\", got \"${header.scheme}\"/\"${requirement.scheme}\"`,\n );\n }\n // Compared through CAIP-2 normalization: a v2 envelope naming\n // \"eip155:8453\" satisfies a requirement quoted as v1's \"base\".\n if (!sameNetwork(header.network, requirement.network)) {\n throw new FacilitatorError(\n 'network_mismatch',\n `payment is on \"${header.network}\" but the requirement wants \"${requirement.network}\"`,\n );\n }\n if (!networkToChain(header.network)) {\n throw new FacilitatorError('unsupported_network', `unknown network \"${header.network}\"`);\n }\n if (header.payload.value !== requirement.maxAmountRequired) {\n throw new FacilitatorError(\n 'amount_mismatch',\n `payment of ${header.payload.value} does not match required ${requirement.maxAmountRequired}`,\n );\n }\n if (header.payload.to !== requirement.payTo) {\n throw new FacilitatorError(\n 'recipient_mismatch',\n `payment pays \"${header.payload.to}\" but the requirement pays \"${requirement.payTo}\"`,\n );\n }\n return header;\n }\n\n /**\n * Verify, then settle: write the transfer on the mock chain and return the\n * settlement response the vendor relays via X-PAYMENT-RESPONSE.\n */\n settle(paymentHeader: string, requirement: PaymentRequirement): SettleResult {\n const header = this.verify(paymentHeader, requirement);\n const chain = networkToChain(header.network);\n if (!chain) throw new FacilitatorError('unsupported_network', `unknown network \"${header.network}\"`);\n const asset = resolveAsset(requirement, this.assetAddresses);\n if (!asset) {\n throw new FacilitatorError('unsupported_asset', `cannot resolve asset \"${requirement.asset}\"`);\n }\n const entry = this.ledger.transfer({\n chain,\n asset,\n from: header.payload.from,\n to: header.payload.to,\n amount: atomicToDecimal(header.payload.value, requirementDecimals(requirement)),\n memo: header.payload.intentId,\n });\n const response: SettlementResponse = {\n success: true,\n transaction: entry.txHash,\n network: header.network,\n payer: header.payload.from,\n };\n return { response, header: encodeSettlementHeader(response), entry };\n }\n}\n","import { EventEmitter } from 'node:events';\nimport {\n ReinEvent,\n compareDecimal,\n type Agent,\n type PaymentIntent,\n type SettledPayment,\n} from '@reinconsole/core';\nimport type { LedgerEntry, MockLedger } from './ledger.js';\n\n/** The slice of the policy engine the indexer subscribes to (NATS in prod). */\nexport interface EngineEvents {\n onEvent(handler: (event: ReinEvent) => void): void;\n}\n\nexport interface MockIndexerOptions {\n ledger: MockLedger;\n /**\n * Directory of managed agents and their wallets (the agents service in\n * prod). Called per ledger entry, so agents registered later are still seen.\n */\n agents: () => readonly Agent[];\n /** Recorded as SettledPayment.facilitator on reconciled payments. */\n facilitator?: string;\n}\n\n/** A `shadow.spend` event, extracted for convenience accessors. */\nexport type ShadowSpend = Extract<ReinEvent, { type: 'shadow.spend' }>;\n\n/**\n * The mock indexer: watches the ledger and classifies every transfer that\n * leaves a managed agent wallet.\n *\n * - Matches an allowed, unsettled intent -> `payment.settled` (reconciled).\n * - No ALLOW decision behind it -> `shadow.spend` — the bypass signal that\n * catches SDK-mode evasion and drives the upgrade to the signer tier.\n *\n * Reconciliation is memo-first (the facilitator stamps the intent id onto the\n * transfer), with a fallback match on chain+asset+amount+recipient for\n * transfers that arrive without a memo. A memo that does NOT resolve to an\n * allowed unsettled intent (denied, unknown, or already settled — a replay)\n * is never fuzzy-matched: it stays a shadow spend.\n */\nexport class MockIndexer {\n private readonly options: MockIndexerOptions;\n private readonly bus = new EventEmitter();\n private readonly emitted: ReinEvent[] = [];\n /** Every intent the engine has seen, by id (from `intent.created`). */\n private readonly intents = new Map<string, PaymentIntent>();\n /** Intents with an ALLOW decision, by id. */\n private readonly allowed = new Map<string, PaymentIntent>();\n private readonly settledIntents = new Set<string>();\n\n constructor(options: MockIndexerOptions) {\n this.options = options;\n options.ledger.onEntry((entry) => this.observe(entry));\n }\n\n /** Subscribe to a policy engine's event stream to learn which intents were allowed. */\n connectEngine(engine: EngineEvents): void {\n engine.onEvent((event) => {\n if (event.type === 'intent.created') {\n this.intents.set(event.intent.id, event.intent);\n } else if (event.type === 'decision.made' && event.decision.outcome === 'allow') {\n const intent = this.intents.get(event.decision.intentId);\n if (intent) this.allowed.set(intent.id, intent);\n }\n });\n }\n\n onEvent(handler: (event: ReinEvent) => void): void {\n this.bus.on('event', handler);\n }\n\n /** Everything the indexer has emitted, oldest first. */\n events(): readonly ReinEvent[] {\n return this.emitted;\n }\n\n settledPayments(): SettledPayment[] {\n return this.emitted.flatMap((e) => (e.type === 'payment.settled' ? [e.payment] : []));\n }\n\n shadowSpends(): ShadowSpend[] {\n return this.emitted.filter((e): e is ShadowSpend => e.type === 'shadow.spend');\n }\n\n private emit(event: ReinEvent): void {\n const parsed = ReinEvent.parse(event);\n this.emitted.push(parsed);\n this.bus.emit('event', parsed);\n }\n\n private agentFor(entry: LedgerEntry): string | undefined {\n for (const agent of this.options.agents()) {\n const owns = agent.wallets.some(\n (w) => w.chain === entry.chain && sameAddress(w.address, entry.from),\n );\n if (owns) return agent.id;\n }\n return undefined;\n }\n\n private observe(entry: LedgerEntry): void {\n const agentId = this.agentFor(entry);\n // Spend from a wallet Rein does not manage is someone else's problem.\n if (!agentId) return;\n\n const intent = this.reconcile(entry, agentId);\n if (intent) {\n this.settledIntents.add(intent.id);\n this.emit({\n type: 'payment.settled',\n at: entry.at,\n payment: {\n intentId: intent.id,\n txHash: entry.txHash,\n chain: entry.chain,\n blockNumber: entry.blockNumber,\n facilitator: this.options.facilitator,\n confirmedAt: entry.at,\n },\n });\n return;\n }\n\n this.emit({\n type: 'shadow.spend',\n at: entry.at,\n agentId,\n txHash: entry.txHash,\n chain: entry.chain,\n amount: entry.amount,\n });\n }\n\n private reconcile(entry: LedgerEntry, agentId: string): PaymentIntent | undefined {\n if (entry.memo !== undefined) {\n const intent = this.allowed.get(entry.memo);\n return intent && intent.agentId === agentId && !this.settledIntents.has(intent.id)\n ? intent\n : undefined;\n }\n for (const intent of this.allowed.values()) {\n if (this.settledIntents.has(intent.id)) continue;\n if (intent.agentId !== agentId) continue;\n if (intent.chain !== entry.chain || intent.asset !== entry.asset) continue;\n if (intent.vendor.address !== entry.to) continue;\n if (compareDecimal(intent.amount, entry.amount) !== 0) continue;\n return intent;\n }\n return undefined;\n }\n}\n\n/** EVM addresses compare case-insensitively; everything else compares exact. */\nfunction sameAddress(a: string, b: string): boolean {\n if (a === b) return true;\n return a.startsWith('0x') && b.startsWith('0x') && a.toLowerCase() === b.toLowerCase();\n}\n","import {\n PaymentRequirement,\n buildPaymentRequiredV2,\n encodeBase64Json,\n type FetchLike,\n} from '@reinconsole/sdk';\nimport { FacilitatorError } from './errors.js';\nimport type { MockFacilitator } from './facilitator.js';\n\nexport interface MockVendorOptions {\n facilitator: MockFacilitator;\n /** Price in atomic units (e.g. \"10000\" = 0.01 USDC at 6 decimals). */\n atomicPrice: string;\n /** Where the vendor wants to be paid. */\n payTo: string;\n network?: string;\n asset?: string;\n scheme?: string;\n /** JSON body served once payment settles. */\n body?: unknown;\n /**\n * Which x402 dialect the vendor's 402s advertise. 'v1' (default) is the\n * classic JSON body; 'dual' adds the v2 PAYMENT-REQUIRED header beside it;\n * 'v2' advertises ONLY the header (the body is not x402) — a strict v2\n * vendor for proving clients need no v1 fallback. Payments are ACCEPTED in\n * both dialects (PAYMENT-SIGNATURE or X-PAYMENT) regardless of this option,\n * mirroring the gate.\n */\n advertise?: 'v1' | 'dual' | 'v2';\n}\n\nexport interface VendorCall {\n url: string;\n payment: string | null;\n}\n\nexport interface MockVendor {\n /** Drop-in fetch for the guard's vendor-facing side. */\n fetch: FetchLike;\n /** Every request the vendor saw, in order. */\n calls: VendorCall[];\n /** The payment requirement this vendor quotes for a given URL. */\n requirementFor(url: string): PaymentRequirement;\n}\n\n/**\n * An in-process x402 vendor wired to the mock facilitator: quotes a 402 with\n * payment requirements until the request carries a payment, then settles\n * through the facilitator (writing the transfer on the mock ledger) and serves\n * the content with the settlement in the response headers. The third leg of\n * the mock rails — guard pays it, indexer watches the ledger behind it.\n */\nexport function createMockVendor(options: MockVendorOptions): MockVendor {\n const calls: VendorCall[] = [];\n const advertise = options.advertise ?? 'v1';\n\n const requirementFor = (url: string): PaymentRequirement =>\n PaymentRequirement.parse({\n scheme: options.scheme ?? 'exact',\n network: options.network ?? 'base',\n maxAmountRequired: options.atomicPrice,\n resource: new URL(url).pathname,\n payTo: options.payTo,\n asset: options.asset ?? 'USDC',\n });\n\n const paymentRequired = (url: string, error: string): Response => {\n const requirement = requirementFor(url);\n // A strict v2 vendor's body is deliberately NOT x402 — everything the\n // protocol needs rides the PAYMENT-REQUIRED header.\n const body =\n advertise === 'v2'\n ? { error }\n : { x402Version: 1, accepts: [requirement], error };\n return new Response(JSON.stringify(body), {\n status: 402,\n headers: {\n 'content-type': 'application/json',\n ...(advertise !== 'v1'\n ? {\n 'PAYMENT-REQUIRED': encodeBase64Json(buildPaymentRequiredV2(requirement, error)),\n }\n : {}),\n },\n });\n };\n\n const fetch: FetchLike = async (input, init) => {\n const url =\n typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;\n const headers = new Headers(\n init?.headers ?? (input instanceof Request ? input.headers : undefined),\n );\n // Dual-stack: v2 payers send PAYMENT-SIGNATURE, v1 payers X-PAYMENT.\n const payment = headers.get('PAYMENT-SIGNATURE') ?? headers.get('X-PAYMENT');\n calls.push({ url, payment });\n\n if (payment === null) return paymentRequired(url, 'payment is required');\n\n let settled;\n try {\n settled = options.facilitator.settle(payment, requirementFor(url));\n } catch (err) {\n if (err instanceof FacilitatorError) return paymentRequired(url, err.message);\n throw err;\n }\n return new Response(JSON.stringify(options.body ?? { ok: true }), {\n status: 200,\n headers: {\n 'content-type': 'application/json',\n // Both dialect names carry the same base64 settlement object; the\n // strict v2 vendor sets ONLY the v2 name.\n ...(advertise !== 'v2' ? { 'X-PAYMENT-RESPONSE': settled.header } : {}),\n 'PAYMENT-RESPONSE': settled.header,\n },\n });\n };\n\n return { fetch, calls, requirementFor };\n}\n"],"mappings":"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","names":["z","z","z","z","z","z","z","z","z","z","parsed","EventEmitter","EventEmitter"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reinconsole/mock-rails",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Simulated payment rails for Rein v0.1 — mock x402 facilitator, on-chain ledger, and indexer with shadow-spend detection.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/bugiiiii11/rein#readme",
|
|
@@ -39,15 +39,15 @@
|
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"zod": "^3.24.1",
|
|
42
|
-
"@reinconsole/sdk": "^0.1.
|
|
43
|
-
"@reinconsole/core": "^0.1.
|
|
42
|
+
"@reinconsole/sdk": "^0.1.1",
|
|
43
|
+
"@reinconsole/core": "^0.1.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^22.10.0",
|
|
47
47
|
"tsup": "^8.3.5",
|
|
48
48
|
"typescript": "^5.7.2",
|
|
49
49
|
"vitest": "^2.1.8",
|
|
50
|
-
"@reinconsole/policy-engine": "0.1.
|
|
50
|
+
"@reinconsole/policy-engine": "0.1.1"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"build": "tsup",
|