@reinconsole/mock-rails 0.1.1 → 0.3.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +584 -235
- 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,34 +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 EnforcementMode = z.enum(["observed", "sdk", "session-key"]);
|
|
51
|
-
var AgentWallet = z.object({
|
|
97
|
+
var EnforcementMode = z2.enum(["observed", "sdk", "session-key"]);
|
|
98
|
+
var AgentWallet = z2.object({
|
|
52
99
|
chain: Chain,
|
|
53
|
-
address:
|
|
100
|
+
address: z2.string().min(1),
|
|
54
101
|
mode: EnforcementMode
|
|
55
102
|
});
|
|
56
|
-
var AgentStatus =
|
|
57
|
-
var
|
|
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({
|
|
58
106
|
id: AgentId,
|
|
59
107
|
orgId: OrgId,
|
|
60
|
-
name:
|
|
108
|
+
name: z2.string().min(1).max(200),
|
|
61
109
|
/** On-chain ERC-8004 identity, if the agent is registered. */
|
|
62
|
-
erc8004Id:
|
|
63
|
-
|
|
110
|
+
erc8004Id: z2.string().optional(),
|
|
111
|
+
/** Semantic grouping labels — the targets of policy `appliesTo.labels`. */
|
|
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([]),
|
|
64
114
|
status: AgentStatus.default("active"),
|
|
65
|
-
createdAt:
|
|
115
|
+
createdAt: z2.coerce.date()
|
|
66
116
|
});
|
|
67
117
|
var ID_PATTERN = /^eip155:(\d+):(0x[0-9a-fA-F]{40})\/(\d+)$/;
|
|
68
118
|
function parseErc8004Id(value) {
|
|
@@ -76,33 +126,33 @@ function parseErc8004Id(value) {
|
|
|
76
126
|
tokenId: BigInt(match[3])
|
|
77
127
|
};
|
|
78
128
|
}
|
|
79
|
-
var Erc8004Id =
|
|
129
|
+
var Erc8004Id = z2.string().refine((value) => parseErc8004Id(value) !== void 0, {
|
|
80
130
|
message: 'expected "eip155:{chainId}:{registry}/{tokenId}"'
|
|
81
131
|
});
|
|
82
|
-
var Vendor =
|
|
83
|
-
host:
|
|
84
|
-
address:
|
|
85
|
-
erc8004Id:
|
|
132
|
+
var Vendor = z2.object({
|
|
133
|
+
host: z2.string().min(1),
|
|
134
|
+
address: z2.string().min(1),
|
|
135
|
+
erc8004Id: z2.string().optional()
|
|
86
136
|
});
|
|
87
|
-
var TaskContext =
|
|
88
|
-
taskId:
|
|
89
|
-
parentRunId:
|
|
90
|
-
purpose:
|
|
137
|
+
var TaskContext = z2.object({
|
|
138
|
+
taskId: z2.string().optional(),
|
|
139
|
+
parentRunId: z2.string().optional(),
|
|
140
|
+
purpose: z2.string().max(500).optional()
|
|
91
141
|
});
|
|
92
|
-
var PaymentIntent =
|
|
142
|
+
var PaymentIntent = z2.object({
|
|
93
143
|
id: IntentId,
|
|
94
144
|
agentId: AgentId,
|
|
95
145
|
vendor: Vendor,
|
|
96
|
-
resource:
|
|
146
|
+
resource: z2.string(),
|
|
97
147
|
amount: DecimalString,
|
|
98
148
|
asset: Asset,
|
|
99
149
|
chain: Chain,
|
|
100
150
|
taskContext: TaskContext.default({}),
|
|
101
|
-
nonce:
|
|
102
|
-
createdAt:
|
|
151
|
+
nonce: z2.string().min(1),
|
|
152
|
+
createdAt: z2.coerce.date()
|
|
103
153
|
});
|
|
104
|
-
var DecisionOutcome =
|
|
105
|
-
var Decision =
|
|
154
|
+
var DecisionOutcome = z2.enum(["allow", "deny", "escalate"]);
|
|
155
|
+
var Decision = z2.object({
|
|
106
156
|
id: DecisionId,
|
|
107
157
|
intentId: IntentId,
|
|
108
158
|
/**
|
|
@@ -111,211 +161,428 @@ var Decision = z.object({
|
|
|
111
161
|
* chain — so a signer can verify an {intent, decision} pair offline as a
|
|
112
162
|
* self-contained spend voucher, not just a reference by id.
|
|
113
163
|
*/
|
|
114
|
-
intentHash:
|
|
164
|
+
intentHash: z2.string(),
|
|
115
165
|
outcome: DecisionOutcome,
|
|
116
166
|
/** Ids of the rules that fired, for explainability. */
|
|
117
|
-
matchedRules:
|
|
167
|
+
matchedRules: z2.array(z2.string()).default([]),
|
|
118
168
|
/** Human-readable explanation surfaced in the dashboard. */
|
|
119
|
-
reason:
|
|
120
|
-
policyId:
|
|
121
|
-
policyVersion:
|
|
169
|
+
reason: z2.string().optional(),
|
|
170
|
+
policyId: z2.string(),
|
|
171
|
+
policyVersion: z2.string(),
|
|
122
172
|
/** Hash of the previous decision in the chain (tamper-evident log). */
|
|
123
|
-
prevHash:
|
|
173
|
+
prevHash: z2.string(),
|
|
124
174
|
/** Hash of this decision's canonical content. */
|
|
125
|
-
hash:
|
|
175
|
+
hash: z2.string(),
|
|
126
176
|
/** Service signing-key signature over `hash`. */
|
|
127
|
-
signature:
|
|
128
|
-
latencyMs:
|
|
129
|
-
decidedAt:
|
|
177
|
+
signature: z2.string(),
|
|
178
|
+
latencyMs: z2.number().nonnegative(),
|
|
179
|
+
decidedAt: z2.coerce.date()
|
|
130
180
|
});
|
|
131
|
-
var
|
|
181
|
+
var AttributedDecision = Decision.extend({ agentId: AgentId.optional() });
|
|
182
|
+
var Session = z2.object({
|
|
132
183
|
id: SessionId,
|
|
133
184
|
agentId: AgentId,
|
|
134
185
|
/** sha256 hex of the bearer token. */
|
|
135
|
-
tokenHash:
|
|
186
|
+
tokenHash: z2.string(),
|
|
136
187
|
/** Cumulative ceiling across the session's lifetime. Absent = uncapped. */
|
|
137
188
|
capAmount: DecimalString.optional(),
|
|
138
189
|
/** Ceiling per individual signature. Absent = uncapped. */
|
|
139
190
|
maxPerPayment: DecimalString.optional(),
|
|
140
|
-
expiresAt:
|
|
141
|
-
createdAt:
|
|
142
|
-
revokedAt:
|
|
191
|
+
expiresAt: z2.coerce.date(),
|
|
192
|
+
createdAt: z2.coerce.date(),
|
|
193
|
+
revokedAt: z2.coerce.date().optional()
|
|
143
194
|
});
|
|
144
|
-
var SettledPayment =
|
|
195
|
+
var SettledPayment = z2.object({
|
|
145
196
|
intentId: IntentId,
|
|
146
|
-
txHash:
|
|
197
|
+
txHash: z2.string(),
|
|
147
198
|
chain: Chain,
|
|
148
|
-
blockNumber:
|
|
149
|
-
facilitator:
|
|
199
|
+
blockNumber: z2.coerce.bigint(),
|
|
200
|
+
facilitator: z2.string().optional(),
|
|
150
201
|
feePaid: DecimalString.optional(),
|
|
151
|
-
confirmedAt:
|
|
202
|
+
confirmedAt: z2.coerce.date()
|
|
203
|
+
});
|
|
204
|
+
var SettlementReport = z2.object({
|
|
205
|
+
intentId: IntentId,
|
|
206
|
+
/** The settling transaction, when the observer saw one. */
|
|
207
|
+
txHash: z2.string().optional(),
|
|
208
|
+
chain: Chain.optional(),
|
|
209
|
+
/** The amount as SETTLED, when known — may differ from the amount allowed. */
|
|
210
|
+
amount: DecimalString.optional(),
|
|
211
|
+
/** Free-form observer tag, e.g. "indexer", "guard", "facilitator". */
|
|
212
|
+
source: z2.string().min(1).max(64).optional(),
|
|
213
|
+
confirmedAt: z2.coerce.date()
|
|
152
214
|
});
|
|
153
|
-
var ReceiptSettlement =
|
|
154
|
-
txHash:
|
|
155
|
-
networkId:
|
|
215
|
+
var ReceiptSettlement = z2.object({
|
|
216
|
+
txHash: z2.string().optional(),
|
|
217
|
+
networkId: z2.string().optional(),
|
|
156
218
|
/** Raw header payload, kept for forensics until the indexer confirms. */
|
|
157
|
-
raw:
|
|
219
|
+
raw: z2.string().optional()
|
|
158
220
|
});
|
|
159
|
-
var Receipt =
|
|
221
|
+
var Receipt = z2.object({
|
|
160
222
|
id: ReceiptId,
|
|
161
223
|
agentId: AgentId,
|
|
162
224
|
intentId: IntentId,
|
|
163
225
|
decisionId: DecisionId,
|
|
164
226
|
outcome: DecisionOutcome,
|
|
165
227
|
/** The URL the agent actually fetched (the paywalled resource). */
|
|
166
|
-
url:
|
|
167
|
-
method:
|
|
168
|
-
vendorHost:
|
|
228
|
+
url: z2.string(),
|
|
229
|
+
method: z2.string().default("GET"),
|
|
230
|
+
vendorHost: z2.string(),
|
|
169
231
|
amount: DecimalString,
|
|
170
232
|
asset: Asset,
|
|
171
233
|
chain: Chain,
|
|
172
234
|
taskContext: TaskContext.default({}),
|
|
173
235
|
/** Human-readable explanation copied from the decision. */
|
|
174
|
-
reason:
|
|
236
|
+
reason: z2.string().optional(),
|
|
175
237
|
/** Present only once a payment was made and the vendor confirmed it. */
|
|
176
238
|
settlement: ReceiptSettlement.optional(),
|
|
177
|
-
createdAt:
|
|
239
|
+
createdAt: z2.coerce.date()
|
|
178
240
|
});
|
|
179
|
-
var GateReceipt =
|
|
241
|
+
var GateReceipt = z2.object({
|
|
180
242
|
id: GateReceiptId,
|
|
181
|
-
at:
|
|
243
|
+
at: z2.coerce.date(),
|
|
182
244
|
/** The route pattern that priced this request, e.g. "/api/reports/*". */
|
|
183
|
-
route:
|
|
245
|
+
route: z2.string().min(1),
|
|
184
246
|
/** The concrete resource paid for (URL path actually requested). */
|
|
185
|
-
resource:
|
|
186
|
-
method:
|
|
247
|
+
resource: z2.string().min(1),
|
|
248
|
+
method: z2.string().min(1),
|
|
187
249
|
/** The paying wallet address, as asserted by the settled payment. */
|
|
188
|
-
payer:
|
|
189
|
-
payTo:
|
|
250
|
+
payer: z2.string().min(1),
|
|
251
|
+
payTo: z2.string().min(1),
|
|
190
252
|
/** Human-unit decimal amount, e.g. "0.05". */
|
|
191
253
|
amount: DecimalString,
|
|
192
254
|
/** The same amount in the asset's atomic units, e.g. "50000". */
|
|
193
|
-
amountAtomic:
|
|
255
|
+
amountAtomic: z2.string().regex(/^\d+$/, "atomic amount must be an integer string"),
|
|
194
256
|
/** Token symbol or contract address, exactly as quoted in the requirement. */
|
|
195
|
-
asset:
|
|
196
|
-
network:
|
|
257
|
+
asset: z2.string().min(1),
|
|
258
|
+
network: z2.string().min(1),
|
|
197
259
|
/** Settlement transaction hash (mock ledger or on-chain). */
|
|
198
|
-
transaction:
|
|
260
|
+
transaction: z2.string().min(1)
|
|
199
261
|
});
|
|
200
|
-
var Window =
|
|
201
|
-
var Multiplier =
|
|
202
|
-
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({
|
|
203
265
|
/** Per-transaction amount exceeds this value. */
|
|
204
266
|
amountGt: DecimalString.optional(),
|
|
205
267
|
/** Sum of spend in a rolling window exceeds `gt`. */
|
|
206
|
-
rollingSum:
|
|
268
|
+
rollingSum: z2.object({ window: Window, gt: DecimalString }).optional(),
|
|
207
269
|
/** Transaction count in a rolling window exceeds `gt`. */
|
|
208
|
-
txCount:
|
|
270
|
+
txCount: z2.object({ window: Window, gt: z2.number().int().nonnegative() }).optional(),
|
|
209
271
|
/** Vendor host matches one of these patterns (supports `*` globs). */
|
|
210
|
-
vendorHostIn:
|
|
272
|
+
vendorHostIn: z2.array(z2.string()).optional(),
|
|
273
|
+
/**
|
|
274
|
+
* Resource PATH matches one of these patterns (supports `*` globs, e.g.
|
|
275
|
+
* "/v1/reports/*"). A full-URL resource is reduced to its pathname before
|
|
276
|
+
* matching (see `resourcePathOf`), so the same pattern works whether the
|
|
277
|
+
* vendor declares "https://api.x.com/v1/answer" or "/v1/answer". Pair
|
|
278
|
+
* with `vendorHostIn` to scope a path rule to specific vendors.
|
|
279
|
+
*/
|
|
280
|
+
resourceIn: z2.array(z2.string()).optional(),
|
|
211
281
|
/** First time Rein has seen this vendor for the agent. */
|
|
212
|
-
vendorFirstSeen:
|
|
282
|
+
vendorFirstSeen: z2.boolean().optional(),
|
|
213
283
|
/** Vendor reputation score is below this threshold (Phase 3 hook). */
|
|
214
|
-
vendorReputationLt:
|
|
284
|
+
vendorReputationLt: z2.number().min(0).max(100).optional(),
|
|
215
285
|
/** Amount is more than `gt`-times the observed median for this resource. */
|
|
216
|
-
amountVsResourceMedian:
|
|
286
|
+
amountVsResourceMedian: z2.object({ gt: Multiplier }).optional(),
|
|
287
|
+
/**
|
|
288
|
+
* Cumulative spend attributed to THIS intent's `taskContext.taskId`
|
|
289
|
+
* (prior spend on the task plus this payment) exceeds `gt`. Scopes a
|
|
290
|
+
* budget to one unit of work rather than to a window: a research run that
|
|
291
|
+
* is meant to cost a dollar cannot quietly cost fifty, however slowly.
|
|
292
|
+
*
|
|
293
|
+
* An intent carrying no `taskId` cannot be attributed to a task, so the
|
|
294
|
+
* predicate never triggers for one. Requiring attribution is a separate,
|
|
295
|
+
* deliberate rule (deny on `taskIdMissing`), not a side effect of setting
|
|
296
|
+
* a budget — otherwise every untagged probe payment would trip every
|
|
297
|
+
* task budget in the policy.
|
|
298
|
+
*/
|
|
299
|
+
taskBudget: z2.object({ gt: DecimalString }).optional(),
|
|
300
|
+
/** The intent carries no `taskContext.taskId` (or an empty one). */
|
|
301
|
+
taskIdMissing: z2.boolean().optional()
|
|
217
302
|
}).refine((c) => Object.values(c).some((v) => v !== void 0), {
|
|
218
303
|
message: "a condition must specify at least one predicate"
|
|
219
304
|
});
|
|
220
|
-
var
|
|
221
|
-
id:
|
|
305
|
+
var Breaker = z2.object({
|
|
306
|
+
id: z2.string().min(1),
|
|
307
|
+
/** The trailing span the tripwires measure over. */
|
|
308
|
+
window: Window,
|
|
309
|
+
/**
|
|
310
|
+
* Trip when the window would hold MORE than this many transactions.
|
|
311
|
+
* `10` permits ten in the window and escalates the eleventh.
|
|
312
|
+
*/
|
|
313
|
+
txCount: z2.number().int().positive().optional(),
|
|
314
|
+
/**
|
|
315
|
+
* Trip when the window's spend would exceed this total. `"50.00"` permits
|
|
316
|
+
* a window totalling exactly 50.00 and escalates the payment that would
|
|
317
|
+
* carry it past. Prospective, like every other spend predicate: the
|
|
318
|
+
* payment that would breach the cap is the one that escalates, rather
|
|
319
|
+
* than the innocent one after it.
|
|
320
|
+
*/
|
|
321
|
+
valueCap: DecimalString.optional()
|
|
322
|
+
}).refine((b) => b.txCount !== void 0 || b.valueCap !== void 0, {
|
|
323
|
+
message: "a breaker must specify at least one of txCount / valueCap"
|
|
324
|
+
});
|
|
325
|
+
var Rule = z2.object({
|
|
326
|
+
id: z2.string().min(1),
|
|
222
327
|
allow: Condition.optional(),
|
|
223
328
|
deny: Condition.optional(),
|
|
224
329
|
escalate: Condition.optional()
|
|
225
330
|
}).refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== void 0).length === 1, {
|
|
226
331
|
message: "a rule must specify exactly one of allow / deny / escalate"
|
|
227
332
|
});
|
|
228
|
-
var PolicyDefault =
|
|
229
|
-
var AppliesTo =
|
|
333
|
+
var PolicyDefault = z2.enum(["allow", "deny"]);
|
|
334
|
+
var AppliesTo = z2.object({
|
|
230
335
|
/** Agent id patterns (supports `*` globs, e.g. "agt_research_*"). */
|
|
231
|
-
agents:
|
|
232
|
-
|
|
336
|
+
agents: z2.array(z2.string()).optional(),
|
|
337
|
+
/**
|
|
338
|
+
* Agent label patterns (supports `*` globs) — semantic targeting. Matches
|
|
339
|
+
* when the agent carries at least one label matching any pattern. Requires
|
|
340
|
+
* the agent DOCUMENT: an intent from an unregistered agent never matches a
|
|
341
|
+
* labels-targeted policy (and so fails closed when no other policy applies).
|
|
342
|
+
*/
|
|
343
|
+
labels: z2.array(z2.string()).optional(),
|
|
344
|
+
chains: z2.array(Chain).optional()
|
|
233
345
|
});
|
|
234
|
-
var Escalation =
|
|
235
|
-
approvers:
|
|
346
|
+
var Escalation = z2.object({
|
|
347
|
+
approvers: z2.array(z2.string()).default([]),
|
|
236
348
|
timeoutAction: PolicyDefault.default("deny"),
|
|
237
|
-
timeoutMin:
|
|
349
|
+
timeoutMin: z2.number().int().positive().default(15)
|
|
238
350
|
});
|
|
239
|
-
var Policy =
|
|
240
|
-
policyId:
|
|
241
|
-
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(),
|
|
242
366
|
appliesTo: AppliesTo.default({}),
|
|
243
|
-
rules:
|
|
367
|
+
rules: z2.array(Rule).default([]),
|
|
368
|
+
/**
|
|
369
|
+
* Behavioral breakers evaluated alongside the rules. A tripped breaker
|
|
370
|
+
* escalates at the same precedence as an `escalate` rule — so an explicit
|
|
371
|
+
* DENY still wins, and an ALLOW rule cannot wave past a tripped breaker.
|
|
372
|
+
*/
|
|
373
|
+
breakers: z2.array(Breaker).default([]),
|
|
244
374
|
default: PolicyDefault.default("deny"),
|
|
245
375
|
/** Below this amount, fail-open is permitted during a policy-service outage. */
|
|
246
376
|
denyFloor: DecimalString.default("0.05"),
|
|
247
377
|
escalation: Escalation.optional()
|
|
248
378
|
});
|
|
249
|
-
var
|
|
250
|
-
|
|
251
|
-
|
|
379
|
+
var LivenessSource = z2.enum([
|
|
380
|
+
/** It submitted an intent — ANY outcome, including a denial. */
|
|
381
|
+
"intent",
|
|
382
|
+
/** It reported in explicitly, having nothing to buy. */
|
|
383
|
+
"heartbeat"
|
|
384
|
+
]);
|
|
385
|
+
var DEFAULT_LIVENESS_GRACE_MS = 6e4;
|
|
386
|
+
var LivenessExpectation = z2.object({
|
|
387
|
+
agentId: AgentId,
|
|
388
|
+
/** Longest silence still considered normal, e.g. '15m'. */
|
|
389
|
+
interval: Window,
|
|
390
|
+
/** Extra slack past `interval` before the silence is an alarm. */
|
|
391
|
+
graceMs: z2.number().int().nonnegative().default(DEFAULT_LIVENESS_GRACE_MS),
|
|
392
|
+
/**
|
|
393
|
+
* When watching began. An agent that has NEVER been seen is measured from
|
|
394
|
+
* here, so a watch on an agent that never starts does raise an alarm — a
|
|
395
|
+
* detector that never came up is exactly as dead as one that stopped.
|
|
396
|
+
*/
|
|
397
|
+
since: z2.coerce.date(),
|
|
398
|
+
/** What this agent is supposed to be doing, shown beside the alarm. */
|
|
399
|
+
note: z2.string().max(200).optional()
|
|
400
|
+
});
|
|
401
|
+
var LivenessWatchInput = LivenessExpectation.omit({ since: true }).extend({
|
|
402
|
+
graceMs: z2.number().int().nonnegative().optional()
|
|
403
|
+
});
|
|
404
|
+
var Heartbeat = z2.object({
|
|
405
|
+
agentId: AgentId,
|
|
406
|
+
/** When the agent was alive. Defaults to arrival time. */
|
|
407
|
+
at: z2.coerce.date().optional(),
|
|
408
|
+
/** Free-form note from the reporter, e.g. "poll cycle 41 ok". */
|
|
409
|
+
note: z2.string().max(200).optional()
|
|
410
|
+
});
|
|
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({
|
|
415
|
+
id: ApproverKeyId,
|
|
416
|
+
orgId: OrgId,
|
|
417
|
+
name: z2.string().min(1).max(200),
|
|
418
|
+
/** ed25519 public key, SPKI PEM — the same encoding as the decision log's. */
|
|
419
|
+
publicKey: z2.string().min(1),
|
|
420
|
+
algorithm: z2.literal("ed25519").default("ed25519"),
|
|
421
|
+
createdAt: z2.coerce.date(),
|
|
422
|
+
revokedAt: z2.coerce.date().optional()
|
|
423
|
+
});
|
|
424
|
+
var ApprovalRequest = z2.object({
|
|
425
|
+
/** The `escalate` decision this request answers (primary key). */
|
|
426
|
+
decisionId: DecisionId,
|
|
427
|
+
intentId: IntentId,
|
|
428
|
+
/** Binds the approval to the exact transfer — the signed bytes commit to it. */
|
|
429
|
+
intentHash: z2.string(),
|
|
430
|
+
agentId: AgentId,
|
|
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(),
|
|
441
|
+
amount: DecimalString,
|
|
442
|
+
asset: Asset,
|
|
443
|
+
chain: Chain,
|
|
444
|
+
/**
|
|
445
|
+
* Task attribution copied from the intent. Carried so an approved payment
|
|
446
|
+
* still counts against its `taskBudget` — an escalation that lost its task
|
|
447
|
+
* id on the way through would make the budget silently under-count exactly
|
|
448
|
+
* the payments a human had to look at.
|
|
449
|
+
*/
|
|
450
|
+
taskId: z2.string().optional(),
|
|
451
|
+
/** Why policy escalated, verbatim from the decision. */
|
|
452
|
+
reason: z2.string(),
|
|
453
|
+
/**
|
|
454
|
+
* Breaker ids whose trip contributed to this escalation. An approval of
|
|
455
|
+
* this request resets exactly these — moving their counting floor to the
|
|
456
|
+
* approval instant — so a human waving one payment through also clears the
|
|
457
|
+
* behavior that stopped it, rather than being asked again immediately.
|
|
458
|
+
* Empty when ordinary rules did the escalating.
|
|
459
|
+
*/
|
|
460
|
+
breakers: z2.array(z2.string()).default([]),
|
|
461
|
+
status: ApprovalStatus,
|
|
462
|
+
createdAt: z2.coerce.date(),
|
|
463
|
+
/** Past this instant the request denies, whatever arrives afterwards. */
|
|
464
|
+
expiresAt: z2.coerce.date(),
|
|
465
|
+
resolvedAt: z2.coerce.date().optional(),
|
|
466
|
+
/** Which registered key signed — absent when the TTL lapsed instead. */
|
|
467
|
+
approverKeyId: ApproverKeyId.optional(),
|
|
468
|
+
/**
|
|
469
|
+
* The follow-up decision appended to the chain when this resolved. That
|
|
470
|
+
* decision, not this record, is the voucher a signer verifies: the original
|
|
471
|
+
* `escalate` decision is never rewritten.
|
|
472
|
+
*/
|
|
473
|
+
finalDecisionId: DecisionId.optional()
|
|
474
|
+
});
|
|
475
|
+
var ApprovalChallenges = z2.object({
|
|
476
|
+
approve: z2.string(),
|
|
477
|
+
reject: z2.string()
|
|
478
|
+
});
|
|
479
|
+
var ApprovalGrant = z2.object({
|
|
480
|
+
decisionId: DecisionId,
|
|
481
|
+
intentHash: z2.string(),
|
|
482
|
+
verdict: ApprovalVerdict,
|
|
483
|
+
approverKeyId: ApproverKeyId,
|
|
484
|
+
signature: z2.string().min(1)
|
|
485
|
+
});
|
|
486
|
+
var ReputationSubject = z2.object({
|
|
487
|
+
kind: z2.enum(["agent", "vendor"]),
|
|
488
|
+
id: z2.string()
|
|
252
489
|
});
|
|
253
|
-
var ReputationComponents =
|
|
254
|
-
volume:
|
|
255
|
-
longevity:
|
|
256
|
-
disputeRate:
|
|
257
|
-
counterpartyQuality:
|
|
258
|
-
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()
|
|
259
496
|
});
|
|
260
|
-
var ReputationScore =
|
|
497
|
+
var ReputationScore = z2.object({
|
|
261
498
|
subject: ReputationSubject,
|
|
262
|
-
score:
|
|
499
|
+
score: z2.number().min(0).max(100),
|
|
263
500
|
components: ReputationComponents,
|
|
264
|
-
confidence:
|
|
265
|
-
asOf:
|
|
501
|
+
confidence: z2.number().min(0).max(1),
|
|
502
|
+
asOf: z2.coerce.date(),
|
|
266
503
|
/** Hash-anchored attestation, optionally published on-chain (ERC-8004). */
|
|
267
|
-
evidenceUri:
|
|
268
|
-
});
|
|
269
|
-
var ReinEvent =
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
type:
|
|
275
|
-
at:
|
|
504
|
+
evidenceUri: z2.string().optional()
|
|
505
|
+
});
|
|
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(),
|
|
276
513
|
agentId: AgentId,
|
|
277
|
-
txHash:
|
|
514
|
+
txHash: z2.string(),
|
|
278
515
|
chain: Chain,
|
|
279
516
|
amount: DecimalString
|
|
280
517
|
}),
|
|
281
|
-
|
|
282
|
-
type:
|
|
283
|
-
at:
|
|
518
|
+
z2.object({
|
|
519
|
+
type: z2.literal("signature.released"),
|
|
520
|
+
at: z2.coerce.date(),
|
|
284
521
|
sessionId: SessionId,
|
|
285
522
|
agentId: AgentId,
|
|
286
523
|
intentId: IntentId,
|
|
287
524
|
decisionId: DecisionId,
|
|
288
525
|
amount: DecimalString
|
|
289
526
|
}),
|
|
290
|
-
|
|
291
|
-
type:
|
|
292
|
-
at:
|
|
527
|
+
z2.object({
|
|
528
|
+
type: z2.literal("signature.refused"),
|
|
529
|
+
at: z2.coerce.date(),
|
|
293
530
|
/** Refusal code, e.g. "decision_replayed" (see @reinconsole/signer). */
|
|
294
|
-
code:
|
|
295
|
-
reason:
|
|
531
|
+
code: z2.string(),
|
|
532
|
+
reason: z2.string(),
|
|
296
533
|
sessionId: SessionId.optional(),
|
|
297
534
|
agentId: AgentId.optional(),
|
|
298
535
|
intentId: IntentId.optional()
|
|
299
536
|
}),
|
|
300
|
-
|
|
301
|
-
type:
|
|
302
|
-
at:
|
|
303
|
-
resource:
|
|
304
|
-
method:
|
|
537
|
+
z2.object({
|
|
538
|
+
type: z2.literal("gate.quoted"),
|
|
539
|
+
at: z2.coerce.date(),
|
|
540
|
+
resource: z2.string(),
|
|
541
|
+
method: z2.string(),
|
|
305
542
|
amount: DecimalString,
|
|
306
|
-
asset:
|
|
307
|
-
network:
|
|
543
|
+
asset: z2.string(),
|
|
544
|
+
network: z2.string()
|
|
545
|
+
}),
|
|
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(),
|
|
550
|
+
request: ApprovalRequest
|
|
551
|
+
}),
|
|
552
|
+
z2.object({
|
|
553
|
+
type: z2.literal("approval.resolved"),
|
|
554
|
+
at: z2.coerce.date(),
|
|
555
|
+
request: ApprovalRequest,
|
|
556
|
+
/** The follow-up allow/deny decision this resolution appended. */
|
|
557
|
+
decision: Decision
|
|
308
558
|
}),
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
559
|
+
z2.object({
|
|
560
|
+
type: z2.literal("liveness.missing"),
|
|
561
|
+
at: z2.coerce.date(),
|
|
562
|
+
agentId: AgentId,
|
|
563
|
+
expectation: LivenessExpectation,
|
|
564
|
+
/** How long the agent has been silent when the alarm was raised. */
|
|
565
|
+
silentMs: z2.number().int().nonnegative(),
|
|
566
|
+
/** Last sighting, absent when the agent was never seen at all. */
|
|
567
|
+
lastSeenAt: z2.coerce.date().optional()
|
|
568
|
+
}),
|
|
569
|
+
z2.object({
|
|
570
|
+
type: z2.literal("liveness.recovered"),
|
|
571
|
+
at: z2.coerce.date(),
|
|
572
|
+
agentId: AgentId,
|
|
573
|
+
/** How long the silence lasted, measured to this sighting. */
|
|
574
|
+
silentMs: z2.number().int().nonnegative(),
|
|
575
|
+
source: LivenessSource
|
|
576
|
+
}),
|
|
577
|
+
z2.object({
|
|
578
|
+
type: z2.literal("gate.refused"),
|
|
579
|
+
at: z2.coerce.date(),
|
|
313
580
|
/** Refusal code, e.g. "payment_replayed" (see @reinconsole/gate). */
|
|
314
|
-
code:
|
|
315
|
-
reason:
|
|
316
|
-
resource:
|
|
581
|
+
code: z2.string(),
|
|
582
|
+
reason: z2.string(),
|
|
583
|
+
resource: z2.string(),
|
|
317
584
|
/** Known only when the payment header decoded far enough to name a payer. */
|
|
318
|
-
payer:
|
|
585
|
+
payer: z2.string().optional()
|
|
319
586
|
})
|
|
320
587
|
]);
|
|
321
588
|
|
|
@@ -350,27 +617,103 @@ var MockLedger = class {
|
|
|
350
617
|
};
|
|
351
618
|
|
|
352
619
|
// ../../packages/sdk/dist/index.js
|
|
353
|
-
import { z as
|
|
354
|
-
var
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
620
|
+
import { z as z3 } from "zod";
|
|
621
|
+
var BreakerState = z3.object({
|
|
622
|
+
breaker: Breaker,
|
|
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()
|
|
630
|
+
});
|
|
631
|
+
var LivenessState = z3.object({
|
|
632
|
+
agentId: z3.string(),
|
|
633
|
+
expectation: LivenessExpectation,
|
|
634
|
+
lastSeenAt: z3.number().optional(),
|
|
635
|
+
lastSource: LivenessSource.optional(),
|
|
636
|
+
silentSince: z3.number(),
|
|
637
|
+
silentMs: z3.number(),
|
|
638
|
+
dueAt: z3.number(),
|
|
639
|
+
overdueAt: z3.number(),
|
|
640
|
+
status: LivenessStatus,
|
|
641
|
+
alertedAt: z3.number().optional()
|
|
642
|
+
});
|
|
643
|
+
var Health = z3.object({
|
|
644
|
+
status: z3.string(),
|
|
645
|
+
publicKey: z3.string(),
|
|
646
|
+
/** "api-key" once the engine demands a credential; "none" while it does not. */
|
|
647
|
+
auth: z3.string().optional(),
|
|
648
|
+
approvals: z3.string().optional()
|
|
649
|
+
});
|
|
650
|
+
var EvaluateResponse = z3.object({
|
|
651
|
+
intent: PaymentIntent,
|
|
652
|
+
decision: Decision,
|
|
653
|
+
/** Present when an escalation was parked for a signed verdict. */
|
|
654
|
+
approval: ApprovalRequest.optional()
|
|
655
|
+
});
|
|
656
|
+
var ApprovalView = z3.object({
|
|
657
|
+
request: ApprovalRequest,
|
|
658
|
+
challenges: ApprovalChallenges,
|
|
659
|
+
/** The follow-up allow/deny decision, once the request has resolved. */
|
|
660
|
+
decision: Decision.optional()
|
|
661
|
+
});
|
|
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"])
|
|
675
|
+
});
|
|
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()
|
|
697
|
+
});
|
|
698
|
+
var IssuedApiKey = z3.object({ key: ApiKey, secret: z3.string() });
|
|
699
|
+
var PaymentRequirement = z3.object({
|
|
700
|
+
scheme: z3.string(),
|
|
701
|
+
network: z3.string(),
|
|
359
702
|
/** Amount in the asset's atomic units (e.g. "10000" = 0.01 USDC at 6 decimals). */
|
|
360
|
-
maxAmountRequired:
|
|
361
|
-
resource:
|
|
362
|
-
description:
|
|
363
|
-
mimeType:
|
|
364
|
-
payTo:
|
|
365
|
-
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(),
|
|
366
709
|
/** Token contract address — or, mock-first, a plain symbol like "USDC". */
|
|
367
|
-
asset:
|
|
368
|
-
extra:
|
|
710
|
+
asset: z3.string().min(1),
|
|
711
|
+
extra: z3.record(z3.unknown()).optional()
|
|
369
712
|
});
|
|
370
|
-
var PaymentRequired =
|
|
371
|
-
x402Version:
|
|
372
|
-
accepts:
|
|
373
|
-
error:
|
|
713
|
+
var PaymentRequired = z3.object({
|
|
714
|
+
x402Version: z3.number(),
|
|
715
|
+
accepts: z3.array(PaymentRequirement).min(1),
|
|
716
|
+
error: z3.string().optional()
|
|
374
717
|
});
|
|
375
718
|
var NETWORK_TO_CHAIN = {
|
|
376
719
|
base: "base",
|
|
@@ -384,6 +727,8 @@ var NETWORK_TO_CHAIN = {
|
|
|
384
727
|
bnb: "bnb",
|
|
385
728
|
bsc: "bnb"
|
|
386
729
|
};
|
|
730
|
+
var ASSET_DECIMALS = { USDC: 6, USDT: 6, EURC: 6 };
|
|
731
|
+
var EVM_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
|
|
387
732
|
var KNOWN_ASSET_ADDRESSES = {
|
|
388
733
|
"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913": "USDC",
|
|
389
734
|
// USDC on Base
|
|
@@ -392,18 +737,38 @@ var KNOWN_ASSET_ADDRESSES = {
|
|
|
392
737
|
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v: "USDC"
|
|
393
738
|
// USDC on Solana
|
|
394
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
|
+
}
|
|
395
757
|
function networkToChain(network) {
|
|
396
758
|
return NETWORK_TO_CHAIN[network.toLowerCase()];
|
|
397
759
|
}
|
|
398
760
|
function resolveAsset(requirement, extraAddresses = {}) {
|
|
399
761
|
const direct = Asset.safeParse(requirement.asset.toUpperCase());
|
|
400
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;
|
|
401
766
|
const symbol = requirement.extra?.["symbol"];
|
|
402
767
|
if (typeof symbol === "string") {
|
|
403
768
|
const fromExtra = Asset.safeParse(symbol.toUpperCase());
|
|
404
769
|
if (fromExtra.success) return fromExtra.data;
|
|
405
770
|
}
|
|
406
|
-
return
|
|
771
|
+
return void 0;
|
|
407
772
|
}
|
|
408
773
|
function atomicToDecimal(atomic, decimals) {
|
|
409
774
|
if (!/^\d+$/.test(atomic)) throw new TypeError(`invalid atomic amount: ${atomic}`);
|
|
@@ -413,49 +778,33 @@ function atomicToDecimal(atomic, decimals) {
|
|
|
413
778
|
const fracPart = digits.slice(digits.length - decimals).replace(/0+$/, "");
|
|
414
779
|
return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;
|
|
415
780
|
}
|
|
416
|
-
function requirementDecimals(requirement) {
|
|
781
|
+
function requirementDecimals(requirement, asset) {
|
|
782
|
+
if (asset) return ASSET_DECIMALS[asset];
|
|
417
783
|
const decimals = requirement.extra?.["decimals"];
|
|
418
784
|
return typeof decimals === "number" && Number.isInteger(decimals) && decimals >= 0 ? decimals : 6;
|
|
419
785
|
}
|
|
420
|
-
var
|
|
421
|
-
|
|
422
|
-
"base-sepolia": "eip155:84532",
|
|
423
|
-
polygon: "eip155:137",
|
|
424
|
-
"polygon-amoy": "eip155:80002",
|
|
425
|
-
bnb: "eip155:56",
|
|
426
|
-
bsc: "eip155:56",
|
|
427
|
-
solana: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
428
|
-
"solana-devnet": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
|
|
429
|
-
};
|
|
430
|
-
function caip2Of(network) {
|
|
431
|
-
const key = network.toLowerCase();
|
|
432
|
-
return CAIP2_ALIASES[key] ?? key;
|
|
433
|
-
}
|
|
434
|
-
function sameNetwork(a, b) {
|
|
435
|
-
return caip2Of(a) === caip2Of(b);
|
|
436
|
-
}
|
|
437
|
-
var PaymentRequirementsV2 = z2.object({
|
|
438
|
-
scheme: z2.string(),
|
|
786
|
+
var PaymentRequirementsV2 = z3.object({
|
|
787
|
+
scheme: z3.string(),
|
|
439
788
|
/** CAIP-2, e.g. "eip155:84532". */
|
|
440
|
-
network:
|
|
789
|
+
network: z3.string(),
|
|
441
790
|
/** Atomic units — v2's rename of v1's maxAmountRequired. */
|
|
442
|
-
amount:
|
|
443
|
-
asset:
|
|
444
|
-
payTo:
|
|
445
|
-
maxTimeoutSeconds:
|
|
446
|
-
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()
|
|
447
796
|
});
|
|
448
|
-
var ResourceInfoV2 =
|
|
449
|
-
url:
|
|
450
|
-
description:
|
|
451
|
-
mimeType:
|
|
797
|
+
var ResourceInfoV2 = z3.object({
|
|
798
|
+
url: z3.string(),
|
|
799
|
+
description: z3.string().optional(),
|
|
800
|
+
mimeType: z3.string().optional()
|
|
452
801
|
});
|
|
453
|
-
var PaymentRequiredV2 =
|
|
454
|
-
x402Version:
|
|
455
|
-
error:
|
|
802
|
+
var PaymentRequiredV2 = z3.object({
|
|
803
|
+
x402Version: z3.literal(2),
|
|
804
|
+
error: z3.string().optional(),
|
|
456
805
|
resource: ResourceInfoV2.optional(),
|
|
457
|
-
accepts:
|
|
458
|
-
extensions:
|
|
806
|
+
accepts: z3.array(PaymentRequirementsV2).min(1),
|
|
807
|
+
extensions: z3.record(z3.unknown()).optional()
|
|
459
808
|
});
|
|
460
809
|
function v2Requirements(requirement) {
|
|
461
810
|
return {
|
|
@@ -468,7 +817,7 @@ function v2Requirements(requirement) {
|
|
|
468
817
|
...requirement.extra ? { extra: requirement.extra } : {}
|
|
469
818
|
};
|
|
470
819
|
}
|
|
471
|
-
function buildPaymentRequiredV2(requirement, error) {
|
|
820
|
+
function buildPaymentRequiredV2(requirement, error, extensions = {}) {
|
|
472
821
|
return {
|
|
473
822
|
x402Version: 2,
|
|
474
823
|
error,
|
|
@@ -480,17 +829,17 @@ function buildPaymentRequiredV2(requirement, error) {
|
|
|
480
829
|
}
|
|
481
830
|
} : {},
|
|
482
831
|
accepts: [v2Requirements(requirement)],
|
|
483
|
-
extensions
|
|
832
|
+
extensions
|
|
484
833
|
};
|
|
485
834
|
}
|
|
486
835
|
function encodeBase64Json(value) {
|
|
487
836
|
return Buffer.from(JSON.stringify(value)).toString("base64");
|
|
488
837
|
}
|
|
489
|
-
var V1Envelope =
|
|
490
|
-
x402Version:
|
|
491
|
-
scheme:
|
|
492
|
-
network:
|
|
493
|
-
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())
|
|
494
843
|
});
|
|
495
844
|
|
|
496
845
|
// src/errors.ts
|
|
@@ -504,35 +853,35 @@ var FacilitatorError = class extends Error {
|
|
|
504
853
|
};
|
|
505
854
|
|
|
506
855
|
// src/payload.ts
|
|
507
|
-
import { z as
|
|
508
|
-
var MockExactPayload =
|
|
509
|
-
from:
|
|
510
|
-
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),
|
|
511
860
|
/** Atomic-unit amount, mirroring the requirement's maxAmountRequired. */
|
|
512
|
-
value:
|
|
513
|
-
asset:
|
|
861
|
+
value: z4.string().regex(/^\d+$/, "atomic amount must be an integer string"),
|
|
862
|
+
asset: z4.string().min(1),
|
|
514
863
|
/**
|
|
515
864
|
* Rein linkage: the guard's payer stamps the intent id here, the facilitator
|
|
516
865
|
* memos it onto the ledger entry, and the indexer reconciles exactly. A real
|
|
517
866
|
* x402 transfer authorization carries a nonce that serves the same role.
|
|
518
867
|
*/
|
|
519
|
-
intentId:
|
|
520
|
-
nonce:
|
|
868
|
+
intentId: z4.string().optional(),
|
|
869
|
+
nonce: z4.string().optional()
|
|
521
870
|
});
|
|
522
|
-
var MockPaymentHeader =
|
|
523
|
-
x402Version:
|
|
524
|
-
scheme:
|
|
525
|
-
network:
|
|
871
|
+
var MockPaymentHeader = z4.object({
|
|
872
|
+
x402Version: z4.literal(1),
|
|
873
|
+
scheme: z4.string(),
|
|
874
|
+
network: z4.string(),
|
|
526
875
|
payload: MockExactPayload
|
|
527
876
|
});
|
|
528
|
-
var MockPaymentHeaderV2 =
|
|
529
|
-
x402Version:
|
|
530
|
-
accepted:
|
|
531
|
-
scheme:
|
|
532
|
-
network:
|
|
533
|
-
amount:
|
|
534
|
-
asset:
|
|
535
|
-
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)
|
|
536
885
|
}).passthrough(),
|
|
537
886
|
payload: MockExactPayload
|
|
538
887
|
}).passthrough();
|
|
@@ -578,12 +927,12 @@ function decodePaymentHeader(raw) {
|
|
|
578
927
|
payload: parsed.data.payload
|
|
579
928
|
};
|
|
580
929
|
}
|
|
581
|
-
var SettlementResponse =
|
|
582
|
-
success:
|
|
930
|
+
var SettlementResponse = z4.object({
|
|
931
|
+
success: z4.boolean(),
|
|
583
932
|
/** The tx hash on the mock ledger (the guard surfaces this on the receipt). */
|
|
584
|
-
transaction:
|
|
585
|
-
network:
|
|
586
|
-
payer:
|
|
933
|
+
transaction: z4.string(),
|
|
934
|
+
network: z4.string(),
|
|
935
|
+
payer: z4.string().optional()
|
|
587
936
|
});
|
|
588
937
|
function encodeSettlementHeader(response) {
|
|
589
938
|
return Buffer.from(JSON.stringify(response)).toString("base64");
|