better-call 0.0.0-experimental.6db8ff2b → 0.0.0-experimental.7db9ff2f
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 +15 -1
- package/dist/capability.cjs +1 -1
- package/dist/capability.cjs.map +1 -1
- package/dist/capability.d.cts +32 -10
- package/dist/capability.d.mts +32 -10
- package/dist/capability.mjs +1 -1
- package/dist/capability.mjs.map +1 -1
- package/dist/error.cjs +64 -5
- package/dist/error.cjs.map +1 -1
- package/dist/error.d.cts +48 -3
- package/dist/error.d.mts +48 -3
- package/dist/error.mjs +63 -6
- package/dist/error.mjs.map +1 -1
- package/dist/event.cjs +210 -0
- package/dist/event.cjs.map +1 -0
- package/dist/event.d.cts +84 -0
- package/dist/event.d.mts +84 -0
- package/dist/event.mjs +201 -0
- package/dist/event.mjs.map +1 -0
- package/dist/fn.cjs +218 -138
- package/dist/fn.cjs.map +1 -1
- package/dist/fn.d.cts +43 -14
- package/dist/fn.d.mts +43 -14
- package/dist/fn.mjs +220 -140
- package/dist/fn.mjs.map +1 -1
- package/dist/index.cjs +16 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -6
- package/dist/index.d.mts +17 -6
- package/dist/index.mjs +9 -4
- package/dist/index.mjs.map +1 -1
- package/dist/module.cjs +6 -4
- package/dist/module.cjs.map +1 -1
- package/dist/module.d.cts +62 -28
- package/dist/module.d.mts +62 -28
- package/dist/module.mjs +6 -4
- package/dist/module.mjs.map +1 -1
- package/dist/plugins/db.cjs +30 -14
- package/dist/plugins/db.cjs.map +1 -1
- package/dist/plugins/db.d.cts +46 -16
- package/dist/plugins/db.d.mts +46 -16
- package/dist/plugins/db.mjs +30 -15
- package/dist/plugins/db.mjs.map +1 -1
- package/dist/plugins/http/attrs.cjs +46 -65
- package/dist/plugins/http/attrs.cjs.map +1 -1
- package/dist/plugins/http/attrs.d.cts +26 -11
- package/dist/plugins/http/attrs.d.mts +26 -11
- package/dist/plugins/http/attrs.mjs +43 -67
- package/dist/plugins/http/attrs.mjs.map +1 -1
- package/dist/plugins/http/cookie.d.cts +592 -53
- package/dist/plugins/http/cookie.d.mts +592 -53
- package/dist/plugins/http/error.cjs +47 -3
- package/dist/plugins/http/error.cjs.map +1 -1
- package/dist/plugins/http/error.d.cts +42 -9
- package/dist/plugins/http/error.d.mts +42 -9
- package/dist/plugins/http/error.mjs +48 -5
- package/dist/plugins/http/error.mjs.map +1 -1
- package/dist/plugins/http/handle.cjs +26 -9
- package/dist/plugins/http/handle.cjs.map +1 -1
- package/dist/plugins/http/handle.d.cts +915 -107
- package/dist/plugins/http/handle.d.mts +915 -107
- package/dist/plugins/http/handle.mjs +26 -9
- package/dist/plugins/http/handle.mjs.map +1 -1
- package/dist/plugins/http/redirect.d.cts +31 -5
- package/dist/plugins/http/redirect.d.mts +31 -5
- package/dist/plugins/http/request.d.cts +123 -7
- package/dist/plugins/http/request.d.mts +123 -7
- package/dist/plugins/http.cjs +12 -0
- package/dist/plugins/http.cjs.map +1 -1
- package/dist/plugins/http.d.cts +921 -109
- package/dist/plugins/http.d.mts +921 -109
- package/dist/plugins/http.mjs +9 -3
- package/dist/plugins/http.mjs.map +1 -1
- package/dist/schema.cjs +368 -67
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +51 -8
- package/dist/schema.d.mts +51 -8
- package/dist/schema.mjs +365 -68
- package/dist/schema.mjs.map +1 -1
- package/dist/scope.d.cts +1 -1
- package/dist/scope.d.mts +1 -1
- package/dist/storage.cjs +53 -1
- package/dist/storage.cjs.map +1 -1
- package/dist/storage.d.cts +23 -12
- package/dist/storage.d.mts +23 -12
- package/dist/storage.mjs +55 -2
- package/dist/storage.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -109,7 +109,21 @@ What this buys, all Effect-inspired but with plain functions:
|
|
|
109
109
|
- **Failure vs defect.** A thrown `c.error(...)` is a `FnError` - a domain outcome, tagged, serializable (`{ tag, data, trail }` survives a wire). Once a fn declares `errors`, any *untagged* throw escaping its body is a bug and comes out as `UnexpectedError` with the original on `cause`. Callers never string-match to tell the two apart.
|
|
110
110
|
- **Typed recovery.** `fn.try(input)` returns `{ ok: true, value } | { ok: false, error }` where `error` is the union of declared errors - TS narrows on `error.tag`. Defects and contract violations still throw. `FnErrors<typeof fn>` gives the union for catch sites.
|
|
111
111
|
- **The trail.** As an error crosses fn frames it collects their keys - `["audit.log", "profile.update", "capability.exec"]` - origin first, so nothing about where a failure started is ever lost.
|
|
112
|
-
- **All issues, not the first.** Validation collects every bad field / tuple position in one `ValidationError.issues` list.
|
|
112
|
+
- **All issues, not the first.** Validation collects every bad field / tuple position in one `ValidationError.issues` list. Paths name the contract door (`sign_in.email.input.email`), and each issue can carry a `received` preview:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
// sign_in.email.input.email: expected an email address, received "nope"
|
|
116
|
+
// sign_in.email.input.password: expected string, received number (1)
|
|
117
|
+
err.issues;
|
|
118
|
+
// [
|
|
119
|
+
// { path: "sign_in.email.input.email", message: "expected an email address, received \"nope\"", received: "\"nope\"" },
|
|
120
|
+
// { path: "sign_in.email.input.password", message: "expected string, received number (1)", received: "1" },
|
|
121
|
+
// ]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
At the HTTP edge (`createHandler` / `handler`), `ValidationError` becomes `400` with that JSON body, `FnError` uses `http.err` status (or `422`), and `UnexpectedError` becomes `500`.
|
|
125
|
+
|
|
126
|
+
Validation stacks point at the call site: a bad `signUpEmail({ email: "nope" })` shows that line, not schema internals. `FnError` / `UnexpectedError` scrub the same way - declared failures point at `c.error(...)`, defects keep the original on `cause`.
|
|
113
127
|
|
|
114
128
|
### vars
|
|
115
129
|
|
package/dist/capability.cjs
CHANGED
|
@@ -307,7 +307,7 @@ const serve = async (modules, authority) => {
|
|
|
307
307
|
};
|
|
308
308
|
}
|
|
309
309
|
const inputSchema = target.$schema?.input;
|
|
310
|
-
if (inputSchema !== void 0) require_attrs.rejectServerOnly(inputSchema, c.input.input, c.input.call);
|
|
310
|
+
if (inputSchema !== void 0) await require_attrs.rejectServerOnly(inputSchema, c.input.input, c.input.call);
|
|
311
311
|
return target(c.input.input, c);
|
|
312
312
|
});
|
|
313
313
|
/** The user's side of a challenge - the demo calls it directly; a real
|
package/dist/capability.cjs.map
CHANGED
|
@@ -1 +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 | null;\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 | null;\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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"}
|
|
1
|
+
{"version":3,"file":"capability.cjs","names":["v","collectFns","rejectServerOnly"],"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 | null;\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 | null;\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.readonly / serverOnly fields before the\n\t\t\t// target validates (object validate would otherwise strip them\n\t\t\t// quietly).\n\t\t\tconst inputSchema = (target as FnDefination<any, any>).$schema?.input;\n\t\t\tif (inputSchema !== undefined) {\n\t\t\t\tawait rejectServerOnly(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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"}
|
package/dist/capability.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TypeDefination } from "./schema.cjs";
|
|
2
2
|
import { OnEntry } from "./module.cjs";
|
|
3
|
-
import {
|
|
3
|
+
import { BoundCall, PublicFn } from "./fn.cjs";
|
|
4
4
|
import { VarDefination } from "./var.cjs";
|
|
5
5
|
//#region src/capability.d.ts
|
|
6
6
|
type Keypair = {
|
|
@@ -127,7 +127,7 @@ type Authority = {
|
|
|
127
127
|
* `c.capability`; `validateCaller` on every fn does the rest.
|
|
128
128
|
*/
|
|
129
129
|
declare const serve: (modules: Record<string, unknown>, authority: Authority) => Promise<{
|
|
130
|
-
exec:
|
|
130
|
+
exec: PublicFn<{
|
|
131
131
|
readonly call: string;
|
|
132
132
|
readonly input: unknown;
|
|
133
133
|
readonly token: unknown;
|
|
@@ -136,7 +136,7 @@ declare const serve: (modules: Record<string, unknown>, authority: Authority) =>
|
|
|
136
136
|
readonly input: TypeDefination<unknown, unknown, never>;
|
|
137
137
|
readonly token: TypeDefination<unknown, unknown, never>;
|
|
138
138
|
}, readonly [], {}, {
|
|
139
|
-
capability?:
|
|
139
|
+
capability?: {
|
|
140
140
|
subject: string;
|
|
141
141
|
caps: (string | {
|
|
142
142
|
fn: string;
|
|
@@ -146,13 +146,35 @@ declare const serve: (modules: Record<string, unknown>, authority: Authority) =>
|
|
|
146
146
|
})[];
|
|
147
147
|
holder: string;
|
|
148
148
|
entry: string | null;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
} | null | undefined;
|
|
150
|
+
}, unknown> & {
|
|
151
|
+
with(context: {
|
|
152
|
+
capability?: ({
|
|
153
|
+
subject: string;
|
|
154
|
+
caps: (string | {
|
|
155
|
+
fn: string;
|
|
156
|
+
input?: {
|
|
157
|
+
[x: string]: unknown;
|
|
158
|
+
} | undefined;
|
|
159
|
+
})[];
|
|
160
|
+
holder: string;
|
|
161
|
+
entry: string | null;
|
|
162
|
+
} & {
|
|
163
|
+
subject: string;
|
|
164
|
+
caps: Cap[];
|
|
165
|
+
holder: string;
|
|
166
|
+
entry: string | null;
|
|
167
|
+
}) | null | undefined;
|
|
168
|
+
}): BoundCall<{
|
|
169
|
+
readonly call: string;
|
|
170
|
+
readonly input: unknown;
|
|
171
|
+
readonly token: unknown;
|
|
172
|
+
}, Promise<unknown>, {
|
|
173
|
+
readonly call: TypeDefination<string, string, never>;
|
|
174
|
+
readonly input: TypeDefination<unknown, unknown, never>;
|
|
175
|
+
readonly token: TypeDefination<unknown, unknown, never>;
|
|
176
|
+
}, {}>;
|
|
177
|
+
};
|
|
156
178
|
decide: (id: string, approve: boolean) => Challenge | undefined;
|
|
157
179
|
challenges: Map<string, Challenge>;
|
|
158
180
|
key: string;
|
package/dist/capability.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TypeDefination } from "./schema.mjs";
|
|
2
2
|
import { OnEntry } from "./module.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { BoundCall, PublicFn } from "./fn.mjs";
|
|
4
4
|
import { VarDefination } from "./var.mjs";
|
|
5
5
|
//#region src/capability.d.ts
|
|
6
6
|
type Keypair = {
|
|
@@ -127,7 +127,7 @@ type Authority = {
|
|
|
127
127
|
* `c.capability`; `validateCaller` on every fn does the rest.
|
|
128
128
|
*/
|
|
129
129
|
declare const serve: (modules: Record<string, unknown>, authority: Authority) => Promise<{
|
|
130
|
-
exec:
|
|
130
|
+
exec: PublicFn<{
|
|
131
131
|
readonly call: string;
|
|
132
132
|
readonly input: unknown;
|
|
133
133
|
readonly token: unknown;
|
|
@@ -136,7 +136,7 @@ declare const serve: (modules: Record<string, unknown>, authority: Authority) =>
|
|
|
136
136
|
readonly input: TypeDefination<unknown, unknown, never>;
|
|
137
137
|
readonly token: TypeDefination<unknown, unknown, never>;
|
|
138
138
|
}, readonly [], {}, {
|
|
139
|
-
capability?:
|
|
139
|
+
capability?: {
|
|
140
140
|
subject: string;
|
|
141
141
|
caps: (string | {
|
|
142
142
|
fn: string;
|
|
@@ -146,13 +146,35 @@ declare const serve: (modules: Record<string, unknown>, authority: Authority) =>
|
|
|
146
146
|
})[];
|
|
147
147
|
holder: string;
|
|
148
148
|
entry: string | null;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
} | null | undefined;
|
|
150
|
+
}, unknown> & {
|
|
151
|
+
with(context: {
|
|
152
|
+
capability?: ({
|
|
153
|
+
subject: string;
|
|
154
|
+
caps: (string | {
|
|
155
|
+
fn: string;
|
|
156
|
+
input?: {
|
|
157
|
+
[x: string]: unknown;
|
|
158
|
+
} | undefined;
|
|
159
|
+
})[];
|
|
160
|
+
holder: string;
|
|
161
|
+
entry: string | null;
|
|
162
|
+
} & {
|
|
163
|
+
subject: string;
|
|
164
|
+
caps: Cap[];
|
|
165
|
+
holder: string;
|
|
166
|
+
entry: string | null;
|
|
167
|
+
}) | null | undefined;
|
|
168
|
+
}): BoundCall<{
|
|
169
|
+
readonly call: string;
|
|
170
|
+
readonly input: unknown;
|
|
171
|
+
readonly token: unknown;
|
|
172
|
+
}, Promise<unknown>, {
|
|
173
|
+
readonly call: TypeDefination<string, string, never>;
|
|
174
|
+
readonly input: TypeDefination<unknown, unknown, never>;
|
|
175
|
+
readonly token: TypeDefination<unknown, unknown, never>;
|
|
176
|
+
}, {}>;
|
|
177
|
+
};
|
|
156
178
|
decide: (id: string, approve: boolean) => Challenge | undefined;
|
|
157
179
|
challenges: Map<string, Challenge>;
|
|
158
180
|
key: string;
|
package/dist/capability.mjs
CHANGED
|
@@ -306,7 +306,7 @@ const serve = async (modules, authority) => {
|
|
|
306
306
|
};
|
|
307
307
|
}
|
|
308
308
|
const inputSchema = target.$schema?.input;
|
|
309
|
-
if (inputSchema !== void 0) rejectServerOnly(inputSchema, c.input.input, c.input.call);
|
|
309
|
+
if (inputSchema !== void 0) await rejectServerOnly(inputSchema, c.input.input, c.input.call);
|
|
310
310
|
return target(c.input.input, c);
|
|
311
311
|
});
|
|
312
312
|
/** The user's side of a challenge - the demo calls it directly; a real
|
package/dist/capability.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability.mjs","names":[],"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 | null;\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 | null;\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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"}
|
|
1
|
+
{"version":3,"file":"capability.mjs","names":[],"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 | null;\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 | null;\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.readonly / serverOnly fields before the\n\t\t\t// target validates (object validate would otherwise strip them\n\t\t\t// quietly).\n\t\t\tconst inputSchema = (target as FnDefination<any, any>).$schema?.input;\n\t\t\tif (inputSchema !== undefined) {\n\t\t\t\tawait rejectServerOnly(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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"}
|