@tenuo/core 0.2.4-beta.0 → 0.3.0-beta.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 (53) hide show
  1. package/README.md +49 -5
  2. package/dist/api.d.ts +416 -17
  3. package/dist/api.js.map +1 -1
  4. package/dist/client.d.ts +59 -2
  5. package/dist/client.js +700 -70
  6. package/dist/client.js.map +1 -1
  7. package/dist/connect.d.ts +53 -0
  8. package/dist/connect.js +177 -0
  9. package/dist/connect.js.map +1 -0
  10. package/dist/constraints.d.ts +54 -3
  11. package/dist/constraints.js +154 -6
  12. package/dist/constraints.js.map +1 -1
  13. package/dist/errors.d.ts +8 -3
  14. package/dist/errors.js +10 -1
  15. package/dist/errors.js.map +1 -1
  16. package/dist/generated/tenuo_wasm.d.ts +136 -7
  17. package/dist/generated/tenuo_wasm.js +398 -9
  18. package/dist/generated/tenuo_wasm_bg.wasm +0 -0
  19. package/dist/generated/tenuo_wasm_bg.wasm.d.ts +40 -22
  20. package/dist/identity.d.ts +25 -0
  21. package/dist/identity.js +61 -0
  22. package/dist/identity.js.map +1 -0
  23. package/dist/index.d.ts +9 -3
  24. package/dist/index.js +5 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/mcp.d.ts +18 -3
  27. package/dist/mcp.js +67 -59
  28. package/dist/mcp.js.map +1 -1
  29. package/dist/nonce.d.ts +6 -1
  30. package/dist/nonce.js +12 -1
  31. package/dist/nonce.js.map +1 -1
  32. package/dist/receipts.d.ts +27 -0
  33. package/dist/receipts.js +128 -0
  34. package/dist/receipts.js.map +1 -0
  35. package/dist/runtime.d.ts +51 -0
  36. package/dist/runtime.js +102 -0
  37. package/dist/runtime.js.map +1 -0
  38. package/dist/session.d.ts +9 -2
  39. package/dist/session.js +56 -0
  40. package/dist/session.js.map +1 -1
  41. package/dist/wasm.d.ts +207 -5
  42. package/dist/wasm.js +62 -4
  43. package/dist/wasm.js.map +1 -1
  44. package/package.json +3 -2
  45. package/dist/api.d.ts.map +0 -1
  46. package/dist/client.d.ts.map +0 -1
  47. package/dist/constraints.d.ts.map +0 -1
  48. package/dist/errors.d.ts.map +0 -1
  49. package/dist/index.d.ts.map +0 -1
  50. package/dist/mcp.d.ts.map +0 -1
  51. package/dist/nonce.d.ts.map +0 -1
  52. package/dist/session.d.ts.map +0 -1
  53. package/dist/wasm.d.ts.map +0 -1
@@ -0,0 +1,51 @@
1
+ import type { PublicKeyHandle, Session, Tenuo, WarrantPart } from "./api.ts";
2
+ import type { HolderIdentity } from "./identity.ts";
3
+ export type ReceiptsMode = "collect" | "off";
4
+ export type RuntimeOptions = {
5
+ readonly identity: HolderIdentity;
6
+ readonly trustedRoots: readonly PublicKeyHandle[];
7
+ /** Published SignedRevocationList. Fetching it is the caller's job. */
8
+ readonly revocationList?: string | Uint8Array;
9
+ /**
10
+ * `collect` retains receipts produced through this runtime's sessions
11
+ * (tools, present, MCP attach) and through this runtime's tenuo
12
+ * (verify, MCP verify/handler) until `acknowledgeReceipts()`.
13
+ * `drainReceipts()` is a snapshot. Default `off`.
14
+ */
15
+ readonly receipts?: ReceiptsMode;
16
+ /** Bound on each receipt outbox. Default 10_000. */
17
+ readonly receiptMax?: number;
18
+ };
19
+ export type SessionWarrant = string | readonly string[] | readonly WarrantPart[];
20
+ /**
21
+ * Long-lived holder runtime. Owns identity, trusted roots, the current
22
+ * revocation list, and optional receipt collection. Does not perform
23
+ * network I/O or invent hosted-service defaults.
24
+ */
25
+ export declare class Runtime {
26
+ #private;
27
+ readonly identity: HolderIdentity;
28
+ readonly tenuo: Tenuo;
29
+ constructor(tenuo: Tenuo, identity: HolderIdentity, collect: boolean, max?: number);
30
+ applyRevocationList(list: string | Uint8Array): void;
31
+ sessionFromWire(warrant: SessionWarrant): Session;
32
+ /** Undrained receipts from every session and presented call handled by this runtime. */
33
+ peekReceipts(): string[];
34
+ /**
35
+ * Snapshot of receipts across holder sessions and presented-path
36
+ * verification. Same as `peekReceipts`; nothing is removed until
37
+ * `acknowledgeReceipts`.
38
+ */
39
+ drainReceipts(): string[];
40
+ acknowledgeReceipts(count: number): number;
41
+ /** Receipts dropped because the shared outbox was full. */
42
+ receiptOverflows(): number;
43
+ }
44
+ export declare function createRuntime(createTenuo: (options: {
45
+ trustedRoots: readonly PublicKeyHandle[];
46
+ revocationList?: string | Uint8Array;
47
+ receiptSigner?: Uint8Array;
48
+ }) => Tenuo, options: RuntimeOptions): Runtime;
49
+ export declare function drainSessionReceipts(session: object): string[];
50
+ export declare function peekSessionReceipts(session: object): string[];
51
+ export declare function acknowledgeSessionReceipts(session: object, count: number): number;
@@ -0,0 +1,102 @@
1
+ import { TenuoConfigurationError } from "./errors.js";
2
+ import { bindHostCollector, bindSessionCollector, hostCollector, linkedHostCollector, ReceiptCollector, sessionCollector, } from "./receipts.js";
3
+ /**
4
+ * Long-lived holder runtime. Owns identity, trusted roots, the current
5
+ * revocation list, and optional receipt collection. Does not perform
6
+ * network I/O or invent hosted-service defaults.
7
+ */
8
+ export class Runtime {
9
+ identity;
10
+ tenuo;
11
+ #collect;
12
+ #max;
13
+ #sessionCollectors = [];
14
+ constructor(tenuo, identity, collect, max = 10_000) {
15
+ this.tenuo = tenuo;
16
+ this.identity = identity;
17
+ this.#collect = collect;
18
+ this.#max = max;
19
+ if (collect) {
20
+ bindHostCollector(tenuo, new ReceiptCollector(max));
21
+ }
22
+ }
23
+ applyRevocationList(list) {
24
+ this.tenuo.revoke(list);
25
+ }
26
+ sessionFromWire(warrant) {
27
+ const session = this.tenuo.sessionFromWire({
28
+ warrant,
29
+ holderKey: this.identity.holderKey,
30
+ });
31
+ if (this.#collect) {
32
+ const collector = new ReceiptCollector(this.#max);
33
+ this.#sessionCollectors.push(collector);
34
+ bindSessionCollector(session, collector, hostCollector(this.tenuo));
35
+ }
36
+ return session;
37
+ }
38
+ /** Undrained receipts from every session and presented call handled by this runtime. */
39
+ peekReceipts() {
40
+ return hostCollector(this.tenuo)?.peek() ?? [];
41
+ }
42
+ /**
43
+ * Snapshot of receipts across holder sessions and presented-path
44
+ * verification. Same as `peekReceipts`; nothing is removed until
45
+ * `acknowledgeReceipts`.
46
+ */
47
+ drainReceipts() {
48
+ return this.peekReceipts();
49
+ }
50
+ acknowledgeReceipts(count) {
51
+ const host = hostCollector(this.tenuo);
52
+ if (host === undefined) {
53
+ return 0;
54
+ }
55
+ const taken = host.peek().slice(0, count);
56
+ const removed = host.acknowledge(count);
57
+ const acked = taken.slice(0, removed);
58
+ for (const collector of this.#sessionCollectors) {
59
+ collector.removeMatching(acked);
60
+ }
61
+ return removed;
62
+ }
63
+ /** Receipts dropped because the shared outbox was full. */
64
+ receiptOverflows() {
65
+ return hostCollector(this.tenuo)?.overflowed ?? 0;
66
+ }
67
+ }
68
+ export function createRuntime(createTenuo, options) {
69
+ if (options.trustedRoots.length === 0) {
70
+ throw new TenuoConfigurationError("createTenuo.runtime() requires at least one trusted root.");
71
+ }
72
+ const tenuoOptions = { trustedRoots: options.trustedRoots };
73
+ if (options.revocationList !== undefined) {
74
+ tenuoOptions.revocationList = options.revocationList;
75
+ }
76
+ const tenuo = createTenuo({
77
+ ...tenuoOptions,
78
+ receiptSigner: options.identity.holderKey,
79
+ });
80
+ if (options.receiptMax !== undefined &&
81
+ (!Number.isInteger(options.receiptMax) || options.receiptMax <= 0)) {
82
+ throw new TenuoConfigurationError("createTenuo.runtime() receiptMax must be a positive integer.");
83
+ }
84
+ return new Runtime(tenuo, options.identity, options.receipts === "collect", options.receiptMax ?? 10_000);
85
+ }
86
+ export function drainSessionReceipts(session) {
87
+ return sessionCollector(session)?.drain() ?? [];
88
+ }
89
+ export function peekSessionReceipts(session) {
90
+ return sessionCollector(session)?.peek() ?? [];
91
+ }
92
+ export function acknowledgeSessionReceipts(session, count) {
93
+ const collector = sessionCollector(session);
94
+ if (collector === undefined) {
95
+ return 0;
96
+ }
97
+ const taken = collector.peek().slice(0, count);
98
+ const removed = collector.acknowledge(count);
99
+ linkedHostCollector(session)?.removeMatching(taken.slice(0, removed));
100
+ return removed;
101
+ }
102
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PublicKeyHandle, Session, Tenuo, WarrantPart } from \"./api.ts\";\nimport { TenuoConfigurationError } from \"./errors.ts\";\nimport type { HolderIdentity } from \"./identity.ts\";\nimport {\n bindHostCollector,\n bindSessionCollector,\n hostCollector,\n linkedHostCollector,\n ReceiptCollector,\n sessionCollector,\n} from \"./receipts.ts\";\n\nexport type ReceiptsMode = \"collect\" | \"off\";\n\nexport type RuntimeOptions = {\n readonly identity: HolderIdentity;\n readonly trustedRoots: readonly PublicKeyHandle[];\n /** Published SignedRevocationList. Fetching it is the caller's job. */\n readonly revocationList?: string | Uint8Array;\n /**\n * `collect` retains receipts produced through this runtime's sessions\n * (tools, present, MCP attach) and through this runtime's tenuo\n * (verify, MCP verify/handler) until `acknowledgeReceipts()`.\n * `drainReceipts()` is a snapshot. Default `off`.\n */\n readonly receipts?: ReceiptsMode;\n /** Bound on each receipt outbox. Default 10_000. */\n readonly receiptMax?: number;\n};\n\nexport type SessionWarrant = string | readonly string[] | readonly WarrantPart[];\n\n/**\n * Long-lived holder runtime. Owns identity, trusted roots, the current\n * revocation list, and optional receipt collection. Does not perform\n * network I/O or invent hosted-service defaults.\n */\nexport class Runtime {\n readonly identity: HolderIdentity;\n readonly tenuo: Tenuo;\n readonly #collect: boolean;\n readonly #max: number;\n readonly #sessionCollectors: ReceiptCollector[] = [];\n\n constructor(\n tenuo: Tenuo,\n identity: HolderIdentity,\n collect: boolean,\n max = 10_000,\n ) {\n this.tenuo = tenuo;\n this.identity = identity;\n this.#collect = collect;\n this.#max = max;\n if (collect) {\n bindHostCollector(tenuo, new ReceiptCollector(max));\n }\n }\n\n applyRevocationList(list: string | Uint8Array): void {\n this.tenuo.revoke(list);\n }\n\n sessionFromWire(warrant: SessionWarrant): Session {\n const session = this.tenuo.sessionFromWire({\n warrant,\n holderKey: this.identity.holderKey,\n });\n if (this.#collect) {\n const collector = new ReceiptCollector(this.#max);\n this.#sessionCollectors.push(collector);\n bindSessionCollector(session, collector, hostCollector(this.tenuo));\n }\n return session;\n }\n\n /** Undrained receipts from every session and presented call handled by this runtime. */\n peekReceipts(): string[] {\n return hostCollector(this.tenuo)?.peek() ?? [];\n }\n\n /**\n * Snapshot of receipts across holder sessions and presented-path\n * verification. Same as `peekReceipts`; nothing is removed until\n * `acknowledgeReceipts`.\n */\n drainReceipts(): string[] {\n return this.peekReceipts();\n }\n\n acknowledgeReceipts(count: number): number {\n const host = hostCollector(this.tenuo);\n if (host === undefined) {\n return 0;\n }\n const taken = host.peek().slice(0, count);\n const removed = host.acknowledge(count);\n const acked = taken.slice(0, removed);\n for (const collector of this.#sessionCollectors) {\n collector.removeMatching(acked);\n }\n return removed;\n }\n\n /** Receipts dropped because the shared outbox was full. */\n receiptOverflows(): number {\n return hostCollector(this.tenuo)?.overflowed ?? 0;\n }\n}\n\nexport function createRuntime(\n createTenuo: (options: {\n trustedRoots: readonly PublicKeyHandle[];\n revocationList?: string | Uint8Array;\n receiptSigner?: Uint8Array;\n }) => Tenuo,\n options: RuntimeOptions,\n): Runtime {\n if (options.trustedRoots.length === 0) {\n throw new TenuoConfigurationError(\n \"createTenuo.runtime() requires at least one trusted root.\",\n );\n }\n const tenuoOptions: {\n trustedRoots: readonly PublicKeyHandle[];\n revocationList?: string | Uint8Array;\n receiptSigner?: Uint8Array;\n } = { trustedRoots: options.trustedRoots };\n if (options.revocationList !== undefined) {\n tenuoOptions.revocationList = options.revocationList;\n }\n const tenuo = createTenuo({\n ...tenuoOptions,\n receiptSigner: options.identity.holderKey,\n });\n if (\n options.receiptMax !== undefined &&\n (!Number.isInteger(options.receiptMax) || options.receiptMax <= 0)\n ) {\n throw new TenuoConfigurationError(\"createTenuo.runtime() receiptMax must be a positive integer.\");\n }\n return new Runtime(\n tenuo,\n options.identity,\n options.receipts === \"collect\",\n options.receiptMax ?? 10_000,\n );\n}\n\nexport function drainSessionReceipts(session: object): string[] {\n return sessionCollector(session)?.drain() ?? [];\n}\n\nexport function peekSessionReceipts(session: object): string[] {\n return sessionCollector(session)?.peek() ?? [];\n}\n\nexport function acknowledgeSessionReceipts(session: object, count: number): number {\n const collector = sessionCollector(session);\n if (collector === undefined) {\n return 0;\n }\n const taken = collector.peek().slice(0, count);\n const removed = collector.acknowledge(count);\n linkedHostCollector(session)?.removeMatching(taken.slice(0, removed));\n return removed;\n}\n"]}
package/dist/session.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Session as SessionContract } from "./api.ts";
1
+ import type { Session as SessionContract, SessionInfo } from "./api.ts";
2
2
  import type { WasmSession } from "./wasm.ts";
3
3
  declare const inspect: unique symbol;
4
4
  /**
@@ -12,8 +12,15 @@ export declare class Session implements SessionContract {
12
12
  [inspect](): string;
13
13
  toWire(): string[];
14
14
  dedupKey(tool: string, args: Readonly<Record<string, unknown>>): string;
15
+ inspect(): SessionInfo;
16
+ /**
17
+ * Snapshot of collected receipts. Same as `drainReceipts`; nothing is
18
+ * removed until `acknowledgeReceipts`.
19
+ */
20
+ peekReceipts(): string[];
21
+ drainReceipts(): string[];
22
+ acknowledgeReceipts(count: number): number;
15
23
  }
16
24
  export declare function isSession(value: unknown): value is Session;
17
25
  export declare function nativeSession(session: Session): WasmSession;
18
26
  export {};
19
- //# sourceMappingURL=session.d.ts.map
package/dist/session.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { TenuoConfigurationError } from "./errors.js";
2
+ import { acknowledgeSessionReceipts, drainSessionReceipts, peekSessionReceipts, } from "./runtime.js";
2
3
  const inspect = Symbol.for("nodejs.util.inspect.custom");
3
4
  const nativeSessions = new WeakMap();
4
5
  /**
@@ -36,6 +37,61 @@ export class Session {
36
37
  }
37
38
  return native.dedupKey(tool, args);
38
39
  }
40
+ inspect() {
41
+ const native = nativeSessions.get(this);
42
+ if (typeof native?.describe !== "function") {
43
+ throw new TenuoConfigurationError("session is not bound to the WASM core");
44
+ }
45
+ const info = native.describe();
46
+ const out = {
47
+ kind: info.kind,
48
+ holderPublicKey: info.holder_public_key,
49
+ rootPublicKey: info.root_public_key,
50
+ depth: info.depth,
51
+ maxDepth: info.max_depth,
52
+ terminal: info.terminal,
53
+ expiresAt: info.expires_at,
54
+ tools: [...info.tools],
55
+ warrantIds: [...info.warrant_ids],
56
+ canAuthorize: info.can_authorize,
57
+ approvalGatedTools: [...info.approval_gated_tools],
58
+ };
59
+ if (info.clearance !== undefined) {
60
+ out.clearance = info.clearance;
61
+ }
62
+ if (info.session_id !== undefined) {
63
+ out.sessionId = info.session_id;
64
+ }
65
+ if (info.agent_id !== undefined) {
66
+ out.agentId = info.agent_id;
67
+ }
68
+ if (info.issuable_tools !== undefined) {
69
+ out.issuableTools = [...info.issuable_tools];
70
+ }
71
+ if (info.max_issue_depth !== undefined) {
72
+ out.maxIssueDepth = info.max_issue_depth;
73
+ }
74
+ if (info.required_approvers !== undefined) {
75
+ out.requiredApprovers = [...info.required_approvers];
76
+ }
77
+ if (info.min_approvals !== undefined) {
78
+ out.minApprovals = info.min_approvals;
79
+ }
80
+ return out;
81
+ }
82
+ /**
83
+ * Snapshot of collected receipts. Same as `drainReceipts`; nothing is
84
+ * removed until `acknowledgeReceipts`.
85
+ */
86
+ peekReceipts() {
87
+ return peekSessionReceipts(this);
88
+ }
89
+ drainReceipts() {
90
+ return drainSessionReceipts(this);
91
+ }
92
+ acknowledgeReceipts(count) {
93
+ return acknowledgeSessionReceipts(this, count);
94
+ }
39
95
  }
40
96
  export function isSession(value) {
41
97
  return value instanceof Session;
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAGtD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AACzD,MAAM,cAAc,GAAG,IAAI,OAAO,EAAwB,CAAC;AAE3D;;GAEG;AACH,MAAM,OAAO,OAAO;IACT,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,cAAuB,CAAC;IAExD,YAAY,MAAmB;QAC7B,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,MAAM;QACJ,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,QAAQ;QACN,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,CAAC,OAAO,CAAC;QACP,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,MAAM;QACJ,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAA2C,CAAC;QAClF,IAAI,MAAM,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,uBAAuB,CAAC,uCAAuC,CAAC,CAAC;QAC7E,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;YAChF,MAAM,IAAI,uBAAuB,CAAC,wCAAwC,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,QAAQ,CAAC,IAAY,EAAE,IAAuC;QAC5D,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,IAAI,CAEzB,CAAC;QACd,IAAI,OAAO,MAAM,EAAE,QAAQ,KAAK,UAAU,EAAE,CAAC;YAC3C,MAAM,IAAI,uBAAuB,CAAC,uCAAuC,CAAC,CAAC;QAC7E,CAAC;QACD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;CACF;AAED,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,KAAK,YAAY,OAAO,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,uBAAuB,CAAC,uCAAuC,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Session as SessionContract, SessionInfo } from \"./api.ts\";\nimport { TenuoConfigurationError } from \"./errors.ts\";\nimport {\n acknowledgeSessionReceipts,\n drainSessionReceipts,\n peekSessionReceipts,\n} from \"./runtime.ts\";\nimport type { WasmSession, WasmSessionInfo } from \"./wasm.ts\";\n\nconst inspect = Symbol.for(\"nodejs.util.inspect.custom\");\nconst nativeSessions = new WeakMap<Session, WasmSession>();\n\n/**\n * Opaque session handle. Structural clones and JSON are not sessions.\n */\nexport class Session implements SessionContract {\n readonly [Symbol.toStringTag] = \"TenuoSession\" as const;\n\n constructor(native: WasmSession) {\n nativeSessions.set(this, native);\n }\n\n toJSON(): string {\n return \"[TenuoSession]\";\n }\n\n toString(): string {\n return \"[TenuoSession]\";\n }\n\n [inspect](): string {\n return \"[TenuoSession]\";\n }\n\n toWire(): string[] {\n const native = nativeSessions.get(this) as { toWire?: () => unknown } | undefined;\n if (native?.toWire === undefined) {\n throw new TenuoConfigurationError(\"session is not bound to the WASM core\");\n }\n const tokens = native.toWire();\n if (!Array.isArray(tokens) || tokens.some((token) => typeof token !== \"string\")) {\n throw new TenuoConfigurationError(\"toWire() did not return warrant tokens\");\n }\n return tokens;\n }\n\n dedupKey(tool: string, args: Readonly<Record<string, unknown>>): string {\n const native = nativeSessions.get(this) as\n | { dedupKey?: (tool: string, args: unknown) => string }\n | undefined;\n if (typeof native?.dedupKey !== \"function\") {\n throw new TenuoConfigurationError(\"session is not bound to the WASM core\");\n }\n return native.dedupKey(tool, args);\n }\n\n inspect(): SessionInfo {\n const native = nativeSessions.get(this) as { describe?: () => unknown } | undefined;\n if (typeof native?.describe !== \"function\") {\n throw new TenuoConfigurationError(\"session is not bound to the WASM core\");\n }\n const info = native.describe() as WasmSessionInfo;\n const out: {\n -readonly [K in keyof SessionInfo]: SessionInfo[K];\n } = {\n kind: info.kind,\n holderPublicKey: info.holder_public_key,\n rootPublicKey: info.root_public_key,\n depth: info.depth,\n maxDepth: info.max_depth,\n terminal: info.terminal,\n expiresAt: info.expires_at,\n tools: [...info.tools],\n warrantIds: [...info.warrant_ids],\n canAuthorize: info.can_authorize,\n approvalGatedTools: [...info.approval_gated_tools],\n };\n if (info.clearance !== undefined) {\n out.clearance = info.clearance;\n }\n if (info.session_id !== undefined) {\n out.sessionId = info.session_id;\n }\n if (info.agent_id !== undefined) {\n out.agentId = info.agent_id;\n }\n if (info.issuable_tools !== undefined) {\n out.issuableTools = [...info.issuable_tools];\n }\n if (info.max_issue_depth !== undefined) {\n out.maxIssueDepth = info.max_issue_depth;\n }\n if (info.required_approvers !== undefined) {\n out.requiredApprovers = [...info.required_approvers];\n }\n if (info.min_approvals !== undefined) {\n out.minApprovals = info.min_approvals;\n }\n return out;\n }\n\n /**\n * Snapshot of collected receipts. Same as `drainReceipts`; nothing is\n * removed until `acknowledgeReceipts`.\n */\n peekReceipts(): string[] {\n return peekSessionReceipts(this);\n }\n\n drainReceipts(): string[] {\n return drainSessionReceipts(this);\n }\n\n acknowledgeReceipts(count: number): number {\n return acknowledgeSessionReceipts(this, count);\n }\n}\n\nexport function isSession(value: unknown): value is Session {\n return value instanceof Session;\n}\n\nexport function nativeSession(session: Session): WasmSession {\n const native = nativeSessions.get(session);\n if (!native) {\n throw new TenuoConfigurationError(\"session is not bound to the WASM core\");\n }\n return native;\n}\n"]}
package/dist/wasm.d.ts CHANGED
@@ -66,9 +66,157 @@ export type WasmReceiptChain = {
66
66
  leaf_holder?: string;
67
67
  };
68
68
  export type WasmSession = object;
69
+ /** Mirrors `SessionInfoDto` in tenuo-wasm. Snake case is the WASM boundary. */
70
+ export type WasmSessionInfo = {
71
+ kind: "execution" | "issuer";
72
+ holder_public_key: string;
73
+ root_public_key: string;
74
+ depth: number;
75
+ max_depth: number;
76
+ terminal: boolean;
77
+ expires_at: number;
78
+ tools: string[];
79
+ warrant_ids: string[];
80
+ can_authorize: boolean;
81
+ clearance?: number;
82
+ session_id?: string;
83
+ agent_id?: string;
84
+ issuable_tools?: string[];
85
+ max_issue_depth?: number;
86
+ required_approvers?: string[];
87
+ min_approvals?: number;
88
+ approval_gated_tools: string[];
89
+ };
90
+ /** Security limits exported by tenuo-core; TypeScript must not redefine them. */
91
+ export type WasmProtocolLimits = {
92
+ max_delegation_depth: number;
93
+ max_warrant_ttl_seconds: number;
94
+ };
95
+ /** Mirrors `NarrowOptions` in tenuo-wasm. Unknown keys are rejected there. */
96
+ export type WasmNarrowOptions = {
97
+ holder?: string;
98
+ ttlSeconds?: number;
99
+ terminal?: boolean;
100
+ maxDepth?: number;
101
+ clearance?: number | string;
102
+ agentId?: string;
103
+ addApprovers?: string[];
104
+ minApprovals?: number;
105
+ };
106
+ export type WasmRequireApproval = {
107
+ approvers: string[];
108
+ min: number;
109
+ tools?: string[];
110
+ gates?: Record<string, {
111
+ message?: string;
112
+ args?: Record<string, unknown>;
113
+ }>;
114
+ };
115
+ /** Mirrors `MintOptions` in tenuo-wasm. */
116
+ export type WasmMintOptions = {
117
+ kind?: "execution" | "issuer";
118
+ allow?: unknown;
119
+ ttlSeconds?: number;
120
+ holder?: string;
121
+ maxDepth?: number;
122
+ clearance?: number | string;
123
+ sessionId?: string;
124
+ agentId?: string;
125
+ requireApproval?: WasmRequireApproval;
126
+ issuableTools?: string[];
127
+ constraintBounds?: unknown;
128
+ maxIssueDepth?: number;
129
+ };
130
+ /** Mirrors `IssueOptions` in tenuo-wasm. */
131
+ export type WasmIssueOptions = {
132
+ allow: unknown;
133
+ holder: string;
134
+ ttlSeconds?: number;
135
+ maxDepth?: number;
136
+ clearance?: number | string;
137
+ sessionId?: string;
138
+ agentId?: string;
139
+ requireApproval?: {
140
+ approvers: string[];
141
+ min: number;
142
+ };
143
+ };
144
+ export type WasmExplainField = {
145
+ field: string;
146
+ kind: string;
147
+ constraint: unknown;
148
+ value?: unknown;
149
+ satisfied: boolean;
150
+ reason?: string;
151
+ };
152
+ export type WasmExplain = {
153
+ tool: string;
154
+ kind: "execution" | "issuer";
155
+ outcome: "allow" | "deny";
156
+ code?: TenuoErrorCode;
157
+ field?: string;
158
+ message?: string;
159
+ tool_granted: boolean;
160
+ fields: WasmExplainField[];
161
+ unknown_fields: string[];
162
+ missing_fields: string[];
163
+ expired: boolean;
164
+ expires_at: number;
165
+ chain_valid: boolean;
166
+ chain_error?: TenuoErrorCode;
167
+ };
168
+ export type WasmApprovalRequest = {
169
+ request_id: string;
170
+ warrant_id: string;
171
+ tool: string;
172
+ args: Record<string, unknown>;
173
+ request_hash: string;
174
+ holder_public_key: string;
175
+ required_approvers: string[];
176
+ min_approvals: number;
177
+ warrant_expires_at: number;
178
+ created_at: number;
179
+ message: string;
180
+ };
181
+ export type WasmAttestation = {
182
+ version: number;
183
+ canonicalization: string;
184
+ warrant_id: string;
185
+ tool: string;
186
+ request_hash: string;
187
+ holder_key_hex: string;
188
+ args_canonical_cbor_b64: string;
189
+ signer_key_hex: string;
190
+ signature_b64: string;
191
+ };
192
+ export type WasmApprovalInfo = {
193
+ approver_public_key: string;
194
+ request_hash: string;
195
+ external_id: string;
196
+ approved_at: number;
197
+ expires_at: number;
198
+ expired: boolean;
199
+ signature_valid: boolean;
200
+ error?: string;
201
+ };
202
+ export type WasmSrlInfo = {
203
+ version: number;
204
+ issued_at: number;
205
+ issuer_public_key: string;
206
+ revoked_ids: string[];
207
+ signature_valid: boolean;
208
+ };
69
209
  export type WasmContext = {
70
- mint(allow: unknown, ttlSeconds: number, requireApproval?: unknown): WasmSession;
71
- narrow(session: WasmSession, allow: unknown): WasmSession;
210
+ withReceiptSigner(secret: Uint8Array): WasmContext;
211
+ mint(allow: unknown, ttlSeconds: number, requireApproval?: unknown, holderHex?: string, maxDepth?: number): WasmSession;
212
+ mintExtended(options: WasmMintOptions): WasmSession;
213
+ narrow(session: WasmSession, allow: unknown, options?: WasmNarrowOptions): WasmSession;
214
+ issue(issuer: WasmSession, options: WasmIssueOptions): WasmSession;
215
+ issuerPublicKey(): string;
216
+ explain(session: WasmSession, tool: string, args: unknown): WasmExplain;
217
+ approvalRequest(session: WasmSession, tool: string, args: unknown): WasmApprovalRequest;
218
+ approvalContextAttestation(session: WasmSession, tool: string, args: unknown): WasmAttestation;
219
+ signRevocationListVersioned(ids: string[], version?: number): string;
72
220
  authorize(session: WasmSession, tool: string, args: unknown, approvals?: unknown, toolAllow?: unknown, requestId?: string): WasmDecision;
73
221
  authorizeAsOf(session: WasmSession, tool: string, args: unknown, asOf: number, approvals?: unknown, toolAllow?: unknown): WasmDecision;
74
222
  loadRevocationList(srl: string): void;
@@ -80,6 +228,7 @@ type Generated = {
80
228
  SdkContext: {
81
229
  new (): WasmContext;
82
230
  fromTrustedRoots(roots: string[]): WasmContext;
231
+ fromIssuerSecret(secret: Uint8Array, extraRoots?: string[]): WasmContext;
83
232
  };
84
233
  SdkSession: {
85
234
  fromWire(warrant: string, holder: Uint8Array): WasmSession;
@@ -88,20 +237,73 @@ type Generated = {
88
237
  };
89
238
  sdkInspectWarrant(wire: string): WasmInspect;
90
239
  sdkInspectParts(payloadHex: string, signatureHex: string): WasmInspect;
240
+ sdkProtocolLimits(): WasmProtocolLimits;
241
+ sdkPublicKeyFromHolderKey(holderSecret: Uint8Array): string;
91
242
  sdkSignApproval(session: WasmSession, tool: string, args: unknown, approverSecret: Uint8Array, externalId: string, asOf?: number): string;
243
+ sdkSignApprovalForRequest(requestHashHex: string, approverSecret: Uint8Array, externalId: string, ttlSeconds?: number, warrantExpiresAt?: number): string;
244
+ sdkInspectApproval(envelope: string): WasmApprovalInfo;
92
245
  sdkSignRevocationList(ids: string[], issuerSecret: Uint8Array): string;
246
+ sdkSignRevocationListVersioned(ids: string[], version: number | undefined, issuerSecret: Uint8Array): string;
93
247
  sdkSignPublishedRevocationList(ids: string[], version: number, issuerSecret: Uint8Array): string;
248
+ sdkInspectRevocationList(wire: string): WasmSrlInfo;
94
249
  sdkVerifyReceipt(wire: string): WasmReceipt;
95
250
  sdkVerifyReceiptChain(wire: string, roots: string[]): WasmReceiptChain;
251
+ approval_requirement(warrantB64: string, tool: string, args: unknown): ApprovalRequirement & {
252
+ error?: string;
253
+ };
254
+ inspect_approval_gate(warrantB64: string, tool: string): ApprovalGateInspection & {
255
+ error?: string;
256
+ };
257
+ evaluate_approval_gates(warrantB64: string, tool: string, args: unknown): {
258
+ approval_required: boolean;
259
+ tool: string;
260
+ error?: string;
261
+ };
96
262
  };
97
263
  export declare function wasmAvailable(): boolean;
98
264
  export declare function loadWasm(): Generated;
99
- export declare function createDevContext(): WasmContext;
100
- export declare function createVerifierContext(rootHexes: readonly string[], revocationList?: string): WasmContext;
265
+ export declare function createDevContext(receiptSigner?: Uint8Array): WasmContext;
266
+ export declare function protocolLimits(): WasmProtocolLimits;
267
+ export declare function createVerifierContext(rootHexes: readonly string[], revocationList?: string, receiptSigner?: Uint8Array): WasmContext;
268
+ export declare function createIssuerContext(secret: Uint8Array, extraRootHexes: readonly string[], receiptSigner?: Uint8Array): WasmContext;
101
269
  export declare function importSessionFromWire(warrant: string, holderKey: Uint8Array): WasmSession;
102
270
  export declare function importSessionFromParts(payloadHex: string, signatureHex: string, holderKey: Uint8Array): WasmSession;
103
271
  export declare function importSessionFromChain(parts: unknown, holderKey: Uint8Array): WasmSession;
104
272
  export declare function inspectWarrant(wire: string): WasmInspect;
105
273
  export declare function inspectParts(payloadHex: string, signatureHex: string): WasmInspect;
274
+ /** Hex public key for a 32-byte holder secret. Ed25519, derived in Rust. */
275
+ export declare function publicKeyHexFromHolderKey(holderSecret: Uint8Array): string;
276
+ export type ApprovalRequirementStatus = "not_gated" | "exempt" | "required" | "denied";
277
+ export type ApprovalRequirement = {
278
+ status: ApprovalRequirementStatus;
279
+ tool: string;
280
+ kind?: "whole_tool" | "argument";
281
+ argument?: string;
282
+ arguments: string[];
283
+ message?: string;
284
+ code?: string;
285
+ reason?: string;
286
+ };
287
+ export type ApprovalGateInspection = {
288
+ kind: "none" | "whole_tool" | "conditional" | "unknown";
289
+ tool: string;
290
+ arguments: string[];
291
+ message?: string;
292
+ };
293
+ /**
294
+ * Typed preflight of a warrant's approval gates for `(tool, args)`.
295
+ *
296
+ * Capability constraints are checked first. `denied` means the authorizer
297
+ * will refuse the call — do not collect approval. Malformed encodings throw
298
+ * (fail-closed).
299
+ */
300
+ export declare function approvalRequirement(warrantB64: string, tool: string, args: Record<string, unknown>): ApprovalRequirement;
301
+ /** Inspect how a warrant gates `tool`, without evaluating arguments. */
302
+ export declare function inspectApprovalGate(warrantB64: string, tool: string): ApprovalGateInspection;
303
+ /**
304
+ * Gate-map-only boolean. Does not run capability checks, so split-view
305
+ * callers (PoP args vs constraint args) still see a firing gate. Prefer
306
+ * {@link approvalRequirement} when the caller must distinguish `denied`.
307
+ */
308
+ export declare function evaluateApprovalGates(warrantB64: string, tool: string, args: Record<string, unknown>): boolean;
106
309
  export {};
107
- //# sourceMappingURL=wasm.d.ts.map
package/dist/wasm.js CHANGED
@@ -31,18 +31,36 @@ export function loadWasm() {
31
31
  throw wrapped;
32
32
  }
33
33
  }
34
- export function createDevContext() {
34
+ export function createDevContext(receiptSigner) {
35
35
  const { SdkContext } = loadWasm();
36
- return new SdkContext();
36
+ let context = new SdkContext();
37
+ if (receiptSigner !== undefined) {
38
+ context = context.withReceiptSigner(receiptSigner);
39
+ }
40
+ return context;
37
41
  }
38
- export function createVerifierContext(rootHexes, revocationList) {
42
+ export function protocolLimits() {
43
+ return loadWasm().sdkProtocolLimits();
44
+ }
45
+ export function createVerifierContext(rootHexes, revocationList, receiptSigner) {
39
46
  const { SdkContext } = loadWasm();
40
- const context = SdkContext.fromTrustedRoots([...rootHexes]);
47
+ let context = SdkContext.fromTrustedRoots([...rootHexes]);
48
+ if (receiptSigner !== undefined) {
49
+ context = context.withReceiptSigner(receiptSigner);
50
+ }
41
51
  if (revocationList !== undefined && revocationList.length > 0) {
42
52
  context.loadRevocationList(revocationList);
43
53
  }
44
54
  return context;
45
55
  }
56
+ export function createIssuerContext(secret, extraRootHexes, receiptSigner) {
57
+ const { SdkContext } = loadWasm();
58
+ let context = SdkContext.fromIssuerSecret(secret, [...extraRootHexes]);
59
+ if (receiptSigner !== undefined) {
60
+ context = context.withReceiptSigner(receiptSigner);
61
+ }
62
+ return context;
63
+ }
46
64
  export function importSessionFromWire(warrant, holderKey) {
47
65
  const { SdkSession } = loadWasm();
48
66
  return SdkSession.fromWire(warrant, holderKey);
@@ -61,4 +79,44 @@ export function inspectWarrant(wire) {
61
79
  export function inspectParts(payloadHex, signatureHex) {
62
80
  return loadWasm().sdkInspectParts(payloadHex, signatureHex);
63
81
  }
82
+ /** Hex public key for a 32-byte holder secret. Ed25519, derived in Rust. */
83
+ export function publicKeyHexFromHolderKey(holderSecret) {
84
+ return loadWasm().sdkPublicKeyFromHolderKey(holderSecret);
85
+ }
86
+ function loadApprovalWasm() {
87
+ return loadWasm();
88
+ }
89
+ function throwIfGateError(error) {
90
+ if (error) {
91
+ throw new TenuoConfigurationError(error);
92
+ }
93
+ }
94
+ /**
95
+ * Typed preflight of a warrant's approval gates for `(tool, args)`.
96
+ *
97
+ * Capability constraints are checked first. `denied` means the authorizer
98
+ * will refuse the call — do not collect approval. Malformed encodings throw
99
+ * (fail-closed).
100
+ */
101
+ export function approvalRequirement(warrantB64, tool, args) {
102
+ const result = loadApprovalWasm().approval_requirement(warrantB64, tool, args);
103
+ throwIfGateError(result.error);
104
+ return result;
105
+ }
106
+ /** Inspect how a warrant gates `tool`, without evaluating arguments. */
107
+ export function inspectApprovalGate(warrantB64, tool) {
108
+ const result = loadApprovalWasm().inspect_approval_gate(warrantB64, tool);
109
+ throwIfGateError(result.error);
110
+ return result;
111
+ }
112
+ /**
113
+ * Gate-map-only boolean. Does not run capability checks, so split-view
114
+ * callers (PoP args vs constraint args) still see a firing gate. Prefer
115
+ * {@link approvalRequirement} when the caller must distinguish `denied`.
116
+ */
117
+ export function evaluateApprovalGates(warrantB64, tool, args) {
118
+ const result = loadApprovalWasm().evaluate_approval_gates(warrantB64, tool, args);
119
+ throwIfGateError(result.error);
120
+ return result.approval_required;
121
+ }
64
122
  //# sourceMappingURL=wasm.js.map