@reinconsole/policy-engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts","../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/agent.ts","../../../packages/core/src/erc8004.ts","../../../packages/core/src/intent.ts","../../../packages/core/src/decision.ts","../../../packages/core/src/canonical.ts","../../../packages/core/src/session.ts","../../../packages/core/src/payment.ts","../../../packages/core/src/receipt.ts","../../../packages/core/src/gate-receipt.ts","../../../packages/core/src/policy.ts","../../../packages/core/src/reputation.ts","../../../packages/core/src/events.ts","../src/engine.ts","../src/evaluator.ts","../src/stores.ts","../src/decision-log.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { fileURLToPath } from 'node:url';\nimport { realpathSync } from 'node:fs';\nimport Fastify, { type FastifyInstance } from 'fastify';\nimport { z } from 'zod';\nimport { Agent, Policy, OrgId, newId } from '@reinconsole/core';\nimport { PolicyEngine, IntentInput } from './engine.js';\n\n/** Input to register an agent (server fills id/createdAt/status). */\nconst AgentInput = z.object({\n orgId: OrgId,\n name: z.string().min(1).max(200),\n erc8004Id: z.string().optional(),\n wallets: Agent.shape.wallets.optional(),\n});\n\n/**\n * Build the policy-engine HTTP API. Pass an engine for tests, or let it create\n * a fresh in-memory one. Returns a Fastify instance (not yet listening).\n */\nexport function buildServer(engine: PolicyEngine = new PolicyEngine()): FastifyInstance {\n const app = Fastify({ logger: false });\n\n // Turn ZodErrors into clean 400s instead of 500s.\n app.setErrorHandler((err: unknown, _req, reply) => {\n if (err instanceof z.ZodError) {\n return reply.status(400).send({ error: 'validation_error', issues: err.issues });\n }\n const message = err instanceof Error ? err.message : String(err);\n return reply.status(500).send({ error: 'internal_error', message });\n });\n\n app.get('/health', () => ({ status: 'ok', publicKey: engine.publicKeyPem }));\n\n // --- Agents ---\n app.post('/v1/agents', (req) => {\n const input = AgentInput.parse(req.body);\n return engine.registerAgent({\n id: newId('agt'),\n orgId: input.orgId,\n name: input.name,\n erc8004Id: input.erc8004Id,\n wallets: input.wallets ?? [],\n status: 'active',\n createdAt: new Date(),\n });\n });\n\n app.get('/v1/agents', () => engine.agents.list());\n\n app.post('/v1/agents/:id/freeze', async (req, reply) => {\n await engine.freeze((req.params as { id: string }).id);\n return reply.status(204).send();\n });\n\n app.post('/v1/agents/:id/unfreeze', async (req, reply) => {\n await engine.unfreeze((req.params as { id: string }).id);\n return reply.status(204).send();\n });\n\n // --- Policies ---\n app.post('/v1/policies', (req) => engine.addPolicy(Policy.parse(req.body)));\n app.get('/v1/policies', () => engine.policies.list());\n\n // --- The hot path ---\n app.post('/v1/evaluate', (req) => engine.evaluateIntent(IntentInput.parse(req.body)));\n\n // --- Audit ---\n app.get('/v1/decisions', () => engine.decisions());\n\n return app;\n}\n\n// Start the server when run directly (tsx/node), not when imported.\nfunction isMainModule(): boolean {\n if (!process.argv[1]) return false;\n try {\n return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));\n } catch {\n return false;\n }\n}\n\nif (isMainModule()) {\n const port = Number(process.env.PORT ?? 8787);\n const host = process.env.HOST ?? '0.0.0.0';\n const app = buildServer();\n app\n .listen({ port, host })\n .then(() => console.log(`[rein] policy-engine listening on http://${host}:${port}`))\n .catch((err) => {\n console.error(err);\n process.exit(1);\n });\n}\n","import { z } from 'zod';\n\n/**\n * Chains Rein observes/governs. x402 is multi-chain; Base and Solana ship\n * first, Polygon and BNB follow. The policy/ledger domain is rail-agnostic —\n * this enum is the only place chains are enumerated.\n */\nexport const Chain = z.enum(['base', 'solana', 'polygon', 'bnb']);\nexport type Chain = z.infer<typeof Chain>;\n\n/** Stablecoins settled over x402. */\nexport const Asset = z.enum(['USDC', 'USDT', 'EURC']);\nexport type Asset = z.infer<typeof Asset>;\n","import { z } from 'zod';\n\n/**\n * Monetary amounts in Rein are always non-negative **decimal strings**, never\n * floats. Float arithmetic silently loses precision on values like 0.1 + 0.2,\n * which is unacceptable for money. All comparison/aggregation goes through the\n * BigInt-backed helpers below.\n */\nexport const DecimalString = z\n .string()\n .regex(/^\\d+(\\.\\d+)?$/, 'must be a non-negative decimal string, e.g. \"5.00\"');\nexport type DecimalString = z.infer<typeof DecimalString>;\n\nconst DECIMAL_RE = /^\\d+(\\.\\d+)?$/;\n\nexport function isValidDecimal(value: string): boolean {\n return DECIMAL_RE.test(value);\n}\n\nfunction assertDecimal(value: string): void {\n if (!isValidDecimal(value)) {\n throw new TypeError(`invalid decimal string: ${JSON.stringify(value)}`);\n }\n}\n\nfunction fractionLength(value: string): number {\n const dot = value.indexOf('.');\n return dot === -1 ? 0 : value.length - dot - 1;\n}\n\n/** Scale a decimal string into an integer BigInt at a fixed number of fraction digits. */\nfunction toScaled(value: string, scale: number): bigint {\n const dot = value.indexOf('.');\n const intPart = dot === -1 ? value : value.slice(0, dot);\n const fracPart = dot === -1 ? '' : value.slice(dot + 1);\n const paddedFrac = (fracPart + '0'.repeat(scale)).slice(0, scale);\n return BigInt(intPart + paddedFrac);\n}\n\n/** Render a scaled BigInt back to a normalized decimal string (no trailing zeros). */\nfunction fromScaled(scaled: bigint, scale: number): string {\n if (scale === 0) return scaled.toString();\n const digits = scaled.toString().padStart(scale + 1, '0');\n const intPart = digits.slice(0, digits.length - scale);\n const fracPart = digits.slice(digits.length - scale).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/** Compare two decimal strings. Returns -1 (a<b), 0 (a==b), or 1 (a>b). */\nexport function compareDecimal(a: string, b: string): -1 | 0 | 1 {\n assertDecimal(a);\n assertDecimal(b);\n const scale = Math.max(fractionLength(a), fractionLength(b));\n const av = toScaled(a, scale);\n const bv = toScaled(b, scale);\n return av < bv ? -1 : av > bv ? 1 : 0;\n}\n\n/** Sum a list of decimal strings without floating-point error. */\nexport function sumDecimal(values: readonly string[]): string {\n if (values.length === 0) return '0';\n let scale = 0;\n for (const v of values) {\n assertDecimal(v);\n scale = Math.max(scale, fractionLength(v));\n }\n let total = 0n;\n for (const v of values) total += toScaled(v, scale);\n return fromScaled(total, scale);\n}\n\n/** Multiply two decimal strings exactly (e.g. median * \"3\" for price-sanity). */\nexport function mulDecimal(a: string, b: string): string {\n assertDecimal(a);\n assertDecimal(b);\n const scaleA = fractionLength(a);\n const scaleB = fractionLength(b);\n const product = toScaled(a, scaleA) * toScaled(b, scaleB);\n return fromScaled(product, scaleA + scaleB);\n}\n\n/** Convenience: a > b. */\nexport function gt(a: string, b: string): boolean {\n return compareDecimal(a, b) === 1;\n}\n\n/** Convenience: a < b. */\nexport function lt(a: string, b: string): boolean {\n return compareDecimal(a, b) === -1;\n}\n","/**\n * Minimal, safe glob matcher supporting only the `*` wildcard (matches any run\n * of characters, including none). Used for vendor host allowlists\n * (e.g. \"*.trusted.io\"), agent-id targeting (e.g. \"agt_research_*\"), and\n * Gate route pricing (e.g. \"/api/reports/*\").\n *\n * Deliberately NOT a regex from user input — the pattern is escaped so a\n * malicious policy value cannot inject regex behavior (ReDoS, etc.).\n */\nexport function globMatch(pattern: string, value: string): boolean {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // escape regex metachars\n const withWildcard = escaped.replace(/\\\\\\*/g, '.*'); // re-enable only `*`\n return new RegExp(`^${withWildcard}$`).test(value);\n}\n\n/** True if `value` matches any pattern in the list. */\nexport function globMatchAny(patterns: readonly string[], value: string): boolean {\n return patterns.some((p) => globMatch(p, value));\n}\n","/**\n * Minimal ULID generation, dependency-free. ULIDs are lexicographically\n * sortable (time-prefixed) and url-safe, which is why Rein uses them for all\n * primary keys instead of UUIDs. Works in Node 22 and modern browsers/edge via\n * the WebCrypto `globalThis.crypto`.\n */\n\n// Crockford's base32 alphabet (excludes I, L, O, U to avoid ambiguity).\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\nfunction encodeTime(now: number): string {\n let time = now;\n let out = '';\n for (let i = TIME_LEN - 1; i >= 0; i--) {\n out = ENCODING.charAt(time % 32) + out;\n time = Math.floor(time / 32);\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n let out = '';\n for (const byte of randomBytes(RANDOM_LEN)) {\n out += ENCODING.charAt(byte % 32);\n }\n return out;\n}\n\n/** Generate a 26-character ULID. */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime) + encodeRandom();\n}\n\n/** Generate a Stripe-style prefixed id, e.g. `newId('agt')` -> `agt_01J...`. */\nexport function newId<P extends string>(prefix: P): `${P}_${string}` {\n return `${prefix}_${ulid()}`;\n}\n","import { z } from 'zod';\n\n/** Crockford base32 ULID body (26 chars), as produced by `ulid()`. */\nconst ULID_BODY = '[0-9A-HJKMNP-TV-Z]{26}';\n\n/**\n * A zod schema for a Stripe-style prefixed ULID, e.g. `agt_01J7...`.\n * Centralizing this keeps id formats consistent across DB rows, API payloads,\n * and SDK types.\n */\nexport function prefixedId(prefix: string) {\n return z\n .string()\n .regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a \"${prefix}_\" prefixed id`);\n}\n\nexport const OrgId = prefixedId('org');\nexport const AgentId = prefixedId('agt');\nexport const PolicyId = prefixedId('pol');\nexport const IntentId = prefixedId('int');\nexport const DecisionId = prefixedId('dec');\nexport const ReceiptId = prefixedId('rcp');\nexport const SessionId = prefixedId('ses');\nexport const GateReceiptId = prefixedId('grc');\n\nexport type OrgId = z.infer<typeof OrgId>;\nexport type AgentId = z.infer<typeof AgentId>;\nexport type PolicyId = z.infer<typeof PolicyId>;\nexport type IntentId = z.infer<typeof IntentId>;\nexport type DecisionId = z.infer<typeof DecisionId>;\nexport type ReceiptId = z.infer<typeof ReceiptId>;\nexport type SessionId = z.infer<typeof SessionId>;\nexport type GateReceiptId = z.infer<typeof GateReceiptId>;\n","import { z } from 'zod';\nimport { AgentId, OrgId } from './ids.js';\nimport { Chain } from './chain.js';\n\n/**\n * Enforcement tier of a given agent wallet:\n * - `observed` — Rein sees spend on-chain but has no control (no SDK either).\n * - `sdk` — agent uses @reinconsole/sdk; advisory + observability (bypassable).\n * - `session-key` — signer-level scope; out-of-policy txs cannot be signed.\n */\nexport const EnforcementMode = z.enum(['observed', 'sdk', 'session-key']);\nexport type EnforcementMode = z.infer<typeof EnforcementMode>;\n\nexport const AgentWallet = z.object({\n chain: Chain,\n address: z.string().min(1),\n mode: EnforcementMode,\n});\nexport type AgentWallet = z.infer<typeof AgentWallet>;\n\nexport const AgentStatus = z.enum(['active', 'frozen']);\nexport type AgentStatus = z.infer<typeof AgentStatus>;\n\nexport const Agent = z.object({\n id: AgentId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** On-chain ERC-8004 identity, if the agent is registered. */\n erc8004Id: z.string().optional(),\n wallets: z.array(AgentWallet).default([]),\n status: AgentStatus.default('active'),\n createdAt: z.coerce.date(),\n});\nexport type Agent = z.infer<typeof Agent>;\n","import { z } from 'zod';\n\n/**\n * The canonical string form of an ERC-8004 agent identity:\n *\n * eip155:{chainId}:{identityRegistry}/{tokenId}\n *\n * The part before the `/` is the spec's registry reference verbatim (the\n * `agentRegistry` field of a registration file, CAIP-10 account form); the\n * tokenId is the ERC-721 id the Identity Registry minted (`agentId` in the\n * spec). This exact string is what `Agent.erc8004Id` / `Vendor.erc8004Id`\n * carry, AND the reputation-subject id a registered agent's evidence keys by.\n *\n * Casing is load-bearing: reputation subject keys for agent-kind ids are\n * case-sensitive unless they start with `0x` (see @reinconsole/graph\n * `normalizeSubject`), and an eip155 string does not. `formatErc8004Id`\n * therefore always emits the registry address in lowercase, and consumers must\n * never hand-build the string — parse then re-format to normalize.\n */\n\nexport interface Erc8004Ref {\n /** EIP-155 chain id (e.g. 8453 Base, 84532 Base Sepolia). */\n chainId: number;\n /** Identity Registry contract address, lowercase 0x-hex. */\n registry: string;\n /** ERC-721 tokenId — the spec's `agentId`. bigint: token ids exceed 2^53. */\n tokenId: bigint;\n}\n\nconst REGISTRY_PATTERN = /^0x[0-9a-fA-F]{40}$/;\nconst ID_PATTERN = /^eip155:(\\d+):(0x[0-9a-fA-F]{40})\\/(\\d+)$/;\n\n/** Build the canonical id string. Throws on a malformed ref (programmer error). */\nexport function formatErc8004Id(ref: Erc8004Ref): string {\n if (!Number.isSafeInteger(ref.chainId) || ref.chainId < 1) {\n throw new RangeError(`erc8004: bad chainId ${ref.chainId}`);\n }\n if (!REGISTRY_PATTERN.test(ref.registry)) {\n throw new RangeError(`erc8004: bad registry address ${ref.registry}`);\n }\n if (typeof ref.tokenId !== 'bigint' || ref.tokenId < 0n) {\n // The typeof guard matters for plain-JS callers: 1.5 < 0n is legal JS and\n // false, and would mint the unparseable \"…/1.5\".\n throw new RangeError(`erc8004: bad tokenId ${ref.tokenId}`);\n }\n return `eip155:${ref.chainId}:${ref.registry.toLowerCase()}/${ref.tokenId}`;\n}\n\n/**\n * Parse a canonical (or hand-written) id string. Accepts any address casing\n * and returns a lowercase ref, or undefined when malformed — so\n * `formatErc8004Id(parseErc8004Id(x)!)` is the normalization step.\n */\nexport function parseErc8004Id(value: string): Erc8004Ref | undefined {\n const match = ID_PATTERN.exec(value);\n if (!match) return undefined;\n const chainId = Number(match[1]);\n if (!Number.isSafeInteger(chainId) || chainId < 1) return undefined;\n return {\n chainId,\n registry: match[2]!.toLowerCase(),\n tokenId: BigInt(match[3]!),\n };\n}\n\n/** Strict boundary schema for the id string (the fields themselves stay free-form). */\nexport const Erc8004Id = z\n .string()\n .refine((value) => parseErc8004Id(value) !== undefined, {\n message: 'expected \"eip155:{chainId}:{registry}/{tokenId}\"',\n });\nexport type Erc8004Id = z.infer<typeof Erc8004Id>;\n","import { z } from 'zod';\nimport { AgentId, IntentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\n\nexport const Vendor = z.object({\n host: z.string().min(1),\n address: z.string().min(1),\n erc8004Id: z.string().optional(),\n});\nexport type Vendor = z.infer<typeof Vendor>;\n\n/**\n * The observability gold: links every micro-payment back to the task and run\n * that caused it, so finance teams can answer \"what was this spend for?\".\n */\nexport const TaskContext = z.object({\n taskId: z.string().optional(),\n parentRunId: z.string().optional(),\n purpose: z.string().max(500).optional(),\n});\nexport type TaskContext = z.infer<typeof TaskContext>;\n\n/**\n * A request to spend, submitted to the policy engine BEFORE any signature is\n * released. The `nonce` provides replay protection on the signer path.\n */\nexport const PaymentIntent = z.object({\n id: IntentId,\n agentId: AgentId,\n vendor: Vendor,\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n nonce: z.string().min(1),\n createdAt: z.coerce.date(),\n});\nexport type PaymentIntent = z.infer<typeof PaymentIntent>;\n","import { z } from 'zod';\nimport { DecisionId, IntentId } from './ids.js';\n\nexport const DecisionOutcome = z.enum(['allow', 'deny', 'escalate']);\nexport type DecisionOutcome = z.infer<typeof DecisionOutcome>;\n\n/**\n * The signed, hash-chained record of a single policy evaluation. Written BEFORE\n * any signature is released. `prevHash` + `hash` form a tamper-evident chain;\n * `signature` is the policy service's signing key over `hash`. The eventual\n * on-chain `txHash` is attached later by the indexer (see SettledPayment).\n */\nexport const Decision = z.object({\n id: DecisionId,\n intentId: IntentId,\n /**\n * sha256 of the intent's canonical content (see canonical.ts). Binds the\n * decision to the exact transfer it judged — amount, recipient, asset,\n * chain — so a signer can verify an {intent, decision} pair offline as a\n * self-contained spend voucher, not just a reference by id.\n */\n intentHash: z.string(),\n outcome: DecisionOutcome,\n /** Ids of the rules that fired, for explainability. */\n matchedRules: z.array(z.string()).default([]),\n /** Human-readable explanation surfaced in the dashboard. */\n reason: z.string().optional(),\n policyId: z.string(),\n policyVersion: z.string(),\n /** Hash of the previous decision in the chain (tamper-evident log). */\n prevHash: z.string(),\n /** Hash of this decision's canonical content. */\n hash: z.string(),\n /** Service signing-key signature over `hash`. */\n signature: z.string(),\n latencyMs: z.number().nonnegative(),\n decidedAt: z.coerce.date(),\n});\nexport type Decision = z.infer<typeof Decision>;\n","import type { PaymentIntent } from './intent.js';\nimport type { DecisionOutcome } from './decision.js';\n\n/**\n * Canonical byte forms shared by the policy engine (which hashes and signs\n * them) and the signer (which verifies them offline). Field order is fixed,\n * dates are ISO strings, and absent optionals are explicit nulls, so the same\n * parsed object always canonicalizes to the same bytes — including after a\n * JSON round-trip over HTTP.\n *\n * These builders are pure (no node:crypto) so @reinconsole/core stays loadable in a\n * browser; services hash the strings with whatever sha256 they have.\n */\n\n/** Canonical form of an intent — what `Decision.intentHash` commits to. */\nexport function canonicalIntent(intent: PaymentIntent): string {\n return JSON.stringify({\n id: intent.id,\n agentId: intent.agentId,\n vendor: {\n host: intent.vendor.host,\n address: intent.vendor.address,\n erc8004Id: intent.vendor.erc8004Id ?? null,\n },\n resource: intent.resource,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: {\n taskId: intent.taskContext.taskId ?? null,\n parentRunId: intent.taskContext.parentRunId ?? null,\n purpose: intent.taskContext.purpose ?? null,\n },\n nonce: intent.nonce,\n createdAt: intent.createdAt.toISOString(),\n });\n}\n\n/** The decision fields covered by `Decision.hash` (and thus its signature). */\nexport interface DecisionContent {\n intentId: string;\n intentHash: string;\n outcome: DecisionOutcome;\n matchedRules: string[];\n policyId: string;\n policyVersion: string;\n prevHash: string;\n decidedAt: Date;\n}\n\n/** Canonical form of a decision — what `Decision.hash` is computed over. */\nexport function canonicalDecision(d: DecisionContent): string {\n return JSON.stringify({\n intentId: d.intentId,\n intentHash: d.intentHash,\n outcome: d.outcome,\n matchedRules: d.matchedRules,\n policyId: d.policyId,\n policyVersion: d.policyVersion,\n prevHash: d.prevHash,\n decidedAt: d.decidedAt.toISOString(),\n });\n}\n","import { z } from 'zod';\nimport { AgentId, SessionId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * A session-key grant: the signer tier's unit of delegated authority. The\n * agent process holds only the bearer token — the wallet key never leaves the\n * signer — and the stored record keeps a hash of the token, never the token\n * itself (it is returned exactly once, at creation).\n *\n * Caps here are the signer-side backstop UNDER whatever policy says: a\n * signature is released only when the engine allowed the intent AND the\n * session has room. Amounts are decimal strings in the asset's human units.\n */\nexport const Session = z.object({\n id: SessionId,\n agentId: AgentId,\n /** sha256 hex of the bearer token. */\n tokenHash: z.string(),\n /** Cumulative ceiling across the session's lifetime. Absent = uncapped. */\n capAmount: DecimalString.optional(),\n /** Ceiling per individual signature. Absent = uncapped. */\n maxPerPayment: DecimalString.optional(),\n expiresAt: z.coerce.date(),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type Session = z.infer<typeof Session>;\n","import { z } from 'zod';\nimport { IntentId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * On-chain confirmation of a settled payment, reconciled by the indexer against\n * the originating intent (amount + recipient + nonce, or facilitator webhook).\n */\nexport const SettledPayment = z.object({\n intentId: IntentId,\n txHash: z.string(),\n chain: Chain,\n blockNumber: z.coerce.bigint(),\n facilitator: z.string().optional(),\n feePaid: DecimalString.optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettledPayment = z.infer<typeof SettledPayment>;\n","import { z } from 'zod';\nimport { ReceiptId, IntentId, DecisionId, AgentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { TaskContext } from './intent.js';\nimport { DecisionOutcome } from './decision.js';\n\n/**\n * What the SDK reports back after settlement: the `X-PAYMENT-RESPONSE` header\n * a vendor returns once payment clears. Mock facilitators fill this in v0.1;\n * the indexer reconciles it against on-chain truth later (see SettledPayment).\n */\nexport const ReceiptSettlement = z.object({\n txHash: z.string().optional(),\n networkId: z.string().optional(),\n /** Raw header payload, kept for forensics until the indexer confirms. */\n raw: z.string().optional(),\n});\nexport type ReceiptSettlement = z.infer<typeof ReceiptSettlement>;\n\n/**\n * The SDK-side record of one guarded payment attempt: which request triggered\n * it, what the engine decided, and (if allowed and paid) how it settled.\n * Receipts are the observability primitive — every 402 the guard touches\n * produces exactly one, whether the payment was allowed or blocked.\n */\nexport const Receipt = z.object({\n id: ReceiptId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n outcome: DecisionOutcome,\n /** The URL the agent actually fetched (the paywalled resource). */\n url: z.string(),\n method: z.string().default('GET'),\n vendorHost: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n /** Human-readable explanation copied from the decision. */\n reason: z.string().optional(),\n /** Present only once a payment was made and the vendor confirmed it. */\n settlement: ReceiptSettlement.optional(),\n createdAt: z.coerce.date(),\n});\nexport type Receipt = z.infer<typeof Receipt>;\n","import { z } from 'zod';\nimport { GateReceiptId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * The vendor-side twin of `Receipt`: one settled x402 payment as the GATE saw\n * it — who paid, for which priced route, and the settlement transaction. The\n * agent-side Receipt records what an agent tried to spend; a GateReceipt\n * records what a vendor actually earned.\n */\nexport const GateReceipt = z.object({\n id: GateReceiptId,\n at: z.coerce.date(),\n /** The route pattern that priced this request, e.g. \"/api/reports/*\". */\n route: z.string().min(1),\n /** The concrete resource paid for (URL path actually requested). */\n resource: z.string().min(1),\n method: z.string().min(1),\n /** The paying wallet address, as asserted by the settled payment. */\n payer: z.string().min(1),\n payTo: z.string().min(1),\n /** Human-unit decimal amount, e.g. \"0.05\". */\n amount: DecimalString,\n /** The same amount in the asset's atomic units, e.g. \"50000\". */\n amountAtomic: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n /** Token symbol or contract address, exactly as quoted in the requirement. */\n asset: z.string().min(1),\n network: z.string().min(1),\n /** Settlement transaction hash (mock ledger or on-chain). */\n transaction: z.string().min(1),\n});\nexport type GateReceipt = z.infer<typeof GateReceipt>;\n","import { z } from 'zod';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/** A rolling-window spec, e.g. \"24h\", \"1h\", \"30m\", \"7d\". */\nexport const Window = z\n .string()\n .regex(/^\\d+[smhd]$/, 'window must be like \"30s\", \"15m\", \"1h\", or \"7d\"');\nexport type Window = z.infer<typeof Window>;\n\n/** A relative multiplier, e.g. \"3x\" (used for price-sanity checks). */\nexport const Multiplier = z.string().regex(/^\\d+(\\.\\d+)?x$/, 'multiplier must be like \"3x\"');\nexport type Multiplier = z.infer<typeof Multiplier>;\n\n/**\n * The set of predicates a rule can test. Multiple predicates in one condition\n * are ANDed together. Each maps to an evaluator in the policy engine.\n */\nexport const Condition = z\n .object({\n /** Per-transaction amount exceeds this value. */\n amountGt: DecimalString.optional(),\n /** Sum of spend in a rolling window exceeds `gt`. */\n rollingSum: z.object({ window: Window, gt: DecimalString }).optional(),\n /** Transaction count in a rolling window exceeds `gt`. */\n txCount: z.object({ window: Window, gt: z.number().int().nonnegative() }).optional(),\n /** Vendor host matches one of these patterns (supports `*` globs). */\n vendorHostIn: z.array(z.string()).optional(),\n /** First time Rein has seen this vendor for the agent. */\n vendorFirstSeen: z.boolean().optional(),\n /** Vendor reputation score is below this threshold (Phase 3 hook). */\n vendorReputationLt: z.number().min(0).max(100).optional(),\n /** Amount is more than `gt`-times the observed median for this resource. */\n amountVsResourceMedian: z.object({ gt: Multiplier }).optional(),\n })\n .refine((c) => Object.values(c).some((v) => v !== undefined), {\n message: 'a condition must specify at least one predicate',\n });\nexport type Condition = z.infer<typeof Condition>;\n\n/**\n * A single rule: an id plus exactly one action (allow / deny / escalate) whose\n * value is the condition that triggers it.\n */\nexport const Rule = z\n .object({\n id: z.string().min(1),\n allow: Condition.optional(),\n deny: Condition.optional(),\n escalate: Condition.optional(),\n })\n .refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== undefined).length === 1, {\n message: 'a rule must specify exactly one of allow / deny / escalate',\n });\nexport type Rule = z.infer<typeof Rule>;\n\nexport const PolicyDefault = z.enum(['allow', 'deny']);\nexport type PolicyDefault = z.infer<typeof PolicyDefault>;\n\nexport const AppliesTo = z.object({\n /** Agent id patterns (supports `*` globs, e.g. \"agt_research_*\"). */\n agents: z.array(z.string()).optional(),\n chains: z.array(Chain).optional(),\n});\nexport type AppliesTo = z.infer<typeof AppliesTo>;\n\nexport const Escalation = z.object({\n approvers: z.array(z.string()).default([]),\n timeoutAction: PolicyDefault.default('deny'),\n timeoutMin: z.number().int().positive().default(15),\n});\nexport type Escalation = z.infer<typeof Escalation>;\n\n/**\n * A declarative, versioned, immutable-once-active policy. Evaluation order in\n * the engine is: explicit DENY > ESCALATE > ALLOW > `default`.\n */\nexport const Policy = z.object({\n policyId: z.string().min(1),\n version: z.string().default('1'),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n default: PolicyDefault.default('deny'),\n /** Below this amount, fail-open is permitted during a policy-service outage. */\n denyFloor: DecimalString.default('0.05'),\n escalation: Escalation.optional(),\n});\nexport type Policy = z.infer<typeof Policy>;\n","import { z } from 'zod';\n\nexport const ReputationSubject = z.object({\n kind: z.enum(['agent', 'vendor']),\n id: z.string(),\n});\nexport type ReputationSubject = z.infer<typeof ReputationSubject>;\n\nexport const ReputationComponents = z.object({\n volume: z.number(),\n longevity: z.number(),\n disputeRate: z.number(),\n counterpartyQuality: z.number(),\n settlementReliability: z.number(),\n});\nexport type ReputationComponents = z.infer<typeof ReputationComponents>;\n\n/**\n * A reputation score for an agent or vendor (Phase 3 — Graph). `confidence` is\n * first-class: a thin-history subject returns LOW confidence rather than a\n * misleadingly high score, so policy can avoid both false trust and unfair\n * freezing.\n */\nexport const ReputationScore = z.object({\n subject: ReputationSubject,\n score: z.number().min(0).max(100),\n components: ReputationComponents,\n confidence: z.number().min(0).max(1),\n asOf: z.coerce.date(),\n /** Hash-anchored attestation, optionally published on-chain (ERC-8004). */\n evidenceUri: z.string().optional(),\n});\nexport type ReputationScore = z.infer<typeof ReputationScore>;\n","import { z } from 'zod';\nimport { AgentId, DecisionId, IntentId, SessionId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { PaymentIntent } from './intent.js';\nimport { Decision } from './decision.js';\nimport { SettledPayment } from './payment.js';\nimport { GateReceipt } from './gate-receipt.js';\n\n/**\n * The canonical event envelope published on the bus (NATS in production).\n * `shadow.spend` is emitted when the indexer sees on-chain spend from a managed\n * wallet with NO corresponding ALLOW decision — the bypass signal that catches\n * SDK-mode evasion and drives the upgrade to the signer tier.\n * `signature.released` / `signature.refused` are that tier's heartbeat: every\n * time the signer does or does not put a key to work, the bus knows why.\n * `gate.*` is the vendor side of the wire: every quote a Gate issues, every\n * payment it accepts, every payment it turns away.\n */\nexport const ReinEvent = z.discriminatedUnion('type', [\n z.object({ type: z.literal('intent.created'), at: z.coerce.date(), intent: PaymentIntent }),\n z.object({ type: z.literal('decision.made'), at: z.coerce.date(), decision: Decision }),\n z.object({ type: z.literal('payment.settled'), at: z.coerce.date(), payment: SettledPayment }),\n z.object({\n type: z.literal('shadow.spend'),\n at: z.coerce.date(),\n agentId: AgentId,\n txHash: z.string(),\n chain: Chain,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.released'),\n at: z.coerce.date(),\n sessionId: SessionId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"decision_replayed\" (see @reinconsole/signer). */\n code: z.string(),\n reason: z.string(),\n sessionId: SessionId.optional(),\n agentId: AgentId.optional(),\n intentId: IntentId.optional(),\n }),\n z.object({\n type: z.literal('gate.quoted'),\n at: z.coerce.date(),\n resource: z.string(),\n method: z.string(),\n amount: DecimalString,\n asset: z.string(),\n network: z.string(),\n }),\n z.object({ type: z.literal('gate.settled'), at: z.coerce.date(), receipt: GateReceipt }),\n z.object({\n type: z.literal('gate.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"payment_replayed\" (see @reinconsole/gate). */\n code: z.string(),\n reason: z.string(),\n resource: z.string(),\n /** Known only when the payment header decoded far enough to name a payer. */\n payer: z.string().optional(),\n }),\n]);\nexport type ReinEvent = z.infer<typeof ReinEvent>;\n","import { EventEmitter } from 'node:events';\nimport { createHash } from 'node:crypto';\nimport { performance } from 'node:perf_hooks';\nimport { z } from 'zod';\nimport {\n canonicalIntent,\n newId,\n PaymentIntent,\n Vendor,\n TaskContext,\n Asset,\n Chain,\n AgentId,\n IntentId,\n DecimalString,\n Agent,\n Policy,\n type Decision,\n type ReinEvent,\n} from '@reinconsole/core';\nimport { evaluate, type EvaluationResult } from './evaluator.js';\nimport {\n InMemorySpendStore,\n InMemoryPolicyStore,\n InMemoryAgentRegistry,\n type SpendStorePort,\n type PolicyStorePort,\n type AgentRegistryPort,\n} from './stores.js';\nimport { DecisionLog } from './decision-log.js';\n\n/** The shape an SDK/client submits. Server-assigned fields are optional. */\nexport const IntentInput = z.object({\n id: IntentId.optional(),\n agentId: AgentId,\n vendor: Vendor,\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.optional(),\n nonce: z.string().min(1).optional(),\n createdAt: z.coerce.date().optional(),\n});\nexport type IntentInput = z.input<typeof IntentInput>;\n\nexport interface EvaluateOutput {\n intent: PaymentIntent;\n decision: Decision;\n}\n\n/** The persistence seams the engine composes over (in-memory when omitted). */\nexport interface EngineStores {\n spend?: SpendStorePort;\n policies?: PolicyStorePort;\n agents?: AgentRegistryPort;\n /** Pre-built decision log (e.g. persistent key + resumed chain from @reinconsole/store). */\n log?: DecisionLog;\n}\n\n/**\n * The policy engine: normalizes intents, applies the kill-switch, evaluates\n * policy, writes a signed decision, emits events, and (on ALLOW) records the\n * spend so rolling budgets/velocity update. Stores are injectable: in-memory\n * by default, durable via @reinconsole/store. Writes are awaited before returning;\n * evaluations are serialized so concurrent intents cannot read a rolling\n * budget before an earlier allow has recorded its spend.\n */\nexport class PolicyEngine {\n readonly spend: SpendStorePort;\n readonly policies: PolicyStorePort;\n readonly agents: AgentRegistryPort;\n private readonly log: DecisionLog;\n private readonly bus = new EventEmitter();\n private tail: Promise<unknown> = Promise.resolve();\n\n constructor(stores: EngineStores = {}) {\n this.spend = stores.spend ?? new InMemorySpendStore();\n this.policies = stores.policies ?? new InMemoryPolicyStore();\n this.agents = stores.agents ?? new InMemoryAgentRegistry();\n this.log = stores.log ?? new DecisionLog();\n }\n\n get publicKeyPem(): string {\n return this.log.publicKeyPem;\n }\n\n onEvent(handler: (event: ReinEvent) => void): void {\n this.bus.on('event', handler);\n }\n\n private emit(event: ReinEvent): void {\n this.bus.emit('event', event);\n }\n\n async registerAgent(input: z.input<typeof Agent>): Promise<Agent> {\n const agent = Agent.parse(input);\n await this.agents.register(agent);\n return agent;\n }\n\n async addPolicy(input: z.input<typeof Policy>): Promise<Policy> {\n const policy = Policy.parse(input);\n await this.policies.add(policy);\n return policy;\n }\n\n async freeze(agentId: string): Promise<void> {\n await this.agents.freeze(agentId);\n }\n\n async unfreeze(agentId: string): Promise<void> {\n await this.agents.unfreeze(agentId);\n }\n\n private normalize(input: IntentInput): PaymentIntent {\n return PaymentIntent.parse({\n id: input.id ?? newId('int'),\n agentId: input.agentId,\n vendor: input.vendor,\n resource: input.resource,\n amount: input.amount,\n asset: input.asset,\n chain: input.chain,\n taskContext: input.taskContext ?? {},\n nonce: input.nonce ?? newId('non'),\n createdAt: input.createdAt ?? new Date(),\n });\n }\n\n evaluateIntent(input: IntentInput): Promise<EvaluateOutput> {\n const run = this.tail.then(() => this.evaluateSerialized(input));\n this.tail = run.catch(() => undefined); // a failed evaluate must not wedge the queue\n return run;\n }\n\n private async evaluateSerialized(input: IntentInput): Promise<EvaluateOutput> {\n const start = performance.now();\n const intent = this.normalize(input);\n this.emit({ type: 'intent.created', at: new Date(), intent });\n\n let result: EvaluationResult;\n if (this.agents.isFrozen(intent.agentId)) {\n result = {\n outcome: 'deny',\n matchedRules: ['agent-frozen'],\n reason: 'agent is frozen (kill switch)',\n policyId: 'system',\n policyVersion: '0',\n };\n } else {\n const ctx = this.spend.contextFor(intent.agentId, intent.createdAt.getTime());\n result = evaluate(intent, this.policies.list(), ctx);\n }\n\n const latencyMs = performance.now() - start;\n const intentHash = createHash('sha256').update(canonicalIntent(intent)).digest('hex');\n const decision = await this.log.append({\n ...result,\n intentId: intent.id,\n intentHash,\n latencyMs,\n });\n this.emit({ type: 'decision.made', at: new Date(), decision });\n\n if (decision.outcome === 'allow') {\n // Optimistically count the spend; the indexer confirms settlement later.\n await this.spend.record({\n agentId: intent.agentId,\n host: intent.vendor.host,\n resource: intent.resource,\n amount: intent.amount,\n at: intent.createdAt.getTime(),\n });\n }\n\n return { intent, decision };\n }\n\n decisions(): readonly Decision[] {\n return this.log.all();\n }\n}\n","import {\n type Policy,\n type PaymentIntent,\n type Condition,\n type DecisionOutcome,\n type Window,\n gt,\n sumDecimal,\n mulDecimal,\n globMatchAny,\n} from '@reinconsole/core';\n\n/**\n * The data the evaluator needs about an agent's history to test predicates.\n * Resolved synchronously per intent (in-memory today; pre-resolved from the\n * DB/Timescale continuous aggregates in production). All sums/counts reflect\n * PRIOR activity — the evaluator adds the current intent itself.\n */\nexport interface SpendContext {\n rollingSum(window: Window): string;\n txCount(window: Window): number;\n isVendorFirstSeen(host: string): boolean;\n vendorReputation(host: string): number | undefined;\n resourceMedian(resource: string): string | undefined;\n}\n\nexport interface EvaluationResult {\n outcome: DecisionOutcome;\n matchedRules: string[];\n reason: string;\n policyId: string;\n policyVersion: string;\n}\n\n/** Does this policy target the given intent's agent + chain? */\nexport function policyApplies(policy: Policy, intent: PaymentIntent): boolean {\n const { agents, chains } = policy.appliesTo;\n if (chains && !chains.includes(intent.chain)) return false;\n if (agents && agents.length > 0 && !globMatchAny(agents, intent.agentId)) return false;\n return true;\n}\n\n/**\n * Evaluate a single condition. All present predicates are ANDed. This is the\n * sandbox boundary: only these typed predicates exist — there is no arbitrary\n * code execution from policy input.\n */\nexport function conditionMatches(\n cond: Condition,\n intent: PaymentIntent,\n ctx: SpendContext,\n): boolean {\n if (cond.amountGt !== undefined && !gt(intent.amount, cond.amountGt)) return false;\n\n if (cond.rollingSum) {\n // Prospective: prior spend in window + this payment.\n const prospective = sumDecimal([ctx.rollingSum(cond.rollingSum.window), intent.amount]);\n if (!gt(prospective, cond.rollingSum.gt)) return false;\n }\n\n if (cond.txCount) {\n const prospective = ctx.txCount(cond.txCount.window) + 1;\n if (prospective <= cond.txCount.gt) return false;\n }\n\n if (cond.vendorHostIn && !globMatchAny(cond.vendorHostIn, intent.vendor.host)) return false;\n\n if (\n cond.vendorFirstSeen !== undefined &&\n ctx.isVendorFirstSeen(intent.vendor.host) !== cond.vendorFirstSeen\n ) {\n return false;\n }\n\n if (cond.vendorReputationLt !== undefined) {\n const rep = ctx.vendorReputation(intent.vendor.host);\n // No reputation data => indeterminate => do not trigger (avoid unfair freeze).\n if (rep === undefined || !(rep < cond.vendorReputationLt)) return false;\n }\n\n if (cond.amountVsResourceMedian) {\n const med = ctx.resourceMedian(intent.resource);\n if (med === undefined) return false;\n const factor = cond.amountVsResourceMedian.gt.replace(/x$/, '');\n if (!gt(intent.amount, mulDecimal(med, factor))) return false;\n }\n\n return true;\n}\n\nfunction actionOf(rule: Policy['rules'][number]): { action: DecisionOutcome; cond: Condition } {\n if (rule.deny) return { action: 'deny', cond: rule.deny };\n if (rule.escalate) return { action: 'escalate', cond: rule.escalate };\n return { action: 'allow', cond: rule.allow as Condition };\n}\n\n/**\n * Evaluate an intent against the applicable policies.\n *\n * Precedence (per the technical doc §3.3): explicit DENY > ESCALATE > ALLOW >\n * policy default. v0.1 selects the FIRST applicable policy (deterministic by\n * insertion order); overlapping-policy merge is a documented future item. When\n * no policy applies, we fail closed (deny).\n */\nexport function evaluate(\n intent: PaymentIntent,\n policies: readonly Policy[],\n ctx: SpendContext,\n): EvaluationResult {\n const policy = policies.find((p) => policyApplies(p, intent));\n if (!policy) {\n return {\n outcome: 'deny',\n matchedRules: [],\n reason: 'no applicable policy (fail-closed default)',\n policyId: 'none',\n policyVersion: '0',\n };\n }\n\n const denies: string[] = [];\n const escalates: string[] = [];\n const allows: string[] = [];\n\n for (const rule of policy.rules) {\n const { action, cond } = actionOf(rule);\n if (!conditionMatches(cond, intent, ctx)) continue;\n if (action === 'deny') denies.push(rule.id);\n else if (action === 'escalate') escalates.push(rule.id);\n else allows.push(rule.id);\n }\n\n const base = { policyId: policy.policyId, policyVersion: policy.version };\n if (denies.length > 0) {\n return { outcome: 'deny', matchedRules: denies, reason: `denied by: ${denies.join(', ')}`, ...base };\n }\n if (escalates.length > 0) {\n return {\n outcome: 'escalate',\n matchedRules: escalates,\n reason: `escalated by: ${escalates.join(', ')}`,\n ...base,\n };\n }\n if (allows.length > 0) {\n return { outcome: 'allow', matchedRules: allows, reason: `allowed by: ${allows.join(', ')}`, ...base };\n }\n return {\n outcome: policy.default,\n matchedRules: [],\n reason: `no rule matched; policy default = ${policy.default}`,\n ...base,\n };\n}\n","import { type Agent, type Policy, type Window, sumDecimal, compareDecimal } from '@reinconsole/core';\nimport { policyApplies, type SpendContext } from './evaluator.js';\n\n/**\n * One observed/pending spend event. The lightweight in-memory stores here\n * implement the ports the engine depends on; @reinconsole/store swaps in\n * Postgres-backed implementations without touching the engine.\n */\nexport interface SpendRecord {\n agentId: string;\n host: string;\n resource: string;\n amount: string;\n at: number; // epoch ms\n}\n\nexport type MaybePromise<T> = T | Promise<T>;\n\n/**\n * The persistence seams the engine depends on. Writes may be asynchronous (a\n * durable store awaits them before returning, so nothing the engine acted on\n * can be lost); reads are synchronous from the store's hydrated working set,\n * which keeps the hot evaluate path and console state snapshots simple.\n */\nexport interface SpendStorePort {\n record(rec: SpendRecord): MaybePromise<void>;\n setVendorReputation(host: string, score: number): MaybePromise<void>;\n /** Resolve a point-in-time spend context for one agent (prior activity only). */\n contextFor(agentId: string, now?: number): SpendContext;\n}\n\nexport interface PolicyStorePort {\n /** Upsert by policyId; an updated policy moves to the END of evaluation order. */\n add(policy: Policy): MaybePromise<void>;\n list(): Policy[];\n get(policyId: string): Policy | undefined;\n}\n\nexport interface AgentRegistryPort {\n register(agent: Agent): MaybePromise<void>;\n get(id: string): Agent | undefined;\n list(): Agent[];\n freeze(id: string): MaybePromise<void>;\n unfreeze(id: string): MaybePromise<void>;\n isFrozen(id: string): boolean;\n}\n\nconst WINDOW_MS: Record<string, number> = { s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000 };\n\nexport function parseWindowMs(window: Window): number {\n const match = /^(\\d+)([smhd])$/.exec(window);\n if (!match) throw new TypeError(`invalid window: ${window}`);\n const unit = WINDOW_MS[match[2] as string];\n return Number(match[1]) * (unit ?? 0);\n}\n\nfunction within(records: readonly SpendRecord[], window: Window, now: number): SpendRecord[] {\n const cutoff = now - parseWindowMs(window);\n return records.filter((r) => r.at >= cutoff);\n}\n\n/** Approximate median (upper-median for even counts; division-free). */\nfunction median(values: readonly string[]): string | undefined {\n if (values.length === 0) return undefined;\n const sorted = [...values].sort(compareDecimal);\n return sorted[Math.floor(sorted.length / 2)];\n}\n\nexport class InMemorySpendStore implements SpendStorePort {\n private readonly records: SpendRecord[] = [];\n private readonly reputations = new Map<string, number>();\n\n record(rec: SpendRecord): void {\n this.records.push(rec);\n }\n\n setVendorReputation(host: string, score: number): void {\n this.reputations.set(host, score);\n }\n\n /** Resolve a point-in-time spend context for one agent (prior activity only). */\n contextFor(agentId: string, now: number = Date.now()): SpendContext {\n const mine = this.records.filter((r) => r.agentId === agentId);\n const reputations = this.reputations;\n const all = this.records;\n return {\n rollingSum: (window) => sumDecimal(within(mine, window, now).map((r) => r.amount)),\n txCount: (window) => within(mine, window, now).length,\n isVendorFirstSeen: (host) => !mine.some((r) => r.host === host),\n vendorReputation: (host) => reputations.get(host),\n resourceMedian: (resource) =>\n median(all.filter((r) => r.resource === resource).map((r) => r.amount)),\n };\n }\n}\n\nexport class InMemoryPolicyStore implements PolicyStorePort {\n private policies: Policy[] = [];\n\n /** Upsert by policyId (a new version replaces the prior one). */\n add(policy: Policy): void {\n this.policies = this.policies.filter((p) => p.policyId !== policy.policyId);\n this.policies.push(policy);\n }\n\n list(): Policy[] {\n return this.policies;\n }\n\n get(policyId: string): Policy | undefined {\n return this.policies.find((p) => p.policyId === policyId);\n }\n\n applicableFor(intent: Parameters<typeof policyApplies>[1]): Policy[] {\n return this.policies.filter((p) => policyApplies(p, intent));\n }\n}\n\nexport class InMemoryAgentRegistry implements AgentRegistryPort {\n private readonly agents = new Map<string, Agent>();\n private readonly frozen = new Set<string>();\n\n register(agent: Agent): void {\n this.agents.set(agent.id, agent);\n if (agent.status === 'frozen') this.frozen.add(agent.id);\n }\n\n get(id: string): Agent | undefined {\n return this.agents.get(id);\n }\n\n list(): Agent[] {\n return [...this.agents.values()];\n }\n\n freeze(id: string): void {\n this.frozen.add(id);\n }\n\n unfreeze(id: string): void {\n this.frozen.delete(id);\n }\n\n isFrozen(id: string): boolean {\n return this.frozen.has(id);\n }\n}\n","import {\n createHash,\n generateKeyPairSync,\n sign as edSign,\n verify as edVerify,\n createPublicKey,\n type KeyObject,\n} from 'node:crypto';\nimport { canonicalDecision, newId, type Decision, type DecisionOutcome } from '@reinconsole/core';\nimport type { MaybePromise } from './stores.js';\n\nexport interface DecisionInput {\n intentId: string;\n /** sha256 of the intent's canonical content — binds the decision to the exact transfer. */\n intentHash: string;\n outcome: DecisionOutcome;\n matchedRules: string[];\n reason: string;\n policyId: string;\n policyVersion: string;\n latencyMs: number;\n}\n\nexport interface DecisionLogKeyPair {\n privateKey: KeyObject;\n publicKey: KeyObject;\n}\n\nexport interface DecisionLogOptions {\n /** Signing key. Generated per instance when omitted (prod: KMS / @reinconsole/store). */\n keyPair?: DecisionLogKeyPair;\n /**\n * A previously persisted chain to resume, verbatim (entries are already\n * hashed and signed). New appends continue from the last entry's hash, so\n * the chain stays verifiable across restarts — provided `keyPair` is the\n * same key that signed the resumed entries.\n */\n resume?: readonly Decision[];\n /**\n * Durable sink, awaited BEFORE an append is applied or returned: a decision\n * either exists in the store and the chain, or in neither.\n */\n persist?: (decision: Decision) => MaybePromise<void>;\n}\n\n/**\n * Append-only, tamper-evident decision log. Each decision is sha256-hashed over\n * its canonical content + the previous hash (a hash chain), then signed with an\n * ed25519 service key. Appends are serialized internally so concurrent calls\n * cannot fork the chain. Verifiable end-to-end via {@link verifyDecisionChain}.\n */\nexport class DecisionLog {\n private prevHash: string;\n private readonly privateKey: KeyObject;\n readonly publicKeyPem: string;\n private readonly chain: Decision[];\n private readonly persist: ((decision: Decision) => MaybePromise<void>) | undefined;\n private tail: Promise<unknown> = Promise.resolve();\n\n constructor(options: DecisionLogOptions = {}) {\n const kp = options.keyPair ?? generateKeyPairSync('ed25519');\n this.privateKey = kp.privateKey;\n this.publicKeyPem = kp.publicKey.export({ type: 'spki', format: 'pem' }).toString();\n this.chain = [...(options.resume ?? [])];\n this.prevHash = this.chain.at(-1)?.hash ?? 'genesis';\n this.persist = options.persist;\n }\n\n append(input: DecisionInput): Promise<Decision> {\n const run = this.tail.then(() => this.appendSerialized(input));\n this.tail = run.catch(() => undefined); // a failed append must not wedge the queue\n return run;\n }\n\n private async appendSerialized(input: DecisionInput): Promise<Decision> {\n const decidedAt = new Date();\n const hash = createHash('sha256')\n .update(canonicalDecision({ ...input, prevHash: this.prevHash, decidedAt }))\n .digest('hex');\n const signature = edSign(null, Buffer.from(hash), this.privateKey).toString('base64');\n\n const decision: Decision = {\n id: newId('dec'),\n intentId: input.intentId,\n intentHash: input.intentHash,\n outcome: input.outcome,\n matchedRules: input.matchedRules,\n reason: input.reason,\n policyId: input.policyId,\n policyVersion: input.policyVersion,\n prevHash: this.prevHash,\n hash,\n signature,\n latencyMs: input.latencyMs,\n decidedAt,\n };\n // Durable first: if the sink throws, neither store nor chain advances.\n if (this.persist) await this.persist(decision);\n this.prevHash = hash;\n this.chain.push(decision);\n return decision;\n }\n\n all(): readonly Decision[] {\n return this.chain;\n }\n}\n\n/** Recompute the hash chain and verify every signature. */\nexport function verifyDecisionChain(\n decisions: readonly Decision[],\n publicKeyPem: string,\n): boolean {\n const publicKey = createPublicKey(publicKeyPem);\n let prev = 'genesis';\n for (const d of decisions) {\n if (d.prevHash !== prev) return false;\n const hash = createHash('sha256').update(canonicalDecision(d)).digest('hex');\n if (hash !== d.hash) return false;\n if (!edVerify(null, Buffer.from(d.hash), publicKey, Buffer.from(d.signature, 'base64'))) {\n return false;\n }\n prev = d.hash;\n }\n return true;\n}\n"],"mappings":"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","names":["z","z","z","z","createHash","z","z","createHash","z"]}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@reinconsole/policy-engine",
3
+ "version": "0.1.0",
4
+ "description": "Rein policy evaluation service — sandboxed declarative rule engine with hash-chained, signed decisions.",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/bugiiiii11/rein#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/bugiiiii11/rein.git",
10
+ "directory": "services/policy-engine"
11
+ },
12
+ "bugs": "https://github.com/bugiiiii11/rein/issues",
13
+ "keywords": [
14
+ "rein",
15
+ "x402",
16
+ "policy",
17
+ "spend-control",
18
+ "ai-agents",
19
+ "agent-payments",
20
+ "audit-log"
21
+ ],
22
+ "engines": {
23
+ "node": ">=22"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "type": "module",
29
+ "sideEffects": [
30
+ "./dist/server.js"
31
+ ],
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "import": "./dist/index.js"
36
+ }
37
+ },
38
+ "main": "./dist/index.js",
39
+ "types": "./dist/index.d.ts",
40
+ "files": [
41
+ "dist"
42
+ ],
43
+ "bin": {
44
+ "rein-policy-engine": "./dist/server.js"
45
+ },
46
+ "dependencies": {
47
+ "fastify": "^5.2.0",
48
+ "zod": "^3.24.1",
49
+ "@reinconsole/core": "^0.1.0"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^22.10.0",
53
+ "tsup": "^8.3.5",
54
+ "tsx": "^4.19.2",
55
+ "typescript": "^5.7.2",
56
+ "vitest": "^2.1.8"
57
+ },
58
+ "scripts": {
59
+ "build": "tsup",
60
+ "dev": "tsx watch src/server.ts",
61
+ "start": "node dist/server.js",
62
+ "typecheck": "tsc --noEmit",
63
+ "test": "vitest run",
64
+ "test:watch": "vitest",
65
+ "clean": "rimraf dist .turbo"
66
+ }
67
+ }