@x402sentinel/x402 0.1.1 → 0.1.2

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.cjs CHANGED
@@ -681,9 +681,19 @@ function validateConfig(config) {
681
681
  }
682
682
 
683
683
  // src/wrapper/headers.ts
684
- function parsePaymentRequired(header) {
685
- const json = Buffer.from(header, "base64").toString("utf-8");
686
- return JSON.parse(json);
684
+ function parsePaymentHeader(header) {
685
+ try {
686
+ return JSON.parse(Buffer.from(header, "base64").toString("utf-8"));
687
+ } catch {
688
+ try {
689
+ return JSON.parse(header);
690
+ } catch {
691
+ return null;
692
+ }
693
+ }
694
+ }
695
+ function normalizeAmountToUSDC(raw) {
696
+ return chunk7H4FRU7K_cjs.formatUSDC(BigInt(raw));
687
697
  }
688
698
  function parsePaymentResponse(header) {
689
699
  if (!header) return null;
@@ -725,7 +735,7 @@ function beforeRequest(url, init, deps) {
725
735
  };
726
736
  if (deps.budgetManager) {
727
737
  const eval_ = deps.budgetManager.evaluate(context);
728
- if (!eval_.allowed && eval_.violation.type === "blocked_endpoint") {
738
+ if (!eval_.allowed) {
729
739
  return { proceed: false, context, evaluation: eval_ };
730
740
  }
731
741
  }
@@ -738,6 +748,13 @@ async function afterResponse(response, context, startTime, deps) {
738
748
  const settlement = parsePaymentResponse(paymentResponseHeader);
739
749
  if (settlement) {
740
750
  context.network = settlement.network ?? context.network;
751
+ if (context.amount === "0.000000") {
752
+ const cachedAmount = deps.priceCache.get(context.endpoint);
753
+ if (cachedAmount) {
754
+ context.amount = cachedAmount;
755
+ deps.priceCache.delete(context.endpoint);
756
+ }
757
+ }
741
758
  const policyEvaluation = determinePolicyEvaluation(context, deps);
742
759
  let budgetRemaining = null;
743
760
  if (deps.budgetManager && context.amount !== "0.000000") {
@@ -773,21 +790,32 @@ async function afterResponse(response, context, startTime, deps) {
773
790
  }
774
791
  }
775
792
  if (response.status === 402) {
776
- const paymentRequiredHeader = response.headers.get("payment-required");
777
- if (paymentRequiredHeader) {
793
+ const rawHeader = response.headers.get("payment-required") || response.headers.get("x-payment");
794
+ if (rawHeader) {
778
795
  try {
779
- const paymentRequired = parsePaymentRequired(paymentRequiredHeader);
780
- const extracted = extractFromPaymentRequired(paymentRequired);
781
- if (extracted) {
782
- context.amount = extracted.amount;
783
- context.asset = extracted.asset;
784
- context.network = extracted.network;
785
- context.scheme = extracted.scheme;
786
- context.payTo = extracted.payTo;
796
+ const paymentRequired = parsePaymentHeader(rawHeader);
797
+ if (paymentRequired) {
798
+ const extracted = extractFromPaymentRequired(paymentRequired);
799
+ if (extracted) {
800
+ const humanAmount = normalizeAmountToUSDC(extracted.amount);
801
+ context.amount = humanAmount;
802
+ context.asset = extracted.asset;
803
+ context.network = extracted.network;
804
+ context.scheme = extracted.scheme;
805
+ context.payTo = extracted.payTo;
806
+ deps.priceCache.set(context.endpoint, humanAmount);
807
+ }
787
808
  }
788
809
  } catch {
789
810
  }
790
811
  }
812
+ if (deps.budgetManager && context.amount !== "0.000000") {
813
+ const eval_ = deps.budgetManager.evaluate(context);
814
+ if (!eval_.allowed) {
815
+ await logBlocked(context, eval_.violation, deps);
816
+ throw new SentinelBudgetError(eval_.violation);
817
+ }
818
+ }
791
819
  const record = enrichRecord({
792
820
  context,
793
821
  config: deps.config,
@@ -806,6 +834,21 @@ async function afterResponse(response, context, startTime, deps) {
806
834
  }
807
835
  return null;
808
836
  }
837
+ async function logBlocked(context, violation, deps) {
838
+ try {
839
+ await deps.auditLogger.logBlocked(context, violation, {
840
+ humanSponsor: deps.config.humanSponsor,
841
+ metadata: deps.config.metadata
842
+ });
843
+ } catch {
844
+ }
845
+ if (deps.config.hooks?.onBudgetExceeded) {
846
+ try {
847
+ await deps.config.hooks.onBudgetExceeded(violation);
848
+ } catch {
849
+ }
850
+ }
851
+ }
809
852
  function determinePolicyEvaluation(context, deps) {
810
853
  if (!deps.budgetManager || context.amount === "0.000000") return true;
811
854
  const eval_ = deps.budgetManager.evaluate(context);
@@ -817,7 +860,8 @@ function wrapWithSentinel(fetchWithPayment, config) {
817
860
  validateConfig(config);
818
861
  const budgetManager = config.budget ? new BudgetManager(config.budget) : null;
819
862
  const auditLogger = new AuditLogger(config.audit ?? { enabled: true, storage: new MemoryStorage() });
820
- const deps = { budgetManager, auditLogger, config };
863
+ const priceCache = /* @__PURE__ */ new Map();
864
+ const deps = { budgetManager, auditLogger, config, priceCache };
821
865
  const sentinelFetch = async (input, init) => {
822
866
  const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
823
867
  const startTime = Date.now();
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/budget/spike-detector.ts","../src/budget/policies.ts","../src/budget/index.ts","../src/audit/storage/memory.ts","../src/utils/id.ts","../src/audit/enrichment.ts","../src/audit/export.ts","../src/audit/index.ts","../src/errors.ts","../src/wrapper/headers.ts","../src/wrapper/interceptor.ts","../src/wrapper/index.ts","../src/audit/storage/file.ts","../src/audit/storage/api.ts"],"names":["calculateAverage","parseUSDC","formatUSDC","getHourStart","getDayStart","compareUSDC","addUSDC","formatUSDCHuman","createHash","appendFileSync","existsSync","readFileSync","dirname","mkdirSync"],"mappings":"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","file":"index.cjs","sourcesContent":["import { parseUSDC, formatUSDC, calculateAverage } from \"../utils/money\";\n\n/** Detects abnormal payment spikes using a rolling window of recent amounts */\nexport class SpikeDetector {\n private readonly windowSize: number;\n private readonly threshold: number;\n private readonly window: string[] = [];\n\n constructor(threshold = 3.0, windowSize = 20) {\n this.threshold = threshold;\n this.windowSize = windowSize;\n }\n\n /** Record a payment amount into the rolling window */\n record(amount: string): void {\n this.window.push(amount);\n if (this.window.length > this.windowSize) {\n this.window.shift();\n }\n }\n\n /**\n * Check if a proposed amount is a spike relative to the rolling average.\n * Returns null if no spike, or a description string if spike detected.\n * Needs at least 3 data points before spike detection activates.\n */\n check(amount: string): string | null {\n if (this.window.length < 3) return null;\n\n const avg = calculateAverage(this.window);\n const avgRaw = parseUSDC(avg);\n if (avgRaw === 0n) return null;\n\n const amountRaw = parseUSDC(amount);\n const ratio = Number(amountRaw) / Number(avgRaw);\n\n if (ratio > this.threshold) {\n return (\n `Payment $${amount} is ${ratio.toFixed(1)}x the rolling average ` +\n `$${formatUSDC(avgRaw)} (threshold: ${this.threshold}x)`\n );\n }\n return null;\n }\n\n /** Get the current rolling average */\n getAverage(): string {\n return calculateAverage(this.window);\n }\n\n /** Get the current window contents */\n getWindow(): string[] {\n return [...this.window];\n }\n\n /** Restore state from serialized data */\n loadWindow(amounts: string[]): void {\n this.window.length = 0;\n for (const a of amounts.slice(-this.windowSize)) {\n this.window.push(a);\n }\n }\n}\n","import type { BudgetPolicy } from \"../types/budget\";\n\n/** Tight limits for low-risk or testing scenarios */\nexport function conservativePolicy(): BudgetPolicy {\n return {\n maxPerCall: \"0.10\",\n maxPerHour: \"5.00\",\n maxPerDay: \"50.00\",\n spikeThreshold: 3.0,\n };\n}\n\n/** Balanced limits for typical production agents */\nexport function standardPolicy(): BudgetPolicy {\n return {\n maxPerCall: \"1.00\",\n maxPerHour: \"25.00\",\n maxPerDay: \"200.00\",\n spikeThreshold: 3.0,\n };\n}\n\n/** Higher limits for trusted, high-throughput agents */\nexport function liberalPolicy(): BudgetPolicy {\n return {\n maxPerCall: \"10.00\",\n maxPerHour: \"100.00\",\n maxPerDay: \"1000.00\",\n spikeThreshold: 5.0,\n };\n}\n\n/** No spending limits — audit logging only */\nexport function unlimitedPolicy(): BudgetPolicy {\n return {};\n}\n\n/** Build a custom policy by overriding defaults */\nexport function customPolicy(overrides: Partial<BudgetPolicy>): BudgetPolicy {\n return { ...standardPolicy(), ...overrides };\n}\n","import type { BudgetPolicy, BudgetState, BudgetViolation, BudgetEvaluation } from \"../types/budget\";\nimport type { PaymentContext } from \"../types/index\";\nimport { addUSDC, compareUSDC } from \"../utils/money\";\nimport { getHourStart, getDayStart } from \"../utils/time\";\nimport { SpikeDetector } from \"./spike-detector\";\n\n/** Enforces budget policies by evaluating proposed payments against spending state */\nexport class BudgetManager {\n private state: BudgetState;\n private readonly policy: BudgetPolicy;\n private readonly spikeDetector: SpikeDetector;\n\n constructor(policy: BudgetPolicy) {\n this.policy = policy;\n this.spikeDetector = new SpikeDetector(\n policy.spikeThreshold ?? 3.0,\n );\n const now = Date.now();\n this.state = {\n totalSpent: \"0.000000\",\n hourlySpent: \"0.000000\",\n dailySpent: \"0.000000\",\n callCount: 0,\n lastReset: { hourly: getHourStart(now), daily: getDayStart(now) },\n rollingAverage: \"0.000000\",\n rollingWindow: [],\n };\n }\n\n /**\n * Evaluate a proposed payment against the budget policy.\n * Called BEFORE every payment. Returns allow/deny with reason.\n */\n evaluate(context: PaymentContext): BudgetEvaluation {\n this.maybeResetWindows();\n const warnings: string[] = [];\n\n // 1. Blocked endpoints (fast reject)\n if (this.policy.blockedEndpoints?.length) {\n for (const pattern of this.policy.blockedEndpoints) {\n if (endpointMatches(context.endpoint, pattern)) {\n return {\n allowed: false,\n violation: this.violation(\"blocked_endpoint\", \"0.000000\", \"0.000000\", context),\n };\n }\n }\n }\n\n // 2. Allowed endpoints whitelist\n if (this.policy.allowedEndpoints?.length) {\n const matched = this.policy.allowedEndpoints.some((p) =>\n endpointMatches(context.endpoint, p),\n );\n if (!matched) {\n return {\n allowed: false,\n violation: this.violation(\"blocked_endpoint\", \"0.000000\", \"0.000000\", context),\n };\n }\n }\n\n // 3. Per-call limit\n if (this.policy.maxPerCall) {\n if (compareUSDC(context.amount, this.policy.maxPerCall) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"per_call\", this.policy.maxPerCall, \"0.000000\", context),\n };\n }\n }\n\n // 4. Spike detection\n const spikeMsg = this.spikeDetector.check(context.amount);\n if (spikeMsg) {\n if (this.policy.spikeThreshold !== undefined) {\n return {\n allowed: false,\n violation: this.violation(\n \"spike\",\n this.spikeDetector.getAverage(),\n this.state.hourlySpent,\n context,\n ),\n };\n }\n warnings.push(spikeMsg);\n }\n\n // 5. Hourly rolling window\n if (this.policy.maxPerHour) {\n const projectedHourly = addUSDC(this.state.hourlySpent, context.amount);\n if (compareUSDC(projectedHourly, this.policy.maxPerHour) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"hourly\", this.policy.maxPerHour, this.state.hourlySpent, context),\n };\n }\n }\n\n // 6. Daily rolling window\n if (this.policy.maxPerDay) {\n const projectedDaily = addUSDC(this.state.dailySpent, context.amount);\n if (compareUSDC(projectedDaily, this.policy.maxPerDay) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"daily\", this.policy.maxPerDay, this.state.dailySpent, context),\n };\n }\n }\n\n // 7. Total lifetime cap\n if (this.policy.maxTotal) {\n const projectedTotal = addUSDC(this.state.totalSpent, context.amount);\n if (compareUSDC(projectedTotal, this.policy.maxTotal) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"total\", this.policy.maxTotal, this.state.totalSpent, context),\n };\n }\n }\n\n // 8. Approval threshold\n if (this.policy.requireApproval) {\n if (compareUSDC(context.amount, this.policy.requireApproval.above) > 0) {\n return {\n allowed: false,\n violation: this.violation(\n \"approval_required\",\n this.policy.requireApproval.above,\n this.state.totalSpent,\n context,\n ),\n };\n }\n }\n\n return { allowed: true, warnings };\n }\n\n /** Record a completed payment. Called AFTER payment succeeds. */\n record(amount: string, _endpoint: string): void {\n this.maybeResetWindows();\n this.state.totalSpent = addUSDC(this.state.totalSpent, amount);\n this.state.hourlySpent = addUSDC(this.state.hourlySpent, amount);\n this.state.dailySpent = addUSDC(this.state.dailySpent, amount);\n this.state.callCount++;\n this.spikeDetector.record(amount);\n this.state.rollingAverage = this.spikeDetector.getAverage();\n this.state.rollingWindow = this.spikeDetector.getWindow();\n }\n\n /** Get current budget state (for dashboard/debugging) */\n getState(): BudgetState {\n this.maybeResetWindows();\n return { ...this.state, rollingWindow: [...this.state.rollingWindow] };\n }\n\n /** Reset spending counters for a given scope */\n reset(scope: \"hourly\" | \"daily\" | \"total\"): void {\n const now = Date.now();\n switch (scope) {\n case \"hourly\":\n this.state.hourlySpent = \"0.000000\";\n this.state.lastReset.hourly = getHourStart(now);\n break;\n case \"daily\":\n this.state.dailySpent = \"0.000000\";\n this.state.lastReset.daily = getDayStart(now);\n break;\n case \"total\":\n this.state.totalSpent = \"0.000000\";\n this.state.hourlySpent = \"0.000000\";\n this.state.dailySpent = \"0.000000\";\n this.state.callCount = 0;\n break;\n }\n }\n\n /** Serialize state for persistence */\n serialize(): string {\n return JSON.stringify(this.state);\n }\n\n /** Restore a BudgetManager from serialized state */\n static deserialize(data: string, policy: BudgetPolicy): BudgetManager {\n const mgr = new BudgetManager(policy);\n const parsed = JSON.parse(data) as BudgetState;\n mgr.state = parsed;\n mgr.spikeDetector.loadWindow(parsed.rollingWindow);\n return mgr;\n }\n\n /** Auto-reset hourly/daily windows when the time window has rolled over */\n private maybeResetWindows(): void {\n const now = Date.now();\n const hourStart = getHourStart(now);\n const dayStart = getDayStart(now);\n\n if (hourStart > this.state.lastReset.hourly) {\n this.state.hourlySpent = \"0.000000\";\n this.state.lastReset.hourly = hourStart;\n }\n if (dayStart > this.state.lastReset.daily) {\n this.state.dailySpent = \"0.000000\";\n this.state.lastReset.daily = dayStart;\n }\n }\n\n private violation(\n type: BudgetViolation[\"type\"],\n limit: string,\n current: string,\n context: PaymentContext,\n ): BudgetViolation {\n return {\n type,\n limit,\n current,\n attempted: context.amount,\n agentId: context.agentId,\n endpoint: context.endpoint,\n timestamp: Date.now(),\n };\n }\n}\n\n/** Simple glob-like endpoint matching (supports * wildcards) */\nfunction endpointMatches(url: string, pattern: string): boolean {\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\*/g, \".*\").replace(/\\?/g, \".\") + \"$\",\n );\n return regex.test(url);\n}\n\nexport { SpikeDetector } from \"./spike-detector\";\nexport {\n conservativePolicy,\n standardPolicy,\n liberalPolicy,\n unlimitedPolicy,\n customPolicy,\n} from \"./policies\";\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { parseUSDC, formatUSDC, formatUSDCHuman, compareUSDC } from \"../../utils/money\";\n\n/** In-memory audit storage with configurable capacity and FIFO eviction */\nexport class MemoryStorage implements StorageBackend {\n private readonly records = new Map<string, AuditRecord>();\n private readonly insertOrder: string[] = [];\n private readonly maxRecords: number;\n\n constructor(maxRecords = 10_000) {\n this.maxRecords = maxRecords;\n }\n\n async write(record: AuditRecord): Promise<void> {\n if (this.records.size >= this.maxRecords) {\n const oldest = this.insertOrder.shift();\n if (oldest) this.records.delete(oldest);\n }\n this.records.set(record.id, record);\n this.insertOrder.push(record.id);\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n let results = this.filter(query);\n results = this.sort(results, query.orderBy, query.order);\n const offset = query.offset ?? 0;\n const limit = query.limit ?? results.length;\n return results.slice(offset, offset + limit);\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n const records = this.filter(query);\n return buildSummary(records, query);\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n return this.filter(query).length;\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n return this.records.get(id) ?? null;\n }\n\n private filter(query: Partial<AuditQuery>): AuditRecord[] {\n return [...this.records.values()].filter((r) => matchesQuery(r, query));\n }\n\n private sort(\n records: AuditRecord[],\n orderBy?: AuditQuery[\"orderBy\"],\n order?: AuditQuery[\"order\"],\n ): AuditRecord[] {\n if (!orderBy) return records;\n const dir = order === \"desc\" ? -1 : 1;\n return records.sort((a, b) => {\n switch (orderBy) {\n case \"created_at\":\n return (a.created_at - b.created_at) * dir;\n case \"amount\":\n return compareUSDC(a.amount, b.amount) * dir;\n case \"endpoint\":\n return a.endpoint.localeCompare(b.endpoint) * dir;\n default:\n return 0;\n }\n });\n }\n}\n\n/** Shared filter logic reusable across storage backends */\nexport function matchesQuery(\n record: AuditRecord,\n query: Partial<AuditQuery>,\n): boolean {\n if (query.agentId && record.agent_id !== query.agentId) return false;\n if (query.team && record.team !== query.team) return false;\n if (query.endpoint && !record.endpoint.includes(query.endpoint)) return false;\n if (query.minAmount && compareUSDC(record.amount, query.minAmount) < 0) return false;\n if (query.maxAmount && compareUSDC(record.amount, query.maxAmount) > 0) return false;\n if (query.startTime && record.created_at < query.startTime) return false;\n if (query.endTime && record.created_at > query.endTime) return false;\n if (query.status?.length && !query.status.includes(record.policy_evaluation)) return false;\n if (query.tags?.length && !query.tags.some((t) => record.tags.includes(t))) return false;\n return true;\n}\n\n/** Build an AuditSummary from a set of records */\nexport function buildSummary(\n records: AuditRecord[],\n query: Partial<AuditQuery>,\n): AuditSummary {\n let totalRaw = 0n;\n let maxRaw = 0n;\n const agents = new Set<string>();\n const endpoints = new Set<string>();\n const byAgent: Record<string, { spend: string; count: number }> = {};\n const byEndpoint: Record<string, { spend: string; count: number }> = {};\n const byTeam: Record<string, { spend: string; count: number }> = {};\n let violations = 0;\n let minTs = Infinity;\n let maxTs = 0;\n\n for (const r of records) {\n const raw = parseUSDC(r.amount);\n totalRaw += raw;\n if (raw > maxRaw) maxRaw = raw;\n agents.add(r.agent_id);\n endpoints.add(r.endpoint);\n\n if (r.created_at < minTs) minTs = r.created_at;\n if (r.created_at > maxTs) maxTs = r.created_at;\n\n if (r.policy_evaluation === \"blocked\") violations++;\n\n // by_agent\n const agentEntry = byAgent[r.agent_id] ?? { spend: \"0.000000\", count: 0 };\n agentEntry.spend = formatUSDC(parseUSDC(agentEntry.spend) + raw);\n agentEntry.count++;\n byAgent[r.agent_id] = agentEntry;\n\n // by_endpoint\n const epEntry = byEndpoint[r.endpoint] ?? { spend: \"0.000000\", count: 0 };\n epEntry.spend = formatUSDC(parseUSDC(epEntry.spend) + raw);\n epEntry.count++;\n byEndpoint[r.endpoint] = epEntry;\n\n // by_team\n const teamKey = r.team ?? \"(none)\";\n const teamEntry = byTeam[teamKey] ?? { spend: \"0.000000\", count: 0 };\n teamEntry.spend = formatUSDC(parseUSDC(teamEntry.spend) + raw);\n teamEntry.count++;\n byTeam[teamKey] = teamEntry;\n }\n\n const count = records.length;\n return {\n total_spend: formatUSDCHuman(totalRaw),\n total_transactions: count,\n unique_endpoints: endpoints.size,\n unique_agents: agents.size,\n avg_payment: count > 0 ? formatUSDCHuman(totalRaw / BigInt(count)) : \"0.00\",\n max_payment: formatUSDCHuman(maxRaw),\n by_agent: byAgent,\n by_endpoint: byEndpoint,\n by_team: byTeam,\n violations,\n period: {\n start: query.startTime ?? (minTs === Infinity ? 0 : minTs),\n end: query.endTime ?? (maxTs === 0 ? 0 : maxTs),\n },\n };\n}\n","import { createHash, randomUUID } from \"node:crypto\";\n\n/**\n * Generate a deterministic record ID from payment attributes.\n * SHA-256 of concatenated inputs, truncated to 16 hex chars.\n */\nexport function generateRecordId(\n agentId: string,\n endpoint: string,\n timestamp: number,\n amount: string,\n): string {\n const input = `${agentId}|${endpoint}|${timestamp}|${amount}`;\n const hash = createHash(\"sha256\").update(input).digest(\"hex\");\n return hash.slice(0, 16);\n}\n\n/** Generate a random session ID (UUID v4) */\nexport function generateSessionId(): string {\n return randomUUID();\n}\n","import type { AuditRecord } from \"../types/audit\";\nimport type { PaymentContext, EnrichmentConfig } from \"../types/index\";\nimport type { SettleResponse } from \"../types/x402-stubs\";\nimport type { SentinelConfig } from \"../types/config\";\nimport { generateRecordId } from \"../utils/id\";\n\ninterface EnrichmentInput {\n context: PaymentContext;\n config: SentinelConfig;\n statusCode: number;\n responseTimeMs: number;\n settlement: SettleResponse | null;\n policyEvaluation: \"allowed\" | \"flagged\" | \"blocked\";\n budgetRemaining: string | null;\n}\n\n/** Build a complete AuditRecord from payment context and settlement data */\nexport function enrichRecord(input: EnrichmentInput): AuditRecord {\n const { context, config, statusCode, responseTimeMs, settlement, policyEvaluation, budgetRemaining } = input;\n const now = Date.now();\n const id = generateRecordId(context.agentId, context.endpoint, now, context.amount);\n\n const tags = computeTags(context, config.audit?.enrichment);\n\n return {\n id,\n agent_id: context.agentId,\n team: context.team,\n human_sponsor: config.humanSponsor ?? null,\n\n amount: context.amount,\n amount_raw: context.amountRaw,\n asset: context.asset,\n network: context.network,\n scheme: context.scheme,\n\n tx_hash: settlement?.transaction ?? null,\n payer_address: settlement?.payer ?? \"\",\n payee_address: context.payTo,\n facilitator: null,\n\n endpoint: context.endpoint,\n method: context.method,\n status_code: statusCode,\n response_time_ms: responseTimeMs,\n\n policy_id: null,\n policy_evaluation: policyEvaluation,\n budget_remaining: budgetRemaining,\n\n task_id: context.metadata[\"task_id\"] ?? null,\n session_id: context.metadata[\"session_id\"] ?? null,\n metadata: { ...context.metadata, ...config.metadata },\n\n created_at: now,\n settled_at: settlement?.success ? now : null,\n\n tags,\n };\n}\n\n/** Build an AuditRecord for a blocked payment attempt */\nexport function enrichBlockedRecord(\n context: PaymentContext,\n config: SentinelConfig,\n policyEvaluation: \"blocked\",\n): AuditRecord {\n return enrichRecord({\n context,\n config,\n statusCode: 0,\n responseTimeMs: 0,\n settlement: null,\n policyEvaluation,\n budgetRemaining: null,\n });\n}\n\nfunction computeTags(context: PaymentContext, enrichment?: EnrichmentConfig): string[] {\n const tags: string[] = [];\n\n if (enrichment?.staticTags) {\n tags.push(...enrichment.staticTags);\n }\n\n if (enrichment?.tagRules) {\n for (const rule of enrichment.tagRules) {\n const regex = new RegExp(rule.pattern);\n if (regex.test(context.endpoint)) {\n tags.push(...rule.tags);\n }\n }\n }\n\n return tags;\n}\n","import type { AuditRecord, AuditSummary } from \"../types/audit\";\n\nconst CSV_HEADERS: (keyof AuditRecord)[] = [\n \"id\", \"agent_id\", \"team\", \"human_sponsor\",\n \"amount\", \"amount_raw\", \"asset\", \"network\", \"scheme\",\n \"tx_hash\", \"payer_address\", \"payee_address\", \"facilitator\",\n \"endpoint\", \"method\", \"status_code\", \"response_time_ms\",\n \"policy_id\", \"policy_evaluation\", \"budget_remaining\",\n \"task_id\", \"session_id\",\n \"created_at\", \"settled_at\",\n];\n\n/** Convert records to a properly escaped CSV string */\nexport function toCSV(records: AuditRecord[]): string {\n const lines: string[] = [CSV_HEADERS.join(\",\")];\n\n for (const record of records) {\n const values = CSV_HEADERS.map((key) => {\n const val = record[key];\n if (val === null || val === undefined) return \"\";\n const str = String(val);\n if (str.includes(\",\") || str.includes('\"') || str.includes(\"\\n\")) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n });\n lines.push(values.join(\",\"));\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/** Convert records to a JSON string */\nexport function toJSON(records: AuditRecord[], pretty = false): string {\n return JSON.stringify(records, null, pretty ? 2 : undefined);\n}\n\n/** Generate a human-readable text summary report */\nexport function toSummaryReport(summary: AuditSummary): string {\n const lines: string[] = [\n \"═══════════════════════════════════════════\",\n \" VALEO SENTINEL — AUDIT SUMMARY REPORT\",\n \"═══════════════════════════════════════════\",\n \"\",\n ` Period: ${new Date(summary.period.start).toISOString()} — ${new Date(summary.period.end).toISOString()}`,\n \"\",\n ` Total Spend: $${summary.total_spend}`,\n ` Total Transactions: ${summary.total_transactions}`,\n ` Unique Agents: ${summary.unique_agents}`,\n ` Unique Endpoints: ${summary.unique_endpoints}`,\n ` Avg Payment: $${summary.avg_payment}`,\n ` Max Payment: $${summary.max_payment}`,\n ` Violations: ${summary.violations}`,\n \"\",\n ];\n\n if (Object.keys(summary.by_agent).length > 0) {\n lines.push(\" ── Spend by Agent ──\");\n for (const [agent, data] of Object.entries(summary.by_agent)) {\n lines.push(` ${agent}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n if (Object.keys(summary.by_team).length > 0) {\n lines.push(\" ── Spend by Team ──\");\n for (const [team, data] of Object.entries(summary.by_team)) {\n lines.push(` ${team}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n if (Object.keys(summary.by_endpoint).length > 0) {\n lines.push(\" ── Spend by Endpoint ──\");\n for (const [ep, data] of Object.entries(summary.by_endpoint)) {\n lines.push(` ${ep}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"═══════════════════════════════════════════\");\n return lines.join(\"\\n\");\n}\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../types/audit\";\nimport type { AuditConfig } from \"../types/config\";\nimport type { PaymentContext } from \"../types/index\";\nimport type { BudgetViolation } from \"../types/budget\";\nimport type { StorageBackend } from \"./storage/interface\";\nimport { MemoryStorage } from \"./storage/memory\";\nimport { enrichBlockedRecord } from \"./enrichment\";\nimport { generateRecordId } from \"../utils/id\";\nimport { toCSV, toJSON } from \"./export\";\n\n/** Central audit logger — writes records to a pluggable storage backend */\nexport class AuditLogger {\n private readonly storage: StorageBackend;\n private readonly enabled: boolean;\n private readonly redactFields: string[];\n\n constructor(config?: AuditConfig) {\n this.enabled = config?.enabled !== false;\n this.storage = config?.storage ?? new MemoryStorage();\n this.redactFields = config?.redactFields ?? [];\n }\n\n /** Log a completed payment record */\n async log(record: Omit<AuditRecord, \"id\" | \"created_at\">): Promise<AuditRecord> {\n const now = Date.now();\n const full: AuditRecord = {\n ...record,\n id: generateRecordId(record.agent_id, record.endpoint, now, record.amount),\n created_at: now,\n };\n\n const redacted = this.redact(full);\n\n if (this.enabled) {\n try {\n await this.storage.write(redacted);\n } catch (err) {\n console.warn(\"[sentinel] Audit write failed (non-fatal):\", err);\n }\n }\n\n return redacted;\n }\n\n /** Log a blocked payment attempt */\n async logBlocked(\n context: PaymentContext,\n violation: BudgetViolation,\n config: { humanSponsor?: string; metadata?: Record<string, string> },\n ): Promise<AuditRecord> {\n const record = enrichBlockedRecord(context, {\n agentId: context.agentId,\n ...config,\n }, \"blocked\");\n record.metadata[\"violation_type\"] = violation.type;\n record.metadata[\"violation_limit\"] = violation.limit;\n\n if (this.enabled) {\n try {\n await this.storage.write(this.redact(record));\n } catch (err) {\n console.warn(\"[sentinel] Audit write failed (non-fatal):\", err);\n }\n }\n\n return record;\n }\n\n /** Query audit records */\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n return this.storage.query(query);\n }\n\n /** Get summary statistics */\n async summarize(query?: Partial<AuditQuery>): Promise<AuditSummary> {\n return this.storage.summarize(query ?? {});\n }\n\n /** Export records as CSV */\n async exportCSV(query?: AuditQuery): Promise<string> {\n const records = await this.storage.query(query ?? {});\n return toCSV(records);\n }\n\n /** Export records as JSON */\n async exportJSON(query?: AuditQuery): Promise<string> {\n const records = await this.storage.query(query ?? {});\n return toJSON(records, true);\n }\n\n /** Flush pending writes to storage */\n async flush(): Promise<void> {\n if (\"flush\" in this.storage && typeof this.storage.flush === \"function\") {\n await (this.storage as StorageBackend & { flush(): Promise<void> }).flush();\n }\n }\n\n /** Get the underlying storage backend (for dashboard integration) */\n getStorage(): StorageBackend {\n return this.storage;\n }\n\n private redact(record: AuditRecord): AuditRecord {\n if (this.redactFields.length === 0) return record;\n const copy = { ...record, metadata: { ...record.metadata } };\n for (const field of this.redactFields) {\n if (field in copy.metadata) {\n copy.metadata[field] = \"[REDACTED]\";\n }\n }\n return copy;\n }\n}\n","import type { AuditRecord } from \"./types/audit\";\nimport type { BudgetViolation } from \"./types/budget\";\nimport { parseUSDC } from \"./utils/money\";\n\nexport class SentinelError extends Error {\n readonly code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.name = \"SentinelError\";\n this.code = code;\n }\n}\n\nexport class SentinelBudgetError extends SentinelError {\n readonly violation: BudgetViolation;\n\n constructor(violation: BudgetViolation) {\n super(buildBudgetMessage(violation), \"BUDGET_EXCEEDED\");\n this.name = \"SentinelBudgetError\";\n this.violation = violation;\n }\n}\n\n/** Audit failures are NEVER fatal — they should be caught and logged */\nexport class SentinelAuditError extends SentinelError {\n readonly record?: Partial<AuditRecord>;\n\n constructor(message: string, record?: Partial<AuditRecord>) {\n super(message, \"AUDIT_ERROR\");\n this.name = \"SentinelAuditError\";\n this.record = record;\n }\n}\n\nexport class SentinelConfigError extends SentinelError {\n constructor(message: string) {\n super(message, \"CONFIG_ERROR\");\n this.name = \"SentinelConfigError\";\n }\n}\n\nfunction buildBudgetMessage(v: BudgetViolation): string {\n const attempted = `$${v.attempted}`;\n\n switch (v.type) {\n case \"per_call\":\n return `Budget exceeded: ${attempted} exceeds per-call limit of $${v.limit} on ${v.agentId}`;\n case \"hourly\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} hourly limit on ${v.agentId} (attempted ${attempted})`;\n case \"daily\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} daily limit on ${v.agentId} (attempted ${attempted})`;\n case \"total\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} total limit on ${v.agentId} (attempted ${attempted})`;\n case \"spike\":\n return `Price spike detected: ${attempted} vs rolling average $${v.limit} on ${v.agentId}`;\n case \"blocked_endpoint\":\n return `Blocked endpoint: ${v.endpoint} is not allowed for ${v.agentId}`;\n case \"approval_required\":\n return `Approval required: ${attempted} exceeds approval threshold $${v.limit} on ${v.agentId}`;\n }\n}\n\n/** Validate a SentinelConfig at initialization time */\nexport function validateConfig(config: {\n agentId: string;\n budget?: {\n maxPerCall?: string;\n maxPerHour?: string;\n maxPerDay?: string;\n maxTotal?: string;\n spikeThreshold?: number;\n allowedEndpoints?: string[];\n blockedEndpoints?: string[];\n };\n}): void {\n if (!config.agentId || config.agentId.trim() === \"\") {\n throw new SentinelConfigError(\"agentId is required and must be non-empty\");\n }\n\n const budget = config.budget;\n if (!budget) return;\n\n const amountFields = [\"maxPerCall\", \"maxPerHour\", \"maxPerDay\", \"maxTotal\"] as const;\n for (const field of amountFields) {\n const value = budget[field];\n if (value !== undefined) {\n try {\n parseUSDC(value);\n } catch {\n throw new SentinelConfigError(\n `budget.${field} \"${value}\" is not a valid USDC amount`,\n );\n }\n }\n }\n\n if (budget.spikeThreshold !== undefined && budget.spikeThreshold <= 1.0) {\n throw new SentinelConfigError(\n `budget.spikeThreshold must be > 1.0, got ${budget.spikeThreshold}`,\n );\n }\n\n if (budget.allowedEndpoints?.length && budget.blockedEndpoints?.length) {\n throw new SentinelConfigError(\n \"Cannot set both allowedEndpoints and blockedEndpoints — use one or the other\",\n );\n }\n}\n","import type { PaymentRequired, PaymentRequirements, SettleResponse } from \"../types/x402-stubs\";\n\n/**\n * Decode the PAYMENT-REQUIRED header from a 402 response.\n * The header value is a Base64-encoded JSON string containing the PaymentRequired object.\n */\nexport function parsePaymentRequired(header: string): PaymentRequired {\n const json = Buffer.from(header, \"base64\").toString(\"utf-8\");\n return JSON.parse(json) as PaymentRequired;\n}\n\n/**\n * Decode the PAYMENT-RESPONSE header from a successful (200) response.\n * The header value is a Base64-encoded JSON string containing the SettleResponse.\n * Returns null if the header is missing or unparseable.\n */\nexport function parsePaymentResponse(header: string | null): SettleResponse | null {\n if (!header) return null;\n try {\n const json = Buffer.from(header, \"base64\").toString(\"utf-8\");\n return JSON.parse(json) as SettleResponse;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract the payment amount, asset, network, and scheme from a PaymentRequirements object.\n * Uses the first entry in the accepts array.\n */\nexport function extractAmount(requirements: PaymentRequirements): {\n amount: string;\n asset: string;\n network: string;\n scheme: string;\n} {\n return {\n amount: requirements.amount,\n asset: requirements.asset,\n network: requirements.network,\n scheme: requirements.scheme,\n };\n}\n\n/**\n * Extract payment info from a PaymentRequired object (the full 402 response).\n * Picks the first accepted payment requirement.\n */\nexport function extractFromPaymentRequired(paymentRequired: PaymentRequired): {\n amount: string;\n asset: string;\n network: string;\n scheme: string;\n payTo: string;\n} | null {\n const first = paymentRequired.accepts[0];\n if (!first) return null;\n return {\n amount: first.amount,\n asset: first.asset,\n network: first.network,\n scheme: first.scheme,\n payTo: first.payTo,\n };\n}\n","import type { SentinelConfig } from \"../types/config\";\nimport type { PaymentContext } from \"../types/index\";\nimport type { AuditRecord } from \"../types/audit\";\nimport type { BudgetEvaluation } from \"../types/budget\";\nimport { BudgetManager } from \"../budget/index\";\nimport { AuditLogger } from \"../audit/index\";\nimport { enrichRecord } from \"../audit/enrichment\";\nimport { parsePaymentResponse, parsePaymentRequired, extractFromPaymentRequired } from \"./headers\";\nimport { formatUSDCHuman, parseUSDC } from \"../utils/money\";\n\nexport interface InterceptorDeps {\n budgetManager: BudgetManager | null;\n auditLogger: AuditLogger;\n config: SentinelConfig;\n}\n\n/**\n * Pre-request interception: build context and evaluate budget.\n * Called BEFORE the underlying fetch. If the request is not a paid endpoint\n * (no amount info yet), we build a placeholder context with \"0.000000\" amount.\n */\nexport function beforeRequest(\n url: string,\n init: RequestInit | undefined,\n deps: InterceptorDeps,\n): {\n proceed: boolean;\n context: PaymentContext;\n evaluation?: BudgetEvaluation;\n} {\n const method = init?.method ?? \"GET\";\n const context: PaymentContext = {\n endpoint: url,\n method: method.toUpperCase(),\n agentId: deps.config.agentId,\n team: deps.config.team ?? null,\n amount: \"0.000000\",\n amountRaw: \"0\",\n asset: \"\",\n network: \"\",\n scheme: \"\",\n payTo: \"\",\n timestamp: Date.now(),\n metadata: { ...(deps.config.metadata ?? {}) },\n };\n\n // We can't know the exact amount before the request (x402 determines it from the 402 response).\n // Budget pre-checks that don't depend on amount (endpoint filtering) can still run.\n // The full budget evaluation happens when we know the amount from the response headers.\n if (deps.budgetManager) {\n // Run endpoint-only checks (blocked/allowed endpoints)\n const eval_ = deps.budgetManager.evaluate(context);\n if (!eval_.allowed && eval_.violation.type === \"blocked_endpoint\") {\n return { proceed: false, context, evaluation: eval_ };\n }\n }\n\n return { proceed: true, context };\n}\n\n/**\n * Post-response interception: parse payment headers, evaluate full budget, log audit record.\n * Called AFTER the underlying fetch returns. Reads ONLY headers, never the body.\n */\nexport async function afterResponse(\n response: Response,\n context: PaymentContext,\n startTime: number,\n deps: InterceptorDeps,\n): Promise<AuditRecord | null> {\n const responseTimeMs = Date.now() - startTime;\n\n // Case 1: Successful response with PAYMENT-RESPONSE header\n const paymentResponseHeader = response.headers.get(\"payment-response\");\n if (paymentResponseHeader) {\n const settlement = parsePaymentResponse(paymentResponseHeader);\n if (settlement) {\n // Enrich context from settlement\n context.network = settlement.network ?? context.network;\n\n // We need the amount from the original payment requirements.\n // Since x402 already handled the 402->200 cycle, we may also have amount info\n // in a custom header or we parse from context. For now, use what's available.\n const policyEvaluation = determinePolicyEvaluation(context, deps);\n let budgetRemaining: string | null = null;\n\n if (deps.budgetManager && context.amount !== \"0.000000\") {\n deps.budgetManager.record(context.amount, context.endpoint);\n const state = deps.budgetManager.getState();\n if (deps.config.budget?.maxTotal) {\n budgetRemaining = formatUSDCHuman(\n parseUSDC(deps.config.budget.maxTotal) - parseUSDC(state.totalSpent),\n );\n }\n }\n\n const record = enrichRecord({\n context,\n config: deps.config,\n statusCode: response.status,\n responseTimeMs,\n settlement,\n policyEvaluation: policyEvaluation ? \"allowed\" : \"flagged\",\n budgetRemaining,\n });\n\n try {\n await deps.auditLogger.log(record);\n } catch (err) {\n console.warn(\"[sentinel] Audit log failed (non-fatal):\", err);\n }\n\n if (deps.config.hooks?.afterPayment) {\n try {\n await deps.config.hooks.afterPayment(record);\n } catch {\n // hooks must never block\n }\n }\n\n return record;\n }\n }\n\n // Case 2: Leaked 402 — x402 failed to complete payment\n if (response.status === 402) {\n const paymentRequiredHeader = response.headers.get(\"payment-required\");\n if (paymentRequiredHeader) {\n try {\n const paymentRequired = parsePaymentRequired(paymentRequiredHeader);\n const extracted = extractFromPaymentRequired(paymentRequired);\n if (extracted) {\n context.amount = extracted.amount;\n context.asset = extracted.asset;\n context.network = extracted.network;\n context.scheme = extracted.scheme;\n context.payTo = extracted.payTo;\n }\n } catch {\n // unparseable header — log what we have\n }\n }\n\n const record = enrichRecord({\n context,\n config: deps.config,\n statusCode: 402,\n responseTimeMs,\n settlement: null,\n policyEvaluation: \"flagged\",\n budgetRemaining: null,\n });\n\n try {\n await deps.auditLogger.log(record);\n } catch (err) {\n console.warn(\"[sentinel] Audit log failed (non-fatal):\", err);\n }\n\n return record;\n }\n\n // Case 3: Non-payment response (no payment headers, not 402)\n return null;\n}\n\nfunction determinePolicyEvaluation(\n context: PaymentContext,\n deps: InterceptorDeps,\n): boolean {\n if (!deps.budgetManager || context.amount === \"0.000000\") return true;\n const eval_ = deps.budgetManager.evaluate(context);\n return eval_.allowed;\n}\n","import type { SentinelConfig } from \"../types/config\";\nimport { BudgetManager } from \"../budget/index\";\nimport { AuditLogger } from \"../audit/index\";\nimport { MemoryStorage } from \"../audit/storage/memory\";\nimport { SentinelBudgetError, validateConfig } from \"../errors\";\nimport { beforeRequest, afterResponse } from \"./interceptor\";\nimport type { InterceptorDeps } from \"./interceptor\";\n\n/**\n * Wrap an x402-enabled fetch function with Sentinel budget enforcement and audit logging.\n *\n * @param fetchWithPayment - The x402-wrapped fetch (from wrapFetchWithPayment)\n * @param config - Sentinel configuration (agent identity, budget, audit settings)\n * @returns A drop-in replacement fetch function with Sentinel instrumentation\n *\n * @example\n * ```ts\n * const fetchWithSentinel = wrapWithSentinel(fetchWithPayment, {\n * agentId: \"agent-weather-001\",\n * budget: standardPolicy(),\n * });\n * const response = await fetchWithSentinel(\"https://api.example.com/weather\");\n * ```\n */\nexport function wrapWithSentinel(\n fetchWithPayment: typeof fetch,\n config: SentinelConfig,\n): typeof fetch {\n validateConfig(config);\n\n const budgetManager = config.budget ? new BudgetManager(config.budget) : null;\n const auditLogger = new AuditLogger(config.audit ?? { enabled: true, storage: new MemoryStorage() });\n\n const deps: InterceptorDeps = { budgetManager, auditLogger, config };\n\n const sentinelFetch: typeof fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url;\n const startTime = Date.now();\n\n // BEFORE: Check endpoint-level budget rules\n const pre = beforeRequest(url, init, deps);\n if (!pre.proceed && pre.evaluation && !pre.evaluation.allowed) {\n const violation = pre.evaluation.violation;\n\n // Log the blocked attempt (non-fatal if logging fails)\n try {\n await auditLogger.logBlocked(pre.context, violation, {\n humanSponsor: config.humanSponsor,\n metadata: config.metadata,\n });\n } catch {\n // audit failures never block\n }\n\n if (config.hooks?.onBudgetExceeded) {\n try {\n await config.hooks.onBudgetExceeded(violation);\n } catch {\n // hooks must never block\n }\n }\n\n throw new SentinelBudgetError(violation);\n }\n\n // EXECUTE: Call the underlying x402-wrapped fetch\n let response: Response;\n try {\n response = await fetchWithPayment(input, init);\n } catch (err) {\n // Network error — log and re-throw\n try {\n const record = {\n agent_id: pre.context.agentId,\n team: pre.context.team,\n human_sponsor: config.humanSponsor ?? null,\n amount: \"0.000000\",\n amount_raw: \"0\",\n asset: \"\",\n network: \"\",\n scheme: \"\",\n tx_hash: null,\n payer_address: \"\",\n payee_address: \"\",\n facilitator: null,\n endpoint: url,\n method: pre.context.method,\n status_code: 0,\n response_time_ms: Date.now() - startTime,\n policy_id: null,\n policy_evaluation: \"flagged\" as const,\n budget_remaining: null,\n task_id: null,\n session_id: null,\n metadata: { error: err instanceof Error ? err.message : String(err) },\n settled_at: null,\n tags: [\"error\", \"network_failure\"],\n };\n await auditLogger.log(record);\n } catch {\n // audit failures never block\n }\n throw err;\n }\n\n // AFTER: Parse response headers (NEVER touch the body), log audit record\n await afterResponse(response, pre.context, startTime, deps);\n\n // Return the original Response object completely untouched\n return response;\n };\n\n return sentinelFetch;\n}\n","import { readFileSync, appendFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { matchesQuery, buildSummary } from \"./memory\";\n\n/** JSONL file-based audit storage — appends one record per line */\nexport class FileStorage implements StorageBackend {\n private readonly filePath: string;\n private buffer: AuditRecord[] = [];\n private readonly flushThreshold: number;\n private flushTimer: NodeJS.Timeout | null = null;\n\n constructor(filePath = \".valeo/audit.jsonl\", flushThreshold = 100) {\n this.filePath = filePath;\n this.flushThreshold = flushThreshold;\n this.ensureDir();\n this.startAutoFlush();\n }\n\n async write(record: AuditRecord): Promise<void> {\n this.buffer.push(record);\n if (this.buffer.length >= this.flushThreshold) {\n await this.flush();\n }\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n await this.flush();\n const all = this.readAll();\n let results = all.filter((r) => matchesQuery(r, query));\n const offset = query.offset ?? 0;\n const limit = query.limit ?? results.length;\n return results.slice(offset, offset + limit);\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n await this.flush();\n const records = this.readAll().filter((r) => matchesQuery(r, query));\n return buildSummary(records, query);\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n await this.flush();\n return this.readAll().filter((r) => matchesQuery(r, query)).length;\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n await this.flush();\n return this.readAll().find((r) => r.id === id) ?? null;\n }\n\n /** Write buffered records to disk */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const lines = this.buffer.map((r) => JSON.stringify(r)).join(\"\\n\") + \"\\n\";\n appendFileSync(this.filePath, lines, \"utf-8\");\n this.buffer = [];\n }\n\n /** Stop the auto-flush timer (for clean shutdown) */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n }\n\n private readAll(): AuditRecord[] {\n if (!existsSync(this.filePath)) return [];\n const content = readFileSync(this.filePath, \"utf-8\");\n return content\n .split(\"\\n\")\n .filter((line) => line.trim().length > 0)\n .map((line) => JSON.parse(line) as AuditRecord);\n }\n\n private ensureDir(): void {\n const dir = dirname(this.filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n private startAutoFlush(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, 5_000);\n this.flushTimer.unref();\n }\n}\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { MemoryStorage } from \"./memory\";\n\ninterface ApiStorageConfig {\n apiKey: string;\n baseUrl?: string;\n batchSize?: number;\n flushIntervalMs?: number;\n}\n\n/**\n * Remote API storage backend — batches and POSTs records to api.valeo.money.\n * Falls back to in-memory storage if the API is unreachable.\n */\nexport class ApiStorage implements StorageBackend {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly batchSize: number;\n private buffer: AuditRecord[] = [];\n private readonly fallback: MemoryStorage;\n private flushTimer: NodeJS.Timeout | null = null;\n private useFallback = false;\n\n constructor(config: ApiStorageConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? \"https://api.valeo.money/v1\";\n this.batchSize = config.batchSize ?? 50;\n this.fallback = new MemoryStorage();\n this.startAutoFlush(config.flushIntervalMs ?? 10_000);\n }\n\n async write(record: AuditRecord): Promise<void> {\n this.buffer.push(record);\n // Always write to fallback for local query support\n await this.fallback.write(record);\n if (this.buffer.length >= this.batchSize) {\n await this.flush();\n }\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n if (this.useFallback) return this.fallback.query(query);\n try {\n return await this.apiRequest<AuditRecord[]>(\"POST\", \"/audit/query\", query);\n } catch {\n this.useFallback = true;\n return this.fallback.query(query);\n }\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n if (this.useFallback) return this.fallback.summarize(query);\n try {\n return await this.apiRequest<AuditSummary>(\"POST\", \"/audit/summarize\", query);\n } catch {\n this.useFallback = true;\n return this.fallback.summarize(query);\n }\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n if (this.useFallback) return this.fallback.count(query);\n try {\n const result = await this.apiRequest<{ count: number }>(\"POST\", \"/audit/count\", query);\n return result.count;\n } catch {\n this.useFallback = true;\n return this.fallback.count(query);\n }\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n if (this.useFallback) return this.fallback.getById(id);\n try {\n return await this.apiRequest<AuditRecord | null>(\"GET\", `/audit/${id}`);\n } catch {\n this.useFallback = true;\n return this.fallback.getById(id);\n }\n }\n\n /** Flush buffered records to the remote API */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const batch = this.buffer.splice(0, this.batchSize);\n try {\n await this.apiRequest(\"POST\", \"/audit/batch\", { records: batch });\n } catch {\n this.useFallback = true;\n console.warn(\n `[sentinel] API unreachable, falling back to in-memory storage. ${batch.length} records buffered locally.`,\n );\n }\n }\n\n /** Stop the auto-flush timer */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n }\n\n private async apiRequest<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const init: RequestInit = {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n };\n if (body) {\n init.body = JSON.stringify(body);\n }\n\n let lastError: Error | undefined;\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n const response = await fetch(url, init);\n if (!response.ok) {\n throw new Error(`API returned ${response.status}: ${response.statusText}`);\n }\n return (await response.json()) as T;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < 2) {\n await sleep(Math.pow(2, attempt) * 1000);\n }\n }\n }\n throw lastError;\n }\n\n private startAutoFlush(intervalMs: number): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, intervalMs);\n this.flushTimer.unref();\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"]}
1
+ {"version":3,"sources":["../src/budget/spike-detector.ts","../src/budget/policies.ts","../src/budget/index.ts","../src/audit/storage/memory.ts","../src/utils/id.ts","../src/audit/enrichment.ts","../src/audit/export.ts","../src/audit/index.ts","../src/errors.ts","../src/wrapper/headers.ts","../src/wrapper/interceptor.ts","../src/wrapper/index.ts","../src/audit/storage/file.ts","../src/audit/storage/api.ts"],"names":["calculateAverage","parseUSDC","formatUSDC","getHourStart","getDayStart","compareUSDC","addUSDC","formatUSDCHuman","createHash","appendFileSync","existsSync","readFileSync","dirname","mkdirSync"],"mappings":";;;;;;;;AAGO,IAAM,gBAAN,MAAoB;AAAA,EACR,UAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAmB,EAAC;AAAA,EAErC,WAAA,CAAY,SAAA,GAAY,CAAA,EAAK,UAAA,GAAa,EAAA,EAAI;AAC5C,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EACpB;AAAA;AAAA,EAGA,OAAO,MAAA,EAAsB;AAC3B,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,MAAM,CAAA;AACvB,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,GAAS,IAAA,CAAK,UAAA,EAAY;AACxC,MAAA,IAAA,CAAK,OAAO,KAAA,EAAM;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAA,EAA+B;AACnC,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAEnC,IAAA,MAAM,GAAA,GAAMA,kCAAA,CAAiB,IAAA,CAAK,MAAM,CAAA;AACxC,IAAA,MAAM,MAAA,GAASC,4BAAU,GAAG,CAAA;AAC5B,IAAA,IAAI,MAAA,KAAW,IAAI,OAAO,IAAA;AAE1B,IAAA,MAAM,SAAA,GAAYA,4BAAU,MAAM,CAAA;AAClC,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,SAAS,CAAA,GAAI,OAAO,MAAM,CAAA;AAE/C,IAAA,IAAI,KAAA,GAAQ,KAAK,SAAA,EAAW;AAC1B,MAAA,OACE,CAAA,SAAA,EAAY,MAAM,CAAA,IAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,uBAAA,EACrCC,4BAAA,CAAW,MAAM,CAAC,CAAA,aAAA,EAAgB,KAAK,SAAS,CAAA,EAAA,CAAA;AAAA,IAExD;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,UAAA,GAAqB;AACnB,IAAA,OAAOF,kCAAA,CAAiB,KAAK,MAAM,CAAA;AAAA,EACrC;AAAA;AAAA,EAGA,SAAA,GAAsB;AACpB,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,MAAM,CAAA;AAAA,EACxB;AAAA;AAAA,EAGA,WAAW,OAAA,EAAyB;AAClC,IAAA,IAAA,CAAK,OAAO,MAAA,GAAS,CAAA;AACrB,IAAA,KAAA,MAAW,KAAK,OAAA,CAAQ,KAAA,CAAM,CAAC,IAAA,CAAK,UAAU,CAAA,EAAG;AAC/C,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAA;;;AC3DO,SAAS,kBAAA,GAAmC;AACjD,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,MAAA;AAAA,IACZ,UAAA,EAAY,MAAA;AAAA,IACZ,SAAA,EAAW,OAAA;AAAA,IACX,cAAA,EAAgB;AAAA,GAClB;AACF;AAGO,SAAS,cAAA,GAA+B;AAC7C,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,MAAA;AAAA,IACZ,UAAA,EAAY,OAAA;AAAA,IACZ,SAAA,EAAW,QAAA;AAAA,IACX,cAAA,EAAgB;AAAA,GAClB;AACF;AAGO,SAAS,aAAA,GAA8B;AAC5C,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,OAAA;AAAA,IACZ,UAAA,EAAY,QAAA;AAAA,IACZ,SAAA,EAAW,SAAA;AAAA,IACX,cAAA,EAAgB;AAAA,GAClB;AACF;AAGO,SAAS,eAAA,GAAgC;AAC9C,EAAA,OAAO,EAAC;AACV;AAGO,SAAS,aAAa,SAAA,EAAgD;AAC3E,EAAA,OAAO,EAAE,GAAG,cAAA,EAAe,EAAG,GAAG,SAAA,EAAU;AAC7C;;;ACjCO,IAAM,aAAA,GAAN,MAAM,cAAA,CAAc;AAAA,EACjB,KAAA;AAAA,EACS,MAAA;AAAA,EACA,aAAA;AAAA,EAEjB,YAAY,MAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,gBAAgB,IAAI,aAAA;AAAA,MACvB,OAAO,cAAA,IAAkB;AAAA,KAC3B;AACA,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,IAAA,CAAK,KAAA,GAAQ;AAAA,MACX,UAAA,EAAY,UAAA;AAAA,MACZ,WAAA,EAAa,UAAA;AAAA,MACb,UAAA,EAAY,UAAA;AAAA,MACZ,SAAA,EAAW,CAAA;AAAA,MACX,SAAA,EAAW,EAAE,MAAA,EAAQG,8BAAA,CAAa,GAAG,CAAA,EAAG,KAAA,EAAOC,6BAAA,CAAY,GAAG,CAAA,EAAE;AAAA,MAChE,cAAA,EAAgB,UAAA;AAAA,MAChB,eAAe;AAAC,KAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,OAAA,EAA2C;AAClD,IAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,IAAA,MAAM,WAAqB,EAAC;AAG5B,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,gBAAA,EAAkB,MAAA,EAAQ;AACxC,MAAA,KAAA,MAAW,OAAA,IAAW,IAAA,CAAK,MAAA,CAAO,gBAAA,EAAkB;AAClD,QAAA,IAAI,eAAA,CAAgB,OAAA,CAAQ,QAAA,EAAU,OAAO,CAAA,EAAG;AAC9C,UAAA,OAAO;AAAA,YACL,OAAA,EAAS,KAAA;AAAA,YACT,WAAW,IAAA,CAAK,SAAA,CAAU,kBAAA,EAAoB,UAAA,EAAY,YAAY,OAAO;AAAA,WAC/E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,gBAAA,EAAkB,MAAA,EAAQ;AACxC,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,gBAAA,CAAiB,IAAA;AAAA,QAAK,CAAC,CAAA,KACjD,eAAA,CAAgB,OAAA,CAAQ,UAAU,CAAC;AAAA,OACrC;AACA,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,WAAW,IAAA,CAAK,SAAA,CAAU,kBAAA,EAAoB,UAAA,EAAY,YAAY,OAAO;AAAA,SAC/E;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,OAAO,UAAA,EAAY;AAC1B,MAAA,IAAIC,8BAAY,OAAA,CAAQ,MAAA,EAAQ,KAAK,MAAA,CAAO,UAAU,IAAI,CAAA,EAAG;AAC3D,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,SAAA,EAAW,KAAK,SAAA,CAAU,UAAA,EAAY,KAAK,MAAA,CAAO,UAAA,EAAY,YAAY,OAAO;AAAA,SACnF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,KAAA,CAAM,QAAQ,MAAM,CAAA;AACxD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAI,IAAA,CAAK,MAAA,CAAO,cAAA,KAAmB,MAAA,EAAW;AAC5C,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,WAAW,IAAA,CAAK,SAAA;AAAA,YACd,OAAA;AAAA,YACA,IAAA,CAAK,cAAc,UAAA,EAAW;AAAA,YAC9B,KAAK,KAAA,CAAM,WAAA;AAAA,YACX;AAAA;AACF,SACF;AAAA,MACF;AACA,MAAA,QAAA,CAAS,KAAK,QAAQ,CAAA;AAAA,IACxB;AAGA,IAAA,IAAI,IAAA,CAAK,OAAO,UAAA,EAAY;AAC1B,MAAA,MAAM,kBAAkBC,yBAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,WAAA,EAAa,QAAQ,MAAM,CAAA;AACtE,MAAA,IAAID,8BAAY,eAAA,EAAiB,IAAA,CAAK,MAAA,CAAO,UAAU,IAAI,CAAA,EAAG;AAC5D,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,SAAA,EAAW,IAAA,CAAK,SAAA,CAAU,QAAA,EAAU,IAAA,CAAK,OAAO,UAAA,EAAY,IAAA,CAAK,KAAA,CAAM,WAAA,EAAa,OAAO;AAAA,SAC7F;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,OAAO,SAAA,EAAW;AACzB,MAAA,MAAM,iBAAiBC,yBAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,UAAA,EAAY,QAAQ,MAAM,CAAA;AACpE,MAAA,IAAID,8BAAY,cAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,SAAS,IAAI,CAAA,EAAG;AAC1D,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,SAAA,EAAW,IAAA,CAAK,SAAA,CAAU,OAAA,EAAS,IAAA,CAAK,OAAO,SAAA,EAAW,IAAA,CAAK,KAAA,CAAM,UAAA,EAAY,OAAO;AAAA,SAC1F;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,OAAO,QAAA,EAAU;AACxB,MAAA,MAAM,iBAAiBC,yBAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,UAAA,EAAY,QAAQ,MAAM,CAAA;AACpE,MAAA,IAAID,8BAAY,cAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,QAAQ,IAAI,CAAA,EAAG;AACzD,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,SAAA,EAAW,IAAA,CAAK,SAAA,CAAU,OAAA,EAAS,IAAA,CAAK,OAAO,QAAA,EAAU,IAAA,CAAK,KAAA,CAAM,UAAA,EAAY,OAAO;AAAA,SACzF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,OAAO,eAAA,EAAiB;AAC/B,MAAA,IAAIA,6BAAA,CAAY,QAAQ,MAAA,EAAQ,IAAA,CAAK,OAAO,eAAA,CAAgB,KAAK,IAAI,CAAA,EAAG;AACtE,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,WAAW,IAAA,CAAK,SAAA;AAAA,YACd,mBAAA;AAAA,YACA,IAAA,CAAK,OAAO,eAAA,CAAgB,KAAA;AAAA,YAC5B,KAAK,KAAA,CAAM,UAAA;AAAA,YACX;AAAA;AACF,SACF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,QAAA,EAAS;AAAA,EACnC;AAAA;AAAA,EAGA,MAAA,CAAO,QAAgB,SAAA,EAAyB;AAC9C,IAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,IAAA,IAAA,CAAK,MAAM,UAAA,GAAaC,yBAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,YAAY,MAAM,CAAA;AAC7D,IAAA,IAAA,CAAK,MAAM,WAAA,GAAcA,yBAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,aAAa,MAAM,CAAA;AAC/D,IAAA,IAAA,CAAK,MAAM,UAAA,GAAaA,yBAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,YAAY,MAAM,CAAA;AAC7D,IAAA,IAAA,CAAK,KAAA,CAAM,SAAA,EAAA;AACX,IAAA,IAAA,CAAK,aAAA,CAAc,OAAO,MAAM,CAAA;AAChC,IAAA,IAAA,CAAK,KAAA,CAAM,cAAA,GAAiB,IAAA,CAAK,aAAA,CAAc,UAAA,EAAW;AAC1D,IAAA,IAAA,CAAK,KAAA,CAAM,aAAA,GAAgB,IAAA,CAAK,aAAA,CAAc,SAAA,EAAU;AAAA,EAC1D;AAAA;AAAA,EAGA,QAAA,GAAwB;AACtB,IAAA,IAAA,CAAK,iBAAA,EAAkB;AACvB,IAAA,OAAO,EAAE,GAAG,IAAA,CAAK,KAAA,EAAO,aAAA,EAAe,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,aAAa,CAAA,EAAE;AAAA,EACvE;AAAA;AAAA,EAGA,MAAM,KAAA,EAA2C;AAC/C,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,QAAQ,KAAA;AAAO,MACb,KAAK,QAAA;AACH,QAAA,IAAA,CAAK,MAAM,WAAA,GAAc,UAAA;AACzB,QAAA,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,MAAA,GAASH,8BAAA,CAAa,GAAG,CAAA;AAC9C,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,IAAA,CAAK,MAAM,UAAA,GAAa,UAAA;AACxB,QAAA,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,KAAA,GAAQC,6BAAA,CAAY,GAAG,CAAA;AAC5C,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,IAAA,CAAK,MAAM,UAAA,GAAa,UAAA;AACxB,QAAA,IAAA,CAAK,MAAM,WAAA,GAAc,UAAA;AACzB,QAAA,IAAA,CAAK,MAAM,UAAA,GAAa,UAAA;AACxB,QAAA,IAAA,CAAK,MAAM,SAAA,GAAY,CAAA;AACvB,QAAA;AAAA;AACJ,EACF;AAAA;AAAA,EAGA,SAAA,GAAoB;AAClB,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,KAAK,CAAA;AAAA,EAClC;AAAA;AAAA,EAGA,OAAO,WAAA,CAAY,IAAA,EAAc,MAAA,EAAqC;AACpE,IAAA,MAAM,GAAA,GAAM,IAAI,cAAA,CAAc,MAAM,CAAA;AACpC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,IAAA,GAAA,CAAI,KAAA,GAAQ,MAAA;AACZ,IAAA,GAAA,CAAI,aAAA,CAAc,UAAA,CAAW,MAAA,CAAO,aAAa,CAAA;AACjD,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA,EAGQ,iBAAA,GAA0B;AAChC,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,SAAA,GAAYD,+BAAa,GAAG,CAAA;AAClC,IAAA,MAAM,QAAA,GAAWC,8BAAY,GAAG,CAAA;AAEhC,IAAA,IAAI,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,MAAA,EAAQ;AAC3C,MAAA,IAAA,CAAK,MAAM,WAAA,GAAc,UAAA;AACzB,MAAA,IAAA,CAAK,KAAA,CAAM,UAAU,MAAA,GAAS,SAAA;AAAA,IAChC;AACA,IAAA,IAAI,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,KAAA,EAAO;AACzC,MAAA,IAAA,CAAK,MAAM,UAAA,GAAa,UAAA;AACxB,MAAA,IAAA,CAAK,KAAA,CAAM,UAAU,KAAA,GAAQ,QAAA;AAAA,IAC/B;AAAA,EACF;AAAA,EAEQ,SAAA,CACN,IAAA,EACA,KAAA,EACA,OAAA,EACA,OAAA,EACiB;AACjB,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,KAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAW,OAAA,CAAQ,MAAA;AAAA,MACnB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,SAAA,EAAW,KAAK,GAAA;AAAI,KACtB;AAAA,EACF;AACF;AAGA,SAAS,eAAA,CAAgB,KAAa,OAAA,EAA0B;AAC9D,EAAA,MAAM,QAAQ,IAAI,MAAA;AAAA,IAChB,GAAA,GAAM,QAAQ,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,GAAI;AAAA,GAC3D;AACA,EAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AACvB;;;ACpOO,IAAM,gBAAN,MAA8C;AAAA,EAClC,OAAA,uBAAc,GAAA,EAAyB;AAAA,EACvC,cAAwB,EAAC;AAAA,EACzB,UAAA;AAAA,EAEjB,WAAA,CAAY,aAAa,GAAA,EAAQ;AAC/B,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EACpB;AAAA,EAEA,MAAM,MAAM,MAAA,EAAoC;AAC9C,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,IAAA,IAAQ,IAAA,CAAK,UAAA,EAAY;AACxC,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,KAAA,EAAM;AACtC,MAAA,IAAI,MAAA,EAAQ,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA;AAAA,IACxC;AACA,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,EAAA,EAAI,MAAM,CAAA;AAClC,IAAA,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,EAAE,CAAA;AAAA,EACjC;AAAA,EAEA,MAAM,MAAM,KAAA,EAA2C;AACrD,IAAA,IAAI,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AAC/B,IAAA,OAAA,GAAU,KAAK,IAAA,CAAK,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,MAAM,KAAK,CAAA;AACvD,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,IAAU,CAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,IAAS,OAAA,CAAQ,MAAA;AACrC,IAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,MAAA,GAAS,KAAK,CAAA;AAAA,EAC7C;AAAA,EAEA,MAAM,UAAU,KAAA,EAAmD;AACjE,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AACjC,IAAA,OAAO,YAAA,CAAa,SAAS,KAAK,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,MAAM,KAAA,EAA6C;AACvD,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,CAAE,MAAA;AAAA,EAC5B;AAAA,EAEA,MAAM,QAAQ,EAAA,EAAyC;AACrD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,IAAK,IAAA;AAAA,EACjC;AAAA,EAEQ,OAAO,KAAA,EAA2C;AACxD,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,YAAA,CAAa,CAAA,EAAG,KAAK,CAAC,CAAA;AAAA,EACxE;AAAA,EAEQ,IAAA,CACN,OAAA,EACA,OAAA,EACA,KAAA,EACe;AACf,IAAA,IAAI,CAAC,SAAS,OAAO,OAAA;AACrB,IAAA,MAAM,GAAA,GAAM,KAAA,KAAU,MAAA,GAAS,EAAA,GAAK,CAAA;AACpC,IAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AAC5B,MAAA,QAAQ,OAAA;AAAS,QACf,KAAK,YAAA;AACH,UAAA,OAAA,CAAQ,CAAA,CAAE,UAAA,GAAa,CAAA,CAAE,UAAA,IAAc,GAAA;AAAA,QACzC,KAAK,QAAA;AACH,UAAA,OAAOC,6BAAA,CAAY,CAAA,CAAE,MAAA,EAAQ,CAAA,CAAE,MAAM,CAAA,GAAI,GAAA;AAAA,QAC3C,KAAK,UAAA;AACH,UAAA,OAAO,CAAA,CAAE,QAAA,CAAS,aAAA,CAAc,CAAA,CAAE,QAAQ,CAAA,GAAI,GAAA;AAAA,QAChD;AACE,UAAA,OAAO,CAAA;AAAA;AACX,IACF,CAAC,CAAA;AAAA,EACH;AACF;AAGO,SAAS,YAAA,CACd,QACA,KAAA,EACS;AACT,EAAA,IAAI,MAAM,OAAA,IAAW,MAAA,CAAO,QAAA,KAAa,KAAA,CAAM,SAAS,OAAO,KAAA;AAC/D,EAAA,IAAI,MAAM,IAAA,IAAQ,MAAA,CAAO,IAAA,KAAS,KAAA,CAAM,MAAM,OAAO,KAAA;AACrD,EAAA,IAAI,KAAA,CAAM,YAAY,CAAC,MAAA,CAAO,SAAS,QAAA,CAAS,KAAA,CAAM,QAAQ,CAAA,EAAG,OAAO,KAAA;AACxE,EAAA,IAAI,KAAA,CAAM,aAAaA,6BAAA,CAAY,MAAA,CAAO,QAAQ,KAAA,CAAM,SAAS,CAAA,GAAI,CAAA,EAAG,OAAO,KAAA;AAC/E,EAAA,IAAI,KAAA,CAAM,aAAaA,6BAAA,CAAY,MAAA,CAAO,QAAQ,KAAA,CAAM,SAAS,CAAA,GAAI,CAAA,EAAG,OAAO,KAAA;AAC/E,EAAA,IAAI,MAAM,SAAA,IAAa,MAAA,CAAO,UAAA,GAAa,KAAA,CAAM,WAAW,OAAO,KAAA;AACnE,EAAA,IAAI,MAAM,OAAA,IAAW,MAAA,CAAO,UAAA,GAAa,KAAA,CAAM,SAAS,OAAO,KAAA;AAC/D,EAAA,IAAI,KAAA,CAAM,MAAA,EAAQ,MAAA,IAAU,CAAC,KAAA,CAAM,OAAO,QAAA,CAAS,MAAA,CAAO,iBAAiB,CAAA,EAAG,OAAO,KAAA;AACrF,EAAA,IAAI,KAAA,CAAM,IAAA,EAAM,MAAA,IAAU,CAAC,MAAM,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,KAAM,OAAO,IAAA,CAAK,QAAA,CAAS,CAAC,CAAC,GAAG,OAAO,KAAA;AACnF,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,YAAA,CACd,SACA,KAAA,EACc;AACd,EAAA,IAAI,QAAA,GAAW,EAAA;AACf,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAY;AAC/B,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,MAAM,UAA4D,EAAC;AACnE,EAAA,MAAM,aAA+D,EAAC;AACtE,EAAA,MAAM,SAA2D,EAAC;AAClE,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,KAAA,GAAQ,QAAA;AACZ,EAAA,IAAI,KAAA,GAAQ,CAAA;AAEZ,EAAA,KAAA,MAAW,KAAK,OAAA,EAAS;AACvB,IAAA,MAAM,GAAA,GAAMJ,2BAAA,CAAU,CAAA,CAAE,MAAM,CAAA;AAC9B,IAAA,QAAA,IAAY,GAAA;AACZ,IAAA,IAAI,GAAA,GAAM,QAAQ,MAAA,GAAS,GAAA;AAC3B,IAAA,MAAA,CAAO,GAAA,CAAI,EAAE,QAAQ,CAAA;AACrB,IAAA,SAAA,CAAU,GAAA,CAAI,EAAE,QAAQ,CAAA;AAExB,IAAA,IAAI,CAAA,CAAE,UAAA,GAAa,KAAA,EAAO,KAAA,GAAQ,CAAA,CAAE,UAAA;AACpC,IAAA,IAAI,CAAA,CAAE,UAAA,GAAa,KAAA,EAAO,KAAA,GAAQ,CAAA,CAAE,UAAA;AAEpC,IAAA,IAAI,CAAA,CAAE,sBAAsB,SAAA,EAAW,UAAA,EAAA;AAGvC,IAAA,MAAM,UAAA,GAAa,QAAQ,CAAA,CAAE,QAAQ,KAAK,EAAE,KAAA,EAAO,UAAA,EAAY,KAAA,EAAO,CAAA,EAAE;AACxE,IAAA,UAAA,CAAW,QAAQC,4BAAA,CAAWD,2BAAA,CAAU,UAAA,CAAW,KAAK,IAAI,GAAG,CAAA;AAC/D,IAAA,UAAA,CAAW,KAAA,EAAA;AACX,IAAA,OAAA,CAAQ,CAAA,CAAE,QAAQ,CAAA,GAAI,UAAA;AAGtB,IAAA,MAAM,OAAA,GAAU,WAAW,CAAA,CAAE,QAAQ,KAAK,EAAE,KAAA,EAAO,UAAA,EAAY,KAAA,EAAO,CAAA,EAAE;AACxE,IAAA,OAAA,CAAQ,QAAQC,4BAAA,CAAWD,2BAAA,CAAU,OAAA,CAAQ,KAAK,IAAI,GAAG,CAAA;AACzD,IAAA,OAAA,CAAQ,KAAA,EAAA;AACR,IAAA,UAAA,CAAW,CAAA,CAAE,QAAQ,CAAA,GAAI,OAAA;AAGzB,IAAA,MAAM,OAAA,GAAU,EAAE,IAAA,IAAQ,QAAA;AAC1B,IAAA,MAAM,SAAA,GAAY,OAAO,OAAO,CAAA,IAAK,EAAE,KAAA,EAAO,UAAA,EAAY,OAAO,CAAA,EAAE;AACnE,IAAA,SAAA,CAAU,QAAQC,4BAAA,CAAWD,2BAAA,CAAU,SAAA,CAAU,KAAK,IAAI,GAAG,CAAA;AAC7D,IAAA,SAAA,CAAU,KAAA,EAAA;AACV,IAAA,MAAA,CAAO,OAAO,CAAA,GAAI,SAAA;AAAA,EACpB;AAEA,EAAA,MAAM,QAAQ,OAAA,CAAQ,MAAA;AACtB,EAAA,OAAO;AAAA,IACL,WAAA,EAAaM,kCAAgB,QAAQ,CAAA;AAAA,IACrC,kBAAA,EAAoB,KAAA;AAAA,IACpB,kBAAkB,SAAA,CAAU,IAAA;AAAA,IAC5B,eAAe,MAAA,CAAO,IAAA;AAAA,IACtB,WAAA,EAAa,QAAQ,CAAA,GAAIA,iCAAA,CAAgB,WAAW,MAAA,CAAO,KAAK,CAAC,CAAA,GAAI,MAAA;AAAA,IACrE,WAAA,EAAaA,kCAAgB,MAAM,CAAA;AAAA,IACnC,QAAA,EAAU,OAAA;AAAA,IACV,WAAA,EAAa,UAAA;AAAA,IACb,OAAA,EAAS,MAAA;AAAA,IACT,UAAA;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,KAAA,CAAM,SAAA,KAAc,KAAA,KAAU,WAAW,CAAA,GAAI,KAAA,CAAA;AAAA,MACpD,GAAA,EAAK,KAAA,CAAM,OAAA,KAAY,KAAA,KAAU,IAAI,CAAA,GAAI,KAAA;AAAA;AAC3C,GACF;AACF;AClJO,SAAS,gBAAA,CACd,OAAA,EACA,QAAA,EACA,SAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,KAAA,GAAQ,GAAG,OAAO,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,EAAI,SAAS,IAAI,MAAM,CAAA,CAAA;AAC3D,EAAA,MAAM,IAAA,GAAOC,kBAAW,QAAQ,CAAA,CAAE,OAAO,KAAK,CAAA,CAAE,OAAO,KAAK,CAAA;AAC5D,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACzB;;;ACEO,SAAS,aAAa,KAAA,EAAqC;AAChE,EAAA,MAAM,EAAE,SAAS,MAAA,EAAQ,UAAA,EAAY,gBAAgB,UAAA,EAAY,gBAAA,EAAkB,iBAAgB,GAAI,KAAA;AACvG,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,MAAM,EAAA,GAAK,iBAAiB,OAAA,CAAQ,OAAA,EAAS,QAAQ,QAAA,EAAU,GAAA,EAAK,QAAQ,MAAM,CAAA;AAElF,EAAA,MAAM,IAAA,GAAO,WAAA,CAAY,OAAA,EAAS,MAAA,CAAO,OAAO,UAAU,CAAA;AAE1D,EAAA,OAAO;AAAA,IACL,EAAA;AAAA,IACA,UAAU,OAAA,CAAQ,OAAA;AAAA,IAClB,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,aAAA,EAAe,OAAO,YAAA,IAAgB,IAAA;AAAA,IAEtC,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,YAAY,OAAA,CAAQ,SAAA;AAAA,IACpB,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAEhB,OAAA,EAAS,YAAY,WAAA,IAAe,IAAA;AAAA,IACpC,aAAA,EAAe,YAAY,KAAA,IAAS,EAAA;AAAA,IACpC,eAAe,OAAA,CAAQ,KAAA;AAAA,IACvB,WAAA,EAAa,IAAA;AAAA,IAEb,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,WAAA,EAAa,UAAA;AAAA,IACb,gBAAA,EAAkB,cAAA;AAAA,IAElB,SAAA,EAAW,IAAA;AAAA,IACX,iBAAA,EAAmB,gBAAA;AAAA,IACnB,gBAAA,EAAkB,eAAA;AAAA,IAElB,OAAA,EAAS,OAAA,CAAQ,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA;AAAA,IACxC,UAAA,EAAY,OAAA,CAAQ,QAAA,CAAS,YAAY,CAAA,IAAK,IAAA;AAAA,IAC9C,UAAU,EAAE,GAAG,QAAQ,QAAA,EAAU,GAAG,OAAO,QAAA,EAAS;AAAA,IAEpD,UAAA,EAAY,GAAA;AAAA,IACZ,UAAA,EAAY,UAAA,EAAY,OAAA,GAAU,GAAA,GAAM,IAAA;AAAA,IAExC;AAAA,GACF;AACF;AAGO,SAAS,mBAAA,CACd,OAAA,EACA,MAAA,EACA,gBAAA,EACa;AACb,EAAA,OAAO,YAAA,CAAa;AAAA,IAClB,OAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA,EAAY,CAAA;AAAA,IACZ,cAAA,EAAgB,CAAA;AAAA,IAChB,UAAA,EAAY,IAAA;AAAA,IACZ,gBAAA;AAAA,IACA,eAAA,EAAiB;AAAA,GAClB,CAAA;AACH;AAEA,SAAS,WAAA,CAAY,SAAyB,UAAA,EAAyC;AACrF,EAAA,MAAM,OAAiB,EAAC;AAExB,EAAA,IAAI,YAAY,UAAA,EAAY;AAC1B,IAAA,IAAA,CAAK,IAAA,CAAK,GAAG,UAAA,CAAW,UAAU,CAAA;AAAA,EACpC;AAEA,EAAA,IAAI,YAAY,QAAA,EAAU;AACxB,IAAA,KAAA,MAAW,IAAA,IAAQ,WAAW,QAAA,EAAU;AACtC,MAAA,MAAM,KAAA,GAAQ,IAAI,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AACrC,MAAA,IAAI,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAChC,QAAA,IAAA,CAAK,IAAA,CAAK,GAAG,IAAA,CAAK,IAAI,CAAA;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;;;AC7FA,IAAM,WAAA,GAAqC;AAAA,EACzC,IAAA;AAAA,EAAM,UAAA;AAAA,EAAY,MAAA;AAAA,EAAQ,eAAA;AAAA,EAC1B,QAAA;AAAA,EAAU,YAAA;AAAA,EAAc,OAAA;AAAA,EAAS,SAAA;AAAA,EAAW,QAAA;AAAA,EAC5C,SAAA;AAAA,EAAW,eAAA;AAAA,EAAiB,eAAA;AAAA,EAAiB,aAAA;AAAA,EAC7C,UAAA;AAAA,EAAY,QAAA;AAAA,EAAU,aAAA;AAAA,EAAe,kBAAA;AAAA,EACrC,WAAA;AAAA,EAAa,mBAAA;AAAA,EAAqB,kBAAA;AAAA,EAClC,SAAA;AAAA,EAAW,YAAA;AAAA,EACX,YAAA;AAAA,EAAc;AAChB,CAAA;AAGO,SAAS,MAAM,OAAA,EAAgC;AACpD,EAAA,MAAM,KAAA,GAAkB,CAAC,WAAA,CAAY,IAAA,CAAK,GAAG,CAAC,CAAA;AAE9C,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAM,MAAA,GAAS,WAAA,CAAY,GAAA,CAAI,CAAC,GAAA,KAAQ;AACtC,MAAA,MAAM,GAAA,GAAM,OAAO,GAAG,CAAA;AACtB,MAAA,IAAI,GAAA,KAAQ,IAAA,IAAQ,GAAA,KAAQ,MAAA,EAAW,OAAO,EAAA;AAC9C,MAAA,MAAM,GAAA,GAAM,OAAO,GAAG,CAAA;AACtB,MAAA,IAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,IAAK,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,IAAK,GAAA,CAAI,QAAA,CAAS,IAAI,CAAA,EAAG;AAChE,QAAA,OAAO,CAAA,CAAA,EAAI,GAAA,CAAI,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,MACpC;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,EAC7B;AAEA,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AAC5B;AAGO,SAAS,MAAA,CAAO,OAAA,EAAwB,MAAA,GAAS,KAAA,EAAe;AACrE,EAAA,OAAO,KAAK,SAAA,CAAU,OAAA,EAAS,IAAA,EAAM,MAAA,GAAS,IAAI,MAAS,CAAA;AAC7D;;;ACxBO,IAAM,cAAN,MAAkB;AAAA,EACN,OAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EAEjB,YAAY,MAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,KAAY,KAAA;AACnC,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA,EAAQ,OAAA,IAAW,IAAI,aAAA,EAAc;AACpD,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA,EAAQ,YAAA,IAAgB,EAAC;AAAA,EAC/C;AAAA;AAAA,EAGA,MAAM,IAAI,MAAA,EAAsE;AAC9E,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,IAAA,GAAoB;AAAA,MACxB,GAAG,MAAA;AAAA,MACH,EAAA,EAAI,iBAAiB,MAAA,CAAO,QAAA,EAAU,OAAO,QAAA,EAAU,GAAA,EAAK,OAAO,MAAM,CAAA;AAAA,MACzE,UAAA,EAAY;AAAA,KACd;AAEA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA;AAEjC,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,QAAQ,CAAA;AAAA,MACnC,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,8CAA8C,GAAG,CAAA;AAAA,MAChE;AAAA,IACF;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,UAAA,CACJ,OAAA,EACA,SAAA,EACA,MAAA,EACsB;AACtB,IAAA,MAAM,MAAA,GAAS,oBAAoB,OAAA,EAAS;AAAA,MAC1C,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,GAAG;AAAA,OACF,SAAS,CAAA;AACZ,IAAA,MAAA,CAAO,QAAA,CAAS,gBAAgB,CAAA,GAAI,SAAA,CAAU,IAAA;AAC9C,IAAA,MAAA,CAAO,QAAA,CAAS,iBAAiB,CAAA,GAAI,SAAA,CAAU,KAAA;AAE/C,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAI;AACF,QAAA,MAAM,KAAK,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA,MAC9C,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,8CAA8C,GAAG,CAAA;AAAA,MAChE;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,MAAM,KAAA,EAA2C;AACrD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA;AAAA,EACjC;AAAA;AAAA,EAGA,MAAM,UAAU,KAAA,EAAoD;AAClE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,CAAU,KAAA,IAAS,EAAE,CAAA;AAAA,EAC3C;AAAA;AAAA,EAGA,MAAM,UAAU,KAAA,EAAqC;AACnD,IAAA,MAAM,UAAU,MAAM,IAAA,CAAK,QAAQ,KAAA,CAAM,KAAA,IAAS,EAAE,CAAA;AACpD,IAAA,OAAO,MAAM,OAAO,CAAA;AAAA,EACtB;AAAA;AAAA,EAGA,MAAM,WAAW,KAAA,EAAqC;AACpD,IAAA,MAAM,UAAU,MAAM,IAAA,CAAK,QAAQ,KAAA,CAAM,KAAA,IAAS,EAAE,CAAA;AACpD,IAAA,OAAO,MAAA,CAAO,SAAS,IAAI,CAAA;AAAA,EAC7B;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,WAAW,IAAA,CAAK,OAAA,IAAW,OAAO,IAAA,CAAK,OAAA,CAAQ,UAAU,UAAA,EAAY;AACvE,MAAA,MAAO,IAAA,CAAK,QAAwD,KAAA,EAAM;AAAA,IAC5E;AAAA,EACF;AAAA;AAAA,EAGA,UAAA,GAA6B;AAC3B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEQ,OAAO,MAAA,EAAkC;AAC/C,IAAA,IAAI,IAAA,CAAK,YAAA,CAAa,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAC3C,IAAA,MAAM,IAAA,GAAO,EAAE,GAAG,MAAA,EAAQ,UAAU,EAAE,GAAG,MAAA,CAAO,QAAA,EAAS,EAAE;AAC3D,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,YAAA,EAAc;AACrC,MAAA,IAAI,KAAA,IAAS,KAAK,QAAA,EAAU;AAC1B,QAAA,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,GAAI,YAAA;AAAA,MACzB;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AC5GO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EAC9B,IAAA;AAAA,EAET,WAAA,CAAY,SAAiB,IAAA,EAAc;AACzC,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,aAAA,CAAc;AAAA,EAC5C,SAAA;AAAA,EAET,YAAY,SAAA,EAA4B;AACtC,IAAA,KAAA,CAAM,kBAAA,CAAmB,SAAS,CAAA,EAAG,iBAAiB,CAAA;AACtD,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AACZ,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AAAA,EACnB;AACF;AAGO,IAAM,kBAAA,GAAN,cAAiC,aAAA,CAAc;AAAA,EAC3C,MAAA;AAAA,EAET,WAAA,CAAY,SAAiB,MAAA,EAA+B;AAC1D,IAAA,KAAA,CAAM,SAAS,aAAa,CAAA;AAC5B,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,aAAA,CAAc;AAAA,EACrD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,SAAS,cAAc,CAAA;AAC7B,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEA,SAAS,mBAAmB,CAAA,EAA4B;AACtD,EAAA,MAAM,SAAA,GAAY,CAAA,CAAA,EAAI,CAAA,CAAE,SAAS,CAAA,CAAA;AAEjC,EAAA,QAAQ,EAAE,IAAA;AAAM,IACd,KAAK,UAAA;AACH,MAAA,OAAO,oBAAoB,SAAS,CAAA,4BAAA,EAA+B,EAAE,KAAK,CAAA,IAAA,EAAO,EAAE,OAAO,CAAA,CAAA;AAAA,IAC5F,KAAK,QAAA;AACH,MAAA,OAAO,CAAA,kBAAA,EAAqB,CAAA,CAAE,OAAO,CAAA,WAAA,EAAc,CAAA,CAAE,KAAK,CAAA,iBAAA,EAAoB,CAAA,CAAE,OAAO,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,CAAA;AAAA,IACjH,KAAK,OAAA;AACH,MAAA,OAAO,CAAA,kBAAA,EAAqB,CAAA,CAAE,OAAO,CAAA,WAAA,EAAc,CAAA,CAAE,KAAK,CAAA,gBAAA,EAAmB,CAAA,CAAE,OAAO,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,CAAA;AAAA,IAChH,KAAK,OAAA;AACH,MAAA,OAAO,CAAA,kBAAA,EAAqB,CAAA,CAAE,OAAO,CAAA,WAAA,EAAc,CAAA,CAAE,KAAK,CAAA,gBAAA,EAAmB,CAAA,CAAE,OAAO,CAAA,YAAA,EAAe,SAAS,CAAA,CAAA,CAAA;AAAA,IAChH,KAAK,OAAA;AACH,MAAA,OAAO,yBAAyB,SAAS,CAAA,qBAAA,EAAwB,EAAE,KAAK,CAAA,IAAA,EAAO,EAAE,OAAO,CAAA,CAAA;AAAA,IAC1F,KAAK,kBAAA;AACH,MAAA,OAAO,CAAA,kBAAA,EAAqB,CAAA,CAAE,QAAQ,CAAA,oBAAA,EAAuB,EAAE,OAAO,CAAA,CAAA;AAAA,IACxE,KAAK,mBAAA;AACH,MAAA,OAAO,sBAAsB,SAAS,CAAA,6BAAA,EAAgC,EAAE,KAAK,CAAA,IAAA,EAAO,EAAE,OAAO,CAAA,CAAA;AAAA;AAEnG;AAGO,SAAS,eAAe,MAAA,EAWtB;AACP,EAAA,IAAI,CAAC,MAAA,CAAO,OAAA,IAAW,OAAO,OAAA,CAAQ,IAAA,OAAW,EAAA,EAAI;AACnD,IAAA,MAAM,IAAI,oBAAoB,2CAA2C,CAAA;AAAA,EAC3E;AAEA,EAAA,MAAM,SAAS,MAAA,CAAO,MAAA;AACtB,EAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,EAAA,MAAM,YAAA,GAAe,CAAC,YAAA,EAAc,YAAA,EAAc,aAAa,UAAU,CAAA;AACzE,EAAA,KAAA,MAAW,SAAS,YAAA,EAAc;AAChC,IAAA,MAAM,KAAA,GAAQ,OAAO,KAAK,CAAA;AAC1B,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,IAAI;AACF,QAAAP,2BAAA,CAAU,KAAK,CAAA;AAAA,MACjB,CAAA,CAAA,MAAQ;AACN,QAAA,MAAM,IAAI,mBAAA;AAAA,UACR,CAAA,OAAA,EAAU,KAAK,CAAA,EAAA,EAAK,KAAK,CAAA,4BAAA;AAAA,SAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,cAAA,KAAmB,MAAA,IAAa,MAAA,CAAO,kBAAkB,CAAA,EAAK;AACvE,IAAA,MAAM,IAAI,mBAAA;AAAA,MACR,CAAA,yCAAA,EAA4C,OAAO,cAAc,CAAA;AAAA,KACnE;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,gBAAA,EAAkB,MAAA,IAAU,MAAA,CAAO,kBAAkB,MAAA,EAAQ;AACtE,IAAA,MAAM,IAAI,mBAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACF;;;AC3FO,SAAS,mBAAmB,MAAA,EAAwC;AACzE,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,MAAM,MAAA,CAAO,IAAA,CAAK,QAAQ,QAAQ,CAAA,CAAE,QAAA,CAAS,OAAO,CAAC,CAAA;AAAA,EACnE,CAAA,CAAA,MAAQ;AACN,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,CAAK,MAAM,MAAM,CAAA;AAAA,IAC1B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AACF;AAOO,SAAS,sBAAsB,GAAA,EAAqB;AACzD,EAAA,OAAOC,4BAAA,CAAW,MAAA,CAAO,GAAG,CAAC,CAAA;AAC/B;AAOO,SAAS,qBAAqB,MAAA,EAA8C;AACjF,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AACpB,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,MAAA,CAAO,IAAA,CAAK,QAAQ,QAAQ,CAAA,CAAE,SAAS,OAAO,CAAA;AAC3D,IAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACxB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAwBO,SAAS,2BAA2B,eAAA,EAMlC;AACP,EAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,OAAA,CAAQ,CAAC,CAAA;AACvC,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,OAAO;AAAA,IACL,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,SAAS,KAAA,CAAM,OAAA;AAAA,IACf,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,OAAO,KAAA,CAAM;AAAA,GACf;AACF;;;AC9DO,SAAS,aAAA,CACd,GAAA,EACA,IAAA,EACA,IAAA,EAKA;AACA,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,IAAU,KAAA;AAC/B,EAAA,MAAM,OAAA,GAA0B;AAAA,IAC9B,QAAA,EAAU,GAAA;AAAA,IACV,MAAA,EAAQ,OAAO,WAAA,EAAY;AAAA,IAC3B,OAAA,EAAS,KAAK,MAAA,CAAO,OAAA;AAAA,IACrB,IAAA,EAAM,IAAA,CAAK,MAAA,CAAO,IAAA,IAAQ,IAAA;AAAA,IAC1B,MAAA,EAAQ,UAAA;AAAA,IACR,SAAA,EAAW,GAAA;AAAA,IACX,KAAA,EAAO,EAAA;AAAA,IACP,OAAA,EAAS,EAAA;AAAA,IACT,MAAA,EAAQ,EAAA;AAAA,IACR,KAAA,EAAO,EAAA;AAAA,IACP,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,IACpB,UAAU,EAAE,GAAI,KAAK,MAAA,CAAO,QAAA,IAAY,EAAC;AAAG,GAC9C;AAEA,EAAA,IAAI,KAAK,aAAA,EAAe;AACtB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,aAAA,CAAc,QAAA,CAAS,OAAO,CAAA;AACjD,IAAA,IAAI,CAAC,MAAM,OAAA,EAAS;AAClB,MAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,OAAA,EAAS,YAAY,KAAA,EAAM;AAAA,IACtD;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,OAAA,EAAQ;AAClC;AAQA,eAAsB,aAAA,CACpB,QAAA,EACA,OAAA,EACA,SAAA,EACA,IAAA,EAC6B;AAC7B,EAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAGpC,EAAA,MAAM,qBAAA,GAAwB,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,kBAAkB,CAAA;AACrE,EAAA,IAAI,qBAAA,EAAuB;AACzB,IAAA,MAAM,UAAA,GAAa,qBAAqB,qBAAqB,CAAA;AAC7D,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,OAAA,CAAQ,OAAA,GAAU,UAAA,CAAW,OAAA,IAAW,OAAA,CAAQ,OAAA;AAGhD,MAAA,IAAI,OAAA,CAAQ,WAAW,UAAA,EAAY;AACjC,QAAA,MAAM,YAAA,GAAe,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,QAAQ,QAAQ,CAAA;AACzD,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,OAAA,CAAQ,MAAA,GAAS,YAAA;AACjB,UAAA,IAAA,CAAK,UAAA,CAAW,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA;AAAA,QACzC;AAAA,MACF;AAEA,MAAA,MAAM,gBAAA,GAAmB,yBAAA,CAA0B,OAAA,EAAS,IAAI,CAAA;AAChE,MAAA,IAAI,eAAA,GAAiC,IAAA;AAErC,MAAA,IAAI,IAAA,CAAK,aAAA,IAAiB,OAAA,CAAQ,MAAA,KAAW,UAAA,EAAY;AACvD,QAAA,IAAA,CAAK,aAAA,CAAc,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,QAAQ,QAAQ,CAAA;AAC1D,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,aAAA,CAAc,QAAA,EAAS;AAC1C,QAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,QAAA,EAAU;AAChC,UAAA,eAAA,GAAkBK,iCAAA;AAAA,YAChBN,2BAAA,CAAU,KAAK,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA,GAAIA,2BAAA,CAAU,MAAM,UAAU;AAAA,WACrE;AAAA,QACF;AAAA,MACF;AAEA,MAAA,MAAM,SAAS,YAAA,CAAa;AAAA,QAC1B,OAAA;AAAA,QACA,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,YAAY,QAAA,CAAS,MAAA;AAAA,QACrB,cAAA;AAAA,QACA,UAAA;AAAA,QACA,gBAAA,EAAkB,mBAAmB,SAAA,GAAY,SAAA;AAAA,QACjD;AAAA,OACD,CAAA;AAED,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,MAAM,CAAA;AAAA,MACnC,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,4CAA4C,GAAG,CAAA;AAAA,MAC9D;AAEA,MAAA,IAAI,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,YAAA,EAAc;AACnC,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,YAAA,CAAa,MAAM,CAAA;AAAA,QAC7C,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AAEA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,IAAA,MAAM,SAAA,GACJ,SAAS,OAAA,CAAQ,GAAA,CAAI,kBAAkB,CAAA,IACvC,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,WAAW,CAAA;AAElC,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,IAAI;AACF,QAAA,MAAM,eAAA,GAAkB,mBAAmB,SAAS,CAAA;AACpD,QAAA,IAAI,eAAA,EAAiB;AACnB,UAAA,MAAM,SAAA,GAAY,2BAA2B,eAAe,CAAA;AAC5D,UAAA,IAAI,SAAA,EAAW;AACb,YAAA,MAAM,WAAA,GAAc,qBAAA,CAAsB,SAAA,CAAU,MAAM,CAAA;AAC1D,YAAA,OAAA,CAAQ,MAAA,GAAS,WAAA;AACjB,YAAA,OAAA,CAAQ,QAAQ,SAAA,CAAU,KAAA;AAC1B,YAAA,OAAA,CAAQ,UAAU,SAAA,CAAU,OAAA;AAC5B,YAAA,OAAA,CAAQ,SAAS,SAAA,CAAU,MAAA;AAC3B,YAAA,OAAA,CAAQ,QAAQ,SAAA,CAAU,KAAA;AAE1B,YAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,OAAA,CAAQ,QAAA,EAAU,WAAW,CAAA;AAAA,UACnD;AAAA,QACF;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,aAAA,IAAiB,OAAA,CAAQ,MAAA,KAAW,UAAA,EAAY;AACvD,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,aAAA,CAAc,QAAA,CAAS,OAAO,CAAA;AACjD,MAAA,IAAI,CAAC,MAAM,OAAA,EAAS;AAClB,QAAA,MAAM,UAAA,CAAW,OAAA,EAAS,KAAA,CAAM,SAAA,EAAW,IAAI,CAAA;AAC/C,QAAA,MAAM,IAAI,mBAAA,CAAoB,KAAA,CAAM,SAAS,CAAA;AAAA,MAC/C;AAAA,IACF;AAEA,IAAA,MAAM,SAAS,YAAA,CAAa;AAAA,MAC1B,OAAA;AAAA,MACA,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAA,EAAY,GAAA;AAAA,MACZ,cAAA;AAAA,MACA,UAAA,EAAY,IAAA;AAAA,MACZ,gBAAA,EAAkB,SAAA;AAAA,MAClB,eAAA,EAAiB;AAAA,KAClB,CAAA;AAED,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,MAAM,CAAA;AAAA,IACnC,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,IAAA,CAAK,4CAA4C,GAAG,CAAA;AAAA,IAC9D;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,OAAO,IAAA;AACT;AAEA,eAAe,UAAA,CACb,OAAA,EACA,SAAA,EACA,IAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,CAAK,WAAA,CAAY,UAAA,CAAW,OAAA,EAAS,SAAA,EAAW;AAAA,MACpD,YAAA,EAAc,KAAK,MAAA,CAAO,YAAA;AAAA,MAC1B,QAAA,EAAU,KAAK,MAAA,CAAO;AAAA,KACvB,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,IAAI,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,gBAAA,EAAkB;AACvC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,gBAAA,CAAiB,SAAS,CAAA;AAAA,IACpD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACF;AAEA,SAAS,yBAAA,CACP,SACA,IAAA,EACS;AACT,EAAA,IAAI,CAAC,IAAA,CAAK,aAAA,IAAiB,OAAA,CAAQ,MAAA,KAAW,YAAY,OAAO,IAAA;AACjE,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,aAAA,CAAc,QAAA,CAAS,OAAO,CAAA;AACjD,EAAA,OAAO,KAAA,CAAM,OAAA;AACf;;;ACxMO,SAAS,gBAAA,CACd,kBACA,MAAA,EACc;AACd,EAAA,cAAA,CAAe,MAAM,CAAA;AAErB,EAAA,MAAM,gBAAgB,MAAA,CAAO,MAAA,GAAS,IAAI,aAAA,CAAc,MAAA,CAAO,MAAM,CAAA,GAAI,IAAA;AACzE,EAAA,MAAM,WAAA,GAAc,IAAI,WAAA,CAAY,MAAA,CAAO,KAAA,IAAS,EAAE,OAAA,EAAS,IAAA,EAAM,OAAA,EAAS,IAAI,aAAA,EAAc,EAAG,CAAA;AAEnG,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAoB;AAC3C,EAAA,MAAM,IAAA,GAAwB,EAAE,aAAA,EAAe,WAAA,EAAa,QAAQ,UAAA,EAAW;AAE/E,EAAA,MAAM,aAAA,GAA8B,OAClC,KAAA,EACA,IAAA,KACsB;AACtB,IAAA,MAAM,GAAA,GAAM,OAAO,KAAA,KAAU,QAAA,GAAW,KAAA,GAAQ,iBAAiB,GAAA,GAAM,KAAA,CAAM,QAAA,EAAS,GAAI,KAAA,CAAM,GAAA;AAChG,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAG3B,IAAA,MAAM,GAAA,GAAM,aAAA,CAAc,GAAA,EAAK,IAAA,EAAM,IAAI,CAAA;AACzC,IAAA,IAAI,CAAC,IAAI,OAAA,IAAW,GAAA,CAAI,cAAc,CAAC,GAAA,CAAI,WAAW,OAAA,EAAS;AAC7D,MAAA,MAAM,SAAA,GAAY,IAAI,UAAA,CAAW,SAAA;AAGjC,MAAA,IAAI;AACF,QAAA,MAAM,WAAA,CAAY,UAAA,CAAW,GAAA,CAAI,OAAA,EAAS,SAAA,EAAW;AAAA,UACnD,cAAc,MAAA,CAAO,YAAA;AAAA,UACrB,UAAU,MAAA,CAAO;AAAA,SAClB,CAAA;AAAA,MACH,CAAA,CAAA,MAAQ;AAAA,MAER;AAEA,MAAA,IAAI,MAAA,CAAO,OAAO,gBAAA,EAAkB;AAClC,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,CAAO,KAAA,CAAM,gBAAA,CAAiB,SAAS,CAAA;AAAA,QAC/C,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AAEA,MAAA,MAAM,IAAI,oBAAoB,SAAS,CAAA;AAAA,IACzC;AAGA,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,MAAM,gBAAA,CAAiB,KAAA,EAAO,IAAI,CAAA;AAAA,IAC/C,SAAS,GAAA,EAAK;AAEZ,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS;AAAA,UACb,QAAA,EAAU,IAAI,OAAA,CAAQ,OAAA;AAAA,UACtB,IAAA,EAAM,IAAI,OAAA,CAAQ,IAAA;AAAA,UAClB,aAAA,EAAe,OAAO,YAAA,IAAgB,IAAA;AAAA,UACtC,MAAA,EAAQ,UAAA;AAAA,UACR,UAAA,EAAY,GAAA;AAAA,UACZ,KAAA,EAAO,EAAA;AAAA,UACP,OAAA,EAAS,EAAA;AAAA,UACT,MAAA,EAAQ,EAAA;AAAA,UACR,OAAA,EAAS,IAAA;AAAA,UACT,aAAA,EAAe,EAAA;AAAA,UACf,aAAA,EAAe,EAAA;AAAA,UACf,WAAA,EAAa,IAAA;AAAA,UACb,QAAA,EAAU,GAAA;AAAA,UACV,MAAA,EAAQ,IAAI,OAAA,CAAQ,MAAA;AAAA,UACpB,WAAA,EAAa,CAAA;AAAA,UACb,gBAAA,EAAkB,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,UAC/B,SAAA,EAAW,IAAA;AAAA,UACX,iBAAA,EAAmB,SAAA;AAAA,UACnB,gBAAA,EAAkB,IAAA;AAAA,UAClB,OAAA,EAAS,IAAA;AAAA,UACT,UAAA,EAAY,IAAA;AAAA,UACZ,QAAA,EAAU,EAAE,KAAA,EAAO,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAA,EAAE;AAAA,UACpE,UAAA,EAAY,IAAA;AAAA,UACZ,IAAA,EAAM,CAAC,OAAA,EAAS,iBAAiB;AAAA,SACnC;AACA,QAAA,MAAM,WAAA,CAAY,IAAI,MAAM,CAAA;AAAA,MAC9B,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AAGA,IAAA,MAAM,aAAA,CAAc,QAAA,EAAU,GAAA,CAAI,OAAA,EAAS,WAAW,IAAI,CAAA;AAG1D,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AAEA,EAAA,OAAO,aAAA;AACT;AC9GO,IAAM,cAAN,MAA4C;AAAA,EAChC,QAAA;AAAA,EACT,SAAwB,EAAC;AAAA,EAChB,cAAA;AAAA,EACT,UAAA,GAAoC,IAAA;AAAA,EAE5C,WAAA,CAAY,QAAA,GAAW,oBAAA,EAAsB,cAAA,GAAiB,GAAA,EAAK;AACjE,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,IAAA,IAAA,CAAK,cAAA,GAAiB,cAAA;AACtB,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,IAAA,CAAK,cAAA,EAAe;AAAA,EACtB;AAAA,EAEA,MAAM,MAAM,MAAA,EAAoC;AAC9C,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,MAAM,CAAA;AACvB,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,IAAU,IAAA,CAAK,cAAA,EAAgB;AAC7C,MAAA,MAAM,KAAK,KAAA,EAAM;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,KAAA,EAA2C;AACrD,IAAA,MAAM,KAAK,KAAA,EAAM;AACjB,IAAA,MAAM,GAAA,GAAM,KAAK,OAAA,EAAQ;AACzB,IAAA,IAAI,OAAA,GAAU,IAAI,MAAA,CAAO,CAAC,MAAM,YAAA,CAAa,CAAA,EAAG,KAAK,CAAC,CAAA;AACtD,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,IAAU,CAAA;AAC/B,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,IAAS,OAAA,CAAQ,MAAA;AACrC,IAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,MAAA,GAAS,KAAK,CAAA;AAAA,EAC7C;AAAA,EAEA,MAAM,UAAU,KAAA,EAAmD;AACjE,IAAA,MAAM,KAAK,KAAA,EAAM;AACjB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,EAAQ,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,YAAA,CAAa,CAAA,EAAG,KAAK,CAAC,CAAA;AACnE,IAAA,OAAO,YAAA,CAAa,SAAS,KAAK,CAAA;AAAA,EACpC;AAAA,EAEA,MAAM,MAAM,KAAA,EAA6C;AACvD,IAAA,MAAM,KAAK,KAAA,EAAM;AACjB,IAAA,OAAO,IAAA,CAAK,OAAA,EAAQ,CAAE,MAAA,CAAO,CAAC,MAAM,YAAA,CAAa,CAAA,EAAG,KAAK,CAAC,CAAA,CAAE,MAAA;AAAA,EAC9D;AAAA,EAEA,MAAM,QAAQ,EAAA,EAAyC;AACrD,IAAA,MAAM,KAAK,KAAA,EAAM;AACjB,IAAA,OAAO,IAAA,CAAK,SAAQ,CAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,IAAK,IAAA;AAAA,EACpD;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AAC9B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AACrE,IAAAQ,iBAAA,CAAe,IAAA,CAAK,QAAA,EAAU,KAAA,EAAO,OAAO,CAAA;AAC5C,IAAA,IAAA,CAAK,SAAS,EAAC;AAAA,EACjB;AAAA;AAAA,EAGA,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,aAAA,CAAc,KAAK,UAAU,CAAA;AAC7B,MAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,OAAA,GAAyB;AAC/B,IAAA,IAAI,CAACC,aAAA,CAAW,IAAA,CAAK,QAAQ,CAAA,SAAU,EAAC;AACxC,IAAA,MAAM,OAAA,GAAUC,eAAA,CAAa,IAAA,CAAK,QAAA,EAAU,OAAO,CAAA;AACnD,IAAA,OAAO,QACJ,KAAA,CAAM,IAAI,EACV,MAAA,CAAO,CAAC,SAAS,IAAA,CAAK,IAAA,GAAO,MAAA,GAAS,CAAC,EACvC,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAgB,CAAA;AAAA,EAClD;AAAA,EAEQ,SAAA,GAAkB;AACxB,IAAA,MAAM,GAAA,GAAMC,YAAA,CAAQ,IAAA,CAAK,QAAQ,CAAA;AACjC,IAAA,IAAI,CAACF,aAAA,CAAW,GAAG,CAAA,EAAG;AACpB,MAAAG,YAAA,CAAU,GAAA,EAAK,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAAA,IACpC;AAAA,EACF;AAAA,EAEQ,cAAA,GAAuB;AAC7B,IAAA,IAAA,CAAK,UAAA,GAAa,YAAY,MAAM;AAClC,MAAA,KAAK,KAAK,KAAA,EAAM;AAAA,IAClB,GAAG,GAAK,CAAA;AACR,IAAA,IAAA,CAAK,WAAW,KAAA,EAAM;AAAA,EACxB;AACF;;;AC3EO,IAAM,aAAN,MAA2C;AAAA,EAC/B,MAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACT,SAAwB,EAAC;AAAA,EAChB,QAAA;AAAA,EACT,UAAA,GAAoC,IAAA;AAAA,EACpC,WAAA,GAAc,KAAA;AAAA,EAEtB,YAAY,MAAA,EAA0B;AACpC,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,OAAA,GAAU,OAAO,OAAA,IAAW,4BAAA;AACjC,IAAA,IAAA,CAAK,SAAA,GAAY,OAAO,SAAA,IAAa,EAAA;AACrC,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,aAAA,EAAc;AAClC,IAAA,IAAA,CAAK,cAAA,CAAe,MAAA,CAAO,eAAA,IAAmB,GAAM,CAAA;AAAA,EACtD;AAAA,EAEA,MAAM,MAAM,MAAA,EAAoC;AAC9C,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,MAAM,CAAA;AAEvB,IAAA,MAAM,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,MAAM,CAAA;AAChC,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,IAAU,IAAA,CAAK,SAAA,EAAW;AACxC,MAAA,MAAM,KAAK,KAAA,EAAM;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,KAAA,EAA2C;AACrD,IAAA,IAAI,KAAK,WAAA,EAAa,OAAO,IAAA,CAAK,QAAA,CAAS,MAAM,KAAK,CAAA;AACtD,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,UAAA,CAA0B,MAAA,EAAQ,gBAAgB,KAAK,CAAA;AAAA,IAC3E,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,MAAA,OAAO,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,KAAK,CAAA;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,KAAA,EAAmD;AACjE,IAAA,IAAI,KAAK,WAAA,EAAa,OAAO,IAAA,CAAK,QAAA,CAAS,UAAU,KAAK,CAAA;AAC1D,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,UAAA,CAAyB,MAAA,EAAQ,oBAAoB,KAAK,CAAA;AAAA,IAC9E,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,MAAA,OAAO,IAAA,CAAK,QAAA,CAAS,SAAA,CAAU,KAAK,CAAA;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,KAAA,EAA6C;AACvD,IAAA,IAAI,KAAK,WAAA,EAAa,OAAO,IAAA,CAAK,QAAA,CAAS,MAAM,KAAK,CAAA;AACtD,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,MAAM,IAAA,CAAK,UAAA,CAA8B,MAAA,EAAQ,gBAAgB,KAAK,CAAA;AACrF,MAAA,OAAO,MAAA,CAAO,KAAA;AAAA,IAChB,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,MAAA,OAAO,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,KAAK,CAAA;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,EAAA,EAAyC;AACrD,IAAA,IAAI,KAAK,WAAA,EAAa,OAAO,IAAA,CAAK,QAAA,CAAS,QAAQ,EAAE,CAAA;AACrD,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,UAAA,CAA+B,KAAA,EAAO,CAAA,OAAA,EAAU,EAAE,CAAA,CAAE,CAAA;AAAA,IACxE,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,MAAA,OAAO,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,EAAE,CAAA;AAAA,IACjC;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AAC9B,IAAA,MAAM,QAAQ,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,KAAK,SAAS,CAAA;AAClD,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,UAAA,CAAW,MAAA,EAAQ,gBAAgB,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,IAClE,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,CAAA,+DAAA,EAAkE,MAAM,MAAM,CAAA,0BAAA;AAAA,OAChF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,aAAA,CAAc,KAAK,UAAU,CAAA;AAC7B,MAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAc,UAAA,CAAc,MAAA,EAAgB,IAAA,EAAc,IAAA,EAA4B;AACpF,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,OAAO,GAAG,IAAI,CAAA,CAAA;AAClC,IAAA,MAAM,IAAA,GAAoB;AAAA,MACxB,MAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA;AAAA;AACtC,KACF;AACA,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAAA,IACjC;AAEA,IAAA,IAAI,SAAA;AACJ,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,GAAU,CAAA,EAAG,OAAA,EAAA,EAAW;AAC5C,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK,IAAI,CAAA;AACtC,QAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,UAAA,MAAM,IAAI,MAAM,CAAA,aAAA,EAAgB,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,QAC3E;AACA,QAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,MAC9B,SAAS,GAAA,EAAK;AACZ,QAAA,SAAA,GAAY,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAC9D,QAAA,IAAI,UAAU,CAAA,EAAG;AACf,UAAA,MAAM,MAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,IAAI,GAAI,CAAA;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AACA,IAAA,MAAM,SAAA;AAAA,EACR;AAAA,EAEQ,eAAe,UAAA,EAA0B;AAC/C,IAAA,IAAA,CAAK,UAAA,GAAa,YAAY,MAAM;AAClC,MAAA,KAAK,KAAK,KAAA,EAAM;AAAA,IAClB,GAAG,UAAU,CAAA;AACb,IAAA,IAAA,CAAK,WAAW,KAAA,EAAM;AAAA,EACxB;AACF;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD","file":"index.cjs","sourcesContent":["import { parseUSDC, formatUSDC, calculateAverage } from \"../utils/money\";\n\n/** Detects abnormal payment spikes using a rolling window of recent amounts */\nexport class SpikeDetector {\n private readonly windowSize: number;\n private readonly threshold: number;\n private readonly window: string[] = [];\n\n constructor(threshold = 3.0, windowSize = 20) {\n this.threshold = threshold;\n this.windowSize = windowSize;\n }\n\n /** Record a payment amount into the rolling window */\n record(amount: string): void {\n this.window.push(amount);\n if (this.window.length > this.windowSize) {\n this.window.shift();\n }\n }\n\n /**\n * Check if a proposed amount is a spike relative to the rolling average.\n * Returns null if no spike, or a description string if spike detected.\n * Needs at least 3 data points before spike detection activates.\n */\n check(amount: string): string | null {\n if (this.window.length < 3) return null;\n\n const avg = calculateAverage(this.window);\n const avgRaw = parseUSDC(avg);\n if (avgRaw === 0n) return null;\n\n const amountRaw = parseUSDC(amount);\n const ratio = Number(amountRaw) / Number(avgRaw);\n\n if (ratio > this.threshold) {\n return (\n `Payment $${amount} is ${ratio.toFixed(1)}x the rolling average ` +\n `$${formatUSDC(avgRaw)} (threshold: ${this.threshold}x)`\n );\n }\n return null;\n }\n\n /** Get the current rolling average */\n getAverage(): string {\n return calculateAverage(this.window);\n }\n\n /** Get the current window contents */\n getWindow(): string[] {\n return [...this.window];\n }\n\n /** Restore state from serialized data */\n loadWindow(amounts: string[]): void {\n this.window.length = 0;\n for (const a of amounts.slice(-this.windowSize)) {\n this.window.push(a);\n }\n }\n}\n","import type { BudgetPolicy } from \"../types/budget\";\n\n/** Tight limits for low-risk or testing scenarios */\nexport function conservativePolicy(): BudgetPolicy {\n return {\n maxPerCall: \"0.10\",\n maxPerHour: \"5.00\",\n maxPerDay: \"50.00\",\n spikeThreshold: 3.0,\n };\n}\n\n/** Balanced limits for typical production agents */\nexport function standardPolicy(): BudgetPolicy {\n return {\n maxPerCall: \"1.00\",\n maxPerHour: \"25.00\",\n maxPerDay: \"200.00\",\n spikeThreshold: 3.0,\n };\n}\n\n/** Higher limits for trusted, high-throughput agents */\nexport function liberalPolicy(): BudgetPolicy {\n return {\n maxPerCall: \"10.00\",\n maxPerHour: \"100.00\",\n maxPerDay: \"1000.00\",\n spikeThreshold: 5.0,\n };\n}\n\n/** No spending limits — audit logging only */\nexport function unlimitedPolicy(): BudgetPolicy {\n return {};\n}\n\n/** Build a custom policy by overriding defaults */\nexport function customPolicy(overrides: Partial<BudgetPolicy>): BudgetPolicy {\n return { ...standardPolicy(), ...overrides };\n}\n","import type { BudgetPolicy, BudgetState, BudgetViolation, BudgetEvaluation } from \"../types/budget\";\nimport type { PaymentContext } from \"../types/index\";\nimport { addUSDC, compareUSDC } from \"../utils/money\";\nimport { getHourStart, getDayStart } from \"../utils/time\";\nimport { SpikeDetector } from \"./spike-detector\";\n\n/** Enforces budget policies by evaluating proposed payments against spending state */\nexport class BudgetManager {\n private state: BudgetState;\n private readonly policy: BudgetPolicy;\n private readonly spikeDetector: SpikeDetector;\n\n constructor(policy: BudgetPolicy) {\n this.policy = policy;\n this.spikeDetector = new SpikeDetector(\n policy.spikeThreshold ?? 3.0,\n );\n const now = Date.now();\n this.state = {\n totalSpent: \"0.000000\",\n hourlySpent: \"0.000000\",\n dailySpent: \"0.000000\",\n callCount: 0,\n lastReset: { hourly: getHourStart(now), daily: getDayStart(now) },\n rollingAverage: \"0.000000\",\n rollingWindow: [],\n };\n }\n\n /**\n * Evaluate a proposed payment against the budget policy.\n * Called BEFORE every payment. Returns allow/deny with reason.\n */\n evaluate(context: PaymentContext): BudgetEvaluation {\n this.maybeResetWindows();\n const warnings: string[] = [];\n\n // 1. Blocked endpoints (fast reject)\n if (this.policy.blockedEndpoints?.length) {\n for (const pattern of this.policy.blockedEndpoints) {\n if (endpointMatches(context.endpoint, pattern)) {\n return {\n allowed: false,\n violation: this.violation(\"blocked_endpoint\", \"0.000000\", \"0.000000\", context),\n };\n }\n }\n }\n\n // 2. Allowed endpoints whitelist\n if (this.policy.allowedEndpoints?.length) {\n const matched = this.policy.allowedEndpoints.some((p) =>\n endpointMatches(context.endpoint, p),\n );\n if (!matched) {\n return {\n allowed: false,\n violation: this.violation(\"blocked_endpoint\", \"0.000000\", \"0.000000\", context),\n };\n }\n }\n\n // 3. Per-call limit\n if (this.policy.maxPerCall) {\n if (compareUSDC(context.amount, this.policy.maxPerCall) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"per_call\", this.policy.maxPerCall, \"0.000000\", context),\n };\n }\n }\n\n // 4. Spike detection\n const spikeMsg = this.spikeDetector.check(context.amount);\n if (spikeMsg) {\n if (this.policy.spikeThreshold !== undefined) {\n return {\n allowed: false,\n violation: this.violation(\n \"spike\",\n this.spikeDetector.getAverage(),\n this.state.hourlySpent,\n context,\n ),\n };\n }\n warnings.push(spikeMsg);\n }\n\n // 5. Hourly rolling window\n if (this.policy.maxPerHour) {\n const projectedHourly = addUSDC(this.state.hourlySpent, context.amount);\n if (compareUSDC(projectedHourly, this.policy.maxPerHour) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"hourly\", this.policy.maxPerHour, this.state.hourlySpent, context),\n };\n }\n }\n\n // 6. Daily rolling window\n if (this.policy.maxPerDay) {\n const projectedDaily = addUSDC(this.state.dailySpent, context.amount);\n if (compareUSDC(projectedDaily, this.policy.maxPerDay) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"daily\", this.policy.maxPerDay, this.state.dailySpent, context),\n };\n }\n }\n\n // 7. Total lifetime cap\n if (this.policy.maxTotal) {\n const projectedTotal = addUSDC(this.state.totalSpent, context.amount);\n if (compareUSDC(projectedTotal, this.policy.maxTotal) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"total\", this.policy.maxTotal, this.state.totalSpent, context),\n };\n }\n }\n\n // 8. Approval threshold\n if (this.policy.requireApproval) {\n if (compareUSDC(context.amount, this.policy.requireApproval.above) > 0) {\n return {\n allowed: false,\n violation: this.violation(\n \"approval_required\",\n this.policy.requireApproval.above,\n this.state.totalSpent,\n context,\n ),\n };\n }\n }\n\n return { allowed: true, warnings };\n }\n\n /** Record a completed payment. Called AFTER payment succeeds. */\n record(amount: string, _endpoint: string): void {\n this.maybeResetWindows();\n this.state.totalSpent = addUSDC(this.state.totalSpent, amount);\n this.state.hourlySpent = addUSDC(this.state.hourlySpent, amount);\n this.state.dailySpent = addUSDC(this.state.dailySpent, amount);\n this.state.callCount++;\n this.spikeDetector.record(amount);\n this.state.rollingAverage = this.spikeDetector.getAverage();\n this.state.rollingWindow = this.spikeDetector.getWindow();\n }\n\n /** Get current budget state (for dashboard/debugging) */\n getState(): BudgetState {\n this.maybeResetWindows();\n return { ...this.state, rollingWindow: [...this.state.rollingWindow] };\n }\n\n /** Reset spending counters for a given scope */\n reset(scope: \"hourly\" | \"daily\" | \"total\"): void {\n const now = Date.now();\n switch (scope) {\n case \"hourly\":\n this.state.hourlySpent = \"0.000000\";\n this.state.lastReset.hourly = getHourStart(now);\n break;\n case \"daily\":\n this.state.dailySpent = \"0.000000\";\n this.state.lastReset.daily = getDayStart(now);\n break;\n case \"total\":\n this.state.totalSpent = \"0.000000\";\n this.state.hourlySpent = \"0.000000\";\n this.state.dailySpent = \"0.000000\";\n this.state.callCount = 0;\n break;\n }\n }\n\n /** Serialize state for persistence */\n serialize(): string {\n return JSON.stringify(this.state);\n }\n\n /** Restore a BudgetManager from serialized state */\n static deserialize(data: string, policy: BudgetPolicy): BudgetManager {\n const mgr = new BudgetManager(policy);\n const parsed = JSON.parse(data) as BudgetState;\n mgr.state = parsed;\n mgr.spikeDetector.loadWindow(parsed.rollingWindow);\n return mgr;\n }\n\n /** Auto-reset hourly/daily windows when the time window has rolled over */\n private maybeResetWindows(): void {\n const now = Date.now();\n const hourStart = getHourStart(now);\n const dayStart = getDayStart(now);\n\n if (hourStart > this.state.lastReset.hourly) {\n this.state.hourlySpent = \"0.000000\";\n this.state.lastReset.hourly = hourStart;\n }\n if (dayStart > this.state.lastReset.daily) {\n this.state.dailySpent = \"0.000000\";\n this.state.lastReset.daily = dayStart;\n }\n }\n\n private violation(\n type: BudgetViolation[\"type\"],\n limit: string,\n current: string,\n context: PaymentContext,\n ): BudgetViolation {\n return {\n type,\n limit,\n current,\n attempted: context.amount,\n agentId: context.agentId,\n endpoint: context.endpoint,\n timestamp: Date.now(),\n };\n }\n}\n\n/** Simple glob-like endpoint matching (supports * wildcards) */\nfunction endpointMatches(url: string, pattern: string): boolean {\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\*/g, \".*\").replace(/\\?/g, \".\") + \"$\",\n );\n return regex.test(url);\n}\n\nexport { SpikeDetector } from \"./spike-detector\";\nexport {\n conservativePolicy,\n standardPolicy,\n liberalPolicy,\n unlimitedPolicy,\n customPolicy,\n} from \"./policies\";\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { parseUSDC, formatUSDC, formatUSDCHuman, compareUSDC } from \"../../utils/money\";\n\n/** In-memory audit storage with configurable capacity and FIFO eviction */\nexport class MemoryStorage implements StorageBackend {\n private readonly records = new Map<string, AuditRecord>();\n private readonly insertOrder: string[] = [];\n private readonly maxRecords: number;\n\n constructor(maxRecords = 10_000) {\n this.maxRecords = maxRecords;\n }\n\n async write(record: AuditRecord): Promise<void> {\n if (this.records.size >= this.maxRecords) {\n const oldest = this.insertOrder.shift();\n if (oldest) this.records.delete(oldest);\n }\n this.records.set(record.id, record);\n this.insertOrder.push(record.id);\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n let results = this.filter(query);\n results = this.sort(results, query.orderBy, query.order);\n const offset = query.offset ?? 0;\n const limit = query.limit ?? results.length;\n return results.slice(offset, offset + limit);\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n const records = this.filter(query);\n return buildSummary(records, query);\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n return this.filter(query).length;\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n return this.records.get(id) ?? null;\n }\n\n private filter(query: Partial<AuditQuery>): AuditRecord[] {\n return [...this.records.values()].filter((r) => matchesQuery(r, query));\n }\n\n private sort(\n records: AuditRecord[],\n orderBy?: AuditQuery[\"orderBy\"],\n order?: AuditQuery[\"order\"],\n ): AuditRecord[] {\n if (!orderBy) return records;\n const dir = order === \"desc\" ? -1 : 1;\n return records.sort((a, b) => {\n switch (orderBy) {\n case \"created_at\":\n return (a.created_at - b.created_at) * dir;\n case \"amount\":\n return compareUSDC(a.amount, b.amount) * dir;\n case \"endpoint\":\n return a.endpoint.localeCompare(b.endpoint) * dir;\n default:\n return 0;\n }\n });\n }\n}\n\n/** Shared filter logic reusable across storage backends */\nexport function matchesQuery(\n record: AuditRecord,\n query: Partial<AuditQuery>,\n): boolean {\n if (query.agentId && record.agent_id !== query.agentId) return false;\n if (query.team && record.team !== query.team) return false;\n if (query.endpoint && !record.endpoint.includes(query.endpoint)) return false;\n if (query.minAmount && compareUSDC(record.amount, query.minAmount) < 0) return false;\n if (query.maxAmount && compareUSDC(record.amount, query.maxAmount) > 0) return false;\n if (query.startTime && record.created_at < query.startTime) return false;\n if (query.endTime && record.created_at > query.endTime) return false;\n if (query.status?.length && !query.status.includes(record.policy_evaluation)) return false;\n if (query.tags?.length && !query.tags.some((t) => record.tags.includes(t))) return false;\n return true;\n}\n\n/** Build an AuditSummary from a set of records */\nexport function buildSummary(\n records: AuditRecord[],\n query: Partial<AuditQuery>,\n): AuditSummary {\n let totalRaw = 0n;\n let maxRaw = 0n;\n const agents = new Set<string>();\n const endpoints = new Set<string>();\n const byAgent: Record<string, { spend: string; count: number }> = {};\n const byEndpoint: Record<string, { spend: string; count: number }> = {};\n const byTeam: Record<string, { spend: string; count: number }> = {};\n let violations = 0;\n let minTs = Infinity;\n let maxTs = 0;\n\n for (const r of records) {\n const raw = parseUSDC(r.amount);\n totalRaw += raw;\n if (raw > maxRaw) maxRaw = raw;\n agents.add(r.agent_id);\n endpoints.add(r.endpoint);\n\n if (r.created_at < minTs) minTs = r.created_at;\n if (r.created_at > maxTs) maxTs = r.created_at;\n\n if (r.policy_evaluation === \"blocked\") violations++;\n\n // by_agent\n const agentEntry = byAgent[r.agent_id] ?? { spend: \"0.000000\", count: 0 };\n agentEntry.spend = formatUSDC(parseUSDC(agentEntry.spend) + raw);\n agentEntry.count++;\n byAgent[r.agent_id] = agentEntry;\n\n // by_endpoint\n const epEntry = byEndpoint[r.endpoint] ?? { spend: \"0.000000\", count: 0 };\n epEntry.spend = formatUSDC(parseUSDC(epEntry.spend) + raw);\n epEntry.count++;\n byEndpoint[r.endpoint] = epEntry;\n\n // by_team\n const teamKey = r.team ?? \"(none)\";\n const teamEntry = byTeam[teamKey] ?? { spend: \"0.000000\", count: 0 };\n teamEntry.spend = formatUSDC(parseUSDC(teamEntry.spend) + raw);\n teamEntry.count++;\n byTeam[teamKey] = teamEntry;\n }\n\n const count = records.length;\n return {\n total_spend: formatUSDCHuman(totalRaw),\n total_transactions: count,\n unique_endpoints: endpoints.size,\n unique_agents: agents.size,\n avg_payment: count > 0 ? formatUSDCHuman(totalRaw / BigInt(count)) : \"0.00\",\n max_payment: formatUSDCHuman(maxRaw),\n by_agent: byAgent,\n by_endpoint: byEndpoint,\n by_team: byTeam,\n violations,\n period: {\n start: query.startTime ?? (minTs === Infinity ? 0 : minTs),\n end: query.endTime ?? (maxTs === 0 ? 0 : maxTs),\n },\n };\n}\n","import { createHash, randomUUID } from \"node:crypto\";\n\n/**\n * Generate a deterministic record ID from payment attributes.\n * SHA-256 of concatenated inputs, truncated to 16 hex chars.\n */\nexport function generateRecordId(\n agentId: string,\n endpoint: string,\n timestamp: number,\n amount: string,\n): string {\n const input = `${agentId}|${endpoint}|${timestamp}|${amount}`;\n const hash = createHash(\"sha256\").update(input).digest(\"hex\");\n return hash.slice(0, 16);\n}\n\n/** Generate a random session ID (UUID v4) */\nexport function generateSessionId(): string {\n return randomUUID();\n}\n","import type { AuditRecord } from \"../types/audit\";\nimport type { PaymentContext, EnrichmentConfig } from \"../types/index\";\nimport type { SettleResponse } from \"../types/x402-stubs\";\nimport type { SentinelConfig } from \"../types/config\";\nimport { generateRecordId } from \"../utils/id\";\n\ninterface EnrichmentInput {\n context: PaymentContext;\n config: SentinelConfig;\n statusCode: number;\n responseTimeMs: number;\n settlement: SettleResponse | null;\n policyEvaluation: \"allowed\" | \"flagged\" | \"blocked\";\n budgetRemaining: string | null;\n}\n\n/** Build a complete AuditRecord from payment context and settlement data */\nexport function enrichRecord(input: EnrichmentInput): AuditRecord {\n const { context, config, statusCode, responseTimeMs, settlement, policyEvaluation, budgetRemaining } = input;\n const now = Date.now();\n const id = generateRecordId(context.agentId, context.endpoint, now, context.amount);\n\n const tags = computeTags(context, config.audit?.enrichment);\n\n return {\n id,\n agent_id: context.agentId,\n team: context.team,\n human_sponsor: config.humanSponsor ?? null,\n\n amount: context.amount,\n amount_raw: context.amountRaw,\n asset: context.asset,\n network: context.network,\n scheme: context.scheme,\n\n tx_hash: settlement?.transaction ?? null,\n payer_address: settlement?.payer ?? \"\",\n payee_address: context.payTo,\n facilitator: null,\n\n endpoint: context.endpoint,\n method: context.method,\n status_code: statusCode,\n response_time_ms: responseTimeMs,\n\n policy_id: null,\n policy_evaluation: policyEvaluation,\n budget_remaining: budgetRemaining,\n\n task_id: context.metadata[\"task_id\"] ?? null,\n session_id: context.metadata[\"session_id\"] ?? null,\n metadata: { ...context.metadata, ...config.metadata },\n\n created_at: now,\n settled_at: settlement?.success ? now : null,\n\n tags,\n };\n}\n\n/** Build an AuditRecord for a blocked payment attempt */\nexport function enrichBlockedRecord(\n context: PaymentContext,\n config: SentinelConfig,\n policyEvaluation: \"blocked\",\n): AuditRecord {\n return enrichRecord({\n context,\n config,\n statusCode: 0,\n responseTimeMs: 0,\n settlement: null,\n policyEvaluation,\n budgetRemaining: null,\n });\n}\n\nfunction computeTags(context: PaymentContext, enrichment?: EnrichmentConfig): string[] {\n const tags: string[] = [];\n\n if (enrichment?.staticTags) {\n tags.push(...enrichment.staticTags);\n }\n\n if (enrichment?.tagRules) {\n for (const rule of enrichment.tagRules) {\n const regex = new RegExp(rule.pattern);\n if (regex.test(context.endpoint)) {\n tags.push(...rule.tags);\n }\n }\n }\n\n return tags;\n}\n","import type { AuditRecord, AuditSummary } from \"../types/audit\";\n\nconst CSV_HEADERS: (keyof AuditRecord)[] = [\n \"id\", \"agent_id\", \"team\", \"human_sponsor\",\n \"amount\", \"amount_raw\", \"asset\", \"network\", \"scheme\",\n \"tx_hash\", \"payer_address\", \"payee_address\", \"facilitator\",\n \"endpoint\", \"method\", \"status_code\", \"response_time_ms\",\n \"policy_id\", \"policy_evaluation\", \"budget_remaining\",\n \"task_id\", \"session_id\",\n \"created_at\", \"settled_at\",\n];\n\n/** Convert records to a properly escaped CSV string */\nexport function toCSV(records: AuditRecord[]): string {\n const lines: string[] = [CSV_HEADERS.join(\",\")];\n\n for (const record of records) {\n const values = CSV_HEADERS.map((key) => {\n const val = record[key];\n if (val === null || val === undefined) return \"\";\n const str = String(val);\n if (str.includes(\",\") || str.includes('\"') || str.includes(\"\\n\")) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n });\n lines.push(values.join(\",\"));\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/** Convert records to a JSON string */\nexport function toJSON(records: AuditRecord[], pretty = false): string {\n return JSON.stringify(records, null, pretty ? 2 : undefined);\n}\n\n/** Generate a human-readable text summary report */\nexport function toSummaryReport(summary: AuditSummary): string {\n const lines: string[] = [\n \"═══════════════════════════════════════════\",\n \" VALEO SENTINEL — AUDIT SUMMARY REPORT\",\n \"═══════════════════════════════════════════\",\n \"\",\n ` Period: ${new Date(summary.period.start).toISOString()} — ${new Date(summary.period.end).toISOString()}`,\n \"\",\n ` Total Spend: $${summary.total_spend}`,\n ` Total Transactions: ${summary.total_transactions}`,\n ` Unique Agents: ${summary.unique_agents}`,\n ` Unique Endpoints: ${summary.unique_endpoints}`,\n ` Avg Payment: $${summary.avg_payment}`,\n ` Max Payment: $${summary.max_payment}`,\n ` Violations: ${summary.violations}`,\n \"\",\n ];\n\n if (Object.keys(summary.by_agent).length > 0) {\n lines.push(\" ── Spend by Agent ──\");\n for (const [agent, data] of Object.entries(summary.by_agent)) {\n lines.push(` ${agent}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n if (Object.keys(summary.by_team).length > 0) {\n lines.push(\" ── Spend by Team ──\");\n for (const [team, data] of Object.entries(summary.by_team)) {\n lines.push(` ${team}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n if (Object.keys(summary.by_endpoint).length > 0) {\n lines.push(\" ── Spend by Endpoint ──\");\n for (const [ep, data] of Object.entries(summary.by_endpoint)) {\n lines.push(` ${ep}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"═══════════════════════════════════════════\");\n return lines.join(\"\\n\");\n}\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../types/audit\";\nimport type { AuditConfig } from \"../types/config\";\nimport type { PaymentContext } from \"../types/index\";\nimport type { BudgetViolation } from \"../types/budget\";\nimport type { StorageBackend } from \"./storage/interface\";\nimport { MemoryStorage } from \"./storage/memory\";\nimport { enrichBlockedRecord } from \"./enrichment\";\nimport { generateRecordId } from \"../utils/id\";\nimport { toCSV, toJSON } from \"./export\";\n\n/** Central audit logger — writes records to a pluggable storage backend */\nexport class AuditLogger {\n private readonly storage: StorageBackend;\n private readonly enabled: boolean;\n private readonly redactFields: string[];\n\n constructor(config?: AuditConfig) {\n this.enabled = config?.enabled !== false;\n this.storage = config?.storage ?? new MemoryStorage();\n this.redactFields = config?.redactFields ?? [];\n }\n\n /** Log a completed payment record */\n async log(record: Omit<AuditRecord, \"id\" | \"created_at\">): Promise<AuditRecord> {\n const now = Date.now();\n const full: AuditRecord = {\n ...record,\n id: generateRecordId(record.agent_id, record.endpoint, now, record.amount),\n created_at: now,\n };\n\n const redacted = this.redact(full);\n\n if (this.enabled) {\n try {\n await this.storage.write(redacted);\n } catch (err) {\n console.warn(\"[sentinel] Audit write failed (non-fatal):\", err);\n }\n }\n\n return redacted;\n }\n\n /** Log a blocked payment attempt */\n async logBlocked(\n context: PaymentContext,\n violation: BudgetViolation,\n config: { humanSponsor?: string; metadata?: Record<string, string> },\n ): Promise<AuditRecord> {\n const record = enrichBlockedRecord(context, {\n agentId: context.agentId,\n ...config,\n }, \"blocked\");\n record.metadata[\"violation_type\"] = violation.type;\n record.metadata[\"violation_limit\"] = violation.limit;\n\n if (this.enabled) {\n try {\n await this.storage.write(this.redact(record));\n } catch (err) {\n console.warn(\"[sentinel] Audit write failed (non-fatal):\", err);\n }\n }\n\n return record;\n }\n\n /** Query audit records */\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n return this.storage.query(query);\n }\n\n /** Get summary statistics */\n async summarize(query?: Partial<AuditQuery>): Promise<AuditSummary> {\n return this.storage.summarize(query ?? {});\n }\n\n /** Export records as CSV */\n async exportCSV(query?: AuditQuery): Promise<string> {\n const records = await this.storage.query(query ?? {});\n return toCSV(records);\n }\n\n /** Export records as JSON */\n async exportJSON(query?: AuditQuery): Promise<string> {\n const records = await this.storage.query(query ?? {});\n return toJSON(records, true);\n }\n\n /** Flush pending writes to storage */\n async flush(): Promise<void> {\n if (\"flush\" in this.storage && typeof this.storage.flush === \"function\") {\n await (this.storage as StorageBackend & { flush(): Promise<void> }).flush();\n }\n }\n\n /** Get the underlying storage backend (for dashboard integration) */\n getStorage(): StorageBackend {\n return this.storage;\n }\n\n private redact(record: AuditRecord): AuditRecord {\n if (this.redactFields.length === 0) return record;\n const copy = { ...record, metadata: { ...record.metadata } };\n for (const field of this.redactFields) {\n if (field in copy.metadata) {\n copy.metadata[field] = \"[REDACTED]\";\n }\n }\n return copy;\n }\n}\n","import type { AuditRecord } from \"./types/audit\";\nimport type { BudgetViolation } from \"./types/budget\";\nimport { parseUSDC } from \"./utils/money\";\n\nexport class SentinelError extends Error {\n readonly code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.name = \"SentinelError\";\n this.code = code;\n }\n}\n\nexport class SentinelBudgetError extends SentinelError {\n readonly violation: BudgetViolation;\n\n constructor(violation: BudgetViolation) {\n super(buildBudgetMessage(violation), \"BUDGET_EXCEEDED\");\n this.name = \"SentinelBudgetError\";\n this.violation = violation;\n }\n}\n\n/** Audit failures are NEVER fatal — they should be caught and logged */\nexport class SentinelAuditError extends SentinelError {\n readonly record?: Partial<AuditRecord>;\n\n constructor(message: string, record?: Partial<AuditRecord>) {\n super(message, \"AUDIT_ERROR\");\n this.name = \"SentinelAuditError\";\n this.record = record;\n }\n}\n\nexport class SentinelConfigError extends SentinelError {\n constructor(message: string) {\n super(message, \"CONFIG_ERROR\");\n this.name = \"SentinelConfigError\";\n }\n}\n\nfunction buildBudgetMessage(v: BudgetViolation): string {\n const attempted = `$${v.attempted}`;\n\n switch (v.type) {\n case \"per_call\":\n return `Budget exceeded: ${attempted} exceeds per-call limit of $${v.limit} on ${v.agentId}`;\n case \"hourly\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} hourly limit on ${v.agentId} (attempted ${attempted})`;\n case \"daily\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} daily limit on ${v.agentId} (attempted ${attempted})`;\n case \"total\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} total limit on ${v.agentId} (attempted ${attempted})`;\n case \"spike\":\n return `Price spike detected: ${attempted} vs rolling average $${v.limit} on ${v.agentId}`;\n case \"blocked_endpoint\":\n return `Blocked endpoint: ${v.endpoint} is not allowed for ${v.agentId}`;\n case \"approval_required\":\n return `Approval required: ${attempted} exceeds approval threshold $${v.limit} on ${v.agentId}`;\n }\n}\n\n/** Validate a SentinelConfig at initialization time */\nexport function validateConfig(config: {\n agentId: string;\n budget?: {\n maxPerCall?: string;\n maxPerHour?: string;\n maxPerDay?: string;\n maxTotal?: string;\n spikeThreshold?: number;\n allowedEndpoints?: string[];\n blockedEndpoints?: string[];\n };\n}): void {\n if (!config.agentId || config.agentId.trim() === \"\") {\n throw new SentinelConfigError(\"agentId is required and must be non-empty\");\n }\n\n const budget = config.budget;\n if (!budget) return;\n\n const amountFields = [\"maxPerCall\", \"maxPerHour\", \"maxPerDay\", \"maxTotal\"] as const;\n for (const field of amountFields) {\n const value = budget[field];\n if (value !== undefined) {\n try {\n parseUSDC(value);\n } catch {\n throw new SentinelConfigError(\n `budget.${field} \"${value}\" is not a valid USDC amount`,\n );\n }\n }\n }\n\n if (budget.spikeThreshold !== undefined && budget.spikeThreshold <= 1.0) {\n throw new SentinelConfigError(\n `budget.spikeThreshold must be > 1.0, got ${budget.spikeThreshold}`,\n );\n }\n\n if (budget.allowedEndpoints?.length && budget.blockedEndpoints?.length) {\n throw new SentinelConfigError(\n \"Cannot set both allowedEndpoints and blockedEndpoints — use one or the other\",\n );\n }\n}\n","import type { PaymentRequired, PaymentRequirements, SettleResponse } from \"../types/x402-stubs\";\nimport { formatUSDC } from \"../utils/money\";\n\n/**\n * Decode the PAYMENT-REQUIRED header from a 402 response.\n * The header value is a Base64-encoded JSON string containing the PaymentRequired object.\n */\nexport function parsePaymentRequired(header: string): PaymentRequired {\n const json = Buffer.from(header, \"base64\").toString(\"utf-8\");\n return JSON.parse(json) as PaymentRequired;\n}\n\n/**\n * Parse a payment header that may be base64-encoded JSON or raw JSON.\n * Handles both `payment-required` and `x-payment` header formats.\n * Returns null if unparseable.\n */\nexport function parsePaymentHeader(header: string): PaymentRequired | null {\n try {\n return JSON.parse(Buffer.from(header, \"base64\").toString(\"utf-8\")) as PaymentRequired;\n } catch {\n try {\n return JSON.parse(header) as PaymentRequired;\n } catch {\n return null;\n }\n }\n}\n\n/**\n * Convert a raw base-unit amount string (e.g. \"1000000\") to a\n * human-readable USDC string (e.g. \"1.000000\").\n * USDC has 6 decimal places.\n */\nexport function normalizeAmountToUSDC(raw: string): string {\n return formatUSDC(BigInt(raw));\n}\n\n/**\n * Decode the PAYMENT-RESPONSE header from a successful (200) response.\n * The header value is a Base64-encoded JSON string containing the SettleResponse.\n * Returns null if the header is missing or unparseable.\n */\nexport function parsePaymentResponse(header: string | null): SettleResponse | null {\n if (!header) return null;\n try {\n const json = Buffer.from(header, \"base64\").toString(\"utf-8\");\n return JSON.parse(json) as SettleResponse;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract the payment amount, asset, network, and scheme from a PaymentRequirements object.\n * Uses the first entry in the accepts array.\n */\nexport function extractAmount(requirements: PaymentRequirements): {\n amount: string;\n asset: string;\n network: string;\n scheme: string;\n} {\n return {\n amount: requirements.amount,\n asset: requirements.asset,\n network: requirements.network,\n scheme: requirements.scheme,\n };\n}\n\n/**\n * Extract payment info from a PaymentRequired object (the full 402 response).\n * Picks the first accepted payment requirement.\n */\nexport function extractFromPaymentRequired(paymentRequired: PaymentRequired): {\n amount: string;\n asset: string;\n network: string;\n scheme: string;\n payTo: string;\n} | null {\n const first = paymentRequired.accepts[0];\n if (!first) return null;\n return {\n amount: first.amount,\n asset: first.asset,\n network: first.network,\n scheme: first.scheme,\n payTo: first.payTo,\n };\n}\n","import type { SentinelConfig } from \"../types/config\";\nimport type { PaymentContext } from \"../types/index\";\nimport type { AuditRecord } from \"../types/audit\";\nimport type { BudgetEvaluation, BudgetViolation } from \"../types/budget\";\nimport { BudgetManager } from \"../budget/index\";\nimport { AuditLogger } from \"../audit/index\";\nimport { enrichRecord } from \"../audit/enrichment\";\nimport {\n parsePaymentResponse,\n parsePaymentHeader,\n extractFromPaymentRequired,\n normalizeAmountToUSDC,\n} from \"./headers\";\nimport { SentinelBudgetError } from \"../errors\";\nimport { formatUSDCHuman, parseUSDC } from \"../utils/money\";\n\nexport interface InterceptorDeps {\n budgetManager: BudgetManager | null;\n auditLogger: AuditLogger;\n config: SentinelConfig;\n priceCache: Map<string, string>;\n}\n\n/**\n * Pre-request interception: build context and evaluate budget.\n * Checks endpoint allowlist/blocklist AND cumulative spend limits.\n * Amount is unknown at this point, so cumulative checks catch the case\n * where hourly/daily/total limits are already exceeded.\n */\nexport function beforeRequest(\n url: string,\n init: RequestInit | undefined,\n deps: InterceptorDeps,\n): {\n proceed: boolean;\n context: PaymentContext;\n evaluation?: BudgetEvaluation;\n} {\n const method = init?.method ?? \"GET\";\n const context: PaymentContext = {\n endpoint: url,\n method: method.toUpperCase(),\n agentId: deps.config.agentId,\n team: deps.config.team ?? null,\n amount: \"0.000000\",\n amountRaw: \"0\",\n asset: \"\",\n network: \"\",\n scheme: \"\",\n payTo: \"\",\n timestamp: Date.now(),\n metadata: { ...(deps.config.metadata ?? {}) },\n };\n\n if (deps.budgetManager) {\n const eval_ = deps.budgetManager.evaluate(context);\n if (!eval_.allowed) {\n return { proceed: false, context, evaluation: eval_ };\n }\n }\n\n return { proceed: true, context };\n}\n\n/**\n * Post-response interception: parse payment headers, evaluate full budget, log audit record.\n * Called AFTER the underlying fetch returns. Reads ONLY headers, never the body.\n *\n * May throw SentinelBudgetError if a 402 price exceeds budget limits.\n */\nexport async function afterResponse(\n response: Response,\n context: PaymentContext,\n startTime: number,\n deps: InterceptorDeps,\n): Promise<AuditRecord | null> {\n const responseTimeMs = Date.now() - startTime;\n\n // Case 1: Successful response with PAYMENT-RESPONSE header\n const paymentResponseHeader = response.headers.get(\"payment-response\");\n if (paymentResponseHeader) {\n const settlement = parsePaymentResponse(paymentResponseHeader);\n if (settlement) {\n context.network = settlement.network ?? context.network;\n\n // Recover the amount from the price cache (set during a prior 402 for this URL)\n if (context.amount === \"0.000000\") {\n const cachedAmount = deps.priceCache.get(context.endpoint);\n if (cachedAmount) {\n context.amount = cachedAmount;\n deps.priceCache.delete(context.endpoint);\n }\n }\n\n const policyEvaluation = determinePolicyEvaluation(context, deps);\n let budgetRemaining: string | null = null;\n\n if (deps.budgetManager && context.amount !== \"0.000000\") {\n deps.budgetManager.record(context.amount, context.endpoint);\n const state = deps.budgetManager.getState();\n if (deps.config.budget?.maxTotal) {\n budgetRemaining = formatUSDCHuman(\n parseUSDC(deps.config.budget.maxTotal) - parseUSDC(state.totalSpent),\n );\n }\n }\n\n const record = enrichRecord({\n context,\n config: deps.config,\n statusCode: response.status,\n responseTimeMs,\n settlement,\n policyEvaluation: policyEvaluation ? \"allowed\" : \"flagged\",\n budgetRemaining,\n });\n\n try {\n await deps.auditLogger.log(record);\n } catch (err) {\n console.warn(\"[sentinel] Audit log failed (non-fatal):\", err);\n }\n\n if (deps.config.hooks?.afterPayment) {\n try {\n await deps.config.hooks.afterPayment(record);\n } catch {\n // hooks must never block\n }\n }\n\n return record;\n }\n }\n\n // Case 2: 402 — parse price, enforce budget, cache for later\n if (response.status === 402) {\n const rawHeader =\n response.headers.get(\"payment-required\") ||\n response.headers.get(\"x-payment\");\n\n if (rawHeader) {\n try {\n const paymentRequired = parsePaymentHeader(rawHeader);\n if (paymentRequired) {\n const extracted = extractFromPaymentRequired(paymentRequired);\n if (extracted) {\n const humanAmount = normalizeAmountToUSDC(extracted.amount);\n context.amount = humanAmount;\n context.asset = extracted.asset;\n context.network = extracted.network;\n context.scheme = extracted.scheme;\n context.payTo = extracted.payTo;\n\n deps.priceCache.set(context.endpoint, humanAmount);\n }\n }\n } catch {\n // unparseable header — continue with what we have\n }\n }\n\n // Evaluate budget against the extracted price\n if (deps.budgetManager && context.amount !== \"0.000000\") {\n const eval_ = deps.budgetManager.evaluate(context);\n if (!eval_.allowed) {\n await logBlocked(context, eval_.violation, deps);\n throw new SentinelBudgetError(eval_.violation);\n }\n }\n\n const record = enrichRecord({\n context,\n config: deps.config,\n statusCode: 402,\n responseTimeMs,\n settlement: null,\n policyEvaluation: \"flagged\",\n budgetRemaining: null,\n });\n\n try {\n await deps.auditLogger.log(record);\n } catch (err) {\n console.warn(\"[sentinel] Audit log failed (non-fatal):\", err);\n }\n\n return record;\n }\n\n // Case 3: Non-payment response (no payment headers, not 402)\n return null;\n}\n\nasync function logBlocked(\n context: PaymentContext,\n violation: BudgetViolation,\n deps: InterceptorDeps,\n): Promise<void> {\n try {\n await deps.auditLogger.logBlocked(context, violation, {\n humanSponsor: deps.config.humanSponsor,\n metadata: deps.config.metadata,\n });\n } catch {\n // audit failures never block\n }\n\n if (deps.config.hooks?.onBudgetExceeded) {\n try {\n await deps.config.hooks.onBudgetExceeded(violation);\n } catch {\n // hooks must never block\n }\n }\n}\n\nfunction determinePolicyEvaluation(\n context: PaymentContext,\n deps: InterceptorDeps,\n): boolean {\n if (!deps.budgetManager || context.amount === \"0.000000\") return true;\n const eval_ = deps.budgetManager.evaluate(context);\n return eval_.allowed;\n}\n","import type { SentinelConfig } from \"../types/config\";\nimport { BudgetManager } from \"../budget/index\";\nimport { AuditLogger } from \"../audit/index\";\nimport { MemoryStorage } from \"../audit/storage/memory\";\nimport { SentinelBudgetError, validateConfig } from \"../errors\";\nimport { beforeRequest, afterResponse } from \"./interceptor\";\nimport type { InterceptorDeps } from \"./interceptor\";\n\n/**\n * Wrap an x402-enabled fetch function with Sentinel budget enforcement and audit logging.\n *\n * @param fetchWithPayment - The x402-wrapped fetch (from wrapFetchWithPayment)\n * @param config - Sentinel configuration (agent identity, budget, audit settings)\n * @returns A drop-in replacement fetch function with Sentinel instrumentation\n *\n * @example\n * ```ts\n * const fetchWithSentinel = wrapWithSentinel(fetchWithPayment, {\n * agentId: \"agent-weather-001\",\n * budget: standardPolicy(),\n * });\n * const response = await fetchWithSentinel(\"https://api.example.com/weather\");\n * ```\n */\nexport function wrapWithSentinel(\n fetchWithPayment: typeof fetch,\n config: SentinelConfig,\n): typeof fetch {\n validateConfig(config);\n\n const budgetManager = config.budget ? new BudgetManager(config.budget) : null;\n const auditLogger = new AuditLogger(config.audit ?? { enabled: true, storage: new MemoryStorage() });\n\n const priceCache = new Map<string, string>();\n const deps: InterceptorDeps = { budgetManager, auditLogger, config, priceCache };\n\n const sentinelFetch: typeof fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url;\n const startTime = Date.now();\n\n // BEFORE: Check endpoint-level budget rules\n const pre = beforeRequest(url, init, deps);\n if (!pre.proceed && pre.evaluation && !pre.evaluation.allowed) {\n const violation = pre.evaluation.violation;\n\n // Log the blocked attempt (non-fatal if logging fails)\n try {\n await auditLogger.logBlocked(pre.context, violation, {\n humanSponsor: config.humanSponsor,\n metadata: config.metadata,\n });\n } catch {\n // audit failures never block\n }\n\n if (config.hooks?.onBudgetExceeded) {\n try {\n await config.hooks.onBudgetExceeded(violation);\n } catch {\n // hooks must never block\n }\n }\n\n throw new SentinelBudgetError(violation);\n }\n\n // EXECUTE: Call the underlying x402-wrapped fetch\n let response: Response;\n try {\n response = await fetchWithPayment(input, init);\n } catch (err) {\n // Network error — log and re-throw\n try {\n const record = {\n agent_id: pre.context.agentId,\n team: pre.context.team,\n human_sponsor: config.humanSponsor ?? null,\n amount: \"0.000000\",\n amount_raw: \"0\",\n asset: \"\",\n network: \"\",\n scheme: \"\",\n tx_hash: null,\n payer_address: \"\",\n payee_address: \"\",\n facilitator: null,\n endpoint: url,\n method: pre.context.method,\n status_code: 0,\n response_time_ms: Date.now() - startTime,\n policy_id: null,\n policy_evaluation: \"flagged\" as const,\n budget_remaining: null,\n task_id: null,\n session_id: null,\n metadata: { error: err instanceof Error ? err.message : String(err) },\n settled_at: null,\n tags: [\"error\", \"network_failure\"],\n };\n await auditLogger.log(record);\n } catch {\n // audit failures never block\n }\n throw err;\n }\n\n // AFTER: Parse response headers (NEVER touch the body), log audit record\n await afterResponse(response, pre.context, startTime, deps);\n\n // Return the original Response object completely untouched\n return response;\n };\n\n return sentinelFetch;\n}\n","import { readFileSync, appendFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { matchesQuery, buildSummary } from \"./memory\";\n\n/** JSONL file-based audit storage — appends one record per line */\nexport class FileStorage implements StorageBackend {\n private readonly filePath: string;\n private buffer: AuditRecord[] = [];\n private readonly flushThreshold: number;\n private flushTimer: NodeJS.Timeout | null = null;\n\n constructor(filePath = \".valeo/audit.jsonl\", flushThreshold = 100) {\n this.filePath = filePath;\n this.flushThreshold = flushThreshold;\n this.ensureDir();\n this.startAutoFlush();\n }\n\n async write(record: AuditRecord): Promise<void> {\n this.buffer.push(record);\n if (this.buffer.length >= this.flushThreshold) {\n await this.flush();\n }\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n await this.flush();\n const all = this.readAll();\n let results = all.filter((r) => matchesQuery(r, query));\n const offset = query.offset ?? 0;\n const limit = query.limit ?? results.length;\n return results.slice(offset, offset + limit);\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n await this.flush();\n const records = this.readAll().filter((r) => matchesQuery(r, query));\n return buildSummary(records, query);\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n await this.flush();\n return this.readAll().filter((r) => matchesQuery(r, query)).length;\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n await this.flush();\n return this.readAll().find((r) => r.id === id) ?? null;\n }\n\n /** Write buffered records to disk */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const lines = this.buffer.map((r) => JSON.stringify(r)).join(\"\\n\") + \"\\n\";\n appendFileSync(this.filePath, lines, \"utf-8\");\n this.buffer = [];\n }\n\n /** Stop the auto-flush timer (for clean shutdown) */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n }\n\n private readAll(): AuditRecord[] {\n if (!existsSync(this.filePath)) return [];\n const content = readFileSync(this.filePath, \"utf-8\");\n return content\n .split(\"\\n\")\n .filter((line) => line.trim().length > 0)\n .map((line) => JSON.parse(line) as AuditRecord);\n }\n\n private ensureDir(): void {\n const dir = dirname(this.filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n private startAutoFlush(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, 5_000);\n this.flushTimer.unref();\n }\n}\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { MemoryStorage } from \"./memory\";\n\ninterface ApiStorageConfig {\n apiKey: string;\n baseUrl?: string;\n batchSize?: number;\n flushIntervalMs?: number;\n}\n\n/**\n * Remote API storage backend — batches and POSTs records to api.valeo.money.\n * Falls back to in-memory storage if the API is unreachable.\n */\nexport class ApiStorage implements StorageBackend {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly batchSize: number;\n private buffer: AuditRecord[] = [];\n private readonly fallback: MemoryStorage;\n private flushTimer: NodeJS.Timeout | null = null;\n private useFallback = false;\n\n constructor(config: ApiStorageConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? \"https://api.valeo.money/v1\";\n this.batchSize = config.batchSize ?? 50;\n this.fallback = new MemoryStorage();\n this.startAutoFlush(config.flushIntervalMs ?? 10_000);\n }\n\n async write(record: AuditRecord): Promise<void> {\n this.buffer.push(record);\n // Always write to fallback for local query support\n await this.fallback.write(record);\n if (this.buffer.length >= this.batchSize) {\n await this.flush();\n }\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n if (this.useFallback) return this.fallback.query(query);\n try {\n return await this.apiRequest<AuditRecord[]>(\"POST\", \"/audit/query\", query);\n } catch {\n this.useFallback = true;\n return this.fallback.query(query);\n }\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n if (this.useFallback) return this.fallback.summarize(query);\n try {\n return await this.apiRequest<AuditSummary>(\"POST\", \"/audit/summarize\", query);\n } catch {\n this.useFallback = true;\n return this.fallback.summarize(query);\n }\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n if (this.useFallback) return this.fallback.count(query);\n try {\n const result = await this.apiRequest<{ count: number }>(\"POST\", \"/audit/count\", query);\n return result.count;\n } catch {\n this.useFallback = true;\n return this.fallback.count(query);\n }\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n if (this.useFallback) return this.fallback.getById(id);\n try {\n return await this.apiRequest<AuditRecord | null>(\"GET\", `/audit/${id}`);\n } catch {\n this.useFallback = true;\n return this.fallback.getById(id);\n }\n }\n\n /** Flush buffered records to the remote API */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const batch = this.buffer.splice(0, this.batchSize);\n try {\n await this.apiRequest(\"POST\", \"/audit/batch\", { records: batch });\n } catch {\n this.useFallback = true;\n console.warn(\n `[sentinel] API unreachable, falling back to in-memory storage. ${batch.length} records buffered locally.`,\n );\n }\n }\n\n /** Stop the auto-flush timer */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n }\n\n private async apiRequest<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const init: RequestInit = {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n };\n if (body) {\n init.body = JSON.stringify(body);\n }\n\n let lastError: Error | undefined;\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n const response = await fetch(url, init);\n if (!response.ok) {\n throw new Error(`API returned ${response.status}: ${response.statusText}`);\n }\n return (await response.json()) as T;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < 2) {\n await sleep(Math.pow(2, attempt) * 1000);\n }\n }\n }\n throw lastError;\n }\n\n private startAutoFlush(intervalMs: number): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, intervalMs);\n this.flushTimer.unref();\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"]}
package/dist/index.js CHANGED
@@ -679,9 +679,19 @@ function validateConfig(config) {
679
679
  }
680
680
 
681
681
  // src/wrapper/headers.ts
682
- function parsePaymentRequired(header) {
683
- const json = Buffer.from(header, "base64").toString("utf-8");
684
- return JSON.parse(json);
682
+ function parsePaymentHeader(header) {
683
+ try {
684
+ return JSON.parse(Buffer.from(header, "base64").toString("utf-8"));
685
+ } catch {
686
+ try {
687
+ return JSON.parse(header);
688
+ } catch {
689
+ return null;
690
+ }
691
+ }
692
+ }
693
+ function normalizeAmountToUSDC(raw) {
694
+ return formatUSDC(BigInt(raw));
685
695
  }
686
696
  function parsePaymentResponse(header) {
687
697
  if (!header) return null;
@@ -723,7 +733,7 @@ function beforeRequest(url, init, deps) {
723
733
  };
724
734
  if (deps.budgetManager) {
725
735
  const eval_ = deps.budgetManager.evaluate(context);
726
- if (!eval_.allowed && eval_.violation.type === "blocked_endpoint") {
736
+ if (!eval_.allowed) {
727
737
  return { proceed: false, context, evaluation: eval_ };
728
738
  }
729
739
  }
@@ -736,6 +746,13 @@ async function afterResponse(response, context, startTime, deps) {
736
746
  const settlement = parsePaymentResponse(paymentResponseHeader);
737
747
  if (settlement) {
738
748
  context.network = settlement.network ?? context.network;
749
+ if (context.amount === "0.000000") {
750
+ const cachedAmount = deps.priceCache.get(context.endpoint);
751
+ if (cachedAmount) {
752
+ context.amount = cachedAmount;
753
+ deps.priceCache.delete(context.endpoint);
754
+ }
755
+ }
739
756
  const policyEvaluation = determinePolicyEvaluation(context, deps);
740
757
  let budgetRemaining = null;
741
758
  if (deps.budgetManager && context.amount !== "0.000000") {
@@ -771,21 +788,32 @@ async function afterResponse(response, context, startTime, deps) {
771
788
  }
772
789
  }
773
790
  if (response.status === 402) {
774
- const paymentRequiredHeader = response.headers.get("payment-required");
775
- if (paymentRequiredHeader) {
791
+ const rawHeader = response.headers.get("payment-required") || response.headers.get("x-payment");
792
+ if (rawHeader) {
776
793
  try {
777
- const paymentRequired = parsePaymentRequired(paymentRequiredHeader);
778
- const extracted = extractFromPaymentRequired(paymentRequired);
779
- if (extracted) {
780
- context.amount = extracted.amount;
781
- context.asset = extracted.asset;
782
- context.network = extracted.network;
783
- context.scheme = extracted.scheme;
784
- context.payTo = extracted.payTo;
794
+ const paymentRequired = parsePaymentHeader(rawHeader);
795
+ if (paymentRequired) {
796
+ const extracted = extractFromPaymentRequired(paymentRequired);
797
+ if (extracted) {
798
+ const humanAmount = normalizeAmountToUSDC(extracted.amount);
799
+ context.amount = humanAmount;
800
+ context.asset = extracted.asset;
801
+ context.network = extracted.network;
802
+ context.scheme = extracted.scheme;
803
+ context.payTo = extracted.payTo;
804
+ deps.priceCache.set(context.endpoint, humanAmount);
805
+ }
785
806
  }
786
807
  } catch {
787
808
  }
788
809
  }
810
+ if (deps.budgetManager && context.amount !== "0.000000") {
811
+ const eval_ = deps.budgetManager.evaluate(context);
812
+ if (!eval_.allowed) {
813
+ await logBlocked(context, eval_.violation, deps);
814
+ throw new SentinelBudgetError(eval_.violation);
815
+ }
816
+ }
789
817
  const record = enrichRecord({
790
818
  context,
791
819
  config: deps.config,
@@ -804,6 +832,21 @@ async function afterResponse(response, context, startTime, deps) {
804
832
  }
805
833
  return null;
806
834
  }
835
+ async function logBlocked(context, violation, deps) {
836
+ try {
837
+ await deps.auditLogger.logBlocked(context, violation, {
838
+ humanSponsor: deps.config.humanSponsor,
839
+ metadata: deps.config.metadata
840
+ });
841
+ } catch {
842
+ }
843
+ if (deps.config.hooks?.onBudgetExceeded) {
844
+ try {
845
+ await deps.config.hooks.onBudgetExceeded(violation);
846
+ } catch {
847
+ }
848
+ }
849
+ }
807
850
  function determinePolicyEvaluation(context, deps) {
808
851
  if (!deps.budgetManager || context.amount === "0.000000") return true;
809
852
  const eval_ = deps.budgetManager.evaluate(context);
@@ -815,7 +858,8 @@ function wrapWithSentinel(fetchWithPayment, config) {
815
858
  validateConfig(config);
816
859
  const budgetManager = config.budget ? new BudgetManager(config.budget) : null;
817
860
  const auditLogger = new AuditLogger(config.audit ?? { enabled: true, storage: new MemoryStorage() });
818
- const deps = { budgetManager, auditLogger, config };
861
+ const priceCache = /* @__PURE__ */ new Map();
862
+ const deps = { budgetManager, auditLogger, config, priceCache };
819
863
  const sentinelFetch = async (input, init) => {
820
864
  const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
821
865
  const startTime = Date.now();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/budget/spike-detector.ts","../src/budget/policies.ts","../src/budget/index.ts","../src/audit/storage/memory.ts","../src/utils/id.ts","../src/audit/enrichment.ts","../src/audit/export.ts","../src/audit/index.ts","../src/errors.ts","../src/wrapper/headers.ts","../src/wrapper/interceptor.ts","../src/wrapper/index.ts","../src/audit/storage/file.ts","../src/audit/storage/api.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { parseUSDC, formatUSDC, calculateAverage } from \"../utils/money\";\n\n/** Detects abnormal payment spikes using a rolling window of recent amounts */\nexport class SpikeDetector {\n private readonly windowSize: number;\n private readonly threshold: number;\n private readonly window: string[] = [];\n\n constructor(threshold = 3.0, windowSize = 20) {\n this.threshold = threshold;\n this.windowSize = windowSize;\n }\n\n /** Record a payment amount into the rolling window */\n record(amount: string): void {\n this.window.push(amount);\n if (this.window.length > this.windowSize) {\n this.window.shift();\n }\n }\n\n /**\n * Check if a proposed amount is a spike relative to the rolling average.\n * Returns null if no spike, or a description string if spike detected.\n * Needs at least 3 data points before spike detection activates.\n */\n check(amount: string): string | null {\n if (this.window.length < 3) return null;\n\n const avg = calculateAverage(this.window);\n const avgRaw = parseUSDC(avg);\n if (avgRaw === 0n) return null;\n\n const amountRaw = parseUSDC(amount);\n const ratio = Number(amountRaw) / Number(avgRaw);\n\n if (ratio > this.threshold) {\n return (\n `Payment $${amount} is ${ratio.toFixed(1)}x the rolling average ` +\n `$${formatUSDC(avgRaw)} (threshold: ${this.threshold}x)`\n );\n }\n return null;\n }\n\n /** Get the current rolling average */\n getAverage(): string {\n return calculateAverage(this.window);\n }\n\n /** Get the current window contents */\n getWindow(): string[] {\n return [...this.window];\n }\n\n /** Restore state from serialized data */\n loadWindow(amounts: string[]): void {\n this.window.length = 0;\n for (const a of amounts.slice(-this.windowSize)) {\n this.window.push(a);\n }\n }\n}\n","import type { BudgetPolicy } from \"../types/budget\";\n\n/** Tight limits for low-risk or testing scenarios */\nexport function conservativePolicy(): BudgetPolicy {\n return {\n maxPerCall: \"0.10\",\n maxPerHour: \"5.00\",\n maxPerDay: \"50.00\",\n spikeThreshold: 3.0,\n };\n}\n\n/** Balanced limits for typical production agents */\nexport function standardPolicy(): BudgetPolicy {\n return {\n maxPerCall: \"1.00\",\n maxPerHour: \"25.00\",\n maxPerDay: \"200.00\",\n spikeThreshold: 3.0,\n };\n}\n\n/** Higher limits for trusted, high-throughput agents */\nexport function liberalPolicy(): BudgetPolicy {\n return {\n maxPerCall: \"10.00\",\n maxPerHour: \"100.00\",\n maxPerDay: \"1000.00\",\n spikeThreshold: 5.0,\n };\n}\n\n/** No spending limits — audit logging only */\nexport function unlimitedPolicy(): BudgetPolicy {\n return {};\n}\n\n/** Build a custom policy by overriding defaults */\nexport function customPolicy(overrides: Partial<BudgetPolicy>): BudgetPolicy {\n return { ...standardPolicy(), ...overrides };\n}\n","import type { BudgetPolicy, BudgetState, BudgetViolation, BudgetEvaluation } from \"../types/budget\";\nimport type { PaymentContext } from \"../types/index\";\nimport { addUSDC, compareUSDC } from \"../utils/money\";\nimport { getHourStart, getDayStart } from \"../utils/time\";\nimport { SpikeDetector } from \"./spike-detector\";\n\n/** Enforces budget policies by evaluating proposed payments against spending state */\nexport class BudgetManager {\n private state: BudgetState;\n private readonly policy: BudgetPolicy;\n private readonly spikeDetector: SpikeDetector;\n\n constructor(policy: BudgetPolicy) {\n this.policy = policy;\n this.spikeDetector = new SpikeDetector(\n policy.spikeThreshold ?? 3.0,\n );\n const now = Date.now();\n this.state = {\n totalSpent: \"0.000000\",\n hourlySpent: \"0.000000\",\n dailySpent: \"0.000000\",\n callCount: 0,\n lastReset: { hourly: getHourStart(now), daily: getDayStart(now) },\n rollingAverage: \"0.000000\",\n rollingWindow: [],\n };\n }\n\n /**\n * Evaluate a proposed payment against the budget policy.\n * Called BEFORE every payment. Returns allow/deny with reason.\n */\n evaluate(context: PaymentContext): BudgetEvaluation {\n this.maybeResetWindows();\n const warnings: string[] = [];\n\n // 1. Blocked endpoints (fast reject)\n if (this.policy.blockedEndpoints?.length) {\n for (const pattern of this.policy.blockedEndpoints) {\n if (endpointMatches(context.endpoint, pattern)) {\n return {\n allowed: false,\n violation: this.violation(\"blocked_endpoint\", \"0.000000\", \"0.000000\", context),\n };\n }\n }\n }\n\n // 2. Allowed endpoints whitelist\n if (this.policy.allowedEndpoints?.length) {\n const matched = this.policy.allowedEndpoints.some((p) =>\n endpointMatches(context.endpoint, p),\n );\n if (!matched) {\n return {\n allowed: false,\n violation: this.violation(\"blocked_endpoint\", \"0.000000\", \"0.000000\", context),\n };\n }\n }\n\n // 3. Per-call limit\n if (this.policy.maxPerCall) {\n if (compareUSDC(context.amount, this.policy.maxPerCall) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"per_call\", this.policy.maxPerCall, \"0.000000\", context),\n };\n }\n }\n\n // 4. Spike detection\n const spikeMsg = this.spikeDetector.check(context.amount);\n if (spikeMsg) {\n if (this.policy.spikeThreshold !== undefined) {\n return {\n allowed: false,\n violation: this.violation(\n \"spike\",\n this.spikeDetector.getAverage(),\n this.state.hourlySpent,\n context,\n ),\n };\n }\n warnings.push(spikeMsg);\n }\n\n // 5. Hourly rolling window\n if (this.policy.maxPerHour) {\n const projectedHourly = addUSDC(this.state.hourlySpent, context.amount);\n if (compareUSDC(projectedHourly, this.policy.maxPerHour) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"hourly\", this.policy.maxPerHour, this.state.hourlySpent, context),\n };\n }\n }\n\n // 6. Daily rolling window\n if (this.policy.maxPerDay) {\n const projectedDaily = addUSDC(this.state.dailySpent, context.amount);\n if (compareUSDC(projectedDaily, this.policy.maxPerDay) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"daily\", this.policy.maxPerDay, this.state.dailySpent, context),\n };\n }\n }\n\n // 7. Total lifetime cap\n if (this.policy.maxTotal) {\n const projectedTotal = addUSDC(this.state.totalSpent, context.amount);\n if (compareUSDC(projectedTotal, this.policy.maxTotal) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"total\", this.policy.maxTotal, this.state.totalSpent, context),\n };\n }\n }\n\n // 8. Approval threshold\n if (this.policy.requireApproval) {\n if (compareUSDC(context.amount, this.policy.requireApproval.above) > 0) {\n return {\n allowed: false,\n violation: this.violation(\n \"approval_required\",\n this.policy.requireApproval.above,\n this.state.totalSpent,\n context,\n ),\n };\n }\n }\n\n return { allowed: true, warnings };\n }\n\n /** Record a completed payment. Called AFTER payment succeeds. */\n record(amount: string, _endpoint: string): void {\n this.maybeResetWindows();\n this.state.totalSpent = addUSDC(this.state.totalSpent, amount);\n this.state.hourlySpent = addUSDC(this.state.hourlySpent, amount);\n this.state.dailySpent = addUSDC(this.state.dailySpent, amount);\n this.state.callCount++;\n this.spikeDetector.record(amount);\n this.state.rollingAverage = this.spikeDetector.getAverage();\n this.state.rollingWindow = this.spikeDetector.getWindow();\n }\n\n /** Get current budget state (for dashboard/debugging) */\n getState(): BudgetState {\n this.maybeResetWindows();\n return { ...this.state, rollingWindow: [...this.state.rollingWindow] };\n }\n\n /** Reset spending counters for a given scope */\n reset(scope: \"hourly\" | \"daily\" | \"total\"): void {\n const now = Date.now();\n switch (scope) {\n case \"hourly\":\n this.state.hourlySpent = \"0.000000\";\n this.state.lastReset.hourly = getHourStart(now);\n break;\n case \"daily\":\n this.state.dailySpent = \"0.000000\";\n this.state.lastReset.daily = getDayStart(now);\n break;\n case \"total\":\n this.state.totalSpent = \"0.000000\";\n this.state.hourlySpent = \"0.000000\";\n this.state.dailySpent = \"0.000000\";\n this.state.callCount = 0;\n break;\n }\n }\n\n /** Serialize state for persistence */\n serialize(): string {\n return JSON.stringify(this.state);\n }\n\n /** Restore a BudgetManager from serialized state */\n static deserialize(data: string, policy: BudgetPolicy): BudgetManager {\n const mgr = new BudgetManager(policy);\n const parsed = JSON.parse(data) as BudgetState;\n mgr.state = parsed;\n mgr.spikeDetector.loadWindow(parsed.rollingWindow);\n return mgr;\n }\n\n /** Auto-reset hourly/daily windows when the time window has rolled over */\n private maybeResetWindows(): void {\n const now = Date.now();\n const hourStart = getHourStart(now);\n const dayStart = getDayStart(now);\n\n if (hourStart > this.state.lastReset.hourly) {\n this.state.hourlySpent = \"0.000000\";\n this.state.lastReset.hourly = hourStart;\n }\n if (dayStart > this.state.lastReset.daily) {\n this.state.dailySpent = \"0.000000\";\n this.state.lastReset.daily = dayStart;\n }\n }\n\n private violation(\n type: BudgetViolation[\"type\"],\n limit: string,\n current: string,\n context: PaymentContext,\n ): BudgetViolation {\n return {\n type,\n limit,\n current,\n attempted: context.amount,\n agentId: context.agentId,\n endpoint: context.endpoint,\n timestamp: Date.now(),\n };\n }\n}\n\n/** Simple glob-like endpoint matching (supports * wildcards) */\nfunction endpointMatches(url: string, pattern: string): boolean {\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\*/g, \".*\").replace(/\\?/g, \".\") + \"$\",\n );\n return regex.test(url);\n}\n\nexport { SpikeDetector } from \"./spike-detector\";\nexport {\n conservativePolicy,\n standardPolicy,\n liberalPolicy,\n unlimitedPolicy,\n customPolicy,\n} from \"./policies\";\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { parseUSDC, formatUSDC, formatUSDCHuman, compareUSDC } from \"../../utils/money\";\n\n/** In-memory audit storage with configurable capacity and FIFO eviction */\nexport class MemoryStorage implements StorageBackend {\n private readonly records = new Map<string, AuditRecord>();\n private readonly insertOrder: string[] = [];\n private readonly maxRecords: number;\n\n constructor(maxRecords = 10_000) {\n this.maxRecords = maxRecords;\n }\n\n async write(record: AuditRecord): Promise<void> {\n if (this.records.size >= this.maxRecords) {\n const oldest = this.insertOrder.shift();\n if (oldest) this.records.delete(oldest);\n }\n this.records.set(record.id, record);\n this.insertOrder.push(record.id);\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n let results = this.filter(query);\n results = this.sort(results, query.orderBy, query.order);\n const offset = query.offset ?? 0;\n const limit = query.limit ?? results.length;\n return results.slice(offset, offset + limit);\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n const records = this.filter(query);\n return buildSummary(records, query);\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n return this.filter(query).length;\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n return this.records.get(id) ?? null;\n }\n\n private filter(query: Partial<AuditQuery>): AuditRecord[] {\n return [...this.records.values()].filter((r) => matchesQuery(r, query));\n }\n\n private sort(\n records: AuditRecord[],\n orderBy?: AuditQuery[\"orderBy\"],\n order?: AuditQuery[\"order\"],\n ): AuditRecord[] {\n if (!orderBy) return records;\n const dir = order === \"desc\" ? -1 : 1;\n return records.sort((a, b) => {\n switch (orderBy) {\n case \"created_at\":\n return (a.created_at - b.created_at) * dir;\n case \"amount\":\n return compareUSDC(a.amount, b.amount) * dir;\n case \"endpoint\":\n return a.endpoint.localeCompare(b.endpoint) * dir;\n default:\n return 0;\n }\n });\n }\n}\n\n/** Shared filter logic reusable across storage backends */\nexport function matchesQuery(\n record: AuditRecord,\n query: Partial<AuditQuery>,\n): boolean {\n if (query.agentId && record.agent_id !== query.agentId) return false;\n if (query.team && record.team !== query.team) return false;\n if (query.endpoint && !record.endpoint.includes(query.endpoint)) return false;\n if (query.minAmount && compareUSDC(record.amount, query.minAmount) < 0) return false;\n if (query.maxAmount && compareUSDC(record.amount, query.maxAmount) > 0) return false;\n if (query.startTime && record.created_at < query.startTime) return false;\n if (query.endTime && record.created_at > query.endTime) return false;\n if (query.status?.length && !query.status.includes(record.policy_evaluation)) return false;\n if (query.tags?.length && !query.tags.some((t) => record.tags.includes(t))) return false;\n return true;\n}\n\n/** Build an AuditSummary from a set of records */\nexport function buildSummary(\n records: AuditRecord[],\n query: Partial<AuditQuery>,\n): AuditSummary {\n let totalRaw = 0n;\n let maxRaw = 0n;\n const agents = new Set<string>();\n const endpoints = new Set<string>();\n const byAgent: Record<string, { spend: string; count: number }> = {};\n const byEndpoint: Record<string, { spend: string; count: number }> = {};\n const byTeam: Record<string, { spend: string; count: number }> = {};\n let violations = 0;\n let minTs = Infinity;\n let maxTs = 0;\n\n for (const r of records) {\n const raw = parseUSDC(r.amount);\n totalRaw += raw;\n if (raw > maxRaw) maxRaw = raw;\n agents.add(r.agent_id);\n endpoints.add(r.endpoint);\n\n if (r.created_at < minTs) minTs = r.created_at;\n if (r.created_at > maxTs) maxTs = r.created_at;\n\n if (r.policy_evaluation === \"blocked\") violations++;\n\n // by_agent\n const agentEntry = byAgent[r.agent_id] ?? { spend: \"0.000000\", count: 0 };\n agentEntry.spend = formatUSDC(parseUSDC(agentEntry.spend) + raw);\n agentEntry.count++;\n byAgent[r.agent_id] = agentEntry;\n\n // by_endpoint\n const epEntry = byEndpoint[r.endpoint] ?? { spend: \"0.000000\", count: 0 };\n epEntry.spend = formatUSDC(parseUSDC(epEntry.spend) + raw);\n epEntry.count++;\n byEndpoint[r.endpoint] = epEntry;\n\n // by_team\n const teamKey = r.team ?? \"(none)\";\n const teamEntry = byTeam[teamKey] ?? { spend: \"0.000000\", count: 0 };\n teamEntry.spend = formatUSDC(parseUSDC(teamEntry.spend) + raw);\n teamEntry.count++;\n byTeam[teamKey] = teamEntry;\n }\n\n const count = records.length;\n return {\n total_spend: formatUSDCHuman(totalRaw),\n total_transactions: count,\n unique_endpoints: endpoints.size,\n unique_agents: agents.size,\n avg_payment: count > 0 ? formatUSDCHuman(totalRaw / BigInt(count)) : \"0.00\",\n max_payment: formatUSDCHuman(maxRaw),\n by_agent: byAgent,\n by_endpoint: byEndpoint,\n by_team: byTeam,\n violations,\n period: {\n start: query.startTime ?? (minTs === Infinity ? 0 : minTs),\n end: query.endTime ?? (maxTs === 0 ? 0 : maxTs),\n },\n };\n}\n","import { createHash, randomUUID } from \"node:crypto\";\n\n/**\n * Generate a deterministic record ID from payment attributes.\n * SHA-256 of concatenated inputs, truncated to 16 hex chars.\n */\nexport function generateRecordId(\n agentId: string,\n endpoint: string,\n timestamp: number,\n amount: string,\n): string {\n const input = `${agentId}|${endpoint}|${timestamp}|${amount}`;\n const hash = createHash(\"sha256\").update(input).digest(\"hex\");\n return hash.slice(0, 16);\n}\n\n/** Generate a random session ID (UUID v4) */\nexport function generateSessionId(): string {\n return randomUUID();\n}\n","import type { AuditRecord } from \"../types/audit\";\nimport type { PaymentContext, EnrichmentConfig } from \"../types/index\";\nimport type { SettleResponse } from \"../types/x402-stubs\";\nimport type { SentinelConfig } from \"../types/config\";\nimport { generateRecordId } from \"../utils/id\";\n\ninterface EnrichmentInput {\n context: PaymentContext;\n config: SentinelConfig;\n statusCode: number;\n responseTimeMs: number;\n settlement: SettleResponse | null;\n policyEvaluation: \"allowed\" | \"flagged\" | \"blocked\";\n budgetRemaining: string | null;\n}\n\n/** Build a complete AuditRecord from payment context and settlement data */\nexport function enrichRecord(input: EnrichmentInput): AuditRecord {\n const { context, config, statusCode, responseTimeMs, settlement, policyEvaluation, budgetRemaining } = input;\n const now = Date.now();\n const id = generateRecordId(context.agentId, context.endpoint, now, context.amount);\n\n const tags = computeTags(context, config.audit?.enrichment);\n\n return {\n id,\n agent_id: context.agentId,\n team: context.team,\n human_sponsor: config.humanSponsor ?? null,\n\n amount: context.amount,\n amount_raw: context.amountRaw,\n asset: context.asset,\n network: context.network,\n scheme: context.scheme,\n\n tx_hash: settlement?.transaction ?? null,\n payer_address: settlement?.payer ?? \"\",\n payee_address: context.payTo,\n facilitator: null,\n\n endpoint: context.endpoint,\n method: context.method,\n status_code: statusCode,\n response_time_ms: responseTimeMs,\n\n policy_id: null,\n policy_evaluation: policyEvaluation,\n budget_remaining: budgetRemaining,\n\n task_id: context.metadata[\"task_id\"] ?? null,\n session_id: context.metadata[\"session_id\"] ?? null,\n metadata: { ...context.metadata, ...config.metadata },\n\n created_at: now,\n settled_at: settlement?.success ? now : null,\n\n tags,\n };\n}\n\n/** Build an AuditRecord for a blocked payment attempt */\nexport function enrichBlockedRecord(\n context: PaymentContext,\n config: SentinelConfig,\n policyEvaluation: \"blocked\",\n): AuditRecord {\n return enrichRecord({\n context,\n config,\n statusCode: 0,\n responseTimeMs: 0,\n settlement: null,\n policyEvaluation,\n budgetRemaining: null,\n });\n}\n\nfunction computeTags(context: PaymentContext, enrichment?: EnrichmentConfig): string[] {\n const tags: string[] = [];\n\n if (enrichment?.staticTags) {\n tags.push(...enrichment.staticTags);\n }\n\n if (enrichment?.tagRules) {\n for (const rule of enrichment.tagRules) {\n const regex = new RegExp(rule.pattern);\n if (regex.test(context.endpoint)) {\n tags.push(...rule.tags);\n }\n }\n }\n\n return tags;\n}\n","import type { AuditRecord, AuditSummary } from \"../types/audit\";\n\nconst CSV_HEADERS: (keyof AuditRecord)[] = [\n \"id\", \"agent_id\", \"team\", \"human_sponsor\",\n \"amount\", \"amount_raw\", \"asset\", \"network\", \"scheme\",\n \"tx_hash\", \"payer_address\", \"payee_address\", \"facilitator\",\n \"endpoint\", \"method\", \"status_code\", \"response_time_ms\",\n \"policy_id\", \"policy_evaluation\", \"budget_remaining\",\n \"task_id\", \"session_id\",\n \"created_at\", \"settled_at\",\n];\n\n/** Convert records to a properly escaped CSV string */\nexport function toCSV(records: AuditRecord[]): string {\n const lines: string[] = [CSV_HEADERS.join(\",\")];\n\n for (const record of records) {\n const values = CSV_HEADERS.map((key) => {\n const val = record[key];\n if (val === null || val === undefined) return \"\";\n const str = String(val);\n if (str.includes(\",\") || str.includes('\"') || str.includes(\"\\n\")) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n });\n lines.push(values.join(\",\"));\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/** Convert records to a JSON string */\nexport function toJSON(records: AuditRecord[], pretty = false): string {\n return JSON.stringify(records, null, pretty ? 2 : undefined);\n}\n\n/** Generate a human-readable text summary report */\nexport function toSummaryReport(summary: AuditSummary): string {\n const lines: string[] = [\n \"═══════════════════════════════════════════\",\n \" VALEO SENTINEL — AUDIT SUMMARY REPORT\",\n \"═══════════════════════════════════════════\",\n \"\",\n ` Period: ${new Date(summary.period.start).toISOString()} — ${new Date(summary.period.end).toISOString()}`,\n \"\",\n ` Total Spend: $${summary.total_spend}`,\n ` Total Transactions: ${summary.total_transactions}`,\n ` Unique Agents: ${summary.unique_agents}`,\n ` Unique Endpoints: ${summary.unique_endpoints}`,\n ` Avg Payment: $${summary.avg_payment}`,\n ` Max Payment: $${summary.max_payment}`,\n ` Violations: ${summary.violations}`,\n \"\",\n ];\n\n if (Object.keys(summary.by_agent).length > 0) {\n lines.push(\" ── Spend by Agent ──\");\n for (const [agent, data] of Object.entries(summary.by_agent)) {\n lines.push(` ${agent}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n if (Object.keys(summary.by_team).length > 0) {\n lines.push(\" ── Spend by Team ──\");\n for (const [team, data] of Object.entries(summary.by_team)) {\n lines.push(` ${team}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n if (Object.keys(summary.by_endpoint).length > 0) {\n lines.push(\" ── Spend by Endpoint ──\");\n for (const [ep, data] of Object.entries(summary.by_endpoint)) {\n lines.push(` ${ep}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"═══════════════════════════════════════════\");\n return lines.join(\"\\n\");\n}\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../types/audit\";\nimport type { AuditConfig } from \"../types/config\";\nimport type { PaymentContext } from \"../types/index\";\nimport type { BudgetViolation } from \"../types/budget\";\nimport type { StorageBackend } from \"./storage/interface\";\nimport { MemoryStorage } from \"./storage/memory\";\nimport { enrichBlockedRecord } from \"./enrichment\";\nimport { generateRecordId } from \"../utils/id\";\nimport { toCSV, toJSON } from \"./export\";\n\n/** Central audit logger — writes records to a pluggable storage backend */\nexport class AuditLogger {\n private readonly storage: StorageBackend;\n private readonly enabled: boolean;\n private readonly redactFields: string[];\n\n constructor(config?: AuditConfig) {\n this.enabled = config?.enabled !== false;\n this.storage = config?.storage ?? new MemoryStorage();\n this.redactFields = config?.redactFields ?? [];\n }\n\n /** Log a completed payment record */\n async log(record: Omit<AuditRecord, \"id\" | \"created_at\">): Promise<AuditRecord> {\n const now = Date.now();\n const full: AuditRecord = {\n ...record,\n id: generateRecordId(record.agent_id, record.endpoint, now, record.amount),\n created_at: now,\n };\n\n const redacted = this.redact(full);\n\n if (this.enabled) {\n try {\n await this.storage.write(redacted);\n } catch (err) {\n console.warn(\"[sentinel] Audit write failed (non-fatal):\", err);\n }\n }\n\n return redacted;\n }\n\n /** Log a blocked payment attempt */\n async logBlocked(\n context: PaymentContext,\n violation: BudgetViolation,\n config: { humanSponsor?: string; metadata?: Record<string, string> },\n ): Promise<AuditRecord> {\n const record = enrichBlockedRecord(context, {\n agentId: context.agentId,\n ...config,\n }, \"blocked\");\n record.metadata[\"violation_type\"] = violation.type;\n record.metadata[\"violation_limit\"] = violation.limit;\n\n if (this.enabled) {\n try {\n await this.storage.write(this.redact(record));\n } catch (err) {\n console.warn(\"[sentinel] Audit write failed (non-fatal):\", err);\n }\n }\n\n return record;\n }\n\n /** Query audit records */\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n return this.storage.query(query);\n }\n\n /** Get summary statistics */\n async summarize(query?: Partial<AuditQuery>): Promise<AuditSummary> {\n return this.storage.summarize(query ?? {});\n }\n\n /** Export records as CSV */\n async exportCSV(query?: AuditQuery): Promise<string> {\n const records = await this.storage.query(query ?? {});\n return toCSV(records);\n }\n\n /** Export records as JSON */\n async exportJSON(query?: AuditQuery): Promise<string> {\n const records = await this.storage.query(query ?? {});\n return toJSON(records, true);\n }\n\n /** Flush pending writes to storage */\n async flush(): Promise<void> {\n if (\"flush\" in this.storage && typeof this.storage.flush === \"function\") {\n await (this.storage as StorageBackend & { flush(): Promise<void> }).flush();\n }\n }\n\n /** Get the underlying storage backend (for dashboard integration) */\n getStorage(): StorageBackend {\n return this.storage;\n }\n\n private redact(record: AuditRecord): AuditRecord {\n if (this.redactFields.length === 0) return record;\n const copy = { ...record, metadata: { ...record.metadata } };\n for (const field of this.redactFields) {\n if (field in copy.metadata) {\n copy.metadata[field] = \"[REDACTED]\";\n }\n }\n return copy;\n }\n}\n","import type { AuditRecord } from \"./types/audit\";\nimport type { BudgetViolation } from \"./types/budget\";\nimport { parseUSDC } from \"./utils/money\";\n\nexport class SentinelError extends Error {\n readonly code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.name = \"SentinelError\";\n this.code = code;\n }\n}\n\nexport class SentinelBudgetError extends SentinelError {\n readonly violation: BudgetViolation;\n\n constructor(violation: BudgetViolation) {\n super(buildBudgetMessage(violation), \"BUDGET_EXCEEDED\");\n this.name = \"SentinelBudgetError\";\n this.violation = violation;\n }\n}\n\n/** Audit failures are NEVER fatal — they should be caught and logged */\nexport class SentinelAuditError extends SentinelError {\n readonly record?: Partial<AuditRecord>;\n\n constructor(message: string, record?: Partial<AuditRecord>) {\n super(message, \"AUDIT_ERROR\");\n this.name = \"SentinelAuditError\";\n this.record = record;\n }\n}\n\nexport class SentinelConfigError extends SentinelError {\n constructor(message: string) {\n super(message, \"CONFIG_ERROR\");\n this.name = \"SentinelConfigError\";\n }\n}\n\nfunction buildBudgetMessage(v: BudgetViolation): string {\n const attempted = `$${v.attempted}`;\n\n switch (v.type) {\n case \"per_call\":\n return `Budget exceeded: ${attempted} exceeds per-call limit of $${v.limit} on ${v.agentId}`;\n case \"hourly\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} hourly limit on ${v.agentId} (attempted ${attempted})`;\n case \"daily\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} daily limit on ${v.agentId} (attempted ${attempted})`;\n case \"total\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} total limit on ${v.agentId} (attempted ${attempted})`;\n case \"spike\":\n return `Price spike detected: ${attempted} vs rolling average $${v.limit} on ${v.agentId}`;\n case \"blocked_endpoint\":\n return `Blocked endpoint: ${v.endpoint} is not allowed for ${v.agentId}`;\n case \"approval_required\":\n return `Approval required: ${attempted} exceeds approval threshold $${v.limit} on ${v.agentId}`;\n }\n}\n\n/** Validate a SentinelConfig at initialization time */\nexport function validateConfig(config: {\n agentId: string;\n budget?: {\n maxPerCall?: string;\n maxPerHour?: string;\n maxPerDay?: string;\n maxTotal?: string;\n spikeThreshold?: number;\n allowedEndpoints?: string[];\n blockedEndpoints?: string[];\n };\n}): void {\n if (!config.agentId || config.agentId.trim() === \"\") {\n throw new SentinelConfigError(\"agentId is required and must be non-empty\");\n }\n\n const budget = config.budget;\n if (!budget) return;\n\n const amountFields = [\"maxPerCall\", \"maxPerHour\", \"maxPerDay\", \"maxTotal\"] as const;\n for (const field of amountFields) {\n const value = budget[field];\n if (value !== undefined) {\n try {\n parseUSDC(value);\n } catch {\n throw new SentinelConfigError(\n `budget.${field} \"${value}\" is not a valid USDC amount`,\n );\n }\n }\n }\n\n if (budget.spikeThreshold !== undefined && budget.spikeThreshold <= 1.0) {\n throw new SentinelConfigError(\n `budget.spikeThreshold must be > 1.0, got ${budget.spikeThreshold}`,\n );\n }\n\n if (budget.allowedEndpoints?.length && budget.blockedEndpoints?.length) {\n throw new SentinelConfigError(\n \"Cannot set both allowedEndpoints and blockedEndpoints — use one or the other\",\n );\n }\n}\n","import type { PaymentRequired, PaymentRequirements, SettleResponse } from \"../types/x402-stubs\";\n\n/**\n * Decode the PAYMENT-REQUIRED header from a 402 response.\n * The header value is a Base64-encoded JSON string containing the PaymentRequired object.\n */\nexport function parsePaymentRequired(header: string): PaymentRequired {\n const json = Buffer.from(header, \"base64\").toString(\"utf-8\");\n return JSON.parse(json) as PaymentRequired;\n}\n\n/**\n * Decode the PAYMENT-RESPONSE header from a successful (200) response.\n * The header value is a Base64-encoded JSON string containing the SettleResponse.\n * Returns null if the header is missing or unparseable.\n */\nexport function parsePaymentResponse(header: string | null): SettleResponse | null {\n if (!header) return null;\n try {\n const json = Buffer.from(header, \"base64\").toString(\"utf-8\");\n return JSON.parse(json) as SettleResponse;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract the payment amount, asset, network, and scheme from a PaymentRequirements object.\n * Uses the first entry in the accepts array.\n */\nexport function extractAmount(requirements: PaymentRequirements): {\n amount: string;\n asset: string;\n network: string;\n scheme: string;\n} {\n return {\n amount: requirements.amount,\n asset: requirements.asset,\n network: requirements.network,\n scheme: requirements.scheme,\n };\n}\n\n/**\n * Extract payment info from a PaymentRequired object (the full 402 response).\n * Picks the first accepted payment requirement.\n */\nexport function extractFromPaymentRequired(paymentRequired: PaymentRequired): {\n amount: string;\n asset: string;\n network: string;\n scheme: string;\n payTo: string;\n} | null {\n const first = paymentRequired.accepts[0];\n if (!first) return null;\n return {\n amount: first.amount,\n asset: first.asset,\n network: first.network,\n scheme: first.scheme,\n payTo: first.payTo,\n };\n}\n","import type { SentinelConfig } from \"../types/config\";\nimport type { PaymentContext } from \"../types/index\";\nimport type { AuditRecord } from \"../types/audit\";\nimport type { BudgetEvaluation } from \"../types/budget\";\nimport { BudgetManager } from \"../budget/index\";\nimport { AuditLogger } from \"../audit/index\";\nimport { enrichRecord } from \"../audit/enrichment\";\nimport { parsePaymentResponse, parsePaymentRequired, extractFromPaymentRequired } from \"./headers\";\nimport { formatUSDCHuman, parseUSDC } from \"../utils/money\";\n\nexport interface InterceptorDeps {\n budgetManager: BudgetManager | null;\n auditLogger: AuditLogger;\n config: SentinelConfig;\n}\n\n/**\n * Pre-request interception: build context and evaluate budget.\n * Called BEFORE the underlying fetch. If the request is not a paid endpoint\n * (no amount info yet), we build a placeholder context with \"0.000000\" amount.\n */\nexport function beforeRequest(\n url: string,\n init: RequestInit | undefined,\n deps: InterceptorDeps,\n): {\n proceed: boolean;\n context: PaymentContext;\n evaluation?: BudgetEvaluation;\n} {\n const method = init?.method ?? \"GET\";\n const context: PaymentContext = {\n endpoint: url,\n method: method.toUpperCase(),\n agentId: deps.config.agentId,\n team: deps.config.team ?? null,\n amount: \"0.000000\",\n amountRaw: \"0\",\n asset: \"\",\n network: \"\",\n scheme: \"\",\n payTo: \"\",\n timestamp: Date.now(),\n metadata: { ...(deps.config.metadata ?? {}) },\n };\n\n // We can't know the exact amount before the request (x402 determines it from the 402 response).\n // Budget pre-checks that don't depend on amount (endpoint filtering) can still run.\n // The full budget evaluation happens when we know the amount from the response headers.\n if (deps.budgetManager) {\n // Run endpoint-only checks (blocked/allowed endpoints)\n const eval_ = deps.budgetManager.evaluate(context);\n if (!eval_.allowed && eval_.violation.type === \"blocked_endpoint\") {\n return { proceed: false, context, evaluation: eval_ };\n }\n }\n\n return { proceed: true, context };\n}\n\n/**\n * Post-response interception: parse payment headers, evaluate full budget, log audit record.\n * Called AFTER the underlying fetch returns. Reads ONLY headers, never the body.\n */\nexport async function afterResponse(\n response: Response,\n context: PaymentContext,\n startTime: number,\n deps: InterceptorDeps,\n): Promise<AuditRecord | null> {\n const responseTimeMs = Date.now() - startTime;\n\n // Case 1: Successful response with PAYMENT-RESPONSE header\n const paymentResponseHeader = response.headers.get(\"payment-response\");\n if (paymentResponseHeader) {\n const settlement = parsePaymentResponse(paymentResponseHeader);\n if (settlement) {\n // Enrich context from settlement\n context.network = settlement.network ?? context.network;\n\n // We need the amount from the original payment requirements.\n // Since x402 already handled the 402->200 cycle, we may also have amount info\n // in a custom header or we parse from context. For now, use what's available.\n const policyEvaluation = determinePolicyEvaluation(context, deps);\n let budgetRemaining: string | null = null;\n\n if (deps.budgetManager && context.amount !== \"0.000000\") {\n deps.budgetManager.record(context.amount, context.endpoint);\n const state = deps.budgetManager.getState();\n if (deps.config.budget?.maxTotal) {\n budgetRemaining = formatUSDCHuman(\n parseUSDC(deps.config.budget.maxTotal) - parseUSDC(state.totalSpent),\n );\n }\n }\n\n const record = enrichRecord({\n context,\n config: deps.config,\n statusCode: response.status,\n responseTimeMs,\n settlement,\n policyEvaluation: policyEvaluation ? \"allowed\" : \"flagged\",\n budgetRemaining,\n });\n\n try {\n await deps.auditLogger.log(record);\n } catch (err) {\n console.warn(\"[sentinel] Audit log failed (non-fatal):\", err);\n }\n\n if (deps.config.hooks?.afterPayment) {\n try {\n await deps.config.hooks.afterPayment(record);\n } catch {\n // hooks must never block\n }\n }\n\n return record;\n }\n }\n\n // Case 2: Leaked 402 — x402 failed to complete payment\n if (response.status === 402) {\n const paymentRequiredHeader = response.headers.get(\"payment-required\");\n if (paymentRequiredHeader) {\n try {\n const paymentRequired = parsePaymentRequired(paymentRequiredHeader);\n const extracted = extractFromPaymentRequired(paymentRequired);\n if (extracted) {\n context.amount = extracted.amount;\n context.asset = extracted.asset;\n context.network = extracted.network;\n context.scheme = extracted.scheme;\n context.payTo = extracted.payTo;\n }\n } catch {\n // unparseable header — log what we have\n }\n }\n\n const record = enrichRecord({\n context,\n config: deps.config,\n statusCode: 402,\n responseTimeMs,\n settlement: null,\n policyEvaluation: \"flagged\",\n budgetRemaining: null,\n });\n\n try {\n await deps.auditLogger.log(record);\n } catch (err) {\n console.warn(\"[sentinel] Audit log failed (non-fatal):\", err);\n }\n\n return record;\n }\n\n // Case 3: Non-payment response (no payment headers, not 402)\n return null;\n}\n\nfunction determinePolicyEvaluation(\n context: PaymentContext,\n deps: InterceptorDeps,\n): boolean {\n if (!deps.budgetManager || context.amount === \"0.000000\") return true;\n const eval_ = deps.budgetManager.evaluate(context);\n return eval_.allowed;\n}\n","import type { SentinelConfig } from \"../types/config\";\nimport { BudgetManager } from \"../budget/index\";\nimport { AuditLogger } from \"../audit/index\";\nimport { MemoryStorage } from \"../audit/storage/memory\";\nimport { SentinelBudgetError, validateConfig } from \"../errors\";\nimport { beforeRequest, afterResponse } from \"./interceptor\";\nimport type { InterceptorDeps } from \"./interceptor\";\n\n/**\n * Wrap an x402-enabled fetch function with Sentinel budget enforcement and audit logging.\n *\n * @param fetchWithPayment - The x402-wrapped fetch (from wrapFetchWithPayment)\n * @param config - Sentinel configuration (agent identity, budget, audit settings)\n * @returns A drop-in replacement fetch function with Sentinel instrumentation\n *\n * @example\n * ```ts\n * const fetchWithSentinel = wrapWithSentinel(fetchWithPayment, {\n * agentId: \"agent-weather-001\",\n * budget: standardPolicy(),\n * });\n * const response = await fetchWithSentinel(\"https://api.example.com/weather\");\n * ```\n */\nexport function wrapWithSentinel(\n fetchWithPayment: typeof fetch,\n config: SentinelConfig,\n): typeof fetch {\n validateConfig(config);\n\n const budgetManager = config.budget ? new BudgetManager(config.budget) : null;\n const auditLogger = new AuditLogger(config.audit ?? { enabled: true, storage: new MemoryStorage() });\n\n const deps: InterceptorDeps = { budgetManager, auditLogger, config };\n\n const sentinelFetch: typeof fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url;\n const startTime = Date.now();\n\n // BEFORE: Check endpoint-level budget rules\n const pre = beforeRequest(url, init, deps);\n if (!pre.proceed && pre.evaluation && !pre.evaluation.allowed) {\n const violation = pre.evaluation.violation;\n\n // Log the blocked attempt (non-fatal if logging fails)\n try {\n await auditLogger.logBlocked(pre.context, violation, {\n humanSponsor: config.humanSponsor,\n metadata: config.metadata,\n });\n } catch {\n // audit failures never block\n }\n\n if (config.hooks?.onBudgetExceeded) {\n try {\n await config.hooks.onBudgetExceeded(violation);\n } catch {\n // hooks must never block\n }\n }\n\n throw new SentinelBudgetError(violation);\n }\n\n // EXECUTE: Call the underlying x402-wrapped fetch\n let response: Response;\n try {\n response = await fetchWithPayment(input, init);\n } catch (err) {\n // Network error — log and re-throw\n try {\n const record = {\n agent_id: pre.context.agentId,\n team: pre.context.team,\n human_sponsor: config.humanSponsor ?? null,\n amount: \"0.000000\",\n amount_raw: \"0\",\n asset: \"\",\n network: \"\",\n scheme: \"\",\n tx_hash: null,\n payer_address: \"\",\n payee_address: \"\",\n facilitator: null,\n endpoint: url,\n method: pre.context.method,\n status_code: 0,\n response_time_ms: Date.now() - startTime,\n policy_id: null,\n policy_evaluation: \"flagged\" as const,\n budget_remaining: null,\n task_id: null,\n session_id: null,\n metadata: { error: err instanceof Error ? err.message : String(err) },\n settled_at: null,\n tags: [\"error\", \"network_failure\"],\n };\n await auditLogger.log(record);\n } catch {\n // audit failures never block\n }\n throw err;\n }\n\n // AFTER: Parse response headers (NEVER touch the body), log audit record\n await afterResponse(response, pre.context, startTime, deps);\n\n // Return the original Response object completely untouched\n return response;\n };\n\n return sentinelFetch;\n}\n","import { readFileSync, appendFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { matchesQuery, buildSummary } from \"./memory\";\n\n/** JSONL file-based audit storage — appends one record per line */\nexport class FileStorage implements StorageBackend {\n private readonly filePath: string;\n private buffer: AuditRecord[] = [];\n private readonly flushThreshold: number;\n private flushTimer: NodeJS.Timeout | null = null;\n\n constructor(filePath = \".valeo/audit.jsonl\", flushThreshold = 100) {\n this.filePath = filePath;\n this.flushThreshold = flushThreshold;\n this.ensureDir();\n this.startAutoFlush();\n }\n\n async write(record: AuditRecord): Promise<void> {\n this.buffer.push(record);\n if (this.buffer.length >= this.flushThreshold) {\n await this.flush();\n }\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n await this.flush();\n const all = this.readAll();\n let results = all.filter((r) => matchesQuery(r, query));\n const offset = query.offset ?? 0;\n const limit = query.limit ?? results.length;\n return results.slice(offset, offset + limit);\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n await this.flush();\n const records = this.readAll().filter((r) => matchesQuery(r, query));\n return buildSummary(records, query);\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n await this.flush();\n return this.readAll().filter((r) => matchesQuery(r, query)).length;\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n await this.flush();\n return this.readAll().find((r) => r.id === id) ?? null;\n }\n\n /** Write buffered records to disk */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const lines = this.buffer.map((r) => JSON.stringify(r)).join(\"\\n\") + \"\\n\";\n appendFileSync(this.filePath, lines, \"utf-8\");\n this.buffer = [];\n }\n\n /** Stop the auto-flush timer (for clean shutdown) */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n }\n\n private readAll(): AuditRecord[] {\n if (!existsSync(this.filePath)) return [];\n const content = readFileSync(this.filePath, \"utf-8\");\n return content\n .split(\"\\n\")\n .filter((line) => line.trim().length > 0)\n .map((line) => JSON.parse(line) as AuditRecord);\n }\n\n private ensureDir(): void {\n const dir = dirname(this.filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n private startAutoFlush(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, 5_000);\n this.flushTimer.unref();\n }\n}\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { MemoryStorage } from \"./memory\";\n\ninterface ApiStorageConfig {\n apiKey: string;\n baseUrl?: string;\n batchSize?: number;\n flushIntervalMs?: number;\n}\n\n/**\n * Remote API storage backend — batches and POSTs records to api.valeo.money.\n * Falls back to in-memory storage if the API is unreachable.\n */\nexport class ApiStorage implements StorageBackend {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly batchSize: number;\n private buffer: AuditRecord[] = [];\n private readonly fallback: MemoryStorage;\n private flushTimer: NodeJS.Timeout | null = null;\n private useFallback = false;\n\n constructor(config: ApiStorageConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? \"https://api.valeo.money/v1\";\n this.batchSize = config.batchSize ?? 50;\n this.fallback = new MemoryStorage();\n this.startAutoFlush(config.flushIntervalMs ?? 10_000);\n }\n\n async write(record: AuditRecord): Promise<void> {\n this.buffer.push(record);\n // Always write to fallback for local query support\n await this.fallback.write(record);\n if (this.buffer.length >= this.batchSize) {\n await this.flush();\n }\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n if (this.useFallback) return this.fallback.query(query);\n try {\n return await this.apiRequest<AuditRecord[]>(\"POST\", \"/audit/query\", query);\n } catch {\n this.useFallback = true;\n return this.fallback.query(query);\n }\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n if (this.useFallback) return this.fallback.summarize(query);\n try {\n return await this.apiRequest<AuditSummary>(\"POST\", \"/audit/summarize\", query);\n } catch {\n this.useFallback = true;\n return this.fallback.summarize(query);\n }\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n if (this.useFallback) return this.fallback.count(query);\n try {\n const result = await this.apiRequest<{ count: number }>(\"POST\", \"/audit/count\", query);\n return result.count;\n } catch {\n this.useFallback = true;\n return this.fallback.count(query);\n }\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n if (this.useFallback) return this.fallback.getById(id);\n try {\n return await this.apiRequest<AuditRecord | null>(\"GET\", `/audit/${id}`);\n } catch {\n this.useFallback = true;\n return this.fallback.getById(id);\n }\n }\n\n /** Flush buffered records to the remote API */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const batch = this.buffer.splice(0, this.batchSize);\n try {\n await this.apiRequest(\"POST\", \"/audit/batch\", { records: batch });\n } catch {\n this.useFallback = true;\n console.warn(\n `[sentinel] API unreachable, falling back to in-memory storage. ${batch.length} records buffered locally.`,\n );\n }\n }\n\n /** Stop the auto-flush timer */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n }\n\n private async apiRequest<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const init: RequestInit = {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n };\n if (body) {\n init.body = JSON.stringify(body);\n }\n\n let lastError: Error | undefined;\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n const response = await fetch(url, init);\n if (!response.ok) {\n throw new Error(`API returned ${response.status}: ${response.statusText}`);\n }\n return (await response.json()) as T;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < 2) {\n await sleep(Math.pow(2, attempt) * 1000);\n }\n }\n }\n throw lastError;\n }\n\n private startAutoFlush(intervalMs: number): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, intervalMs);\n this.flushTimer.unref();\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"]}
1
+ {"version":3,"sources":["../src/budget/spike-detector.ts","../src/budget/policies.ts","../src/budget/index.ts","../src/audit/storage/memory.ts","../src/utils/id.ts","../src/audit/enrichment.ts","../src/audit/export.ts","../src/audit/index.ts","../src/errors.ts","../src/wrapper/headers.ts","../src/wrapper/interceptor.ts","../src/wrapper/index.ts","../src/audit/storage/file.ts","../src/audit/storage/api.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { parseUSDC, formatUSDC, calculateAverage } from \"../utils/money\";\n\n/** Detects abnormal payment spikes using a rolling window of recent amounts */\nexport class SpikeDetector {\n private readonly windowSize: number;\n private readonly threshold: number;\n private readonly window: string[] = [];\n\n constructor(threshold = 3.0, windowSize = 20) {\n this.threshold = threshold;\n this.windowSize = windowSize;\n }\n\n /** Record a payment amount into the rolling window */\n record(amount: string): void {\n this.window.push(amount);\n if (this.window.length > this.windowSize) {\n this.window.shift();\n }\n }\n\n /**\n * Check if a proposed amount is a spike relative to the rolling average.\n * Returns null if no spike, or a description string if spike detected.\n * Needs at least 3 data points before spike detection activates.\n */\n check(amount: string): string | null {\n if (this.window.length < 3) return null;\n\n const avg = calculateAverage(this.window);\n const avgRaw = parseUSDC(avg);\n if (avgRaw === 0n) return null;\n\n const amountRaw = parseUSDC(amount);\n const ratio = Number(amountRaw) / Number(avgRaw);\n\n if (ratio > this.threshold) {\n return (\n `Payment $${amount} is ${ratio.toFixed(1)}x the rolling average ` +\n `$${formatUSDC(avgRaw)} (threshold: ${this.threshold}x)`\n );\n }\n return null;\n }\n\n /** Get the current rolling average */\n getAverage(): string {\n return calculateAverage(this.window);\n }\n\n /** Get the current window contents */\n getWindow(): string[] {\n return [...this.window];\n }\n\n /** Restore state from serialized data */\n loadWindow(amounts: string[]): void {\n this.window.length = 0;\n for (const a of amounts.slice(-this.windowSize)) {\n this.window.push(a);\n }\n }\n}\n","import type { BudgetPolicy } from \"../types/budget\";\n\n/** Tight limits for low-risk or testing scenarios */\nexport function conservativePolicy(): BudgetPolicy {\n return {\n maxPerCall: \"0.10\",\n maxPerHour: \"5.00\",\n maxPerDay: \"50.00\",\n spikeThreshold: 3.0,\n };\n}\n\n/** Balanced limits for typical production agents */\nexport function standardPolicy(): BudgetPolicy {\n return {\n maxPerCall: \"1.00\",\n maxPerHour: \"25.00\",\n maxPerDay: \"200.00\",\n spikeThreshold: 3.0,\n };\n}\n\n/** Higher limits for trusted, high-throughput agents */\nexport function liberalPolicy(): BudgetPolicy {\n return {\n maxPerCall: \"10.00\",\n maxPerHour: \"100.00\",\n maxPerDay: \"1000.00\",\n spikeThreshold: 5.0,\n };\n}\n\n/** No spending limits — audit logging only */\nexport function unlimitedPolicy(): BudgetPolicy {\n return {};\n}\n\n/** Build a custom policy by overriding defaults */\nexport function customPolicy(overrides: Partial<BudgetPolicy>): BudgetPolicy {\n return { ...standardPolicy(), ...overrides };\n}\n","import type { BudgetPolicy, BudgetState, BudgetViolation, BudgetEvaluation } from \"../types/budget\";\nimport type { PaymentContext } from \"../types/index\";\nimport { addUSDC, compareUSDC } from \"../utils/money\";\nimport { getHourStart, getDayStart } from \"../utils/time\";\nimport { SpikeDetector } from \"./spike-detector\";\n\n/** Enforces budget policies by evaluating proposed payments against spending state */\nexport class BudgetManager {\n private state: BudgetState;\n private readonly policy: BudgetPolicy;\n private readonly spikeDetector: SpikeDetector;\n\n constructor(policy: BudgetPolicy) {\n this.policy = policy;\n this.spikeDetector = new SpikeDetector(\n policy.spikeThreshold ?? 3.0,\n );\n const now = Date.now();\n this.state = {\n totalSpent: \"0.000000\",\n hourlySpent: \"0.000000\",\n dailySpent: \"0.000000\",\n callCount: 0,\n lastReset: { hourly: getHourStart(now), daily: getDayStart(now) },\n rollingAverage: \"0.000000\",\n rollingWindow: [],\n };\n }\n\n /**\n * Evaluate a proposed payment against the budget policy.\n * Called BEFORE every payment. Returns allow/deny with reason.\n */\n evaluate(context: PaymentContext): BudgetEvaluation {\n this.maybeResetWindows();\n const warnings: string[] = [];\n\n // 1. Blocked endpoints (fast reject)\n if (this.policy.blockedEndpoints?.length) {\n for (const pattern of this.policy.blockedEndpoints) {\n if (endpointMatches(context.endpoint, pattern)) {\n return {\n allowed: false,\n violation: this.violation(\"blocked_endpoint\", \"0.000000\", \"0.000000\", context),\n };\n }\n }\n }\n\n // 2. Allowed endpoints whitelist\n if (this.policy.allowedEndpoints?.length) {\n const matched = this.policy.allowedEndpoints.some((p) =>\n endpointMatches(context.endpoint, p),\n );\n if (!matched) {\n return {\n allowed: false,\n violation: this.violation(\"blocked_endpoint\", \"0.000000\", \"0.000000\", context),\n };\n }\n }\n\n // 3. Per-call limit\n if (this.policy.maxPerCall) {\n if (compareUSDC(context.amount, this.policy.maxPerCall) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"per_call\", this.policy.maxPerCall, \"0.000000\", context),\n };\n }\n }\n\n // 4. Spike detection\n const spikeMsg = this.spikeDetector.check(context.amount);\n if (spikeMsg) {\n if (this.policy.spikeThreshold !== undefined) {\n return {\n allowed: false,\n violation: this.violation(\n \"spike\",\n this.spikeDetector.getAverage(),\n this.state.hourlySpent,\n context,\n ),\n };\n }\n warnings.push(spikeMsg);\n }\n\n // 5. Hourly rolling window\n if (this.policy.maxPerHour) {\n const projectedHourly = addUSDC(this.state.hourlySpent, context.amount);\n if (compareUSDC(projectedHourly, this.policy.maxPerHour) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"hourly\", this.policy.maxPerHour, this.state.hourlySpent, context),\n };\n }\n }\n\n // 6. Daily rolling window\n if (this.policy.maxPerDay) {\n const projectedDaily = addUSDC(this.state.dailySpent, context.amount);\n if (compareUSDC(projectedDaily, this.policy.maxPerDay) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"daily\", this.policy.maxPerDay, this.state.dailySpent, context),\n };\n }\n }\n\n // 7. Total lifetime cap\n if (this.policy.maxTotal) {\n const projectedTotal = addUSDC(this.state.totalSpent, context.amount);\n if (compareUSDC(projectedTotal, this.policy.maxTotal) > 0) {\n return {\n allowed: false,\n violation: this.violation(\"total\", this.policy.maxTotal, this.state.totalSpent, context),\n };\n }\n }\n\n // 8. Approval threshold\n if (this.policy.requireApproval) {\n if (compareUSDC(context.amount, this.policy.requireApproval.above) > 0) {\n return {\n allowed: false,\n violation: this.violation(\n \"approval_required\",\n this.policy.requireApproval.above,\n this.state.totalSpent,\n context,\n ),\n };\n }\n }\n\n return { allowed: true, warnings };\n }\n\n /** Record a completed payment. Called AFTER payment succeeds. */\n record(amount: string, _endpoint: string): void {\n this.maybeResetWindows();\n this.state.totalSpent = addUSDC(this.state.totalSpent, amount);\n this.state.hourlySpent = addUSDC(this.state.hourlySpent, amount);\n this.state.dailySpent = addUSDC(this.state.dailySpent, amount);\n this.state.callCount++;\n this.spikeDetector.record(amount);\n this.state.rollingAverage = this.spikeDetector.getAverage();\n this.state.rollingWindow = this.spikeDetector.getWindow();\n }\n\n /** Get current budget state (for dashboard/debugging) */\n getState(): BudgetState {\n this.maybeResetWindows();\n return { ...this.state, rollingWindow: [...this.state.rollingWindow] };\n }\n\n /** Reset spending counters for a given scope */\n reset(scope: \"hourly\" | \"daily\" | \"total\"): void {\n const now = Date.now();\n switch (scope) {\n case \"hourly\":\n this.state.hourlySpent = \"0.000000\";\n this.state.lastReset.hourly = getHourStart(now);\n break;\n case \"daily\":\n this.state.dailySpent = \"0.000000\";\n this.state.lastReset.daily = getDayStart(now);\n break;\n case \"total\":\n this.state.totalSpent = \"0.000000\";\n this.state.hourlySpent = \"0.000000\";\n this.state.dailySpent = \"0.000000\";\n this.state.callCount = 0;\n break;\n }\n }\n\n /** Serialize state for persistence */\n serialize(): string {\n return JSON.stringify(this.state);\n }\n\n /** Restore a BudgetManager from serialized state */\n static deserialize(data: string, policy: BudgetPolicy): BudgetManager {\n const mgr = new BudgetManager(policy);\n const parsed = JSON.parse(data) as BudgetState;\n mgr.state = parsed;\n mgr.spikeDetector.loadWindow(parsed.rollingWindow);\n return mgr;\n }\n\n /** Auto-reset hourly/daily windows when the time window has rolled over */\n private maybeResetWindows(): void {\n const now = Date.now();\n const hourStart = getHourStart(now);\n const dayStart = getDayStart(now);\n\n if (hourStart > this.state.lastReset.hourly) {\n this.state.hourlySpent = \"0.000000\";\n this.state.lastReset.hourly = hourStart;\n }\n if (dayStart > this.state.lastReset.daily) {\n this.state.dailySpent = \"0.000000\";\n this.state.lastReset.daily = dayStart;\n }\n }\n\n private violation(\n type: BudgetViolation[\"type\"],\n limit: string,\n current: string,\n context: PaymentContext,\n ): BudgetViolation {\n return {\n type,\n limit,\n current,\n attempted: context.amount,\n agentId: context.agentId,\n endpoint: context.endpoint,\n timestamp: Date.now(),\n };\n }\n}\n\n/** Simple glob-like endpoint matching (supports * wildcards) */\nfunction endpointMatches(url: string, pattern: string): boolean {\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\*/g, \".*\").replace(/\\?/g, \".\") + \"$\",\n );\n return regex.test(url);\n}\n\nexport { SpikeDetector } from \"./spike-detector\";\nexport {\n conservativePolicy,\n standardPolicy,\n liberalPolicy,\n unlimitedPolicy,\n customPolicy,\n} from \"./policies\";\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { parseUSDC, formatUSDC, formatUSDCHuman, compareUSDC } from \"../../utils/money\";\n\n/** In-memory audit storage with configurable capacity and FIFO eviction */\nexport class MemoryStorage implements StorageBackend {\n private readonly records = new Map<string, AuditRecord>();\n private readonly insertOrder: string[] = [];\n private readonly maxRecords: number;\n\n constructor(maxRecords = 10_000) {\n this.maxRecords = maxRecords;\n }\n\n async write(record: AuditRecord): Promise<void> {\n if (this.records.size >= this.maxRecords) {\n const oldest = this.insertOrder.shift();\n if (oldest) this.records.delete(oldest);\n }\n this.records.set(record.id, record);\n this.insertOrder.push(record.id);\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n let results = this.filter(query);\n results = this.sort(results, query.orderBy, query.order);\n const offset = query.offset ?? 0;\n const limit = query.limit ?? results.length;\n return results.slice(offset, offset + limit);\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n const records = this.filter(query);\n return buildSummary(records, query);\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n return this.filter(query).length;\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n return this.records.get(id) ?? null;\n }\n\n private filter(query: Partial<AuditQuery>): AuditRecord[] {\n return [...this.records.values()].filter((r) => matchesQuery(r, query));\n }\n\n private sort(\n records: AuditRecord[],\n orderBy?: AuditQuery[\"orderBy\"],\n order?: AuditQuery[\"order\"],\n ): AuditRecord[] {\n if (!orderBy) return records;\n const dir = order === \"desc\" ? -1 : 1;\n return records.sort((a, b) => {\n switch (orderBy) {\n case \"created_at\":\n return (a.created_at - b.created_at) * dir;\n case \"amount\":\n return compareUSDC(a.amount, b.amount) * dir;\n case \"endpoint\":\n return a.endpoint.localeCompare(b.endpoint) * dir;\n default:\n return 0;\n }\n });\n }\n}\n\n/** Shared filter logic reusable across storage backends */\nexport function matchesQuery(\n record: AuditRecord,\n query: Partial<AuditQuery>,\n): boolean {\n if (query.agentId && record.agent_id !== query.agentId) return false;\n if (query.team && record.team !== query.team) return false;\n if (query.endpoint && !record.endpoint.includes(query.endpoint)) return false;\n if (query.minAmount && compareUSDC(record.amount, query.minAmount) < 0) return false;\n if (query.maxAmount && compareUSDC(record.amount, query.maxAmount) > 0) return false;\n if (query.startTime && record.created_at < query.startTime) return false;\n if (query.endTime && record.created_at > query.endTime) return false;\n if (query.status?.length && !query.status.includes(record.policy_evaluation)) return false;\n if (query.tags?.length && !query.tags.some((t) => record.tags.includes(t))) return false;\n return true;\n}\n\n/** Build an AuditSummary from a set of records */\nexport function buildSummary(\n records: AuditRecord[],\n query: Partial<AuditQuery>,\n): AuditSummary {\n let totalRaw = 0n;\n let maxRaw = 0n;\n const agents = new Set<string>();\n const endpoints = new Set<string>();\n const byAgent: Record<string, { spend: string; count: number }> = {};\n const byEndpoint: Record<string, { spend: string; count: number }> = {};\n const byTeam: Record<string, { spend: string; count: number }> = {};\n let violations = 0;\n let minTs = Infinity;\n let maxTs = 0;\n\n for (const r of records) {\n const raw = parseUSDC(r.amount);\n totalRaw += raw;\n if (raw > maxRaw) maxRaw = raw;\n agents.add(r.agent_id);\n endpoints.add(r.endpoint);\n\n if (r.created_at < minTs) minTs = r.created_at;\n if (r.created_at > maxTs) maxTs = r.created_at;\n\n if (r.policy_evaluation === \"blocked\") violations++;\n\n // by_agent\n const agentEntry = byAgent[r.agent_id] ?? { spend: \"0.000000\", count: 0 };\n agentEntry.spend = formatUSDC(parseUSDC(agentEntry.spend) + raw);\n agentEntry.count++;\n byAgent[r.agent_id] = agentEntry;\n\n // by_endpoint\n const epEntry = byEndpoint[r.endpoint] ?? { spend: \"0.000000\", count: 0 };\n epEntry.spend = formatUSDC(parseUSDC(epEntry.spend) + raw);\n epEntry.count++;\n byEndpoint[r.endpoint] = epEntry;\n\n // by_team\n const teamKey = r.team ?? \"(none)\";\n const teamEntry = byTeam[teamKey] ?? { spend: \"0.000000\", count: 0 };\n teamEntry.spend = formatUSDC(parseUSDC(teamEntry.spend) + raw);\n teamEntry.count++;\n byTeam[teamKey] = teamEntry;\n }\n\n const count = records.length;\n return {\n total_spend: formatUSDCHuman(totalRaw),\n total_transactions: count,\n unique_endpoints: endpoints.size,\n unique_agents: agents.size,\n avg_payment: count > 0 ? formatUSDCHuman(totalRaw / BigInt(count)) : \"0.00\",\n max_payment: formatUSDCHuman(maxRaw),\n by_agent: byAgent,\n by_endpoint: byEndpoint,\n by_team: byTeam,\n violations,\n period: {\n start: query.startTime ?? (minTs === Infinity ? 0 : minTs),\n end: query.endTime ?? (maxTs === 0 ? 0 : maxTs),\n },\n };\n}\n","import { createHash, randomUUID } from \"node:crypto\";\n\n/**\n * Generate a deterministic record ID from payment attributes.\n * SHA-256 of concatenated inputs, truncated to 16 hex chars.\n */\nexport function generateRecordId(\n agentId: string,\n endpoint: string,\n timestamp: number,\n amount: string,\n): string {\n const input = `${agentId}|${endpoint}|${timestamp}|${amount}`;\n const hash = createHash(\"sha256\").update(input).digest(\"hex\");\n return hash.slice(0, 16);\n}\n\n/** Generate a random session ID (UUID v4) */\nexport function generateSessionId(): string {\n return randomUUID();\n}\n","import type { AuditRecord } from \"../types/audit\";\nimport type { PaymentContext, EnrichmentConfig } from \"../types/index\";\nimport type { SettleResponse } from \"../types/x402-stubs\";\nimport type { SentinelConfig } from \"../types/config\";\nimport { generateRecordId } from \"../utils/id\";\n\ninterface EnrichmentInput {\n context: PaymentContext;\n config: SentinelConfig;\n statusCode: number;\n responseTimeMs: number;\n settlement: SettleResponse | null;\n policyEvaluation: \"allowed\" | \"flagged\" | \"blocked\";\n budgetRemaining: string | null;\n}\n\n/** Build a complete AuditRecord from payment context and settlement data */\nexport function enrichRecord(input: EnrichmentInput): AuditRecord {\n const { context, config, statusCode, responseTimeMs, settlement, policyEvaluation, budgetRemaining } = input;\n const now = Date.now();\n const id = generateRecordId(context.agentId, context.endpoint, now, context.amount);\n\n const tags = computeTags(context, config.audit?.enrichment);\n\n return {\n id,\n agent_id: context.agentId,\n team: context.team,\n human_sponsor: config.humanSponsor ?? null,\n\n amount: context.amount,\n amount_raw: context.amountRaw,\n asset: context.asset,\n network: context.network,\n scheme: context.scheme,\n\n tx_hash: settlement?.transaction ?? null,\n payer_address: settlement?.payer ?? \"\",\n payee_address: context.payTo,\n facilitator: null,\n\n endpoint: context.endpoint,\n method: context.method,\n status_code: statusCode,\n response_time_ms: responseTimeMs,\n\n policy_id: null,\n policy_evaluation: policyEvaluation,\n budget_remaining: budgetRemaining,\n\n task_id: context.metadata[\"task_id\"] ?? null,\n session_id: context.metadata[\"session_id\"] ?? null,\n metadata: { ...context.metadata, ...config.metadata },\n\n created_at: now,\n settled_at: settlement?.success ? now : null,\n\n tags,\n };\n}\n\n/** Build an AuditRecord for a blocked payment attempt */\nexport function enrichBlockedRecord(\n context: PaymentContext,\n config: SentinelConfig,\n policyEvaluation: \"blocked\",\n): AuditRecord {\n return enrichRecord({\n context,\n config,\n statusCode: 0,\n responseTimeMs: 0,\n settlement: null,\n policyEvaluation,\n budgetRemaining: null,\n });\n}\n\nfunction computeTags(context: PaymentContext, enrichment?: EnrichmentConfig): string[] {\n const tags: string[] = [];\n\n if (enrichment?.staticTags) {\n tags.push(...enrichment.staticTags);\n }\n\n if (enrichment?.tagRules) {\n for (const rule of enrichment.tagRules) {\n const regex = new RegExp(rule.pattern);\n if (regex.test(context.endpoint)) {\n tags.push(...rule.tags);\n }\n }\n }\n\n return tags;\n}\n","import type { AuditRecord, AuditSummary } from \"../types/audit\";\n\nconst CSV_HEADERS: (keyof AuditRecord)[] = [\n \"id\", \"agent_id\", \"team\", \"human_sponsor\",\n \"amount\", \"amount_raw\", \"asset\", \"network\", \"scheme\",\n \"tx_hash\", \"payer_address\", \"payee_address\", \"facilitator\",\n \"endpoint\", \"method\", \"status_code\", \"response_time_ms\",\n \"policy_id\", \"policy_evaluation\", \"budget_remaining\",\n \"task_id\", \"session_id\",\n \"created_at\", \"settled_at\",\n];\n\n/** Convert records to a properly escaped CSV string */\nexport function toCSV(records: AuditRecord[]): string {\n const lines: string[] = [CSV_HEADERS.join(\",\")];\n\n for (const record of records) {\n const values = CSV_HEADERS.map((key) => {\n const val = record[key];\n if (val === null || val === undefined) return \"\";\n const str = String(val);\n if (str.includes(\",\") || str.includes('\"') || str.includes(\"\\n\")) {\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n }\n return str;\n });\n lines.push(values.join(\",\"));\n }\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/** Convert records to a JSON string */\nexport function toJSON(records: AuditRecord[], pretty = false): string {\n return JSON.stringify(records, null, pretty ? 2 : undefined);\n}\n\n/** Generate a human-readable text summary report */\nexport function toSummaryReport(summary: AuditSummary): string {\n const lines: string[] = [\n \"═══════════════════════════════════════════\",\n \" VALEO SENTINEL — AUDIT SUMMARY REPORT\",\n \"═══════════════════════════════════════════\",\n \"\",\n ` Period: ${new Date(summary.period.start).toISOString()} — ${new Date(summary.period.end).toISOString()}`,\n \"\",\n ` Total Spend: $${summary.total_spend}`,\n ` Total Transactions: ${summary.total_transactions}`,\n ` Unique Agents: ${summary.unique_agents}`,\n ` Unique Endpoints: ${summary.unique_endpoints}`,\n ` Avg Payment: $${summary.avg_payment}`,\n ` Max Payment: $${summary.max_payment}`,\n ` Violations: ${summary.violations}`,\n \"\",\n ];\n\n if (Object.keys(summary.by_agent).length > 0) {\n lines.push(\" ── Spend by Agent ──\");\n for (const [agent, data] of Object.entries(summary.by_agent)) {\n lines.push(` ${agent}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n if (Object.keys(summary.by_team).length > 0) {\n lines.push(\" ── Spend by Team ──\");\n for (const [team, data] of Object.entries(summary.by_team)) {\n lines.push(` ${team}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n if (Object.keys(summary.by_endpoint).length > 0) {\n lines.push(\" ── Spend by Endpoint ──\");\n for (const [ep, data] of Object.entries(summary.by_endpoint)) {\n lines.push(` ${ep}: $${data.spend} (${data.count} txns)`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"═══════════════════════════════════════════\");\n return lines.join(\"\\n\");\n}\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../types/audit\";\nimport type { AuditConfig } from \"../types/config\";\nimport type { PaymentContext } from \"../types/index\";\nimport type { BudgetViolation } from \"../types/budget\";\nimport type { StorageBackend } from \"./storage/interface\";\nimport { MemoryStorage } from \"./storage/memory\";\nimport { enrichBlockedRecord } from \"./enrichment\";\nimport { generateRecordId } from \"../utils/id\";\nimport { toCSV, toJSON } from \"./export\";\n\n/** Central audit logger — writes records to a pluggable storage backend */\nexport class AuditLogger {\n private readonly storage: StorageBackend;\n private readonly enabled: boolean;\n private readonly redactFields: string[];\n\n constructor(config?: AuditConfig) {\n this.enabled = config?.enabled !== false;\n this.storage = config?.storage ?? new MemoryStorage();\n this.redactFields = config?.redactFields ?? [];\n }\n\n /** Log a completed payment record */\n async log(record: Omit<AuditRecord, \"id\" | \"created_at\">): Promise<AuditRecord> {\n const now = Date.now();\n const full: AuditRecord = {\n ...record,\n id: generateRecordId(record.agent_id, record.endpoint, now, record.amount),\n created_at: now,\n };\n\n const redacted = this.redact(full);\n\n if (this.enabled) {\n try {\n await this.storage.write(redacted);\n } catch (err) {\n console.warn(\"[sentinel] Audit write failed (non-fatal):\", err);\n }\n }\n\n return redacted;\n }\n\n /** Log a blocked payment attempt */\n async logBlocked(\n context: PaymentContext,\n violation: BudgetViolation,\n config: { humanSponsor?: string; metadata?: Record<string, string> },\n ): Promise<AuditRecord> {\n const record = enrichBlockedRecord(context, {\n agentId: context.agentId,\n ...config,\n }, \"blocked\");\n record.metadata[\"violation_type\"] = violation.type;\n record.metadata[\"violation_limit\"] = violation.limit;\n\n if (this.enabled) {\n try {\n await this.storage.write(this.redact(record));\n } catch (err) {\n console.warn(\"[sentinel] Audit write failed (non-fatal):\", err);\n }\n }\n\n return record;\n }\n\n /** Query audit records */\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n return this.storage.query(query);\n }\n\n /** Get summary statistics */\n async summarize(query?: Partial<AuditQuery>): Promise<AuditSummary> {\n return this.storage.summarize(query ?? {});\n }\n\n /** Export records as CSV */\n async exportCSV(query?: AuditQuery): Promise<string> {\n const records = await this.storage.query(query ?? {});\n return toCSV(records);\n }\n\n /** Export records as JSON */\n async exportJSON(query?: AuditQuery): Promise<string> {\n const records = await this.storage.query(query ?? {});\n return toJSON(records, true);\n }\n\n /** Flush pending writes to storage */\n async flush(): Promise<void> {\n if (\"flush\" in this.storage && typeof this.storage.flush === \"function\") {\n await (this.storage as StorageBackend & { flush(): Promise<void> }).flush();\n }\n }\n\n /** Get the underlying storage backend (for dashboard integration) */\n getStorage(): StorageBackend {\n return this.storage;\n }\n\n private redact(record: AuditRecord): AuditRecord {\n if (this.redactFields.length === 0) return record;\n const copy = { ...record, metadata: { ...record.metadata } };\n for (const field of this.redactFields) {\n if (field in copy.metadata) {\n copy.metadata[field] = \"[REDACTED]\";\n }\n }\n return copy;\n }\n}\n","import type { AuditRecord } from \"./types/audit\";\nimport type { BudgetViolation } from \"./types/budget\";\nimport { parseUSDC } from \"./utils/money\";\n\nexport class SentinelError extends Error {\n readonly code: string;\n\n constructor(message: string, code: string) {\n super(message);\n this.name = \"SentinelError\";\n this.code = code;\n }\n}\n\nexport class SentinelBudgetError extends SentinelError {\n readonly violation: BudgetViolation;\n\n constructor(violation: BudgetViolation) {\n super(buildBudgetMessage(violation), \"BUDGET_EXCEEDED\");\n this.name = \"SentinelBudgetError\";\n this.violation = violation;\n }\n}\n\n/** Audit failures are NEVER fatal — they should be caught and logged */\nexport class SentinelAuditError extends SentinelError {\n readonly record?: Partial<AuditRecord>;\n\n constructor(message: string, record?: Partial<AuditRecord>) {\n super(message, \"AUDIT_ERROR\");\n this.name = \"SentinelAuditError\";\n this.record = record;\n }\n}\n\nexport class SentinelConfigError extends SentinelError {\n constructor(message: string) {\n super(message, \"CONFIG_ERROR\");\n this.name = \"SentinelConfigError\";\n }\n}\n\nfunction buildBudgetMessage(v: BudgetViolation): string {\n const attempted = `$${v.attempted}`;\n\n switch (v.type) {\n case \"per_call\":\n return `Budget exceeded: ${attempted} exceeds per-call limit of $${v.limit} on ${v.agentId}`;\n case \"hourly\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} hourly limit on ${v.agentId} (attempted ${attempted})`;\n case \"daily\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} daily limit on ${v.agentId} (attempted ${attempted})`;\n case \"total\":\n return `Budget exceeded: $${v.current} spent of $${v.limit} total limit on ${v.agentId} (attempted ${attempted})`;\n case \"spike\":\n return `Price spike detected: ${attempted} vs rolling average $${v.limit} on ${v.agentId}`;\n case \"blocked_endpoint\":\n return `Blocked endpoint: ${v.endpoint} is not allowed for ${v.agentId}`;\n case \"approval_required\":\n return `Approval required: ${attempted} exceeds approval threshold $${v.limit} on ${v.agentId}`;\n }\n}\n\n/** Validate a SentinelConfig at initialization time */\nexport function validateConfig(config: {\n agentId: string;\n budget?: {\n maxPerCall?: string;\n maxPerHour?: string;\n maxPerDay?: string;\n maxTotal?: string;\n spikeThreshold?: number;\n allowedEndpoints?: string[];\n blockedEndpoints?: string[];\n };\n}): void {\n if (!config.agentId || config.agentId.trim() === \"\") {\n throw new SentinelConfigError(\"agentId is required and must be non-empty\");\n }\n\n const budget = config.budget;\n if (!budget) return;\n\n const amountFields = [\"maxPerCall\", \"maxPerHour\", \"maxPerDay\", \"maxTotal\"] as const;\n for (const field of amountFields) {\n const value = budget[field];\n if (value !== undefined) {\n try {\n parseUSDC(value);\n } catch {\n throw new SentinelConfigError(\n `budget.${field} \"${value}\" is not a valid USDC amount`,\n );\n }\n }\n }\n\n if (budget.spikeThreshold !== undefined && budget.spikeThreshold <= 1.0) {\n throw new SentinelConfigError(\n `budget.spikeThreshold must be > 1.0, got ${budget.spikeThreshold}`,\n );\n }\n\n if (budget.allowedEndpoints?.length && budget.blockedEndpoints?.length) {\n throw new SentinelConfigError(\n \"Cannot set both allowedEndpoints and blockedEndpoints — use one or the other\",\n );\n }\n}\n","import type { PaymentRequired, PaymentRequirements, SettleResponse } from \"../types/x402-stubs\";\nimport { formatUSDC } from \"../utils/money\";\n\n/**\n * Decode the PAYMENT-REQUIRED header from a 402 response.\n * The header value is a Base64-encoded JSON string containing the PaymentRequired object.\n */\nexport function parsePaymentRequired(header: string): PaymentRequired {\n const json = Buffer.from(header, \"base64\").toString(\"utf-8\");\n return JSON.parse(json) as PaymentRequired;\n}\n\n/**\n * Parse a payment header that may be base64-encoded JSON or raw JSON.\n * Handles both `payment-required` and `x-payment` header formats.\n * Returns null if unparseable.\n */\nexport function parsePaymentHeader(header: string): PaymentRequired | null {\n try {\n return JSON.parse(Buffer.from(header, \"base64\").toString(\"utf-8\")) as PaymentRequired;\n } catch {\n try {\n return JSON.parse(header) as PaymentRequired;\n } catch {\n return null;\n }\n }\n}\n\n/**\n * Convert a raw base-unit amount string (e.g. \"1000000\") to a\n * human-readable USDC string (e.g. \"1.000000\").\n * USDC has 6 decimal places.\n */\nexport function normalizeAmountToUSDC(raw: string): string {\n return formatUSDC(BigInt(raw));\n}\n\n/**\n * Decode the PAYMENT-RESPONSE header from a successful (200) response.\n * The header value is a Base64-encoded JSON string containing the SettleResponse.\n * Returns null if the header is missing or unparseable.\n */\nexport function parsePaymentResponse(header: string | null): SettleResponse | null {\n if (!header) return null;\n try {\n const json = Buffer.from(header, \"base64\").toString(\"utf-8\");\n return JSON.parse(json) as SettleResponse;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract the payment amount, asset, network, and scheme from a PaymentRequirements object.\n * Uses the first entry in the accepts array.\n */\nexport function extractAmount(requirements: PaymentRequirements): {\n amount: string;\n asset: string;\n network: string;\n scheme: string;\n} {\n return {\n amount: requirements.amount,\n asset: requirements.asset,\n network: requirements.network,\n scheme: requirements.scheme,\n };\n}\n\n/**\n * Extract payment info from a PaymentRequired object (the full 402 response).\n * Picks the first accepted payment requirement.\n */\nexport function extractFromPaymentRequired(paymentRequired: PaymentRequired): {\n amount: string;\n asset: string;\n network: string;\n scheme: string;\n payTo: string;\n} | null {\n const first = paymentRequired.accepts[0];\n if (!first) return null;\n return {\n amount: first.amount,\n asset: first.asset,\n network: first.network,\n scheme: first.scheme,\n payTo: first.payTo,\n };\n}\n","import type { SentinelConfig } from \"../types/config\";\nimport type { PaymentContext } from \"../types/index\";\nimport type { AuditRecord } from \"../types/audit\";\nimport type { BudgetEvaluation, BudgetViolation } from \"../types/budget\";\nimport { BudgetManager } from \"../budget/index\";\nimport { AuditLogger } from \"../audit/index\";\nimport { enrichRecord } from \"../audit/enrichment\";\nimport {\n parsePaymentResponse,\n parsePaymentHeader,\n extractFromPaymentRequired,\n normalizeAmountToUSDC,\n} from \"./headers\";\nimport { SentinelBudgetError } from \"../errors\";\nimport { formatUSDCHuman, parseUSDC } from \"../utils/money\";\n\nexport interface InterceptorDeps {\n budgetManager: BudgetManager | null;\n auditLogger: AuditLogger;\n config: SentinelConfig;\n priceCache: Map<string, string>;\n}\n\n/**\n * Pre-request interception: build context and evaluate budget.\n * Checks endpoint allowlist/blocklist AND cumulative spend limits.\n * Amount is unknown at this point, so cumulative checks catch the case\n * where hourly/daily/total limits are already exceeded.\n */\nexport function beforeRequest(\n url: string,\n init: RequestInit | undefined,\n deps: InterceptorDeps,\n): {\n proceed: boolean;\n context: PaymentContext;\n evaluation?: BudgetEvaluation;\n} {\n const method = init?.method ?? \"GET\";\n const context: PaymentContext = {\n endpoint: url,\n method: method.toUpperCase(),\n agentId: deps.config.agentId,\n team: deps.config.team ?? null,\n amount: \"0.000000\",\n amountRaw: \"0\",\n asset: \"\",\n network: \"\",\n scheme: \"\",\n payTo: \"\",\n timestamp: Date.now(),\n metadata: { ...(deps.config.metadata ?? {}) },\n };\n\n if (deps.budgetManager) {\n const eval_ = deps.budgetManager.evaluate(context);\n if (!eval_.allowed) {\n return { proceed: false, context, evaluation: eval_ };\n }\n }\n\n return { proceed: true, context };\n}\n\n/**\n * Post-response interception: parse payment headers, evaluate full budget, log audit record.\n * Called AFTER the underlying fetch returns. Reads ONLY headers, never the body.\n *\n * May throw SentinelBudgetError if a 402 price exceeds budget limits.\n */\nexport async function afterResponse(\n response: Response,\n context: PaymentContext,\n startTime: number,\n deps: InterceptorDeps,\n): Promise<AuditRecord | null> {\n const responseTimeMs = Date.now() - startTime;\n\n // Case 1: Successful response with PAYMENT-RESPONSE header\n const paymentResponseHeader = response.headers.get(\"payment-response\");\n if (paymentResponseHeader) {\n const settlement = parsePaymentResponse(paymentResponseHeader);\n if (settlement) {\n context.network = settlement.network ?? context.network;\n\n // Recover the amount from the price cache (set during a prior 402 for this URL)\n if (context.amount === \"0.000000\") {\n const cachedAmount = deps.priceCache.get(context.endpoint);\n if (cachedAmount) {\n context.amount = cachedAmount;\n deps.priceCache.delete(context.endpoint);\n }\n }\n\n const policyEvaluation = determinePolicyEvaluation(context, deps);\n let budgetRemaining: string | null = null;\n\n if (deps.budgetManager && context.amount !== \"0.000000\") {\n deps.budgetManager.record(context.amount, context.endpoint);\n const state = deps.budgetManager.getState();\n if (deps.config.budget?.maxTotal) {\n budgetRemaining = formatUSDCHuman(\n parseUSDC(deps.config.budget.maxTotal) - parseUSDC(state.totalSpent),\n );\n }\n }\n\n const record = enrichRecord({\n context,\n config: deps.config,\n statusCode: response.status,\n responseTimeMs,\n settlement,\n policyEvaluation: policyEvaluation ? \"allowed\" : \"flagged\",\n budgetRemaining,\n });\n\n try {\n await deps.auditLogger.log(record);\n } catch (err) {\n console.warn(\"[sentinel] Audit log failed (non-fatal):\", err);\n }\n\n if (deps.config.hooks?.afterPayment) {\n try {\n await deps.config.hooks.afterPayment(record);\n } catch {\n // hooks must never block\n }\n }\n\n return record;\n }\n }\n\n // Case 2: 402 — parse price, enforce budget, cache for later\n if (response.status === 402) {\n const rawHeader =\n response.headers.get(\"payment-required\") ||\n response.headers.get(\"x-payment\");\n\n if (rawHeader) {\n try {\n const paymentRequired = parsePaymentHeader(rawHeader);\n if (paymentRequired) {\n const extracted = extractFromPaymentRequired(paymentRequired);\n if (extracted) {\n const humanAmount = normalizeAmountToUSDC(extracted.amount);\n context.amount = humanAmount;\n context.asset = extracted.asset;\n context.network = extracted.network;\n context.scheme = extracted.scheme;\n context.payTo = extracted.payTo;\n\n deps.priceCache.set(context.endpoint, humanAmount);\n }\n }\n } catch {\n // unparseable header — continue with what we have\n }\n }\n\n // Evaluate budget against the extracted price\n if (deps.budgetManager && context.amount !== \"0.000000\") {\n const eval_ = deps.budgetManager.evaluate(context);\n if (!eval_.allowed) {\n await logBlocked(context, eval_.violation, deps);\n throw new SentinelBudgetError(eval_.violation);\n }\n }\n\n const record = enrichRecord({\n context,\n config: deps.config,\n statusCode: 402,\n responseTimeMs,\n settlement: null,\n policyEvaluation: \"flagged\",\n budgetRemaining: null,\n });\n\n try {\n await deps.auditLogger.log(record);\n } catch (err) {\n console.warn(\"[sentinel] Audit log failed (non-fatal):\", err);\n }\n\n return record;\n }\n\n // Case 3: Non-payment response (no payment headers, not 402)\n return null;\n}\n\nasync function logBlocked(\n context: PaymentContext,\n violation: BudgetViolation,\n deps: InterceptorDeps,\n): Promise<void> {\n try {\n await deps.auditLogger.logBlocked(context, violation, {\n humanSponsor: deps.config.humanSponsor,\n metadata: deps.config.metadata,\n });\n } catch {\n // audit failures never block\n }\n\n if (deps.config.hooks?.onBudgetExceeded) {\n try {\n await deps.config.hooks.onBudgetExceeded(violation);\n } catch {\n // hooks must never block\n }\n }\n}\n\nfunction determinePolicyEvaluation(\n context: PaymentContext,\n deps: InterceptorDeps,\n): boolean {\n if (!deps.budgetManager || context.amount === \"0.000000\") return true;\n const eval_ = deps.budgetManager.evaluate(context);\n return eval_.allowed;\n}\n","import type { SentinelConfig } from \"../types/config\";\nimport { BudgetManager } from \"../budget/index\";\nimport { AuditLogger } from \"../audit/index\";\nimport { MemoryStorage } from \"../audit/storage/memory\";\nimport { SentinelBudgetError, validateConfig } from \"../errors\";\nimport { beforeRequest, afterResponse } from \"./interceptor\";\nimport type { InterceptorDeps } from \"./interceptor\";\n\n/**\n * Wrap an x402-enabled fetch function with Sentinel budget enforcement and audit logging.\n *\n * @param fetchWithPayment - The x402-wrapped fetch (from wrapFetchWithPayment)\n * @param config - Sentinel configuration (agent identity, budget, audit settings)\n * @returns A drop-in replacement fetch function with Sentinel instrumentation\n *\n * @example\n * ```ts\n * const fetchWithSentinel = wrapWithSentinel(fetchWithPayment, {\n * agentId: \"agent-weather-001\",\n * budget: standardPolicy(),\n * });\n * const response = await fetchWithSentinel(\"https://api.example.com/weather\");\n * ```\n */\nexport function wrapWithSentinel(\n fetchWithPayment: typeof fetch,\n config: SentinelConfig,\n): typeof fetch {\n validateConfig(config);\n\n const budgetManager = config.budget ? new BudgetManager(config.budget) : null;\n const auditLogger = new AuditLogger(config.audit ?? { enabled: true, storage: new MemoryStorage() });\n\n const priceCache = new Map<string, string>();\n const deps: InterceptorDeps = { budgetManager, auditLogger, config, priceCache };\n\n const sentinelFetch: typeof fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> => {\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.toString() : input.url;\n const startTime = Date.now();\n\n // BEFORE: Check endpoint-level budget rules\n const pre = beforeRequest(url, init, deps);\n if (!pre.proceed && pre.evaluation && !pre.evaluation.allowed) {\n const violation = pre.evaluation.violation;\n\n // Log the blocked attempt (non-fatal if logging fails)\n try {\n await auditLogger.logBlocked(pre.context, violation, {\n humanSponsor: config.humanSponsor,\n metadata: config.metadata,\n });\n } catch {\n // audit failures never block\n }\n\n if (config.hooks?.onBudgetExceeded) {\n try {\n await config.hooks.onBudgetExceeded(violation);\n } catch {\n // hooks must never block\n }\n }\n\n throw new SentinelBudgetError(violation);\n }\n\n // EXECUTE: Call the underlying x402-wrapped fetch\n let response: Response;\n try {\n response = await fetchWithPayment(input, init);\n } catch (err) {\n // Network error — log and re-throw\n try {\n const record = {\n agent_id: pre.context.agentId,\n team: pre.context.team,\n human_sponsor: config.humanSponsor ?? null,\n amount: \"0.000000\",\n amount_raw: \"0\",\n asset: \"\",\n network: \"\",\n scheme: \"\",\n tx_hash: null,\n payer_address: \"\",\n payee_address: \"\",\n facilitator: null,\n endpoint: url,\n method: pre.context.method,\n status_code: 0,\n response_time_ms: Date.now() - startTime,\n policy_id: null,\n policy_evaluation: \"flagged\" as const,\n budget_remaining: null,\n task_id: null,\n session_id: null,\n metadata: { error: err instanceof Error ? err.message : String(err) },\n settled_at: null,\n tags: [\"error\", \"network_failure\"],\n };\n await auditLogger.log(record);\n } catch {\n // audit failures never block\n }\n throw err;\n }\n\n // AFTER: Parse response headers (NEVER touch the body), log audit record\n await afterResponse(response, pre.context, startTime, deps);\n\n // Return the original Response object completely untouched\n return response;\n };\n\n return sentinelFetch;\n}\n","import { readFileSync, appendFileSync, existsSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { matchesQuery, buildSummary } from \"./memory\";\n\n/** JSONL file-based audit storage — appends one record per line */\nexport class FileStorage implements StorageBackend {\n private readonly filePath: string;\n private buffer: AuditRecord[] = [];\n private readonly flushThreshold: number;\n private flushTimer: NodeJS.Timeout | null = null;\n\n constructor(filePath = \".valeo/audit.jsonl\", flushThreshold = 100) {\n this.filePath = filePath;\n this.flushThreshold = flushThreshold;\n this.ensureDir();\n this.startAutoFlush();\n }\n\n async write(record: AuditRecord): Promise<void> {\n this.buffer.push(record);\n if (this.buffer.length >= this.flushThreshold) {\n await this.flush();\n }\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n await this.flush();\n const all = this.readAll();\n let results = all.filter((r) => matchesQuery(r, query));\n const offset = query.offset ?? 0;\n const limit = query.limit ?? results.length;\n return results.slice(offset, offset + limit);\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n await this.flush();\n const records = this.readAll().filter((r) => matchesQuery(r, query));\n return buildSummary(records, query);\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n await this.flush();\n return this.readAll().filter((r) => matchesQuery(r, query)).length;\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n await this.flush();\n return this.readAll().find((r) => r.id === id) ?? null;\n }\n\n /** Write buffered records to disk */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const lines = this.buffer.map((r) => JSON.stringify(r)).join(\"\\n\") + \"\\n\";\n appendFileSync(this.filePath, lines, \"utf-8\");\n this.buffer = [];\n }\n\n /** Stop the auto-flush timer (for clean shutdown) */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n }\n\n private readAll(): AuditRecord[] {\n if (!existsSync(this.filePath)) return [];\n const content = readFileSync(this.filePath, \"utf-8\");\n return content\n .split(\"\\n\")\n .filter((line) => line.trim().length > 0)\n .map((line) => JSON.parse(line) as AuditRecord);\n }\n\n private ensureDir(): void {\n const dir = dirname(this.filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n private startAutoFlush(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, 5_000);\n this.flushTimer.unref();\n }\n}\n","import type { AuditRecord, AuditQuery, AuditSummary } from \"../../types/audit\";\nimport type { StorageBackend } from \"./interface\";\nimport { MemoryStorage } from \"./memory\";\n\ninterface ApiStorageConfig {\n apiKey: string;\n baseUrl?: string;\n batchSize?: number;\n flushIntervalMs?: number;\n}\n\n/**\n * Remote API storage backend — batches and POSTs records to api.valeo.money.\n * Falls back to in-memory storage if the API is unreachable.\n */\nexport class ApiStorage implements StorageBackend {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly batchSize: number;\n private buffer: AuditRecord[] = [];\n private readonly fallback: MemoryStorage;\n private flushTimer: NodeJS.Timeout | null = null;\n private useFallback = false;\n\n constructor(config: ApiStorageConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? \"https://api.valeo.money/v1\";\n this.batchSize = config.batchSize ?? 50;\n this.fallback = new MemoryStorage();\n this.startAutoFlush(config.flushIntervalMs ?? 10_000);\n }\n\n async write(record: AuditRecord): Promise<void> {\n this.buffer.push(record);\n // Always write to fallback for local query support\n await this.fallback.write(record);\n if (this.buffer.length >= this.batchSize) {\n await this.flush();\n }\n }\n\n async query(query: AuditQuery): Promise<AuditRecord[]> {\n if (this.useFallback) return this.fallback.query(query);\n try {\n return await this.apiRequest<AuditRecord[]>(\"POST\", \"/audit/query\", query);\n } catch {\n this.useFallback = true;\n return this.fallback.query(query);\n }\n }\n\n async summarize(query: Partial<AuditQuery>): Promise<AuditSummary> {\n if (this.useFallback) return this.fallback.summarize(query);\n try {\n return await this.apiRequest<AuditSummary>(\"POST\", \"/audit/summarize\", query);\n } catch {\n this.useFallback = true;\n return this.fallback.summarize(query);\n }\n }\n\n async count(query: Partial<AuditQuery>): Promise<number> {\n if (this.useFallback) return this.fallback.count(query);\n try {\n const result = await this.apiRequest<{ count: number }>(\"POST\", \"/audit/count\", query);\n return result.count;\n } catch {\n this.useFallback = true;\n return this.fallback.count(query);\n }\n }\n\n async getById(id: string): Promise<AuditRecord | null> {\n if (this.useFallback) return this.fallback.getById(id);\n try {\n return await this.apiRequest<AuditRecord | null>(\"GET\", `/audit/${id}`);\n } catch {\n this.useFallback = true;\n return this.fallback.getById(id);\n }\n }\n\n /** Flush buffered records to the remote API */\n async flush(): Promise<void> {\n if (this.buffer.length === 0) return;\n const batch = this.buffer.splice(0, this.batchSize);\n try {\n await this.apiRequest(\"POST\", \"/audit/batch\", { records: batch });\n } catch {\n this.useFallback = true;\n console.warn(\n `[sentinel] API unreachable, falling back to in-memory storage. ${batch.length} records buffered locally.`,\n );\n }\n }\n\n /** Stop the auto-flush timer */\n destroy(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n }\n\n private async apiRequest<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n const init: RequestInit = {\n method,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n };\n if (body) {\n init.body = JSON.stringify(body);\n }\n\n let lastError: Error | undefined;\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n const response = await fetch(url, init);\n if (!response.ok) {\n throw new Error(`API returned ${response.status}: ${response.statusText}`);\n }\n return (await response.json()) as T;\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n if (attempt < 2) {\n await sleep(Math.pow(2, attempt) * 1000);\n }\n }\n }\n throw lastError;\n }\n\n private startAutoFlush(intervalMs: number): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, intervalMs);\n this.flushTimer.unref();\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x402sentinel/x402",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Enterprise audit, compliance, and budget enforcement for x402 payments",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",