better-call 0.0.0-experimental.01ff4b77

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.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -0
  3. package/dist/capability.cjs +417 -0
  4. package/dist/capability.cjs.map +1 -0
  5. package/dist/capability.d.cts +189 -0
  6. package/dist/capability.d.mts +189 -0
  7. package/dist/capability.mjs +401 -0
  8. package/dist/capability.mjs.map +1 -0
  9. package/dist/error.cjs +76 -0
  10. package/dist/error.cjs.map +1 -0
  11. package/dist/error.d.cts +51 -0
  12. package/dist/error.d.mts +51 -0
  13. package/dist/error.mjs +72 -0
  14. package/dist/error.mjs.map +1 -0
  15. package/dist/fn.cjs +350 -0
  16. package/dist/fn.cjs.map +1 -0
  17. package/dist/fn.d.cts +378 -0
  18. package/dist/fn.d.mts +378 -0
  19. package/dist/fn.mjs +350 -0
  20. package/dist/fn.mjs.map +1 -0
  21. package/dist/index.cjs +43 -0
  22. package/dist/index.cjs.map +1 -0
  23. package/dist/index.d.cts +50 -0
  24. package/dist/index.d.mts +50 -0
  25. package/dist/index.mjs +24 -0
  26. package/dist/index.mjs.map +1 -0
  27. package/dist/module.cjs +176 -0
  28. package/dist/module.cjs.map +1 -0
  29. package/dist/module.d.cts +283 -0
  30. package/dist/module.d.mts +283 -0
  31. package/dist/module.mjs +166 -0
  32. package/dist/module.mjs.map +1 -0
  33. package/dist/plugins/db.cjs +24 -0
  34. package/dist/plugins/db.cjs.map +1 -0
  35. package/dist/plugins/db.d.cts +18 -0
  36. package/dist/plugins/db.d.mts +18 -0
  37. package/dist/plugins/db.mjs +19 -0
  38. package/dist/plugins/db.mjs.map +1 -0
  39. package/dist/plugins/http/attrs.cjs +91 -0
  40. package/dist/plugins/http/attrs.cjs.map +1 -0
  41. package/dist/plugins/http/attrs.d.cts +26 -0
  42. package/dist/plugins/http/attrs.d.mts +26 -0
  43. package/dist/plugins/http/attrs.mjs +87 -0
  44. package/dist/plugins/http/attrs.mjs.map +1 -0
  45. package/dist/plugins/http/cookie.cjs +117 -0
  46. package/dist/plugins/http/cookie.cjs.map +1 -0
  47. package/dist/plugins/http/cookie.d.cts +637 -0
  48. package/dist/plugins/http/cookie.d.mts +637 -0
  49. package/dist/plugins/http/cookie.mjs +113 -0
  50. package/dist/plugins/http/cookie.mjs.map +1 -0
  51. package/dist/plugins/http/error.cjs +39 -0
  52. package/dist/plugins/http/error.cjs.map +1 -0
  53. package/dist/plugins/http/error.d.cts +38 -0
  54. package/dist/plugins/http/error.d.mts +38 -0
  55. package/dist/plugins/http/error.mjs +35 -0
  56. package/dist/plugins/http/error.mjs.map +1 -0
  57. package/dist/plugins/http/handle.cjs +73 -0
  58. package/dist/plugins/http/handle.cjs.map +1 -0
  59. package/dist/plugins/http/handle.d.cts +955 -0
  60. package/dist/plugins/http/handle.d.mts +955 -0
  61. package/dist/plugins/http/handle.mjs +72 -0
  62. package/dist/plugins/http/handle.mjs.map +1 -0
  63. package/dist/plugins/http/redirect.cjs +82 -0
  64. package/dist/plugins/http/redirect.cjs.map +1 -0
  65. package/dist/plugins/http/redirect.d.cts +67 -0
  66. package/dist/plugins/http/redirect.d.mts +67 -0
  67. package/dist/plugins/http/redirect.mjs +79 -0
  68. package/dist/plugins/http/redirect.mjs.map +1 -0
  69. package/dist/plugins/http/request.cjs +63 -0
  70. package/dist/plugins/http/request.cjs.map +1 -0
  71. package/dist/plugins/http/request.d.cts +142 -0
  72. package/dist/plugins/http/request.d.mts +142 -0
  73. package/dist/plugins/http/request.mjs +61 -0
  74. package/dist/plugins/http/request.mjs.map +1 -0
  75. package/dist/plugins/http/response.cjs +13 -0
  76. package/dist/plugins/http/response.cjs.map +1 -0
  77. package/dist/plugins/http/response.d.cts +18 -0
  78. package/dist/plugins/http/response.d.mts +18 -0
  79. package/dist/plugins/http/response.mjs +13 -0
  80. package/dist/plugins/http/response.mjs.map +1 -0
  81. package/dist/plugins/http.cjs +64 -0
  82. package/dist/plugins/http.cjs.map +1 -0
  83. package/dist/plugins/http.d.cts +945 -0
  84. package/dist/plugins/http.d.mts +945 -0
  85. package/dist/plugins/http.mjs +37 -0
  86. package/dist/plugins/http.mjs.map +1 -0
  87. package/dist/plugins/read-only.cjs +19 -0
  88. package/dist/plugins/read-only.cjs.map +1 -0
  89. package/dist/plugins/read-only.d.cts +17 -0
  90. package/dist/plugins/read-only.d.mts +17 -0
  91. package/dist/plugins/read-only.mjs +19 -0
  92. package/dist/plugins/read-only.mjs.map +1 -0
  93. package/dist/schema.cjs +245 -0
  94. package/dist/schema.cjs.map +1 -0
  95. package/dist/schema.d.cts +411 -0
  96. package/dist/schema.d.mts +411 -0
  97. package/dist/schema.mjs +235 -0
  98. package/dist/schema.mjs.map +1 -0
  99. package/dist/scope.d.cts +31 -0
  100. package/dist/scope.d.mts +31 -0
  101. package/dist/storage.cjs +308 -0
  102. package/dist/storage.cjs.map +1 -0
  103. package/dist/storage.d.cts +220 -0
  104. package/dist/storage.d.mts +220 -0
  105. package/dist/storage.mjs +302 -0
  106. package/dist/storage.mjs.map +1 -0
  107. package/dist/types.d.cts +8 -0
  108. package/dist/types.d.mts +8 -0
  109. package/dist/var.cjs +186 -0
  110. package/dist/var.cjs.map +1 -0
  111. package/dist/var.d.cts +46 -0
  112. package/dist/var.d.mts +46 -0
  113. package/dist/var.mjs +177 -0
  114. package/dist/var.mjs.map +1 -0
  115. package/package.json +114 -0
@@ -0,0 +1,417 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_module = require("./module.cjs");
3
+ const require_index = require("./index.cjs");
4
+ const require_attrs = require("./plugins/http/attrs.cjs");
5
+ //#region src/capability.ts
6
+ const subtle = globalThis.crypto.subtle;
7
+ const b64 = (bytes) => {
8
+ const view = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
9
+ let binary = "";
10
+ for (const byte of view) binary += String.fromCharCode(byte);
11
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
12
+ };
13
+ const unb64 = (text) => {
14
+ const binary = atob(text.replaceAll("-", "+").replaceAll("_", "/"));
15
+ const bytes = new Uint8Array(binary.length);
16
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
17
+ return bytes;
18
+ };
19
+ const utf8 = (text) => new TextEncoder().encode(text);
20
+ const generateKeypair = async () => {
21
+ const pair = await subtle.generateKey({ name: "Ed25519" }, true, ["sign", "verify"]);
22
+ return {
23
+ id: b64(await subtle.exportKey("raw", pair.publicKey)),
24
+ sign: async (payload) => b64(await subtle.sign("Ed25519", pair.privateKey, utf8(payload)))
25
+ };
26
+ };
27
+ const verifySignature = async (publicKeyId, payload, signature) => {
28
+ try {
29
+ const key = await subtle.importKey("raw", unb64(publicKeyId), { name: "Ed25519" }, false, ["verify"]);
30
+ return await subtle.verify("Ed25519", key, unb64(signature), utf8(payload));
31
+ } catch {
32
+ return false;
33
+ }
34
+ };
35
+ const fnOf = (cap) => typeof cap === "string" ? cap : cap.fn;
36
+ const pinOf = (cap) => typeof cap === "string" ? void 0 : cap.input;
37
+ const fmtCap = (cap) => typeof cap === "string" || !cap.input ? fnOf(cap) : `${cap.fn}(${JSON.stringify(cap.input)})`;
38
+ const sameJson = (a, b) => JSON.stringify(a) === JSON.stringify(b);
39
+ /** Does holding `parent` justify holding `child`? Same fn, and every
40
+ * field the parent pins must be pinned identically by the child. */
41
+ const covers = (parent, child) => {
42
+ if (fnOf(parent) !== fnOf(child)) return false;
43
+ const pin = pinOf(parent);
44
+ if (!pin) return true;
45
+ const childPin = pinOf(child);
46
+ if (!childPin) return false;
47
+ return Object.entries(pin).every(([field, value]) => sameJson(childPin[field], value));
48
+ };
49
+ /** Do these held caps authorize calling `fn` with `input`? */
50
+ const permits = (caps, fn, input) => caps.some((cap) => {
51
+ if (fnOf(cap) !== fn) return false;
52
+ const pin = pinOf(cap);
53
+ if (!pin) return true;
54
+ return Object.entries(pin).every(([field, value]) => sameJson(input?.[field], value));
55
+ });
56
+ const now = () => Math.floor(Date.now() / 1e3);
57
+ /** Deterministic serialization: object keys sorted at every depth so the
58
+ * signed bytes never depend on construction order or a re-serializing
59
+ * intermediary. This IS the signing format - both minting and verifying
60
+ * go through it. */
61
+ const canonical = (value) => {
62
+ if (value === void 0) return "null";
63
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
64
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
65
+ const source = value;
66
+ return `{${Object.keys(source).filter((key) => source[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonical(source[key])}`).join(",")}}`;
67
+ };
68
+ const payloadOf = (token) => {
69
+ const { sig, ...rest } = token;
70
+ return canonical(rest);
71
+ };
72
+ const mintDelegation = async (issuer, body) => {
73
+ const unsigned = {
74
+ typ: "dlg",
75
+ iss: issuer.id,
76
+ ...body
77
+ };
78
+ return {
79
+ ...unsigned,
80
+ sig: await issuer.sign(payloadOf(unsigned))
81
+ };
82
+ };
83
+ const mintInvocation = async (holder, call, proof, input) => {
84
+ const unsigned = {
85
+ typ: "inv",
86
+ iss: holder.id,
87
+ call,
88
+ input,
89
+ exp: now() + 30,
90
+ nonce: b64(crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(8))),
91
+ prf: proof
92
+ };
93
+ return {
94
+ ...unsigned,
95
+ sig: await holder.sign(payloadOf(unsigned))
96
+ };
97
+ };
98
+ var CapabilityError = class extends Error {
99
+ constructor(message) {
100
+ super(message);
101
+ this.name = "CapabilityError";
102
+ }
103
+ };
104
+ /** A crafted chain of self-signed links (valid until the root check at the
105
+ * very bottom) would otherwise force unbounded recursion and signature
106
+ * verifications - a cheap denial-of-service. Cap the depth. */
107
+ const MAX_DELEGATION_DEPTH = 16;
108
+ /** Walk the chain: every link signed, attenuating, unexpired, rooted. */
109
+ const verifyDelegation = async (root, link, depth = 0) => {
110
+ if (depth > 16) throw new CapabilityError("delegation chain too deep");
111
+ if (link.typ !== "dlg") throw new CapabilityError("not a delegation");
112
+ if (link.exp < now()) throw new CapabilityError("delegation expired");
113
+ if (!await verifySignature(link.iss, payloadOf(link), link.sig)) throw new CapabilityError("bad delegation signature");
114
+ if (!link.prf) {
115
+ if (link.iss !== root) throw new CapabilityError("chain does not root at this server");
116
+ return link;
117
+ }
118
+ const parent = await verifyDelegation(root, link.prf, depth + 1);
119
+ if (parent.aud !== link.iss) throw new CapabilityError("delegation not issued by its parent's audience");
120
+ if (parent.sub !== link.sub) throw new CapabilityError("delegation changes subject");
121
+ for (const cap of link.caps) if (!parent.caps.some((held) => covers(held, cap))) throw new CapabilityError(`delegation escalates: ${fmtCap(cap)}`);
122
+ return link;
123
+ };
124
+ const verifyInvocation = async (root, token) => {
125
+ if (token?.typ !== "inv") throw new CapabilityError("not an invocation");
126
+ if (token.exp < now()) throw new CapabilityError("invocation expired");
127
+ if (!await verifySignature(token.iss, payloadOf(token), token.sig)) throw new CapabilityError("bad invocation signature");
128
+ const proof = await verifyDelegation(root, token.prf);
129
+ if (proof.aud !== token.iss) throw new CapabilityError("invocation not signed by delegation holder");
130
+ return {
131
+ subject: proof.sub,
132
+ caps: proof.caps,
133
+ holder: token.iss
134
+ };
135
+ };
136
+ const verifyAttestation = async (root, token) => {
137
+ if (token?.typ !== "idt") throw new CapabilityError("not an attestation");
138
+ if (token.exp < now()) throw new CapabilityError("attestation expired");
139
+ if (token.iss !== root) throw new CapabilityError("attestation not signed by this server");
140
+ if (!await verifySignature(token.iss, payloadOf(token), token.sig)) throw new CapabilityError("bad attestation signature");
141
+ return token.sub;
142
+ };
143
+ const capability = require_index.v.var("capability", { default: null });
144
+ const validateCaller = (fnKey) => require_index.v.on(fnKey, async (c, next) => {
145
+ const wire = c.capability;
146
+ if (!wire) return next();
147
+ if (wire.entry === fnKey) {
148
+ if (!permits(wire.caps, fnKey, c.input)) throw new CapabilityError(`"${fnKey}" refused: caller's references do not cover it (held: ${wire.caps.map(fmtCap).join(", ") || "none"})`);
149
+ c.capability = {
150
+ ...wire,
151
+ entry: null
152
+ };
153
+ return next();
154
+ }
155
+ return next();
156
+ });
157
+ /**
158
+ * The remote boundary - the ONLY place a reference is ever reified or
159
+ * verified, and the only construction in the whole model. Capabilities
160
+ * are not registered or created anywhere: the fns you serve ARE the
161
+ * capability space, one per key, and EVERY one of them validates its
162
+ * caller - there is no public list. Everything crosses as data: a fn
163
+ * key, JSON input, and a freshly minted invocation. Verification sets
164
+ * `c.capability`; `validateCaller` on every fn does the rest.
165
+ */
166
+ const serve = async (modules, authority) => {
167
+ const key = await generateKeypair();
168
+ const ttl = authority.ttl ?? 3600;
169
+ const challenges = /* @__PURE__ */ new Map();
170
+ let challengeSeq = 0;
171
+ const spent = /* @__PURE__ */ new Map();
172
+ const spend = async (token) => {
173
+ const held = await verifyInvocation(key.id, token);
174
+ const t = now();
175
+ for (const [seen, exp] of spent) if (exp < t) spent.delete(seen);
176
+ const id = `${token.iss}:${token.nonce}`;
177
+ if (spent.has(id)) throw new CapabilityError("invocation already spent");
178
+ spent.set(id, token.exp);
179
+ return held;
180
+ };
181
+ const issue = (holder, subject, caps) => mintDelegation(key, {
182
+ aud: holder,
183
+ sub: subject,
184
+ caps,
185
+ exp: now() + ttl
186
+ });
187
+ const mintAttestation = async (subject) => {
188
+ const unsigned = {
189
+ typ: "idt",
190
+ iss: key.id,
191
+ sub: subject,
192
+ exp: now() + ttl
193
+ };
194
+ return {
195
+ ...unsigned,
196
+ sig: await key.sign(payloadOf(unsigned))
197
+ };
198
+ };
199
+ const attest = authority.attest ?? mintAttestation;
200
+ const verify = authority.verify ?? ((attestation) => verifyAttestation(key.id, attestation));
201
+ /** A reference is only as real as its fn: naming one that is not
202
+ * served is refused outright - there is no registry it could exist in
203
+ * instead. */
204
+ const assertServed = (caps, fns) => {
205
+ for (const cap of caps) if (!fns[fnOf(cap)]) throw new CapabilityError(`no fn "${fnOf(cap)}" to have a cap for`);
206
+ };
207
+ const fns = {};
208
+ const builtins = { request: require_index.v.fn("capability.request", { input: {
209
+ holder: require_index.v.string({ optional: true }),
210
+ token: require_index.v.any(),
211
+ attestation: require_index.v.any(),
212
+ caps: require_index.v.any(),
213
+ goal: require_index.v.string({ optional: true })
214
+ } }, async (c) => {
215
+ const caps = c.input.caps;
216
+ if (!caps) {
217
+ const holder = c.input.holder;
218
+ if (!holder) throw new CapabilityError("no holder");
219
+ const subject = c.input.attestation ? await verify(c.input.attestation) : null;
220
+ if (c.input.attestation && subject == null) throw new CapabilityError("attestation does not pass");
221
+ const granted = authority.defaults(subject);
222
+ assertServed(granted, fns);
223
+ return {
224
+ status: subject ? "approved" : "challenge",
225
+ delegation: await issue(holder, subject ?? `anon:${holder}`, granted)
226
+ };
227
+ }
228
+ const token = c.input.token;
229
+ if (token?.call !== "capability.request") throw new CapabilityError("invocation not minted for capability.request");
230
+ const held = await spend(token);
231
+ assertServed(caps, fns);
232
+ const payout = async () => ({
233
+ status: "approved",
234
+ delegation: await issue(held.holder, held.subject, [...held.caps, ...caps])
235
+ });
236
+ const open = [...challenges.values()].find((challenge) => challenge.holder === held.holder && sameJson(challenge.caps, caps));
237
+ if (open) {
238
+ if (open.status === "pending") return {
239
+ status: "challenge",
240
+ id: open.id
241
+ };
242
+ challenges.delete(open.id);
243
+ return open.status === "approved" ? payout() : { status: "denied" };
244
+ }
245
+ const verdict = (authority.decide ?? (() => "challenge"))({
246
+ subject: held.subject,
247
+ caps,
248
+ goal: c.input.goal
249
+ });
250
+ if (verdict === "deny") return { status: "denied" };
251
+ if (verdict === "approve") return payout();
252
+ const id = `chal_${++challengeSeq}`;
253
+ challenges.set(id, {
254
+ id,
255
+ subject: held.subject,
256
+ holder: held.holder,
257
+ caps,
258
+ goal: c.input.goal,
259
+ status: "pending"
260
+ });
261
+ return {
262
+ status: "challenge",
263
+ id
264
+ };
265
+ }) };
266
+ const builtinKeys = new Set(Object.values(builtins).map((builtin) => builtin.key));
267
+ for (const fn of Object.values({
268
+ ...require_module.collectFns([modules]),
269
+ ...builtins
270
+ })) fns[fn.key] = fn;
271
+ assertServed(authority.defaults(null), fns);
272
+ const guards = Object.fromEntries(Object.keys(fns).filter((fnKey) => !builtinKeys.has(fnKey)).map((fnKey) => [`guard ${fnKey}`, validateCaller(fnKey)]));
273
+ /** ANY fn can prove identity: when `identify` reads a subject out of a
274
+ * result, attested proof of WHO rides back alongside it. */
275
+ const attestors = Object.fromEntries(Object.keys(fns).filter((fnKey) => !builtinKeys.has(fnKey)).map((fnKey) => [`attest ${fnKey}`, require_index.v.on(fnKey, async (_c, next) => {
276
+ const result = await next();
277
+ const subject = authority.identify(result);
278
+ if (subject == null) return result;
279
+ return {
280
+ ...result,
281
+ attestation: await attest(subject)
282
+ };
283
+ })]));
284
+ const exec = require_index.v.fn("capability.exec", {
285
+ input: {
286
+ call: require_index.v.string(),
287
+ input: require_index.v.any(),
288
+ token: require_index.v.any()
289
+ },
290
+ use: [
291
+ modules,
292
+ { capability },
293
+ guards,
294
+ attestors
295
+ ]
296
+ }, async (c) => {
297
+ const target = fns[c.input.call];
298
+ if (!target) throw new CapabilityError(`no fn "${c.input.call}"`);
299
+ if (!builtinKeys.has(c.input.call)) {
300
+ const token = c.input.token;
301
+ if (!token) throw new CapabilityError("no capability presented");
302
+ if (token.call !== c.input.call) throw new CapabilityError("invocation minted for a different fn");
303
+ if (!sameJson(token.input, c.input.input)) throw new CapabilityError("invocation minted for different input");
304
+ c.capability = {
305
+ ...await spend(token),
306
+ entry: c.input.call
307
+ };
308
+ }
309
+ const inputSchema = target.$schema?.input;
310
+ if (inputSchema !== void 0) require_attrs.rejectServerOnly(inputSchema, c.input.input, c.input.call);
311
+ return target(c.input.input, c);
312
+ });
313
+ /** The user's side of a challenge - the demo calls it directly; a real
314
+ * server surfaces it in the IDP, an email, wherever the user is. */
315
+ const decide = (id, approve) => {
316
+ const challenge = challenges.get(id);
317
+ if (challenge) challenge.status = approve ? "approved" : "denied";
318
+ return challenge;
319
+ };
320
+ return {
321
+ exec,
322
+ decide,
323
+ challenges,
324
+ key: key.id
325
+ };
326
+ };
327
+ /**
328
+ * An agent: a keypair plus whatever reified references it holds. Born
329
+ * asking - creation requests the default caps. Without attestation, the
330
+ * answer is the bootstrap challenge: a delegation whose only power is
331
+ * signing in. With attestation (passed in, or earned by a call whose
332
+ * result attests), the answer is the defaults. EVERY call re-mints a
333
+ * single-use invocation over the fn AND the input; nothing is public.
334
+ */
335
+ const createAgent = async (transport, options) => {
336
+ const me = await generateKeypair();
337
+ let held = null;
338
+ let attestation = options?.attestation ?? null;
339
+ const requestDefaults = async () => {
340
+ const result = await transport({
341
+ call: "capability.request",
342
+ input: {
343
+ holder: me.id,
344
+ attestation: attestation ?? void 0
345
+ }
346
+ });
347
+ if (result.delegation) held = result.delegation;
348
+ return result;
349
+ };
350
+ await requestDefaults();
351
+ return {
352
+ id: me.id,
353
+ attestation: () => attestation,
354
+ hold: (delegation) => {
355
+ held = delegation;
356
+ },
357
+ held: () => held,
358
+ call: async (call, input) => {
359
+ if (!held) throw new CapabilityError("agent holds no delegation");
360
+ const result = await transport({
361
+ call,
362
+ input,
363
+ token: await mintInvocation(me, call, held, input)
364
+ });
365
+ if (result?.attestation != null) {
366
+ attestation = result.attestation;
367
+ await requestDefaults();
368
+ }
369
+ return result;
370
+ },
371
+ request: async (caps, goal) => {
372
+ if (!held) throw new CapabilityError("agent holds no delegation");
373
+ const result = await transport({
374
+ call: "capability.request",
375
+ input: {
376
+ token: await mintInvocation(me, "capability.request", held),
377
+ caps,
378
+ goal
379
+ }
380
+ });
381
+ if (result.status === "approved") held = result.delegation;
382
+ return result;
383
+ },
384
+ /** Hand a SLICE of held references to another agent, re-minted for
385
+ * their key - fewer fns, or the same fn pinned to narrower input.
386
+ * The other agent spends with their own signature. */
387
+ delegate: async (toAgentId, caps) => {
388
+ if (!held) throw new CapabilityError("agent holds no delegation");
389
+ return mintDelegation(me, {
390
+ aud: toAgentId,
391
+ sub: held.sub,
392
+ caps,
393
+ exp: held.exp,
394
+ prf: held
395
+ });
396
+ }
397
+ };
398
+ };
399
+ //#endregion
400
+ exports.CapabilityError = CapabilityError;
401
+ exports.MAX_DELEGATION_DEPTH = MAX_DELEGATION_DEPTH;
402
+ exports.capability = capability;
403
+ exports.covers = covers;
404
+ exports.createAgent = createAgent;
405
+ exports.fmtCap = fmtCap;
406
+ exports.fnOf = fnOf;
407
+ exports.generateKeypair = generateKeypair;
408
+ exports.mintDelegation = mintDelegation;
409
+ exports.mintInvocation = mintInvocation;
410
+ exports.permits = permits;
411
+ exports.serve = serve;
412
+ exports.validateCaller = validateCaller;
413
+ exports.verifyAttestation = verifyAttestation;
414
+ exports.verifyDelegation = verifyDelegation;
415
+ exports.verifyInvocation = verifyInvocation;
416
+
417
+ //# sourceMappingURL=capability.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability.cjs","names":["v","collectFns"],"sources":["../src/capability.ts"],"sourcesContent":["import { collectFns, type FnDefination, type Module, v } from \"./index\";\nimport { rejectServerOnly } from \"./plugins/http/attrs\";\n\nconst subtle = globalThis.crypto.subtle;\n\nconst b64 = (bytes: ArrayBuffer | Uint8Array) => {\n\tconst view = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n\tlet binary = \"\";\n\tfor (const byte of view) binary += String.fromCharCode(byte);\n\treturn btoa(binary)\n\t\t.replaceAll(\"+\", \"-\")\n\t\t.replaceAll(\"/\", \"_\")\n\t\t.replace(/=+$/, \"\");\n};\n\nconst unb64 = (text: string) => {\n\tconst binary = atob(text.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\"));\n\tconst bytes = new Uint8Array(binary.length);\n\tfor (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n\treturn bytes;\n};\n\nconst utf8 = (text: string) => new TextEncoder().encode(text);\n\nexport type Keypair = {\n\tid: string;\n\tsign: (payload: string) => Promise<string>;\n};\n\nexport const generateKeypair = async (): Promise<Keypair> => {\n\tconst pair = (await subtle.generateKey({ name: \"Ed25519\" }, true, [\n\t\t\"sign\",\n\t\t\"verify\",\n\t])) as CryptoKeyPair;\n\tconst id = b64(await subtle.exportKey(\"raw\", pair.publicKey));\n\treturn {\n\t\tid,\n\t\tsign: async (payload) =>\n\t\t\tb64(await subtle.sign(\"Ed25519\", pair.privateKey, utf8(payload))),\n\t};\n};\n\nconst verifySignature = async (\n\tpublicKeyId: string,\n\tpayload: string,\n\tsignature: string,\n) => {\n\t// Malformed base64, a wrong-length key, or a bad signature are all just\n\t// \"this did not verify\" - never a thrown DOMException that escapes the\n\t// CapabilityError contract the callers rely on.\n\ttry {\n\t\tconst key = await subtle.importKey(\n\t\t\t\"raw\",\n\t\t\tunb64(publicKeyId),\n\t\t\t{ name: \"Ed25519\" },\n\t\t\tfalse,\n\t\t\t[\"verify\"],\n\t\t);\n\t\treturn await subtle.verify(\"Ed25519\", key, unb64(signature), utf8(payload));\n\t} catch {\n\t\treturn false;\n\t}\n};\n\n/** The name of a right: a fn key, optionally pinned to exact input\n * fields. Never signed on its own - delegations carry caps, invocations\n * spend them. */\nexport type Cap = string | { fn: string; input?: Record<string, unknown> };\n\nexport const fnOf = (cap: Cap) => (typeof cap === \"string\" ? cap : cap.fn);\n\nconst pinOf = (cap: Cap) => (typeof cap === \"string\" ? undefined : cap.input);\n\nexport const fmtCap = (cap: Cap) =>\n\ttypeof cap === \"string\" || !cap.input\n\t\t? fnOf(cap)\n\t\t: `${cap.fn}(${JSON.stringify(cap.input)})`;\n\nconst sameJson = (a: unknown, b: unknown) =>\n\tJSON.stringify(a) === JSON.stringify(b);\n\n/** Does holding `parent` justify holding `child`? Same fn, and every\n * field the parent pins must be pinned identically by the child. */\nexport const covers = (parent: Cap, child: Cap) => {\n\tif (fnOf(parent) !== fnOf(child)) return false;\n\tconst pin = pinOf(parent);\n\tif (!pin) return true;\n\tconst childPin = pinOf(child);\n\tif (!childPin) return false;\n\treturn Object.entries(pin).every(([field, value]) =>\n\t\tsameJson(childPin[field], value),\n\t);\n};\n\n/** Do these held caps authorize calling `fn` with `input`? */\nexport const permits = (caps: Cap[], fn: string, input: unknown) =>\n\tcaps.some((cap) => {\n\t\tif (fnOf(cap) !== fn) return false;\n\t\tconst pin = pinOf(cap);\n\t\tif (!pin) return true;\n\t\treturn Object.entries(pin).every(([field, value]) =>\n\t\t\tsameJson((input as Record<string, unknown>)?.[field], value),\n\t\t);\n\t});\n\nexport type Delegation = {\n\ttyp: \"dlg\";\n\tiss: string;\n\taud: string;\n\tsub: string;\n\tcaps: Cap[];\n\texp: number;\n\tprf?: Delegation;\n\tsig: string;\n};\n\nexport type Invocation = {\n\ttyp: \"inv\";\n\tiss: string;\n\tcall: string;\n\tinput?: unknown;\n\texp: number;\n\tnonce: string;\n\tprf: Delegation;\n\tsig: string;\n};\n\nconst now = () => Math.floor(Date.now() / 1000);\n\n/** Deterministic serialization: object keys sorted at every depth so the\n * signed bytes never depend on construction order or a re-serializing\n * intermediary. This IS the signing format - both minting and verifying\n * go through it. */\nconst canonical = (value: unknown): string => {\n\t// Mirror JSON.stringify's treatment of undefined so the signed bytes\n\t// survive a JSON wire round-trip: an undefined object field is dropped,\n\t// an undefined array slot becomes null.\n\tif (value === undefined) return \"null\";\n\tif (value === null || typeof value !== \"object\") return JSON.stringify(value);\n\tif (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`;\n\tconst source = value as Record<string, unknown>;\n\tconst entries = Object.keys(source)\n\t\t.filter((key) => source[key] !== undefined)\n\t\t.sort()\n\t\t.map((key) => `${JSON.stringify(key)}:${canonical(source[key])}`);\n\treturn `{${entries.join(\",\")}}`;\n};\n\nconst payloadOf = (token: Record<string, unknown>) => {\n\tconst { sig, ...rest } = token;\n\treturn canonical(rest);\n};\n\nexport const mintDelegation = async (\n\tissuer: Keypair,\n\tbody: Omit<Delegation, \"typ\" | \"iss\" | \"sig\">,\n): Promise<Delegation> => {\n\tconst unsigned = { typ: \"dlg\" as const, iss: issuer.id, ...body };\n\treturn { ...unsigned, sig: await issuer.sign(payloadOf(unsigned)) };\n};\n\nexport const mintInvocation = async (\n\tholder: Keypair,\n\tcall: string,\n\tproof: Delegation,\n\tinput?: unknown,\n): Promise<Invocation> => {\n\tconst unsigned = {\n\t\ttyp: \"inv\" as const,\n\t\tiss: holder.id,\n\t\tcall,\n\t\tinput,\n\t\texp: now() + 30,\n\t\tnonce: b64(crypto.getRandomValues(new Uint8Array(8))),\n\t\tprf: proof,\n\t};\n\treturn { ...unsigned, sig: await holder.sign(payloadOf(unsigned)) };\n};\n\nexport class CapabilityError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CapabilityError\";\n\t}\n}\n\n/** A crafted chain of self-signed links (valid until the root check at the\n * very bottom) would otherwise force unbounded recursion and signature\n * verifications - a cheap denial-of-service. Cap the depth. */\nexport const MAX_DELEGATION_DEPTH = 16;\n\n/** Walk the chain: every link signed, attenuating, unexpired, rooted. */\nexport const verifyDelegation = async (\n\troot: string,\n\tlink: Delegation,\n\tdepth = 0,\n): Promise<Delegation> => {\n\tif (depth > MAX_DELEGATION_DEPTH) {\n\t\tthrow new CapabilityError(\"delegation chain too deep\");\n\t}\n\tif (link.typ !== \"dlg\") throw new CapabilityError(\"not a delegation\");\n\tif (link.exp < now()) throw new CapabilityError(\"delegation expired\");\n\tif (!(await verifySignature(link.iss, payloadOf(link), link.sig))) {\n\t\tthrow new CapabilityError(\"bad delegation signature\");\n\t}\n\tif (!link.prf) {\n\t\tif (link.iss !== root) {\n\t\t\tthrow new CapabilityError(\"chain does not root at this server\");\n\t\t}\n\t\treturn link;\n\t}\n\tconst parent = await verifyDelegation(root, link.prf, depth + 1);\n\tif (parent.aud !== link.iss) {\n\t\tthrow new CapabilityError(\"delegation not issued by its parent's audience\");\n\t}\n\tif (parent.sub !== link.sub) {\n\t\tthrow new CapabilityError(\"delegation changes subject\");\n\t}\n\tfor (const cap of link.caps) {\n\t\tif (!parent.caps.some((held) => covers(held, cap))) {\n\t\t\tthrow new CapabilityError(`delegation escalates: ${fmtCap(cap)}`);\n\t\t}\n\t}\n\treturn link;\n};\n\nexport const verifyInvocation = async (root: string, token: Invocation) => {\n\tif (token?.typ !== \"inv\") throw new CapabilityError(\"not an invocation\");\n\tif (token.exp < now()) throw new CapabilityError(\"invocation expired\");\n\tif (!(await verifySignature(token.iss, payloadOf(token), token.sig))) {\n\t\tthrow new CapabilityError(\"bad invocation signature\");\n\t}\n\tconst proof = await verifyDelegation(root, token.prf);\n\t// Proof of possession: ONLY the delegation's audience can spend it. A\n\t// stolen delegation is inert - spending demands a re-mint by `aud`.\n\tif (proof.aud !== token.iss) {\n\t\tthrow new CapabilityError(\"invocation not signed by delegation holder\");\n\t}\n\treturn { subject: proof.sub, caps: proof.caps, holder: token.iss };\n};\n\nexport type Attestation = {\n\ttyp: \"idt\";\n\tiss: string;\n\tsub: string;\n\texp: number;\n\tsig: string;\n};\n\nexport const verifyAttestation = async (root: string, token: Attestation) => {\n\tif (token?.typ !== \"idt\") throw new CapabilityError(\"not an attestation\");\n\tif (token.exp < now()) throw new CapabilityError(\"attestation expired\");\n\tif (token.iss !== root) {\n\t\tthrow new CapabilityError(\"attestation not signed by this server\");\n\t}\n\tif (!(await verifySignature(token.iss, payloadOf(token), token.sig))) {\n\t\tthrow new CapabilityError(\"bad attestation signature\");\n\t}\n\treturn token.sub;\n};\n\nexport const capability = v.var(\"capability\", {\n\tdefault: null as null | {\n\t\tsubject: string;\n\t\tcaps: Cap[];\n\t\tholder: string;\n\t\tentry: string | null;\n\t},\n});\n\nexport const validateCaller = (fnKey: string) =>\n\tv.on(fnKey, async (c, next) => {\n\t\tconst wire = c.capability;\n\t\t// No boundary above this call: the caller reached this fn through\n\t\t// a memory reference it was handed. That possession is the\n\t\t// capability - nothing to verify.\n\t\tif (!wire) return next();\n\t\tif (wire.entry === fnKey) {\n\t\t\t// The boundary frame itself: the caller holds no memory\n\t\t\t// reference here, only the reified one - it must cover this fn\n\t\t\t// AND this input.\n\t\t\tif (!permits(wire.caps, fnKey, c.input)) {\n\t\t\t\tthrow new CapabilityError(\n\t\t\t\t\t`\"${fnKey}\" refused: caller's references do not cover it (held: ${wire.caps.map(fmtCap).join(\", \") || \"none\"})`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// The wire hop is spent: below this frame, every call is\n\t\t\t// fn-to-fn by direct reference again.\n\t\t\tc.capability = { ...wire, entry: null };\n\t\t\treturn next();\n\t\t}\n\t\t// Called from inside by a fn that already passed the boundary\n\t\t// check: its body holds this fn by reference - implied.\n\t\treturn next();\n\t});\n\n/* -------------------------------- authority -------------------------------- */\n\nexport type Challenge = {\n\tid: string;\n\tsubject: string;\n\tholder: string;\n\tcaps: Cap[];\n\tgoal?: string;\n\tstatus: \"pending\" | \"approved\" | \"denied\";\n};\n\n/**\n * Authority never checks a call - `validateCaller` owns that. It answers\n * the questions that come BEFORE any call: what references does a caller\n * start with, what proves WHO a caller acts for, and how are requests\n * for more settled?\n */\nexport type Authority = {\n\t/**\n\t * The first grant: what a request with no caps named pays out, given\n\t * who was proven - and `null` IS an answer. Nobody's defaults should\n\t * be just enough to go earn attestation (here: sign in); there is no\n\t * separate \"bootstrap caps\" list.\n\t */\n\tdefaults: (subject: string | null) => Cap[];\n\t/**\n\t * Reads a proven subject out of ANY fn's result: the moment authority\n\t * learns WHO, attested proof rides back alongside the result.\n\t */\n\tidentify: (result: unknown) => string | null;\n\t/**\n\t * Turns a subject into the portable attestation handed back. Defaults\n\t * to a token this server signs itself; swap together with `verify` to\n\t * lean on an external IDP instead.\n\t */\n\tattest?: (subject: string) => unknown | Promise<unknown>;\n\t/** Decides whether a presented attestation passes. */\n\tverify?: (attestation: unknown) => string | null | Promise<string | null>;\n\t/** How widening requests are settled. Default: challenge everything. */\n\tdecide?: (request: {\n\t\tsubject: string;\n\t\tcaps: Cap[];\n\t\tgoal?: string;\n\t}) => \"approve\" | \"challenge\" | \"deny\";\n\t/** Delegation and attestation lifetime, seconds. */\n\tttl?: number;\n};\n\n/* --------------------------------- server --------------------------------- */\n\n/**\n * The remote boundary - the ONLY place a reference is ever reified or\n * verified, and the only construction in the whole model. Capabilities\n * are not registered or created anywhere: the fns you serve ARE the\n * capability space, one per key, and EVERY one of them validates its\n * caller - there is no public list. Everything crosses as data: a fn\n * key, JSON input, and a freshly minted invocation. Verification sets\n * `c.capability`; `validateCaller` on every fn does the rest.\n */\nexport const serve = async (\n\tmodules: Record<string, unknown>,\n\tauthority: Authority,\n) => {\n\tconst key = await generateKeypair();\n\tconst ttl = authority.ttl ?? 3600;\n\tconst challenges = new Map<string, Challenge>();\n\tlet challengeSeq = 0;\n\n\t// A minted invocation spends exactly ONCE. Its nonce is remembered\n\t// until the invocation would expire anyway; a replay within that window\n\t// is refused. This is what makes \"single-use\" true rather than a claim.\n\tconst spent = new Map<string, number>();\n\tconst spend = async (token: Invocation) => {\n\t\tconst held = await verifyInvocation(key.id, token);\n\t\tconst t = now();\n\t\tfor (const [seen, exp] of spent) if (exp < t) spent.delete(seen);\n\t\tconst id = `${token.iss}:${token.nonce}`;\n\t\tif (spent.has(id)) throw new CapabilityError(\"invocation already spent\");\n\t\tspent.set(id, token.exp);\n\t\treturn held;\n\t};\n\n\tconst issue = (holder: string, subject: string, caps: Cap[]) =>\n\t\tmintDelegation(key, { aud: holder, sub: subject, caps, exp: now() + ttl });\n\n\tconst mintAttestation = async (subject: string): Promise<Attestation> => {\n\t\tconst unsigned = {\n\t\t\ttyp: \"idt\" as const,\n\t\t\tiss: key.id,\n\t\t\tsub: subject,\n\t\t\texp: now() + ttl,\n\t\t};\n\t\treturn { ...unsigned, sig: await key.sign(payloadOf(unsigned)) };\n\t};\n\n\t// What passes as proof of WHO is the authority's policy. The default\n\t// pair is self-generated: this server attests subjects with its own\n\t// signed id token, and only such tokens verify back.\n\tconst attest = authority.attest ?? mintAttestation;\n\tconst verify =\n\t\tauthority.verify ??\n\t\t((attestation: unknown) =>\n\t\t\tverifyAttestation(key.id, attestation as Attestation));\n\n\t/** A reference is only as real as its fn: naming one that is not\n\t * served is refused outright - there is no registry it could exist in\n\t * instead. */\n\tconst assertServed = (caps: Cap[], fns: Record<string, unknown>) => {\n\t\tfor (const cap of caps) {\n\t\t\tif (!fns[fnOf(cap)]) {\n\t\t\t\tthrow new CapabilityError(`no fn \"${fnOf(cap)}\" to have a cap for`);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst fns: Record<string, FnDefination<any, any>> = {};\n\n\t/**\n\t * The one entry point that needs no capability - it is where reified\n\t * references come from. No caps named = asking for the DEFAULTS:\n\t * whoever the presented attestation proves gets that subject's\n\t * defaults; empty hands get NOBODY'S defaults as a challenge - just\n\t * enough power to go earn attestation. Caps named = widening: approve\n\t * / challenge / deny by the authority, and asking again with the same\n\t * caps resumes an open challenge.\n\t */\n\tconst request = v.fn(\n\t\t\"capability.request\",\n\t\t{\n\t\t\tinput: {\n\t\t\t\tholder: v.string({ optional: true }),\n\t\t\t\ttoken: v.any(),\n\t\t\t\tattestation: v.any(),\n\t\t\t\tcaps: v.any(),\n\t\t\t\tgoal: v.string({ optional: true }),\n\t\t\t},\n\t\t},\n\t\tasync (c) => {\n\t\t\tconst caps = c.input.caps as Cap[] | undefined;\n\n\t\t\tif (!caps) {\n\t\t\t\tconst holder = c.input.holder;\n\t\t\t\tif (!holder) throw new CapabilityError(\"no holder\");\n\t\t\t\tconst subject = c.input.attestation\n\t\t\t\t\t? await verify(c.input.attestation)\n\t\t\t\t\t: null;\n\t\t\t\tif (c.input.attestation && subject == null) {\n\t\t\t\t\tthrow new CapabilityError(\"attestation does not pass\");\n\t\t\t\t}\n\t\t\t\t// `null` is an answer: nobody's defaults are the first grant -\n\t\t\t\t// just enough to go earn attestation.\n\t\t\t\tconst granted = authority.defaults(subject);\n\t\t\t\tassertServed(granted, fns);\n\t\t\t\treturn {\n\t\t\t\t\tstatus: subject ? (\"approved\" as const) : (\"challenge\" as const),\n\t\t\t\t\tdelegation: await issue(holder, subject ?? `anon:${holder}`, granted),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// The invocation here proves POSSESSION of a chain - who is\n\t\t\t// asking - not authority over what is asked for; that is the\n\t\t\t// very thing the request is trying to widen. It must still be an\n\t\t\t// invocation minted for THIS builtin, spent once like any other.\n\t\t\tconst token = c.input.token as Invocation | undefined;\n\t\t\tif (token?.call !== \"capability.request\") {\n\t\t\t\tthrow new CapabilityError(\n\t\t\t\t\t\"invocation not minted for capability.request\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst held = await spend(token);\n\t\t\tassertServed(caps, fns);\n\t\t\tconst payout = async () => ({\n\t\t\t\tstatus: \"approved\" as const,\n\t\t\t\tdelegation: await issue(held.holder, held.subject, [\n\t\t\t\t\t...held.caps,\n\t\t\t\t\t...caps,\n\t\t\t\t]),\n\t\t\t});\n\t\t\tconst open = [...challenges.values()].find(\n\t\t\t\t(challenge) =>\n\t\t\t\t\tchallenge.holder === held.holder && sameJson(challenge.caps, caps),\n\t\t\t);\n\t\t\tif (open) {\n\t\t\t\tif (open.status === \"pending\") {\n\t\t\t\t\treturn { status: \"challenge\" as const, id: open.id };\n\t\t\t\t}\n\t\t\t\tchallenges.delete(open.id);\n\t\t\t\treturn open.status === \"approved\"\n\t\t\t\t\t? payout()\n\t\t\t\t\t: { status: \"denied\" as const };\n\t\t\t}\n\t\t\tconst verdict = (authority.decide ?? (() => \"challenge\"))({\n\t\t\t\tsubject: held.subject,\n\t\t\t\tcaps,\n\t\t\t\tgoal: c.input.goal,\n\t\t\t});\n\t\t\tif (verdict === \"deny\") return { status: \"denied\" as const };\n\t\t\tif (verdict === \"approve\") return payout();\n\t\t\tconst id = `chal_${++challengeSeq}`;\n\t\t\tchallenges.set(id, {\n\t\t\t\tid,\n\t\t\t\tsubject: held.subject,\n\t\t\t\tholder: held.holder,\n\t\t\t\tcaps,\n\t\t\t\tgoal: c.input.goal,\n\t\t\t\tstatus: \"pending\",\n\t\t\t});\n\t\t\treturn { status: \"challenge\" as const, id };\n\t\t},\n\t);\n\n\tconst builtins = { request };\n\tconst builtinKeys = new Set<string>(\n\t\tObject.values(builtins).map((builtin) => builtin.key),\n\t);\n\tfor (const fn of Object.values({\n\t\t...collectFns([modules]),\n\t\t...builtins,\n\t})) {\n\t\tfns[fn.key] = fn;\n\t}\n\tassertServed(authority.defaults(null), fns);\n\n\t// The rule, mounted on every served fn: each validates its own caller.\n\tconst guards = Object.fromEntries(\n\t\tObject.keys(fns)\n\t\t\t.filter((fnKey) => !builtinKeys.has(fnKey))\n\t\t\t.map((fnKey) => [`guard ${fnKey}`, validateCaller(fnKey)]),\n\t) as Module;\n\n\t/** ANY fn can prove identity: when `identify` reads a subject out of a\n\t * result, attested proof of WHO rides back alongside it. */\n\tconst attestors = Object.fromEntries(\n\t\tObject.keys(fns)\n\t\t\t.filter((fnKey) => !builtinKeys.has(fnKey))\n\t\t\t.map((fnKey) => [\n\t\t\t\t`attest ${fnKey}`,\n\t\t\t\tv.on(fnKey, async (_c, next) => {\n\t\t\t\t\tconst result = await next();\n\t\t\t\t\tconst subject = authority.identify(result);\n\t\t\t\t\tif (subject == null) return result;\n\t\t\t\t\treturn { ...result, attestation: await attest(subject) };\n\t\t\t\t}),\n\t\t\t]),\n\t) as Module;\n\n\tconst exec = v.fn(\n\t\t\"capability.exec\",\n\t\t{\n\t\t\tinput: { call: v.string(), input: v.any(), token: v.any() },\n\t\t\tuse: [modules, { capability }, guards, attestors],\n\t\t},\n\t\tasync (c) => {\n\t\t\tconst target = fns[c.input.call];\n\t\t\tif (!target) throw new CapabilityError(`no fn \"${c.input.call}\"`);\n\t\t\tif (!builtinKeys.has(c.input.call)) {\n\t\t\t\tconst token = c.input.token as Invocation | undefined;\n\t\t\t\tif (!token) throw new CapabilityError(\"no capability presented\");\n\t\t\t\tif (token.call !== c.input.call) {\n\t\t\t\t\tthrow new CapabilityError(\"invocation minted for a different fn\");\n\t\t\t\t}\n\t\t\t\tif (!sameJson(token.input, c.input.input)) {\n\t\t\t\t\tthrow new CapabilityError(\"invocation minted for different input\");\n\t\t\t\t}\n\t\t\t\t// The boundary only proves the chain is genuinely held and\n\t\t\t\t// bound to this exact message, spent once. Whether it covers\n\t\t\t\t// the call is the target fn's own check - `entry` tells it\n\t\t\t\t// which frame has no memory reference behind it.\n\t\t\t\tconst held = await spend(token);\n\t\t\t\tc.capability = { ...held, entry: c.input.call };\n\t\t\t}\n\t\t\t// Wire edge: reject http.serverOnly fields before the target\n\t\t\t// validates (object validate would otherwise strip them quietly).\n\t\t\tconst inputSchema = (target as FnDefination<any, any>).$schema?.input;\n\t\t\tif (inputSchema !== undefined) {\n\t\t\t\trejectServerOnly(inputSchema, c.input.input, c.input.call);\n\t\t\t}\n\t\t\treturn (target as (i: unknown, p: unknown) => unknown)(c.input.input, c);\n\t\t},\n\t);\n\n\t/** The user's side of a challenge - the demo calls it directly; a real\n\t * server surfaces it in the IDP, an email, wherever the user is. */\n\tconst decide = (id: string, approve: boolean) => {\n\t\tconst challenge = challenges.get(id);\n\t\tif (challenge) challenge.status = approve ? \"approved\" : \"denied\";\n\t\treturn challenge;\n\t};\n\n\treturn { exec, decide, challenges, key: key.id };\n};\n\n/* --------------------------------- client --------------------------------- */\n\nexport type Transport = (message: {\n\tcall: string;\n\tinput?: unknown;\n\ttoken?: Invocation;\n}) => Promise<any>;\n\n/**\n * An agent: a keypair plus whatever reified references it holds. Born\n * asking - creation requests the default caps. Without attestation, the\n * answer is the bootstrap challenge: a delegation whose only power is\n * signing in. With attestation (passed in, or earned by a call whose\n * result attests), the answer is the defaults. EVERY call re-mints a\n * single-use invocation over the fn AND the input; nothing is public.\n */\nexport const createAgent = async (\n\ttransport: Transport,\n\toptions?: { attestation?: unknown },\n) => {\n\tconst me = await generateKeypair();\n\tlet held: Delegation | null = null;\n\t// Opaque to the agent: whatever the server hands back as proof of who\n\t// it acts for, kept and re-presented as-is.\n\tlet attestation: unknown = options?.attestation ?? null;\n\n\tconst requestDefaults = async () => {\n\t\tconst result = await transport({\n\t\t\tcall: \"capability.request\",\n\t\t\tinput: { holder: me.id, attestation: attestation ?? undefined },\n\t\t});\n\t\tif (result.delegation) held = result.delegation as Delegation;\n\t\treturn result;\n\t};\n\n\tawait requestDefaults();\n\n\treturn {\n\t\tid: me.id,\n\t\tattestation: () => attestation,\n\t\thold: (delegation: Delegation) => {\n\t\t\theld = delegation;\n\t\t},\n\t\theld: () => held,\n\t\tcall: async (call: string, input?: unknown) => {\n\t\t\tif (!held) throw new CapabilityError(\"agent holds no delegation\");\n\t\t\tconst token = await mintInvocation(me, call, held, input);\n\t\t\tconst result = await transport({ call, input, token });\n\t\t\t// A result carrying attestation is the server saying \"now I\n\t\t\t// know who you act for\" - keep it, trade it for the defaults.\n\t\t\tif (result?.attestation != null) {\n\t\t\t\tattestation = result.attestation;\n\t\t\t\tawait requestDefaults();\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\trequest: async (caps: Cap[], goal?: string) => {\n\t\t\tif (!held) throw new CapabilityError(\"agent holds no delegation\");\n\t\t\tconst token = await mintInvocation(me, \"capability.request\", held);\n\t\t\tconst result = await transport({\n\t\t\t\tcall: \"capability.request\",\n\t\t\t\tinput: { token, caps, goal },\n\t\t\t});\n\t\t\tif (result.status === \"approved\") held = result.delegation;\n\t\t\treturn result;\n\t\t},\n\t\t/** Hand a SLICE of held references to another agent, re-minted for\n\t\t * their key - fewer fns, or the same fn pinned to narrower input.\n\t\t * The other agent spends with their own signature. */\n\t\tdelegate: async (toAgentId: string, caps: Cap[]) => {\n\t\t\tif (!held) throw new CapabilityError(\"agent holds no delegation\");\n\t\t\treturn mintDelegation(me, {\n\t\t\t\taud: toAgentId,\n\t\t\t\tsub: held.sub,\n\t\t\t\tcaps,\n\t\t\t\texp: held.exp,\n\t\t\t\tprf: held,\n\t\t\t});\n\t\t},\n\t};\n};\n"],"mappings":"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"}