@reinconsole/graph 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +15 -2
- package/dist/index.js +221 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Phase 3 of **[Rein](https://github.com/bugiiiii11/rein)** — the reputation graph. Guard receipts say what agents tried to spend; gate receipts say what vendors actually earned. The graph listens to both, scores every vendor and payer it has evidence on, and feeds the scores back into enforcement on both sides of the wire.
|
|
4
4
|
|
|
5
|
-
> **Status: v0.
|
|
5
|
+
> **Status: v0.2 — early open-source infrastructure, live on testnet.** APIs may change before 1.0. See the live scoreboard: [Rein console](https://app.reinconsole.com).
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
package/dist/index.d.ts
CHANGED
|
@@ -186,8 +186,21 @@ declare function reliabilityComponent(ev: SubjectEvidence): number;
|
|
|
186
186
|
* Confidence is first-class (see core ReputationScore): a thin or brand-new
|
|
187
187
|
* history yields LOW confidence rather than a misleading score, so consumers
|
|
188
188
|
* (engine sync, gate screening) can refuse to act on it. Depth of evidence
|
|
189
|
-
* saturates around 10 observations; age
|
|
190
|
-
*
|
|
189
|
+
* saturates around 10 observations; age stops mattering after a week.
|
|
190
|
+
*
|
|
191
|
+
* The 0.1 age floor is load-bearing for fairness. Both consumers act at a 0.3
|
|
192
|
+
* confidence floor (`syncVendors`, `payerCheck`), so capping a day-0 subject at
|
|
193
|
+
* 0.1 makes first-day enforcement impossible BY CONSTRUCTION rather than by
|
|
194
|
+
* arithmetic luck. It used to be 0.4, which left day-0 subjects enforceable
|
|
195
|
+
* after only 14 observations — `depth` saturates so fast that a busy vendor
|
|
196
|
+
* cleared that in seconds, and the console's own vendor sat at 0.30136 against
|
|
197
|
+
* the 0.3 floor, i.e. inside the newcomer grace period by 0.0014. Enforcement
|
|
198
|
+
* now needs roughly 1.6 days (high volume) to 2.3 days (moderate) of history:
|
|
199
|
+
* a grace period measured in time, which is what "newcomer" means.
|
|
200
|
+
*
|
|
201
|
+
* Note the constant only ever applies to subjects younger than a week — past
|
|
202
|
+
* 7 days `min(1, d/7)` saturates and age is 1.0 under any floor — so lowering
|
|
203
|
+
* it leaves every mature score bit-for-bit unchanged.
|
|
191
204
|
*/
|
|
192
205
|
declare function confidence(ev: SubjectEvidence, nowMs: number): number;
|
|
193
206
|
/** Blend all five components into the headline 0–100 score. */
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,8 @@ var DecisionId = prefixedId("dec");
|
|
|
53
53
|
var ReceiptId = prefixedId("rcp");
|
|
54
54
|
var SessionId = prefixedId("ses");
|
|
55
55
|
var GateReceiptId = prefixedId("grc");
|
|
56
|
+
var ApiKeyId = prefixedId("key");
|
|
57
|
+
var ApproverKeyId = prefixedId("apk");
|
|
56
58
|
var EnforcementMode = z.enum(["observed", "sdk", "session-key"]);
|
|
57
59
|
var AgentWallet = z.object({
|
|
58
60
|
chain: Chain,
|
|
@@ -60,12 +62,15 @@ var AgentWallet = z.object({
|
|
|
60
62
|
mode: EnforcementMode
|
|
61
63
|
});
|
|
62
64
|
var AgentStatus = z.enum(["active", "frozen"]);
|
|
65
|
+
var AgentLabel = z.string().max(40).regex(/^[a-z0-9][a-z0-9-]*$/, 'label must be a lowercase slug like "research" or "prod-trading"');
|
|
63
66
|
var Agent = z.object({
|
|
64
67
|
id: AgentId,
|
|
65
68
|
orgId: OrgId,
|
|
66
69
|
name: z.string().min(1).max(200),
|
|
67
70
|
/** On-chain ERC-8004 identity, if the agent is registered. */
|
|
68
71
|
erc8004Id: z.string().optional(),
|
|
72
|
+
/** Semantic grouping labels — the targets of policy `appliesTo.labels`. */
|
|
73
|
+
labels: z.array(AgentLabel).max(16).refine((ls) => new Set(ls).size === ls.length, { message: "labels must be unique" }).default([]),
|
|
69
74
|
wallets: z.array(AgentWallet).default([]),
|
|
70
75
|
status: AgentStatus.default("active"),
|
|
71
76
|
createdAt: z.coerce.date()
|
|
@@ -169,6 +174,17 @@ var SettledPayment = z.object({
|
|
|
169
174
|
feePaid: DecimalString.optional(),
|
|
170
175
|
confirmedAt: z.coerce.date()
|
|
171
176
|
});
|
|
177
|
+
var SettlementReport = z.object({
|
|
178
|
+
intentId: IntentId,
|
|
179
|
+
/** The settling transaction, when the observer saw one. */
|
|
180
|
+
txHash: z.string().optional(),
|
|
181
|
+
chain: Chain.optional(),
|
|
182
|
+
/** The amount as SETTLED, when known — may differ from the amount allowed. */
|
|
183
|
+
amount: DecimalString.optional(),
|
|
184
|
+
/** Free-form observer tag, e.g. "indexer", "guard", "facilitator". */
|
|
185
|
+
source: z.string().min(1).max(64).optional(),
|
|
186
|
+
confirmedAt: z.coerce.date()
|
|
187
|
+
});
|
|
172
188
|
var ReceiptSettlement = z.object({
|
|
173
189
|
txHash: z.string().optional(),
|
|
174
190
|
networkId: z.string().optional(),
|
|
@@ -227,15 +243,58 @@ var Condition = z.object({
|
|
|
227
243
|
txCount: z.object({ window: Window, gt: z.number().int().nonnegative() }).optional(),
|
|
228
244
|
/** Vendor host matches one of these patterns (supports `*` globs). */
|
|
229
245
|
vendorHostIn: z.array(z.string()).optional(),
|
|
246
|
+
/**
|
|
247
|
+
* Resource PATH matches one of these patterns (supports `*` globs, e.g.
|
|
248
|
+
* "/v1/reports/*"). A full-URL resource is reduced to its pathname before
|
|
249
|
+
* matching (see `resourcePathOf`), so the same pattern works whether the
|
|
250
|
+
* vendor declares "https://api.x.com/v1/answer" or "/v1/answer". Pair
|
|
251
|
+
* with `vendorHostIn` to scope a path rule to specific vendors.
|
|
252
|
+
*/
|
|
253
|
+
resourceIn: z.array(z.string()).optional(),
|
|
230
254
|
/** First time Rein has seen this vendor for the agent. */
|
|
231
255
|
vendorFirstSeen: z.boolean().optional(),
|
|
232
256
|
/** Vendor reputation score is below this threshold (Phase 3 hook). */
|
|
233
257
|
vendorReputationLt: z.number().min(0).max(100).optional(),
|
|
234
258
|
/** Amount is more than `gt`-times the observed median for this resource. */
|
|
235
|
-
amountVsResourceMedian: z.object({ gt: Multiplier }).optional()
|
|
259
|
+
amountVsResourceMedian: z.object({ gt: Multiplier }).optional(),
|
|
260
|
+
/**
|
|
261
|
+
* Cumulative spend attributed to THIS intent's `taskContext.taskId`
|
|
262
|
+
* (prior spend on the task plus this payment) exceeds `gt`. Scopes a
|
|
263
|
+
* budget to one unit of work rather than to a window: a research run that
|
|
264
|
+
* is meant to cost a dollar cannot quietly cost fifty, however slowly.
|
|
265
|
+
*
|
|
266
|
+
* An intent carrying no `taskId` cannot be attributed to a task, so the
|
|
267
|
+
* predicate never triggers for one. Requiring attribution is a separate,
|
|
268
|
+
* deliberate rule (deny on `taskIdMissing`), not a side effect of setting
|
|
269
|
+
* a budget — otherwise every untagged probe payment would trip every
|
|
270
|
+
* task budget in the policy.
|
|
271
|
+
*/
|
|
272
|
+
taskBudget: z.object({ gt: DecimalString }).optional(),
|
|
273
|
+
/** The intent carries no `taskContext.taskId` (or an empty one). */
|
|
274
|
+
taskIdMissing: z.boolean().optional()
|
|
236
275
|
}).refine((c) => Object.values(c).some((v) => v !== void 0), {
|
|
237
276
|
message: "a condition must specify at least one predicate"
|
|
238
277
|
});
|
|
278
|
+
var Breaker = z.object({
|
|
279
|
+
id: z.string().min(1),
|
|
280
|
+
/** The trailing span the tripwires measure over. */
|
|
281
|
+
window: Window,
|
|
282
|
+
/**
|
|
283
|
+
* Trip when the window would hold MORE than this many transactions.
|
|
284
|
+
* `10` permits ten in the window and escalates the eleventh.
|
|
285
|
+
*/
|
|
286
|
+
txCount: z.number().int().positive().optional(),
|
|
287
|
+
/**
|
|
288
|
+
* Trip when the window's spend would exceed this total. `"50.00"` permits
|
|
289
|
+
* a window totalling exactly 50.00 and escalates the payment that would
|
|
290
|
+
* carry it past. Prospective, like every other spend predicate: the
|
|
291
|
+
* payment that would breach the cap is the one that escalates, rather
|
|
292
|
+
* than the innocent one after it.
|
|
293
|
+
*/
|
|
294
|
+
valueCap: DecimalString.optional()
|
|
295
|
+
}).refine((b) => b.txCount !== void 0 || b.valueCap !== void 0, {
|
|
296
|
+
message: "a breaker must specify at least one of txCount / valueCap"
|
|
297
|
+
});
|
|
239
298
|
var Rule = z.object({
|
|
240
299
|
id: z.string().min(1),
|
|
241
300
|
allow: Condition.optional(),
|
|
@@ -248,6 +307,13 @@ var PolicyDefault = z.enum(["allow", "deny"]);
|
|
|
248
307
|
var AppliesTo = z.object({
|
|
249
308
|
/** Agent id patterns (supports `*` globs, e.g. "agt_research_*"). */
|
|
250
309
|
agents: z.array(z.string()).optional(),
|
|
310
|
+
/**
|
|
311
|
+
* Agent label patterns (supports `*` globs) — semantic targeting. Matches
|
|
312
|
+
* when the agent carries at least one label matching any pattern. Requires
|
|
313
|
+
* the agent DOCUMENT: an intent from an unregistered agent never matches a
|
|
314
|
+
* labels-targeted policy (and so fails closed when no other policy applies).
|
|
315
|
+
*/
|
|
316
|
+
labels: z.array(z.string()).optional(),
|
|
251
317
|
chains: z.array(Chain).optional()
|
|
252
318
|
});
|
|
253
319
|
var Escalation = z.object({
|
|
@@ -260,11 +326,134 @@ var Policy = z.object({
|
|
|
260
326
|
version: z.string().default("1"),
|
|
261
327
|
appliesTo: AppliesTo.default({}),
|
|
262
328
|
rules: z.array(Rule).default([]),
|
|
329
|
+
/**
|
|
330
|
+
* Behavioral breakers evaluated alongside the rules. A tripped breaker
|
|
331
|
+
* escalates at the same precedence as an `escalate` rule — so an explicit
|
|
332
|
+
* DENY still wins, and an ALLOW rule cannot wave past a tripped breaker.
|
|
333
|
+
*/
|
|
334
|
+
breakers: z.array(Breaker).default([]),
|
|
263
335
|
default: PolicyDefault.default("deny"),
|
|
264
336
|
/** Below this amount, fail-open is permitted during a policy-service outage. */
|
|
265
337
|
denyFloor: DecimalString.default("0.05"),
|
|
266
338
|
escalation: Escalation.optional()
|
|
267
339
|
});
|
|
340
|
+
var LivenessSource = z.enum([
|
|
341
|
+
/** It submitted an intent — ANY outcome, including a denial. */
|
|
342
|
+
"intent",
|
|
343
|
+
/** It reported in explicitly, having nothing to buy. */
|
|
344
|
+
"heartbeat"
|
|
345
|
+
]);
|
|
346
|
+
var DEFAULT_LIVENESS_GRACE_MS = 6e4;
|
|
347
|
+
var LivenessExpectation = z.object({
|
|
348
|
+
agentId: AgentId,
|
|
349
|
+
/** Longest silence still considered normal, e.g. '15m'. */
|
|
350
|
+
interval: Window,
|
|
351
|
+
/** Extra slack past `interval` before the silence is an alarm. */
|
|
352
|
+
graceMs: z.number().int().nonnegative().default(DEFAULT_LIVENESS_GRACE_MS),
|
|
353
|
+
/**
|
|
354
|
+
* When watching began. An agent that has NEVER been seen is measured from
|
|
355
|
+
* here, so a watch on an agent that never starts does raise an alarm — a
|
|
356
|
+
* detector that never came up is exactly as dead as one that stopped.
|
|
357
|
+
*/
|
|
358
|
+
since: z.coerce.date(),
|
|
359
|
+
/** What this agent is supposed to be doing, shown beside the alarm. */
|
|
360
|
+
note: z.string().max(200).optional()
|
|
361
|
+
});
|
|
362
|
+
var LivenessWatchInput = LivenessExpectation.omit({ since: true }).extend({
|
|
363
|
+
graceMs: z.number().int().nonnegative().optional()
|
|
364
|
+
});
|
|
365
|
+
var Heartbeat = z.object({
|
|
366
|
+
agentId: AgentId,
|
|
367
|
+
/** When the agent was alive. Defaults to arrival time. */
|
|
368
|
+
at: z.coerce.date().optional(),
|
|
369
|
+
/** Free-form note from the reporter, e.g. "poll cycle 41 ok". */
|
|
370
|
+
note: z.string().max(200).optional()
|
|
371
|
+
});
|
|
372
|
+
var LivenessStatus = z.enum(["alive", "late", "missing", "unknown"]);
|
|
373
|
+
var ApiKeyScope = z.enum(["read", "evaluate", "approve", "admin"]);
|
|
374
|
+
var ApiKey = z.object({
|
|
375
|
+
id: ApiKeyId,
|
|
376
|
+
name: z.string().min(1).max(200),
|
|
377
|
+
scopes: z.array(ApiKeyScope).min(1),
|
|
378
|
+
createdAt: z.coerce.date(),
|
|
379
|
+
/** Last successful authentication, for spotting keys that can be retired. */
|
|
380
|
+
lastUsedAt: z.coerce.date().optional(),
|
|
381
|
+
/** Set by revoke(); a revoked key never authenticates again. */
|
|
382
|
+
revokedAt: z.coerce.date().optional(),
|
|
383
|
+
/** Set by rotate(); with `previousSecretExpiresAt` it dates the overlap. */
|
|
384
|
+
rotatedAt: z.coerce.date().optional()
|
|
385
|
+
});
|
|
386
|
+
var ApiKeyRecord = ApiKey.extend({
|
|
387
|
+
secretHash: z.string(),
|
|
388
|
+
previousSecretHash: z.string().optional(),
|
|
389
|
+
previousSecretExpiresAt: z.coerce.date().optional()
|
|
390
|
+
});
|
|
391
|
+
var ApprovalVerdict = z.enum(["approve", "reject"]);
|
|
392
|
+
var ApprovalStatus = z.enum(["pending", "approved", "rejected", "expired"]);
|
|
393
|
+
var ApproverKey = z.object({
|
|
394
|
+
id: ApproverKeyId,
|
|
395
|
+
orgId: OrgId,
|
|
396
|
+
name: z.string().min(1).max(200),
|
|
397
|
+
/** ed25519 public key, SPKI PEM — the same encoding as the decision log's. */
|
|
398
|
+
publicKey: z.string().min(1),
|
|
399
|
+
algorithm: z.literal("ed25519").default("ed25519"),
|
|
400
|
+
createdAt: z.coerce.date(),
|
|
401
|
+
revokedAt: z.coerce.date().optional()
|
|
402
|
+
});
|
|
403
|
+
var ApprovalRequest = z.object({
|
|
404
|
+
/** The `escalate` decision this request answers (primary key). */
|
|
405
|
+
decisionId: DecisionId,
|
|
406
|
+
intentId: IntentId,
|
|
407
|
+
/** Binds the approval to the exact transfer — the signed bytes commit to it. */
|
|
408
|
+
intentHash: z.string(),
|
|
409
|
+
agentId: AgentId,
|
|
410
|
+
vendorHost: z.string(),
|
|
411
|
+
resource: z.string(),
|
|
412
|
+
amount: DecimalString,
|
|
413
|
+
asset: Asset,
|
|
414
|
+
chain: Chain,
|
|
415
|
+
/**
|
|
416
|
+
* Task attribution copied from the intent. Carried so an approved payment
|
|
417
|
+
* still counts against its `taskBudget` — an escalation that lost its task
|
|
418
|
+
* id on the way through would make the budget silently under-count exactly
|
|
419
|
+
* the payments a human had to look at.
|
|
420
|
+
*/
|
|
421
|
+
taskId: z.string().optional(),
|
|
422
|
+
/** Why policy escalated, verbatim from the decision. */
|
|
423
|
+
reason: z.string(),
|
|
424
|
+
/**
|
|
425
|
+
* Breaker ids whose trip contributed to this escalation. An approval of
|
|
426
|
+
* this request resets exactly these — moving their counting floor to the
|
|
427
|
+
* approval instant — so a human waving one payment through also clears the
|
|
428
|
+
* behavior that stopped it, rather than being asked again immediately.
|
|
429
|
+
* Empty when ordinary rules did the escalating.
|
|
430
|
+
*/
|
|
431
|
+
breakers: z.array(z.string()).default([]),
|
|
432
|
+
status: ApprovalStatus,
|
|
433
|
+
createdAt: z.coerce.date(),
|
|
434
|
+
/** Past this instant the request denies, whatever arrives afterwards. */
|
|
435
|
+
expiresAt: z.coerce.date(),
|
|
436
|
+
resolvedAt: z.coerce.date().optional(),
|
|
437
|
+
/** Which registered key signed — absent when the TTL lapsed instead. */
|
|
438
|
+
approverKeyId: ApproverKeyId.optional(),
|
|
439
|
+
/**
|
|
440
|
+
* The follow-up decision appended to the chain when this resolved. That
|
|
441
|
+
* decision, not this record, is the voucher a signer verifies: the original
|
|
442
|
+
* `escalate` decision is never rewritten.
|
|
443
|
+
*/
|
|
444
|
+
finalDecisionId: DecisionId.optional()
|
|
445
|
+
});
|
|
446
|
+
var ApprovalChallenges = z.object({
|
|
447
|
+
approve: z.string(),
|
|
448
|
+
reject: z.string()
|
|
449
|
+
});
|
|
450
|
+
var ApprovalGrant = z.object({
|
|
451
|
+
decisionId: DecisionId,
|
|
452
|
+
intentHash: z.string(),
|
|
453
|
+
verdict: ApprovalVerdict,
|
|
454
|
+
approverKeyId: ApproverKeyId,
|
|
455
|
+
signature: z.string().min(1)
|
|
456
|
+
});
|
|
268
457
|
var ReputationSubject = z.object({
|
|
269
458
|
kind: z.enum(["agent", "vendor"]),
|
|
270
459
|
id: z.string()
|
|
@@ -326,6 +515,36 @@ var ReinEvent = z.discriminatedUnion("type", [
|
|
|
326
515
|
network: z.string()
|
|
327
516
|
}),
|
|
328
517
|
z.object({ type: z.literal("gate.settled"), at: z.coerce.date(), receipt: GateReceipt }),
|
|
518
|
+
z.object({
|
|
519
|
+
type: z.literal("approval.requested"),
|
|
520
|
+
at: z.coerce.date(),
|
|
521
|
+
request: ApprovalRequest
|
|
522
|
+
}),
|
|
523
|
+
z.object({
|
|
524
|
+
type: z.literal("approval.resolved"),
|
|
525
|
+
at: z.coerce.date(),
|
|
526
|
+
request: ApprovalRequest,
|
|
527
|
+
/** The follow-up allow/deny decision this resolution appended. */
|
|
528
|
+
decision: Decision
|
|
529
|
+
}),
|
|
530
|
+
z.object({
|
|
531
|
+
type: z.literal("liveness.missing"),
|
|
532
|
+
at: z.coerce.date(),
|
|
533
|
+
agentId: AgentId,
|
|
534
|
+
expectation: LivenessExpectation,
|
|
535
|
+
/** How long the agent has been silent when the alarm was raised. */
|
|
536
|
+
silentMs: z.number().int().nonnegative(),
|
|
537
|
+
/** Last sighting, absent when the agent was never seen at all. */
|
|
538
|
+
lastSeenAt: z.coerce.date().optional()
|
|
539
|
+
}),
|
|
540
|
+
z.object({
|
|
541
|
+
type: z.literal("liveness.recovered"),
|
|
542
|
+
at: z.coerce.date(),
|
|
543
|
+
agentId: AgentId,
|
|
544
|
+
/** How long the silence lasted, measured to this sighting. */
|
|
545
|
+
silentMs: z.number().int().nonnegative(),
|
|
546
|
+
source: LivenessSource
|
|
547
|
+
}),
|
|
329
548
|
z.object({
|
|
330
549
|
type: z.literal("gate.refused"),
|
|
331
550
|
at: z.coerce.date(),
|
|
@@ -542,7 +761,7 @@ function confidence(ev, nowMs) {
|
|
|
542
761
|
const observations = ev.attempts + ev.disputes + ev.endorsements + ev.shadowSpends + replays + others;
|
|
543
762
|
const depth = 1 - Math.exp(-observations / 10);
|
|
544
763
|
const knownDays = Math.max(0, nowMs - ev.firstSeenMs) / DAY_MS;
|
|
545
|
-
const age = 0.
|
|
764
|
+
const age = 0.1 + 0.9 * Math.min(1, knownDays / 7);
|
|
546
765
|
return clamp(depth * age, 0, 1);
|
|
547
766
|
}
|
|
548
767
|
function blend(components, weights) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/agent.ts","../../../packages/core/src/erc8004.ts","../../../packages/core/src/intent.ts","../../../packages/core/src/decision.ts","../../../packages/core/src/canonical.ts","../../../packages/core/src/session.ts","../../../packages/core/src/payment.ts","../../../packages/core/src/receipt.ts","../../../packages/core/src/gate-receipt.ts","../../../packages/core/src/policy.ts","../../../packages/core/src/reputation.ts","../../../packages/core/src/events.ts","../src/evidence.ts","../src/intents.ts","../src/scoring.ts","../src/graph.ts","../src/server.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Chains Rein observes/governs. x402 is multi-chain; Base and Solana ship\n * first, Polygon and BNB follow. The policy/ledger domain is rail-agnostic —\n * this enum is the only place chains are enumerated.\n */\nexport const Chain = z.enum(['base', 'solana', 'polygon', 'bnb']);\nexport type Chain = z.infer<typeof Chain>;\n\n/** Stablecoins settled over x402. */\nexport const Asset = z.enum(['USDC', 'USDT', 'EURC']);\nexport type Asset = z.infer<typeof Asset>;\n","import { z } from 'zod';\n\n/**\n * Monetary amounts in Rein are always non-negative **decimal strings**, never\n * floats. Float arithmetic silently loses precision on values like 0.1 + 0.2,\n * which is unacceptable for money. All comparison/aggregation goes through the\n * BigInt-backed helpers below.\n */\nexport const DecimalString = z\n .string()\n .regex(/^\\d+(\\.\\d+)?$/, 'must be a non-negative decimal string, e.g. \"5.00\"');\nexport type DecimalString = z.infer<typeof DecimalString>;\n\nconst DECIMAL_RE = /^\\d+(\\.\\d+)?$/;\n\nexport function isValidDecimal(value: string): boolean {\n return DECIMAL_RE.test(value);\n}\n\nfunction assertDecimal(value: string): void {\n if (!isValidDecimal(value)) {\n throw new TypeError(`invalid decimal string: ${JSON.stringify(value)}`);\n }\n}\n\nfunction fractionLength(value: string): number {\n const dot = value.indexOf('.');\n return dot === -1 ? 0 : value.length - dot - 1;\n}\n\n/** Scale a decimal string into an integer BigInt at a fixed number of fraction digits. */\nfunction toScaled(value: string, scale: number): bigint {\n const dot = value.indexOf('.');\n const intPart = dot === -1 ? value : value.slice(0, dot);\n const fracPart = dot === -1 ? '' : value.slice(dot + 1);\n const paddedFrac = (fracPart + '0'.repeat(scale)).slice(0, scale);\n return BigInt(intPart + paddedFrac);\n}\n\n/** Render a scaled BigInt back to a normalized decimal string (no trailing zeros). */\nfunction fromScaled(scaled: bigint, scale: number): string {\n if (scale === 0) return scaled.toString();\n const digits = scaled.toString().padStart(scale + 1, '0');\n const intPart = digits.slice(0, digits.length - scale);\n const fracPart = digits.slice(digits.length - scale).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/** Compare two decimal strings. Returns -1 (a<b), 0 (a==b), or 1 (a>b). */\nexport function compareDecimal(a: string, b: string): -1 | 0 | 1 {\n assertDecimal(a);\n assertDecimal(b);\n const scale = Math.max(fractionLength(a), fractionLength(b));\n const av = toScaled(a, scale);\n const bv = toScaled(b, scale);\n return av < bv ? -1 : av > bv ? 1 : 0;\n}\n\n/** Sum a list of decimal strings without floating-point error. */\nexport function sumDecimal(values: readonly string[]): string {\n if (values.length === 0) return '0';\n let scale = 0;\n for (const v of values) {\n assertDecimal(v);\n scale = Math.max(scale, fractionLength(v));\n }\n let total = 0n;\n for (const v of values) total += toScaled(v, scale);\n return fromScaled(total, scale);\n}\n\n/** Multiply two decimal strings exactly (e.g. median * \"3\" for price-sanity). */\nexport function mulDecimal(a: string, b: string): string {\n assertDecimal(a);\n assertDecimal(b);\n const scaleA = fractionLength(a);\n const scaleB = fractionLength(b);\n const product = toScaled(a, scaleA) * toScaled(b, scaleB);\n return fromScaled(product, scaleA + scaleB);\n}\n\n/** Convenience: a > b. */\nexport function gt(a: string, b: string): boolean {\n return compareDecimal(a, b) === 1;\n}\n\n/** Convenience: a < b. */\nexport function lt(a: string, b: string): boolean {\n return compareDecimal(a, b) === -1;\n}\n","/**\n * Minimal, safe glob matcher supporting only the `*` wildcard (matches any run\n * of characters, including none). Used for vendor host allowlists\n * (e.g. \"*.trusted.io\"), agent-id targeting (e.g. \"agt_research_*\"), and\n * Gate route pricing (e.g. \"/api/reports/*\").\n *\n * Deliberately NOT a regex from user input — the pattern is escaped so a\n * malicious policy value cannot inject regex behavior (ReDoS, etc.).\n */\nexport function globMatch(pattern: string, value: string): boolean {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // escape regex metachars\n const withWildcard = escaped.replace(/\\\\\\*/g, '.*'); // re-enable only `*`\n return new RegExp(`^${withWildcard}$`).test(value);\n}\n\n/** True if `value` matches any pattern in the list. */\nexport function globMatchAny(patterns: readonly string[], value: string): boolean {\n return patterns.some((p) => globMatch(p, value));\n}\n","/**\n * Minimal ULID generation, dependency-free. ULIDs are lexicographically\n * sortable (time-prefixed) and url-safe, which is why Rein uses them for all\n * primary keys instead of UUIDs. Works in Node 22 and modern browsers/edge via\n * the WebCrypto `globalThis.crypto`.\n */\n\n// Crockford's base32 alphabet (excludes I, L, O, U to avoid ambiguity).\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\nfunction encodeTime(now: number): string {\n let time = now;\n let out = '';\n for (let i = TIME_LEN - 1; i >= 0; i--) {\n out = ENCODING.charAt(time % 32) + out;\n time = Math.floor(time / 32);\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n let out = '';\n for (const byte of randomBytes(RANDOM_LEN)) {\n out += ENCODING.charAt(byte % 32);\n }\n return out;\n}\n\n/** Generate a 26-character ULID. */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime) + encodeRandom();\n}\n\n/** Generate a Stripe-style prefixed id, e.g. `newId('agt')` -> `agt_01J...`. */\nexport function newId<P extends string>(prefix: P): `${P}_${string}` {\n return `${prefix}_${ulid()}`;\n}\n","import { z } from 'zod';\n\n/** Crockford base32 ULID body (26 chars), as produced by `ulid()`. */\nconst ULID_BODY = '[0-9A-HJKMNP-TV-Z]{26}';\n\n/**\n * A zod schema for a Stripe-style prefixed ULID, e.g. `agt_01J7...`.\n * Centralizing this keeps id formats consistent across DB rows, API payloads,\n * and SDK types.\n */\nexport function prefixedId(prefix: string) {\n return z\n .string()\n .regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a \"${prefix}_\" prefixed id`);\n}\n\nexport const OrgId = prefixedId('org');\nexport const AgentId = prefixedId('agt');\nexport const PolicyId = prefixedId('pol');\nexport const IntentId = prefixedId('int');\nexport const DecisionId = prefixedId('dec');\nexport const ReceiptId = prefixedId('rcp');\nexport const SessionId = prefixedId('ses');\nexport const GateReceiptId = prefixedId('grc');\n\nexport type OrgId = z.infer<typeof OrgId>;\nexport type AgentId = z.infer<typeof AgentId>;\nexport type PolicyId = z.infer<typeof PolicyId>;\nexport type IntentId = z.infer<typeof IntentId>;\nexport type DecisionId = z.infer<typeof DecisionId>;\nexport type ReceiptId = z.infer<typeof ReceiptId>;\nexport type SessionId = z.infer<typeof SessionId>;\nexport type GateReceiptId = z.infer<typeof GateReceiptId>;\n","import { z } from 'zod';\nimport { AgentId, OrgId } from './ids.js';\nimport { Chain } from './chain.js';\n\n/**\n * Enforcement tier of a given agent wallet:\n * - `observed` — Rein sees spend on-chain but has no control (no SDK either).\n * - `sdk` — agent uses @reinconsole/sdk; advisory + observability (bypassable).\n * - `session-key` — signer-level scope; out-of-policy txs cannot be signed.\n */\nexport const EnforcementMode = z.enum(['observed', 'sdk', 'session-key']);\nexport type EnforcementMode = z.infer<typeof EnforcementMode>;\n\nexport const AgentWallet = z.object({\n chain: Chain,\n address: z.string().min(1),\n mode: EnforcementMode,\n});\nexport type AgentWallet = z.infer<typeof AgentWallet>;\n\nexport const AgentStatus = z.enum(['active', 'frozen']);\nexport type AgentStatus = z.infer<typeof AgentStatus>;\n\nexport const Agent = z.object({\n id: AgentId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** On-chain ERC-8004 identity, if the agent is registered. */\n erc8004Id: z.string().optional(),\n wallets: z.array(AgentWallet).default([]),\n status: AgentStatus.default('active'),\n createdAt: z.coerce.date(),\n});\nexport type Agent = z.infer<typeof Agent>;\n","import { z } from 'zod';\n\n/**\n * The canonical string form of an ERC-8004 agent identity:\n *\n * eip155:{chainId}:{identityRegistry}/{tokenId}\n *\n * The part before the `/` is the spec's registry reference verbatim (the\n * `agentRegistry` field of a registration file, CAIP-10 account form); the\n * tokenId is the ERC-721 id the Identity Registry minted (`agentId` in the\n * spec). This exact string is what `Agent.erc8004Id` / `Vendor.erc8004Id`\n * carry, AND the reputation-subject id a registered agent's evidence keys by.\n *\n * Casing is load-bearing: reputation subject keys for agent-kind ids are\n * case-sensitive unless they start with `0x` (see @reinconsole/graph\n * `normalizeSubject`), and an eip155 string does not. `formatErc8004Id`\n * therefore always emits the registry address in lowercase, and consumers must\n * never hand-build the string — parse then re-format to normalize.\n */\n\nexport interface Erc8004Ref {\n /** EIP-155 chain id (e.g. 8453 Base, 84532 Base Sepolia). */\n chainId: number;\n /** Identity Registry contract address, lowercase 0x-hex. */\n registry: string;\n /** ERC-721 tokenId — the spec's `agentId`. bigint: token ids exceed 2^53. */\n tokenId: bigint;\n}\n\nconst REGISTRY_PATTERN = /^0x[0-9a-fA-F]{40}$/;\nconst ID_PATTERN = /^eip155:(\\d+):(0x[0-9a-fA-F]{40})\\/(\\d+)$/;\n\n/** Build the canonical id string. Throws on a malformed ref (programmer error). */\nexport function formatErc8004Id(ref: Erc8004Ref): string {\n if (!Number.isSafeInteger(ref.chainId) || ref.chainId < 1) {\n throw new RangeError(`erc8004: bad chainId ${ref.chainId}`);\n }\n if (!REGISTRY_PATTERN.test(ref.registry)) {\n throw new RangeError(`erc8004: bad registry address ${ref.registry}`);\n }\n if (typeof ref.tokenId !== 'bigint' || ref.tokenId < 0n) {\n // The typeof guard matters for plain-JS callers: 1.5 < 0n is legal JS and\n // false, and would mint the unparseable \"…/1.5\".\n throw new RangeError(`erc8004: bad tokenId ${ref.tokenId}`);\n }\n return `eip155:${ref.chainId}:${ref.registry.toLowerCase()}/${ref.tokenId}`;\n}\n\n/**\n * Parse a canonical (or hand-written) id string. Accepts any address casing\n * and returns a lowercase ref, or undefined when malformed — so\n * `formatErc8004Id(parseErc8004Id(x)!)` is the normalization step.\n */\nexport function parseErc8004Id(value: string): Erc8004Ref | undefined {\n const match = ID_PATTERN.exec(value);\n if (!match) return undefined;\n const chainId = Number(match[1]);\n if (!Number.isSafeInteger(chainId) || chainId < 1) return undefined;\n return {\n chainId,\n registry: match[2]!.toLowerCase(),\n tokenId: BigInt(match[3]!),\n };\n}\n\n/** Strict boundary schema for the id string (the fields themselves stay free-form). */\nexport const Erc8004Id = z\n .string()\n .refine((value) => parseErc8004Id(value) !== undefined, {\n message: 'expected \"eip155:{chainId}:{registry}/{tokenId}\"',\n });\nexport type Erc8004Id = z.infer<typeof Erc8004Id>;\n","import { z } from 'zod';\nimport { AgentId, IntentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\n\nexport const Vendor = z.object({\n host: z.string().min(1),\n address: z.string().min(1),\n erc8004Id: z.string().optional(),\n});\nexport type Vendor = z.infer<typeof Vendor>;\n\n/**\n * The observability gold: links every micro-payment back to the task and run\n * that caused it, so finance teams can answer \"what was this spend for?\".\n */\nexport const TaskContext = z.object({\n taskId: z.string().optional(),\n parentRunId: z.string().optional(),\n purpose: z.string().max(500).optional(),\n});\nexport type TaskContext = z.infer<typeof TaskContext>;\n\n/**\n * A request to spend, submitted to the policy engine BEFORE any signature is\n * released. The `nonce` provides replay protection on the signer path.\n */\nexport const PaymentIntent = z.object({\n id: IntentId,\n agentId: AgentId,\n vendor: Vendor,\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n nonce: z.string().min(1),\n createdAt: z.coerce.date(),\n});\nexport type PaymentIntent = z.infer<typeof PaymentIntent>;\n","import { z } from 'zod';\nimport { DecisionId, IntentId } from './ids.js';\n\nexport const DecisionOutcome = z.enum(['allow', 'deny', 'escalate']);\nexport type DecisionOutcome = z.infer<typeof DecisionOutcome>;\n\n/**\n * The signed, hash-chained record of a single policy evaluation. Written BEFORE\n * any signature is released. `prevHash` + `hash` form a tamper-evident chain;\n * `signature` is the policy service's signing key over `hash`. The eventual\n * on-chain `txHash` is attached later by the indexer (see SettledPayment).\n */\nexport const Decision = z.object({\n id: DecisionId,\n intentId: IntentId,\n /**\n * sha256 of the intent's canonical content (see canonical.ts). Binds the\n * decision to the exact transfer it judged — amount, recipient, asset,\n * chain — so a signer can verify an {intent, decision} pair offline as a\n * self-contained spend voucher, not just a reference by id.\n */\n intentHash: z.string(),\n outcome: DecisionOutcome,\n /** Ids of the rules that fired, for explainability. */\n matchedRules: z.array(z.string()).default([]),\n /** Human-readable explanation surfaced in the dashboard. */\n reason: z.string().optional(),\n policyId: z.string(),\n policyVersion: z.string(),\n /** Hash of the previous decision in the chain (tamper-evident log). */\n prevHash: z.string(),\n /** Hash of this decision's canonical content. */\n hash: z.string(),\n /** Service signing-key signature over `hash`. */\n signature: z.string(),\n latencyMs: z.number().nonnegative(),\n decidedAt: z.coerce.date(),\n});\nexport type Decision = z.infer<typeof Decision>;\n","import type { PaymentIntent } from './intent.js';\nimport type { DecisionOutcome } from './decision.js';\n\n/**\n * Canonical byte forms shared by the policy engine (which hashes and signs\n * them) and the signer (which verifies them offline). Field order is fixed,\n * dates are ISO strings, and absent optionals are explicit nulls, so the same\n * parsed object always canonicalizes to the same bytes — including after a\n * JSON round-trip over HTTP.\n *\n * These builders are pure (no node:crypto) so @reinconsole/core stays loadable in a\n * browser; services hash the strings with whatever sha256 they have.\n */\n\n/** Canonical form of an intent — what `Decision.intentHash` commits to. */\nexport function canonicalIntent(intent: PaymentIntent): string {\n return JSON.stringify({\n id: intent.id,\n agentId: intent.agentId,\n vendor: {\n host: intent.vendor.host,\n address: intent.vendor.address,\n erc8004Id: intent.vendor.erc8004Id ?? null,\n },\n resource: intent.resource,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: {\n taskId: intent.taskContext.taskId ?? null,\n parentRunId: intent.taskContext.parentRunId ?? null,\n purpose: intent.taskContext.purpose ?? null,\n },\n nonce: intent.nonce,\n createdAt: intent.createdAt.toISOString(),\n });\n}\n\n/** The decision fields covered by `Decision.hash` (and thus its signature). */\nexport interface DecisionContent {\n intentId: string;\n intentHash: string;\n outcome: DecisionOutcome;\n matchedRules: string[];\n policyId: string;\n policyVersion: string;\n prevHash: string;\n decidedAt: Date;\n}\n\n/** Canonical form of a decision — what `Decision.hash` is computed over. */\nexport function canonicalDecision(d: DecisionContent): string {\n return JSON.stringify({\n intentId: d.intentId,\n intentHash: d.intentHash,\n outcome: d.outcome,\n matchedRules: d.matchedRules,\n policyId: d.policyId,\n policyVersion: d.policyVersion,\n prevHash: d.prevHash,\n decidedAt: d.decidedAt.toISOString(),\n });\n}\n","import { z } from 'zod';\nimport { AgentId, SessionId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * A session-key grant: the signer tier's unit of delegated authority. The\n * agent process holds only the bearer token — the wallet key never leaves the\n * signer — and the stored record keeps a hash of the token, never the token\n * itself (it is returned exactly once, at creation).\n *\n * Caps here are the signer-side backstop UNDER whatever policy says: a\n * signature is released only when the engine allowed the intent AND the\n * session has room. Amounts are decimal strings in the asset's human units.\n */\nexport const Session = z.object({\n id: SessionId,\n agentId: AgentId,\n /** sha256 hex of the bearer token. */\n tokenHash: z.string(),\n /** Cumulative ceiling across the session's lifetime. Absent = uncapped. */\n capAmount: DecimalString.optional(),\n /** Ceiling per individual signature. Absent = uncapped. */\n maxPerPayment: DecimalString.optional(),\n expiresAt: z.coerce.date(),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type Session = z.infer<typeof Session>;\n","import { z } from 'zod';\nimport { IntentId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * On-chain confirmation of a settled payment, reconciled by the indexer against\n * the originating intent (amount + recipient + nonce, or facilitator webhook).\n */\nexport const SettledPayment = z.object({\n intentId: IntentId,\n txHash: z.string(),\n chain: Chain,\n blockNumber: z.coerce.bigint(),\n facilitator: z.string().optional(),\n feePaid: DecimalString.optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettledPayment = z.infer<typeof SettledPayment>;\n","import { z } from 'zod';\nimport { ReceiptId, IntentId, DecisionId, AgentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { TaskContext } from './intent.js';\nimport { DecisionOutcome } from './decision.js';\n\n/**\n * What the SDK reports back after settlement: the `X-PAYMENT-RESPONSE` header\n * a vendor returns once payment clears. Mock facilitators fill this in v0.1;\n * the indexer reconciles it against on-chain truth later (see SettledPayment).\n */\nexport const ReceiptSettlement = z.object({\n txHash: z.string().optional(),\n networkId: z.string().optional(),\n /** Raw header payload, kept for forensics until the indexer confirms. */\n raw: z.string().optional(),\n});\nexport type ReceiptSettlement = z.infer<typeof ReceiptSettlement>;\n\n/**\n * The SDK-side record of one guarded payment attempt: which request triggered\n * it, what the engine decided, and (if allowed and paid) how it settled.\n * Receipts are the observability primitive — every 402 the guard touches\n * produces exactly one, whether the payment was allowed or blocked.\n */\nexport const Receipt = z.object({\n id: ReceiptId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n outcome: DecisionOutcome,\n /** The URL the agent actually fetched (the paywalled resource). */\n url: z.string(),\n method: z.string().default('GET'),\n vendorHost: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n /** Human-readable explanation copied from the decision. */\n reason: z.string().optional(),\n /** Present only once a payment was made and the vendor confirmed it. */\n settlement: ReceiptSettlement.optional(),\n createdAt: z.coerce.date(),\n});\nexport type Receipt = z.infer<typeof Receipt>;\n","import { z } from 'zod';\nimport { GateReceiptId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * The vendor-side twin of `Receipt`: one settled x402 payment as the GATE saw\n * it — who paid, for which priced route, and the settlement transaction. The\n * agent-side Receipt records what an agent tried to spend; a GateReceipt\n * records what a vendor actually earned.\n */\nexport const GateReceipt = z.object({\n id: GateReceiptId,\n at: z.coerce.date(),\n /** The route pattern that priced this request, e.g. \"/api/reports/*\". */\n route: z.string().min(1),\n /** The concrete resource paid for (URL path actually requested). */\n resource: z.string().min(1),\n method: z.string().min(1),\n /** The paying wallet address, as asserted by the settled payment. */\n payer: z.string().min(1),\n payTo: z.string().min(1),\n /** Human-unit decimal amount, e.g. \"0.05\". */\n amount: DecimalString,\n /** The same amount in the asset's atomic units, e.g. \"50000\". */\n amountAtomic: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n /** Token symbol or contract address, exactly as quoted in the requirement. */\n asset: z.string().min(1),\n network: z.string().min(1),\n /** Settlement transaction hash (mock ledger or on-chain). */\n transaction: z.string().min(1),\n});\nexport type GateReceipt = z.infer<typeof GateReceipt>;\n","import { z } from 'zod';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/** A rolling-window spec, e.g. \"24h\", \"1h\", \"30m\", \"7d\". */\nexport const Window = z\n .string()\n .regex(/^\\d+[smhd]$/, 'window must be like \"30s\", \"15m\", \"1h\", or \"7d\"');\nexport type Window = z.infer<typeof Window>;\n\n/** A relative multiplier, e.g. \"3x\" (used for price-sanity checks). */\nexport const Multiplier = z.string().regex(/^\\d+(\\.\\d+)?x$/, 'multiplier must be like \"3x\"');\nexport type Multiplier = z.infer<typeof Multiplier>;\n\n/**\n * The set of predicates a rule can test. Multiple predicates in one condition\n * are ANDed together. Each maps to an evaluator in the policy engine.\n */\nexport const Condition = z\n .object({\n /** Per-transaction amount exceeds this value. */\n amountGt: DecimalString.optional(),\n /** Sum of spend in a rolling window exceeds `gt`. */\n rollingSum: z.object({ window: Window, gt: DecimalString }).optional(),\n /** Transaction count in a rolling window exceeds `gt`. */\n txCount: z.object({ window: Window, gt: z.number().int().nonnegative() }).optional(),\n /** Vendor host matches one of these patterns (supports `*` globs). */\n vendorHostIn: z.array(z.string()).optional(),\n /** First time Rein has seen this vendor for the agent. */\n vendorFirstSeen: z.boolean().optional(),\n /** Vendor reputation score is below this threshold (Phase 3 hook). */\n vendorReputationLt: z.number().min(0).max(100).optional(),\n /** Amount is more than `gt`-times the observed median for this resource. */\n amountVsResourceMedian: z.object({ gt: Multiplier }).optional(),\n })\n .refine((c) => Object.values(c).some((v) => v !== undefined), {\n message: 'a condition must specify at least one predicate',\n });\nexport type Condition = z.infer<typeof Condition>;\n\n/**\n * A single rule: an id plus exactly one action (allow / deny / escalate) whose\n * value is the condition that triggers it.\n */\nexport const Rule = z\n .object({\n id: z.string().min(1),\n allow: Condition.optional(),\n deny: Condition.optional(),\n escalate: Condition.optional(),\n })\n .refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== undefined).length === 1, {\n message: 'a rule must specify exactly one of allow / deny / escalate',\n });\nexport type Rule = z.infer<typeof Rule>;\n\nexport const PolicyDefault = z.enum(['allow', 'deny']);\nexport type PolicyDefault = z.infer<typeof PolicyDefault>;\n\nexport const AppliesTo = z.object({\n /** Agent id patterns (supports `*` globs, e.g. \"agt_research_*\"). */\n agents: z.array(z.string()).optional(),\n chains: z.array(Chain).optional(),\n});\nexport type AppliesTo = z.infer<typeof AppliesTo>;\n\nexport const Escalation = z.object({\n approvers: z.array(z.string()).default([]),\n timeoutAction: PolicyDefault.default('deny'),\n timeoutMin: z.number().int().positive().default(15),\n});\nexport type Escalation = z.infer<typeof Escalation>;\n\n/**\n * A declarative, versioned, immutable-once-active policy. Evaluation order in\n * the engine is: explicit DENY > ESCALATE > ALLOW > `default`.\n */\nexport const Policy = z.object({\n policyId: z.string().min(1),\n version: z.string().default('1'),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n default: PolicyDefault.default('deny'),\n /** Below this amount, fail-open is permitted during a policy-service outage. */\n denyFloor: DecimalString.default('0.05'),\n escalation: Escalation.optional(),\n});\nexport type Policy = z.infer<typeof Policy>;\n","import { z } from 'zod';\n\nexport const ReputationSubject = z.object({\n kind: z.enum(['agent', 'vendor']),\n id: z.string(),\n});\nexport type ReputationSubject = z.infer<typeof ReputationSubject>;\n\nexport const ReputationComponents = z.object({\n volume: z.number(),\n longevity: z.number(),\n disputeRate: z.number(),\n counterpartyQuality: z.number(),\n settlementReliability: z.number(),\n});\nexport type ReputationComponents = z.infer<typeof ReputationComponents>;\n\n/**\n * A reputation score for an agent or vendor (Phase 3 — Graph). `confidence` is\n * first-class: a thin-history subject returns LOW confidence rather than a\n * misleadingly high score, so policy can avoid both false trust and unfair\n * freezing.\n */\nexport const ReputationScore = z.object({\n subject: ReputationSubject,\n score: z.number().min(0).max(100),\n components: ReputationComponents,\n confidence: z.number().min(0).max(1),\n asOf: z.coerce.date(),\n /** Hash-anchored attestation, optionally published on-chain (ERC-8004). */\n evidenceUri: z.string().optional(),\n});\nexport type ReputationScore = z.infer<typeof ReputationScore>;\n","import { z } from 'zod';\nimport { AgentId, DecisionId, IntentId, SessionId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { PaymentIntent } from './intent.js';\nimport { Decision } from './decision.js';\nimport { SettledPayment } from './payment.js';\nimport { GateReceipt } from './gate-receipt.js';\n\n/**\n * The canonical event envelope published on the bus (NATS in production).\n * `shadow.spend` is emitted when the indexer sees on-chain spend from a managed\n * wallet with NO corresponding ALLOW decision — the bypass signal that catches\n * SDK-mode evasion and drives the upgrade to the signer tier.\n * `signature.released` / `signature.refused` are that tier's heartbeat: every\n * time the signer does or does not put a key to work, the bus knows why.\n * `gate.*` is the vendor side of the wire: every quote a Gate issues, every\n * payment it accepts, every payment it turns away.\n */\nexport const ReinEvent = z.discriminatedUnion('type', [\n z.object({ type: z.literal('intent.created'), at: z.coerce.date(), intent: PaymentIntent }),\n z.object({ type: z.literal('decision.made'), at: z.coerce.date(), decision: Decision }),\n z.object({ type: z.literal('payment.settled'), at: z.coerce.date(), payment: SettledPayment }),\n z.object({\n type: z.literal('shadow.spend'),\n at: z.coerce.date(),\n agentId: AgentId,\n txHash: z.string(),\n chain: Chain,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.released'),\n at: z.coerce.date(),\n sessionId: SessionId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"decision_replayed\" (see @reinconsole/signer). */\n code: z.string(),\n reason: z.string(),\n sessionId: SessionId.optional(),\n agentId: AgentId.optional(),\n intentId: IntentId.optional(),\n }),\n z.object({\n type: z.literal('gate.quoted'),\n at: z.coerce.date(),\n resource: z.string(),\n method: z.string(),\n amount: DecimalString,\n asset: z.string(),\n network: z.string(),\n }),\n z.object({ type: z.literal('gate.settled'), at: z.coerce.date(), receipt: GateReceipt }),\n z.object({\n type: z.literal('gate.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"payment_replayed\" (see @reinconsole/gate). */\n code: z.string(),\n reason: z.string(),\n resource: z.string(),\n /** Known only when the payment header decoded far enough to name a payer. */\n payer: z.string().optional(),\n }),\n]);\nexport type ReinEvent = z.infer<typeof ReinEvent>;\n","import { formatErc8004Id, parseErc8004Id, sumDecimal, type ReputationSubject } from '@reinconsole/core';\n\n/** A value that may be produced synchronously or awaited (durable writes). */\nexport type MaybePromise<T> = T | Promise<T>;\n\n/** One settled-money edge to a counterparty (the \"graph\" in reputation graph). */\nexport interface CounterpartyLine {\n settled: number;\n /** Settled decimal volume across this edge. */\n volume: string;\n}\n\n/**\n * Everything the graph has observed about one subject. Counters are raw and\n * append-only — scoring (scoring.ts) is a pure function over this record, so a\n * score is always re-derivable and explainable from the evidence behind it.\n */\nexport interface SubjectEvidence {\n subject: ReputationSubject;\n firstSeenMs: number;\n lastSeenMs: number;\n /** Payment attempts observed (allowed intents, presented payments). */\n attempts: number;\n /** Confirmed settlements (indexer-reconciled or gate-receipted). */\n settled: number;\n /** Settled decimal volume. */\n volume: string;\n /** Refusals by code (gate refusal codes, signer refusal codes). */\n refusals: Record<string, number>;\n /** Managed-wallet spend with no ALLOW decision behind it (bypass). */\n shadowSpends: number;\n /** Manual out-of-band reports (chargebacks, fraud complaints). */\n disputes: number;\n /** Manual out-of-band vouches. */\n endorsements: number;\n /** Who this subject has settled money with, keyed by subjectKey(). */\n counterparties: Map<string, CounterpartyLine>;\n}\n\n/**\n * Canonical subject identity. Hosts and EVM addresses are case-insensitive,\n * so they normalize to lowercase; ULID agent ids are case-sensitive and pass\n * through. ERC-8004 ids (`eip155:{chainId}:{registry}/{tokenId}`) normalize\n * via parse->format — @reinconsole/erc8004 always emits the canonical form, but this\n * is the graph's OWN boundary (remote producers hit POST /v1/links with\n * hand-built strings), and a checksummed registry or zero-padded tokenId\n * variant must not mint a split subject row. Note the two id spaces under\n * kind \"agent\": the engine names agents by ULID, a gate names them by paying\n * wallet — ERC-8004 linking (S17) folds both into the on-chain identity.\n */\nexport function normalizeSubject(subject: ReputationSubject): ReputationSubject {\n if (subject.id.startsWith('eip155:')) {\n const ref = parseErc8004Id(subject.id);\n if (ref) return { kind: subject.kind, id: formatErc8004Id(ref) };\n // Malformed eip155-ish strings fall through to the plain rules below.\n }\n const id =\n subject.kind === 'vendor' || subject.id.startsWith('0x') || subject.id.startsWith('0X')\n ? subject.id.toLowerCase()\n : subject.id;\n return { kind: subject.kind, id };\n}\n\nexport function subjectKey(subject: ReputationSubject): string {\n const normal = normalizeSubject(subject);\n return `${normal.kind}:${normal.id}`;\n}\n\n/**\n * The evidence store seam the graph depends on. Writes may be asynchronous (a\n * durable ledger persists behind them); reads are synchronous from the\n * hydrated working set so `score()` / `payerCheck()` stay sync in the gate hot\n * path. Mutations are explicit, atomic operations rather than a returned record\n * the caller mutates — that is what lets a durable implementation persist them.\n */\nexport interface EvidenceLedgerPort {\n /** A payment attempt (allowed intent / presented payment). */\n recordAttempt(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /** A confirmed settlement between two subjects (credits both sides + the edge). */\n recordSettlement(\n a: ReputationSubject,\n b: ReputationSubject,\n amount: string,\n atMs: number,\n ): MaybePromise<void>;\n /** A refusal against a subject, by code. */\n recordRefusal(subject: ReputationSubject, code: string, atMs: number): MaybePromise<void>;\n /** Managed-wallet spend with no ALLOW behind it. */\n recordShadowSpend(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /** An out-of-band dispute. */\n recordDispute(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /** An out-of-band endorsement. */\n recordEndorsement(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /**\n * Fold everything known about `alias` into `canonical` and forget the alias:\n * counters sum, volumes add, first/last seen widen, and settled-money edges\n * re-key on BOTH endpoints (peers that pointed at the alias now point at the\n * canonical subject). No-op when the alias has no record — which makes\n * re-asserting links at boot idempotent. This is the identity-linking\n * primitive (ERC-8004: one on-chain identity, many addresses/ids).\n */\n merge(canonical: ReputationSubject, alias: ReputationSubject): MaybePromise<void>;\n get(subject: ReputationSubject): SubjectEvidence | undefined;\n getByKey(key: string): SubjectEvidence | undefined;\n all(): IterableIterator<SubjectEvidence>;\n readonly size: number;\n /**\n * Await any pending durable writes (no-op in memory). Durable\n * implementations surface write failures HERE — the graph fire-and-forgets\n * its writes (a bus handler cannot await), so flush() is the error channel.\n */\n flush?(): Promise<void>;\n}\n\n/** The evidence store: one record per subject, created on first sighting. */\nexport class EvidenceLedger implements EvidenceLedgerPort {\n private readonly records = new Map<string, SubjectEvidence>();\n\n recordAttempt(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).attempts += 1;\n }\n\n recordSettlement(\n a: ReputationSubject,\n b: ReputationSubject,\n amount: string,\n atMs: number,\n ): void {\n for (const [subject, other] of [\n [a, b],\n [b, a],\n ] as const) {\n const ev = this.touch(subject, atMs);\n ev.settled += 1;\n ev.volume = sumDecimal([ev.volume, amount]);\n const key = subjectKey(other);\n const line = ev.counterparties.get(key) ?? { settled: 0, volume: '0' };\n line.settled += 1;\n line.volume = sumDecimal([line.volume, amount]);\n ev.counterparties.set(key, line);\n }\n }\n\n recordRefusal(subject: ReputationSubject, code: string, atMs: number): void {\n const ev = this.touch(subject, atMs);\n ev.refusals[code] = (ev.refusals[code] ?? 0) + 1;\n }\n\n recordShadowSpend(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).shadowSpends += 1;\n }\n\n recordDispute(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).disputes += 1;\n }\n\n recordEndorsement(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).endorsements += 1;\n }\n\n merge(canonical: ReputationSubject, alias: ReputationSubject): void {\n const aliasKey = subjectKey(alias);\n const canonicalKey = subjectKey(canonical);\n const from = this.records.get(aliasKey);\n if (!from || aliasKey === canonicalKey) return;\n // The canonical side may have no record yet — the alias's history becomes\n // its history (same create shape as touch, seeded with the alias's window).\n const into = this.records.get(canonicalKey) ?? this.touch(canonical, from.firstSeenMs);\n into.firstSeenMs = Math.min(into.firstSeenMs, from.firstSeenMs);\n into.lastSeenMs = Math.max(into.lastSeenMs, from.lastSeenMs);\n into.attempts += from.attempts;\n into.settled += from.settled;\n into.volume = sumDecimal([into.volume, from.volume]);\n for (const [code, count] of Object.entries(from.refusals)) {\n into.refusals[code] = (into.refusals[code] ?? 0) + count;\n }\n into.shadowSpends += from.shadowSpends;\n into.disputes += from.disputes;\n into.endorsements += from.endorsements;\n for (const [peerKey, line] of from.counterparties) {\n if (peerKey === canonicalKey) continue; // a self-edge would score the subject by itself\n const existing = into.counterparties.get(peerKey) ?? { settled: 0, volume: '0' };\n existing.settled += line.settled;\n existing.volume = sumDecimal([existing.volume, line.volume]);\n into.counterparties.set(peerKey, existing);\n // Re-key the peer's reverse edge: alias -> canonical.\n const peer = this.records.get(peerKey);\n const held = peer?.counterparties.get(aliasKey);\n if (peer && held) {\n peer.counterparties.delete(aliasKey);\n const reverse = peer.counterparties.get(canonicalKey) ?? { settled: 0, volume: '0' };\n reverse.settled += held.settled;\n reverse.volume = sumDecimal([reverse.volume, held.volume]);\n peer.counterparties.set(canonicalKey, reverse);\n }\n }\n into.counterparties.delete(aliasKey);\n this.records.delete(aliasKey);\n }\n\n get(subject: ReputationSubject): SubjectEvidence | undefined {\n return this.records.get(subjectKey(subject));\n }\n\n getByKey(key: string): SubjectEvidence | undefined {\n return this.records.get(key);\n }\n\n all(): IterableIterator<SubjectEvidence> {\n return this.records.values();\n }\n\n get size(): number {\n return this.records.size;\n }\n\n /**\n * Insert a fully-formed record verbatim — the hydration primitive a durable\n * store uses to rebuild the working set on open. Bypasses the live counters\n * (the record already holds its accumulated state and timestamps).\n */\n load(record: SubjectEvidence): void {\n this.records.set(subjectKey(record.subject), record);\n }\n\n /** Get-or-create the record for a subject and stamp first/last seen. */\n private touch(subject: ReputationSubject, atMs: number): SubjectEvidence {\n const key = subjectKey(subject);\n let record = this.records.get(key);\n if (!record) {\n record = {\n subject: normalizeSubject(subject),\n firstSeenMs: atMs,\n lastSeenMs: atMs,\n attempts: 0,\n settled: 0,\n volume: '0',\n refusals: {},\n shadowSpends: 0,\n disputes: 0,\n endorsements: 0,\n counterparties: new Map(),\n };\n this.records.set(key, record);\n }\n if (atMs < record.firstSeenMs) record.firstSeenMs = atMs;\n if (atMs > record.lastSeenMs) record.lastSeenMs = atMs;\n return record;\n }\n}\n","import type { MaybePromise } from './evidence.js';\n\n/**\n * What an `intent.created` event tells us, kept until the matching\n * `payment.settled` (which carries only an intentId) can be attributed.\n */\nexport interface IntentFacts {\n agentId: string;\n host: string;\n amount: string;\n}\n\nexport const DEFAULT_CORRELATION_LIMIT = 10_000;\n\n/**\n * Bridges `intent.created` -> later `payment.settled`/`decision.made`. A\n * `payment.settled` event names only an intentId, so the graph remembers every\n * undecided intent until it settles. Bounded (oldest-evicted) so undecided\n * intents that never settle cannot leak. Writes may be async (a durable store\n * persists them so an in-flight intent survives a restart); reads are sync.\n */\nexport interface IntentCorrelationPort {\n remember(intentId: string, facts: IntentFacts): MaybePromise<void>;\n /** Read the facts without consuming them (decision.made reads, doesn't burn). */\n peek(intentId: string): IntentFacts | undefined;\n /** Read and consume (payment.settled attributes once, then forgets). */\n take(intentId: string): IntentFacts | undefined;\n readonly size: number;\n /**\n * Await any pending durable writes (no-op in memory). Durable\n * implementations surface write failures HERE — the graph fire-and-forgets\n * its writes, so flush() is the error channel.\n */\n flush?(): Promise<void>;\n}\n\n/** In-memory correlation map with FIFO eviction once `limit` is reached. */\nexport class InMemoryIntentStore implements IntentCorrelationPort {\n private readonly intents = new Map<string, IntentFacts>();\n\n constructor(private readonly limit: number = DEFAULT_CORRELATION_LIMIT) {}\n\n remember(intentId: string, facts: IntentFacts): void {\n // Re-remembering an existing id is an update, not a new entry — evicting\n // for it would shrink the working set below the bound (and desync a\n // durable mirror, whose upsert adds no row). Updates keep their position,\n // matching an SQL upsert leaving seq unchanged.\n if (!this.intents.has(intentId) && this.intents.size >= this.limit) {\n const oldest = this.intents.keys().next().value;\n if (oldest !== undefined) this.intents.delete(oldest);\n }\n this.intents.set(intentId, facts);\n }\n\n peek(intentId: string): IntentFacts | undefined {\n return this.intents.get(intentId);\n }\n\n take(intentId: string): IntentFacts | undefined {\n const facts = this.intents.get(intentId);\n if (facts) this.intents.delete(intentId);\n return facts;\n }\n\n get size(): number {\n return this.intents.size;\n }\n}\n","import type { ReputationComponents } from '@reinconsole/core';\nimport type { SubjectEvidence } from './evidence.js';\n\n/**\n * Component weights, summing to 1. The blend is a deliberately transparent\n * heuristic: every component is 0–100 with higher = healthier, so a score is\n * readable straight off its explanation. Sophistication can replace this\n * later without touching the evidence model — scores are pure functions of\n * evidence, never stored.\n */\nexport interface ScoreWeights {\n volume: number;\n longevity: number;\n disputeRate: number;\n counterpartyQuality: number;\n settlementReliability: number;\n}\n\nexport const DEFAULT_WEIGHTS: ScoreWeights = {\n settlementReliability: 0.3,\n disputeRate: 0.3,\n volume: 0.15,\n counterpartyQuality: 0.15,\n longevity: 0.1,\n};\n\nconst DAY_MS = 86_400_000;\n\n/**\n * How much one bad observation hurts, relative to a plain refusal. Disputes\n * and shadow spends are deliberate misconduct; a replay means someone tried\n * to spend the same money twice; the rest is sloppiness.\n */\nconst BADNESS = { dispute: 4, shadowSpend: 4, replay: 3, refusal: 1, endorsementCredit: 2 };\n\nconst REPLAY_CODES = new Set(['payment_replayed', 'decision_replayed']);\n\nfunction clamp(value: number, lo: number, hi: number): number {\n return Math.min(hi, Math.max(lo, value));\n}\n\nfunction refusalCounts(ev: SubjectEvidence): { replays: number; others: number } {\n let replays = 0;\n let others = 0;\n for (const [code, count] of Object.entries(ev.refusals)) {\n if (REPLAY_CODES.has(code)) replays += count;\n else others += count;\n }\n return { replays, others };\n}\n\n/** Saturating settled-transaction volume: 0 at none, ~63 at 20, ~92 at 50. */\nexport function volumeComponent(ev: SubjectEvidence): number {\n return 100 * (1 - Math.exp(-ev.settled / 20));\n}\n\n/** How long the subject has been known: linear to 100 at 30 days. */\nexport function longevityComponent(ev: SubjectEvidence, nowMs: number): number {\n const knownDays = Math.max(0, nowMs - ev.firstSeenMs) / DAY_MS;\n return 100 * Math.min(1, knownDays / 30);\n}\n\n/**\n * Dispute hygiene (the core field is named `disputeRate`; the component is\n * stored INVERTED — 100 = a clean record — so all five components blend in\n * the same direction). Weighted badness over total interactions; manual\n * endorsements buy back a little slack.\n */\nexport function disputeComponent(ev: SubjectEvidence): number {\n const { replays, others } = refusalCounts(ev);\n const badness = Math.max(\n 0,\n ev.disputes * BADNESS.dispute +\n ev.shadowSpends * BADNESS.shadowSpend +\n replays * BADNESS.replay +\n others * BADNESS.refusal -\n ev.endorsements * BADNESS.endorsementCredit,\n );\n const interactions = Math.max(1, ev.attempts + ev.disputes + ev.endorsements);\n return 100 * Math.max(0, 1 - badness / interactions);\n}\n\n/** Settled / attempted. No attempts yet = neutral 50, not perfect 100. */\nexport function reliabilityComponent(ev: SubjectEvidence): number {\n if (ev.attempts === 0) return 50;\n return 100 * Math.min(1, ev.settled / ev.attempts);\n}\n\n/**\n * Confidence is first-class (see core ReputationScore): a thin or brand-new\n * history yields LOW confidence rather than a misleading score, so consumers\n * (engine sync, gate screening) can refuse to act on it. Depth of evidence\n * saturates around 10 observations; age discounts same-day evidence to 40%\n * and stops mattering after a week.\n */\nexport function confidence(ev: SubjectEvidence, nowMs: number): number {\n const { replays, others } = refusalCounts(ev);\n const observations =\n ev.attempts + ev.disputes + ev.endorsements + ev.shadowSpends + replays + others;\n const depth = 1 - Math.exp(-observations / 10);\n const knownDays = Math.max(0, nowMs - ev.firstSeenMs) / DAY_MS;\n const age = 0.4 + 0.6 * Math.min(1, knownDays / 7);\n return clamp(depth * age, 0, 1);\n}\n\n/** Blend all five components into the headline 0–100 score. */\nexport function blend(components: ReputationComponents, weights: ScoreWeights): number {\n const total =\n components.volume * weights.volume +\n components.longevity * weights.longevity +\n components.disputeRate * weights.disputeRate +\n components.counterpartyQuality * weights.counterpartyQuality +\n components.settlementReliability * weights.settlementReliability;\n return clamp(Math.round(total), 0, 100);\n}\n\n/**\n * The one-hop base score: the blend WITHOUT counterpartyQuality, with the\n * remaining weights renormalized. Counterparty quality for subject A averages\n * the base scores of A's counterparties — base, not full, so the computation\n * is a single hop and cycles (A pays B pays A) cannot recurse.\n */\nexport function blendBase(ev: SubjectEvidence, nowMs: number, weights: ScoreWeights): number {\n const remaining =\n weights.volume + weights.longevity + weights.disputeRate + weights.settlementReliability;\n if (remaining <= 0) return 50;\n const total =\n volumeComponent(ev) * weights.volume +\n longevityComponent(ev, nowMs) * weights.longevity +\n disputeComponent(ev) * weights.disputeRate +\n reliabilityComponent(ev) * weights.settlementReliability;\n return clamp(total / remaining, 0, 100);\n}\n","import {\n ReputationScore,\n type Receipt,\n type ReinEvent,\n type ReputationComponents,\n type ReputationSubject,\n} from '@reinconsole/core';\nimport {\n EvidenceLedger,\n normalizeSubject,\n subjectKey,\n type EvidenceLedgerPort,\n type MaybePromise,\n type SubjectEvidence,\n} from './evidence.js';\nimport {\n DEFAULT_CORRELATION_LIMIT,\n InMemoryIntentStore,\n type IntentCorrelationPort,\n} from './intents.js';\nimport {\n blend,\n blendBase,\n confidence,\n DEFAULT_WEIGHTS,\n disputeComponent,\n longevityComponent,\n reliabilityComponent,\n volumeComponent,\n type ScoreWeights,\n} from './scoring.js';\n\n/** Anything with a Rein event bus: engine, indexer, gate, signer. */\nexport interface EventSource {\n onEvent(handler: (event: ReinEvent) => void): void;\n}\n\n/**\n * Gate refusal codes that are the vendor's throttle or the vendor's rails\n * failing — not payer misbehavior. They must never become reputation evidence\n * (see the `gate.refused` case below). Mirrors @reinconsole/gate's no-fault classes;\n * kept as strings because the event schema deliberately carries codes as\n * strings (remote gates may run other versions).\n */\nconst NO_FAULT_GATE_CODES = new Set([\n 'rate_limited',\n 'velocity_exceeded',\n 'rails_unavailable',\n 'settle_unknown',\n]);\n\n/**\n * Where vendor scores land. `PolicyEngine.spend` satisfies this structurally,\n * so `graph.syncVendors(engine.spend)` closes the loop — durable when the\n * engine runs on @reinconsole/store.\n */\nexport interface VendorReputationSink {\n setVendorReputation(host: string, score: number): void | Promise<void>;\n}\n\nexport interface ReputationGraphOptions {\n weights?: Partial<ScoreWeights>;\n /** Injectable clock (scores are functions of evidence AND time). */\n now?: () => Date;\n /**\n * Max undecided intents remembered for settlement correlation. Ignored when\n * a custom `intents` store is injected (that store owns its own bound).\n */\n correlationLimit?: number;\n /**\n * Durable evidence ledger. Defaults to in-memory; @reinconsole/store provides a\n * PGlite-backed one so scores survive a restart.\n */\n ledger?: EvidenceLedgerPort;\n /** Durable intent correlation store. Defaults to in-memory (bounded by `correlationLimit`). */\n intents?: IntentCorrelationPort;\n}\n\nexport interface ManualReport {\n subject: ReputationSubject;\n kind: 'dispute' | 'endorsement';\n /** When the incident happened (defaults to now). */\n at?: Date;\n note?: string;\n}\n\nexport interface SyncedVendorScore {\n host: string;\n score: number;\n confidence: number;\n}\n\nexport interface SyncOptions {\n /**\n * Scores below this confidence are NOT pushed — the evaluator treats an\n * unknown reputation as indeterminate (never triggers vendorReputationLt),\n * and a thin history must stay unknown rather than condemn a newcomer.\n */\n minConfidence?: number;\n}\n\n/** A score plus the raw evidence it was derived from, render-ready. */\nexport interface ReputationExplanation {\n score: ReputationScore;\n weights: ScoreWeights;\n evidence: {\n attempts: number;\n settled: number;\n volume: string;\n refusals: Record<string, number>;\n shadowSpends: number;\n disputes: number;\n endorsements: number;\n firstSeen: Date;\n lastSeen: Date;\n counterparties: { subject: ReputationSubject; settled: number; volume: string }[];\n };\n}\n\n/**\n * The Rein reputation graph (Phase 3). Subscribes to the event buses both\n * sides already publish — the engine/indexer name vendors by host and agents\n * by id; a gate names payers by wallet — and accumulates per-subject evidence:\n * settlements, refusals, shadow spends, manual disputes, and settled-money\n * edges between counterparties. Scores are computed on demand (never stored)\n * from that evidence, so every number is explainable, and they feed back into\n * enforcement on both sides of the wire:\n *\n * graph.syncVendors(engine.spend) -> policies with vendorReputationLt fire\n * screen: { check: payerCheck(graph) } -> a gate turns away low-rep wallets\n *\n * Event mapping notes: engine-side evidence keys agents by ULID and vendors by\n * host; gate-side evidence keys payers by wallet and recipients by payTo\n * address — distinct subjects, so feeding one graph from BOTH buses (the\n * console world) never double-counts. `payment.settled` carries only an\n * intentId, so the graph keeps a bounded intent.created correlation map.\n * Denied decisions are deliberately NOT held against anyone: a deny means\n * policy worked, not that the agent or vendor misbehaved.\n */\nexport class ReputationGraph {\n private readonly ledger: EvidenceLedgerPort;\n private readonly intents: IntentCorrelationPort;\n private readonly weights: ScoreWeights;\n private readonly now: () => Date;\n /** aliasKey -> canonical subject. Links are derived state (an agent registry\n * or ERC-8004 lookup knows them) — re-assert at boot; merges are idempotent. */\n private readonly aliases = new Map<string, ReputationSubject>();\n\n constructor(options: ReputationGraphOptions = {}) {\n this.weights = { ...DEFAULT_WEIGHTS, ...options.weights };\n this.now = options.now ?? (() => new Date());\n this.ledger = options.ledger ?? new EvidenceLedger();\n this.intents =\n options.intents ??\n new InMemoryIntentStore(options.correlationLimit ?? DEFAULT_CORRELATION_LIMIT);\n }\n\n /** Subscribe to a bus. Returns `this` so construction chains. */\n observe(source: EventSource): this {\n source.onEvent((event) => this.ingest(event));\n return this;\n }\n\n /**\n * Fire-and-forget a port write: bus handlers cannot await, and a rejecting\n * durable write must never become an unhandled rejection (Node kills the\n * process). Failures are the port's to surface — flush() throws them.\n */\n private fire(write: () => MaybePromise<void>): void {\n // Thunk form (parity with the gate's fire, S19): a ledger that THROWS\n // synchronously must not turn an ingest into a crash — telemetry failures\n // are the port's to surface, and flush() throws them.\n try {\n void Promise.resolve(write()).catch(() => undefined);\n } catch {\n // swallowed by design — see above\n }\n }\n\n /**\n * Declare that `alias` is the same real-world party as `canonical` (the\n * ERC-8004 identity story: one identity, many addresses/ids — an engine\n * agent's ULID and its paying wallet, or a vendor's host and its payTo\n * address). Everything already known about the alias is folded into the\n * canonical subject, and all future evidence and lookups for the alias\n * resolve to it. Idempotent — re-asserting known links at boot is free.\n */\n link(canonical: ReputationSubject, alias: ReputationSubject): void {\n const target = normalizeSubject(this.resolve(canonical)); // flatten chains\n const aliasKey = subjectKey(alias);\n if (subjectKey(target) === aliasKey) return;\n this.aliases.set(aliasKey, target);\n // Repoint any alias that resolved THROUGH this alias (a->b then b->c).\n for (const [key, resolved] of this.aliases) {\n if (subjectKey(resolved) === aliasKey) this.aliases.set(key, target);\n }\n this.fire(() => this.ledger.merge(target, alias));\n }\n\n /** The canonical subject for a possibly-aliased one. */\n private resolve(subject: ReputationSubject): ReputationSubject {\n return this.aliases.get(subjectKey(subject)) ?? subject;\n }\n\n ingest(event: ReinEvent): void {\n const atMs = event.at.getTime();\n switch (event.type) {\n case 'intent.created': {\n this.fire(() =>\n this.intents.remember(event.intent.id, {\n agentId: event.intent.agentId,\n host: event.intent.vendor.host,\n amount: event.intent.amount,\n }),\n );\n return;\n }\n case 'decision.made': {\n if (event.decision.outcome !== 'allow') return;\n const facts = this.intents.peek(event.decision.intentId);\n if (!facts) return;\n this.fire(() => this.ledger.recordAttempt(this.resolve({ kind: 'agent', id: facts.agentId }), atMs));\n this.fire(() => this.ledger.recordAttempt(this.resolve({ kind: 'vendor', id: facts.host }), atMs));\n return;\n }\n case 'payment.settled': {\n const facts = this.intents.take(event.payment.intentId);\n if (!facts) return; // unattributable — no subject to credit\n const agent = this.resolve({ kind: 'agent', id: facts.agentId });\n const vendor = this.resolve({ kind: 'vendor', id: facts.host });\n this.fire(() => this.ledger.recordSettlement(agent, vendor, facts.amount, atMs));\n return;\n }\n case 'shadow.spend': {\n this.fire(() => this.ledger.recordShadowSpend(this.resolve({ kind: 'agent', id: event.agentId }), atMs));\n return;\n }\n case 'signature.refused': {\n const agentId = event.agentId; // hoisted: narrowing must survive the thunk\n if (!agentId) return;\n this.fire(() =>\n this.ledger.recordRefusal(this.resolve({ kind: 'agent', id: agentId }), event.code, atMs),\n );\n return;\n }\n case 'gate.settled': {\n const payer = this.resolve({ kind: 'agent', id: event.receipt.payer });\n const recipient = this.resolve({ kind: 'vendor', id: event.receipt.payTo });\n this.fire(() => this.ledger.recordAttempt(payer, atMs));\n this.fire(() => this.ledger.recordAttempt(recipient, atMs));\n this.fire(() => this.ledger.recordSettlement(payer, recipient, event.receipt.amount, atMs));\n return;\n }\n case 'gate.refused': {\n // No-fault refusals carry NO evidence — the gate-side parallel of\n // \"denied decisions count against no one\". Throttle codes are the\n // VENDOR'S cap (one gate's rate limit must not bleed into a payer's\n // global score); rails codes are the vendor's infrastructure failing\n // (a settle_unknown payment may even have gone through). Not even the\n // attempt is recorded: an attempt with no settlement would silently\n // drag settlementReliability down.\n if (!event.payer || NO_FAULT_GATE_CODES.has(event.code)) return;\n const payer = this.resolve({ kind: 'agent', id: event.payer });\n this.fire(() => this.ledger.recordAttempt(payer, atMs));\n this.fire(() => this.ledger.recordRefusal(payer, event.code, atMs));\n return;\n }\n // signature.released and gate.quoted carry no evidence the engine-side\n // events don't already: released duplicates the allow that preceded it,\n // and a quote names no payer.\n case 'signature.released':\n case 'gate.quoted':\n return;\n }\n }\n\n /**\n * Agent-side alternative to observing the engine bus: feed the SDK guard's\n * onReceipt straight in. Connect events OR receipts per side, not both —\n * a receipt restates the decision/settlement the bus already carried.\n */\n ingestReceipt(receipt: Receipt): void {\n if (receipt.outcome !== 'allow') return; // policy verdicts are not subject badness\n const atMs = receipt.createdAt.getTime();\n const agent = this.resolve({ kind: 'agent', id: receipt.agentId });\n const vendor = this.resolve({ kind: 'vendor', id: receipt.vendorHost });\n this.fire(() => this.ledger.recordAttempt(agent, atMs));\n this.fire(() => this.ledger.recordAttempt(vendor, atMs));\n if (receipt.settlement?.txHash) {\n this.fire(() => this.ledger.recordSettlement(agent, vendor, receipt.amount, atMs));\n }\n }\n\n /** Record an out-of-band dispute or endorsement against a subject. */\n report(input: ManualReport): void {\n const atMs = (input.at ?? this.now()).getTime();\n const subject = this.resolve(input.subject);\n if (input.kind === 'dispute') this.fire(() => this.ledger.recordDispute(subject, atMs));\n else this.fire(() => this.ledger.recordEndorsement(subject, atMs));\n }\n\n /** Await any pending durable writes (no-op for in-memory stores). */\n async flush(): Promise<void> {\n await this.ledger.flush?.();\n await this.intents.flush?.();\n }\n\n /** The score for one subject, or undefined when nothing is known (fairness).\n * Aliased subjects resolve to their canonical identity — a linked wallet\n * answers with the merged history, on both sides of the wire. */\n score(subject: ReputationSubject): ReputationScore | undefined {\n const ev = this.ledger.get(this.resolve(subject));\n return ev && this.scoreOf(ev);\n }\n\n /** All known scores, best first. */\n scores(kind?: ReputationSubject['kind']): ReputationScore[] {\n const out: ReputationScore[] = [];\n for (const ev of this.ledger.all()) {\n if (kind && ev.subject.kind !== kind) continue;\n out.push(this.scoreOf(ev));\n }\n return out.sort((a, b) => b.score - a.score);\n }\n\n /** The score plus the raw evidence behind it. */\n explain(subject: ReputationSubject): ReputationExplanation | undefined {\n const ev = this.ledger.get(this.resolve(subject));\n if (!ev) return undefined;\n return {\n score: this.scoreOf(ev),\n weights: this.weights,\n evidence: {\n attempts: ev.attempts,\n settled: ev.settled,\n volume: ev.volume,\n refusals: { ...ev.refusals },\n shadowSpends: ev.shadowSpends,\n disputes: ev.disputes,\n endorsements: ev.endorsements,\n firstSeen: new Date(ev.firstSeenMs),\n lastSeen: new Date(ev.lastSeenMs),\n counterparties: [...ev.counterparties.entries()].map(([key, line]) => {\n const [kind, ...id] = key.split(':');\n return {\n subject: { kind: kind as ReputationSubject['kind'], id: id.join(':') },\n settled: line.settled,\n volume: line.volume,\n };\n }),\n },\n };\n }\n\n /**\n * Push every vendor score that clears the confidence floor into the engine's\n * spend store (or any sink). Returns what was pushed. Low-confidence scores\n * are withheld so `vendorReputationLt` keeps treating thin histories as\n * unknown — the evaluator's no-data-no-trigger rule stays intact end to end.\n */\n async syncVendors(\n sink: VendorReputationSink,\n options: SyncOptions = {},\n ): Promise<SyncedVendorScore[]> {\n const minConfidence = options.minConfidence ?? 0.3;\n const pushed: SyncedVendorScore[] = [];\n for (const ev of this.ledger.all()) {\n if (ev.subject.kind !== 'vendor') continue;\n const score = this.scoreOf(ev);\n if (score.confidence < minConfidence) continue;\n await sink.setVendorReputation(ev.subject.id, score.score);\n pushed.push({ host: ev.subject.id, score: score.score, confidence: score.confidence });\n }\n return pushed;\n }\n\n /** Number of subjects with evidence. */\n subjects(): number {\n return this.ledger.size;\n }\n\n private scoreOf(ev: SubjectEvidence): ReputationScore {\n const nowMs = this.now().getTime();\n const components: ReputationComponents = {\n volume: volumeComponent(ev),\n longevity: longevityComponent(ev, nowMs),\n disputeRate: disputeComponent(ev),\n counterpartyQuality: this.counterpartyQuality(ev, nowMs),\n settlementReliability: reliabilityComponent(ev),\n };\n return ReputationScore.parse({\n subject: ev.subject,\n score: blend(components, this.weights),\n components,\n confidence: confidence(ev, nowMs),\n asOf: new Date(nowMs),\n });\n }\n\n /** One-hop mean of the counterparties' base scores; neutral 50 when alone. */\n private counterpartyQuality(ev: SubjectEvidence, nowMs: number): number {\n if (ev.counterparties.size === 0) return 50;\n let total = 0;\n for (const key of ev.counterparties.keys()) {\n const other = this.ledger.getByKey(key);\n total += other ? blendBase(other, nowMs, this.weights) : 50;\n }\n return total / ev.counterparties.size;\n }\n}\n\nexport interface PayerCheckOptions {\n /** Refuse payers scoring below this (default 40). */\n denyBelow?: number;\n /** Ignore scores below this confidence (default 0.3) — newcomers pass. */\n minConfidence?: number;\n}\n\n/**\n * Reputation-driven gate screening: plugs into @reinconsole/gate's `screen.check`.\n * Unknown wallets and thin histories pass (same fairness rule as the engine\n * sync); a confident low score is turned away at the door, before any\n * facilitator round-trip.\n */\nexport function payerCheck(\n graph: ReputationGraph,\n options: PayerCheckOptions = {},\n): (payer: string) => string | undefined {\n const denyBelow = options.denyBelow ?? 40;\n const minConfidence = options.minConfidence ?? 0.3;\n return (payer) => {\n const score = graph.score({ kind: 'agent', id: payer });\n if (!score || score.confidence < minConfidence) return undefined;\n if (score.score >= denyBelow) return undefined;\n return `payer reputation ${score.score} is below this gate's floor of ${denyBelow}`;\n };\n}\n","import { fileURLToPath } from 'node:url';\nimport { realpathSync } from 'node:fs';\nimport Fastify, { type FastifyInstance } from 'fastify';\nimport { z } from 'zod';\nimport { ReinEvent, ReputationSubject } from '@reinconsole/core';\nimport { ReputationGraph } from './graph.js';\n\nconst ReportInput = z.object({\n subject: ReputationSubject,\n kind: z.enum(['dispute', 'endorsement']),\n at: z.coerce.date().optional(),\n note: z.string().max(500).optional(),\n});\n\nconst ScoresQuery = z.object({ kind: z.enum(['agent', 'vendor']).optional() });\n\nconst LinkInput = z\n .object({\n canonical: ReputationSubject,\n alias: ReputationSubject,\n })\n // Merging across kinds would delete a vendor row into an agent identity\n // (silently dropping the host from syncVendors) — always a caller bug.\n .refine((l) => l.canonical.kind === l.alias.kind, {\n message: 'canonical and alias must be the same kind',\n });\n\n/**\n * Build the graph HTTP API. Remote producers POST their events here; anyone\n * can read scores with the evidence behind them. Pass a graph for tests, or\n * let it create a fresh in-memory one.\n */\nexport function buildGraphServer(graph: ReputationGraph = new ReputationGraph()): FastifyInstance {\n const app = Fastify({ logger: false });\n\n // Turn ZodErrors into clean 400s instead of 500s.\n app.setErrorHandler((err: unknown, _req, reply) => {\n if (err instanceof z.ZodError) {\n return reply.status(400).send({ error: 'validation_error', issues: err.issues });\n }\n const message = err instanceof Error ? err.message : String(err);\n return reply.status(500).send({ error: 'internal_error', message });\n });\n\n app.get('/health', () => ({ status: 'ok', subjects: graph.subjects() }));\n\n // --- Ingestion ---\n // The HTTP path can await durability even though the in-process bus path\n // cannot — flush the durable writes before answering so a POST that returns\n // 200 is persisted.\n app.post('/v1/events', async (req) => {\n const events = z.union([ReinEvent.transform((e) => [e]), z.array(ReinEvent)]).parse(req.body);\n for (const event of events) graph.ingest(event);\n await graph.flush();\n return { ingested: events.length };\n });\n\n app.post('/v1/reports', async (req) => {\n const input = ReportInput.parse(req.body);\n graph.report(input);\n await graph.flush();\n return graph.score(input.subject);\n });\n\n // --- Identity links ---\n // Unverified by DESIGN: this endpoint's trust level equals POST /v1/events —\n // whoever can post events can already fabricate the evidence itself. On-chain\n // verification belongs to the CALLER (@reinconsole/erc8004 derives link facts from\n // the Identity Registry, then asserts them here).\n app.post('/v1/links', async (req) => {\n const links = z.union([LinkInput.transform((l) => [l]), z.array(LinkInput)]).parse(req.body);\n for (const link of links) graph.link(link.canonical, link.alias);\n await graph.flush(); // durable merges land before the 200 (same contract as /v1/events)\n return { linked: links.length };\n });\n\n // --- Scores ---\n app.get('/v1/scores', (req) => {\n const { kind } = ScoresQuery.parse(req.query);\n return graph.scores(kind);\n });\n\n app.get('/v1/scores/:kind/:id', (req, reply) => {\n const subject = ReputationSubject.parse(req.params);\n const explanation = graph.explain(subject);\n if (!explanation) {\n return reply\n .status(404)\n .send({ error: 'not_found', message: `no evidence for ${subject.kind} ${subject.id}` });\n }\n return explanation;\n });\n\n return app;\n}\n\n// Start the server when run directly (tsx/node), not when imported.\nfunction isMainModule(): boolean {\n if (!process.argv[1]) return false;\n try {\n return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));\n } catch {\n return false;\n }\n}\n\nif (isMainModule()) {\n const port = Number(process.env.PORT ?? 8788);\n const host = process.env.HOST ?? '0.0.0.0';\n const app = buildGraphServer();\n app\n .listen({ port, host })\n .then(() => console.log(`[rein] graph listening on http://${host}:${port}`))\n .catch((err) => {\n console.error(err);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":["z","z","z","z","z"]}
|
|
1
|
+
{"version":3,"sources":["../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/agent.ts","../../../packages/core/src/erc8004.ts","../../../packages/core/src/intent.ts","../../../packages/core/src/decision.ts","../../../packages/core/src/canonical.ts","../../../packages/core/src/session.ts","../../../packages/core/src/payment.ts","../../../packages/core/src/receipt.ts","../../../packages/core/src/gate-receipt.ts","../../../packages/core/src/policy.ts","../../../packages/core/src/liveness.ts","../../../packages/core/src/api-key.ts","../../../packages/core/src/approval.ts","../../../packages/core/src/reputation.ts","../../../packages/core/src/events.ts","../src/evidence.ts","../src/intents.ts","../src/scoring.ts","../src/graph.ts","../src/server.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Chains Rein observes/governs. x402 is multi-chain; Base and Solana ship\n * first, Polygon and BNB follow. The policy/ledger domain is rail-agnostic —\n * this enum is the only place chains are enumerated.\n */\nexport const Chain = z.enum(['base', 'solana', 'polygon', 'bnb']);\nexport type Chain = z.infer<typeof Chain>;\n\n/** Stablecoins settled over x402. */\nexport const Asset = z.enum(['USDC', 'USDT', 'EURC']);\nexport type Asset = z.infer<typeof Asset>;\n","import { z } from 'zod';\n\n/**\n * Monetary amounts in Rein are always non-negative **decimal strings**, never\n * floats. Float arithmetic silently loses precision on values like 0.1 + 0.2,\n * which is unacceptable for money. All comparison/aggregation goes through the\n * BigInt-backed helpers below.\n */\nexport const DecimalString = z\n .string()\n .regex(/^\\d+(\\.\\d+)?$/, 'must be a non-negative decimal string, e.g. \"5.00\"');\nexport type DecimalString = z.infer<typeof DecimalString>;\n\nconst DECIMAL_RE = /^\\d+(\\.\\d+)?$/;\n\nexport function isValidDecimal(value: string): boolean {\n return DECIMAL_RE.test(value);\n}\n\nfunction assertDecimal(value: string): void {\n if (!isValidDecimal(value)) {\n throw new TypeError(`invalid decimal string: ${JSON.stringify(value)}`);\n }\n}\n\nfunction fractionLength(value: string): number {\n const dot = value.indexOf('.');\n return dot === -1 ? 0 : value.length - dot - 1;\n}\n\n/** Scale a decimal string into an integer BigInt at a fixed number of fraction digits. */\nfunction toScaled(value: string, scale: number): bigint {\n const dot = value.indexOf('.');\n const intPart = dot === -1 ? value : value.slice(0, dot);\n const fracPart = dot === -1 ? '' : value.slice(dot + 1);\n const paddedFrac = (fracPart + '0'.repeat(scale)).slice(0, scale);\n return BigInt(intPart + paddedFrac);\n}\n\n/** Render a scaled BigInt back to a normalized decimal string (no trailing zeros). */\nfunction fromScaled(scaled: bigint, scale: number): string {\n if (scale === 0) return scaled.toString();\n const digits = scaled.toString().padStart(scale + 1, '0');\n const intPart = digits.slice(0, digits.length - scale);\n const fracPart = digits.slice(digits.length - scale).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/** Compare two decimal strings. Returns -1 (a<b), 0 (a==b), or 1 (a>b). */\nexport function compareDecimal(a: string, b: string): -1 | 0 | 1 {\n assertDecimal(a);\n assertDecimal(b);\n const scale = Math.max(fractionLength(a), fractionLength(b));\n const av = toScaled(a, scale);\n const bv = toScaled(b, scale);\n return av < bv ? -1 : av > bv ? 1 : 0;\n}\n\n/** Sum a list of decimal strings without floating-point error. */\nexport function sumDecimal(values: readonly string[]): string {\n if (values.length === 0) return '0';\n let scale = 0;\n for (const v of values) {\n assertDecimal(v);\n scale = Math.max(scale, fractionLength(v));\n }\n let total = 0n;\n for (const v of values) total += toScaled(v, scale);\n return fromScaled(total, scale);\n}\n\n/** Multiply two decimal strings exactly (e.g. median * \"3\" for price-sanity). */\nexport function mulDecimal(a: string, b: string): string {\n assertDecimal(a);\n assertDecimal(b);\n const scaleA = fractionLength(a);\n const scaleB = fractionLength(b);\n const product = toScaled(a, scaleA) * toScaled(b, scaleB);\n return fromScaled(product, scaleA + scaleB);\n}\n\n/** Convenience: a > b. */\nexport function gt(a: string, b: string): boolean {\n return compareDecimal(a, b) === 1;\n}\n\n/** Convenience: a < b. */\nexport function lt(a: string, b: string): boolean {\n return compareDecimal(a, b) === -1;\n}\n","/**\n * Minimal, safe glob matcher supporting only the `*` wildcard (matches any run\n * of characters, including none). Used for vendor host allowlists\n * (e.g. \"*.trusted.io\"), agent-id targeting (e.g. \"agt_research_*\"), and\n * Gate route pricing (e.g. \"/api/reports/*\").\n *\n * Deliberately NOT a regex from user input — the pattern is escaped so a\n * malicious policy value cannot inject regex behavior (ReDoS, etc.).\n */\nexport function globMatch(pattern: string, value: string): boolean {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // escape regex metachars\n const withWildcard = escaped.replace(/\\\\\\*/g, '.*'); // re-enable only `*`\n return new RegExp(`^${withWildcard}$`).test(value);\n}\n\n/** True if `value` matches any pattern in the list. */\nexport function globMatchAny(patterns: readonly string[], value: string): boolean {\n return patterns.some((p) => globMatch(p, value));\n}\n","/**\n * Minimal ULID generation, dependency-free. ULIDs are lexicographically\n * sortable (time-prefixed) and url-safe, which is why Rein uses them for all\n * primary keys instead of UUIDs. Works in Node 22 and modern browsers/edge via\n * the WebCrypto `globalThis.crypto`.\n */\n\n// Crockford's base32 alphabet (excludes I, L, O, U to avoid ambiguity).\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\nfunction encodeTime(now: number): string {\n let time = now;\n let out = '';\n for (let i = TIME_LEN - 1; i >= 0; i--) {\n out = ENCODING.charAt(time % 32) + out;\n time = Math.floor(time / 32);\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n let out = '';\n for (const byte of randomBytes(RANDOM_LEN)) {\n out += ENCODING.charAt(byte % 32);\n }\n return out;\n}\n\n/** Generate a 26-character ULID. */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime) + encodeRandom();\n}\n\n/** Generate a Stripe-style prefixed id, e.g. `newId('agt')` -> `agt_01J...`. */\nexport function newId<P extends string>(prefix: P): `${P}_${string}` {\n return `${prefix}_${ulid()}`;\n}\n","import { z } from 'zod';\r\n\r\n/** Crockford base32 ULID body (26 chars), as produced by `ulid()`. */\r\nconst ULID_BODY = '[0-9A-HJKMNP-TV-Z]{26}';\r\n\r\n/**\r\n * A zod schema for a Stripe-style prefixed ULID, e.g. `agt_01J7...`.\r\n * Centralizing this keeps id formats consistent across DB rows, API payloads,\r\n * and SDK types.\r\n */\r\nexport function prefixedId(prefix: string) {\r\n return z\r\n .string()\r\n .regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a \"${prefix}_\" prefixed id`);\r\n}\r\n\r\nexport const OrgId = prefixedId('org');\r\nexport const AgentId = prefixedId('agt');\r\nexport const PolicyId = prefixedId('pol');\r\nexport const IntentId = prefixedId('int');\r\nexport const DecisionId = prefixedId('dec');\r\nexport const ReceiptId = prefixedId('rcp');\r\nexport const SessionId = prefixedId('ses');\r\nexport const GateReceiptId = prefixedId('grc');\r\nexport const ApiKeyId = prefixedId('key');\r\nexport const ApproverKeyId = prefixedId('apk');\r\n\r\nexport type OrgId = z.infer<typeof OrgId>;\r\nexport type AgentId = z.infer<typeof AgentId>;\r\nexport type PolicyId = z.infer<typeof PolicyId>;\r\nexport type IntentId = z.infer<typeof IntentId>;\r\nexport type DecisionId = z.infer<typeof DecisionId>;\r\nexport type ReceiptId = z.infer<typeof ReceiptId>;\r\nexport type SessionId = z.infer<typeof SessionId>;\r\nexport type GateReceiptId = z.infer<typeof GateReceiptId>;\r\nexport type ApiKeyId = z.infer<typeof ApiKeyId>;\r\nexport type ApproverKeyId = z.infer<typeof ApproverKeyId>;\r\n","import { z } from 'zod';\nimport { AgentId, OrgId } from './ids.js';\nimport { Chain } from './chain.js';\n\n/**\n * Enforcement tier of a given agent wallet:\n * - `observed` — Rein sees spend on-chain but has no control (no SDK either).\n * - `sdk` — agent uses @reinconsole/sdk; advisory + observability (bypassable).\n * - `session-key` — signer-level scope; out-of-policy txs cannot be signed.\n */\nexport const EnforcementMode = z.enum(['observed', 'sdk', 'session-key']);\nexport type EnforcementMode = z.infer<typeof EnforcementMode>;\n\nexport const AgentWallet = z.object({\n chain: Chain,\n address: z.string().min(1),\n mode: EnforcementMode,\n});\nexport type AgentWallet = z.infer<typeof AgentWallet>;\n\nexport const AgentStatus = z.enum(['active', 'frozen']);\nexport type AgentStatus = z.infer<typeof AgentStatus>;\n\n/**\n * A semantic grouping label, e.g. \"research\" or \"prod-trading\". Lowercase\n * slugs only — policy `appliesTo.labels` matches these (with globs), and a\n * case-normalization mismatch would silently un-target a policy.\n */\nexport const AgentLabel = z\n .string()\n .max(40)\n .regex(/^[a-z0-9][a-z0-9-]*$/, 'label must be a lowercase slug like \"research\" or \"prod-trading\"');\nexport type AgentLabel = z.infer<typeof AgentLabel>;\n\nexport const Agent = z.object({\n id: AgentId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** On-chain ERC-8004 identity, if the agent is registered. */\n erc8004Id: z.string().optional(),\n /** Semantic grouping labels — the targets of policy `appliesTo.labels`. */\n labels: z\n .array(AgentLabel)\n .max(16)\n .refine((ls) => new Set(ls).size === ls.length, { message: 'labels must be unique' })\n .default([]),\n wallets: z.array(AgentWallet).default([]),\n status: AgentStatus.default('active'),\n createdAt: z.coerce.date(),\n});\nexport type Agent = z.infer<typeof Agent>;\n","import { z } from 'zod';\n\n/**\n * The canonical string form of an ERC-8004 agent identity:\n *\n * eip155:{chainId}:{identityRegistry}/{tokenId}\n *\n * The part before the `/` is the spec's registry reference verbatim (the\n * `agentRegistry` field of a registration file, CAIP-10 account form); the\n * tokenId is the ERC-721 id the Identity Registry minted (`agentId` in the\n * spec). This exact string is what `Agent.erc8004Id` / `Vendor.erc8004Id`\n * carry, AND the reputation-subject id a registered agent's evidence keys by.\n *\n * Casing is load-bearing: reputation subject keys for agent-kind ids are\n * case-sensitive unless they start with `0x` (see @reinconsole/graph\n * `normalizeSubject`), and an eip155 string does not. `formatErc8004Id`\n * therefore always emits the registry address in lowercase, and consumers must\n * never hand-build the string — parse then re-format to normalize.\n */\n\nexport interface Erc8004Ref {\n /** EIP-155 chain id (e.g. 8453 Base, 84532 Base Sepolia). */\n chainId: number;\n /** Identity Registry contract address, lowercase 0x-hex. */\n registry: string;\n /** ERC-721 tokenId — the spec's `agentId`. bigint: token ids exceed 2^53. */\n tokenId: bigint;\n}\n\nconst REGISTRY_PATTERN = /^0x[0-9a-fA-F]{40}$/;\nconst ID_PATTERN = /^eip155:(\\d+):(0x[0-9a-fA-F]{40})\\/(\\d+)$/;\n\n/** Build the canonical id string. Throws on a malformed ref (programmer error). */\nexport function formatErc8004Id(ref: Erc8004Ref): string {\n if (!Number.isSafeInteger(ref.chainId) || ref.chainId < 1) {\n throw new RangeError(`erc8004: bad chainId ${ref.chainId}`);\n }\n if (!REGISTRY_PATTERN.test(ref.registry)) {\n throw new RangeError(`erc8004: bad registry address ${ref.registry}`);\n }\n if (typeof ref.tokenId !== 'bigint' || ref.tokenId < 0n) {\n // The typeof guard matters for plain-JS callers: 1.5 < 0n is legal JS and\n // false, and would mint the unparseable \"…/1.5\".\n throw new RangeError(`erc8004: bad tokenId ${ref.tokenId}`);\n }\n return `eip155:${ref.chainId}:${ref.registry.toLowerCase()}/${ref.tokenId}`;\n}\n\n/**\n * Parse a canonical (or hand-written) id string. Accepts any address casing\n * and returns a lowercase ref, or undefined when malformed — so\n * `formatErc8004Id(parseErc8004Id(x)!)` is the normalization step.\n */\nexport function parseErc8004Id(value: string): Erc8004Ref | undefined {\n const match = ID_PATTERN.exec(value);\n if (!match) return undefined;\n const chainId = Number(match[1]);\n if (!Number.isSafeInteger(chainId) || chainId < 1) return undefined;\n return {\n chainId,\n registry: match[2]!.toLowerCase(),\n tokenId: BigInt(match[3]!),\n };\n}\n\n/** Strict boundary schema for the id string (the fields themselves stay free-form). */\nexport const Erc8004Id = z\n .string()\n .refine((value) => parseErc8004Id(value) !== undefined, {\n message: 'expected \"eip155:{chainId}:{registry}/{tokenId}\"',\n });\nexport type Erc8004Id = z.infer<typeof Erc8004Id>;\n","import { z } from 'zod';\nimport { AgentId, IntentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\n\nexport const Vendor = z.object({\n host: z.string().min(1),\n address: z.string().min(1),\n erc8004Id: z.string().optional(),\n});\nexport type Vendor = z.infer<typeof Vendor>;\n\n/**\n * The observability gold: links every micro-payment back to the task and run\n * that caused it, so finance teams can answer \"what was this spend for?\".\n */\nexport const TaskContext = z.object({\n taskId: z.string().optional(),\n parentRunId: z.string().optional(),\n purpose: z.string().max(500).optional(),\n});\nexport type TaskContext = z.infer<typeof TaskContext>;\n\n/**\n * A request to spend, submitted to the policy engine BEFORE any signature is\n * released. The `nonce` provides replay protection on the signer path.\n */\nexport const PaymentIntent = z.object({\n id: IntentId,\n agentId: AgentId,\n vendor: Vendor,\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n nonce: z.string().min(1),\n createdAt: z.coerce.date(),\n});\nexport type PaymentIntent = z.infer<typeof PaymentIntent>;\n\n/**\n * Reduce an intent's `resource` to its path for policy matching. The value is\n * vendor-declared and shape-varies: the x402 spec puts a full URL in\n * `requirement.resource`, while the guard falls back to the request pathname\n * when the vendor omits it. Policies match on the PATH so authors never need\n * to know which shape a vendor emits; host targeting stays with\n * `vendorHostIn`, which is derived from the real request URL rather than the\n * vendor's own claim. Query strings do not survive the reduction.\n */\nexport function resourcePathOf(resource: string): string {\n try {\n const url = new URL(resource);\n if (url.protocol === 'http:' || url.protocol === 'https:') return url.pathname;\n } catch {\n // Not a URL — already a bare path.\n }\n return resource;\n}\n","import { z } from 'zod';\nimport { DecisionId, IntentId } from './ids.js';\n\nexport const DecisionOutcome = z.enum(['allow', 'deny', 'escalate']);\nexport type DecisionOutcome = z.infer<typeof DecisionOutcome>;\n\n/**\n * The signed, hash-chained record of a single policy evaluation. Written BEFORE\n * any signature is released. `prevHash` + `hash` form a tamper-evident chain;\n * `signature` is the policy service's signing key over `hash`. The eventual\n * on-chain `txHash` is attached later by the indexer (see SettledPayment).\n */\nexport const Decision = z.object({\n id: DecisionId,\n intentId: IntentId,\n /**\n * sha256 of the intent's canonical content (see canonical.ts). Binds the\n * decision to the exact transfer it judged — amount, recipient, asset,\n * chain — so a signer can verify an {intent, decision} pair offline as a\n * self-contained spend voucher, not just a reference by id.\n */\n intentHash: z.string(),\n outcome: DecisionOutcome,\n /** Ids of the rules that fired, for explainability. */\n matchedRules: z.array(z.string()).default([]),\n /** Human-readable explanation surfaced in the dashboard. */\n reason: z.string().optional(),\n policyId: z.string(),\n policyVersion: z.string(),\n /** Hash of the previous decision in the chain (tamper-evident log). */\n prevHash: z.string(),\n /** Hash of this decision's canonical content. */\n hash: z.string(),\n /** Service signing-key signature over `hash`. */\n signature: z.string(),\n latencyMs: z.number().nonnegative(),\n decidedAt: z.coerce.date(),\n});\nexport type Decision = z.infer<typeof Decision>;\n","import type { PaymentIntent } from './intent.js';\r\nimport type { DecisionOutcome } from './decision.js';\r\nimport type { ApprovalVerdict } from './approval.js';\r\n\r\n/**\r\n * Canonical byte forms shared by the policy engine (which hashes and signs\r\n * them) and the signer (which verifies them offline). Field order is fixed,\r\n * dates are ISO strings, and absent optionals are explicit nulls, so the same\r\n * parsed object always canonicalizes to the same bytes — including after a\r\n * JSON round-trip over HTTP.\r\n *\r\n * These builders are pure (no node:crypto) so @reinconsole/core stays loadable in a\r\n * browser; services hash the strings with whatever sha256 they have.\r\n */\r\n\r\n/** Canonical form of an intent — what `Decision.intentHash` commits to. */\r\nexport function canonicalIntent(intent: PaymentIntent): string {\r\n return JSON.stringify({\r\n id: intent.id,\r\n agentId: intent.agentId,\r\n vendor: {\r\n host: intent.vendor.host,\r\n address: intent.vendor.address,\r\n erc8004Id: intent.vendor.erc8004Id ?? null,\r\n },\r\n resource: intent.resource,\r\n amount: intent.amount,\r\n asset: intent.asset,\r\n chain: intent.chain,\r\n taskContext: {\r\n taskId: intent.taskContext.taskId ?? null,\r\n parentRunId: intent.taskContext.parentRunId ?? null,\r\n purpose: intent.taskContext.purpose ?? null,\r\n },\r\n nonce: intent.nonce,\r\n createdAt: intent.createdAt.toISOString(),\r\n });\r\n}\r\n\r\n/** The decision fields covered by `Decision.hash` (and thus its signature). */\r\nexport interface DecisionContent {\r\n intentId: string;\r\n intentHash: string;\r\n outcome: DecisionOutcome;\r\n matchedRules: string[];\r\n policyId: string;\r\n policyVersion: string;\r\n prevHash: string;\r\n decidedAt: Date;\r\n}\r\n\r\n/** Canonical form of a decision — what `Decision.hash` is computed over. */\r\nexport function canonicalDecision(d: DecisionContent): string {\r\n return JSON.stringify({\r\n intentId: d.intentId,\r\n intentHash: d.intentHash,\r\n outcome: d.outcome,\r\n matchedRules: d.matchedRules,\r\n policyId: d.policyId,\r\n policyVersion: d.policyVersion,\r\n prevHash: d.prevHash,\r\n decidedAt: d.decidedAt.toISOString(),\r\n });\r\n}\r\n\r\n/** The fields an approval signature commits to. */\r\nexport interface ApprovalContent {\r\n decisionId: string;\r\n intentHash: string;\r\n verdict: ApprovalVerdict;\r\n}\r\n\r\n/**\r\n * Canonical form of an approval — the exact bytes an approver signs.\r\n *\r\n * Three properties are deliberate. The leading `rein` domain tag separates\r\n * this signature space from the decision log's, so a decision signature can\r\n * never be replayed as an approval or the reverse. `decisionId` makes each\r\n * challenge single-use: one escalation, one decision id, one signature that\r\n * means anything. And `verdict` is INSIDE the signed bytes — without it, a\r\n * captured approval could be resubmitted as a rejection (or vice versa) by\r\n * anyone who saw it in flight.\r\n */\r\nexport function canonicalApproval(a: ApprovalContent): string {\r\n return JSON.stringify({\r\n rein: 'approval/v1',\r\n decisionId: a.decisionId,\r\n intentHash: a.intentHash,\r\n verdict: a.verdict,\r\n });\r\n}\r\n","import { z } from 'zod';\nimport { AgentId, SessionId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * A session-key grant: the signer tier's unit of delegated authority. The\n * agent process holds only the bearer token — the wallet key never leaves the\n * signer — and the stored record keeps a hash of the token, never the token\n * itself (it is returned exactly once, at creation).\n *\n * Caps here are the signer-side backstop UNDER whatever policy says: a\n * signature is released only when the engine allowed the intent AND the\n * session has room. Amounts are decimal strings in the asset's human units.\n */\nexport const Session = z.object({\n id: SessionId,\n agentId: AgentId,\n /** sha256 hex of the bearer token. */\n tokenHash: z.string(),\n /** Cumulative ceiling across the session's lifetime. Absent = uncapped. */\n capAmount: DecimalString.optional(),\n /** Ceiling per individual signature. Absent = uncapped. */\n maxPerPayment: DecimalString.optional(),\n expiresAt: z.coerce.date(),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type Session = z.infer<typeof Session>;\n","import { z } from 'zod';\nimport { IntentId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * On-chain confirmation of a settled payment, reconciled by the indexer against\n * the originating intent (amount + recipient + nonce, or facilitator webhook).\n */\nexport const SettledPayment = z.object({\n intentId: IntentId,\n txHash: z.string(),\n chain: Chain,\n blockNumber: z.coerce.bigint(),\n facilitator: z.string().optional(),\n feePaid: DecimalString.optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettledPayment = z.infer<typeof SettledPayment>;\n\n/**\n * A report that an allowed intent's payment actually landed — the settlement\n * half of reconciliation (\"allowed but never settled\", B1).\n *\n * Deliberately looser than {@link SettledPayment}: the on-chain confirmation\n * requires a tx hash and a block, while a REPORT is whatever the observer\n * could see. A vendor's `X-PAYMENT-RESPONSE` names a transaction but no block;\n * a facilitator webhook may name neither. Demanding the strong shape would\n * mean the weakest observers — the ones a deployment actually has — could\n * report nothing at all, and every allowance would read as a gap.\n *\n * `source` records WHO said so, because the evidence is not all equal: an\n * independent indexer watching the chain is the strong claim, while a guard\n * reporting on its own payment is the agent vouching for itself. Nothing here\n * grants authority — a settlement report can only ever CLOSE a gap in the\n * reconciliation report, never authorize a payment or alter a decision.\n */\nexport const SettlementReport = z.object({\n intentId: IntentId,\n /** The settling transaction, when the observer saw one. */\n txHash: z.string().optional(),\n chain: Chain.optional(),\n /** The amount as SETTLED, when known — may differ from the amount allowed. */\n amount: DecimalString.optional(),\n /** Free-form observer tag, e.g. \"indexer\", \"guard\", \"facilitator\". */\n source: z.string().min(1).max(64).optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettlementReport = z.infer<typeof SettlementReport>;\n","import { z } from 'zod';\nimport { ReceiptId, IntentId, DecisionId, AgentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { TaskContext } from './intent.js';\nimport { DecisionOutcome } from './decision.js';\n\n/**\n * What the SDK reports back after settlement: the `X-PAYMENT-RESPONSE` header\n * a vendor returns once payment clears. Mock facilitators fill this in v0.1;\n * the indexer reconciles it against on-chain truth later (see SettledPayment).\n */\nexport const ReceiptSettlement = z.object({\n txHash: z.string().optional(),\n networkId: z.string().optional(),\n /** Raw header payload, kept for forensics until the indexer confirms. */\n raw: z.string().optional(),\n});\nexport type ReceiptSettlement = z.infer<typeof ReceiptSettlement>;\n\n/**\n * The SDK-side record of one guarded payment attempt: which request triggered\n * it, what the engine decided, and (if allowed and paid) how it settled.\n * Receipts are the observability primitive — every 402 the guard touches\n * produces exactly one, whether the payment was allowed or blocked.\n */\nexport const Receipt = z.object({\n id: ReceiptId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n outcome: DecisionOutcome,\n /** The URL the agent actually fetched (the paywalled resource). */\n url: z.string(),\n method: z.string().default('GET'),\n vendorHost: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n /** Human-readable explanation copied from the decision. */\n reason: z.string().optional(),\n /** Present only once a payment was made and the vendor confirmed it. */\n settlement: ReceiptSettlement.optional(),\n createdAt: z.coerce.date(),\n});\nexport type Receipt = z.infer<typeof Receipt>;\n","import { z } from 'zod';\nimport { GateReceiptId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * The vendor-side twin of `Receipt`: one settled x402 payment as the GATE saw\n * it — who paid, for which priced route, and the settlement transaction. The\n * agent-side Receipt records what an agent tried to spend; a GateReceipt\n * records what a vendor actually earned.\n */\nexport const GateReceipt = z.object({\n id: GateReceiptId,\n at: z.coerce.date(),\n /** The route pattern that priced this request, e.g. \"/api/reports/*\". */\n route: z.string().min(1),\n /** The concrete resource paid for (URL path actually requested). */\n resource: z.string().min(1),\n method: z.string().min(1),\n /** The paying wallet address, as asserted by the settled payment. */\n payer: z.string().min(1),\n payTo: z.string().min(1),\n /** Human-unit decimal amount, e.g. \"0.05\". */\n amount: DecimalString,\n /** The same amount in the asset's atomic units, e.g. \"50000\". */\n amountAtomic: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n /** Token symbol or contract address, exactly as quoted in the requirement. */\n asset: z.string().min(1),\n network: z.string().min(1),\n /** Settlement transaction hash (mock ledger or on-chain). */\n transaction: z.string().min(1),\n});\nexport type GateReceipt = z.infer<typeof GateReceipt>;\n","import { z } from 'zod';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/** A rolling-window spec, e.g. \"24h\", \"1h\", \"30m\", \"7d\". */\nexport const Window = z\n .string()\n .regex(/^\\d+[smhd]$/, 'window must be like \"30s\", \"15m\", \"1h\", or \"7d\"');\nexport type Window = z.infer<typeof Window>;\n\n/** A relative multiplier, e.g. \"3x\" (used for price-sanity checks). */\nexport const Multiplier = z.string().regex(/^\\d+(\\.\\d+)?x$/, 'multiplier must be like \"3x\"');\nexport type Multiplier = z.infer<typeof Multiplier>;\n\n/**\n * The set of predicates a rule can test. Multiple predicates in one condition\n * are ANDed together. Each maps to an evaluator in the policy engine.\n */\nexport const Condition = z\n .object({\n /** Per-transaction amount exceeds this value. */\n amountGt: DecimalString.optional(),\n /** Sum of spend in a rolling window exceeds `gt`. */\n rollingSum: z.object({ window: Window, gt: DecimalString }).optional(),\n /** Transaction count in a rolling window exceeds `gt`. */\n txCount: z.object({ window: Window, gt: z.number().int().nonnegative() }).optional(),\n /** Vendor host matches one of these patterns (supports `*` globs). */\n vendorHostIn: z.array(z.string()).optional(),\n /**\n * Resource PATH matches one of these patterns (supports `*` globs, e.g.\n * \"/v1/reports/*\"). A full-URL resource is reduced to its pathname before\n * matching (see `resourcePathOf`), so the same pattern works whether the\n * vendor declares \"https://api.x.com/v1/answer\" or \"/v1/answer\". Pair\n * with `vendorHostIn` to scope a path rule to specific vendors.\n */\n resourceIn: z.array(z.string()).optional(),\n /** First time Rein has seen this vendor for the agent. */\n vendorFirstSeen: z.boolean().optional(),\n /** Vendor reputation score is below this threshold (Phase 3 hook). */\n vendorReputationLt: z.number().min(0).max(100).optional(),\n /** Amount is more than `gt`-times the observed median for this resource. */\n amountVsResourceMedian: z.object({ gt: Multiplier }).optional(),\n /**\n * Cumulative spend attributed to THIS intent's `taskContext.taskId`\n * (prior spend on the task plus this payment) exceeds `gt`. Scopes a\n * budget to one unit of work rather than to a window: a research run that\n * is meant to cost a dollar cannot quietly cost fifty, however slowly.\n *\n * An intent carrying no `taskId` cannot be attributed to a task, so the\n * predicate never triggers for one. Requiring attribution is a separate,\n * deliberate rule (deny on `taskIdMissing`), not a side effect of setting\n * a budget — otherwise every untagged probe payment would trip every\n * task budget in the policy.\n */\n taskBudget: z.object({ gt: DecimalString }).optional(),\n /** The intent carries no `taskContext.taskId` (or an empty one). */\n taskIdMissing: z.boolean().optional(),\n })\n .refine((c) => Object.values(c).some((v) => v !== undefined), {\n message: 'a condition must specify at least one predicate',\n });\nexport type Condition = z.infer<typeof Condition>;\n\n/**\n * A behavioral circuit breaker: one primitive with three tripwires — a window\n * (rate), a transaction count, and a value cap — measured over the agent's\n * own recent activity.\n *\n * A breaker is not a rule. Rules ask about the intent in front of them; a\n * breaker asks whether the agent's BEHAVIOR has left the envelope it was\n * given, and once it has, every subsequent intent ESCALATES for a signed\n * approval. It never denies on its own: an agent that trips a breaker in the\n * middle of a job must be able to be waved through by a human, because a\n * silent deny at the wrong moment strands the work with no path forward and\n * no one told (the failure mode Flash's exit paths taught).\n *\n * Reset happens two ways, and they are one mechanism: the window rolling\n * forward, or a signed approval, which moves the breaker's counting floor to\n * now. Nothing \"un-trips\" a breaker by decree — the activity simply stops\n * being inside the measured span.\n *\n * Targeting is the policy's job: `appliesTo.agents` / `appliesTo.labels`\n * decide WHICH agents carry the breaker. COUNTING is always per agent — a\n * breaker pooled across every agent sharing a label needs a cross-agent\n * aggregate the per-agent spend context cannot express, and is deferred.\n */\nexport const Breaker = z\n .object({\n id: z.string().min(1),\n /** The trailing span the tripwires measure over. */\n window: Window,\n /**\n * Trip when the window would hold MORE than this many transactions.\n * `10` permits ten in the window and escalates the eleventh.\n */\n txCount: z.number().int().positive().optional(),\n /**\n * Trip when the window's spend would exceed this total. `\"50.00\"` permits\n * a window totalling exactly 50.00 and escalates the payment that would\n * carry it past. Prospective, like every other spend predicate: the\n * payment that would breach the cap is the one that escalates, rather\n * than the innocent one after it.\n */\n valueCap: DecimalString.optional(),\n })\n .refine((b) => b.txCount !== undefined || b.valueCap !== undefined, {\n message: 'a breaker must specify at least one of txCount / valueCap',\n });\nexport type Breaker = z.infer<typeof Breaker>;\n\n/**\n * A single rule: an id plus exactly one action (allow / deny / escalate) whose\n * value is the condition that triggers it.\n */\nexport const Rule = z\n .object({\n id: z.string().min(1),\n allow: Condition.optional(),\n deny: Condition.optional(),\n escalate: Condition.optional(),\n })\n .refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== undefined).length === 1, {\n message: 'a rule must specify exactly one of allow / deny / escalate',\n });\nexport type Rule = z.infer<typeof Rule>;\n\nexport const PolicyDefault = z.enum(['allow', 'deny']);\nexport type PolicyDefault = z.infer<typeof PolicyDefault>;\n\nexport const AppliesTo = z.object({\n /** Agent id patterns (supports `*` globs, e.g. \"agt_research_*\"). */\n agents: z.array(z.string()).optional(),\n /**\n * Agent label patterns (supports `*` globs) — semantic targeting. Matches\n * when the agent carries at least one label matching any pattern. Requires\n * the agent DOCUMENT: an intent from an unregistered agent never matches a\n * labels-targeted policy (and so fails closed when no other policy applies).\n */\n labels: z.array(z.string()).optional(),\n chains: z.array(Chain).optional(),\n});\nexport type AppliesTo = z.infer<typeof AppliesTo>;\n\nexport const Escalation = z.object({\n approvers: z.array(z.string()).default([]),\n timeoutAction: PolicyDefault.default('deny'),\n timeoutMin: z.number().int().positive().default(15),\n});\nexport type Escalation = z.infer<typeof Escalation>;\n\n/**\n * A declarative, versioned, immutable-once-active policy. Evaluation order in\n * the engine is: explicit DENY > ESCALATE > ALLOW > `default`.\n */\nexport const Policy = z.object({\n policyId: z.string().min(1),\n version: z.string().default('1'),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n /**\n * Behavioral breakers evaluated alongside the rules. A tripped breaker\n * escalates at the same precedence as an `escalate` rule — so an explicit\n * DENY still wins, and an ALLOW rule cannot wave past a tripped breaker.\n */\n breakers: z.array(Breaker).default([]),\n default: PolicyDefault.default('deny'),\n /** Below this amount, fail-open is permitted during a policy-service outage. */\n denyFloor: DecimalString.default('0.05'),\n escalation: Escalation.optional(),\n});\nexport type Policy = z.infer<typeof Policy>;\n","import { z } from 'zod';\nimport { AgentId } from './ids.js';\nimport { Window } from './policy.js';\n\n/**\n * Dead-man monitoring: the alarm for an agent that stopped (Phase B2).\n *\n * Every other control in Rein answers \"should this payment happen?\". This one\n * answers the question nothing else in the stack asks: an agent that has gone\n * quiet raises no intent, breaks no budget, and trips no breaker — it simply\n * disappears, and a control plane watching only for bad payments will report\n * a perfectly clean month while the work silently stopped being done. (Flash\n * lost four detectors this way, none of which announced anything.)\n *\n * Three rules hold the design honest, and each is the direct mirror of a rule\n * B1 already established:\n *\n * 1. An expectation is DECLARED, never inferred. Most agents are episodic:\n * they run when there is work. Silence is only evidence for an agent\n * somebody said should be periodic, so an unwatched agent has no liveness\n * state at all — the same rule as `taskBudget`, which never fires on an\n * intent that carries no task id.\n * 2. Silence has an AGE, not a boolean — `late` before `missing` — exactly as\n * a missing settlement is `in-flight` before it is `unsettled`.\n * 3. The engine never alarms about silence it did not witness. An engine that\n * was down cannot tell a dead agent from its own outage, so a silence\n * older than this process reads `unknown` until the process has been up\n * long enough to certify it. B1 refuses to manufacture gaps out of records\n * it cannot join; this refuses to manufacture alarms out of downtime.\n *\n * Liveness is observability and carries no authority whatsoever: it cannot\n * deny, escalate, freeze, or alter any decision. A missing agent is news for\n * a human, not an input to policy.\n */\n\n/** How the engine came to know an agent was alive. */\nexport const LivenessSource = z.enum([\n /** It submitted an intent — ANY outcome, including a denial. */\n 'intent',\n /** It reported in explicitly, having nothing to buy. */\n 'heartbeat',\n]);\nexport type LivenessSource = z.infer<typeof LivenessSource>;\n\n/** Default slack past the interval before silence becomes an alarm. */\nexport const DEFAULT_LIVENESS_GRACE_MS = 60_000;\n\n/**\n * \"This agent is supposed to check in at least this often.\"\n *\n * `graceMs` is what keeps a jittery-but-healthy agent out of the alert\n * channel: an agent on a 15m cadence that lands at 15m04s is not a dead agent,\n * and an alarm that cries at every wobble is one an operator learns to ignore\n * — which is the failure mode that loses the detector nobody was watching.\n */\nexport const LivenessExpectation = z.object({\n agentId: AgentId,\n /** Longest silence still considered normal, e.g. '15m'. */\n interval: Window,\n /** Extra slack past `interval` before the silence is an alarm. */\n graceMs: z.number().int().nonnegative().default(DEFAULT_LIVENESS_GRACE_MS),\n /**\n * When watching began. An agent that has NEVER been seen is measured from\n * here, so a watch on an agent that never starts does raise an alarm — a\n * detector that never came up is exactly as dead as one that stopped.\n */\n since: z.coerce.date(),\n /** What this agent is supposed to be doing, shown beside the alarm. */\n note: z.string().max(200).optional(),\n});\nexport type LivenessExpectation = z.infer<typeof LivenessExpectation>;\n\n/** The registration payload; the engine stamps `since`. */\nexport const LivenessWatchInput = LivenessExpectation.omit({ since: true }).extend({\n graceMs: z.number().int().nonnegative().optional(),\n});\nexport type LivenessWatchInput = z.input<typeof LivenessWatchInput>;\n\n/**\n * An out-of-band \"I am alive\" from an agent with nothing to buy.\n *\n * The engine sees every intent, so a spending agent needs no heartbeat at all.\n * This exists for the agent that is working and simply not paying for\n * anything — without it, a dead-man alarm is really a no-spend alarm, and it\n * would page a human every time an agent had a quiet afternoon.\n *\n * It authorizes nothing. The only thing a heartbeat can change is a row in the\n * liveness report; it cannot lift a breaker, a budget, or a freeze.\n */\nexport const Heartbeat = z.object({\n agentId: AgentId,\n /** When the agent was alive. Defaults to arrival time. */\n at: z.coerce.date().optional(),\n /** Free-form note from the reporter, e.g. \"poll cycle 41 ok\". */\n note: z.string().max(200).optional(),\n});\nexport type Heartbeat = z.infer<typeof Heartbeat>;\n\n/**\n * Where an agent stands against its expectation.\n *\n * - `alive` — seen within the interval.\n * - `late` — past the interval, inside the grace. Not yet news.\n * - `missing` — past both, and this process watched it happen. THE alarm.\n * - `unknown` — past both, but the engine has not been up long enough to have\n * witnessed the silence. Not an alarm: an engine that restarted\n * five minutes ago knows nothing about the last three days.\n */\nexport const LivenessStatus = z.enum(['alive', 'late', 'missing', 'unknown']);\nexport type LivenessStatus = z.infer<typeof LivenessStatus>;\n","import { z } from 'zod';\nimport { ApiKeyId } from './ids.js';\n\n/**\n * What a key is allowed to reach. `admin` satisfies every requirement (it is\n * the issuing/rotating key); the rest are least-privilege grants so an agent\n * runtime carrying an `evaluate` key cannot rewrite policy, and an approval\n * relay cannot read the spend history.\n */\nexport const ApiKeyScope = z.enum(['read', 'evaluate', 'approve', 'admin']);\nexport type ApiKeyScope = z.infer<typeof ApiKeyScope>;\n\n/**\n * The public view of an API key — everything except the secret. This is what\n * the API returns on list/issue; the secret itself is shown exactly once, at\n * issuance, and never persisted in recoverable form (see {@link ApiKeyRecord}).\n */\nexport const ApiKey = z.object({\n id: ApiKeyId,\n name: z.string().min(1).max(200),\n scopes: z.array(ApiKeyScope).min(1),\n createdAt: z.coerce.date(),\n /** Last successful authentication, for spotting keys that can be retired. */\n lastUsedAt: z.coerce.date().optional(),\n /** Set by revoke(); a revoked key never authenticates again. */\n revokedAt: z.coerce.date().optional(),\n /** Set by rotate(); with `previousSecretExpiresAt` it dates the overlap. */\n rotatedAt: z.coerce.date().optional(),\n});\nexport type ApiKey = z.infer<typeof ApiKey>;\n\n/**\n * SERVER-SIDE ONLY. The stored form: the public record plus sha256 digests of\n * the secrets. Digests, not secrets — a stolen database yields nothing that\n * authenticates. Rotation keeps the outgoing digest alive until\n * `previousSecretExpiresAt` so a running fleet can roll over without a\n * flag-day restart; past that instant only the current secret verifies.\n *\n * This shape never leaves the engine: every route answers with {@link ApiKey}.\n */\nexport const ApiKeyRecord = ApiKey.extend({\n secretHash: z.string(),\n previousSecretHash: z.string().optional(),\n previousSecretExpiresAt: z.coerce.date().optional(),\n});\nexport type ApiKeyRecord = z.infer<typeof ApiKeyRecord>;\n\n/** Strip the digests: the only sanctioned way to put a key on the wire. */\nexport function toPublicApiKey(record: ApiKeyRecord): ApiKey {\n const { secretHash, previousSecretHash, previousSecretExpiresAt, ...pub } = record;\n void secretHash;\n void previousSecretHash;\n void previousSecretExpiresAt;\n return pub;\n}\n","import { z } from 'zod';\nimport { AgentId, ApproverKeyId, DecisionId, IntentId, OrgId } from './ids.js';\nimport { Asset, Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * Human approval of an escalated payment.\n *\n * The load-bearing rule: an approval is a SIGNATURE over the decision, made by\n * a key registered with the engine. The delivery channel (Telegram, email,\n * whatever) is transport, never authority — anyone who compromises the channel\n * gets to show a human a message, not to release funds. There is deliberately\n * no click-to-approve path.\n */\n\nexport const ApprovalVerdict = z.enum(['approve', 'reject']);\nexport type ApprovalVerdict = z.infer<typeof ApprovalVerdict>;\n\n/**\n * `pending` is the only non-terminal state. `expired` is what a TTL lapse\n * converts to — indistinguishable from `rejected` in effect (both deny), but\n * distinguished in the record so \"nobody answered\" and \"somebody said no\" stay\n * separable in an audit.\n */\nexport const ApprovalStatus = z.enum(['pending', 'approved', 'rejected', 'expired']);\nexport type ApprovalStatus = z.infer<typeof ApprovalStatus>;\n\n/**\n * A key whose signature the engine accepts as an approval. Public half only —\n * the private half lives with the human (a hardware token, a laptop, an\n * offline signer) and must never reach the engine.\n */\nexport const ApproverKey = z.object({\n id: ApproverKeyId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** ed25519 public key, SPKI PEM — the same encoding as the decision log's. */\n publicKey: z.string().min(1),\n algorithm: z.literal('ed25519').default('ed25519'),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type ApproverKey = z.infer<typeof ApproverKey>;\n\n/**\n * A parked escalation: the payment the engine refused to allow on its own\n * authority, held open until a signature arrives or the TTL lapses. Keyed by\n * the escalating decision — one decision, at most one approval request.\n *\n * The payment facts are copied in rather than referenced so the challenge a\n * human sees is self-contained: amount, vendor and resource are exactly what\n * they are being asked to authorize.\n */\nexport const ApprovalRequest = z.object({\n /** The `escalate` decision this request answers (primary key). */\n decisionId: DecisionId,\n intentId: IntentId,\n /** Binds the approval to the exact transfer — the signed bytes commit to it. */\n intentHash: z.string(),\n agentId: AgentId,\n vendorHost: z.string(),\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n /**\n * Task attribution copied from the intent. Carried so an approved payment\n * still counts against its `taskBudget` — an escalation that lost its task\n * id on the way through would make the budget silently under-count exactly\n * the payments a human had to look at.\n */\n taskId: z.string().optional(),\n /** Why policy escalated, verbatim from the decision. */\n reason: z.string(),\n /**\n * Breaker ids whose trip contributed to this escalation. An approval of\n * this request resets exactly these — moving their counting floor to the\n * approval instant — so a human waving one payment through also clears the\n * behavior that stopped it, rather than being asked again immediately.\n * Empty when ordinary rules did the escalating.\n */\n breakers: z.array(z.string()).default([]),\n status: ApprovalStatus,\n createdAt: z.coerce.date(),\n /** Past this instant the request denies, whatever arrives afterwards. */\n expiresAt: z.coerce.date(),\n resolvedAt: z.coerce.date().optional(),\n /** Which registered key signed — absent when the TTL lapsed instead. */\n approverKeyId: ApproverKeyId.optional(),\n /**\n * The follow-up decision appended to the chain when this resolved. That\n * decision, not this record, is the voucher a signer verifies: the original\n * `escalate` decision is never rewritten.\n */\n finalDecisionId: DecisionId.optional(),\n});\nexport type ApprovalRequest = z.infer<typeof ApprovalRequest>;\n\n/** The two byte-strings an approver may sign for a given request. */\nexport const ApprovalChallenges = z.object({\n approve: z.string(),\n reject: z.string(),\n});\nexport type ApprovalChallenges = z.infer<typeof ApprovalChallenges>;\n\n/**\n * A signed verdict, submitted to the engine by anyone (the signature is the\n * authority, so the carrier does not matter). `signature` is base64 ed25519\n * over `canonicalApproval({ decisionId, intentHash, verdict })`.\n */\nexport const ApprovalGrant = z.object({\n decisionId: DecisionId,\n intentHash: z.string(),\n verdict: ApprovalVerdict,\n approverKeyId: ApproverKeyId,\n signature: z.string().min(1),\n});\nexport type ApprovalGrant = z.infer<typeof ApprovalGrant>;\n\n/** Terminal statuses — a request in one of these will never change again. */\nexport function isResolved(status: ApprovalStatus): boolean {\n return status !== 'pending';\n}\n","import { z } from 'zod';\n\nexport const ReputationSubject = z.object({\n kind: z.enum(['agent', 'vendor']),\n id: z.string(),\n});\nexport type ReputationSubject = z.infer<typeof ReputationSubject>;\n\nexport const ReputationComponents = z.object({\n volume: z.number(),\n longevity: z.number(),\n disputeRate: z.number(),\n counterpartyQuality: z.number(),\n settlementReliability: z.number(),\n});\nexport type ReputationComponents = z.infer<typeof ReputationComponents>;\n\n/**\n * A reputation score for an agent or vendor (Phase 3 — Graph). `confidence` is\n * first-class: a thin-history subject returns LOW confidence rather than a\n * misleadingly high score, so policy can avoid both false trust and unfair\n * freezing.\n */\nexport const ReputationScore = z.object({\n subject: ReputationSubject,\n score: z.number().min(0).max(100),\n components: ReputationComponents,\n confidence: z.number().min(0).max(1),\n asOf: z.coerce.date(),\n /** Hash-anchored attestation, optionally published on-chain (ERC-8004). */\n evidenceUri: z.string().optional(),\n});\nexport type ReputationScore = z.infer<typeof ReputationScore>;\n","import { z } from 'zod';\nimport { AgentId, DecisionId, IntentId, SessionId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { PaymentIntent } from './intent.js';\nimport { Decision } from './decision.js';\nimport { SettledPayment } from './payment.js';\nimport { GateReceipt } from './gate-receipt.js';\nimport { ApprovalRequest } from './approval.js';\nimport { LivenessExpectation, LivenessSource } from './liveness.js';\n\n/**\n * The canonical event envelope published on the bus (NATS in production).\n * `shadow.spend` is emitted when the indexer sees on-chain spend from a managed\n * wallet with NO corresponding ALLOW decision — the bypass signal that catches\n * SDK-mode evasion and drives the upgrade to the signer tier.\n * `signature.released` / `signature.refused` are that tier's heartbeat: every\n * time the signer does or does not put a key to work, the bus knows why.\n * `gate.*` is the vendor side of the wire: every quote a Gate issues, every\n * payment it accepts, every payment it turns away.\n * `approval.*` is the human-in-the-loop tier: an escalated intent parked for a\n * signature, and the signed (or lapsed) verdict that closed it.\n * `liveness.*` is the dead-man tier (B2), and the only pair here emitted by\n * something NOT happening: a watched agent that went quiet past its expected\n * interval, and the sighting that ended the silence.\n */\nexport const ReinEvent = z.discriminatedUnion('type', [\n z.object({ type: z.literal('intent.created'), at: z.coerce.date(), intent: PaymentIntent }),\n z.object({ type: z.literal('decision.made'), at: z.coerce.date(), decision: Decision }),\n z.object({ type: z.literal('payment.settled'), at: z.coerce.date(), payment: SettledPayment }),\n z.object({\n type: z.literal('shadow.spend'),\n at: z.coerce.date(),\n agentId: AgentId,\n txHash: z.string(),\n chain: Chain,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.released'),\n at: z.coerce.date(),\n sessionId: SessionId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"decision_replayed\" (see @reinconsole/signer). */\n code: z.string(),\n reason: z.string(),\n sessionId: SessionId.optional(),\n agentId: AgentId.optional(),\n intentId: IntentId.optional(),\n }),\n z.object({\n type: z.literal('gate.quoted'),\n at: z.coerce.date(),\n resource: z.string(),\n method: z.string(),\n amount: DecimalString,\n asset: z.string(),\n network: z.string(),\n }),\n z.object({ type: z.literal('gate.settled'), at: z.coerce.date(), receipt: GateReceipt }),\n z.object({\n type: z.literal('approval.requested'),\n at: z.coerce.date(),\n request: ApprovalRequest,\n }),\n z.object({\n type: z.literal('approval.resolved'),\n at: z.coerce.date(),\n request: ApprovalRequest,\n /** The follow-up allow/deny decision this resolution appended. */\n decision: Decision,\n }),\n z.object({\n type: z.literal('liveness.missing'),\n at: z.coerce.date(),\n agentId: AgentId,\n expectation: LivenessExpectation,\n /** How long the agent has been silent when the alarm was raised. */\n silentMs: z.number().int().nonnegative(),\n /** Last sighting, absent when the agent was never seen at all. */\n lastSeenAt: z.coerce.date().optional(),\n }),\n z.object({\n type: z.literal('liveness.recovered'),\n at: z.coerce.date(),\n agentId: AgentId,\n /** How long the silence lasted, measured to this sighting. */\n silentMs: z.number().int().nonnegative(),\n source: LivenessSource,\n }),\n z.object({\n type: z.literal('gate.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"payment_replayed\" (see @reinconsole/gate). */\n code: z.string(),\n reason: z.string(),\n resource: z.string(),\n /** Known only when the payment header decoded far enough to name a payer. */\n payer: z.string().optional(),\n }),\n]);\nexport type ReinEvent = z.infer<typeof ReinEvent>;\n","import { formatErc8004Id, parseErc8004Id, sumDecimal, type ReputationSubject } from '@reinconsole/core';\n\n/** A value that may be produced synchronously or awaited (durable writes). */\nexport type MaybePromise<T> = T | Promise<T>;\n\n/** One settled-money edge to a counterparty (the \"graph\" in reputation graph). */\nexport interface CounterpartyLine {\n settled: number;\n /** Settled decimal volume across this edge. */\n volume: string;\n}\n\n/**\n * Everything the graph has observed about one subject. Counters are raw and\n * append-only — scoring (scoring.ts) is a pure function over this record, so a\n * score is always re-derivable and explainable from the evidence behind it.\n */\nexport interface SubjectEvidence {\n subject: ReputationSubject;\n firstSeenMs: number;\n lastSeenMs: number;\n /** Payment attempts observed (allowed intents, presented payments). */\n attempts: number;\n /** Confirmed settlements (indexer-reconciled or gate-receipted). */\n settled: number;\n /** Settled decimal volume. */\n volume: string;\n /** Refusals by code (gate refusal codes, signer refusal codes). */\n refusals: Record<string, number>;\n /** Managed-wallet spend with no ALLOW decision behind it (bypass). */\n shadowSpends: number;\n /** Manual out-of-band reports (chargebacks, fraud complaints). */\n disputes: number;\n /** Manual out-of-band vouches. */\n endorsements: number;\n /** Who this subject has settled money with, keyed by subjectKey(). */\n counterparties: Map<string, CounterpartyLine>;\n}\n\n/**\n * Canonical subject identity. Hosts and EVM addresses are case-insensitive,\n * so they normalize to lowercase; ULID agent ids are case-sensitive and pass\n * through. ERC-8004 ids (`eip155:{chainId}:{registry}/{tokenId}`) normalize\n * via parse->format — @reinconsole/erc8004 always emits the canonical form, but this\n * is the graph's OWN boundary (remote producers hit POST /v1/links with\n * hand-built strings), and a checksummed registry or zero-padded tokenId\n * variant must not mint a split subject row. Note the two id spaces under\n * kind \"agent\": the engine names agents by ULID, a gate names them by paying\n * wallet — ERC-8004 linking (S17) folds both into the on-chain identity.\n */\nexport function normalizeSubject(subject: ReputationSubject): ReputationSubject {\n if (subject.id.startsWith('eip155:')) {\n const ref = parseErc8004Id(subject.id);\n if (ref) return { kind: subject.kind, id: formatErc8004Id(ref) };\n // Malformed eip155-ish strings fall through to the plain rules below.\n }\n const id =\n subject.kind === 'vendor' || subject.id.startsWith('0x') || subject.id.startsWith('0X')\n ? subject.id.toLowerCase()\n : subject.id;\n return { kind: subject.kind, id };\n}\n\nexport function subjectKey(subject: ReputationSubject): string {\n const normal = normalizeSubject(subject);\n return `${normal.kind}:${normal.id}`;\n}\n\n/**\n * The evidence store seam the graph depends on. Writes may be asynchronous (a\n * durable ledger persists behind them); reads are synchronous from the\n * hydrated working set so `score()` / `payerCheck()` stay sync in the gate hot\n * path. Mutations are explicit, atomic operations rather than a returned record\n * the caller mutates — that is what lets a durable implementation persist them.\n */\nexport interface EvidenceLedgerPort {\n /** A payment attempt (allowed intent / presented payment). */\n recordAttempt(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /** A confirmed settlement between two subjects (credits both sides + the edge). */\n recordSettlement(\n a: ReputationSubject,\n b: ReputationSubject,\n amount: string,\n atMs: number,\n ): MaybePromise<void>;\n /** A refusal against a subject, by code. */\n recordRefusal(subject: ReputationSubject, code: string, atMs: number): MaybePromise<void>;\n /** Managed-wallet spend with no ALLOW behind it. */\n recordShadowSpend(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /** An out-of-band dispute. */\n recordDispute(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /** An out-of-band endorsement. */\n recordEndorsement(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /**\n * Fold everything known about `alias` into `canonical` and forget the alias:\n * counters sum, volumes add, first/last seen widen, and settled-money edges\n * re-key on BOTH endpoints (peers that pointed at the alias now point at the\n * canonical subject). No-op when the alias has no record — which makes\n * re-asserting links at boot idempotent. This is the identity-linking\n * primitive (ERC-8004: one on-chain identity, many addresses/ids).\n */\n merge(canonical: ReputationSubject, alias: ReputationSubject): MaybePromise<void>;\n get(subject: ReputationSubject): SubjectEvidence | undefined;\n getByKey(key: string): SubjectEvidence | undefined;\n all(): IterableIterator<SubjectEvidence>;\n readonly size: number;\n /**\n * Await any pending durable writes (no-op in memory). Durable\n * implementations surface write failures HERE — the graph fire-and-forgets\n * its writes (a bus handler cannot await), so flush() is the error channel.\n */\n flush?(): Promise<void>;\n}\n\n/** The evidence store: one record per subject, created on first sighting. */\nexport class EvidenceLedger implements EvidenceLedgerPort {\n private readonly records = new Map<string, SubjectEvidence>();\n\n recordAttempt(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).attempts += 1;\n }\n\n recordSettlement(\n a: ReputationSubject,\n b: ReputationSubject,\n amount: string,\n atMs: number,\n ): void {\n for (const [subject, other] of [\n [a, b],\n [b, a],\n ] as const) {\n const ev = this.touch(subject, atMs);\n ev.settled += 1;\n ev.volume = sumDecimal([ev.volume, amount]);\n const key = subjectKey(other);\n const line = ev.counterparties.get(key) ?? { settled: 0, volume: '0' };\n line.settled += 1;\n line.volume = sumDecimal([line.volume, amount]);\n ev.counterparties.set(key, line);\n }\n }\n\n recordRefusal(subject: ReputationSubject, code: string, atMs: number): void {\n const ev = this.touch(subject, atMs);\n ev.refusals[code] = (ev.refusals[code] ?? 0) + 1;\n }\n\n recordShadowSpend(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).shadowSpends += 1;\n }\n\n recordDispute(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).disputes += 1;\n }\n\n recordEndorsement(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).endorsements += 1;\n }\n\n merge(canonical: ReputationSubject, alias: ReputationSubject): void {\n const aliasKey = subjectKey(alias);\n const canonicalKey = subjectKey(canonical);\n const from = this.records.get(aliasKey);\n if (!from || aliasKey === canonicalKey) return;\n // The canonical side may have no record yet — the alias's history becomes\n // its history (same create shape as touch, seeded with the alias's window).\n const into = this.records.get(canonicalKey) ?? this.touch(canonical, from.firstSeenMs);\n into.firstSeenMs = Math.min(into.firstSeenMs, from.firstSeenMs);\n into.lastSeenMs = Math.max(into.lastSeenMs, from.lastSeenMs);\n into.attempts += from.attempts;\n into.settled += from.settled;\n into.volume = sumDecimal([into.volume, from.volume]);\n for (const [code, count] of Object.entries(from.refusals)) {\n into.refusals[code] = (into.refusals[code] ?? 0) + count;\n }\n into.shadowSpends += from.shadowSpends;\n into.disputes += from.disputes;\n into.endorsements += from.endorsements;\n for (const [peerKey, line] of from.counterparties) {\n if (peerKey === canonicalKey) continue; // a self-edge would score the subject by itself\n const existing = into.counterparties.get(peerKey) ?? { settled: 0, volume: '0' };\n existing.settled += line.settled;\n existing.volume = sumDecimal([existing.volume, line.volume]);\n into.counterparties.set(peerKey, existing);\n // Re-key the peer's reverse edge: alias -> canonical.\n const peer = this.records.get(peerKey);\n const held = peer?.counterparties.get(aliasKey);\n if (peer && held) {\n peer.counterparties.delete(aliasKey);\n const reverse = peer.counterparties.get(canonicalKey) ?? { settled: 0, volume: '0' };\n reverse.settled += held.settled;\n reverse.volume = sumDecimal([reverse.volume, held.volume]);\n peer.counterparties.set(canonicalKey, reverse);\n }\n }\n into.counterparties.delete(aliasKey);\n this.records.delete(aliasKey);\n }\n\n get(subject: ReputationSubject): SubjectEvidence | undefined {\n return this.records.get(subjectKey(subject));\n }\n\n getByKey(key: string): SubjectEvidence | undefined {\n return this.records.get(key);\n }\n\n all(): IterableIterator<SubjectEvidence> {\n return this.records.values();\n }\n\n get size(): number {\n return this.records.size;\n }\n\n /**\n * Insert a fully-formed record verbatim — the hydration primitive a durable\n * store uses to rebuild the working set on open. Bypasses the live counters\n * (the record already holds its accumulated state and timestamps).\n */\n load(record: SubjectEvidence): void {\n this.records.set(subjectKey(record.subject), record);\n }\n\n /** Get-or-create the record for a subject and stamp first/last seen. */\n private touch(subject: ReputationSubject, atMs: number): SubjectEvidence {\n const key = subjectKey(subject);\n let record = this.records.get(key);\n if (!record) {\n record = {\n subject: normalizeSubject(subject),\n firstSeenMs: atMs,\n lastSeenMs: atMs,\n attempts: 0,\n settled: 0,\n volume: '0',\n refusals: {},\n shadowSpends: 0,\n disputes: 0,\n endorsements: 0,\n counterparties: new Map(),\n };\n this.records.set(key, record);\n }\n if (atMs < record.firstSeenMs) record.firstSeenMs = atMs;\n if (atMs > record.lastSeenMs) record.lastSeenMs = atMs;\n return record;\n }\n}\n","import type { MaybePromise } from './evidence.js';\n\n/**\n * What an `intent.created` event tells us, kept until the matching\n * `payment.settled` (which carries only an intentId) can be attributed.\n */\nexport interface IntentFacts {\n agentId: string;\n host: string;\n amount: string;\n}\n\nexport const DEFAULT_CORRELATION_LIMIT = 10_000;\n\n/**\n * Bridges `intent.created` -> later `payment.settled`/`decision.made`. A\n * `payment.settled` event names only an intentId, so the graph remembers every\n * undecided intent until it settles. Bounded (oldest-evicted) so undecided\n * intents that never settle cannot leak. Writes may be async (a durable store\n * persists them so an in-flight intent survives a restart); reads are sync.\n */\nexport interface IntentCorrelationPort {\n remember(intentId: string, facts: IntentFacts): MaybePromise<void>;\n /** Read the facts without consuming them (decision.made reads, doesn't burn). */\n peek(intentId: string): IntentFacts | undefined;\n /** Read and consume (payment.settled attributes once, then forgets). */\n take(intentId: string): IntentFacts | undefined;\n readonly size: number;\n /**\n * Await any pending durable writes (no-op in memory). Durable\n * implementations surface write failures HERE — the graph fire-and-forgets\n * its writes, so flush() is the error channel.\n */\n flush?(): Promise<void>;\n}\n\n/** In-memory correlation map with FIFO eviction once `limit` is reached. */\nexport class InMemoryIntentStore implements IntentCorrelationPort {\n private readonly intents = new Map<string, IntentFacts>();\n\n constructor(private readonly limit: number = DEFAULT_CORRELATION_LIMIT) {}\n\n remember(intentId: string, facts: IntentFacts): void {\n // Re-remembering an existing id is an update, not a new entry — evicting\n // for it would shrink the working set below the bound (and desync a\n // durable mirror, whose upsert adds no row). Updates keep their position,\n // matching an SQL upsert leaving seq unchanged.\n if (!this.intents.has(intentId) && this.intents.size >= this.limit) {\n const oldest = this.intents.keys().next().value;\n if (oldest !== undefined) this.intents.delete(oldest);\n }\n this.intents.set(intentId, facts);\n }\n\n peek(intentId: string): IntentFacts | undefined {\n return this.intents.get(intentId);\n }\n\n take(intentId: string): IntentFacts | undefined {\n const facts = this.intents.get(intentId);\n if (facts) this.intents.delete(intentId);\n return facts;\n }\n\n get size(): number {\n return this.intents.size;\n }\n}\n","import type { ReputationComponents } from '@reinconsole/core';\nimport type { SubjectEvidence } from './evidence.js';\n\n/**\n * Component weights, summing to 1. The blend is a deliberately transparent\n * heuristic: every component is 0–100 with higher = healthier, so a score is\n * readable straight off its explanation. Sophistication can replace this\n * later without touching the evidence model — scores are pure functions of\n * evidence, never stored.\n */\nexport interface ScoreWeights {\n volume: number;\n longevity: number;\n disputeRate: number;\n counterpartyQuality: number;\n settlementReliability: number;\n}\n\nexport const DEFAULT_WEIGHTS: ScoreWeights = {\n settlementReliability: 0.3,\n disputeRate: 0.3,\n volume: 0.15,\n counterpartyQuality: 0.15,\n longevity: 0.1,\n};\n\nconst DAY_MS = 86_400_000;\n\n/**\n * How much one bad observation hurts, relative to a plain refusal. Disputes\n * and shadow spends are deliberate misconduct; a replay means someone tried\n * to spend the same money twice; the rest is sloppiness.\n */\nconst BADNESS = { dispute: 4, shadowSpend: 4, replay: 3, refusal: 1, endorsementCredit: 2 };\n\nconst REPLAY_CODES = new Set(['payment_replayed', 'decision_replayed']);\n\nfunction clamp(value: number, lo: number, hi: number): number {\n return Math.min(hi, Math.max(lo, value));\n}\n\nfunction refusalCounts(ev: SubjectEvidence): { replays: number; others: number } {\n let replays = 0;\n let others = 0;\n for (const [code, count] of Object.entries(ev.refusals)) {\n if (REPLAY_CODES.has(code)) replays += count;\n else others += count;\n }\n return { replays, others };\n}\n\n/** Saturating settled-transaction volume: 0 at none, ~63 at 20, ~92 at 50. */\nexport function volumeComponent(ev: SubjectEvidence): number {\n return 100 * (1 - Math.exp(-ev.settled / 20));\n}\n\n/** How long the subject has been known: linear to 100 at 30 days. */\nexport function longevityComponent(ev: SubjectEvidence, nowMs: number): number {\n const knownDays = Math.max(0, nowMs - ev.firstSeenMs) / DAY_MS;\n return 100 * Math.min(1, knownDays / 30);\n}\n\n/**\n * Dispute hygiene (the core field is named `disputeRate`; the component is\n * stored INVERTED — 100 = a clean record — so all five components blend in\n * the same direction). Weighted badness over total interactions; manual\n * endorsements buy back a little slack.\n */\nexport function disputeComponent(ev: SubjectEvidence): number {\n const { replays, others } = refusalCounts(ev);\n const badness = Math.max(\n 0,\n ev.disputes * BADNESS.dispute +\n ev.shadowSpends * BADNESS.shadowSpend +\n replays * BADNESS.replay +\n others * BADNESS.refusal -\n ev.endorsements * BADNESS.endorsementCredit,\n );\n const interactions = Math.max(1, ev.attempts + ev.disputes + ev.endorsements);\n return 100 * Math.max(0, 1 - badness / interactions);\n}\n\n/** Settled / attempted. No attempts yet = neutral 50, not perfect 100. */\nexport function reliabilityComponent(ev: SubjectEvidence): number {\n if (ev.attempts === 0) return 50;\n return 100 * Math.min(1, ev.settled / ev.attempts);\n}\n\n/**\n * Confidence is first-class (see core ReputationScore): a thin or brand-new\n * history yields LOW confidence rather than a misleading score, so consumers\n * (engine sync, gate screening) can refuse to act on it. Depth of evidence\n * saturates around 10 observations; age stops mattering after a week.\n *\n * The 0.1 age floor is load-bearing for fairness. Both consumers act at a 0.3\n * confidence floor (`syncVendors`, `payerCheck`), so capping a day-0 subject at\n * 0.1 makes first-day enforcement impossible BY CONSTRUCTION rather than by\n * arithmetic luck. It used to be 0.4, which left day-0 subjects enforceable\n * after only 14 observations — `depth` saturates so fast that a busy vendor\n * cleared that in seconds, and the console's own vendor sat at 0.30136 against\n * the 0.3 floor, i.e. inside the newcomer grace period by 0.0014. Enforcement\n * now needs roughly 1.6 days (high volume) to 2.3 days (moderate) of history:\n * a grace period measured in time, which is what \"newcomer\" means.\n *\n * Note the constant only ever applies to subjects younger than a week — past\n * 7 days `min(1, d/7)` saturates and age is 1.0 under any floor — so lowering\n * it leaves every mature score bit-for-bit unchanged.\n */\nexport function confidence(ev: SubjectEvidence, nowMs: number): number {\n const { replays, others } = refusalCounts(ev);\n const observations =\n ev.attempts + ev.disputes + ev.endorsements + ev.shadowSpends + replays + others;\n const depth = 1 - Math.exp(-observations / 10);\n const knownDays = Math.max(0, nowMs - ev.firstSeenMs) / DAY_MS;\n const age = 0.1 + 0.9 * Math.min(1, knownDays / 7);\n return clamp(depth * age, 0, 1);\n}\n\n/** Blend all five components into the headline 0–100 score. */\nexport function blend(components: ReputationComponents, weights: ScoreWeights): number {\n const total =\n components.volume * weights.volume +\n components.longevity * weights.longevity +\n components.disputeRate * weights.disputeRate +\n components.counterpartyQuality * weights.counterpartyQuality +\n components.settlementReliability * weights.settlementReliability;\n return clamp(Math.round(total), 0, 100);\n}\n\n/**\n * The one-hop base score: the blend WITHOUT counterpartyQuality, with the\n * remaining weights renormalized. Counterparty quality for subject A averages\n * the base scores of A's counterparties — base, not full, so the computation\n * is a single hop and cycles (A pays B pays A) cannot recurse.\n */\nexport function blendBase(ev: SubjectEvidence, nowMs: number, weights: ScoreWeights): number {\n const remaining =\n weights.volume + weights.longevity + weights.disputeRate + weights.settlementReliability;\n if (remaining <= 0) return 50;\n const total =\n volumeComponent(ev) * weights.volume +\n longevityComponent(ev, nowMs) * weights.longevity +\n disputeComponent(ev) * weights.disputeRate +\n reliabilityComponent(ev) * weights.settlementReliability;\n return clamp(total / remaining, 0, 100);\n}\n","import {\n ReputationScore,\n type Receipt,\n type ReinEvent,\n type ReputationComponents,\n type ReputationSubject,\n} from '@reinconsole/core';\nimport {\n EvidenceLedger,\n normalizeSubject,\n subjectKey,\n type EvidenceLedgerPort,\n type MaybePromise,\n type SubjectEvidence,\n} from './evidence.js';\nimport {\n DEFAULT_CORRELATION_LIMIT,\n InMemoryIntentStore,\n type IntentCorrelationPort,\n} from './intents.js';\nimport {\n blend,\n blendBase,\n confidence,\n DEFAULT_WEIGHTS,\n disputeComponent,\n longevityComponent,\n reliabilityComponent,\n volumeComponent,\n type ScoreWeights,\n} from './scoring.js';\n\n/** Anything with a Rein event bus: engine, indexer, gate, signer. */\nexport interface EventSource {\n onEvent(handler: (event: ReinEvent) => void): void;\n}\n\n/**\n * Gate refusal codes that are the vendor's throttle or the vendor's rails\n * failing — not payer misbehavior. They must never become reputation evidence\n * (see the `gate.refused` case below). Mirrors @reinconsole/gate's no-fault classes;\n * kept as strings because the event schema deliberately carries codes as\n * strings (remote gates may run other versions).\n */\nconst NO_FAULT_GATE_CODES = new Set([\n 'rate_limited',\n 'velocity_exceeded',\n 'rails_unavailable',\n 'settle_unknown',\n]);\n\n/**\n * Where vendor scores land. `PolicyEngine.spend` satisfies this structurally,\n * so `graph.syncVendors(engine.spend)` closes the loop — durable when the\n * engine runs on @reinconsole/store.\n */\nexport interface VendorReputationSink {\n setVendorReputation(host: string, score: number): void | Promise<void>;\n}\n\nexport interface ReputationGraphOptions {\n weights?: Partial<ScoreWeights>;\n /** Injectable clock (scores are functions of evidence AND time). */\n now?: () => Date;\n /**\n * Max undecided intents remembered for settlement correlation. Ignored when\n * a custom `intents` store is injected (that store owns its own bound).\n */\n correlationLimit?: number;\n /**\n * Durable evidence ledger. Defaults to in-memory; @reinconsole/store provides a\n * PGlite-backed one so scores survive a restart.\n */\n ledger?: EvidenceLedgerPort;\n /** Durable intent correlation store. Defaults to in-memory (bounded by `correlationLimit`). */\n intents?: IntentCorrelationPort;\n}\n\nexport interface ManualReport {\n subject: ReputationSubject;\n kind: 'dispute' | 'endorsement';\n /** When the incident happened (defaults to now). */\n at?: Date;\n note?: string;\n}\n\nexport interface SyncedVendorScore {\n host: string;\n score: number;\n confidence: number;\n}\n\nexport interface SyncOptions {\n /**\n * Scores below this confidence are NOT pushed — the evaluator treats an\n * unknown reputation as indeterminate (never triggers vendorReputationLt),\n * and a thin history must stay unknown rather than condemn a newcomer.\n */\n minConfidence?: number;\n}\n\n/** A score plus the raw evidence it was derived from, render-ready. */\nexport interface ReputationExplanation {\n score: ReputationScore;\n weights: ScoreWeights;\n evidence: {\n attempts: number;\n settled: number;\n volume: string;\n refusals: Record<string, number>;\n shadowSpends: number;\n disputes: number;\n endorsements: number;\n firstSeen: Date;\n lastSeen: Date;\n counterparties: { subject: ReputationSubject; settled: number; volume: string }[];\n };\n}\n\n/**\n * The Rein reputation graph (Phase 3). Subscribes to the event buses both\n * sides already publish — the engine/indexer name vendors by host and agents\n * by id; a gate names payers by wallet — and accumulates per-subject evidence:\n * settlements, refusals, shadow spends, manual disputes, and settled-money\n * edges between counterparties. Scores are computed on demand (never stored)\n * from that evidence, so every number is explainable, and they feed back into\n * enforcement on both sides of the wire:\n *\n * graph.syncVendors(engine.spend) -> policies with vendorReputationLt fire\n * screen: { check: payerCheck(graph) } -> a gate turns away low-rep wallets\n *\n * Event mapping notes: engine-side evidence keys agents by ULID and vendors by\n * host; gate-side evidence keys payers by wallet and recipients by payTo\n * address — distinct subjects, so feeding one graph from BOTH buses (the\n * console world) never double-counts. `payment.settled` carries only an\n * intentId, so the graph keeps a bounded intent.created correlation map.\n * Denied decisions are deliberately NOT held against anyone: a deny means\n * policy worked, not that the agent or vendor misbehaved.\n */\nexport class ReputationGraph {\n private readonly ledger: EvidenceLedgerPort;\n private readonly intents: IntentCorrelationPort;\n private readonly weights: ScoreWeights;\n private readonly now: () => Date;\n /** aliasKey -> canonical subject. Links are derived state (an agent registry\n * or ERC-8004 lookup knows them) — re-assert at boot; merges are idempotent. */\n private readonly aliases = new Map<string, ReputationSubject>();\n\n constructor(options: ReputationGraphOptions = {}) {\n this.weights = { ...DEFAULT_WEIGHTS, ...options.weights };\n this.now = options.now ?? (() => new Date());\n this.ledger = options.ledger ?? new EvidenceLedger();\n this.intents =\n options.intents ??\n new InMemoryIntentStore(options.correlationLimit ?? DEFAULT_CORRELATION_LIMIT);\n }\n\n /** Subscribe to a bus. Returns `this` so construction chains. */\n observe(source: EventSource): this {\n source.onEvent((event) => this.ingest(event));\n return this;\n }\n\n /**\n * Fire-and-forget a port write: bus handlers cannot await, and a rejecting\n * durable write must never become an unhandled rejection (Node kills the\n * process). Failures are the port's to surface — flush() throws them.\n */\n private fire(write: () => MaybePromise<void>): void {\n // Thunk form (parity with the gate's fire, S19): a ledger that THROWS\n // synchronously must not turn an ingest into a crash — telemetry failures\n // are the port's to surface, and flush() throws them.\n try {\n void Promise.resolve(write()).catch(() => undefined);\n } catch {\n // swallowed by design — see above\n }\n }\n\n /**\n * Declare that `alias` is the same real-world party as `canonical` (the\n * ERC-8004 identity story: one identity, many addresses/ids — an engine\n * agent's ULID and its paying wallet, or a vendor's host and its payTo\n * address). Everything already known about the alias is folded into the\n * canonical subject, and all future evidence and lookups for the alias\n * resolve to it. Idempotent — re-asserting known links at boot is free.\n */\n link(canonical: ReputationSubject, alias: ReputationSubject): void {\n const target = normalizeSubject(this.resolve(canonical)); // flatten chains\n const aliasKey = subjectKey(alias);\n if (subjectKey(target) === aliasKey) return;\n this.aliases.set(aliasKey, target);\n // Repoint any alias that resolved THROUGH this alias (a->b then b->c).\n for (const [key, resolved] of this.aliases) {\n if (subjectKey(resolved) === aliasKey) this.aliases.set(key, target);\n }\n this.fire(() => this.ledger.merge(target, alias));\n }\n\n /** The canonical subject for a possibly-aliased one. */\n private resolve(subject: ReputationSubject): ReputationSubject {\n return this.aliases.get(subjectKey(subject)) ?? subject;\n }\n\n ingest(event: ReinEvent): void {\n const atMs = event.at.getTime();\n switch (event.type) {\n case 'intent.created': {\n this.fire(() =>\n this.intents.remember(event.intent.id, {\n agentId: event.intent.agentId,\n host: event.intent.vendor.host,\n amount: event.intent.amount,\n }),\n );\n return;\n }\n case 'decision.made': {\n if (event.decision.outcome !== 'allow') return;\n const facts = this.intents.peek(event.decision.intentId);\n if (!facts) return;\n this.fire(() => this.ledger.recordAttempt(this.resolve({ kind: 'agent', id: facts.agentId }), atMs));\n this.fire(() => this.ledger.recordAttempt(this.resolve({ kind: 'vendor', id: facts.host }), atMs));\n return;\n }\n case 'payment.settled': {\n const facts = this.intents.take(event.payment.intentId);\n if (!facts) return; // unattributable — no subject to credit\n const agent = this.resolve({ kind: 'agent', id: facts.agentId });\n const vendor = this.resolve({ kind: 'vendor', id: facts.host });\n this.fire(() => this.ledger.recordSettlement(agent, vendor, facts.amount, atMs));\n return;\n }\n case 'shadow.spend': {\n this.fire(() => this.ledger.recordShadowSpend(this.resolve({ kind: 'agent', id: event.agentId }), atMs));\n return;\n }\n case 'signature.refused': {\n const agentId = event.agentId; // hoisted: narrowing must survive the thunk\n if (!agentId) return;\n this.fire(() =>\n this.ledger.recordRefusal(this.resolve({ kind: 'agent', id: agentId }), event.code, atMs),\n );\n return;\n }\n case 'gate.settled': {\n const payer = this.resolve({ kind: 'agent', id: event.receipt.payer });\n const recipient = this.resolve({ kind: 'vendor', id: event.receipt.payTo });\n this.fire(() => this.ledger.recordAttempt(payer, atMs));\n this.fire(() => this.ledger.recordAttempt(recipient, atMs));\n this.fire(() => this.ledger.recordSettlement(payer, recipient, event.receipt.amount, atMs));\n return;\n }\n case 'gate.refused': {\n // No-fault refusals carry NO evidence — the gate-side parallel of\n // \"denied decisions count against no one\". Throttle codes are the\n // VENDOR'S cap (one gate's rate limit must not bleed into a payer's\n // global score); rails codes are the vendor's infrastructure failing\n // (a settle_unknown payment may even have gone through). Not even the\n // attempt is recorded: an attempt with no settlement would silently\n // drag settlementReliability down.\n if (!event.payer || NO_FAULT_GATE_CODES.has(event.code)) return;\n const payer = this.resolve({ kind: 'agent', id: event.payer });\n this.fire(() => this.ledger.recordAttempt(payer, atMs));\n this.fire(() => this.ledger.recordRefusal(payer, event.code, atMs));\n return;\n }\n // signature.released and gate.quoted carry no evidence the engine-side\n // events don't already: released duplicates the allow that preceded it,\n // and a quote names no payer.\n case 'signature.released':\n case 'gate.quoted':\n return;\n }\n }\n\n /**\n * Agent-side alternative to observing the engine bus: feed the SDK guard's\n * onReceipt straight in. Connect events OR receipts per side, not both —\n * a receipt restates the decision/settlement the bus already carried.\n */\n ingestReceipt(receipt: Receipt): void {\n if (receipt.outcome !== 'allow') return; // policy verdicts are not subject badness\n const atMs = receipt.createdAt.getTime();\n const agent = this.resolve({ kind: 'agent', id: receipt.agentId });\n const vendor = this.resolve({ kind: 'vendor', id: receipt.vendorHost });\n this.fire(() => this.ledger.recordAttempt(agent, atMs));\n this.fire(() => this.ledger.recordAttempt(vendor, atMs));\n if (receipt.settlement?.txHash) {\n this.fire(() => this.ledger.recordSettlement(agent, vendor, receipt.amount, atMs));\n }\n }\n\n /** Record an out-of-band dispute or endorsement against a subject. */\n report(input: ManualReport): void {\n const atMs = (input.at ?? this.now()).getTime();\n const subject = this.resolve(input.subject);\n if (input.kind === 'dispute') this.fire(() => this.ledger.recordDispute(subject, atMs));\n else this.fire(() => this.ledger.recordEndorsement(subject, atMs));\n }\n\n /** Await any pending durable writes (no-op for in-memory stores). */\n async flush(): Promise<void> {\n await this.ledger.flush?.();\n await this.intents.flush?.();\n }\n\n /** The score for one subject, or undefined when nothing is known (fairness).\n * Aliased subjects resolve to their canonical identity — a linked wallet\n * answers with the merged history, on both sides of the wire. */\n score(subject: ReputationSubject): ReputationScore | undefined {\n const ev = this.ledger.get(this.resolve(subject));\n return ev && this.scoreOf(ev);\n }\n\n /** All known scores, best first. */\n scores(kind?: ReputationSubject['kind']): ReputationScore[] {\n const out: ReputationScore[] = [];\n for (const ev of this.ledger.all()) {\n if (kind && ev.subject.kind !== kind) continue;\n out.push(this.scoreOf(ev));\n }\n return out.sort((a, b) => b.score - a.score);\n }\n\n /** The score plus the raw evidence behind it. */\n explain(subject: ReputationSubject): ReputationExplanation | undefined {\n const ev = this.ledger.get(this.resolve(subject));\n if (!ev) return undefined;\n return {\n score: this.scoreOf(ev),\n weights: this.weights,\n evidence: {\n attempts: ev.attempts,\n settled: ev.settled,\n volume: ev.volume,\n refusals: { ...ev.refusals },\n shadowSpends: ev.shadowSpends,\n disputes: ev.disputes,\n endorsements: ev.endorsements,\n firstSeen: new Date(ev.firstSeenMs),\n lastSeen: new Date(ev.lastSeenMs),\n counterparties: [...ev.counterparties.entries()].map(([key, line]) => {\n const [kind, ...id] = key.split(':');\n return {\n subject: { kind: kind as ReputationSubject['kind'], id: id.join(':') },\n settled: line.settled,\n volume: line.volume,\n };\n }),\n },\n };\n }\n\n /**\n * Push every vendor score that clears the confidence floor into the engine's\n * spend store (or any sink). Returns what was pushed. Low-confidence scores\n * are withheld so `vendorReputationLt` keeps treating thin histories as\n * unknown — the evaluator's no-data-no-trigger rule stays intact end to end.\n */\n async syncVendors(\n sink: VendorReputationSink,\n options: SyncOptions = {},\n ): Promise<SyncedVendorScore[]> {\n const minConfidence = options.minConfidence ?? 0.3;\n const pushed: SyncedVendorScore[] = [];\n for (const ev of this.ledger.all()) {\n if (ev.subject.kind !== 'vendor') continue;\n const score = this.scoreOf(ev);\n if (score.confidence < minConfidence) continue;\n await sink.setVendorReputation(ev.subject.id, score.score);\n pushed.push({ host: ev.subject.id, score: score.score, confidence: score.confidence });\n }\n return pushed;\n }\n\n /** Number of subjects with evidence. */\n subjects(): number {\n return this.ledger.size;\n }\n\n private scoreOf(ev: SubjectEvidence): ReputationScore {\n const nowMs = this.now().getTime();\n const components: ReputationComponents = {\n volume: volumeComponent(ev),\n longevity: longevityComponent(ev, nowMs),\n disputeRate: disputeComponent(ev),\n counterpartyQuality: this.counterpartyQuality(ev, nowMs),\n settlementReliability: reliabilityComponent(ev),\n };\n return ReputationScore.parse({\n subject: ev.subject,\n score: blend(components, this.weights),\n components,\n confidence: confidence(ev, nowMs),\n asOf: new Date(nowMs),\n });\n }\n\n /** One-hop mean of the counterparties' base scores; neutral 50 when alone. */\n private counterpartyQuality(ev: SubjectEvidence, nowMs: number): number {\n if (ev.counterparties.size === 0) return 50;\n let total = 0;\n for (const key of ev.counterparties.keys()) {\n const other = this.ledger.getByKey(key);\n total += other ? blendBase(other, nowMs, this.weights) : 50;\n }\n return total / ev.counterparties.size;\n }\n}\n\nexport interface PayerCheckOptions {\n /** Refuse payers scoring below this (default 40). */\n denyBelow?: number;\n /** Ignore scores below this confidence (default 0.3) — newcomers pass. */\n minConfidence?: number;\n}\n\n/**\n * Reputation-driven gate screening: plugs into @reinconsole/gate's `screen.check`.\n * Unknown wallets and thin histories pass (same fairness rule as the engine\n * sync); a confident low score is turned away at the door, before any\n * facilitator round-trip.\n */\nexport function payerCheck(\n graph: ReputationGraph,\n options: PayerCheckOptions = {},\n): (payer: string) => string | undefined {\n const denyBelow = options.denyBelow ?? 40;\n const minConfidence = options.minConfidence ?? 0.3;\n return (payer) => {\n const score = graph.score({ kind: 'agent', id: payer });\n if (!score || score.confidence < minConfidence) return undefined;\n if (score.score >= denyBelow) return undefined;\n return `payer reputation ${score.score} is below this gate's floor of ${denyBelow}`;\n };\n}\n","import { fileURLToPath } from 'node:url';\nimport { realpathSync } from 'node:fs';\nimport Fastify, { type FastifyInstance } from 'fastify';\nimport { z } from 'zod';\nimport { ReinEvent, ReputationSubject } from '@reinconsole/core';\nimport { ReputationGraph } from './graph.js';\n\nconst ReportInput = z.object({\n subject: ReputationSubject,\n kind: z.enum(['dispute', 'endorsement']),\n at: z.coerce.date().optional(),\n note: z.string().max(500).optional(),\n});\n\nconst ScoresQuery = z.object({ kind: z.enum(['agent', 'vendor']).optional() });\n\nconst LinkInput = z\n .object({\n canonical: ReputationSubject,\n alias: ReputationSubject,\n })\n // Merging across kinds would delete a vendor row into an agent identity\n // (silently dropping the host from syncVendors) — always a caller bug.\n .refine((l) => l.canonical.kind === l.alias.kind, {\n message: 'canonical and alias must be the same kind',\n });\n\n/**\n * Build the graph HTTP API. Remote producers POST their events here; anyone\n * can read scores with the evidence behind them. Pass a graph for tests, or\n * let it create a fresh in-memory one.\n */\nexport function buildGraphServer(graph: ReputationGraph = new ReputationGraph()): FastifyInstance {\n const app = Fastify({ logger: false });\n\n // Turn ZodErrors into clean 400s instead of 500s.\n app.setErrorHandler((err: unknown, _req, reply) => {\n if (err instanceof z.ZodError) {\n return reply.status(400).send({ error: 'validation_error', issues: err.issues });\n }\n const message = err instanceof Error ? err.message : String(err);\n return reply.status(500).send({ error: 'internal_error', message });\n });\n\n app.get('/health', () => ({ status: 'ok', subjects: graph.subjects() }));\n\n // --- Ingestion ---\n // The HTTP path can await durability even though the in-process bus path\n // cannot — flush the durable writes before answering so a POST that returns\n // 200 is persisted.\n app.post('/v1/events', async (req) => {\n const events = z.union([ReinEvent.transform((e) => [e]), z.array(ReinEvent)]).parse(req.body);\n for (const event of events) graph.ingest(event);\n await graph.flush();\n return { ingested: events.length };\n });\n\n app.post('/v1/reports', async (req) => {\n const input = ReportInput.parse(req.body);\n graph.report(input);\n await graph.flush();\n return graph.score(input.subject);\n });\n\n // --- Identity links ---\n // Unverified by DESIGN: this endpoint's trust level equals POST /v1/events —\n // whoever can post events can already fabricate the evidence itself. On-chain\n // verification belongs to the CALLER (@reinconsole/erc8004 derives link facts from\n // the Identity Registry, then asserts them here).\n app.post('/v1/links', async (req) => {\n const links = z.union([LinkInput.transform((l) => [l]), z.array(LinkInput)]).parse(req.body);\n for (const link of links) graph.link(link.canonical, link.alias);\n await graph.flush(); // durable merges land before the 200 (same contract as /v1/events)\n return { linked: links.length };\n });\n\n // --- Scores ---\n app.get('/v1/scores', (req) => {\n const { kind } = ScoresQuery.parse(req.query);\n return graph.scores(kind);\n });\n\n app.get('/v1/scores/:kind/:id', (req, reply) => {\n const subject = ReputationSubject.parse(req.params);\n const explanation = graph.explain(subject);\n if (!explanation) {\n return reply\n .status(404)\n .send({ error: 'not_found', message: `no evidence for ${subject.kind} ${subject.id}` });\n }\n return explanation;\n });\n\n return app;\n}\n\n// Start the server when run directly (tsx/node), not when imported.\nfunction isMainModule(): boolean {\n if (!process.argv[1]) return false;\n try {\n return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));\n } catch {\n return false;\n }\n}\n\nif (isMainModule()) {\n const port = Number(process.env.PORT ?? 8788);\n const host = process.env.HOST ?? '0.0.0.0';\n const app = buildGraphServer();\n app\n .listen({ port, host })\n .then(() => console.log(`[rein] graph listening on http://${host}:${port}`))\n .catch((err) => {\n console.error(err);\n process.exit(1);\n });\n}\n"],"mappings":"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","names":["z","z","z","z","z","z","z","z"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reinconsole/graph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Rein's reputation graph (Phase 3) — turns guard receipts and gate receipts into explainable reputation scores, and feeds them back into policy (vendorReputationLt) and gate screening.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/bugiiiii11/rein#readme",
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"fastify": "^5.2.0",
|
|
43
43
|
"zod": "^3.24.1",
|
|
44
|
-
"@reinconsole/core": "^0.
|
|
44
|
+
"@reinconsole/core": "^0.2.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^22.10.0",
|
|
48
48
|
"tsup": "^8.3.5",
|
|
49
49
|
"typescript": "^5.7.2",
|
|
50
50
|
"vitest": "^2.1.8",
|
|
51
|
-
"@reinconsole/gate": "0.
|
|
52
|
-
"@reinconsole/policy-engine": "0.
|
|
51
|
+
"@reinconsole/gate": "0.2.0",
|
|
52
|
+
"@reinconsole/policy-engine": "0.2.0"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "tsup",
|