@cotal-ai/auth 0.0.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +202 -0
  2. package/dist/callout.d.ts +108 -0
  3. package/dist/callout.d.ts.map +1 -0
  4. package/dist/callout.js +219 -0
  5. package/dist/callout.js.map +1 -0
  6. package/dist/commands.d.ts +2 -0
  7. package/dist/commands.d.ts.map +1 -0
  8. package/dist/commands.js +359 -0
  9. package/dist/commands.js.map +1 -0
  10. package/dist/derive.d.ts +15 -0
  11. package/dist/derive.d.ts.map +1 -0
  12. package/dist/derive.js +72 -0
  13. package/dist/derive.js.map +1 -0
  14. package/dist/idp.d.ts +63 -0
  15. package/dist/idp.d.ts.map +1 -0
  16. package/dist/idp.js +125 -0
  17. package/dist/idp.js.map +1 -0
  18. package/dist/index.d.ts +13 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +13 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/issuer.d.ts +78 -0
  23. package/dist/issuer.d.ts.map +1 -0
  24. package/dist/issuer.js +137 -0
  25. package/dist/issuer.js.map +1 -0
  26. package/dist/ledger.d.ts +108 -0
  27. package/dist/ledger.d.ts.map +1 -0
  28. package/dist/ledger.js +399 -0
  29. package/dist/ledger.js.map +1 -0
  30. package/dist/login.d.ts +69 -0
  31. package/dist/login.d.ts.map +1 -0
  32. package/dist/login.js +338 -0
  33. package/dist/login.js.map +1 -0
  34. package/dist/permissions.d.ts +28 -0
  35. package/dist/permissions.d.ts.map +1 -0
  36. package/dist/permissions.js +50 -0
  37. package/dist/permissions.js.map +1 -0
  38. package/dist/provider.d.ts +18 -0
  39. package/dist/provider.d.ts.map +1 -0
  40. package/dist/provider.js +213 -0
  41. package/dist/provider.js.map +1 -0
  42. package/dist/service.d.ts +10 -0
  43. package/dist/service.d.ts.map +1 -0
  44. package/dist/service.js +288 -0
  45. package/dist/service.js.map +1 -0
  46. package/dist/store.d.ts +82 -0
  47. package/dist/store.d.ts.map +1 -0
  48. package/dist/store.js +208 -0
  49. package/dist/store.js.map +1 -0
  50. package/dist/token.d.ts +68 -0
  51. package/dist/token.d.ts.map +1 -0
  52. package/dist/token.js +128 -0
  53. package/dist/token.js.map +1 -0
  54. package/package.json +35 -5
  55. package/README.md +0 -4
package/dist/idp.js ADDED
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Plane-1 IdP bridge — the token exchange that turns an EXTERNAL IdP-authenticated human into a
3
+ * Cotal user bearer (the plan's §"Plane 1"): verify the IdP's JWT offline against its pinned JWKS,
4
+ * derive the opaque per-space owner from the IdP subject, authorize the requested actor against
5
+ * the operator's ledger, and mint the bearer through the {@link UserTokenIssuer}.
6
+ *
7
+ * The bridge is IdP-GENERIC on purpose (pluggable edges): any IdP that publishes an EdDSA/Ed25519
8
+ * JWKS and mints `iss`/`aud`/`sub`/`exp` JWTs plugs in via {@link IdpConfig} — Better Auth (JWT
9
+ * plugin) is the reference IdP, and the integration smoke runs a real instance. Nothing
10
+ * Better-Auth-specific leaks in here.
11
+ *
12
+ * Trust-boundary order inside {@link IdpBridge.exchange} (each step fail-loud, no fallback):
13
+ * 1. the requested actor is grammar-asserted BEFORE anything else touches it;
14
+ * 2. the IdP token verifies against the PINNED key path only — `alg` pinned to EdDSA, embedded
15
+ * key material (`jku`/`jwk`/`x5u`/`x5c`) rejected outright, exact `iss`/`aud`, `exp` and a
16
+ * non-post-dated `iat` required, `sub` a non-empty string (no coercion);
17
+ * 3. the owner derives from the JSON-array encoding of [idp issuer, sub] — issuer-namespaced so
18
+ * the same `sub` from two IdPs can never collide, INJECTIVE by construction (JSON escaping —
19
+ * no delimiter an issuer/sub pair could straddle), and deterministic so re-login re-lands in
20
+ * the same lanes. This encoding is FROZEN: changing it (or the IdP issuer string) re-keys
21
+ * every owner in the space — a migration, like rotating the space secret;
22
+ * 4. the ledger hook AUTHORIZES (owner, actor) and is the ONLY source of `scope`/`parent` — the
23
+ * request cannot carry them (server-authored `act`, no confused deputy). The hook must return
24
+ * an explicit grant object; anything else is a deny;
25
+ * 5. the issuer mints (which re-asserts every claim shape — the issuer ↔ validator inverse).
26
+ */
27
+ import { decodeJwt, decodeProtectedHeader, jwtVerify } from "jose";
28
+ import { assertValidOwnerToken } from "@cotal-ai/core";
29
+ import { deriveOwnerForIdpSubject } from "./derive.js";
30
+ import { MAX_TOKEN_TTL_SEC, USER_TOKEN_VIEWS, VIEW_REQUIRED_SCOPE } from "./token.js";
31
+ /** Verify an external IdP JWT against the pinned config and return its `sub` AND `exp`. Same pinning
32
+ * posture as `validateUserToken`, minus the Cotal claim shape (an IdP token has no `ver`/`act`; its
33
+ * lifetime is the IdP's session policy — but it must expire and must not be post-dated). The `exp` is
34
+ * returned so `exchange` can CAP the minted Cotal bearer to the upstream proof's remaining life. */
35
+ async function verifyIdpToken(token, idp) {
36
+ const header = decodeProtectedHeader(token);
37
+ if (header.jku !== undefined || header.jwk !== undefined || header.x5u !== undefined || header.x5c !== undefined)
38
+ throw new Error("idp token: embedded key material (jku/jwk/x5u/x5c) is rejected - keys resolve only via the pinned JWKS");
39
+ if (header.alg !== "EdDSA")
40
+ throw new Error(`idp token: alg must be EdDSA (got ${String(header.alg)})`);
41
+ const tol = idp.clockToleranceSec ?? 5;
42
+ const { payload } = await jwtVerify(token, idp.key, {
43
+ algorithms: ["EdDSA"],
44
+ issuer: idp.issuer,
45
+ audience: idp.audience,
46
+ clockTolerance: tol,
47
+ });
48
+ // jose's `audience` option is SET-MEMBERSHIP (an aud array containing the expected value
49
+ // passes) — exact means the token's audience set is exactly {configured}: the plain string, or
50
+ // a singleton array of it. A multi-audience session proof minted for other services too must
51
+ // not be exchangeable here.
52
+ if (payload.aud !== idp.audience && !(Array.isArray(payload.aud) && payload.aud.length === 1 && payload.aud[0] === idp.audience))
53
+ throw new Error("idp token: aud must be exactly the configured audience - a multi-audience session proof is rejected");
54
+ if (typeof payload.exp !== "number")
55
+ throw new Error("idp token: exp is required - an IdP session proof must expire");
56
+ if (typeof payload.iat !== "number")
57
+ throw new Error("idp token: iat is required");
58
+ if (payload.iat > Math.floor(Date.now() / 1000) + tol)
59
+ throw new Error("idp token: iat is in the future");
60
+ if (typeof payload.sub !== "string" || !payload.sub)
61
+ throw new Error("idp token: sub must be a non-empty string user id - no coercion at a trust boundary");
62
+ return { sub: payload.sub, exp: payload.exp };
63
+ }
64
+ /** Build an {@link IdpBridge}. Misconfig fails HERE, at construction — an empty pin would
65
+ * otherwise fail closed on every exchange with a far worse operator signal. */
66
+ export function createIdpBridge(opts) {
67
+ if (!opts.space)
68
+ throw new Error("idp bridge: a space is required");
69
+ if (typeof opts.idp?.issuer !== "string" || !opts.idp.issuer)
70
+ throw new Error("idp bridge: idp.issuer (the exact iss pin) is required");
71
+ if (typeof opts.idp.audience !== "string" || !opts.idp.audience)
72
+ throw new Error("idp bridge: idp.audience (the exact aud pin) is required");
73
+ if (!opts.idp.key)
74
+ throw new Error("idp bridge: idp.key (the pinned JWKS resolver / public key) is required");
75
+ if (typeof opts.authorizeActor !== "function")
76
+ throw new Error("idp bridge: an authorizeActor ledger hook is required - there is no allow-by-default");
77
+ return {
78
+ exchange: async (idpToken, req) => {
79
+ assertValidOwnerToken(req.actor);
80
+ const { sub, exp: idpExp } = await verifyIdpToken(idpToken, opts.idp);
81
+ // The (issuer, sub) → derivation-input encoding lives in ONE place (deriveOwnerForIdpSubject),
82
+ // shared with the operator grant command — the ledger's grant-time owner and the exchange-time
83
+ // owner must be the same bytes or every grant silently misses.
84
+ const owner = deriveOwnerForIdpSubject(opts.spaceSecret, opts.idp.issuer, sub);
85
+ const grant = await opts.authorizeActor(owner, req.actor);
86
+ if (grant === null || typeof grant !== "object" || Array.isArray(grant))
87
+ throw new Error("idp bridge: authorizeActor must return a grant object - anything else is a deny");
88
+ if (req.view !== undefined) {
89
+ // An elevated view is authorized against the FRESH grant just read, per the central
90
+ // policy table (admin-gated operator views; spawn-gated deployer). The refusal names the
91
+ // exact re-grant (ADD to the current list — the upsert replaces it), mirroring the
92
+ // control-op copy.
93
+ if (!USER_TOKEN_VIEWS.includes(req.view))
94
+ throw new Error(`view "${String(req.view)}" is not a known view (${USER_TOKEN_VIEWS.join(", ")})`);
95
+ const need = VIEW_REQUIRED_SCOPE[req.view];
96
+ if (!(grant.scope ?? []).includes(need))
97
+ throw new Error(`the "${req.view}" view needs scope "${need}", which your grant lacks. Ask the mesh operator to re-grant with "${need}" ADDED to your current scope: ` +
98
+ `cotal actor grant ${req.actor} --owner ${owner} --scope ${[...(grant.scope ?? []), need].join(",")} (the upsert replaces the scope list; the operator can confirm with \`cotal actor list\`)`);
99
+ }
100
+ // Cap the minted bearer's lifetime to the IdP proof's REMAINING life: the Cotal bearer must not
101
+ // outlive the session proof it rests on. Otherwise a near-expired (or stolen just-before-expiry)
102
+ // IdP JWT would exchange for a full MAX_TOKEN_TTL_SEC bearer, widening authority past the upstream
103
+ // proof and defeating the "revocation bites when the IdP session lapses" model. An already-lapsed
104
+ // proof cannot mint anything (fail-loud).
105
+ const idpRemaining = idpExp - Math.floor(Date.now() / 1000);
106
+ if (idpRemaining <= 0)
107
+ throw new Error("idp bridge: the IdP session proof has expired - cannot mint a bearer");
108
+ const ttlSec = Math.min(req.ttlSec ?? MAX_TOKEN_TTL_SEC, idpRemaining);
109
+ const token = await opts.issuer.issue({
110
+ owner,
111
+ space: opts.space,
112
+ actor: req.actor,
113
+ scope: grant.scope,
114
+ parent: grant.parent,
115
+ view: req.view,
116
+ ttlSec,
117
+ });
118
+ const { exp } = decodeJwt(token);
119
+ if (typeof exp !== "number")
120
+ throw new Error("idp bridge: minted bearer is missing exp - issuer contract violated");
121
+ return { token, owner, exp };
122
+ },
123
+ };
124
+ }
125
+ //# sourceMappingURL=idp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idp.js","sourceRoot":"","sources":["../src/idp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export { deriveOwnerToken, deriveOwnerForIdpSubject } from "./derive.js";
2
+ export { AUTH_CALLOUT_SUBJECT, createCalloutAuth, startAuthCallout, type CalloutAuth, type CalloutProvisionInput, type CalloutConnection, type CalloutMsg, type StartAuthCalloutOpts, } from "./callout.js";
3
+ export { validateUserToken, USER_TOKEN_VER, MAX_TOKEN_TTL_SEC, USER_TOKEN_VIEWS, VIEW_REQUIRED_SCOPE, type UserTokenActor, type UserTokenView, type ValidatedUserToken, type ValidateUserTokenOpts, } from "./token.js";
4
+ export { USER_TOKEN_ALG, createUserTokenIssuer, generateSigningKey, exportSigningKey, importSigningKey, pinnedJwksResolver, type SigningKey, type SerializedSigningKey, type IssueClaims, type UserTokenIssuer, type CreateIssuerOpts, } from "./issuer.js";
5
+ export { createIdpBridge, type IdpConfig, type ActorGrant, type CreateIdpBridgeOpts, type ExchangeResult, type IdpBridge, } from "./idp.js";
6
+ export { deviceLogin, establishIdpSession, fetchIdpJwt, revokeIdpSession, loadIdpSession, saveIdpSession, deleteIdpSession, requireIdpSession, normalizeIdpUrl, probeIdpJwks, type IdpSession, type DeviceLoginOpts, type DeviceLoginPrompt, } from "./login.js";
7
+ export { calloutPermissions, type AclResolver } from "./permissions.js";
8
+ export { clearAuthServiceInfo, ensureCalloutAuth, ensureIssuer, ensureOwnerSecret, ensurePinnedIdp, loadAuthServiceInfo, loadCalloutAuth, loadIssuer, loadOwnerSecret, loadPinnedIdp, loadServiceKeys, saveAuthServiceInfo, saveServiceKeys, spaceIssuer, type AuthServiceInfo, type PinnedIdp, type ServiceKeys, } from "./store.js";
9
+ export { actorLedgerDir, managedActorLedgerDir, findInteractiveActor, findManagedActor, findActorUnified, grantActor, grantManagedActor, ledgerAclResolver, ledgerAuthorizeConnect, ledgerAuthorizeGrant, ledgerAuthorizeAgentExchange, ledgerRowFilename, loadActorLedger, revokeActor, revokeManagedActor, newActorToken, hashActorToken, AGENT_BEARER_TTL_SEC, type ActorKind, type ActorRow, } from "./ledger.js";
10
+ export { runAuthService, JWKS_MAX_AGE_SEC } from "./service.js";
11
+ export { cotalAuthProvider } from "./provider.js";
12
+ import "./commands.js";
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,oBAAoB,GAC1B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,oBAAoB,EACzB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,SAAS,GACf,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,eAAe,EACf,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,4BAA4B,EAC5B,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,KAAK,SAAS,EACd,KAAK,QAAQ,GACd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ export { deriveOwnerToken, deriveOwnerForIdpSubject } from "./derive.js";
2
+ export { AUTH_CALLOUT_SUBJECT, createCalloutAuth, startAuthCallout, } from "./callout.js";
3
+ export { validateUserToken, USER_TOKEN_VER, MAX_TOKEN_TTL_SEC, USER_TOKEN_VIEWS, VIEW_REQUIRED_SCOPE, } from "./token.js";
4
+ export { USER_TOKEN_ALG, createUserTokenIssuer, generateSigningKey, exportSigningKey, importSigningKey, pinnedJwksResolver, } from "./issuer.js";
5
+ export { createIdpBridge, } from "./idp.js";
6
+ export { deviceLogin, establishIdpSession, fetchIdpJwt, revokeIdpSession, loadIdpSession, saveIdpSession, deleteIdpSession, requireIdpSession, normalizeIdpUrl, probeIdpJwks, } from "./login.js";
7
+ export { calloutPermissions } from "./permissions.js";
8
+ export { clearAuthServiceInfo, ensureCalloutAuth, ensureIssuer, ensureOwnerSecret, ensurePinnedIdp, loadAuthServiceInfo, loadCalloutAuth, loadIssuer, loadOwnerSecret, loadPinnedIdp, loadServiceKeys, saveAuthServiceInfo, saveServiceKeys, spaceIssuer, } from "./store.js";
9
+ export { actorLedgerDir, managedActorLedgerDir, findInteractiveActor, findManagedActor, findActorUnified, grantActor, grantManagedActor, ledgerAclResolver, ledgerAuthorizeConnect, ledgerAuthorizeGrant, ledgerAuthorizeAgentExchange, ledgerRowFilename, loadActorLedger, revokeActor, revokeManagedActor, newActorToken, hashActorToken, AGENT_BEARER_TTL_SEC, } from "./ledger.js";
10
+ export { runAuthService, JWKS_MAX_AGE_SEC } from "./service.js";
11
+ export { cotalAuthProvider } from "./provider.js"; // self-registers the "auth-provider" extension
12
+ import "./commands.js"; // self-registers `login` / `logout` / `actor` / `auth-service` into the core Registry
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,GAMjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,GAKpB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,GAMnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,GAMhB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,YAAY,GAIb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAoB,MAAM,kBAAkB,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,eAAe,EACf,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,WAAW,GAIZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,4BAA4B,EAC5B,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,oBAAoB,GAGrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC,CAAC,+CAA+C;AAClG,OAAO,eAAe,CAAC,CAAC,sFAAsF"}
@@ -0,0 +1,78 @@
1
+ import type { CryptoKey, JWK, JWTVerifyGetKey } from "jose";
2
+ import { type UserTokenView } from "./token.js";
3
+ /** The one signing algorithm — Ed25519. Pinned on both mint and verify. */
4
+ export declare const USER_TOKEN_ALG = "EdDSA";
5
+ /** An active signing key: the private `CryptoKey` for minting + its published public JWK. The `kid`
6
+ * is the RFC 7638 thumbprint of the public key (stable, collision-free, verifier-recomputable). */
7
+ export interface SigningKey {
8
+ kid: string;
9
+ privateKey: CryptoKey;
10
+ /** Public JWK as published in the set (carries `kid`/`alg`/`use`; never `d`). */
11
+ publicJwk: JWK;
12
+ }
13
+ /** A signing key serialized for persistence — the PRIVATE JWK (with `d`) plus its kid. Guard this at
14
+ * rest like any signing secret; `importSigningKey` restores it (kid integrity re-checked). */
15
+ export interface SerializedSigningKey {
16
+ kid: string;
17
+ privateJwk: JWK;
18
+ }
19
+ /** Mint a fresh Ed25519 signing key (extractable, so it can be persisted with {@link exportSigningKey}). */
20
+ export declare function generateSigningKey(): Promise<SigningKey>;
21
+ /** Serialize a signing key (private JWK + kid) for persistence. */
22
+ export declare function exportSigningKey(key: SigningKey): Promise<SerializedSigningKey>;
23
+ /** Restore a persisted signing key; re-derives the kid from the public projection and refuses a
24
+ * serialized blob whose stored kid doesn't match (tamper / corruption fail-loud). */
25
+ export declare function importSigningKey(s: SerializedSigningKey): Promise<SigningKey>;
26
+ /** The claims a caller supplies to mint a bearer — the owner is already derived and the actor is
27
+ * already ledger-authorized upstream; the issuer only stamps and signs. */
28
+ export interface IssueClaims {
29
+ /** The opaque derived owner (`u_…`; format-asserted). */
30
+ owner: string;
31
+ /** The space the bearer is scoped to (becomes `aud`). */
32
+ space: string;
33
+ /** The ledger-authorized agent-instance id (becomes `act.actor`; grammar-asserted). */
34
+ actor: string;
35
+ /** Capability scope. */
36
+ scope?: string[];
37
+ /** At most one spawner audit link, `<owner>.<actor>` dot-form. */
38
+ parent?: string;
39
+ /** Exchange-authorized elevated view (already ledger-checked upstream; the issuer only stamps —
40
+ * and re-asserts the closed enum, mint ↔ validate inverse). */
41
+ view?: UserTokenView;
42
+ /** Requested lifetime; capped at {@link MAX_TOKEN_TTL_SEC} (an overlong ask THROWS). */
43
+ ttlSec?: number;
44
+ }
45
+ /** A running issuer: mints bearers with the active key, publishes the public JWKS, and rotates. */
46
+ export interface UserTokenIssuer {
47
+ /** The `iss` every bearer carries (verifiers pin this). */
48
+ readonly issuer: string;
49
+ /** The active signing kid. */
50
+ activeKid(): string;
51
+ /** Mint a bearer for a validated (owner, actor). Returns the compact JWS. */
52
+ issue(claims: IssueClaims): Promise<string>;
53
+ /** The public JWK Set to publish for offline verification (all live kids, public members only). */
54
+ jwks(): {
55
+ keys: JWK[];
56
+ };
57
+ /** Add a key and make it the active signer; prior keys stay published until {@link retire}. */
58
+ rotate(key: SigningKey): void;
59
+ /** Drop a retired kid from the set — after that, tokens it signed no longer verify. */
60
+ retire(kid: string): void;
61
+ /** A verifier over the CURRENT key set (reflects rotate/retire live) — for a co-located callout
62
+ * or tests. Same `JWTVerifyGetKey` shape {@link validateUserToken} accepts. */
63
+ localKeySet(): JWTVerifyGetKey;
64
+ }
65
+ export interface CreateIssuerOpts {
66
+ /** Exact issuer string minted into `iss` (verifiers pin it). */
67
+ issuer: string;
68
+ /** The initial (active) signing key. */
69
+ key: SigningKey;
70
+ }
71
+ /** Build a {@link UserTokenIssuer}. */
72
+ export declare function createUserTokenIssuer(opts: CreateIssuerOpts): UserTokenIssuer;
73
+ /** Build the callout's pinned key resolver: a `createRemoteJWKSet` locked to ONE origin. The token
74
+ * never influences where the key comes from — jose fetches only this URL and ignores any embedded
75
+ * `jku`/`jwk` (and {@link validateUserToken} rejects those headers outright). HTTPS is required
76
+ * except for loopback (dev). */
77
+ export declare function pinnedJwksResolver(jwksUri: string): JWTVerifyGetKey;
78
+ //# sourceMappingURL=issuer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issuer.d.ts","sourceRoot":"","sources":["../src/issuer.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAE5D,OAAO,EAAuD,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAErG,2EAA2E;AAC3E,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;oGACoG;AACpG,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,SAAS,CAAC;IACtB,iFAAiF;IACjF,SAAS,EAAE,GAAG,CAAC;CAChB;AAED;+FAC+F;AAC/F,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,GAAG,CAAC;CACjB;AAeD,4GAA4G;AAC5G,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,UAAU,CAAC,CAG9D;AAED,mEAAmE;AACnE,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAErF;AAED;sFACsF;AACtF,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,UAAU,CAAC,CAKnF;AAED;4EAC4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;oEACgE;IAChE,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,mGAAmG;AACnG,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8BAA8B;IAC9B,SAAS,IAAI,MAAM,CAAC;IACpB,6EAA6E;IAC7E,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,mGAAmG;IACnG,IAAI,IAAI;QAAE,IAAI,EAAE,GAAG,EAAE,CAAA;KAAE,CAAC;IACxB,+FAA+F;IAC/F,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,uFAAuF;IACvF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;oFACgF;IAChF,WAAW,IAAI,eAAe,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,GAAG,EAAE,UAAU,CAAC;CACjB;AAED,uCAAuC;AACvC,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,GAAG,eAAe,CAgE7E;AAED;;;iCAGiC;AACjC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAMnE"}
package/dist/issuer.js ADDED
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Plane-1 user-bearer ISSUER — the server-side piece that turns an already-authenticated human
3
+ * (an owner) into the short-lived Cotal user bearer an agent presents to the callout (the plan's
4
+ * §"Plane 1"; the exact claim shape {@link validateUserToken} enforces on the other side).
5
+ *
6
+ * This is the production form of what the callout E2E smoke hand-rolls: an EdDSA (Ed25519) signer
7
+ * whose public keys are published as a JWKS the callout verifies against OFFLINE. It is deliberately
8
+ * NOT the Better-Auth binding (that's Plane-1's IdP adapter, a later slice) — an issuer takes an
9
+ * ALREADY-derived owner + a ledger-authorized actor and mints; deriving the owner and authorizing
10
+ * the actor happen upstream.
11
+ *
12
+ * Load-bearing properties:
13
+ * - `alg` is EdDSA only; every token carries a `kid` so verifiers pick the right key across rotation;
14
+ * - the minted claims are exactly {@link validateUserToken}'s reject matrix inverse — a token this
15
+ * issuer produces MUST validate, and the round-trip smoke pins that (issuer ↔ validator agree);
16
+ * - the lifetime is capped at {@link MAX_TOKEN_TTL_SEC} at MINT (fail loud on an overlong ask) — the
17
+ * validator caps on the read side too, but a mint that quietly exceeded the cap would be dead JWTs;
18
+ * - rotation is real: multiple keys live in the JWKS at once (sign with the newest, verify any
19
+ * still-published kid), and a retired kid stops verifying — that's the revocation seam for the
20
+ * signing key, distinct from the per-token exp lever.
21
+ *
22
+ * NOTHING here leaks private material: `jwks()` exports public JWKs only; the private key stays a
23
+ * `CryptoKey` in memory (or a persisted private JWK the operator controls).
24
+ */
25
+ import { SignJWT, calculateJwkThumbprint, createRemoteJWKSet, exportJWK, generateKeyPair, importJWK } from "jose";
26
+ import { assertDerivedOwnerToken, assertValidOwnerToken } from "@cotal-ai/core";
27
+ import { MAX_TOKEN_TTL_SEC, USER_TOKEN_VER, USER_TOKEN_VIEWS } from "./token.js";
28
+ /** The one signing algorithm — Ed25519. Pinned on both mint and verify. */
29
+ export const USER_TOKEN_ALG = "EdDSA";
30
+ function publicMembers(jwk) {
31
+ // OKP public projection — the members a verifier (and the thumbprint) needs; drop the private `d`.
32
+ if (jwk.kty !== "OKP" || jwk.crv !== "Ed25519" || typeof jwk.x !== "string")
33
+ throw new Error(`signing key must be an Ed25519 OKP JWK (got kty=${String(jwk.kty)} crv=${String(jwk.crv)})`);
34
+ return { kty: jwk.kty, crv: jwk.crv, x: jwk.x };
35
+ }
36
+ async function toSigningKey(privateKey, privateJwk) {
37
+ const pub = publicMembers(privateJwk);
38
+ const kid = await calculateJwkThumbprint(pub);
39
+ return { kid, privateKey, publicJwk: { ...pub, kid, alg: USER_TOKEN_ALG, use: "sig" } };
40
+ }
41
+ /** Mint a fresh Ed25519 signing key (extractable, so it can be persisted with {@link exportSigningKey}). */
42
+ export async function generateSigningKey() {
43
+ const { privateKey } = await generateKeyPair(USER_TOKEN_ALG, { extractable: true });
44
+ return toSigningKey(privateKey, await exportJWK(privateKey));
45
+ }
46
+ /** Serialize a signing key (private JWK + kid) for persistence. */
47
+ export async function exportSigningKey(key) {
48
+ return { kid: key.kid, privateJwk: await exportJWK(key.privateKey) };
49
+ }
50
+ /** Restore a persisted signing key; re-derives the kid from the public projection and refuses a
51
+ * serialized blob whose stored kid doesn't match (tamper / corruption fail-loud). */
52
+ export async function importSigningKey(s) {
53
+ const privateKey = (await importJWK(s.privateJwk, USER_TOKEN_ALG));
54
+ const key = await toSigningKey(privateKey, s.privateJwk);
55
+ if (key.kid !== s.kid)
56
+ throw new Error(`signing key kid mismatch: serialized ${s.kid} != recomputed ${key.kid}`);
57
+ return key;
58
+ }
59
+ /** Build a {@link UserTokenIssuer}. */
60
+ export function createUserTokenIssuer(opts) {
61
+ if (!opts.issuer)
62
+ throw new Error("issuer: an `iss` string is required");
63
+ const keys = new Map([[opts.key.kid, opts.key]]);
64
+ let active = opts.key.kid;
65
+ const issue = async (claims) => {
66
+ // Every claim is RUNTIME-shape-checked, not just TS-typed: C2 feeds this from IdP/session JSON,
67
+ // and a mis-shaped claim must fail HERE — signing it would mint a dead bearer the validator
68
+ // rejects, silently breaking the issuer ↔ validator inverse.
69
+ assertDerivedOwnerToken(claims.owner);
70
+ assertValidOwnerToken(claims.actor);
71
+ if (typeof claims.space !== "string" || !claims.space)
72
+ throw new Error("issue: space (aud) must be a non-empty string");
73
+ if (claims.scope !== undefined && !(Array.isArray(claims.scope) && claims.scope.every((s) => typeof s === "string")))
74
+ throw new Error("issue: scope must be a string list when present");
75
+ if (claims.parent !== undefined) {
76
+ if (typeof claims.parent !== "string")
77
+ throw new Error("issue: parent must be a string principal (<owner>.<actor>)");
78
+ const parts = claims.parent.split(".");
79
+ if (parts.length !== 2)
80
+ throw new Error(`issue: parent "${claims.parent}" is not a principal (<owner>.<actor>)`);
81
+ assertDerivedOwnerToken(parts[0]);
82
+ assertValidOwnerToken(parts[1]);
83
+ }
84
+ if (claims.view !== undefined && !USER_TOKEN_VIEWS.includes(claims.view))
85
+ throw new Error(`issue: view "${String(claims.view)}" is not a known view (${USER_TOKEN_VIEWS.join(", ")}) - the enum is closed on the mint side too`);
86
+ const ttl = claims.ttlSec ?? MAX_TOKEN_TTL_SEC;
87
+ if (typeof ttl !== "number" || !Number.isFinite(ttl) || !(ttl > 0) || ttl > MAX_TOKEN_TTL_SEC)
88
+ throw new Error(`issue: ttlSec ${ttl} out of range (0, ${MAX_TOKEN_TTL_SEC}] - the cap is the revocation lever`);
89
+ const signer = keys.get(active);
90
+ if (!signer)
91
+ throw new Error("issue: no active signing key");
92
+ const now = Math.floor(Date.now() / 1000);
93
+ return new SignJWT({
94
+ scope: claims.scope ?? [],
95
+ ver: USER_TOKEN_VER,
96
+ act: { owner: claims.owner, actor: claims.actor, ...(claims.scope ? { scope: claims.scope } : {}), ...(claims.parent ? { parent: claims.parent } : {}), ...(claims.view ? { view: claims.view } : {}) },
97
+ })
98
+ .setProtectedHeader({ alg: USER_TOKEN_ALG, kid: signer.kid })
99
+ .setSubject(claims.owner)
100
+ .setIssuer(opts.issuer)
101
+ .setAudience(claims.space)
102
+ .setIssuedAt(now)
103
+ .setNotBefore(now)
104
+ .setExpirationTime(now + ttl)
105
+ .sign(signer.privateKey);
106
+ };
107
+ return {
108
+ issuer: opts.issuer,
109
+ activeKid: () => active,
110
+ issue,
111
+ jwks: () => ({ keys: [...keys.values()].map((k) => k.publicJwk) }),
112
+ rotate: (key) => { keys.set(key.kid, key); active = key.kid; },
113
+ retire: (kid) => {
114
+ if (kid === active)
115
+ throw new Error(`issuer: refusing to retire the active kid ${kid} - rotate to a new key first`);
116
+ keys.delete(kid);
117
+ },
118
+ localKeySet: () => async (header) => {
119
+ const jwk = header.kid ? keys.get(header.kid)?.publicJwk : undefined;
120
+ if (!jwk)
121
+ throw new Error(`no published signing key for kid ${String(header.kid)}`);
122
+ return (await importJWK(jwk, USER_TOKEN_ALG));
123
+ },
124
+ };
125
+ }
126
+ /** Build the callout's pinned key resolver: a `createRemoteJWKSet` locked to ONE origin. The token
127
+ * never influences where the key comes from — jose fetches only this URL and ignores any embedded
128
+ * `jku`/`jwk` (and {@link validateUserToken} rejects those headers outright). HTTPS is required
129
+ * except for loopback (dev). */
130
+ export function pinnedJwksResolver(jwksUri) {
131
+ const url = new URL(jwksUri);
132
+ const loopback = url.hostname === "127.0.0.1" || url.hostname === "localhost" || url.hostname === "[::1]";
133
+ if (url.protocol !== "https:" && !loopback)
134
+ throw new Error(`JWKS origin must be https (or loopback for dev), got ${url.protocol}//${url.hostname}`);
135
+ return createRemoteJWKSet(url);
136
+ }
137
+ //# sourceMappingURL=issuer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issuer.js","sourceRoot":"","sources":["../src/issuer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,108 @@
1
+ import type { ActorGrant } from "./idp.js";
2
+ import type { ValidatedUserToken } from "./token.js";
3
+ import type { AclResolver } from "./permissions.js";
4
+ /** The two row spaces. The KIND is the directory — never a field a partial write could flip. */
5
+ export type ActorKind = "interactive" | "managed-agent";
6
+ /** One granted (owner, actor) row — everything the two trust boundaries mint from. */
7
+ export interface ActorRow {
8
+ /** The opaque derived owner (`u_…`) this actor belongs to. */
9
+ owner: string;
10
+ /** The agent-instance id under that owner. */
11
+ actor: string;
12
+ /** Capability scope the bearer carries (`act.scope`, e.g. `["spawn"]`). Explicit; default none. */
13
+ scope: string[];
14
+ /** Channel read ACL minted at connect. Explicit at grant time — the resolver invents no default. */
15
+ allowSubscribe: string[];
16
+ /** Channel post ACL minted at connect. Explicit at grant time (empty = cannot post anywhere). */
17
+ allowPublish: string[];
18
+ /** Role (scopes the TASK-queue consumer), when the actor serves one. */
19
+ role?: string;
20
+ /** The spawning principal (`<owner>.<actor>` dot-form) when the ledger records one (audit link). */
21
+ parent?: string;
22
+ /** Operator-chosen display label for `list` legibility (e.g. "david laptop"). NEVER the IdP
23
+ * subject/email — the ledger stays as non-PII as the wire. */
24
+ label?: string;
25
+ /** SHA-256 hex of the per-agent exchange secret. REQUIRED in a managed-agent row (its space's
26
+ * defining shape), REFUSED in an interactive row (readRow fails closed on either violation).
27
+ * The plaintext secret is returned ONCE at grant time and never persisted. */
28
+ tokenHash?: string;
29
+ /** ISO timestamp of the grant (audit). */
30
+ grantedAt: string;
31
+ }
32
+ /** Every granted row in BOTH spaces, read fresh, tagged with its kind. Missing dirs = EMPTY ledger
33
+ * (deny-all). A row that cannot be read throws (fail closed) rather than being silently omitted
34
+ * from an authorization listing. */
35
+ export declare function loadActorLedger(dir: string): Array<ActorRow & {
36
+ kind: ActorKind;
37
+ }>;
38
+ export declare function findInteractiveActor(dir: string, owner: string, actor: string): ActorRow | undefined;
39
+ export declare function findManagedActor(dir: string, owner: string, actor: string): ActorRow | undefined;
40
+ /** The CONNECT boundary's unified read — a bearer minted by EITHER exchange path authorizes here,
41
+ * so both spaces are consulted. A (owner, actor) present in BOTH is a broken ledger (the writers
42
+ * refuse it; only manual tampering produces it) and DENIES, fail-closed, naming both files. */
43
+ export declare function findActorUnified(dir: string, owner: string, actor: string): (ActorRow & {
44
+ kind: ActorKind;
45
+ }) | undefined;
46
+ /** Grant (or update — an upsert, so re-granting narrows/widens in place) an INTERACTIVE (owner,
47
+ * actor) row. Refuses a token hash (that's the managed space's shape, written only by the spawn
48
+ * path) and refuses to shadow an existing managed-agent row — the two spaces stay disjoint at the
49
+ * write, so the read sides never disambiguate.
50
+ *
51
+ * NOT attenuated by design: interactive rows are OPERATOR-authored (the local `cotal actor grant`
52
+ * CLI is the only writer), and the operator is the authority the envelope rule bottoms out in. An
53
+ * optional `parent` here is an audit link only — do not build a delegated-USER write path on this
54
+ * function; user-authored delegation belongs in the managed space, where the chain walk enforces
55
+ * the envelope (an interactive row that carries a parent still gets link-checked when a managed
56
+ * chain passes THROUGH it). */
57
+ export declare function grantActor(dir: string, row: Omit<ActorRow, "grantedAt">): ActorRow;
58
+ /** Author a MANAGED-AGENT row (spawn path only): the same upsert semantics, in the managed space,
59
+ * with the secret hash REQUIRED — and never shadowing an interactive row. */
60
+ export declare function grantManagedActor(dir: string, row: Omit<ActorRow, "grantedAt"> & {
61
+ tokenHash: string;
62
+ }): ActorRow;
63
+ /** Revoke a row in one space. Returns false when there was nothing to revoke. NOTE: this stops NEW
64
+ * bearer mints and NEW connects immediately (both boundaries read fresh); an ALREADY-LIVE
65
+ * connection dies at its bearer-bound JWT expiry — live eviction is the D5 lever, not the ledger's. */
66
+ export declare function revokeActor(dir: string, owner: string, actor: string): boolean;
67
+ export declare function revokeManagedActor(dir: string, owner: string, actor: string): boolean;
68
+ /** The IdP bridge's `authorizeActor` hook (bearer-MINT boundary) — INTERACTIVE rows only, by
69
+ * construction. A name that exists only as a managed agent gets the exact managed-path answer
70
+ * (never "not granted", which would read as a permissions problem, and never a mint). */
71
+ export declare function ledgerAuthorizeGrant(dir: string): (owner: string, actor: string) => ActorGrant;
72
+ /** The callout's `authorizeActor` hook (CONNECT boundary): the row must still exist — in EITHER
73
+ * space (bearers from both exchange paths connect here) — and the bearer's `act.scope` must sit
74
+ * within the row's CURRENT scope — a bearer minted before a scope narrowing is refused at
75
+ * connect, not honored until expiry. */
76
+ export declare function ledgerAuthorizeConnect(dir: string): (t: ValidatedUserToken) => void;
77
+ /** The channel-ACL resolver over this ledger — the ONE resolver both the callout permission
78
+ * supplier uses today and the IdP bridge shares when it needs channel authority (gate 4's "shared
79
+ * by both"). Serves bearers from both spaces (unified read). A missing row throws (the callout
80
+ * turns it into a signed deny). */
81
+ export declare function ledgerAclResolver(dir: string): AclResolver;
82
+ /** Ensure a filename-hostile owner/actor can never traverse (defense-in-depth behind the grammar
83
+ * asserts in {@link rowPath}) — exported for the smoke that pins the property. */
84
+ export declare function ledgerRowFilename(owner: string, actor: string): string;
85
+ /** Where the per-row files live under a provider state dir (for tooling/tests). */
86
+ export declare function actorLedgerDir(dir: string): string;
87
+ /** The managed-agent row space (for tooling/tests). */
88
+ export declare function managedActorLedgerDir(dir: string): string;
89
+ /** Agent bearers are SHORT by design — a spawned agent's endpoint re-exchanges ahead of every
90
+ * expiry, so revocation (row deletion) bites a live connection within this window even before
91
+ * live eviction lands. There is no upstream IdP proof to cap to; this constant is that cap. */
92
+ export declare const AGENT_BEARER_TTL_SEC = 300;
93
+ /** Generate a fresh per-agent exchange secret (returned to the spawner ONCE) + its ledger hash. */
94
+ export declare function newActorToken(): {
95
+ actorToken: string;
96
+ tokenHash: string;
97
+ };
98
+ export declare function hashActorToken(actorToken: string): string;
99
+ /** Authorize one AGENT exchange (`{ owner, actor, actorToken }`, no IdP proof) — MANAGED rows only,
100
+ * by construction. The presented secret must hash to the row's (constant-time over the two fixed
101
+ * 32-byte digests). Every failure is the SAME sentence — a prober must not learn whether an
102
+ * (owner, actor) row exists, lives in the other space, or got the secret wrong (the sentence
103
+ * still names the operator's likely fix: respawn). */
104
+ export declare function ledgerAuthorizeAgentExchange(dir: string, owner: string, actor: string, actorToken: string): {
105
+ scope: string[];
106
+ parent?: string;
107
+ };
108
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../src/ledger.ts"],"names":[],"mappings":"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"}