@reinconsole/mock-rails 0.4.0 → 0.5.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/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { EventEmitter } from "events";
3
3
  import { randomBytes } from "crypto";
4
4
 
5
- // ../../packages/core/dist/chunk-AW74KJ6X.js
5
+ // ../../packages/core/dist/chunk-SRKPESD5.js
6
6
  import { z } from "zod";
7
7
  var ULID_BODY = "[0-9A-HJKMNP-TV-Z]{26}";
8
8
  function prefixedId(prefix) {
@@ -18,7 +18,7 @@ var SessionId = prefixedId("ses");
18
18
  var GateReceiptId = prefixedId("grc");
19
19
  var ApiKeyId = prefixedId("key");
20
20
  var ApproverKeyId = prefixedId("apk");
21
- var ApiKeyScope = z.enum(["read", "evaluate", "approve", "report", "admin"]);
21
+ var ApiKeyScope = z.enum(["read", "evaluate", "approve", "report", "identity", "admin"]);
22
22
  var ApiKey = z.object({
23
23
  id: ApiKeyId,
24
24
  name: z.string().min(1).max(200),
@@ -655,6 +655,14 @@ var Health = z3.object({
655
655
  auth: z3.string().optional(),
656
656
  approvals: z3.string().optional()
657
657
  });
658
+ var ChainVerdict = z3.object({
659
+ intact: z3.boolean(),
660
+ /** Decisions this key can see — the same number as `chainLength`. */
661
+ visible: z3.number().int().nonnegative(),
662
+ verifiedAt: z3.string(),
663
+ /** Index of the first bad link. Unscoped keys only. */
664
+ brokenAt: z3.number().int().nonnegative().optional()
665
+ });
658
666
  var EvaluateResponse = z3.object({
659
667
  intent: PaymentIntent,
660
668
  decision: Decision,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ledger.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/api-key.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.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/liveness.ts","../../../packages/core/src/approval.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/** 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');\nexport const ApiKeyId = prefixedId('key');\nexport const ApproverKeyId = prefixedId('apk');\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>;\nexport type ApiKeyId = z.infer<typeof ApiKeyId>;\nexport type ApproverKeyId = z.infer<typeof ApproverKeyId>;\n","import { z } from 'zod';\nimport { AgentId, ApiKeyId, OrgId } from './ids.js';\n\n/**\n * What a key is allowed to reach. `admin` satisfies every requirement (it is\n * the issuing/rotating key); the rest are least-privilege grants so an agent\n * runtime carrying an `evaluate` key cannot rewrite policy, and an approval\n * relay cannot read the spend history.\n *\n * `report` is the graph's ingestion grant, and it is deliberately NOT folded\n * into `evaluate`: evidence written to the reputation graph is about OTHER\n * subjects, so a fleet key that may spend its own budget has no business\n * moving a vendor's score. The engine's own reporting routes ride `evaluate`\n * because there the reporter IS the spender — that reasoning does not reach\n * across to a shared graph.\n */\nexport const ApiKeyScope = z.enum(['read', 'evaluate', 'approve', 'report', 'admin']);\nexport type ApiKeyScope = z.infer<typeof ApiKeyScope>;\n\n/**\n * The public view of an API key — everything except the secret. This is what\n * the API returns on list/issue; the secret itself is shown exactly once, at\n * issuance, and never persisted in recoverable form (see {@link ApiKeyRecord}).\n */\nexport const ApiKey = z.object({\n id: ApiKeyId,\n name: z.string().min(1).max(200),\n scopes: z.array(ApiKeyScope).min(1),\n /**\n * The org this key acts inside. ABSENT means unscoped — an operator key that\n * reads and writes across every org, which is what a self-hosted single-org\n * deployment and every env-seeded boot secret have always been. That is the\n * compatibility rule the whole tenancy design rests on: adding tenancy\n * changed no existing key's behaviour, because no existing key has this\n * field.\n *\n * Present, it is a hard confinement, not a default: the key cannot read,\n * spend, approve or govern outside the org, and a write it submits is\n * stamped with this org rather than the one the body asked for.\n */\n orgId: OrgId.optional(),\n /**\n * Narrow an org-scoped key further, to specific agents — what an agent\n * runtime should carry, so a stolen key spends one agent's budget rather\n * than the org's. Only meaningful alongside {@link ApiKey.orgId}: agent\n * narrowing without an org is refused at issuance, because the scope it\n * would describe has no org to resolve policies and approvers in.\n *\n * Capped at 64: a list long enough to need more is a fleet, and a fleet is\n * what the org scope is for.\n */\n agentIds: z.array(AgentId).max(64).optional(),\n createdAt: z.coerce.date(),\n /** Last successful authentication, for spotting keys that can be retired. */\n lastUsedAt: z.coerce.date().optional(),\n /** Set by revoke(); a revoked key never authenticates again. */\n revokedAt: z.coerce.date().optional(),\n /** Set by rotate(); with `previousSecretExpiresAt` it dates the overlap. */\n rotatedAt: z.coerce.date().optional(),\n /**\n * Past this instant the key stops authenticating, like a revoked one.\n * ABSENT means it never expires -- every key before the sandbox, and every\n * key an operator mints. Only the anonymous sandbox sets it, and a key minted\n * BY an expiring key inherits the deadline: a sandbox that could mint itself\n * a permanent key would not be a 7-day sandbox.\n */\n expiresAt: z.coerce.date().optional(),\n});\nexport type ApiKey = z.infer<typeof ApiKey>;\n\n/**\n * SERVER-SIDE ONLY. The stored form: the public record plus sha256 digests of\n * the secrets. Digests, not secrets — a stolen database yields nothing that\n * authenticates. Rotation keeps the outgoing digest alive until\n * `previousSecretExpiresAt` so a running fleet can roll over without a\n * flag-day restart; past that instant only the current secret verifies.\n *\n * This shape never leaves the engine: every route answers with {@link ApiKey}.\n */\nexport const ApiKeyRecord = ApiKey.extend({\n secretHash: z.string(),\n previousSecretHash: z.string().optional(),\n previousSecretExpiresAt: z.coerce.date().optional(),\n});\nexport type ApiKeyRecord = z.infer<typeof ApiKeyRecord>;\n\n/** Strip the digests: the only sanctioned way to put a key on the wire. */\nexport function toPublicApiKey(record: ApiKeyRecord): ApiKey {\n const { secretHash, previousSecretHash, previousSecretExpiresAt, ...pub } = record;\n void secretHash;\n void previousSecretHash;\n void previousSecretExpiresAt;\n return pub;\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/**\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/**\n * `a - b` for decimal strings, exact. Requires `a >= b`: the one caller is\n * \"how much more settled than was allowed\", and a negative money string is a\n * shape nothing else in the system accepts, so asking for one is a bug here\n * rather than a value to hand on.\n */\nexport function subDecimal(a: string, b: string): string {\n if (compareDecimal(a, b) < 0) {\n throw new RangeError(`subDecimal: ${a} is less than ${b}`);\n }\n const scale = Math.max(fractionLength(a), fractionLength(b));\n return fromScaled(toScaled(a, scale) - toScaled(b, scale), 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","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\n/**\n * A semantic grouping label, e.g. \"research\" or \"prod-trading\". Lowercase\n * slugs only — policy `appliesTo.labels` matches these (with globs), and a\n * case-normalization mismatch would silently un-target a policy.\n */\nexport const AgentLabel = z\n .string()\n .max(40)\n .regex(/^[a-z0-9][a-z0-9-]*$/, 'label must be a lowercase slug like \"research\" or \"prod-trading\"');\nexport type AgentLabel = z.infer<typeof AgentLabel>;\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 /** Semantic grouping labels — the targets of policy `appliesTo.labels`. */\n labels: z\n .array(AgentLabel)\n .max(16)\n .refine((ls) => new Set(ls).size === ls.length, { message: 'labels must be unique' })\n .default([]),\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\n/**\n * Reduce an intent's `resource` to its path for policy matching. The value is\n * vendor-declared and shape-varies: the x402 spec puts a full URL in\n * `requirement.resource`, while the guard falls back to the request pathname\n * when the vendor omits it. Policies match on the PATH so authors never need\n * to know which shape a vendor emits; host targeting stays with\n * `vendorHostIn`, which is derived from the real request URL rather than the\n * vendor's own claim. Query strings do not survive the reduction.\n */\nexport function resourcePathOf(resource: string): string {\n try {\n const url = new URL(resource);\n if (url.protocol === 'http:' || url.protocol === 'https:') return url.pathname;\n } catch {\n // Not a URL — already a bare path.\n }\n return resource;\n}\n","import { z } from 'zod';\nimport { AgentId, 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\n/**\n * A decision as `GET /v1/decisions` serves it (0.3.0): the signed record plus\n * `agentId`, the agent whose intent it judged.\n *\n * `agentId` is an ENVELOPE field -- the engine's own attribution, outside\n * `hash` and `signature`, so a verified chain vouches for nothing about it.\n * Putting it inside would have changed the hash of every future decision and\n * split the chain into two formats. It is here for a reconciler that is not\n * co-located with the agent: `reconcile()` needs an allowed intent's agent,\n * or agent B's payment against A's intent is credited to A (S74), and before\n * this field only `/v1/reconciliation` carried it -- and erases it the moment\n * a settlement lands. Absent on an unattributed (pre-tenancy) row.\n */\nexport const AttributedDecision = Decision.extend({ agentId: AgentId.optional() });\nexport type AttributedDecision = z.infer<typeof AttributedDecision>;\n","import type { PaymentIntent } from './intent.js';\nimport type { DecisionOutcome } from './decision.js';\nimport type { ApprovalVerdict } from './approval.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\n/** The fields an approval signature commits to. */\nexport interface ApprovalContent {\n decisionId: string;\n intentHash: string;\n verdict: ApprovalVerdict;\n}\n\n/**\n * Canonical form of an approval — the exact bytes an approver signs.\n *\n * Three properties are deliberate. The leading `rein` domain tag separates\n * this signature space from the decision log's, so a decision signature can\n * never be replayed as an approval or the reverse. `decisionId` makes each\n * challenge single-use: one escalation, one decision id, one signature that\n * means anything. And `verdict` is INSIDE the signed bytes — without it, a\n * captured approval could be resubmitted as a rejection (or vice versa) by\n * anyone who saw it in flight.\n */\nexport function canonicalApproval(a: ApprovalContent): string {\n return JSON.stringify({\n rein: 'approval/v1',\n decisionId: a.decisionId,\n intentHash: a.intentHash,\n verdict: a.verdict,\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\n/**\n * A report that an allowed intent's payment actually landed — the settlement\n * half of reconciliation (\"allowed but never settled\", B1).\n *\n * Deliberately looser than {@link SettledPayment}: the on-chain confirmation\n * requires a tx hash and a block, while a REPORT is whatever the observer\n * could see. A vendor's `X-PAYMENT-RESPONSE` names a transaction but no block;\n * a facilitator webhook may name neither. Demanding the strong shape would\n * mean the weakest observers — the ones a deployment actually has — could\n * report nothing at all, and every allowance would read as a gap.\n *\n * `source` records WHO said so, because the evidence is not all equal: an\n * independent indexer watching the chain is the strong claim, while a guard\n * reporting on its own payment is the agent vouching for itself. Nothing here\n * grants authority — a settlement report can only ever CLOSE a gap in the\n * reconciliation report, never authorize a payment or alter a decision.\n */\nexport const SettlementReport = z.object({\n intentId: IntentId,\n /** The settling transaction, when the observer saw one. */\n txHash: z.string().optional(),\n chain: Chain.optional(),\n /** The amount as SETTLED, when known — may differ from the amount allowed. */\n amount: DecimalString.optional(),\n /** Free-form observer tag, e.g. \"indexer\", \"guard\", \"facilitator\". */\n source: z.string().min(1).max(64).optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettlementReport = z.infer<typeof SettlementReport>;\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 { OrgId } from './ids.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 /**\n * Resource PATH matches one of these patterns (supports `*` globs, e.g.\n * \"/v1/reports/*\"). A full-URL resource is reduced to its pathname before\n * matching (see `resourcePathOf`), so the same pattern works whether the\n * vendor declares \"https://api.x.com/v1/answer\" or \"/v1/answer\". Pair\n * with `vendorHostIn` to scope a path rule to specific vendors.\n */\n resourceIn: 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 * Cumulative spend attributed to THIS intent's `taskContext.taskId`\n * (prior spend on the task plus this payment) exceeds `gt`. Scopes a\n * budget to one unit of work rather than to a window: a research run that\n * is meant to cost a dollar cannot quietly cost fifty, however slowly.\n *\n * An intent carrying no `taskId` cannot be attributed to a task, so the\n * predicate never triggers for one. Requiring attribution is a separate,\n * deliberate rule (deny on `taskIdMissing`), not a side effect of setting\n * a budget — otherwise every untagged probe payment would trip every\n * task budget in the policy.\n */\n taskBudget: z.object({ gt: DecimalString }).optional(),\n /** The intent carries no `taskContext.taskId` (or an empty one). */\n taskIdMissing: z.boolean().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 behavioral circuit breaker: one primitive with three tripwires — a window\n * (rate), a transaction count, and a value cap — measured over the agent's\n * own recent activity.\n *\n * A breaker is not a rule. Rules ask about the intent in front of them; a\n * breaker asks whether the agent's BEHAVIOR has left the envelope it was\n * given, and once it has, every subsequent intent ESCALATES for a signed\n * approval. It never denies on its own: an agent that trips a breaker in the\n * middle of a job must be able to be waved through by a human, because a\n * silent deny at the wrong moment strands the work with no path forward and\n * no one told (the failure mode Flash's exit paths taught).\n *\n * Reset happens two ways, and they are one mechanism: the window rolling\n * forward, or a signed approval, which moves the breaker's counting floor to\n * now. Nothing \"un-trips\" a breaker by decree — the activity simply stops\n * being inside the measured span.\n *\n * Targeting is the policy's job: `appliesTo.agents` / `appliesTo.labels`\n * decide WHICH agents carry the breaker. COUNTING is always per agent — a\n * breaker pooled across every agent sharing a label needs a cross-agent\n * aggregate the per-agent spend context cannot express, and is deferred.\n */\nexport const Breaker = z\n .object({\n id: z.string().min(1),\n /** The trailing span the tripwires measure over. */\n window: Window,\n /**\n * Trip when the window would hold MORE than this many transactions.\n * `10` permits ten in the window and escalates the eleventh.\n */\n txCount: z.number().int().positive().optional(),\n /**\n * Trip when the window's spend would exceed this total. `\"50.00\"` permits\n * a window totalling exactly 50.00 and escalates the payment that would\n * carry it past. Prospective, like every other spend predicate: the\n * payment that would breach the cap is the one that escalates, rather\n * than the innocent one after it.\n */\n valueCap: DecimalString.optional(),\n })\n .refine((b) => b.txCount !== undefined || b.valueCap !== undefined, {\n message: 'a breaker must specify at least one of txCount / valueCap',\n });\nexport type Breaker = z.infer<typeof Breaker>;\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 /**\n * Agent label patterns (supports `*` globs) — semantic targeting. Matches\n * when the agent carries at least one label matching any pattern. Requires\n * the agent DOCUMENT: an intent from an unregistered agent never matches a\n * labels-targeted policy (and so fails closed when no other policy applies).\n */\n labels: 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 /**\n * The org this policy governs. ABSENT means GLOBAL — it is considered for\n * every agent, which is what every policy written before tenancy existed is\n * and stays.\n *\n * This is separate from {@link AppliesTo} on purpose, and it has to be:\n * `appliesTo: {}` matches every agent, so a tenant's policy carrying the\n * default targeting would otherwise govern other tenants' agents the moment\n * it was written. Org scoping is applied BEFORE targeting — a policy whose\n * `orgId` is not the agent's org is not a candidate at all.\n */\n orgId: OrgId.optional(),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n /**\n * Behavioral breakers evaluated alongside the rules. A tripped breaker\n * escalates at the same precedence as an `escalate` rule — so an explicit\n * DENY still wins, and an ALLOW rule cannot wave past a tripped breaker.\n */\n breakers: z.array(Breaker).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';\nimport { AgentId } from './ids.js';\nimport { Window } from './policy.js';\n\n/**\n * Dead-man monitoring: the alarm for an agent that stopped (Phase B2).\n *\n * Every other control in Rein answers \"should this payment happen?\". This one\n * answers the question nothing else in the stack asks: an agent that has gone\n * quiet raises no intent, breaks no budget, and trips no breaker — it simply\n * disappears, and a control plane watching only for bad payments will report\n * a perfectly clean month while the work silently stopped being done. (Flash\n * lost four detectors this way, none of which announced anything.)\n *\n * Three rules hold the design honest, and each is the direct mirror of a rule\n * B1 already established:\n *\n * 1. An expectation is DECLARED, never inferred. Most agents are episodic:\n * they run when there is work. Silence is only evidence for an agent\n * somebody said should be periodic, so an unwatched agent has no liveness\n * state at all — the same rule as `taskBudget`, which never fires on an\n * intent that carries no task id.\n * 2. Silence has an AGE, not a boolean — `late` before `missing` — exactly as\n * a missing settlement is `in-flight` before it is `unsettled`.\n * 3. The engine never alarms about silence it did not witness. An engine that\n * was down cannot tell a dead agent from its own outage, so a silence\n * older than this process reads `unknown` until the process has been up\n * long enough to certify it. B1 refuses to manufacture gaps out of records\n * it cannot join; this refuses to manufacture alarms out of downtime.\n *\n * Liveness is observability and carries no authority whatsoever: it cannot\n * deny, escalate, freeze, or alter any decision. A missing agent is news for\n * a human, not an input to policy.\n */\n\n/** How the engine came to know an agent was alive. */\nexport const LivenessSource = z.enum([\n /** It submitted an intent — ANY outcome, including a denial. */\n 'intent',\n /** It reported in explicitly, having nothing to buy. */\n 'heartbeat',\n]);\nexport type LivenessSource = z.infer<typeof LivenessSource>;\n\n/** Default slack past the interval before silence becomes an alarm. */\nexport const DEFAULT_LIVENESS_GRACE_MS = 60_000;\n\n/**\n * \"This agent is supposed to check in at least this often.\"\n *\n * `graceMs` is what keeps a jittery-but-healthy agent out of the alert\n * channel: an agent on a 15m cadence that lands at 15m04s is not a dead agent,\n * and an alarm that cries at every wobble is one an operator learns to ignore\n * — which is the failure mode that loses the detector nobody was watching.\n */\nexport const LivenessExpectation = z.object({\n agentId: AgentId,\n /** Longest silence still considered normal, e.g. '15m'. */\n interval: Window,\n /** Extra slack past `interval` before the silence is an alarm. */\n graceMs: z.number().int().nonnegative().default(DEFAULT_LIVENESS_GRACE_MS),\n /**\n * When watching began. An agent that has NEVER been seen is measured from\n * here, so a watch on an agent that never starts does raise an alarm — a\n * detector that never came up is exactly as dead as one that stopped.\n */\n since: z.coerce.date(),\n /** What this agent is supposed to be doing, shown beside the alarm. */\n note: z.string().max(200).optional(),\n});\nexport type LivenessExpectation = z.infer<typeof LivenessExpectation>;\n\n/** The registration payload; the engine stamps `since`. */\nexport const LivenessWatchInput = LivenessExpectation.omit({ since: true }).extend({\n graceMs: z.number().int().nonnegative().optional(),\n});\nexport type LivenessWatchInput = z.input<typeof LivenessWatchInput>;\n\n/**\n * An out-of-band \"I am alive\" from an agent with nothing to buy.\n *\n * The engine sees every intent, so a spending agent needs no heartbeat at all.\n * This exists for the agent that is working and simply not paying for\n * anything — without it, a dead-man alarm is really a no-spend alarm, and it\n * would page a human every time an agent had a quiet afternoon.\n *\n * It authorizes nothing. The only thing a heartbeat can change is a row in the\n * liveness report; it cannot lift a breaker, a budget, or a freeze.\n */\nexport const Heartbeat = z.object({\n agentId: AgentId,\n /** When the agent was alive. Defaults to arrival time. */\n at: z.coerce.date().optional(),\n /** Free-form note from the reporter, e.g. \"poll cycle 41 ok\". */\n note: z.string().max(200).optional(),\n});\nexport type Heartbeat = z.infer<typeof Heartbeat>;\n\n/**\n * Where an agent stands against its expectation.\n *\n * - `alive` — seen within the interval.\n * - `late` — past the interval, inside the grace. Not yet news.\n * - `missing` — past both, and this process watched it happen. THE alarm.\n * - `unknown` — past both, but the engine has not been up long enough to have\n * witnessed the silence. Not an alarm: an engine that restarted\n * five minutes ago knows nothing about the last three days.\n */\nexport const LivenessStatus = z.enum(['alive', 'late', 'missing', 'unknown']);\nexport type LivenessStatus = z.infer<typeof LivenessStatus>;\n","import { z } from 'zod';\nimport { AgentId, ApproverKeyId, DecisionId, IntentId, OrgId } from './ids.js';\nimport { Asset, Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * Human approval of an escalated payment.\n *\n * The load-bearing rule: an approval is a SIGNATURE over the decision, made by\n * a key registered with the engine. The delivery channel (Telegram, email,\n * whatever) is transport, never authority — anyone who compromises the channel\n * gets to show a human a message, not to release funds. There is deliberately\n * no click-to-approve path.\n */\n\nexport const ApprovalVerdict = z.enum(['approve', 'reject']);\nexport type ApprovalVerdict = z.infer<typeof ApprovalVerdict>;\n\n/**\n * `pending` is the only non-terminal state. `expired` is what a TTL lapse\n * converts to — indistinguishable from `rejected` in effect (both deny), but\n * distinguished in the record so \"nobody answered\" and \"somebody said no\" stay\n * separable in an audit.\n */\nexport const ApprovalStatus = z.enum(['pending', 'approved', 'rejected', 'expired']);\nexport type ApprovalStatus = z.infer<typeof ApprovalStatus>;\n\n/**\n * A key whose signature the engine accepts as an approval. Public half only —\n * the private half lives with the human (a hardware token, a laptop, an\n * offline signer) and must never reach the engine.\n */\nexport const ApproverKey = z.object({\n id: ApproverKeyId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** ed25519 public key, SPKI PEM — the same encoding as the decision log's. */\n publicKey: z.string().min(1),\n algorithm: z.literal('ed25519').default('ed25519'),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type ApproverKey = z.infer<typeof ApproverKey>;\n\n/**\n * A parked escalation: the payment the engine refused to allow on its own\n * authority, held open until a signature arrives or the TTL lapses. Keyed by\n * the escalating decision — one decision, at most one approval request.\n *\n * The payment facts are copied in rather than referenced so the challenge a\n * human sees is self-contained: amount, vendor and resource are exactly what\n * they are being asked to authorize.\n */\nexport const ApprovalRequest = z.object({\n /** The `escalate` decision this request answers (primary key). */\n decisionId: DecisionId,\n intentId: IntentId,\n /** Binds the approval to the exact transfer — the signed bytes commit to it. */\n intentHash: z.string(),\n agentId: AgentId,\n /**\n * The org the escalating agent belongs to, stamped when the request is\n * parked. ABSENT means the agent was never registered (or the request\n * predates tenancy), and such a request is answerable only by an unscoped\n * operator — there is no org to check an approver against, and guessing one\n * is how a cross-tenant approval happens.\n */\n orgId: OrgId.optional(),\n vendorHost: z.string(),\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n /**\n * Task attribution copied from the intent. Carried so an approved payment\n * still counts against its `taskBudget` — an escalation that lost its task\n * id on the way through would make the budget silently under-count exactly\n * the payments a human had to look at.\n */\n taskId: z.string().optional(),\n /** Why policy escalated, verbatim from the decision. */\n reason: z.string(),\n /**\n * Breaker ids whose trip contributed to this escalation. An approval of\n * this request resets exactly these — moving their counting floor to the\n * approval instant — so a human waving one payment through also clears the\n * behavior that stopped it, rather than being asked again immediately.\n * Empty when ordinary rules did the escalating.\n */\n breakers: z.array(z.string()).default([]),\n status: ApprovalStatus,\n createdAt: z.coerce.date(),\n /** Past this instant the request denies, whatever arrives afterwards. */\n expiresAt: z.coerce.date(),\n resolvedAt: z.coerce.date().optional(),\n /** Which registered key signed — absent when the TTL lapsed instead. */\n approverKeyId: ApproverKeyId.optional(),\n /**\n * The follow-up decision appended to the chain when this resolved. That\n * decision, not this record, is the voucher a signer verifies: the original\n * `escalate` decision is never rewritten.\n */\n finalDecisionId: DecisionId.optional(),\n});\nexport type ApprovalRequest = z.infer<typeof ApprovalRequest>;\n\n/** The two byte-strings an approver may sign for a given request. */\nexport const ApprovalChallenges = z.object({\n approve: z.string(),\n reject: z.string(),\n});\nexport type ApprovalChallenges = z.infer<typeof ApprovalChallenges>;\n\n/**\n * A signed verdict, submitted to the engine by anyone (the signature is the\n * authority, so the carrier does not matter). `signature` is base64 ed25519\n * over `canonicalApproval({ decisionId, intentHash, verdict })`.\n */\nexport const ApprovalGrant = z.object({\n decisionId: DecisionId,\n intentHash: z.string(),\n verdict: ApprovalVerdict,\n approverKeyId: ApproverKeyId,\n signature: z.string().min(1),\n});\nexport type ApprovalGrant = z.infer<typeof ApprovalGrant>;\n\n/** Terminal statuses — a request in one of these will never change again. */\nexport function isResolved(status: ApprovalStatus): boolean {\n return status !== 'pending';\n}\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';\nimport { ApprovalRequest } from './approval.js';\nimport { LivenessExpectation, LivenessSource } from './liveness.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 * `approval.*` is the human-in-the-loop tier: an escalated intent parked for a\n * signature, and the signed (or lapsed) verdict that closed it.\n * `liveness.*` is the dead-man tier (B2), and the only pair here emitted by\n * something NOT happening: a watched agent that went quiet past its expected\n * interval, and the sighting that ended the silence.\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('approval.requested'),\n at: z.coerce.date(),\n request: ApprovalRequest,\n }),\n z.object({\n type: z.literal('approval.resolved'),\n at: z.coerce.date(),\n request: ApprovalRequest,\n /** The follow-up allow/deny decision this resolution appended. */\n decision: Decision,\n }),\n z.object({\n type: z.literal('liveness.missing'),\n at: z.coerce.date(),\n agentId: AgentId,\n expectation: LivenessExpectation,\n /** How long the agent has been silent when the alarm was raised. */\n silentMs: z.number().int().nonnegative(),\n /** Last sighting, absent when the agent was never seen at all. */\n lastSeenAt: z.coerce.date().optional(),\n }),\n z.object({\n type: z.literal('liveness.recovered'),\n at: z.coerce.date(),\n agentId: AgentId,\n /** How long the silence lasted, measured to this sighting. */\n silentMs: z.number().int().nonnegative(),\n source: LivenessSource,\n }),\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 { ApprovalRequest, 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. The payment was never\n * constructed, so no funds moved. Carries the full evidence trail.\n *\n * When the outcome was `escalate`, `approval` carries the parked request — and\n * its `status` says which kind of block this is: `pending` means a signed\n * verdict could still release it (the guard stopped waiting, or was never\n * asked to), while `rejected`/`expired` are final. An absent `approval` on an\n * escalation means the engine has no approval tier at all: nothing can\n * release it.\n */\nexport class PaymentBlockedError extends ReinError {\n constructor(\n readonly intent: PaymentIntent,\n readonly decision: Decision,\n readonly receipt: Receipt,\n readonly approval?: ApprovalRequest,\n ) {\n super(\n `rein blocked payment of ${intent.amount} ${intent.asset} to ${intent.vendor.host}: ` +\n `${decision.outcome}${decision.reason ? ` (${decision.reason})` : ''}` +\n (approval ? ` [approval ${approval.status}]` : ''),\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 {\n Agent,\n ApiKey,\n ApprovalChallenges,\n ApprovalGrant,\n ApprovalRequest,\n ApproverKey,\n AttributedDecision,\n Breaker,\n Decision,\n LivenessExpectation,\n LivenessSource,\n LivenessStatus,\n PaymentIntent,\n Policy,\n SettlementReport,\n type ApiKeyScope,\n} 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\n/**\n * One breaker's standing for one agent, as the engine reports it. Mirrors the\n * engine's `BreakerState`; declared here so the client validates the wire\n * shape rather than trusting it.\n */\nexport const BreakerState = z.object({\n breaker: Breaker,\n policyId: z.string(),\n txCount: z.number(),\n sum: z.string(),\n countingFrom: z.number(),\n resetAt: z.number().optional(),\n tripped: z.boolean(),\n reason: z.string().optional(),\n});\nexport type BreakerState = z.infer<typeof BreakerState>;\n\n/**\n * Where one watched agent stands against its expectation (B2). Mirrors the\n * engine's `LivenessState`; note `unknown`, which is not an alarm — it means\n * the engine has not been up long enough to have witnessed the silence, and a\n * caller that treats it as `missing` would page someone about a restart.\n */\nexport const LivenessState = z.object({\n agentId: z.string(),\n expectation: LivenessExpectation,\n lastSeenAt: z.number().optional(),\n lastSource: LivenessSource.optional(),\n silentSince: z.number(),\n silentMs: z.number(),\n dueAt: z.number(),\n overdueAt: z.number(),\n status: LivenessStatus,\n alertedAt: z.number().optional(),\n});\nexport type LivenessState = z.infer<typeof LivenessState>;\n\nconst Health = z.object({\n status: z.string(),\n publicKey: z.string(),\n /** \"api-key\" once the engine demands a credential; \"none\" while it does not. */\n auth: z.string().optional(),\n approvals: z.string().optional(),\n});\n\nconst EvaluateResponse = z.object({\n intent: PaymentIntent,\n decision: Decision,\n /** Present when an escalation was parked for a signed verdict. */\n approval: ApprovalRequest.optional(),\n});\nexport type EvaluateResponse = z.infer<typeof EvaluateResponse>;\n\n/** A parked escalation plus the bytes to sign and, once resolved, its decision. */\nconst ApprovalView = z.object({\n request: ApprovalRequest,\n challenges: ApprovalChallenges,\n /** The follow-up allow/deny decision, once the request has resolved. */\n decision: Decision.optional(),\n});\nexport type ApprovalView = z.infer<typeof ApprovalView>;\n\nconst ResolveResponse = z.object({ request: ApprovalRequest, decision: Decision });\nexport type ResolveResponse = z.infer<typeof ResolveResponse>;\n\n/**\n * One allowance the settlement facts disagree with (B1): nothing settled\n * behind it, or — `overspent` — a settlement for more than it allowed, with\n * the amount that moved in `settledAmount`. Mirrors the engine's shape.\n */\nexport const AllowanceGap = z.object({\n intentId: z.string(),\n decisionId: z.string().optional(),\n agentId: z.string(),\n host: z.string(),\n resource: z.string(),\n amount: z.string(),\n settledAmount: z.string().optional(),\n taskId: z.string().optional(),\n allowedAt: z.number(),\n ageMs: z.number(),\n state: z.enum(['in-flight', 'unsettled', 'overspent']),\n});\nexport type AllowanceGap = z.infer<typeof AllowanceGap>;\n\n/**\n * The reconciliation report. Declared here so the client validates the wire\n * shape rather than trusting it — and note `settlementsSeen`: zero means this\n * engine has never been told about a settlement, so the gaps below say more\n * about the deployment's wiring than about its payments.\n */\nexport const ReconciliationReport = z.object({\n from: z.number(),\n to: z.number(),\n window: z.string(),\n graceMs: z.number(),\n allowed: z.number(),\n allowedValue: z.string(),\n settled: z.number(),\n settledValue: z.string(),\n inFlight: z.number(),\n inFlightValue: z.string(),\n unsettled: z.number(),\n unsettledValue: z.string(),\n // Optional on the wire so a 0.2.0 engine still validates; absent means the\n // engine predates the check, not that nothing was overspent.\n overspent: z.number().optional(),\n overspentValue: z.string().optional(),\n unattributed: z.number(),\n settlementsSeen: z.number(),\n gaps: z.array(AllowanceGap),\n truncated: z.boolean(),\n});\nexport type ReconciliationReport = z.infer<typeof ReconciliationReport>;\n\nexport interface ReconciliationQuery {\n /** Trailing span of allowances to cover, e.g. '24h'. */\n window?: string;\n /** How long an allowance may go unsettled before it counts as a gap. */\n graceMs?: number;\n limit?: number;\n agentId?: string;\n}\n\nconst IssuedApiKey = z.object({ key: ApiKey, secret: z.string() });\nexport type IssuedApiKey = z.infer<typeof IssuedApiKey>;\n\nexport interface EngineClientOptions {\n /** Base URL of the policy engine, e.g. \"http://localhost:8787\". */\n baseUrl: string;\n /**\n * API-key secret, sent as `Authorization: Bearer`. Required by any engine\n * started with one; omit only for a local engine running without auth.\n */\n apiKey?: string;\n /** Override the transport (tests, custom agents). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\nexport interface AwaitApprovalOptions {\n /** Give up after this long and return the still-pending view. */\n timeoutMs?: number;\n /** How often to re-read the request. */\n pollMs?: number;\n /** Abort the wait early (an agent loop shutting down). */\n signal?: AbortSignal;\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 private readonly apiKey: string | undefined;\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 this.apiKey = options.apiKey;\n }\n\n /** The transport half: everything but parsing, so a caller can read headers. */\n private async send(method: string, path: string, body?: unknown): Promise<Response> {\n const headers: Record<string, string> = {};\n if (body !== undefined) headers['content-type'] = 'application/json';\n if (this.apiKey) headers['authorization'] = `Bearer ${this.apiKey}`;\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n ...(body === undefined ? {} : { body: 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 return res;\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.send(method, path, body);\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 /** Semantic grouping labels (lowercase slugs) — policy `appliesTo.labels` targets these. */\n labels?: Agent['labels'];\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 /**\n * Where the agent's behavioral breakers stand. Read-only: nothing here can\n * trip or clear one — a breaker clears when its window rolls forward or\n * when a signed approval moves its floor.\n */\n breakerStates(agentId: string): Promise<BreakerState[]> {\n return this.request('GET', `/v1/agents/${agentId}/breakers`, z.array(BreakerState));\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 /**\n * The first page of the decision chain (up to 500, the engine's default).\n *\n * On a chain longer than that this is a verifying PREFIX, not the whole log\n * — `prevHash` links check out, but the newest decisions are not here. Use\n * {@link decisionsPage} when you need to walk to the head.\n *\n * Each record carries `agentId` from a 0.3.0 engine -- unsigned, see\n * AttributedDecision -- and lacks it from an older one.\n */\n decisions(): Promise<AttributedDecision[]> {\n return this.request('GET', '/v1/decisions', z.array(AttributedDecision));\n }\n\n /**\n * One page of the decision chain, plus where the next one starts.\n *\n * `nextAfter` is `undefined` at the head of the chain, which is the signal to\n * stop — not an empty page, which a caller polling a live engine would see\n * constantly and could not tell from \"caught up\". Feed it back as `after` to\n * continue; concatenating the pages in order reproduces exactly what the\n * caller is entitled to see, so `verifyDecisionChain` accepts the result.\n *\n * `chainLength` is how many decisions this key can see in total, which for\n * an org-scoped key is its own rows and not the engine's chain.\n */\n async decisionsPage(\n query: { after?: number; limit?: number } = {},\n ): Promise<{ decisions: AttributedDecision[]; nextAfter?: number; chainLength: number }> {\n const params = new URLSearchParams();\n if (query.after !== undefined) params.set('after', String(query.after));\n if (query.limit !== undefined) params.set('limit', String(query.limit));\n const qs = params.toString();\n const res = await this.send('GET', `/v1/decisions${qs ? `?${qs}` : ''}`);\n const decisions = z.array(AttributedDecision).parse(await res.json());\n const next = res.headers.get('rein-next-after');\n const length = res.headers.get('rein-chain-length');\n return {\n decisions,\n ...(next === null ? {} : { nextAfter: Number(next) }),\n // An engine older than this header still answers the route; fall back to\n // what the page itself proves rather than reporting a NaN length.\n chainLength: length === null ? decisions.length : Number(length),\n };\n }\n\n // --- Reconciliation (B1) ---\n\n /**\n * Tell the engine an allowed payment landed. The engine watches no chain, so\n * this is how a gap gets closed — by the guard that paid, an indexer, or a\n * facilitator webhook. It authorizes nothing: the only thing a settlement\n * report can change is a line in the reconciliation report.\n */\n reportSettlement(input: z.input<typeof SettlementReport>): Promise<SettlementReport> {\n return this.request('POST', '/v1/settlements', SettlementReport, SettlementReport.parse(input));\n }\n\n /** Which allowances in the window have no settlement behind them. */\n reconciliation(query: ReconciliationQuery = {}): Promise<ReconciliationReport> {\n const params = new URLSearchParams();\n if (query.window !== undefined) params.set('window', query.window);\n if (query.graceMs !== undefined) params.set('graceMs', String(query.graceMs));\n if (query.limit !== undefined) params.set('limit', String(query.limit));\n if (query.agentId !== undefined) params.set('agentId', query.agentId);\n const qs = params.toString();\n return this.request(\n 'GET',\n `/v1/reconciliation${qs ? `?${qs}` : ''}`,\n ReconciliationReport,\n );\n }\n\n // --- Dead-man monitoring (B2) ---\n\n /**\n * Expect this agent to be active at least every `interval`. Watching is\n * declared, never inferred: an agent nobody watches has no liveness state,\n * because silence is only evidence about an agent somebody said should be\n * periodic.\n */\n watchLiveness(\n agentId: string,\n expectation: { interval: string; graceMs?: number; note?: string },\n ): Promise<LivenessExpectation> {\n return this.request('PUT', `/v1/agents/${agentId}/liveness`, LivenessExpectation, expectation);\n }\n\n unwatchLiveness(agentId: string): Promise<void> {\n return this.request('DELETE', `/v1/agents/${agentId}/liveness`, z.void());\n }\n\n /**\n * \"I am alive, I just have nothing to buy.\"\n *\n * Only needed by an agent that goes quiet on purpose — every intent is\n * already a sighting, whatever the engine decided about it. It authorizes\n * nothing: the only thing it can change is a row in the liveness report.\n */\n heartbeat(agentId: string, input: { at?: Date; note?: string } = {}): Promise<LivenessState> {\n return this.request('POST', `/v1/agents/${agentId}/heartbeat`, LivenessState, {\n ...(input.at ? { at: input.at.toISOString() } : {}),\n ...(input.note ? { note: input.note } : {}),\n });\n }\n\n /** Where every watched agent stands. Worst first. */\n liveness(): Promise<LivenessState[]> {\n return this.request('GET', '/v1/liveness', z.array(LivenessState));\n }\n\n // --- API keys (admin scope) ---\n\n /**\n * Mint a key. The secret in the response is the only copy that will exist.\n *\n * `orgId` confines the new key to one tenant and `agentIds` narrows it\n * further to named agents — what an agent runtime should carry, so a stolen\n * key spends one agent's budget rather than the whole org's. Omitting both\n * mints an unscoped operator key, which is what a single-tenant self-hosted\n * engine wants and has always had. A caller that is itself org-scoped has\n * its own org applied regardless of what it asks for here.\n */\n issueApiKey(input: {\n name: string;\n scopes: ApiKeyScope[];\n orgId?: string;\n agentIds?: string[];\n }): Promise<IssuedApiKey> {\n return this.request('POST', '/v1/keys', IssuedApiKey, input);\n }\n\n listApiKeys(): Promise<ApiKey[]> {\n return this.request('GET', '/v1/keys', z.array(ApiKey));\n }\n\n /**\n * Mint a replacement secret. The outgoing one keeps working for `graceMs`\n * (engine default: 1h) so callers can be redeployed one at a time; pass 0\n * when the old secret is compromised and must die now.\n */\n rotateApiKey(keyId: string, options: { graceMs?: number } = {}): Promise<IssuedApiKey> {\n return this.request('POST', `/v1/keys/${keyId}/rotate`, IssuedApiKey, options);\n }\n\n revokeApiKey(keyId: string): Promise<ApiKey> {\n return this.request('POST', `/v1/keys/${keyId}/revoke`, ApiKey);\n }\n\n // --- Approvals ---\n\n /** Register the PUBLIC half of an approver key. The private half never travels. */\n registerApprover(input: { orgId: string; name: string; publicKey: string }): Promise<ApproverKey> {\n return this.request('POST', '/v1/approvers', ApproverKey, input);\n }\n\n listApprovers(): Promise<ApproverKey[]> {\n return this.request('GET', '/v1/approvers', z.array(ApproverKey));\n }\n\n revokeApprover(keyId: string): Promise<ApproverKey> {\n return this.request('POST', `/v1/approvers/${keyId}/revoke`, ApproverKey);\n }\n\n /** Every escalation still answerable right now. */\n pendingApprovals(): Promise<ApprovalRequest[]> {\n return this.request('GET', '/v1/approvals', z.array(ApprovalRequest));\n }\n\n /** One escalation, with the exact bytes to sign for each verdict. */\n approval(decisionId: string): Promise<ApprovalView> {\n return this.request('GET', `/v1/approvals/${decisionId}`, ApprovalView);\n }\n\n /**\n * Submit a signed verdict. The signature is the authority — this call can be\n * made by anyone, from anywhere, including a relay that never sees a key.\n */\n resolveApproval(grant: ApprovalGrant): Promise<ResolveResponse> {\n const { decisionId, ...body } = ApprovalGrant.parse(grant);\n return this.request('POST', `/v1/approvals/${decisionId}/resolve`, ResolveResponse, body);\n }\n\n /**\n * Poll until an escalation resolves, times out, or the caller aborts. The\n * returned view is whatever was true when polling stopped — a caller must\n * check `request.status` rather than assume it resolved.\n */\n async awaitApproval(\n decisionId: string,\n options: AwaitApprovalOptions = {},\n ): Promise<ApprovalView> {\n const pollMs = options.pollMs ?? 1_000;\n const deadline = Date.now() + (options.timeoutMs ?? 300_000);\n for (;;) {\n const view = await this.approval(decisionId);\n if (view.request.status !== 'pending') return view;\n if (options.signal?.aborted || Date.now() + pollMs > deadline) return view;\n await sleep(pollMs, options.signal);\n }\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(done, ms);\n function done(): void {\n clearTimeout(timer);\n signal?.removeEventListener('abort', done);\n resolve();\n }\n signal?.addEventListener('abort', done, { once: true });\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). */\n/**\n * Decimals per asset, from the token contracts -- NOT from the counterparty.\n *\n * `extra.decimals` arrives inside the vendor's own 402 challenge, and it used\n * to be what converted `maxAmountRequired` into the human amount policy is\n * evaluated against. The payer signs the RAW atomic value, so the vendor owned\n * the ratio between the number Rein judged and the number the wallet\n * authorized: quote 500000000 with `decimals: 12` and a 500 USDC charge is\n * evaluated as 0.0005, passes every cap and budget, and settles for 500.\n * Circle's USDC is 6 everywhere it is deployed; USDT and EURC are 6 on Base.\n */\nconst ASSET_DECIMALS: Record<Asset, number> = { USDC: 6, USDT: 6, EURC: 6 };\n\n/** An EVM token address: only the address tables may name one. */\nconst EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;\n\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\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\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 known =\n extraAddresses[requirement.asset] ??\n extraAddresses[requirement.asset.toLowerCase()] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset.toLowerCase()];\n if (known) return known;\n\n // `extra.symbol` is the counterparty's word for its own token, and it is\n // consulted LAST and never for an address. It used to come first, so any\n // EIP-3009 token could present itself as `USDC`: the engine evaluated the\n // agent's USDC caps and budgets, and the payer then signed a\n // TransferWithAuthorization against the attacker's chosen contract, spending\n // a balance no USDC policy was ever written about.\n if (EVM_ADDRESS.test(requirement.asset)) return undefined;\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 undefined;\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\n/**\n * The decimals to read `maxAmountRequired` with.\n *\n * Pass the RESOLVED asset and the answer comes from `ASSET_DECIMALS` -- the\n * token's own precision, which the counterparty does not get a vote on. The\n * no-asset form is the legacy one and still honours `extra.decimals`; it must\n * not be used on any path that leads to a signature.\n */\nexport function requirementDecimals(requirement: PaymentRequirement, asset?: Asset): number {\n if (asset) return ASSET_DECIMALS[asset];\n const decimals = requirement.extra?.['decimals'];\n return typeof decimals === 'number' && Number.isInteger(decimals) && decimals >= 0 ? decimals : 6;\n}\n\n/**\n * Does the vendor's stated precision match the token's? A disagreement is not\n * an error to correct silently -- it is an offer whose amount we cannot agree\n * on, which makes it ungovernable, so `selectRequirement` skips it.\n */\nexport function decimalsAgree(requirement: PaymentRequirement, asset: Asset): boolean {\n const stated = requirement.extra?.['decimals'];\n if (stated === undefined) return true;\n return stated === ASSET_DECIMALS[asset];\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, an allowed network, and a resolvable asset.\n * Returns undefined when no offer qualifies — callers must treat that as\n * fail-closed.\n *\n * `networks` is the testnet/mainnet boundary, and it has to live HERE rather\n * than downstream of evaluate. `networkToChain` folds a testnet onto its\n * mainnet — `base-sepolia` and `base` both become `'base'` — because policy\n * is written about chains, not deployments. That is right for policy and\n * useless as a safety rail: the engine cannot tell a Sepolia offer from a\n * mainnet one, so a testnet agent handed a mainnet 402 would be allowed by\n * every policy it has and would then sign for real money. Filtering before\n * selection is what makes a network allow-list mean anything.\n */\nexport function selectRequirement(\n accepts: readonly PaymentRequirement[],\n extraAddresses: Record<string, Asset> = {},\n networks?: readonly string[],\n): ResolvedRequirement | undefined {\n const allowed = networks?.map(caip2Of);\n for (const requirement of accepts) {\n if (requirement.scheme.toLowerCase() !== 'exact') continue;\n const chain = networkToChain(requirement.network);\n if (!chain) continue;\n if (allowed && !allowed.includes(caip2Of(requirement.network))) continue;\n const asset = resolveAsset(requirement, extraAddresses);\n if (!asset) continue;\n // Fail closed on a token whose precision the vendor states differently\n // from the contract: the amount policy would judge and the amount the\n // wallet would authorize are not the same number.\n if (!decimalsAgree(requirement, asset)) continue;\n const amount = atomicToDecimal(\n requirement.maxAmountRequired,\n requirementDecimals(requirement, asset),\n );\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 { caip2Of, PaymentRequirement } from './x402.js';\n\n// caip2Of/sameNetwork LIVE in x402.ts: selectRequirement's network allow-list\n// needs them, and importing them back up from here would close a cycle\n// through this module's zod consts. Re-exported so the v2 dialect still\n// reads as their home.\nexport { caip2Of, sameNetwork } 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/** 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. */\n/**\n * Build the v2 PaymentRequired a vendor advertises.\n *\n * `extensions` is the spec's open slot for things that are not payment terms\n * -- discovery metadata, for instance. It stays a plain record here rather\n * than a union of known keys: the gate owns what goes in (see\n * `GateRoute.discovery`), and a codec that validated the payload would have\n * to be revised for every extension anyone ever writes. An empty object is\n * still emitted when there is nothing to say, because the field is not\n * optional on the wire.\n */\nexport function buildPaymentRequiredV2(\n requirement: PaymentRequirement,\n error: string,\n extensions: Record<string, unknown> = {},\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 ApprovalRequest,\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 encodeBase64Json,\n parsePaymentRequiredHeader,\n requirementFromV2,\n wrapPaymentV2,\n type PaymentRequiredV2,\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 /**\n * API-key secret for the engine. Required by any engine started with one;\n * without it every call comes back 401 as an EngineError.\n */\n apiKey?: 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 /**\n * The networks this guard will govern payments on, as x402 ids in either\n * dialect (`base-sepolia`, `eip155:8453`, ...). A 402 offering only\n * networks outside the list is treated as an ungovernable paywall and\n * fails closed, BEFORE the engine is asked.\n *\n * Omitted means \"any network the SDK maps to a chain\", which is what every\n * guard got before profiles. Set it on anything holding a real key: the\n * engine cannot enforce this boundary for you, because policy is written\n * about chains and `networkToChain` folds `base-sepolia` into `base` (see\n * selectRequirement). A testnet agent without this list will happily be\n * allowed to pay a mainnet 402.\n */\n networks?: readonly string[];\n /** Called once per receipt, as it is recorded. */\n onReceipt?: (receipt: Receipt) => void;\n /**\n * How many receipts `receipts()` keeps, oldest evicted first. Default 1000.\n * The log is a session convenience; `onReceipt` sees every receipt, capped\n * or not, and is the path for anything that must not lose one. Without a\n * cap a long-lived guard -- an MCP server -- grows without bound.\n */\n maxReceipts?: number;\n /**\n * In advisory mode (no `payer`) an allowed 402 is released upward and its\n * receipt waits for the payment layer's X-PAYMENT retry to settle it. A\n * retry that never comes would leave that entry forever; after this many\n * milliseconds it is forgotten and the receipt stays unsettled -- which\n * reconciliation, not this log, is there to notice. Default 300 000: the\n * x402 authorization window, after which the retry could not pay anyway.\n */\n pendingTtlMs?: number;\n /**\n * Tell the engine when a payment settles, so reconciliation can close the\n * allowance (B1). On by default: without a report from somewhere, every\n * allowance the engine made reads as a gap, and the one component that sees\n * both the decision and the vendor's confirmation is this guard.\n *\n * Best-effort by construction — the report is fired and forgotten, and a\n * failed one never touches the payment. Telemetry must not be able to change\n * a payment's outcome. Set false where an independent indexer reports\n * instead, which is the stronger evidence: a guard reporting its own\n * settlement is the spender vouching for itself.\n */\n reportSettlement?: boolean;\n /**\n * What to do when policy escalates: by default nothing — the payment blocks\n * immediately, exactly as a deny does, and a human can still approve it out\n * of band. Set `await: true` and the guard holds the request open while it\n * waits for a signed verdict, then proceeds on an approval or blocks on a\n * rejection/expiry. Only ever wait where a stalled request is acceptable.\n */\n escalation?: EscalationOptions;\n}\n\nexport interface EscalationOptions {\n /** Hold the request open until the escalation resolves. Default: false. */\n await?: boolean;\n /** Stop waiting after this long, leaving the request pending. Default 5 min. */\n timeoutMs?: number;\n /** How often to re-read the parked request. Default 1s. */\n pollMs?: number;\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 */\nconst DEFAULT_MAX_RECEIPTS = 1000;\nconst DEFAULT_PENDING_TTL_MS = 300_000;\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({\n baseUrl: options.engineUrl,\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\n ...(options.engineFetch ? { fetch: options.engineFetch } : {}),\n });\n }\n\n /** The most recent `maxReceipts` receipts 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, this.options.networks);\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 evaluated = await this.client.evaluate(submission);\n const intent = evaluated.intent;\n let decision = evaluated.decision;\n let approval = evaluated.approval;\n\n // An escalation is a question, not yet an answer. When the caller has\n // opted into waiting, hold here until a signed verdict lands — the\n // decision we continue with is then the engine's FOLLOW-UP decision, the\n // one a signer will accept as a voucher.\n if (decision.outcome === 'escalate' && approval && this.options.escalation?.await) {\n const settled = await this.awaitEscalation(approval);\n approval = settled.request;\n if (settled.decision) decision = settled.decision;\n }\n\n if (decision.outcome !== 'allow') {\n const receipt = this.record(intent, decision, url, init);\n if (this.options.onBlocked === 'respond') return blockedResponse(receipt, approval);\n throw new PaymentBlockedError(intent, decision, receipt, approval);\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.sweepPending();\n this.pendingByUrl.set(url, receipt);\n // Only the offer that was actually evaluated. See ParsedPaywall.narrowed.\n return paywall.narrowed ?? 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 const max = this.options.maxReceipts ?? DEFAULT_MAX_RECEIPTS;\n if (this.log.length > max) this.log.splice(0, this.log.length - max);\n this.options.onReceipt?.(receipt);\n if (settlement) this.announceSettlement(receipt);\n return receipt;\n }\n\n /**\n * Fire-and-forget the settlement fact at the engine. Deliberately silent on\n * failure: a reconciliation report that never arrives leaves a gap open,\n * which is the SAFE direction — an operator sees a payment they must check.\n * Raising here would let telemetry break a payment that already succeeded.\n *\n * The amount is not reported: the guard knows what it was asked to pay, not\n * what the chain moved, and a settlement report should carry only what its\n * reporter actually observed.\n */\n private announceSettlement(receipt: Receipt): void {\n if (this.options.reportSettlement === false) return;\n const txHash = receipt.settlement?.txHash;\n void this.client\n .reportSettlement({\n intentId: receipt.intentId,\n ...(txHash !== undefined ? { txHash } : {}),\n chain: receipt.chain,\n source: 'guard',\n confirmedAt: receipt.createdAt,\n })\n .catch(() => undefined);\n }\n\n /**\n * Wait out a parked escalation. Never waits past the request's own TTL:\n * after that instant the engine can only deny it, so continuing to poll\n * would just be a slower block.\n */\n private async awaitEscalation(request: ApprovalRequest): Promise<ApprovalOutcome> {\n const options = this.options.escalation ?? {};\n const untilExpiry = Math.max(0, request.expiresAt.getTime() - Date.now()) + 1_000;\n const view = await this.client.awaitApproval(request.decisionId, {\n timeoutMs: Math.min(options.timeoutMs ?? 300_000, untilExpiry),\n ...(options.pollMs !== undefined ? { pollMs: options.pollMs } : {}),\n });\n return { request: view.request, ...(view.decision ? { decision: view.decision } : {}) };\n }\n\n /** Drop advisory receipts whose retry window has passed -- see `pendingTtlMs`. */\n private sweepPending(): void {\n const cutoff = Date.now() - (this.options.pendingTtlMs ?? DEFAULT_PENDING_TTL_MS);\n for (const [url, receipt] of this.pendingByUrl) {\n if (receipt.createdAt.getTime() < cutoff) this.pendingByUrl.delete(url);\n }\n }\n\n private settlePending(url: string, res: Response): void {\n this.sweepPending();\n const receipt = this.pendingByUrl.get(url);\n if (!receipt || !res.ok) return;\n const settlement = parseSettlement(res);\n if (settlement) {\n receipt.settlement = settlement;\n this.announceSettlement(receipt);\n }\n this.pendingByUrl.delete(url);\n }\n}\n\n/** How a waited-on escalation came out. */\ninterface ApprovalOutcome {\n request: ApprovalRequest;\n /** The follow-up allow/deny decision, absent while still pending. */\n decision?: Decision;\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 * The same 402 carrying ONLY the offer the guard evaluated.\n *\n * In advisory mode the guard does not pay; it hands the 402 back to the\n * payment layer above, which holds the key. Releasing the vendor's body\n * verbatim meant that layer chose from the FULL `accepts` list -- including\n * the offers the network allow-list had just rejected. A hostile 402 that\n * lists a 0.001 Sepolia offer and a 250 USDC mainnet one gets the cheap one\n * evaluated and allowed, and the expensive one paid, while the receipt and\n * the engine record the cheap one. Narrowing the body is what makes the\n * testnet pin structural rather than advisory.\n */\n narrowed?: Response;\n}\n\n/** Rebuild a 402 carrying a single offer, in whichever dialects it used. */\nfunction narrow402(\n res: Response,\n body: unknown,\n v2: PaymentRequiredV2 | undefined,\n keepV1: PaymentRequirement | undefined,\n keepV2Index: number | undefined,\n): Response {\n const headers = new Headers(res.headers);\n if (v2 && keepV2Index !== undefined) {\n const offer = v2.accepts[keepV2Index];\n if (offer) headers.set('PAYMENT-REQUIRED', encodeBase64Json({ ...v2, accepts: [offer] }));\n }\n let text: string | undefined;\n if (keepV1 && body && typeof body === 'object') {\n text = JSON.stringify({ ...(body as Record<string, unknown>), accepts: [keepV1] });\n headers.delete('content-length');\n }\n return new Response(text ?? res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\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 networks: readonly string[] | undefined,\n): Promise<ParsedPaywall | undefined> {\n const v2 = parsePaymentRequiredHeader(res.headers.get('PAYMENT-REQUIRED'));\n const body = await res\n .clone()\n .json()\n .catch(() => undefined);\n const parsed = PaymentRequired.safeParse(body);\n\n // Which v1 offer (if the body is v1) the guard would govern. Computed even\n // on the v2 path, because a dual-stack 402 answers both and a v1-only layer\n // above would otherwise still read the unfiltered body.\n const v1Resolved = parsed.success\n ? selectRequirement(parsed.data.accepts, assetAddresses, networks)\n : undefined;\n\n if (v2) {\n const asRequirements = v2.accepts.map((offer) => requirementFromV2(offer, v2.resource));\n const resolved = selectRequirement(asRequirements, assetAddresses, networks);\n if (resolved) {\n const index = asRequirements.indexOf(resolved.requirement);\n const narrowed = narrow402(res, body, v2, v1Resolved?.requirement, index);\n return v2.resource !== undefined\n ? { resolved, wire: 2, resource: v2.resource, narrowed }\n : { resolved, wire: 2, narrowed };\n }\n }\n\n if (parsed.success) {\n return {\n resolved: v1Resolved,\n wire: 1,\n ...(v1Resolved\n ? { narrowed: narrow402(res, body, v2, v1Resolved.requirement, undefined) }\n : {}),\n };\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, approval?: ApprovalRequest): 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 // `pending` here means a signed verdict could still release this\n // payment; anything else is final.\n ...(approval\n ? {\n approval: {\n status: approval.status,\n decisionId: approval.decisionId,\n expiresAt: approval.expiresAt.toISOString(),\n },\n }\n : {}),\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","z","z","z","parsed","EventEmitter","EventEmitter"]}
1
+ {"version":3,"sources":["../src/ledger.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/api-key.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.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/liveness.ts","../../../packages/core/src/approval.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/** 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');\nexport const ApiKeyId = prefixedId('key');\nexport const ApproverKeyId = prefixedId('apk');\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>;\nexport type ApiKeyId = z.infer<typeof ApiKeyId>;\nexport type ApproverKeyId = z.infer<typeof ApproverKeyId>;\n","import { z } from 'zod';\nimport { AgentId, ApiKeyId, OrgId } from './ids.js';\n\n/**\n * What a key is allowed to reach. `admin` satisfies every requirement (it is\n * the issuing/rotating key); the rest are least-privilege grants so an agent\n * runtime carrying an `evaluate` key cannot rewrite policy, and an approval\n * relay cannot read the spend history.\n *\n * `report` is the graph's ingestion grant, and it is deliberately NOT folded\n * into `evaluate`: evidence written to the reputation graph is about OTHER\n * subjects, so a fleet key that may spend its own budget has no business\n * moving a vendor's score. The engine's own reporting routes ride `evaluate`\n * because there the reporter IS the spender — that reasoning does not reach\n * across to a shared graph.\n *\n * `identity` is the hosted console's grant (Sprint 13): it redeems claim codes\n * and turns a signed-in owner into a short-lived read key for their org. It is\n * useful only on an UNSCOPED key -- those routes have no tenant rule, so an\n * org-scoped key holding it is refused before the route runs -- and it reads\n * and spends nothing by itself.\n */\nexport const ApiKeyScope = z.enum(['read', 'evaluate', 'approve', 'report', 'identity', 'admin']);\nexport type ApiKeyScope = z.infer<typeof ApiKeyScope>;\n\n/**\n * The public view of an API key — everything except the secret. This is what\n * the API returns on list/issue; the secret itself is shown exactly once, at\n * issuance, and never persisted in recoverable form (see {@link ApiKeyRecord}).\n */\nexport const ApiKey = z.object({\n id: ApiKeyId,\n name: z.string().min(1).max(200),\n scopes: z.array(ApiKeyScope).min(1),\n /**\n * The org this key acts inside. ABSENT means unscoped — an operator key that\n * reads and writes across every org, which is what a self-hosted single-org\n * deployment and every env-seeded boot secret have always been. That is the\n * compatibility rule the whole tenancy design rests on: adding tenancy\n * changed no existing key's behaviour, because no existing key has this\n * field.\n *\n * Present, it is a hard confinement, not a default: the key cannot read,\n * spend, approve or govern outside the org, and a write it submits is\n * stamped with this org rather than the one the body asked for.\n */\n orgId: OrgId.optional(),\n /**\n * Narrow an org-scoped key further, to specific agents — what an agent\n * runtime should carry, so a stolen key spends one agent's budget rather\n * than the org's. Only meaningful alongside {@link ApiKey.orgId}: agent\n * narrowing without an org is refused at issuance, because the scope it\n * would describe has no org to resolve policies and approvers in.\n *\n * Capped at 64: a list long enough to need more is a fleet, and a fleet is\n * what the org scope is for.\n */\n agentIds: z.array(AgentId).max(64).optional(),\n createdAt: z.coerce.date(),\n /** Last successful authentication, for spotting keys that can be retired. */\n lastUsedAt: z.coerce.date().optional(),\n /** Set by revoke(); a revoked key never authenticates again. */\n revokedAt: z.coerce.date().optional(),\n /** Set by rotate(); with `previousSecretExpiresAt` it dates the overlap. */\n rotatedAt: z.coerce.date().optional(),\n /**\n * Past this instant the key stops authenticating, like a revoked one.\n * ABSENT means it never expires -- every key before the sandbox, and every\n * key an operator mints. Only the anonymous sandbox sets it, and a key minted\n * BY an expiring key inherits the deadline: a sandbox that could mint itself\n * a permanent key would not be a 7-day sandbox.\n */\n expiresAt: z.coerce.date().optional(),\n});\nexport type ApiKey = z.infer<typeof ApiKey>;\n\n/**\n * SERVER-SIDE ONLY. The stored form: the public record plus sha256 digests of\n * the secrets. Digests, not secrets — a stolen database yields nothing that\n * authenticates. Rotation keeps the outgoing digest alive until\n * `previousSecretExpiresAt` so a running fleet can roll over without a\n * flag-day restart; past that instant only the current secret verifies.\n *\n * This shape never leaves the engine: every route answers with {@link ApiKey}.\n */\nexport const ApiKeyRecord = ApiKey.extend({\n secretHash: z.string(),\n previousSecretHash: z.string().optional(),\n previousSecretExpiresAt: z.coerce.date().optional(),\n});\nexport type ApiKeyRecord = z.infer<typeof ApiKeyRecord>;\n\n/** Strip the digests: the only sanctioned way to put a key on the wire. */\nexport function toPublicApiKey(record: ApiKeyRecord): ApiKey {\n const { secretHash, previousSecretHash, previousSecretExpiresAt, ...pub } = record;\n void secretHash;\n void previousSecretHash;\n void previousSecretExpiresAt;\n return pub;\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/**\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/**\n * `a - b` for decimal strings, exact. Requires `a >= b`: the one caller is\n * \"how much more settled than was allowed\", and a negative money string is a\n * shape nothing else in the system accepts, so asking for one is a bug here\n * rather than a value to hand on.\n */\nexport function subDecimal(a: string, b: string): string {\n if (compareDecimal(a, b) < 0) {\n throw new RangeError(`subDecimal: ${a} is less than ${b}`);\n }\n const scale = Math.max(fractionLength(a), fractionLength(b));\n return fromScaled(toScaled(a, scale) - toScaled(b, scale), 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","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\n/**\n * A semantic grouping label, e.g. \"research\" or \"prod-trading\". Lowercase\n * slugs only — policy `appliesTo.labels` matches these (with globs), and a\n * case-normalization mismatch would silently un-target a policy.\n */\nexport const AgentLabel = z\n .string()\n .max(40)\n .regex(/^[a-z0-9][a-z0-9-]*$/, 'label must be a lowercase slug like \"research\" or \"prod-trading\"');\nexport type AgentLabel = z.infer<typeof AgentLabel>;\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 /** Semantic grouping labels — the targets of policy `appliesTo.labels`. */\n labels: z\n .array(AgentLabel)\n .max(16)\n .refine((ls) => new Set(ls).size === ls.length, { message: 'labels must be unique' })\n .default([]),\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\n/**\n * Reduce an intent's `resource` to its path for policy matching. The value is\n * vendor-declared and shape-varies: the x402 spec puts a full URL in\n * `requirement.resource`, while the guard falls back to the request pathname\n * when the vendor omits it. Policies match on the PATH so authors never need\n * to know which shape a vendor emits; host targeting stays with\n * `vendorHostIn`, which is derived from the real request URL rather than the\n * vendor's own claim. Query strings do not survive the reduction.\n */\nexport function resourcePathOf(resource: string): string {\n try {\n const url = new URL(resource);\n if (url.protocol === 'http:' || url.protocol === 'https:') return url.pathname;\n } catch {\n // Not a URL — already a bare path.\n }\n return resource;\n}\n","import { z } from 'zod';\nimport { AgentId, 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\n/**\n * A decision as `GET /v1/decisions` serves it (0.3.0): the signed record plus\n * `agentId`, the agent whose intent it judged.\n *\n * `agentId` is an ENVELOPE field -- the engine's own attribution, outside\n * `hash` and `signature`, so a verified chain vouches for nothing about it.\n * Putting it inside would have changed the hash of every future decision and\n * split the chain into two formats. It is here for a reconciler that is not\n * co-located with the agent: `reconcile()` needs an allowed intent's agent,\n * or agent B's payment against A's intent is credited to A (S74), and before\n * this field only `/v1/reconciliation` carried it -- and erases it the moment\n * a settlement lands. Absent on an unattributed (pre-tenancy) row.\n */\nexport const AttributedDecision = Decision.extend({ agentId: AgentId.optional() });\nexport type AttributedDecision = z.infer<typeof AttributedDecision>;\n","import type { PaymentIntent } from './intent.js';\nimport type { DecisionOutcome } from './decision.js';\nimport type { ApprovalVerdict } from './approval.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\n/** The fields an approval signature commits to. */\nexport interface ApprovalContent {\n decisionId: string;\n intentHash: string;\n verdict: ApprovalVerdict;\n}\n\n/**\n * Canonical form of an approval — the exact bytes an approver signs.\n *\n * Three properties are deliberate. The leading `rein` domain tag separates\n * this signature space from the decision log's, so a decision signature can\n * never be replayed as an approval or the reverse. `decisionId` makes each\n * challenge single-use: one escalation, one decision id, one signature that\n * means anything. And `verdict` is INSIDE the signed bytes — without it, a\n * captured approval could be resubmitted as a rejection (or vice versa) by\n * anyone who saw it in flight.\n */\nexport function canonicalApproval(a: ApprovalContent): string {\n return JSON.stringify({\n rein: 'approval/v1',\n decisionId: a.decisionId,\n intentHash: a.intentHash,\n verdict: a.verdict,\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\n/**\n * A report that an allowed intent's payment actually landed — the settlement\n * half of reconciliation (\"allowed but never settled\", B1).\n *\n * Deliberately looser than {@link SettledPayment}: the on-chain confirmation\n * requires a tx hash and a block, while a REPORT is whatever the observer\n * could see. A vendor's `X-PAYMENT-RESPONSE` names a transaction but no block;\n * a facilitator webhook may name neither. Demanding the strong shape would\n * mean the weakest observers — the ones a deployment actually has — could\n * report nothing at all, and every allowance would read as a gap.\n *\n * `source` records WHO said so, because the evidence is not all equal: an\n * independent indexer watching the chain is the strong claim, while a guard\n * reporting on its own payment is the agent vouching for itself. Nothing here\n * grants authority — a settlement report can only ever CLOSE a gap in the\n * reconciliation report, never authorize a payment or alter a decision.\n */\nexport const SettlementReport = z.object({\n intentId: IntentId,\n /** The settling transaction, when the observer saw one. */\n txHash: z.string().optional(),\n chain: Chain.optional(),\n /** The amount as SETTLED, when known — may differ from the amount allowed. */\n amount: DecimalString.optional(),\n /** Free-form observer tag, e.g. \"indexer\", \"guard\", \"facilitator\". */\n source: z.string().min(1).max(64).optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettlementReport = z.infer<typeof SettlementReport>;\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 { OrgId } from './ids.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 /**\n * Resource PATH matches one of these patterns (supports `*` globs, e.g.\n * \"/v1/reports/*\"). A full-URL resource is reduced to its pathname before\n * matching (see `resourcePathOf`), so the same pattern works whether the\n * vendor declares \"https://api.x.com/v1/answer\" or \"/v1/answer\". Pair\n * with `vendorHostIn` to scope a path rule to specific vendors.\n */\n resourceIn: 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 * Cumulative spend attributed to THIS intent's `taskContext.taskId`\n * (prior spend on the task plus this payment) exceeds `gt`. Scopes a\n * budget to one unit of work rather than to a window: a research run that\n * is meant to cost a dollar cannot quietly cost fifty, however slowly.\n *\n * An intent carrying no `taskId` cannot be attributed to a task, so the\n * predicate never triggers for one. Requiring attribution is a separate,\n * deliberate rule (deny on `taskIdMissing`), not a side effect of setting\n * a budget — otherwise every untagged probe payment would trip every\n * task budget in the policy.\n */\n taskBudget: z.object({ gt: DecimalString }).optional(),\n /** The intent carries no `taskContext.taskId` (or an empty one). */\n taskIdMissing: z.boolean().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 behavioral circuit breaker: one primitive with three tripwires — a window\n * (rate), a transaction count, and a value cap — measured over the agent's\n * own recent activity.\n *\n * A breaker is not a rule. Rules ask about the intent in front of them; a\n * breaker asks whether the agent's BEHAVIOR has left the envelope it was\n * given, and once it has, every subsequent intent ESCALATES for a signed\n * approval. It never denies on its own: an agent that trips a breaker in the\n * middle of a job must be able to be waved through by a human, because a\n * silent deny at the wrong moment strands the work with no path forward and\n * no one told (the failure mode Flash's exit paths taught).\n *\n * Reset happens two ways, and they are one mechanism: the window rolling\n * forward, or a signed approval, which moves the breaker's counting floor to\n * now. Nothing \"un-trips\" a breaker by decree — the activity simply stops\n * being inside the measured span.\n *\n * Targeting is the policy's job: `appliesTo.agents` / `appliesTo.labels`\n * decide WHICH agents carry the breaker. COUNTING is always per agent — a\n * breaker pooled across every agent sharing a label needs a cross-agent\n * aggregate the per-agent spend context cannot express, and is deferred.\n */\nexport const Breaker = z\n .object({\n id: z.string().min(1),\n /** The trailing span the tripwires measure over. */\n window: Window,\n /**\n * Trip when the window would hold MORE than this many transactions.\n * `10` permits ten in the window and escalates the eleventh.\n */\n txCount: z.number().int().positive().optional(),\n /**\n * Trip when the window's spend would exceed this total. `\"50.00\"` permits\n * a window totalling exactly 50.00 and escalates the payment that would\n * carry it past. Prospective, like every other spend predicate: the\n * payment that would breach the cap is the one that escalates, rather\n * than the innocent one after it.\n */\n valueCap: DecimalString.optional(),\n })\n .refine((b) => b.txCount !== undefined || b.valueCap !== undefined, {\n message: 'a breaker must specify at least one of txCount / valueCap',\n });\nexport type Breaker = z.infer<typeof Breaker>;\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 /**\n * Agent label patterns (supports `*` globs) — semantic targeting. Matches\n * when the agent carries at least one label matching any pattern. Requires\n * the agent DOCUMENT: an intent from an unregistered agent never matches a\n * labels-targeted policy (and so fails closed when no other policy applies).\n */\n labels: 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 /**\n * The org this policy governs. ABSENT means GLOBAL — it is considered for\n * every agent, which is what every policy written before tenancy existed is\n * and stays.\n *\n * This is separate from {@link AppliesTo} on purpose, and it has to be:\n * `appliesTo: {}` matches every agent, so a tenant's policy carrying the\n * default targeting would otherwise govern other tenants' agents the moment\n * it was written. Org scoping is applied BEFORE targeting — a policy whose\n * `orgId` is not the agent's org is not a candidate at all.\n */\n orgId: OrgId.optional(),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n /**\n * Behavioral breakers evaluated alongside the rules. A tripped breaker\n * escalates at the same precedence as an `escalate` rule — so an explicit\n * DENY still wins, and an ALLOW rule cannot wave past a tripped breaker.\n */\n breakers: z.array(Breaker).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';\nimport { AgentId } from './ids.js';\nimport { Window } from './policy.js';\n\n/**\n * Dead-man monitoring: the alarm for an agent that stopped (Phase B2).\n *\n * Every other control in Rein answers \"should this payment happen?\". This one\n * answers the question nothing else in the stack asks: an agent that has gone\n * quiet raises no intent, breaks no budget, and trips no breaker — it simply\n * disappears, and a control plane watching only for bad payments will report\n * a perfectly clean month while the work silently stopped being done. (Flash\n * lost four detectors this way, none of which announced anything.)\n *\n * Three rules hold the design honest, and each is the direct mirror of a rule\n * B1 already established:\n *\n * 1. An expectation is DECLARED, never inferred. Most agents are episodic:\n * they run when there is work. Silence is only evidence for an agent\n * somebody said should be periodic, so an unwatched agent has no liveness\n * state at all — the same rule as `taskBudget`, which never fires on an\n * intent that carries no task id.\n * 2. Silence has an AGE, not a boolean — `late` before `missing` — exactly as\n * a missing settlement is `in-flight` before it is `unsettled`.\n * 3. The engine never alarms about silence it did not witness. An engine that\n * was down cannot tell a dead agent from its own outage, so a silence\n * older than this process reads `unknown` until the process has been up\n * long enough to certify it. B1 refuses to manufacture gaps out of records\n * it cannot join; this refuses to manufacture alarms out of downtime.\n *\n * Liveness is observability and carries no authority whatsoever: it cannot\n * deny, escalate, freeze, or alter any decision. A missing agent is news for\n * a human, not an input to policy.\n */\n\n/** How the engine came to know an agent was alive. */\nexport const LivenessSource = z.enum([\n /** It submitted an intent — ANY outcome, including a denial. */\n 'intent',\n /** It reported in explicitly, having nothing to buy. */\n 'heartbeat',\n]);\nexport type LivenessSource = z.infer<typeof LivenessSource>;\n\n/** Default slack past the interval before silence becomes an alarm. */\nexport const DEFAULT_LIVENESS_GRACE_MS = 60_000;\n\n/**\n * \"This agent is supposed to check in at least this often.\"\n *\n * `graceMs` is what keeps a jittery-but-healthy agent out of the alert\n * channel: an agent on a 15m cadence that lands at 15m04s is not a dead agent,\n * and an alarm that cries at every wobble is one an operator learns to ignore\n * — which is the failure mode that loses the detector nobody was watching.\n */\nexport const LivenessExpectation = z.object({\n agentId: AgentId,\n /** Longest silence still considered normal, e.g. '15m'. */\n interval: Window,\n /** Extra slack past `interval` before the silence is an alarm. */\n graceMs: z.number().int().nonnegative().default(DEFAULT_LIVENESS_GRACE_MS),\n /**\n * When watching began. An agent that has NEVER been seen is measured from\n * here, so a watch on an agent that never starts does raise an alarm — a\n * detector that never came up is exactly as dead as one that stopped.\n */\n since: z.coerce.date(),\n /** What this agent is supposed to be doing, shown beside the alarm. */\n note: z.string().max(200).optional(),\n});\nexport type LivenessExpectation = z.infer<typeof LivenessExpectation>;\n\n/** The registration payload; the engine stamps `since`. */\nexport const LivenessWatchInput = LivenessExpectation.omit({ since: true }).extend({\n graceMs: z.number().int().nonnegative().optional(),\n});\nexport type LivenessWatchInput = z.input<typeof LivenessWatchInput>;\n\n/**\n * An out-of-band \"I am alive\" from an agent with nothing to buy.\n *\n * The engine sees every intent, so a spending agent needs no heartbeat at all.\n * This exists for the agent that is working and simply not paying for\n * anything — without it, a dead-man alarm is really a no-spend alarm, and it\n * would page a human every time an agent had a quiet afternoon.\n *\n * It authorizes nothing. The only thing a heartbeat can change is a row in the\n * liveness report; it cannot lift a breaker, a budget, or a freeze.\n */\nexport const Heartbeat = z.object({\n agentId: AgentId,\n /** When the agent was alive. Defaults to arrival time. */\n at: z.coerce.date().optional(),\n /** Free-form note from the reporter, e.g. \"poll cycle 41 ok\". */\n note: z.string().max(200).optional(),\n});\nexport type Heartbeat = z.infer<typeof Heartbeat>;\n\n/**\n * Where an agent stands against its expectation.\n *\n * - `alive` — seen within the interval.\n * - `late` — past the interval, inside the grace. Not yet news.\n * - `missing` — past both, and this process watched it happen. THE alarm.\n * - `unknown` — past both, but the engine has not been up long enough to have\n * witnessed the silence. Not an alarm: an engine that restarted\n * five minutes ago knows nothing about the last three days.\n */\nexport const LivenessStatus = z.enum(['alive', 'late', 'missing', 'unknown']);\nexport type LivenessStatus = z.infer<typeof LivenessStatus>;\n","import { z } from 'zod';\nimport { AgentId, ApproverKeyId, DecisionId, IntentId, OrgId } from './ids.js';\nimport { Asset, Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * Human approval of an escalated payment.\n *\n * The load-bearing rule: an approval is a SIGNATURE over the decision, made by\n * a key registered with the engine. The delivery channel (Telegram, email,\n * whatever) is transport, never authority — anyone who compromises the channel\n * gets to show a human a message, not to release funds. There is deliberately\n * no click-to-approve path.\n */\n\nexport const ApprovalVerdict = z.enum(['approve', 'reject']);\nexport type ApprovalVerdict = z.infer<typeof ApprovalVerdict>;\n\n/**\n * `pending` is the only non-terminal state. `expired` is what a TTL lapse\n * converts to — indistinguishable from `rejected` in effect (both deny), but\n * distinguished in the record so \"nobody answered\" and \"somebody said no\" stay\n * separable in an audit.\n */\nexport const ApprovalStatus = z.enum(['pending', 'approved', 'rejected', 'expired']);\nexport type ApprovalStatus = z.infer<typeof ApprovalStatus>;\n\n/**\n * A key whose signature the engine accepts as an approval. Public half only —\n * the private half lives with the human (a hardware token, a laptop, an\n * offline signer) and must never reach the engine.\n */\nexport const ApproverKey = z.object({\n id: ApproverKeyId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** ed25519 public key, SPKI PEM — the same encoding as the decision log's. */\n publicKey: z.string().min(1),\n algorithm: z.literal('ed25519').default('ed25519'),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type ApproverKey = z.infer<typeof ApproverKey>;\n\n/**\n * A parked escalation: the payment the engine refused to allow on its own\n * authority, held open until a signature arrives or the TTL lapses. Keyed by\n * the escalating decision — one decision, at most one approval request.\n *\n * The payment facts are copied in rather than referenced so the challenge a\n * human sees is self-contained: amount, vendor and resource are exactly what\n * they are being asked to authorize.\n */\nexport const ApprovalRequest = z.object({\n /** The `escalate` decision this request answers (primary key). */\n decisionId: DecisionId,\n intentId: IntentId,\n /** Binds the approval to the exact transfer — the signed bytes commit to it. */\n intentHash: z.string(),\n agentId: AgentId,\n /**\n * The org the escalating agent belongs to, stamped when the request is\n * parked. ABSENT means the agent was never registered (or the request\n * predates tenancy), and such a request is answerable only by an unscoped\n * operator — there is no org to check an approver against, and guessing one\n * is how a cross-tenant approval happens.\n */\n orgId: OrgId.optional(),\n vendorHost: z.string(),\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n /**\n * Task attribution copied from the intent. Carried so an approved payment\n * still counts against its `taskBudget` — an escalation that lost its task\n * id on the way through would make the budget silently under-count exactly\n * the payments a human had to look at.\n */\n taskId: z.string().optional(),\n /** Why policy escalated, verbatim from the decision. */\n reason: z.string(),\n /**\n * Breaker ids whose trip contributed to this escalation. An approval of\n * this request resets exactly these — moving their counting floor to the\n * approval instant — so a human waving one payment through also clears the\n * behavior that stopped it, rather than being asked again immediately.\n * Empty when ordinary rules did the escalating.\n */\n breakers: z.array(z.string()).default([]),\n status: ApprovalStatus,\n createdAt: z.coerce.date(),\n /** Past this instant the request denies, whatever arrives afterwards. */\n expiresAt: z.coerce.date(),\n resolvedAt: z.coerce.date().optional(),\n /** Which registered key signed — absent when the TTL lapsed instead. */\n approverKeyId: ApproverKeyId.optional(),\n /**\n * The follow-up decision appended to the chain when this resolved. That\n * decision, not this record, is the voucher a signer verifies: the original\n * `escalate` decision is never rewritten.\n */\n finalDecisionId: DecisionId.optional(),\n});\nexport type ApprovalRequest = z.infer<typeof ApprovalRequest>;\n\n/** The two byte-strings an approver may sign for a given request. */\nexport const ApprovalChallenges = z.object({\n approve: z.string(),\n reject: z.string(),\n});\nexport type ApprovalChallenges = z.infer<typeof ApprovalChallenges>;\n\n/**\n * A signed verdict, submitted to the engine by anyone (the signature is the\n * authority, so the carrier does not matter). `signature` is base64 ed25519\n * over `canonicalApproval({ decisionId, intentHash, verdict })`.\n */\nexport const ApprovalGrant = z.object({\n decisionId: DecisionId,\n intentHash: z.string(),\n verdict: ApprovalVerdict,\n approverKeyId: ApproverKeyId,\n signature: z.string().min(1),\n});\nexport type ApprovalGrant = z.infer<typeof ApprovalGrant>;\n\n/** Terminal statuses — a request in one of these will never change again. */\nexport function isResolved(status: ApprovalStatus): boolean {\n return status !== 'pending';\n}\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';\nimport { ApprovalRequest } from './approval.js';\nimport { LivenessExpectation, LivenessSource } from './liveness.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 * `approval.*` is the human-in-the-loop tier: an escalated intent parked for a\n * signature, and the signed (or lapsed) verdict that closed it.\n * `liveness.*` is the dead-man tier (B2), and the only pair here emitted by\n * something NOT happening: a watched agent that went quiet past its expected\n * interval, and the sighting that ended the silence.\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('approval.requested'),\n at: z.coerce.date(),\n request: ApprovalRequest,\n }),\n z.object({\n type: z.literal('approval.resolved'),\n at: z.coerce.date(),\n request: ApprovalRequest,\n /** The follow-up allow/deny decision this resolution appended. */\n decision: Decision,\n }),\n z.object({\n type: z.literal('liveness.missing'),\n at: z.coerce.date(),\n agentId: AgentId,\n expectation: LivenessExpectation,\n /** How long the agent has been silent when the alarm was raised. */\n silentMs: z.number().int().nonnegative(),\n /** Last sighting, absent when the agent was never seen at all. */\n lastSeenAt: z.coerce.date().optional(),\n }),\n z.object({\n type: z.literal('liveness.recovered'),\n at: z.coerce.date(),\n agentId: AgentId,\n /** How long the silence lasted, measured to this sighting. */\n silentMs: z.number().int().nonnegative(),\n source: LivenessSource,\n }),\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 { ApprovalRequest, 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. The payment was never\n * constructed, so no funds moved. Carries the full evidence trail.\n *\n * When the outcome was `escalate`, `approval` carries the parked request — and\n * its `status` says which kind of block this is: `pending` means a signed\n * verdict could still release it (the guard stopped waiting, or was never\n * asked to), while `rejected`/`expired` are final. An absent `approval` on an\n * escalation means the engine has no approval tier at all: nothing can\n * release it.\n */\nexport class PaymentBlockedError extends ReinError {\n constructor(\n readonly intent: PaymentIntent,\n readonly decision: Decision,\n readonly receipt: Receipt,\n readonly approval?: ApprovalRequest,\n ) {\n super(\n `rein blocked payment of ${intent.amount} ${intent.asset} to ${intent.vendor.host}: ` +\n `${decision.outcome}${decision.reason ? ` (${decision.reason})` : ''}` +\n (approval ? ` [approval ${approval.status}]` : ''),\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 {\n Agent,\n ApiKey,\n ApprovalChallenges,\n ApprovalGrant,\n ApprovalRequest,\n ApproverKey,\n AttributedDecision,\n Breaker,\n Decision,\n LivenessExpectation,\n LivenessSource,\n LivenessStatus,\n PaymentIntent,\n Policy,\n SettlementReport,\n type ApiKeyScope,\n} 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\n/**\n * One breaker's standing for one agent, as the engine reports it. Mirrors the\n * engine's `BreakerState`; declared here so the client validates the wire\n * shape rather than trusting it.\n */\nexport const BreakerState = z.object({\n breaker: Breaker,\n policyId: z.string(),\n txCount: z.number(),\n sum: z.string(),\n countingFrom: z.number(),\n resetAt: z.number().optional(),\n tripped: z.boolean(),\n reason: z.string().optional(),\n});\nexport type BreakerState = z.infer<typeof BreakerState>;\n\n/**\n * Where one watched agent stands against its expectation (B2). Mirrors the\n * engine's `LivenessState`; note `unknown`, which is not an alarm — it means\n * the engine has not been up long enough to have witnessed the silence, and a\n * caller that treats it as `missing` would page someone about a restart.\n */\nexport const LivenessState = z.object({\n agentId: z.string(),\n expectation: LivenessExpectation,\n lastSeenAt: z.number().optional(),\n lastSource: LivenessSource.optional(),\n silentSince: z.number(),\n silentMs: z.number(),\n dueAt: z.number(),\n overdueAt: z.number(),\n status: LivenessStatus,\n alertedAt: z.number().optional(),\n});\nexport type LivenessState = z.infer<typeof LivenessState>;\n\nconst Health = z.object({\n status: z.string(),\n publicKey: z.string(),\n /** \"api-key\" once the engine demands a credential; \"none\" while it does not. */\n auth: z.string().optional(),\n approvals: z.string().optional(),\n});\n\n/** What `GET /v1/chain/verify` answers — see {@link EngineClient.verifyChain}. */\nexport const ChainVerdict = z.object({\n intact: z.boolean(),\n /** Decisions this key can see — the same number as `chainLength`. */\n visible: z.number().int().nonnegative(),\n verifiedAt: z.string(),\n /** Index of the first bad link. Unscoped keys only. */\n brokenAt: z.number().int().nonnegative().optional(),\n});\nexport type ChainVerdict = z.infer<typeof ChainVerdict>;\n\nconst EvaluateResponse = z.object({\n intent: PaymentIntent,\n decision: Decision,\n /** Present when an escalation was parked for a signed verdict. */\n approval: ApprovalRequest.optional(),\n});\nexport type EvaluateResponse = z.infer<typeof EvaluateResponse>;\n\n/** A parked escalation plus the bytes to sign and, once resolved, its decision. */\nconst ApprovalView = z.object({\n request: ApprovalRequest,\n challenges: ApprovalChallenges,\n /** The follow-up allow/deny decision, once the request has resolved. */\n decision: Decision.optional(),\n});\nexport type ApprovalView = z.infer<typeof ApprovalView>;\n\nconst ResolveResponse = z.object({ request: ApprovalRequest, decision: Decision });\nexport type ResolveResponse = z.infer<typeof ResolveResponse>;\n\n/**\n * One allowance the settlement facts disagree with (B1): nothing settled\n * behind it, or — `overspent` — a settlement for more than it allowed, with\n * the amount that moved in `settledAmount`. Mirrors the engine's shape.\n */\nexport const AllowanceGap = z.object({\n intentId: z.string(),\n decisionId: z.string().optional(),\n agentId: z.string(),\n host: z.string(),\n resource: z.string(),\n amount: z.string(),\n settledAmount: z.string().optional(),\n taskId: z.string().optional(),\n allowedAt: z.number(),\n ageMs: z.number(),\n state: z.enum(['in-flight', 'unsettled', 'overspent']),\n});\nexport type AllowanceGap = z.infer<typeof AllowanceGap>;\n\n/**\n * The reconciliation report. Declared here so the client validates the wire\n * shape rather than trusting it — and note `settlementsSeen`: zero means this\n * engine has never been told about a settlement, so the gaps below say more\n * about the deployment's wiring than about its payments.\n */\nexport const ReconciliationReport = z.object({\n from: z.number(),\n to: z.number(),\n window: z.string(),\n graceMs: z.number(),\n allowed: z.number(),\n allowedValue: z.string(),\n settled: z.number(),\n settledValue: z.string(),\n inFlight: z.number(),\n inFlightValue: z.string(),\n unsettled: z.number(),\n unsettledValue: z.string(),\n // Optional on the wire so a 0.2.0 engine still validates; absent means the\n // engine predates the check, not that nothing was overspent.\n overspent: z.number().optional(),\n overspentValue: z.string().optional(),\n unattributed: z.number(),\n settlementsSeen: z.number(),\n gaps: z.array(AllowanceGap),\n truncated: z.boolean(),\n});\nexport type ReconciliationReport = z.infer<typeof ReconciliationReport>;\n\nexport interface ReconciliationQuery {\n /** Trailing span of allowances to cover, e.g. '24h'. */\n window?: string;\n /** How long an allowance may go unsettled before it counts as a gap. */\n graceMs?: number;\n limit?: number;\n agentId?: string;\n}\n\nconst IssuedApiKey = z.object({ key: ApiKey, secret: z.string() });\nexport type IssuedApiKey = z.infer<typeof IssuedApiKey>;\n\nexport interface EngineClientOptions {\n /** Base URL of the policy engine, e.g. \"http://localhost:8787\". */\n baseUrl: string;\n /**\n * API-key secret, sent as `Authorization: Bearer`. Required by any engine\n * started with one; omit only for a local engine running without auth.\n */\n apiKey?: string;\n /** Override the transport (tests, custom agents). Defaults to global fetch. */\n fetch?: FetchLike;\n}\n\nexport interface AwaitApprovalOptions {\n /** Give up after this long and return the still-pending view. */\n timeoutMs?: number;\n /** How often to re-read the request. */\n pollMs?: number;\n /** Abort the wait early (an agent loop shutting down). */\n signal?: AbortSignal;\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 private readonly apiKey: string | undefined;\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 this.apiKey = options.apiKey;\n }\n\n /** The transport half: everything but parsing, so a caller can read headers. */\n private async send(method: string, path: string, body?: unknown): Promise<Response> {\n const headers: Record<string, string> = {};\n if (body !== undefined) headers['content-type'] = 'application/json';\n if (this.apiKey) headers['authorization'] = `Bearer ${this.apiKey}`;\n const res = await this.fetchImpl(`${this.baseUrl}${path}`, {\n method,\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n ...(body === undefined ? {} : { body: 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 return res;\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.send(method, path, body);\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 /** Semantic grouping labels (lowercase slugs) — policy `appliesTo.labels` targets these. */\n labels?: Agent['labels'];\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 /**\n * Where the agent's behavioral breakers stand. Read-only: nothing here can\n * trip or clear one — a breaker clears when its window rolls forward or\n * when a signed approval moves its floor.\n */\n breakerStates(agentId: string): Promise<BreakerState[]> {\n return this.request('GET', `/v1/agents/${agentId}/breakers`, z.array(BreakerState));\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 /**\n * The first page of the decision chain (up to 500, the engine's default).\n *\n * On a chain longer than that this is a verifying PREFIX, not the whole log\n * — `prevHash` links check out, but the newest decisions are not here. Use\n * {@link decisionsPage} when you need to walk to the head.\n *\n * Each record carries `agentId` from a 0.3.0 engine -- unsigned, see\n * AttributedDecision -- and lacks it from an older one.\n */\n decisions(): Promise<AttributedDecision[]> {\n return this.request('GET', '/v1/decisions', z.array(AttributedDecision));\n }\n\n /**\n * One page of the decision chain, plus where the next one starts.\n *\n * `nextAfter` is `undefined` at the head of the chain, which is the signal to\n * stop — not an empty page, which a caller polling a live engine would see\n * constantly and could not tell from \"caught up\". Feed it back as `after` to\n * continue; concatenating the pages in order reproduces exactly what the\n * caller is entitled to see, so `verifyDecisionChain` accepts the result.\n *\n * `chainLength` is how many decisions this key can see in total, which for\n * an org-scoped key is its own rows and not the engine's chain.\n */\n async decisionsPage(\n query: { after?: number; limit?: number } = {},\n ): Promise<{ decisions: AttributedDecision[]; nextAfter?: number; chainLength: number }> {\n const params = new URLSearchParams();\n if (query.after !== undefined) params.set('after', String(query.after));\n if (query.limit !== undefined) params.set('limit', String(query.limit));\n const qs = params.toString();\n const res = await this.send('GET', `/v1/decisions${qs ? `?${qs}` : ''}`);\n const decisions = z.array(AttributedDecision).parse(await res.json());\n const next = res.headers.get('rein-next-after');\n const length = res.headers.get('rein-chain-length');\n return {\n decisions,\n ...(next === null ? {} : { nextAfter: Number(next) }),\n // An engine older than this header still answers the route; fall back to\n // what the page itself proves rather than reporting a NaN length.\n chainLength: length === null ? decisions.length : Number(length),\n };\n }\n\n /**\n * The engine's own verdict on its WHOLE decision chain.\n *\n * An org-scoped key reads a SUBSEQUENCE of one chain from `decisionsPage`,\n * whose `prevHash` links lead to rows the key cannot see, so running\n * `verifyDecisionChain` over those pages proves only the links between\n * visible rows. This is the engine verifying every link, including the ones\n * between other tenants' rows, and answering `intact` without showing them.\n * Needs a 0.6.0 engine; an older one answers 404.\n */\n verifyChain(): Promise<ChainVerdict> {\n return this.request('GET', '/v1/chain/verify', ChainVerdict);\n }\n\n // --- Reconciliation (B1) ---\n\n /**\n * Tell the engine an allowed payment landed. The engine watches no chain, so\n * this is how a gap gets closed — by the guard that paid, an indexer, or a\n * facilitator webhook. It authorizes nothing: the only thing a settlement\n * report can change is a line in the reconciliation report.\n */\n reportSettlement(input: z.input<typeof SettlementReport>): Promise<SettlementReport> {\n return this.request('POST', '/v1/settlements', SettlementReport, SettlementReport.parse(input));\n }\n\n /** Which allowances in the window have no settlement behind them. */\n reconciliation(query: ReconciliationQuery = {}): Promise<ReconciliationReport> {\n const params = new URLSearchParams();\n if (query.window !== undefined) params.set('window', query.window);\n if (query.graceMs !== undefined) params.set('graceMs', String(query.graceMs));\n if (query.limit !== undefined) params.set('limit', String(query.limit));\n if (query.agentId !== undefined) params.set('agentId', query.agentId);\n const qs = params.toString();\n return this.request(\n 'GET',\n `/v1/reconciliation${qs ? `?${qs}` : ''}`,\n ReconciliationReport,\n );\n }\n\n // --- Dead-man monitoring (B2) ---\n\n /**\n * Expect this agent to be active at least every `interval`. Watching is\n * declared, never inferred: an agent nobody watches has no liveness state,\n * because silence is only evidence about an agent somebody said should be\n * periodic.\n */\n watchLiveness(\n agentId: string,\n expectation: { interval: string; graceMs?: number; note?: string },\n ): Promise<LivenessExpectation> {\n return this.request('PUT', `/v1/agents/${agentId}/liveness`, LivenessExpectation, expectation);\n }\n\n unwatchLiveness(agentId: string): Promise<void> {\n return this.request('DELETE', `/v1/agents/${agentId}/liveness`, z.void());\n }\n\n /**\n * \"I am alive, I just have nothing to buy.\"\n *\n * Only needed by an agent that goes quiet on purpose — every intent is\n * already a sighting, whatever the engine decided about it. It authorizes\n * nothing: the only thing it can change is a row in the liveness report.\n */\n heartbeat(agentId: string, input: { at?: Date; note?: string } = {}): Promise<LivenessState> {\n return this.request('POST', `/v1/agents/${agentId}/heartbeat`, LivenessState, {\n ...(input.at ? { at: input.at.toISOString() } : {}),\n ...(input.note ? { note: input.note } : {}),\n });\n }\n\n /** Where every watched agent stands. Worst first. */\n liveness(): Promise<LivenessState[]> {\n return this.request('GET', '/v1/liveness', z.array(LivenessState));\n }\n\n // --- API keys (admin scope) ---\n\n /**\n * Mint a key. The secret in the response is the only copy that will exist.\n *\n * `orgId` confines the new key to one tenant and `agentIds` narrows it\n * further to named agents — what an agent runtime should carry, so a stolen\n * key spends one agent's budget rather than the whole org's. Omitting both\n * mints an unscoped operator key, which is what a single-tenant self-hosted\n * engine wants and has always had. A caller that is itself org-scoped has\n * its own org applied regardless of what it asks for here.\n */\n issueApiKey(input: {\n name: string;\n scopes: ApiKeyScope[];\n orgId?: string;\n agentIds?: string[];\n }): Promise<IssuedApiKey> {\n return this.request('POST', '/v1/keys', IssuedApiKey, input);\n }\n\n listApiKeys(): Promise<ApiKey[]> {\n return this.request('GET', '/v1/keys', z.array(ApiKey));\n }\n\n /**\n * Mint a replacement secret. The outgoing one keeps working for `graceMs`\n * (engine default: 1h) so callers can be redeployed one at a time; pass 0\n * when the old secret is compromised and must die now.\n */\n rotateApiKey(keyId: string, options: { graceMs?: number } = {}): Promise<IssuedApiKey> {\n return this.request('POST', `/v1/keys/${keyId}/rotate`, IssuedApiKey, options);\n }\n\n revokeApiKey(keyId: string): Promise<ApiKey> {\n return this.request('POST', `/v1/keys/${keyId}/revoke`, ApiKey);\n }\n\n // --- Approvals ---\n\n /** Register the PUBLIC half of an approver key. The private half never travels. */\n registerApprover(input: { orgId: string; name: string; publicKey: string }): Promise<ApproverKey> {\n return this.request('POST', '/v1/approvers', ApproverKey, input);\n }\n\n listApprovers(): Promise<ApproverKey[]> {\n return this.request('GET', '/v1/approvers', z.array(ApproverKey));\n }\n\n revokeApprover(keyId: string): Promise<ApproverKey> {\n return this.request('POST', `/v1/approvers/${keyId}/revoke`, ApproverKey);\n }\n\n /** Every escalation still answerable right now. */\n pendingApprovals(): Promise<ApprovalRequest[]> {\n return this.request('GET', '/v1/approvals', z.array(ApprovalRequest));\n }\n\n /** One escalation, with the exact bytes to sign for each verdict. */\n approval(decisionId: string): Promise<ApprovalView> {\n return this.request('GET', `/v1/approvals/${decisionId}`, ApprovalView);\n }\n\n /**\n * Submit a signed verdict. The signature is the authority — this call can be\n * made by anyone, from anywhere, including a relay that never sees a key.\n */\n resolveApproval(grant: ApprovalGrant): Promise<ResolveResponse> {\n const { decisionId, ...body } = ApprovalGrant.parse(grant);\n return this.request('POST', `/v1/approvals/${decisionId}/resolve`, ResolveResponse, body);\n }\n\n /**\n * Poll until an escalation resolves, times out, or the caller aborts. The\n * returned view is whatever was true when polling stopped — a caller must\n * check `request.status` rather than assume it resolved.\n */\n async awaitApproval(\n decisionId: string,\n options: AwaitApprovalOptions = {},\n ): Promise<ApprovalView> {\n const pollMs = options.pollMs ?? 1_000;\n const deadline = Date.now() + (options.timeoutMs ?? 300_000);\n for (;;) {\n const view = await this.approval(decisionId);\n if (view.request.status !== 'pending') return view;\n if (options.signal?.aborted || Date.now() + pollMs > deadline) return view;\n await sleep(pollMs, options.signal);\n }\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(done, ms);\n function done(): void {\n clearTimeout(timer);\n signal?.removeEventListener('abort', done);\n resolve();\n }\n signal?.addEventListener('abort', done, { once: true });\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). */\n/**\n * Decimals per asset, from the token contracts -- NOT from the counterparty.\n *\n * `extra.decimals` arrives inside the vendor's own 402 challenge, and it used\n * to be what converted `maxAmountRequired` into the human amount policy is\n * evaluated against. The payer signs the RAW atomic value, so the vendor owned\n * the ratio between the number Rein judged and the number the wallet\n * authorized: quote 500000000 with `decimals: 12` and a 500 USDC charge is\n * evaluated as 0.0005, passes every cap and budget, and settles for 500.\n * Circle's USDC is 6 everywhere it is deployed; USDT and EURC are 6 on Base.\n */\nconst ASSET_DECIMALS: Record<Asset, number> = { USDC: 6, USDT: 6, EURC: 6 };\n\n/** An EVM token address: only the address tables may name one. */\nconst EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;\n\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\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\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 known =\n extraAddresses[requirement.asset] ??\n extraAddresses[requirement.asset.toLowerCase()] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset] ??\n KNOWN_ASSET_ADDRESSES[requirement.asset.toLowerCase()];\n if (known) return known;\n\n // `extra.symbol` is the counterparty's word for its own token, and it is\n // consulted LAST and never for an address. It used to come first, so any\n // EIP-3009 token could present itself as `USDC`: the engine evaluated the\n // agent's USDC caps and budgets, and the payer then signed a\n // TransferWithAuthorization against the attacker's chosen contract, spending\n // a balance no USDC policy was ever written about.\n if (EVM_ADDRESS.test(requirement.asset)) return undefined;\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 undefined;\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\n/**\n * The decimals to read `maxAmountRequired` with.\n *\n * Pass the RESOLVED asset and the answer comes from `ASSET_DECIMALS` -- the\n * token's own precision, which the counterparty does not get a vote on. The\n * no-asset form is the legacy one and still honours `extra.decimals`; it must\n * not be used on any path that leads to a signature.\n */\nexport function requirementDecimals(requirement: PaymentRequirement, asset?: Asset): number {\n if (asset) return ASSET_DECIMALS[asset];\n const decimals = requirement.extra?.['decimals'];\n return typeof decimals === 'number' && Number.isInteger(decimals) && decimals >= 0 ? decimals : 6;\n}\n\n/**\n * Does the vendor's stated precision match the token's? A disagreement is not\n * an error to correct silently -- it is an offer whose amount we cannot agree\n * on, which makes it ungovernable, so `selectRequirement` skips it.\n */\nexport function decimalsAgree(requirement: PaymentRequirement, asset: Asset): boolean {\n const stated = requirement.extra?.['decimals'];\n if (stated === undefined) return true;\n return stated === ASSET_DECIMALS[asset];\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, an allowed network, and a resolvable asset.\n * Returns undefined when no offer qualifies — callers must treat that as\n * fail-closed.\n *\n * `networks` is the testnet/mainnet boundary, and it has to live HERE rather\n * than downstream of evaluate. `networkToChain` folds a testnet onto its\n * mainnet — `base-sepolia` and `base` both become `'base'` — because policy\n * is written about chains, not deployments. That is right for policy and\n * useless as a safety rail: the engine cannot tell a Sepolia offer from a\n * mainnet one, so a testnet agent handed a mainnet 402 would be allowed by\n * every policy it has and would then sign for real money. Filtering before\n * selection is what makes a network allow-list mean anything.\n */\nexport function selectRequirement(\n accepts: readonly PaymentRequirement[],\n extraAddresses: Record<string, Asset> = {},\n networks?: readonly string[],\n): ResolvedRequirement | undefined {\n const allowed = networks?.map(caip2Of);\n for (const requirement of accepts) {\n if (requirement.scheme.toLowerCase() !== 'exact') continue;\n const chain = networkToChain(requirement.network);\n if (!chain) continue;\n if (allowed && !allowed.includes(caip2Of(requirement.network))) continue;\n const asset = resolveAsset(requirement, extraAddresses);\n if (!asset) continue;\n // Fail closed on a token whose precision the vendor states differently\n // from the contract: the amount policy would judge and the amount the\n // wallet would authorize are not the same number.\n if (!decimalsAgree(requirement, asset)) continue;\n const amount = atomicToDecimal(\n requirement.maxAmountRequired,\n requirementDecimals(requirement, asset),\n );\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 { caip2Of, PaymentRequirement } from './x402.js';\n\n// caip2Of/sameNetwork LIVE in x402.ts: selectRequirement's network allow-list\n// needs them, and importing them back up from here would close a cycle\n// through this module's zod consts. Re-exported so the v2 dialect still\n// reads as their home.\nexport { caip2Of, sameNetwork } 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/** 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. */\n/**\n * Build the v2 PaymentRequired a vendor advertises.\n *\n * `extensions` is the spec's open slot for things that are not payment terms\n * -- discovery metadata, for instance. It stays a plain record here rather\n * than a union of known keys: the gate owns what goes in (see\n * `GateRoute.discovery`), and a codec that validated the payload would have\n * to be revised for every extension anyone ever writes. An empty object is\n * still emitted when there is nothing to say, because the field is not\n * optional on the wire.\n */\nexport function buildPaymentRequiredV2(\n requirement: PaymentRequirement,\n error: string,\n extensions: Record<string, unknown> = {},\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 ApprovalRequest,\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 encodeBase64Json,\n parsePaymentRequiredHeader,\n requirementFromV2,\n wrapPaymentV2,\n type PaymentRequiredV2,\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 /**\n * API-key secret for the engine. Required by any engine started with one;\n * without it every call comes back 401 as an EngineError.\n */\n apiKey?: 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 /**\n * The networks this guard will govern payments on, as x402 ids in either\n * dialect (`base-sepolia`, `eip155:8453`, ...). A 402 offering only\n * networks outside the list is treated as an ungovernable paywall and\n * fails closed, BEFORE the engine is asked.\n *\n * Omitted means \"any network the SDK maps to a chain\", which is what every\n * guard got before profiles. Set it on anything holding a real key: the\n * engine cannot enforce this boundary for you, because policy is written\n * about chains and `networkToChain` folds `base-sepolia` into `base` (see\n * selectRequirement). A testnet agent without this list will happily be\n * allowed to pay a mainnet 402.\n */\n networks?: readonly string[];\n /** Called once per receipt, as it is recorded. */\n onReceipt?: (receipt: Receipt) => void;\n /**\n * How many receipts `receipts()` keeps, oldest evicted first. Default 1000.\n * The log is a session convenience; `onReceipt` sees every receipt, capped\n * or not, and is the path for anything that must not lose one. Without a\n * cap a long-lived guard -- an MCP server -- grows without bound.\n */\n maxReceipts?: number;\n /**\n * In advisory mode (no `payer`) an allowed 402 is released upward and its\n * receipt waits for the payment layer's X-PAYMENT retry to settle it. A\n * retry that never comes would leave that entry forever; after this many\n * milliseconds it is forgotten and the receipt stays unsettled -- which\n * reconciliation, not this log, is there to notice. Default 300 000: the\n * x402 authorization window, after which the retry could not pay anyway.\n */\n pendingTtlMs?: number;\n /**\n * Tell the engine when a payment settles, so reconciliation can close the\n * allowance (B1). On by default: without a report from somewhere, every\n * allowance the engine made reads as a gap, and the one component that sees\n * both the decision and the vendor's confirmation is this guard.\n *\n * Best-effort by construction — the report is fired and forgotten, and a\n * failed one never touches the payment. Telemetry must not be able to change\n * a payment's outcome. Set false where an independent indexer reports\n * instead, which is the stronger evidence: a guard reporting its own\n * settlement is the spender vouching for itself.\n */\n reportSettlement?: boolean;\n /**\n * What to do when policy escalates: by default nothing — the payment blocks\n * immediately, exactly as a deny does, and a human can still approve it out\n * of band. Set `await: true` and the guard holds the request open while it\n * waits for a signed verdict, then proceeds on an approval or blocks on a\n * rejection/expiry. Only ever wait where a stalled request is acceptable.\n */\n escalation?: EscalationOptions;\n}\n\nexport interface EscalationOptions {\n /** Hold the request open until the escalation resolves. Default: false. */\n await?: boolean;\n /** Stop waiting after this long, leaving the request pending. Default 5 min. */\n timeoutMs?: number;\n /** How often to re-read the parked request. Default 1s. */\n pollMs?: number;\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 */\nconst DEFAULT_MAX_RECEIPTS = 1000;\nconst DEFAULT_PENDING_TTL_MS = 300_000;\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({\n baseUrl: options.engineUrl,\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\n ...(options.engineFetch ? { fetch: options.engineFetch } : {}),\n });\n }\n\n /** The most recent `maxReceipts` receipts 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, this.options.networks);\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 evaluated = await this.client.evaluate(submission);\n const intent = evaluated.intent;\n let decision = evaluated.decision;\n let approval = evaluated.approval;\n\n // An escalation is a question, not yet an answer. When the caller has\n // opted into waiting, hold here until a signed verdict lands — the\n // decision we continue with is then the engine's FOLLOW-UP decision, the\n // one a signer will accept as a voucher.\n if (decision.outcome === 'escalate' && approval && this.options.escalation?.await) {\n const settled = await this.awaitEscalation(approval);\n approval = settled.request;\n if (settled.decision) decision = settled.decision;\n }\n\n if (decision.outcome !== 'allow') {\n const receipt = this.record(intent, decision, url, init);\n if (this.options.onBlocked === 'respond') return blockedResponse(receipt, approval);\n throw new PaymentBlockedError(intent, decision, receipt, approval);\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.sweepPending();\n this.pendingByUrl.set(url, receipt);\n // Only the offer that was actually evaluated. See ParsedPaywall.narrowed.\n return paywall.narrowed ?? 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 const max = this.options.maxReceipts ?? DEFAULT_MAX_RECEIPTS;\n if (this.log.length > max) this.log.splice(0, this.log.length - max);\n this.options.onReceipt?.(receipt);\n if (settlement) this.announceSettlement(receipt);\n return receipt;\n }\n\n /**\n * Fire-and-forget the settlement fact at the engine. Deliberately silent on\n * failure: a reconciliation report that never arrives leaves a gap open,\n * which is the SAFE direction — an operator sees a payment they must check.\n * Raising here would let telemetry break a payment that already succeeded.\n *\n * The amount is not reported: the guard knows what it was asked to pay, not\n * what the chain moved, and a settlement report should carry only what its\n * reporter actually observed.\n */\n private announceSettlement(receipt: Receipt): void {\n if (this.options.reportSettlement === false) return;\n const txHash = receipt.settlement?.txHash;\n void this.client\n .reportSettlement({\n intentId: receipt.intentId,\n ...(txHash !== undefined ? { txHash } : {}),\n chain: receipt.chain,\n source: 'guard',\n confirmedAt: receipt.createdAt,\n })\n .catch(() => undefined);\n }\n\n /**\n * Wait out a parked escalation. Never waits past the request's own TTL:\n * after that instant the engine can only deny it, so continuing to poll\n * would just be a slower block.\n */\n private async awaitEscalation(request: ApprovalRequest): Promise<ApprovalOutcome> {\n const options = this.options.escalation ?? {};\n const untilExpiry = Math.max(0, request.expiresAt.getTime() - Date.now()) + 1_000;\n const view = await this.client.awaitApproval(request.decisionId, {\n timeoutMs: Math.min(options.timeoutMs ?? 300_000, untilExpiry),\n ...(options.pollMs !== undefined ? { pollMs: options.pollMs } : {}),\n });\n return { request: view.request, ...(view.decision ? { decision: view.decision } : {}) };\n }\n\n /** Drop advisory receipts whose retry window has passed -- see `pendingTtlMs`. */\n private sweepPending(): void {\n const cutoff = Date.now() - (this.options.pendingTtlMs ?? DEFAULT_PENDING_TTL_MS);\n for (const [url, receipt] of this.pendingByUrl) {\n if (receipt.createdAt.getTime() < cutoff) this.pendingByUrl.delete(url);\n }\n }\n\n private settlePending(url: string, res: Response): void {\n this.sweepPending();\n const receipt = this.pendingByUrl.get(url);\n if (!receipt || !res.ok) return;\n const settlement = parseSettlement(res);\n if (settlement) {\n receipt.settlement = settlement;\n this.announceSettlement(receipt);\n }\n this.pendingByUrl.delete(url);\n }\n}\n\n/** How a waited-on escalation came out. */\ninterface ApprovalOutcome {\n request: ApprovalRequest;\n /** The follow-up allow/deny decision, absent while still pending. */\n decision?: Decision;\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 * The same 402 carrying ONLY the offer the guard evaluated.\n *\n * In advisory mode the guard does not pay; it hands the 402 back to the\n * payment layer above, which holds the key. Releasing the vendor's body\n * verbatim meant that layer chose from the FULL `accepts` list -- including\n * the offers the network allow-list had just rejected. A hostile 402 that\n * lists a 0.001 Sepolia offer and a 250 USDC mainnet one gets the cheap one\n * evaluated and allowed, and the expensive one paid, while the receipt and\n * the engine record the cheap one. Narrowing the body is what makes the\n * testnet pin structural rather than advisory.\n */\n narrowed?: Response;\n}\n\n/** Rebuild a 402 carrying a single offer, in whichever dialects it used. */\nfunction narrow402(\n res: Response,\n body: unknown,\n v2: PaymentRequiredV2 | undefined,\n keepV1: PaymentRequirement | undefined,\n keepV2Index: number | undefined,\n): Response {\n const headers = new Headers(res.headers);\n if (v2 && keepV2Index !== undefined) {\n const offer = v2.accepts[keepV2Index];\n if (offer) headers.set('PAYMENT-REQUIRED', encodeBase64Json({ ...v2, accepts: [offer] }));\n }\n let text: string | undefined;\n if (keepV1 && body && typeof body === 'object') {\n text = JSON.stringify({ ...(body as Record<string, unknown>), accepts: [keepV1] });\n headers.delete('content-length');\n }\n return new Response(text ?? res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\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 networks: readonly string[] | undefined,\n): Promise<ParsedPaywall | undefined> {\n const v2 = parsePaymentRequiredHeader(res.headers.get('PAYMENT-REQUIRED'));\n const body = await res\n .clone()\n .json()\n .catch(() => undefined);\n const parsed = PaymentRequired.safeParse(body);\n\n // Which v1 offer (if the body is v1) the guard would govern. Computed even\n // on the v2 path, because a dual-stack 402 answers both and a v1-only layer\n // above would otherwise still read the unfiltered body.\n const v1Resolved = parsed.success\n ? selectRequirement(parsed.data.accepts, assetAddresses, networks)\n : undefined;\n\n if (v2) {\n const asRequirements = v2.accepts.map((offer) => requirementFromV2(offer, v2.resource));\n const resolved = selectRequirement(asRequirements, assetAddresses, networks);\n if (resolved) {\n const index = asRequirements.indexOf(resolved.requirement);\n const narrowed = narrow402(res, body, v2, v1Resolved?.requirement, index);\n return v2.resource !== undefined\n ? { resolved, wire: 2, resource: v2.resource, narrowed }\n : { resolved, wire: 2, narrowed };\n }\n }\n\n if (parsed.success) {\n return {\n resolved: v1Resolved,\n wire: 1,\n ...(v1Resolved\n ? { narrowed: narrow402(res, body, v2, v1Resolved.requirement, undefined) }\n : {}),\n };\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, approval?: ApprovalRequest): 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 // `pending` here means a signed verdict could still release this\n // payment; anything else is final.\n ...(approval\n ? {\n approval: {\n status: approval.status,\n decisionId: approval.decisionId,\n expiresAt: approval.expiresAt.toISOString(),\n },\n }\n : {}),\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","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.4.0",
3
+ "version": "0.5.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.4.0",
43
- "@reinconsole/core": "^0.4.0"
42
+ "@reinconsole/core": "^0.5.1",
43
+ "@reinconsole/sdk": "^0.5.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.4.0"
50
+ "@reinconsole/policy-engine": "0.5.1"
51
51
  },
52
52
  "scripts": {
53
53
  "build": "tsup",