@reinconsole/mock-rails 0.2.0 → 0.3.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.js +427 -368
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -2,11 +2,70 @@
|
|
|
2
2
|
import { EventEmitter } from "events";
|
|
3
3
|
import { randomBytes } from "crypto";
|
|
4
4
|
|
|
5
|
-
// ../../packages/core/dist/
|
|
5
|
+
// ../../packages/core/dist/chunk-6H2LDEB7.js
|
|
6
6
|
import { z } from "zod";
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
var ULID_BODY = "[0-9A-HJKMNP-TV-Z]{26}";
|
|
8
|
+
function prefixedId(prefix) {
|
|
9
|
+
return z.string().regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a "${prefix}_" prefixed id`);
|
|
10
|
+
}
|
|
11
|
+
var OrgId = prefixedId("org");
|
|
12
|
+
var AgentId = prefixedId("agt");
|
|
13
|
+
var PolicyId = prefixedId("pol");
|
|
14
|
+
var IntentId = prefixedId("int");
|
|
15
|
+
var DecisionId = prefixedId("dec");
|
|
16
|
+
var ReceiptId = prefixedId("rcp");
|
|
17
|
+
var SessionId = prefixedId("ses");
|
|
18
|
+
var GateReceiptId = prefixedId("grc");
|
|
19
|
+
var ApiKeyId = prefixedId("key");
|
|
20
|
+
var ApproverKeyId = prefixedId("apk");
|
|
21
|
+
var ApiKeyScope = z.enum(["read", "evaluate", "approve", "report", "admin"]);
|
|
22
|
+
var ApiKey = z.object({
|
|
23
|
+
id: ApiKeyId,
|
|
24
|
+
name: z.string().min(1).max(200),
|
|
25
|
+
scopes: z.array(ApiKeyScope).min(1),
|
|
26
|
+
/**
|
|
27
|
+
* The org this key acts inside. ABSENT means unscoped — an operator key that
|
|
28
|
+
* reads and writes across every org, which is what a self-hosted single-org
|
|
29
|
+
* deployment and every env-seeded boot secret have always been. That is the
|
|
30
|
+
* compatibility rule the whole tenancy design rests on: adding tenancy
|
|
31
|
+
* changed no existing key's behaviour, because no existing key has this
|
|
32
|
+
* field.
|
|
33
|
+
*
|
|
34
|
+
* Present, it is a hard confinement, not a default: the key cannot read,
|
|
35
|
+
* spend, approve or govern outside the org, and a write it submits is
|
|
36
|
+
* stamped with this org rather than the one the body asked for.
|
|
37
|
+
*/
|
|
38
|
+
orgId: OrgId.optional(),
|
|
39
|
+
/**
|
|
40
|
+
* Narrow an org-scoped key further, to specific agents — what an agent
|
|
41
|
+
* runtime should carry, so a stolen key spends one agent's budget rather
|
|
42
|
+
* than the org's. Only meaningful alongside {@link ApiKey.orgId}: agent
|
|
43
|
+
* narrowing without an org is refused at issuance, because the scope it
|
|
44
|
+
* would describe has no org to resolve policies and approvers in.
|
|
45
|
+
*
|
|
46
|
+
* Capped at 64: a list long enough to need more is a fleet, and a fleet is
|
|
47
|
+
* what the org scope is for.
|
|
48
|
+
*/
|
|
49
|
+
agentIds: z.array(AgentId).max(64).optional(),
|
|
50
|
+
createdAt: z.coerce.date(),
|
|
51
|
+
/** Last successful authentication, for spotting keys that can be retired. */
|
|
52
|
+
lastUsedAt: z.coerce.date().optional(),
|
|
53
|
+
/** Set by revoke(); a revoked key never authenticates again. */
|
|
54
|
+
revokedAt: z.coerce.date().optional(),
|
|
55
|
+
/** Set by rotate(); with `previousSecretExpiresAt` it dates the overlap. */
|
|
56
|
+
rotatedAt: z.coerce.date().optional()
|
|
57
|
+
});
|
|
58
|
+
var ApiKeyRecord = ApiKey.extend({
|
|
59
|
+
secretHash: z.string(),
|
|
60
|
+
previousSecretHash: z.string().optional(),
|
|
61
|
+
previousSecretExpiresAt: z.coerce.date().optional()
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// ../../packages/core/dist/index.js
|
|
65
|
+
import { z as z2 } from "zod";
|
|
66
|
+
var Chain = z2.enum(["base", "solana", "polygon", "bnb"]);
|
|
67
|
+
var Asset = z2.enum(["USDC", "USDT", "EURC"]);
|
|
68
|
+
var DecimalString = z2.string().regex(/^\d+(\.\d+)?$/, 'must be a non-negative decimal string, e.g. "5.00"');
|
|
10
69
|
var DECIMAL_RE = /^\d+(\.\d+)?$/;
|
|
11
70
|
function isValidDecimal(value) {
|
|
12
71
|
return DECIMAL_RE.test(value);
|
|
@@ -35,39 +94,25 @@ function compareDecimal(a, b) {
|
|
|
35
94
|
const bv = toScaled(b, scale);
|
|
36
95
|
return av < bv ? -1 : av > bv ? 1 : 0;
|
|
37
96
|
}
|
|
38
|
-
var
|
|
39
|
-
|
|
40
|
-
return z.string().regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a "${prefix}_" prefixed id`);
|
|
41
|
-
}
|
|
42
|
-
var OrgId = prefixedId("org");
|
|
43
|
-
var AgentId = prefixedId("agt");
|
|
44
|
-
var PolicyId = prefixedId("pol");
|
|
45
|
-
var IntentId = prefixedId("int");
|
|
46
|
-
var DecisionId = prefixedId("dec");
|
|
47
|
-
var ReceiptId = prefixedId("rcp");
|
|
48
|
-
var SessionId = prefixedId("ses");
|
|
49
|
-
var GateReceiptId = prefixedId("grc");
|
|
50
|
-
var ApiKeyId = prefixedId("key");
|
|
51
|
-
var ApproverKeyId = prefixedId("apk");
|
|
52
|
-
var EnforcementMode = z.enum(["observed", "sdk", "session-key"]);
|
|
53
|
-
var AgentWallet = z.object({
|
|
97
|
+
var EnforcementMode = z2.enum(["observed", "sdk", "session-key"]);
|
|
98
|
+
var AgentWallet = z2.object({
|
|
54
99
|
chain: Chain,
|
|
55
|
-
address:
|
|
100
|
+
address: z2.string().min(1),
|
|
56
101
|
mode: EnforcementMode
|
|
57
102
|
});
|
|
58
|
-
var AgentStatus =
|
|
59
|
-
var AgentLabel =
|
|
60
|
-
var Agent =
|
|
103
|
+
var AgentStatus = z2.enum(["active", "frozen"]);
|
|
104
|
+
var AgentLabel = z2.string().max(40).regex(/^[a-z0-9][a-z0-9-]*$/, 'label must be a lowercase slug like "research" or "prod-trading"');
|
|
105
|
+
var Agent = z2.object({
|
|
61
106
|
id: AgentId,
|
|
62
107
|
orgId: OrgId,
|
|
63
|
-
name:
|
|
108
|
+
name: z2.string().min(1).max(200),
|
|
64
109
|
/** On-chain ERC-8004 identity, if the agent is registered. */
|
|
65
|
-
erc8004Id:
|
|
110
|
+
erc8004Id: z2.string().optional(),
|
|
66
111
|
/** Semantic grouping labels — the targets of policy `appliesTo.labels`. */
|
|
67
|
-
labels:
|
|
68
|
-
wallets:
|
|
112
|
+
labels: z2.array(AgentLabel).max(16).refine((ls) => new Set(ls).size === ls.length, { message: "labels must be unique" }).default([]),
|
|
113
|
+
wallets: z2.array(AgentWallet).default([]),
|
|
69
114
|
status: AgentStatus.default("active"),
|
|
70
|
-
createdAt:
|
|
115
|
+
createdAt: z2.coerce.date()
|
|
71
116
|
});
|
|
72
117
|
var ID_PATTERN = /^eip155:(\d+):(0x[0-9a-fA-F]{40})\/(\d+)$/;
|
|
73
118
|
function parseErc8004Id(value) {
|
|
@@ -81,33 +126,33 @@ function parseErc8004Id(value) {
|
|
|
81
126
|
tokenId: BigInt(match[3])
|
|
82
127
|
};
|
|
83
128
|
}
|
|
84
|
-
var Erc8004Id =
|
|
129
|
+
var Erc8004Id = z2.string().refine((value) => parseErc8004Id(value) !== void 0, {
|
|
85
130
|
message: 'expected "eip155:{chainId}:{registry}/{tokenId}"'
|
|
86
131
|
});
|
|
87
|
-
var Vendor =
|
|
88
|
-
host:
|
|
89
|
-
address:
|
|
90
|
-
erc8004Id:
|
|
132
|
+
var Vendor = z2.object({
|
|
133
|
+
host: z2.string().min(1),
|
|
134
|
+
address: z2.string().min(1),
|
|
135
|
+
erc8004Id: z2.string().optional()
|
|
91
136
|
});
|
|
92
|
-
var TaskContext =
|
|
93
|
-
taskId:
|
|
94
|
-
parentRunId:
|
|
95
|
-
purpose:
|
|
137
|
+
var TaskContext = z2.object({
|
|
138
|
+
taskId: z2.string().optional(),
|
|
139
|
+
parentRunId: z2.string().optional(),
|
|
140
|
+
purpose: z2.string().max(500).optional()
|
|
96
141
|
});
|
|
97
|
-
var PaymentIntent =
|
|
142
|
+
var PaymentIntent = z2.object({
|
|
98
143
|
id: IntentId,
|
|
99
144
|
agentId: AgentId,
|
|
100
145
|
vendor: Vendor,
|
|
101
|
-
resource:
|
|
146
|
+
resource: z2.string(),
|
|
102
147
|
amount: DecimalString,
|
|
103
148
|
asset: Asset,
|
|
104
149
|
chain: Chain,
|
|
105
150
|
taskContext: TaskContext.default({}),
|
|
106
|
-
nonce:
|
|
107
|
-
createdAt:
|
|
151
|
+
nonce: z2.string().min(1),
|
|
152
|
+
createdAt: z2.coerce.date()
|
|
108
153
|
});
|
|
109
|
-
var DecisionOutcome =
|
|
110
|
-
var Decision =
|
|
154
|
+
var DecisionOutcome = z2.enum(["allow", "deny", "escalate"]);
|
|
155
|
+
var Decision = z2.object({
|
|
111
156
|
id: DecisionId,
|
|
112
157
|
intentId: IntentId,
|
|
113
158
|
/**
|
|
@@ -116,114 +161,115 @@ var Decision = z.object({
|
|
|
116
161
|
* chain — so a signer can verify an {intent, decision} pair offline as a
|
|
117
162
|
* self-contained spend voucher, not just a reference by id.
|
|
118
163
|
*/
|
|
119
|
-
intentHash:
|
|
164
|
+
intentHash: z2.string(),
|
|
120
165
|
outcome: DecisionOutcome,
|
|
121
166
|
/** Ids of the rules that fired, for explainability. */
|
|
122
|
-
matchedRules:
|
|
167
|
+
matchedRules: z2.array(z2.string()).default([]),
|
|
123
168
|
/** Human-readable explanation surfaced in the dashboard. */
|
|
124
|
-
reason:
|
|
125
|
-
policyId:
|
|
126
|
-
policyVersion:
|
|
169
|
+
reason: z2.string().optional(),
|
|
170
|
+
policyId: z2.string(),
|
|
171
|
+
policyVersion: z2.string(),
|
|
127
172
|
/** Hash of the previous decision in the chain (tamper-evident log). */
|
|
128
|
-
prevHash:
|
|
173
|
+
prevHash: z2.string(),
|
|
129
174
|
/** Hash of this decision's canonical content. */
|
|
130
|
-
hash:
|
|
175
|
+
hash: z2.string(),
|
|
131
176
|
/** Service signing-key signature over `hash`. */
|
|
132
|
-
signature:
|
|
133
|
-
latencyMs:
|
|
134
|
-
decidedAt:
|
|
177
|
+
signature: z2.string(),
|
|
178
|
+
latencyMs: z2.number().nonnegative(),
|
|
179
|
+
decidedAt: z2.coerce.date()
|
|
135
180
|
});
|
|
136
|
-
var
|
|
181
|
+
var AttributedDecision = Decision.extend({ agentId: AgentId.optional() });
|
|
182
|
+
var Session = z2.object({
|
|
137
183
|
id: SessionId,
|
|
138
184
|
agentId: AgentId,
|
|
139
185
|
/** sha256 hex of the bearer token. */
|
|
140
|
-
tokenHash:
|
|
186
|
+
tokenHash: z2.string(),
|
|
141
187
|
/** Cumulative ceiling across the session's lifetime. Absent = uncapped. */
|
|
142
188
|
capAmount: DecimalString.optional(),
|
|
143
189
|
/** Ceiling per individual signature. Absent = uncapped. */
|
|
144
190
|
maxPerPayment: DecimalString.optional(),
|
|
145
|
-
expiresAt:
|
|
146
|
-
createdAt:
|
|
147
|
-
revokedAt:
|
|
191
|
+
expiresAt: z2.coerce.date(),
|
|
192
|
+
createdAt: z2.coerce.date(),
|
|
193
|
+
revokedAt: z2.coerce.date().optional()
|
|
148
194
|
});
|
|
149
|
-
var SettledPayment =
|
|
195
|
+
var SettledPayment = z2.object({
|
|
150
196
|
intentId: IntentId,
|
|
151
|
-
txHash:
|
|
197
|
+
txHash: z2.string(),
|
|
152
198
|
chain: Chain,
|
|
153
|
-
blockNumber:
|
|
154
|
-
facilitator:
|
|
199
|
+
blockNumber: z2.coerce.bigint(),
|
|
200
|
+
facilitator: z2.string().optional(),
|
|
155
201
|
feePaid: DecimalString.optional(),
|
|
156
|
-
confirmedAt:
|
|
202
|
+
confirmedAt: z2.coerce.date()
|
|
157
203
|
});
|
|
158
|
-
var SettlementReport =
|
|
204
|
+
var SettlementReport = z2.object({
|
|
159
205
|
intentId: IntentId,
|
|
160
206
|
/** The settling transaction, when the observer saw one. */
|
|
161
|
-
txHash:
|
|
207
|
+
txHash: z2.string().optional(),
|
|
162
208
|
chain: Chain.optional(),
|
|
163
209
|
/** The amount as SETTLED, when known — may differ from the amount allowed. */
|
|
164
210
|
amount: DecimalString.optional(),
|
|
165
211
|
/** Free-form observer tag, e.g. "indexer", "guard", "facilitator". */
|
|
166
|
-
source:
|
|
167
|
-
confirmedAt:
|
|
212
|
+
source: z2.string().min(1).max(64).optional(),
|
|
213
|
+
confirmedAt: z2.coerce.date()
|
|
168
214
|
});
|
|
169
|
-
var ReceiptSettlement =
|
|
170
|
-
txHash:
|
|
171
|
-
networkId:
|
|
215
|
+
var ReceiptSettlement = z2.object({
|
|
216
|
+
txHash: z2.string().optional(),
|
|
217
|
+
networkId: z2.string().optional(),
|
|
172
218
|
/** Raw header payload, kept for forensics until the indexer confirms. */
|
|
173
|
-
raw:
|
|
219
|
+
raw: z2.string().optional()
|
|
174
220
|
});
|
|
175
|
-
var Receipt =
|
|
221
|
+
var Receipt = z2.object({
|
|
176
222
|
id: ReceiptId,
|
|
177
223
|
agentId: AgentId,
|
|
178
224
|
intentId: IntentId,
|
|
179
225
|
decisionId: DecisionId,
|
|
180
226
|
outcome: DecisionOutcome,
|
|
181
227
|
/** The URL the agent actually fetched (the paywalled resource). */
|
|
182
|
-
url:
|
|
183
|
-
method:
|
|
184
|
-
vendorHost:
|
|
228
|
+
url: z2.string(),
|
|
229
|
+
method: z2.string().default("GET"),
|
|
230
|
+
vendorHost: z2.string(),
|
|
185
231
|
amount: DecimalString,
|
|
186
232
|
asset: Asset,
|
|
187
233
|
chain: Chain,
|
|
188
234
|
taskContext: TaskContext.default({}),
|
|
189
235
|
/** Human-readable explanation copied from the decision. */
|
|
190
|
-
reason:
|
|
236
|
+
reason: z2.string().optional(),
|
|
191
237
|
/** Present only once a payment was made and the vendor confirmed it. */
|
|
192
238
|
settlement: ReceiptSettlement.optional(),
|
|
193
|
-
createdAt:
|
|
239
|
+
createdAt: z2.coerce.date()
|
|
194
240
|
});
|
|
195
|
-
var GateReceipt =
|
|
241
|
+
var GateReceipt = z2.object({
|
|
196
242
|
id: GateReceiptId,
|
|
197
|
-
at:
|
|
243
|
+
at: z2.coerce.date(),
|
|
198
244
|
/** The route pattern that priced this request, e.g. "/api/reports/*". */
|
|
199
|
-
route:
|
|
245
|
+
route: z2.string().min(1),
|
|
200
246
|
/** The concrete resource paid for (URL path actually requested). */
|
|
201
|
-
resource:
|
|
202
|
-
method:
|
|
247
|
+
resource: z2.string().min(1),
|
|
248
|
+
method: z2.string().min(1),
|
|
203
249
|
/** The paying wallet address, as asserted by the settled payment. */
|
|
204
|
-
payer:
|
|
205
|
-
payTo:
|
|
250
|
+
payer: z2.string().min(1),
|
|
251
|
+
payTo: z2.string().min(1),
|
|
206
252
|
/** Human-unit decimal amount, e.g. "0.05". */
|
|
207
253
|
amount: DecimalString,
|
|
208
254
|
/** The same amount in the asset's atomic units, e.g. "50000". */
|
|
209
|
-
amountAtomic:
|
|
255
|
+
amountAtomic: z2.string().regex(/^\d+$/, "atomic amount must be an integer string"),
|
|
210
256
|
/** Token symbol or contract address, exactly as quoted in the requirement. */
|
|
211
|
-
asset:
|
|
212
|
-
network:
|
|
257
|
+
asset: z2.string().min(1),
|
|
258
|
+
network: z2.string().min(1),
|
|
213
259
|
/** Settlement transaction hash (mock ledger or on-chain). */
|
|
214
|
-
transaction:
|
|
260
|
+
transaction: z2.string().min(1)
|
|
215
261
|
});
|
|
216
|
-
var Window =
|
|
217
|
-
var Multiplier =
|
|
218
|
-
var Condition =
|
|
262
|
+
var Window = z2.string().regex(/^\d+[smhd]$/, 'window must be like "30s", "15m", "1h", or "7d"');
|
|
263
|
+
var Multiplier = z2.string().regex(/^\d+(\.\d+)?x$/, 'multiplier must be like "3x"');
|
|
264
|
+
var Condition = z2.object({
|
|
219
265
|
/** Per-transaction amount exceeds this value. */
|
|
220
266
|
amountGt: DecimalString.optional(),
|
|
221
267
|
/** Sum of spend in a rolling window exceeds `gt`. */
|
|
222
|
-
rollingSum:
|
|
268
|
+
rollingSum: z2.object({ window: Window, gt: DecimalString }).optional(),
|
|
223
269
|
/** Transaction count in a rolling window exceeds `gt`. */
|
|
224
|
-
txCount:
|
|
270
|
+
txCount: z2.object({ window: Window, gt: z2.number().int().nonnegative() }).optional(),
|
|
225
271
|
/** Vendor host matches one of these patterns (supports `*` globs). */
|
|
226
|
-
vendorHostIn:
|
|
272
|
+
vendorHostIn: z2.array(z2.string()).optional(),
|
|
227
273
|
/**
|
|
228
274
|
* Resource PATH matches one of these patterns (supports `*` globs, e.g.
|
|
229
275
|
* "/v1/reports/*"). A full-URL resource is reduced to its pathname before
|
|
@@ -231,13 +277,13 @@ var Condition = z.object({
|
|
|
231
277
|
* vendor declares "https://api.x.com/v1/answer" or "/v1/answer". Pair
|
|
232
278
|
* with `vendorHostIn` to scope a path rule to specific vendors.
|
|
233
279
|
*/
|
|
234
|
-
resourceIn:
|
|
280
|
+
resourceIn: z2.array(z2.string()).optional(),
|
|
235
281
|
/** First time Rein has seen this vendor for the agent. */
|
|
236
|
-
vendorFirstSeen:
|
|
282
|
+
vendorFirstSeen: z2.boolean().optional(),
|
|
237
283
|
/** Vendor reputation score is below this threshold (Phase 3 hook). */
|
|
238
|
-
vendorReputationLt:
|
|
284
|
+
vendorReputationLt: z2.number().min(0).max(100).optional(),
|
|
239
285
|
/** Amount is more than `gt`-times the observed median for this resource. */
|
|
240
|
-
amountVsResourceMedian:
|
|
286
|
+
amountVsResourceMedian: z2.object({ gt: Multiplier }).optional(),
|
|
241
287
|
/**
|
|
242
288
|
* Cumulative spend attributed to THIS intent's `taskContext.taskId`
|
|
243
289
|
* (prior spend on the task plus this payment) exceeds `gt`. Scopes a
|
|
@@ -250,21 +296,21 @@ var Condition = z.object({
|
|
|
250
296
|
* a budget — otherwise every untagged probe payment would trip every
|
|
251
297
|
* task budget in the policy.
|
|
252
298
|
*/
|
|
253
|
-
taskBudget:
|
|
299
|
+
taskBudget: z2.object({ gt: DecimalString }).optional(),
|
|
254
300
|
/** The intent carries no `taskContext.taskId` (or an empty one). */
|
|
255
|
-
taskIdMissing:
|
|
301
|
+
taskIdMissing: z2.boolean().optional()
|
|
256
302
|
}).refine((c) => Object.values(c).some((v) => v !== void 0), {
|
|
257
303
|
message: "a condition must specify at least one predicate"
|
|
258
304
|
});
|
|
259
|
-
var Breaker =
|
|
260
|
-
id:
|
|
305
|
+
var Breaker = z2.object({
|
|
306
|
+
id: z2.string().min(1),
|
|
261
307
|
/** The trailing span the tripwires measure over. */
|
|
262
308
|
window: Window,
|
|
263
309
|
/**
|
|
264
310
|
* Trip when the window would hold MORE than this many transactions.
|
|
265
311
|
* `10` permits ten in the window and escalates the eleventh.
|
|
266
312
|
*/
|
|
267
|
-
txCount:
|
|
313
|
+
txCount: z2.number().int().positive().optional(),
|
|
268
314
|
/**
|
|
269
315
|
* Trip when the window's spend would exceed this total. `"50.00"` permits
|
|
270
316
|
* a window totalling exactly 50.00 and escalates the payment that would
|
|
@@ -276,120 +322,122 @@ var Breaker = z.object({
|
|
|
276
322
|
}).refine((b) => b.txCount !== void 0 || b.valueCap !== void 0, {
|
|
277
323
|
message: "a breaker must specify at least one of txCount / valueCap"
|
|
278
324
|
});
|
|
279
|
-
var Rule =
|
|
280
|
-
id:
|
|
325
|
+
var Rule = z2.object({
|
|
326
|
+
id: z2.string().min(1),
|
|
281
327
|
allow: Condition.optional(),
|
|
282
328
|
deny: Condition.optional(),
|
|
283
329
|
escalate: Condition.optional()
|
|
284
330
|
}).refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== void 0).length === 1, {
|
|
285
331
|
message: "a rule must specify exactly one of allow / deny / escalate"
|
|
286
332
|
});
|
|
287
|
-
var PolicyDefault =
|
|
288
|
-
var AppliesTo =
|
|
333
|
+
var PolicyDefault = z2.enum(["allow", "deny"]);
|
|
334
|
+
var AppliesTo = z2.object({
|
|
289
335
|
/** Agent id patterns (supports `*` globs, e.g. "agt_research_*"). */
|
|
290
|
-
agents:
|
|
336
|
+
agents: z2.array(z2.string()).optional(),
|
|
291
337
|
/**
|
|
292
338
|
* Agent label patterns (supports `*` globs) — semantic targeting. Matches
|
|
293
339
|
* when the agent carries at least one label matching any pattern. Requires
|
|
294
340
|
* the agent DOCUMENT: an intent from an unregistered agent never matches a
|
|
295
341
|
* labels-targeted policy (and so fails closed when no other policy applies).
|
|
296
342
|
*/
|
|
297
|
-
labels:
|
|
298
|
-
chains:
|
|
343
|
+
labels: z2.array(z2.string()).optional(),
|
|
344
|
+
chains: z2.array(Chain).optional()
|
|
299
345
|
});
|
|
300
|
-
var Escalation =
|
|
301
|
-
approvers:
|
|
346
|
+
var Escalation = z2.object({
|
|
347
|
+
approvers: z2.array(z2.string()).default([]),
|
|
302
348
|
timeoutAction: PolicyDefault.default("deny"),
|
|
303
|
-
timeoutMin:
|
|
349
|
+
timeoutMin: z2.number().int().positive().default(15)
|
|
304
350
|
});
|
|
305
|
-
var Policy =
|
|
306
|
-
policyId:
|
|
307
|
-
version:
|
|
351
|
+
var Policy = z2.object({
|
|
352
|
+
policyId: z2.string().min(1),
|
|
353
|
+
version: z2.string().default("1"),
|
|
354
|
+
/**
|
|
355
|
+
* The org this policy governs. ABSENT means GLOBAL — it is considered for
|
|
356
|
+
* every agent, which is what every policy written before tenancy existed is
|
|
357
|
+
* and stays.
|
|
358
|
+
*
|
|
359
|
+
* This is separate from {@link AppliesTo} on purpose, and it has to be:
|
|
360
|
+
* `appliesTo: {}` matches every agent, so a tenant's policy carrying the
|
|
361
|
+
* default targeting would otherwise govern other tenants' agents the moment
|
|
362
|
+
* it was written. Org scoping is applied BEFORE targeting — a policy whose
|
|
363
|
+
* `orgId` is not the agent's org is not a candidate at all.
|
|
364
|
+
*/
|
|
365
|
+
orgId: OrgId.optional(),
|
|
308
366
|
appliesTo: AppliesTo.default({}),
|
|
309
|
-
rules:
|
|
367
|
+
rules: z2.array(Rule).default([]),
|
|
310
368
|
/**
|
|
311
369
|
* Behavioral breakers evaluated alongside the rules. A tripped breaker
|
|
312
370
|
* escalates at the same precedence as an `escalate` rule — so an explicit
|
|
313
371
|
* DENY still wins, and an ALLOW rule cannot wave past a tripped breaker.
|
|
314
372
|
*/
|
|
315
|
-
breakers:
|
|
373
|
+
breakers: z2.array(Breaker).default([]),
|
|
316
374
|
default: PolicyDefault.default("deny"),
|
|
317
375
|
/** Below this amount, fail-open is permitted during a policy-service outage. */
|
|
318
376
|
denyFloor: DecimalString.default("0.05"),
|
|
319
377
|
escalation: Escalation.optional()
|
|
320
378
|
});
|
|
321
|
-
var LivenessSource =
|
|
379
|
+
var LivenessSource = z2.enum([
|
|
322
380
|
/** It submitted an intent — ANY outcome, including a denial. */
|
|
323
381
|
"intent",
|
|
324
382
|
/** It reported in explicitly, having nothing to buy. */
|
|
325
383
|
"heartbeat"
|
|
326
384
|
]);
|
|
327
385
|
var DEFAULT_LIVENESS_GRACE_MS = 6e4;
|
|
328
|
-
var LivenessExpectation =
|
|
386
|
+
var LivenessExpectation = z2.object({
|
|
329
387
|
agentId: AgentId,
|
|
330
388
|
/** Longest silence still considered normal, e.g. '15m'. */
|
|
331
389
|
interval: Window,
|
|
332
390
|
/** Extra slack past `interval` before the silence is an alarm. */
|
|
333
|
-
graceMs:
|
|
391
|
+
graceMs: z2.number().int().nonnegative().default(DEFAULT_LIVENESS_GRACE_MS),
|
|
334
392
|
/**
|
|
335
393
|
* When watching began. An agent that has NEVER been seen is measured from
|
|
336
394
|
* here, so a watch on an agent that never starts does raise an alarm — a
|
|
337
395
|
* detector that never came up is exactly as dead as one that stopped.
|
|
338
396
|
*/
|
|
339
|
-
since:
|
|
397
|
+
since: z2.coerce.date(),
|
|
340
398
|
/** What this agent is supposed to be doing, shown beside the alarm. */
|
|
341
|
-
note:
|
|
399
|
+
note: z2.string().max(200).optional()
|
|
342
400
|
});
|
|
343
401
|
var LivenessWatchInput = LivenessExpectation.omit({ since: true }).extend({
|
|
344
|
-
graceMs:
|
|
402
|
+
graceMs: z2.number().int().nonnegative().optional()
|
|
345
403
|
});
|
|
346
|
-
var Heartbeat =
|
|
404
|
+
var Heartbeat = z2.object({
|
|
347
405
|
agentId: AgentId,
|
|
348
406
|
/** When the agent was alive. Defaults to arrival time. */
|
|
349
|
-
at:
|
|
407
|
+
at: z2.coerce.date().optional(),
|
|
350
408
|
/** Free-form note from the reporter, e.g. "poll cycle 41 ok". */
|
|
351
|
-
note:
|
|
409
|
+
note: z2.string().max(200).optional()
|
|
352
410
|
});
|
|
353
|
-
var LivenessStatus =
|
|
354
|
-
var
|
|
355
|
-
var
|
|
356
|
-
|
|
357
|
-
name: z.string().min(1).max(200),
|
|
358
|
-
scopes: z.array(ApiKeyScope).min(1),
|
|
359
|
-
createdAt: z.coerce.date(),
|
|
360
|
-
/** Last successful authentication, for spotting keys that can be retired. */
|
|
361
|
-
lastUsedAt: z.coerce.date().optional(),
|
|
362
|
-
/** Set by revoke(); a revoked key never authenticates again. */
|
|
363
|
-
revokedAt: z.coerce.date().optional(),
|
|
364
|
-
/** Set by rotate(); with `previousSecretExpiresAt` it dates the overlap. */
|
|
365
|
-
rotatedAt: z.coerce.date().optional()
|
|
366
|
-
});
|
|
367
|
-
var ApiKeyRecord = ApiKey.extend({
|
|
368
|
-
secretHash: z.string(),
|
|
369
|
-
previousSecretHash: z.string().optional(),
|
|
370
|
-
previousSecretExpiresAt: z.coerce.date().optional()
|
|
371
|
-
});
|
|
372
|
-
var ApprovalVerdict = z.enum(["approve", "reject"]);
|
|
373
|
-
var ApprovalStatus = z.enum(["pending", "approved", "rejected", "expired"]);
|
|
374
|
-
var ApproverKey = z.object({
|
|
411
|
+
var LivenessStatus = z2.enum(["alive", "late", "missing", "unknown"]);
|
|
412
|
+
var ApprovalVerdict = z2.enum(["approve", "reject"]);
|
|
413
|
+
var ApprovalStatus = z2.enum(["pending", "approved", "rejected", "expired"]);
|
|
414
|
+
var ApproverKey = z2.object({
|
|
375
415
|
id: ApproverKeyId,
|
|
376
416
|
orgId: OrgId,
|
|
377
|
-
name:
|
|
417
|
+
name: z2.string().min(1).max(200),
|
|
378
418
|
/** ed25519 public key, SPKI PEM — the same encoding as the decision log's. */
|
|
379
|
-
publicKey:
|
|
380
|
-
algorithm:
|
|
381
|
-
createdAt:
|
|
382
|
-
revokedAt:
|
|
419
|
+
publicKey: z2.string().min(1),
|
|
420
|
+
algorithm: z2.literal("ed25519").default("ed25519"),
|
|
421
|
+
createdAt: z2.coerce.date(),
|
|
422
|
+
revokedAt: z2.coerce.date().optional()
|
|
383
423
|
});
|
|
384
|
-
var ApprovalRequest =
|
|
424
|
+
var ApprovalRequest = z2.object({
|
|
385
425
|
/** The `escalate` decision this request answers (primary key). */
|
|
386
426
|
decisionId: DecisionId,
|
|
387
427
|
intentId: IntentId,
|
|
388
428
|
/** Binds the approval to the exact transfer — the signed bytes commit to it. */
|
|
389
|
-
intentHash:
|
|
429
|
+
intentHash: z2.string(),
|
|
390
430
|
agentId: AgentId,
|
|
391
|
-
|
|
392
|
-
|
|
431
|
+
/**
|
|
432
|
+
* The org the escalating agent belongs to, stamped when the request is
|
|
433
|
+
* parked. ABSENT means the agent was never registered (or the request
|
|
434
|
+
* predates tenancy), and such a request is answerable only by an unscoped
|
|
435
|
+
* operator — there is no org to check an approver against, and guessing one
|
|
436
|
+
* is how a cross-tenant approval happens.
|
|
437
|
+
*/
|
|
438
|
+
orgId: OrgId.optional(),
|
|
439
|
+
vendorHost: z2.string(),
|
|
440
|
+
resource: z2.string(),
|
|
393
441
|
amount: DecimalString,
|
|
394
442
|
asset: Asset,
|
|
395
443
|
chain: Chain,
|
|
@@ -399,9 +447,9 @@ var ApprovalRequest = z.object({
|
|
|
399
447
|
* id on the way through would make the budget silently under-count exactly
|
|
400
448
|
* the payments a human had to look at.
|
|
401
449
|
*/
|
|
402
|
-
taskId:
|
|
450
|
+
taskId: z2.string().optional(),
|
|
403
451
|
/** Why policy escalated, verbatim from the decision. */
|
|
404
|
-
reason:
|
|
452
|
+
reason: z2.string(),
|
|
405
453
|
/**
|
|
406
454
|
* Breaker ids whose trip contributed to this escalation. An approval of
|
|
407
455
|
* this request resets exactly these — moving their counting floor to the
|
|
@@ -409,12 +457,12 @@ var ApprovalRequest = z.object({
|
|
|
409
457
|
* behavior that stopped it, rather than being asked again immediately.
|
|
410
458
|
* Empty when ordinary rules did the escalating.
|
|
411
459
|
*/
|
|
412
|
-
breakers:
|
|
460
|
+
breakers: z2.array(z2.string()).default([]),
|
|
413
461
|
status: ApprovalStatus,
|
|
414
|
-
createdAt:
|
|
462
|
+
createdAt: z2.coerce.date(),
|
|
415
463
|
/** Past this instant the request denies, whatever arrives afterwards. */
|
|
416
|
-
expiresAt:
|
|
417
|
-
resolvedAt:
|
|
464
|
+
expiresAt: z2.coerce.date(),
|
|
465
|
+
resolvedAt: z2.coerce.date().optional(),
|
|
418
466
|
/** Which registered key signed — absent when the TTL lapsed instead. */
|
|
419
467
|
approverKeyId: ApproverKeyId.optional(),
|
|
420
468
|
/**
|
|
@@ -424,117 +472,117 @@ var ApprovalRequest = z.object({
|
|
|
424
472
|
*/
|
|
425
473
|
finalDecisionId: DecisionId.optional()
|
|
426
474
|
});
|
|
427
|
-
var ApprovalChallenges =
|
|
428
|
-
approve:
|
|
429
|
-
reject:
|
|
475
|
+
var ApprovalChallenges = z2.object({
|
|
476
|
+
approve: z2.string(),
|
|
477
|
+
reject: z2.string()
|
|
430
478
|
});
|
|
431
|
-
var ApprovalGrant =
|
|
479
|
+
var ApprovalGrant = z2.object({
|
|
432
480
|
decisionId: DecisionId,
|
|
433
|
-
intentHash:
|
|
481
|
+
intentHash: z2.string(),
|
|
434
482
|
verdict: ApprovalVerdict,
|
|
435
483
|
approverKeyId: ApproverKeyId,
|
|
436
|
-
signature:
|
|
484
|
+
signature: z2.string().min(1)
|
|
437
485
|
});
|
|
438
|
-
var ReputationSubject =
|
|
439
|
-
kind:
|
|
440
|
-
id:
|
|
486
|
+
var ReputationSubject = z2.object({
|
|
487
|
+
kind: z2.enum(["agent", "vendor"]),
|
|
488
|
+
id: z2.string()
|
|
441
489
|
});
|
|
442
|
-
var ReputationComponents =
|
|
443
|
-
volume:
|
|
444
|
-
longevity:
|
|
445
|
-
disputeRate:
|
|
446
|
-
counterpartyQuality:
|
|
447
|
-
settlementReliability:
|
|
490
|
+
var ReputationComponents = z2.object({
|
|
491
|
+
volume: z2.number(),
|
|
492
|
+
longevity: z2.number(),
|
|
493
|
+
disputeRate: z2.number(),
|
|
494
|
+
counterpartyQuality: z2.number(),
|
|
495
|
+
settlementReliability: z2.number()
|
|
448
496
|
});
|
|
449
|
-
var ReputationScore =
|
|
497
|
+
var ReputationScore = z2.object({
|
|
450
498
|
subject: ReputationSubject,
|
|
451
|
-
score:
|
|
499
|
+
score: z2.number().min(0).max(100),
|
|
452
500
|
components: ReputationComponents,
|
|
453
|
-
confidence:
|
|
454
|
-
asOf:
|
|
501
|
+
confidence: z2.number().min(0).max(1),
|
|
502
|
+
asOf: z2.coerce.date(),
|
|
455
503
|
/** Hash-anchored attestation, optionally published on-chain (ERC-8004). */
|
|
456
|
-
evidenceUri:
|
|
504
|
+
evidenceUri: z2.string().optional()
|
|
457
505
|
});
|
|
458
|
-
var ReinEvent =
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
type:
|
|
464
|
-
at:
|
|
506
|
+
var ReinEvent = z2.discriminatedUnion("type", [
|
|
507
|
+
z2.object({ type: z2.literal("intent.created"), at: z2.coerce.date(), intent: PaymentIntent }),
|
|
508
|
+
z2.object({ type: z2.literal("decision.made"), at: z2.coerce.date(), decision: Decision }),
|
|
509
|
+
z2.object({ type: z2.literal("payment.settled"), at: z2.coerce.date(), payment: SettledPayment }),
|
|
510
|
+
z2.object({
|
|
511
|
+
type: z2.literal("shadow.spend"),
|
|
512
|
+
at: z2.coerce.date(),
|
|
465
513
|
agentId: AgentId,
|
|
466
|
-
txHash:
|
|
514
|
+
txHash: z2.string(),
|
|
467
515
|
chain: Chain,
|
|
468
516
|
amount: DecimalString
|
|
469
517
|
}),
|
|
470
|
-
|
|
471
|
-
type:
|
|
472
|
-
at:
|
|
518
|
+
z2.object({
|
|
519
|
+
type: z2.literal("signature.released"),
|
|
520
|
+
at: z2.coerce.date(),
|
|
473
521
|
sessionId: SessionId,
|
|
474
522
|
agentId: AgentId,
|
|
475
523
|
intentId: IntentId,
|
|
476
524
|
decisionId: DecisionId,
|
|
477
525
|
amount: DecimalString
|
|
478
526
|
}),
|
|
479
|
-
|
|
480
|
-
type:
|
|
481
|
-
at:
|
|
527
|
+
z2.object({
|
|
528
|
+
type: z2.literal("signature.refused"),
|
|
529
|
+
at: z2.coerce.date(),
|
|
482
530
|
/** Refusal code, e.g. "decision_replayed" (see @reinconsole/signer). */
|
|
483
|
-
code:
|
|
484
|
-
reason:
|
|
531
|
+
code: z2.string(),
|
|
532
|
+
reason: z2.string(),
|
|
485
533
|
sessionId: SessionId.optional(),
|
|
486
534
|
agentId: AgentId.optional(),
|
|
487
535
|
intentId: IntentId.optional()
|
|
488
536
|
}),
|
|
489
|
-
|
|
490
|
-
type:
|
|
491
|
-
at:
|
|
492
|
-
resource:
|
|
493
|
-
method:
|
|
537
|
+
z2.object({
|
|
538
|
+
type: z2.literal("gate.quoted"),
|
|
539
|
+
at: z2.coerce.date(),
|
|
540
|
+
resource: z2.string(),
|
|
541
|
+
method: z2.string(),
|
|
494
542
|
amount: DecimalString,
|
|
495
|
-
asset:
|
|
496
|
-
network:
|
|
543
|
+
asset: z2.string(),
|
|
544
|
+
network: z2.string()
|
|
497
545
|
}),
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
type:
|
|
501
|
-
at:
|
|
546
|
+
z2.object({ type: z2.literal("gate.settled"), at: z2.coerce.date(), receipt: GateReceipt }),
|
|
547
|
+
z2.object({
|
|
548
|
+
type: z2.literal("approval.requested"),
|
|
549
|
+
at: z2.coerce.date(),
|
|
502
550
|
request: ApprovalRequest
|
|
503
551
|
}),
|
|
504
|
-
|
|
505
|
-
type:
|
|
506
|
-
at:
|
|
552
|
+
z2.object({
|
|
553
|
+
type: z2.literal("approval.resolved"),
|
|
554
|
+
at: z2.coerce.date(),
|
|
507
555
|
request: ApprovalRequest,
|
|
508
556
|
/** The follow-up allow/deny decision this resolution appended. */
|
|
509
557
|
decision: Decision
|
|
510
558
|
}),
|
|
511
|
-
|
|
512
|
-
type:
|
|
513
|
-
at:
|
|
559
|
+
z2.object({
|
|
560
|
+
type: z2.literal("liveness.missing"),
|
|
561
|
+
at: z2.coerce.date(),
|
|
514
562
|
agentId: AgentId,
|
|
515
563
|
expectation: LivenessExpectation,
|
|
516
564
|
/** How long the agent has been silent when the alarm was raised. */
|
|
517
|
-
silentMs:
|
|
565
|
+
silentMs: z2.number().int().nonnegative(),
|
|
518
566
|
/** Last sighting, absent when the agent was never seen at all. */
|
|
519
|
-
lastSeenAt:
|
|
567
|
+
lastSeenAt: z2.coerce.date().optional()
|
|
520
568
|
}),
|
|
521
|
-
|
|
522
|
-
type:
|
|
523
|
-
at:
|
|
569
|
+
z2.object({
|
|
570
|
+
type: z2.literal("liveness.recovered"),
|
|
571
|
+
at: z2.coerce.date(),
|
|
524
572
|
agentId: AgentId,
|
|
525
573
|
/** How long the silence lasted, measured to this sighting. */
|
|
526
|
-
silentMs:
|
|
574
|
+
silentMs: z2.number().int().nonnegative(),
|
|
527
575
|
source: LivenessSource
|
|
528
576
|
}),
|
|
529
|
-
|
|
530
|
-
type:
|
|
531
|
-
at:
|
|
577
|
+
z2.object({
|
|
578
|
+
type: z2.literal("gate.refused"),
|
|
579
|
+
at: z2.coerce.date(),
|
|
532
580
|
/** Refusal code, e.g. "payment_replayed" (see @reinconsole/gate). */
|
|
533
|
-
code:
|
|
534
|
-
reason:
|
|
535
|
-
resource:
|
|
581
|
+
code: z2.string(),
|
|
582
|
+
reason: z2.string(),
|
|
583
|
+
resource: z2.string(),
|
|
536
584
|
/** Known only when the payment header decoded far enough to name a payer. */
|
|
537
|
-
payer:
|
|
585
|
+
payer: z2.string().optional()
|
|
538
586
|
})
|
|
539
587
|
]);
|
|
540
588
|
|
|
@@ -569,98 +617,103 @@ var MockLedger = class {
|
|
|
569
617
|
};
|
|
570
618
|
|
|
571
619
|
// ../../packages/sdk/dist/index.js
|
|
572
|
-
import { z as
|
|
573
|
-
var BreakerState =
|
|
620
|
+
import { z as z3 } from "zod";
|
|
621
|
+
var BreakerState = z3.object({
|
|
574
622
|
breaker: Breaker,
|
|
575
|
-
policyId:
|
|
576
|
-
txCount:
|
|
577
|
-
sum:
|
|
578
|
-
countingFrom:
|
|
579
|
-
resetAt:
|
|
580
|
-
tripped:
|
|
581
|
-
reason:
|
|
623
|
+
policyId: z3.string(),
|
|
624
|
+
txCount: z3.number(),
|
|
625
|
+
sum: z3.string(),
|
|
626
|
+
countingFrom: z3.number(),
|
|
627
|
+
resetAt: z3.number().optional(),
|
|
628
|
+
tripped: z3.boolean(),
|
|
629
|
+
reason: z3.string().optional()
|
|
582
630
|
});
|
|
583
|
-
var LivenessState =
|
|
584
|
-
agentId:
|
|
631
|
+
var LivenessState = z3.object({
|
|
632
|
+
agentId: z3.string(),
|
|
585
633
|
expectation: LivenessExpectation,
|
|
586
|
-
lastSeenAt:
|
|
634
|
+
lastSeenAt: z3.number().optional(),
|
|
587
635
|
lastSource: LivenessSource.optional(),
|
|
588
|
-
silentSince:
|
|
589
|
-
silentMs:
|
|
590
|
-
dueAt:
|
|
591
|
-
overdueAt:
|
|
636
|
+
silentSince: z3.number(),
|
|
637
|
+
silentMs: z3.number(),
|
|
638
|
+
dueAt: z3.number(),
|
|
639
|
+
overdueAt: z3.number(),
|
|
592
640
|
status: LivenessStatus,
|
|
593
|
-
alertedAt:
|
|
641
|
+
alertedAt: z3.number().optional()
|
|
594
642
|
});
|
|
595
|
-
var Health =
|
|
596
|
-
status:
|
|
597
|
-
publicKey:
|
|
643
|
+
var Health = z3.object({
|
|
644
|
+
status: z3.string(),
|
|
645
|
+
publicKey: z3.string(),
|
|
598
646
|
/** "api-key" once the engine demands a credential; "none" while it does not. */
|
|
599
|
-
auth:
|
|
600
|
-
approvals:
|
|
647
|
+
auth: z3.string().optional(),
|
|
648
|
+
approvals: z3.string().optional()
|
|
601
649
|
});
|
|
602
|
-
var EvaluateResponse =
|
|
650
|
+
var EvaluateResponse = z3.object({
|
|
603
651
|
intent: PaymentIntent,
|
|
604
652
|
decision: Decision,
|
|
605
653
|
/** Present when an escalation was parked for a signed verdict. */
|
|
606
654
|
approval: ApprovalRequest.optional()
|
|
607
655
|
});
|
|
608
|
-
var ApprovalView =
|
|
656
|
+
var ApprovalView = z3.object({
|
|
609
657
|
request: ApprovalRequest,
|
|
610
658
|
challenges: ApprovalChallenges,
|
|
611
659
|
/** The follow-up allow/deny decision, once the request has resolved. */
|
|
612
660
|
decision: Decision.optional()
|
|
613
661
|
});
|
|
614
|
-
var ResolveResponse =
|
|
615
|
-
var AllowanceGap =
|
|
616
|
-
intentId:
|
|
617
|
-
decisionId:
|
|
618
|
-
agentId:
|
|
619
|
-
host:
|
|
620
|
-
resource:
|
|
621
|
-
amount:
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
662
|
+
var ResolveResponse = z3.object({ request: ApprovalRequest, decision: Decision });
|
|
663
|
+
var AllowanceGap = z3.object({
|
|
664
|
+
intentId: z3.string(),
|
|
665
|
+
decisionId: z3.string().optional(),
|
|
666
|
+
agentId: z3.string(),
|
|
667
|
+
host: z3.string(),
|
|
668
|
+
resource: z3.string(),
|
|
669
|
+
amount: z3.string(),
|
|
670
|
+
settledAmount: z3.string().optional(),
|
|
671
|
+
taskId: z3.string().optional(),
|
|
672
|
+
allowedAt: z3.number(),
|
|
673
|
+
ageMs: z3.number(),
|
|
674
|
+
state: z3.enum(["in-flight", "unsettled", "overspent"])
|
|
626
675
|
});
|
|
627
|
-
var ReconciliationReport =
|
|
628
|
-
from:
|
|
629
|
-
to:
|
|
630
|
-
window:
|
|
631
|
-
graceMs:
|
|
632
|
-
allowed:
|
|
633
|
-
allowedValue:
|
|
634
|
-
settled:
|
|
635
|
-
settledValue:
|
|
636
|
-
inFlight:
|
|
637
|
-
inFlightValue:
|
|
638
|
-
unsettled:
|
|
639
|
-
unsettledValue:
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
676
|
+
var ReconciliationReport = z3.object({
|
|
677
|
+
from: z3.number(),
|
|
678
|
+
to: z3.number(),
|
|
679
|
+
window: z3.string(),
|
|
680
|
+
graceMs: z3.number(),
|
|
681
|
+
allowed: z3.number(),
|
|
682
|
+
allowedValue: z3.string(),
|
|
683
|
+
settled: z3.number(),
|
|
684
|
+
settledValue: z3.string(),
|
|
685
|
+
inFlight: z3.number(),
|
|
686
|
+
inFlightValue: z3.string(),
|
|
687
|
+
unsettled: z3.number(),
|
|
688
|
+
unsettledValue: z3.string(),
|
|
689
|
+
// Optional on the wire so a 0.2.0 engine still validates; absent means the
|
|
690
|
+
// engine predates the check, not that nothing was overspent.
|
|
691
|
+
overspent: z3.number().optional(),
|
|
692
|
+
overspentValue: z3.string().optional(),
|
|
693
|
+
unattributed: z3.number(),
|
|
694
|
+
settlementsSeen: z3.number(),
|
|
695
|
+
gaps: z3.array(AllowanceGap),
|
|
696
|
+
truncated: z3.boolean()
|
|
644
697
|
});
|
|
645
|
-
var IssuedApiKey =
|
|
646
|
-
var PaymentRequirement =
|
|
647
|
-
scheme:
|
|
648
|
-
network:
|
|
698
|
+
var IssuedApiKey = z3.object({ key: ApiKey, secret: z3.string() });
|
|
699
|
+
var PaymentRequirement = z3.object({
|
|
700
|
+
scheme: z3.string(),
|
|
701
|
+
network: z3.string(),
|
|
649
702
|
/** Amount in the asset's atomic units (e.g. "10000" = 0.01 USDC at 6 decimals). */
|
|
650
|
-
maxAmountRequired:
|
|
651
|
-
resource:
|
|
652
|
-
description:
|
|
653
|
-
mimeType:
|
|
654
|
-
payTo:
|
|
655
|
-
maxTimeoutSeconds:
|
|
703
|
+
maxAmountRequired: z3.string().regex(/^\d+$/, "atomic amount must be an integer string"),
|
|
704
|
+
resource: z3.string().optional(),
|
|
705
|
+
description: z3.string().optional(),
|
|
706
|
+
mimeType: z3.string().optional(),
|
|
707
|
+
payTo: z3.string().min(1),
|
|
708
|
+
maxTimeoutSeconds: z3.number().optional(),
|
|
656
709
|
/** Token contract address — or, mock-first, a plain symbol like "USDC". */
|
|
657
|
-
asset:
|
|
658
|
-
extra:
|
|
710
|
+
asset: z3.string().min(1),
|
|
711
|
+
extra: z3.record(z3.unknown()).optional()
|
|
659
712
|
});
|
|
660
|
-
var PaymentRequired =
|
|
661
|
-
x402Version:
|
|
662
|
-
accepts:
|
|
663
|
-
error:
|
|
713
|
+
var PaymentRequired = z3.object({
|
|
714
|
+
x402Version: z3.number(),
|
|
715
|
+
accepts: z3.array(PaymentRequirement).min(1),
|
|
716
|
+
error: z3.string().optional()
|
|
664
717
|
});
|
|
665
718
|
var NETWORK_TO_CHAIN = {
|
|
666
719
|
base: "base",
|
|
@@ -674,6 +727,8 @@ var NETWORK_TO_CHAIN = {
|
|
|
674
727
|
bnb: "bnb",
|
|
675
728
|
bsc: "bnb"
|
|
676
729
|
};
|
|
730
|
+
var ASSET_DECIMALS = { USDC: 6, USDT: 6, EURC: 6 };
|
|
731
|
+
var EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
|
|
677
732
|
var KNOWN_ASSET_ADDRESSES = {
|
|
678
733
|
"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913": "USDC",
|
|
679
734
|
// USDC on Base
|
|
@@ -682,18 +737,38 @@ var KNOWN_ASSET_ADDRESSES = {
|
|
|
682
737
|
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: "USDC"
|
|
683
738
|
// USDC on Solana
|
|
684
739
|
};
|
|
740
|
+
var CAIP2_ALIASES = {
|
|
741
|
+
base: "eip155:8453",
|
|
742
|
+
"base-sepolia": "eip155:84532",
|
|
743
|
+
polygon: "eip155:137",
|
|
744
|
+
"polygon-amoy": "eip155:80002",
|
|
745
|
+
bnb: "eip155:56",
|
|
746
|
+
bsc: "eip155:56",
|
|
747
|
+
solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
748
|
+
"solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
|
|
749
|
+
};
|
|
750
|
+
function caip2Of(network) {
|
|
751
|
+
const key = network.toLowerCase();
|
|
752
|
+
return CAIP2_ALIASES[key] ?? key;
|
|
753
|
+
}
|
|
754
|
+
function sameNetwork(a, b) {
|
|
755
|
+
return caip2Of(a) === caip2Of(b);
|
|
756
|
+
}
|
|
685
757
|
function networkToChain(network) {
|
|
686
758
|
return NETWORK_TO_CHAIN[network.toLowerCase()];
|
|
687
759
|
}
|
|
688
760
|
function resolveAsset(requirement, extraAddresses = {}) {
|
|
689
761
|
const direct = Asset.safeParse(requirement.asset.toUpperCase());
|
|
690
762
|
if (direct.success) return direct.data;
|
|
763
|
+
const known = extraAddresses[requirement.asset] ?? extraAddresses[requirement.asset.toLowerCase()] ?? KNOWN_ASSET_ADDRESSES[requirement.asset] ?? KNOWN_ASSET_ADDRESSES[requirement.asset.toLowerCase()];
|
|
764
|
+
if (known) return known;
|
|
765
|
+
if (EVM_ADDRESS.test(requirement.asset)) return void 0;
|
|
691
766
|
const symbol = requirement.extra?.["symbol"];
|
|
692
767
|
if (typeof symbol === "string") {
|
|
693
768
|
const fromExtra = Asset.safeParse(symbol.toUpperCase());
|
|
694
769
|
if (fromExtra.success) return fromExtra.data;
|
|
695
770
|
}
|
|
696
|
-
return
|
|
771
|
+
return void 0;
|
|
697
772
|
}
|
|
698
773
|
function atomicToDecimal(atomic, decimals) {
|
|
699
774
|
if (!/^\d+$/.test(atomic)) throw new TypeError(`invalid atomic amount: ${atomic}`);
|
|
@@ -703,49 +778,33 @@ function atomicToDecimal(atomic, decimals) {
|
|
|
703
778
|
const fracPart = digits.slice(digits.length - decimals).replace(/0+$/, "");
|
|
704
779
|
return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;
|
|
705
780
|
}
|
|
706
|
-
function requirementDecimals(requirement) {
|
|
781
|
+
function requirementDecimals(requirement, asset) {
|
|
782
|
+
if (asset) return ASSET_DECIMALS[asset];
|
|
707
783
|
const decimals = requirement.extra?.["decimals"];
|
|
708
784
|
return typeof decimals === "number" && Number.isInteger(decimals) && decimals >= 0 ? decimals : 6;
|
|
709
785
|
}
|
|
710
|
-
var
|
|
711
|
-
|
|
712
|
-
"base-sepolia": "eip155:84532",
|
|
713
|
-
polygon: "eip155:137",
|
|
714
|
-
"polygon-amoy": "eip155:80002",
|
|
715
|
-
bnb: "eip155:56",
|
|
716
|
-
bsc: "eip155:56",
|
|
717
|
-
solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
718
|
-
"solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
|
|
719
|
-
};
|
|
720
|
-
function caip2Of(network) {
|
|
721
|
-
const key = network.toLowerCase();
|
|
722
|
-
return CAIP2_ALIASES[key] ?? key;
|
|
723
|
-
}
|
|
724
|
-
function sameNetwork(a, b) {
|
|
725
|
-
return caip2Of(a) === caip2Of(b);
|
|
726
|
-
}
|
|
727
|
-
var PaymentRequirementsV2 = z2.object({
|
|
728
|
-
scheme: z2.string(),
|
|
786
|
+
var PaymentRequirementsV2 = z3.object({
|
|
787
|
+
scheme: z3.string(),
|
|
729
788
|
/** CAIP-2, e.g. "eip155:84532". */
|
|
730
|
-
network:
|
|
789
|
+
network: z3.string(),
|
|
731
790
|
/** Atomic units — v2's rename of v1's maxAmountRequired. */
|
|
732
|
-
amount:
|
|
733
|
-
asset:
|
|
734
|
-
payTo:
|
|
735
|
-
maxTimeoutSeconds:
|
|
736
|
-
extra:
|
|
791
|
+
amount: z3.string().regex(/^\d+$/, "atomic amount must be an integer string"),
|
|
792
|
+
asset: z3.string().min(1),
|
|
793
|
+
payTo: z3.string().min(1),
|
|
794
|
+
maxTimeoutSeconds: z3.number().optional(),
|
|
795
|
+
extra: z3.record(z3.unknown()).optional()
|
|
737
796
|
});
|
|
738
|
-
var ResourceInfoV2 =
|
|
739
|
-
url:
|
|
740
|
-
description:
|
|
741
|
-
mimeType:
|
|
797
|
+
var ResourceInfoV2 = z3.object({
|
|
798
|
+
url: z3.string(),
|
|
799
|
+
description: z3.string().optional(),
|
|
800
|
+
mimeType: z3.string().optional()
|
|
742
801
|
});
|
|
743
|
-
var PaymentRequiredV2 =
|
|
744
|
-
x402Version:
|
|
745
|
-
error:
|
|
802
|
+
var PaymentRequiredV2 = z3.object({
|
|
803
|
+
x402Version: z3.literal(2),
|
|
804
|
+
error: z3.string().optional(),
|
|
746
805
|
resource: ResourceInfoV2.optional(),
|
|
747
|
-
accepts:
|
|
748
|
-
extensions:
|
|
806
|
+
accepts: z3.array(PaymentRequirementsV2).min(1),
|
|
807
|
+
extensions: z3.record(z3.unknown()).optional()
|
|
749
808
|
});
|
|
750
809
|
function v2Requirements(requirement) {
|
|
751
810
|
return {
|
|
@@ -758,7 +817,7 @@ function v2Requirements(requirement) {
|
|
|
758
817
|
...requirement.extra ? { extra: requirement.extra } : {}
|
|
759
818
|
};
|
|
760
819
|
}
|
|
761
|
-
function buildPaymentRequiredV2(requirement, error) {
|
|
820
|
+
function buildPaymentRequiredV2(requirement, error, extensions = {}) {
|
|
762
821
|
return {
|
|
763
822
|
x402Version: 2,
|
|
764
823
|
error,
|
|
@@ -770,17 +829,17 @@ function buildPaymentRequiredV2(requirement, error) {
|
|
|
770
829
|
}
|
|
771
830
|
} : {},
|
|
772
831
|
accepts: [v2Requirements(requirement)],
|
|
773
|
-
extensions
|
|
832
|
+
extensions
|
|
774
833
|
};
|
|
775
834
|
}
|
|
776
835
|
function encodeBase64Json(value) {
|
|
777
836
|
return Buffer.from(JSON.stringify(value)).toString("base64");
|
|
778
837
|
}
|
|
779
|
-
var V1Envelope =
|
|
780
|
-
x402Version:
|
|
781
|
-
scheme:
|
|
782
|
-
network:
|
|
783
|
-
payload:
|
|
838
|
+
var V1Envelope = z3.object({
|
|
839
|
+
x402Version: z3.literal(1),
|
|
840
|
+
scheme: z3.string(),
|
|
841
|
+
network: z3.string(),
|
|
842
|
+
payload: z3.record(z3.unknown())
|
|
784
843
|
});
|
|
785
844
|
|
|
786
845
|
// src/errors.ts
|
|
@@ -794,35 +853,35 @@ var FacilitatorError = class extends Error {
|
|
|
794
853
|
};
|
|
795
854
|
|
|
796
855
|
// src/payload.ts
|
|
797
|
-
import { z as
|
|
798
|
-
var MockExactPayload =
|
|
799
|
-
from:
|
|
800
|
-
to:
|
|
856
|
+
import { z as z4 } from "zod";
|
|
857
|
+
var MockExactPayload = z4.object({
|
|
858
|
+
from: z4.string().min(1),
|
|
859
|
+
to: z4.string().min(1),
|
|
801
860
|
/** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */
|
|
802
|
-
value:
|
|
803
|
-
asset:
|
|
861
|
+
value: z4.string().regex(/^\d+$/, "atomic amount must be an integer string"),
|
|
862
|
+
asset: z4.string().min(1),
|
|
804
863
|
/**
|
|
805
864
|
* Rein linkage: the guard's payer stamps the intent id here, the facilitator
|
|
806
865
|
* memos it onto the ledger entry, and the indexer reconciles exactly. A real
|
|
807
866
|
* x402 transfer authorization carries a nonce that serves the same role.
|
|
808
867
|
*/
|
|
809
|
-
intentId:
|
|
810
|
-
nonce:
|
|
868
|
+
intentId: z4.string().optional(),
|
|
869
|
+
nonce: z4.string().optional()
|
|
811
870
|
});
|
|
812
|
-
var MockPaymentHeader =
|
|
813
|
-
x402Version:
|
|
814
|
-
scheme:
|
|
815
|
-
network:
|
|
871
|
+
var MockPaymentHeader = z4.object({
|
|
872
|
+
x402Version: z4.literal(1),
|
|
873
|
+
scheme: z4.string(),
|
|
874
|
+
network: z4.string(),
|
|
816
875
|
payload: MockExactPayload
|
|
817
876
|
});
|
|
818
|
-
var MockPaymentHeaderV2 =
|
|
819
|
-
x402Version:
|
|
820
|
-
accepted:
|
|
821
|
-
scheme:
|
|
822
|
-
network:
|
|
823
|
-
amount:
|
|
824
|
-
asset:
|
|
825
|
-
payTo:
|
|
877
|
+
var MockPaymentHeaderV2 = z4.object({
|
|
878
|
+
x402Version: z4.literal(2),
|
|
879
|
+
accepted: z4.object({
|
|
880
|
+
scheme: z4.string(),
|
|
881
|
+
network: z4.string(),
|
|
882
|
+
amount: z4.string().regex(/^\d+$/, "atomic amount must be an integer string"),
|
|
883
|
+
asset: z4.string().min(1),
|
|
884
|
+
payTo: z4.string().min(1)
|
|
826
885
|
}).passthrough(),
|
|
827
886
|
payload: MockExactPayload
|
|
828
887
|
}).passthrough();
|
|
@@ -868,12 +927,12 @@ function decodePaymentHeader(raw) {
|
|
|
868
927
|
payload: parsed.data.payload
|
|
869
928
|
};
|
|
870
929
|
}
|
|
871
|
-
var SettlementResponse =
|
|
872
|
-
success:
|
|
930
|
+
var SettlementResponse = z4.object({
|
|
931
|
+
success: z4.boolean(),
|
|
873
932
|
/** The tx hash on the mock ledger (the guard surfaces this on the receipt). */
|
|
874
|
-
transaction:
|
|
875
|
-
network:
|
|
876
|
-
payer:
|
|
933
|
+
transaction: z4.string(),
|
|
934
|
+
network: z4.string(),
|
|
935
|
+
payer: z4.string().optional()
|
|
877
936
|
});
|
|
878
937
|
function encodeSettlementHeader(response) {
|
|
879
938
|
return Buffer.from(JSON.stringify(response)).toString("base64");
|