@tenuo/core 0.3.1-beta.0 → 0.3.3-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.
- package/LICENSE +76 -61
- package/README.md +20 -9
- package/dist/api.d.ts +46 -6
- package/dist/api.js.map +1 -1
- package/dist/build-info.json +3 -3
- package/dist/client.js +170 -6
- package/dist/client.js.map +1 -1
- package/dist/generated/tenuo_wasm.d.ts +28 -2
- package/dist/generated/tenuo_wasm.js +95 -5
- package/dist/generated/tenuo_wasm_bg.wasm +0 -0
- package/dist/generated/tenuo_wasm_bg.wasm.d.ts +5 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +47 -110
- package/dist/mcp.js.map +1 -1
- package/dist/replay.d.ts +20 -0
- package/dist/replay.js +117 -0
- package/dist/replay.js.map +1 -0
- package/dist/session.d.ts +1 -0
- package/dist/session.js +11 -0
- package/dist/session.js.map +1 -1
- package/dist/wasm.d.ts +21 -1
- package/dist/wasm.js +12 -0
- package/dist/wasm.js.map +1 -1
- package/package.json +12 -5
package/dist/replay.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { AuthorizationDeniedError, TenuoConfigurationError } from "./errors.js";
|
|
3
|
+
import { loadWasm } from "./wasm.js";
|
|
4
|
+
const REPLAY_STORE_UNAVAILABLE = "Replay store unavailable";
|
|
5
|
+
/**
|
|
6
|
+
* Record `key` in a `NonceStore`. Throws `replayed()` when the store has
|
|
7
|
+
* already seen it, and the constant "Replay store unavailable" when the
|
|
8
|
+
* store throws, rejects, or returns a non-boolean. Shared by the MCP PoP
|
|
9
|
+
* check and approval consumption.
|
|
10
|
+
*/
|
|
11
|
+
export async function admitNonce(store, key, onNonceStoreError, replayed) {
|
|
12
|
+
if (store === undefined) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
let admitted;
|
|
16
|
+
try {
|
|
17
|
+
admitted = store.checkAndRecord(key);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
throw replayStoreUnavailable(error, onNonceStoreError);
|
|
21
|
+
}
|
|
22
|
+
if (isThenable(admitted)) {
|
|
23
|
+
try {
|
|
24
|
+
admitted = await admitted;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
throw replayStoreUnavailable(error, onNonceStoreError);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (typeof admitted !== "boolean") {
|
|
31
|
+
throw replayStoreUnavailable(new TenuoConfigurationError("NonceStore.checkAndRecord() must return boolean or Promise<boolean>"), onNonceStoreError);
|
|
32
|
+
}
|
|
33
|
+
if (!admitted) {
|
|
34
|
+
throw replayed();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Make approvals one-use: record every approval envelope that counts for
|
|
39
|
+
* this call (valid signature and, when `requestHash` is known, bound to this
|
|
40
|
+
* exact request). Run only after core allowed the call. Do not apply a second
|
|
41
|
+
* expiry check here: core intentionally accepts its configured clock-skew
|
|
42
|
+
* grace window, and an approval it accepted must still be consumed.
|
|
43
|
+
*
|
|
44
|
+
* Keys come from signed approval fields, so re-encoding an envelope (hex,
|
|
45
|
+
* base64, bytes) does not make it fresh again.
|
|
46
|
+
*/
|
|
47
|
+
export async function consumeApprovals(store, approvals, requestHash, tool, onNonceStoreError) {
|
|
48
|
+
if (store === undefined || !Array.isArray(approvals) || approvals.length === 0) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const expected = requestHash?.toLowerCase();
|
|
52
|
+
const keys = new Set();
|
|
53
|
+
for (const envelope of approvals) {
|
|
54
|
+
const info = inspect(envelope);
|
|
55
|
+
if (!info.signature_valid) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (expected !== undefined && info.request_hash.toLowerCase() !== expected) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
keys.add(approvalKey(info));
|
|
62
|
+
}
|
|
63
|
+
for (const key of keys) {
|
|
64
|
+
await admitNonce(store, key, onNonceStoreError, () => new AuthorizationDeniedError("TENUO_INSUFFICIENT_APPROVALS", `Approval already used: an approval for ${tool} was consumed by an earlier call. Request a new approval.`));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function snapshotApprovals(approvals) {
|
|
68
|
+
if (!Array.isArray(approvals)) {
|
|
69
|
+
return approvals;
|
|
70
|
+
}
|
|
71
|
+
return approvals.map((envelope) => envelope instanceof Uint8Array ? new Uint8Array(envelope) : envelope);
|
|
72
|
+
}
|
|
73
|
+
function inspect(envelope) {
|
|
74
|
+
if (typeof envelope !== "string" && !(envelope instanceof Uint8Array)) {
|
|
75
|
+
throw new TenuoConfigurationError("could not inspect an authorized approval for replay protection");
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
return loadWasm().sdkInspectApproval(envelope);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
const wrapped = new TenuoConfigurationError("could not inspect an authorized approval for replay protection");
|
|
82
|
+
wrapped.cause = error;
|
|
83
|
+
throw wrapped;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function approvalKey(info) {
|
|
87
|
+
const digest = createHash("sha256")
|
|
88
|
+
.update(JSON.stringify([
|
|
89
|
+
info.approver_public_key.toLowerCase(),
|
|
90
|
+
info.request_hash.toLowerCase(),
|
|
91
|
+
info.nonce.toLowerCase(),
|
|
92
|
+
]))
|
|
93
|
+
.digest("hex");
|
|
94
|
+
return `tenuo-approval-v1:${digest}`;
|
|
95
|
+
}
|
|
96
|
+
function replayStoreUnavailable(cause, onNonceStoreError) {
|
|
97
|
+
if (onNonceStoreError !== undefined) {
|
|
98
|
+
try {
|
|
99
|
+
const result = onNonceStoreError(cause);
|
|
100
|
+
if (isThenable(result)) {
|
|
101
|
+
void Promise.resolve(result).catch(() => undefined);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Isolated — must not change the public error.
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const error = new TenuoConfigurationError(REPLAY_STORE_UNAVAILABLE);
|
|
109
|
+
if (cause !== undefined) {
|
|
110
|
+
error.cause = cause;
|
|
111
|
+
}
|
|
112
|
+
return error;
|
|
113
|
+
}
|
|
114
|
+
function isThenable(value) {
|
|
115
|
+
return value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { NonceStore } from \"./api.ts\";\nimport { AuthorizationDeniedError, TenuoConfigurationError } from \"./errors.ts\";\nimport { loadWasm, type WasmApprovalInfo } from \"./wasm.ts\";\n\nconst REPLAY_STORE_UNAVAILABLE = \"Replay store unavailable\";\n\n/**\n * Record `key` in a `NonceStore`. Throws `replayed()` when the store has\n * already seen it, and the constant \"Replay store unavailable\" when the\n * store throws, rejects, or returns a non-boolean. Shared by the MCP PoP\n * check and approval consumption.\n */\nexport async function admitNonce(\n store: NonceStore | undefined,\n key: string,\n onNonceStoreError: ((error: unknown) => void | Promise<void>) | undefined,\n replayed: () => Error,\n): Promise<void> {\n if (store === undefined) {\n return;\n }\n let admitted: boolean | Promise<boolean>;\n try {\n admitted = store.checkAndRecord(key);\n } catch (error) {\n throw replayStoreUnavailable(error, onNonceStoreError);\n }\n if (isThenable(admitted)) {\n try {\n admitted = await admitted;\n } catch (error) {\n throw replayStoreUnavailable(error, onNonceStoreError);\n }\n }\n if (typeof admitted !== \"boolean\") {\n throw replayStoreUnavailable(\n new TenuoConfigurationError(\"NonceStore.checkAndRecord() must return boolean or Promise<boolean>\"),\n onNonceStoreError,\n );\n }\n if (!admitted) {\n throw replayed();\n }\n}\n\n/**\n * Make approvals one-use: record every approval envelope that counts for\n * this call (valid signature and, when `requestHash` is known, bound to this\n * exact request). Run only after core allowed the call. Do not apply a second\n * expiry check here: core intentionally accepts its configured clock-skew\n * grace window, and an approval it accepted must still be consumed.\n *\n * Keys come from signed approval fields, so re-encoding an envelope (hex,\n * base64, bytes) does not make it fresh again.\n */\nexport async function consumeApprovals(\n store: NonceStore | undefined,\n approvals: unknown,\n requestHash: string | undefined,\n tool: string,\n onNonceStoreError: ((error: unknown) => void | Promise<void>) | undefined,\n): Promise<void> {\n if (store === undefined || !Array.isArray(approvals) || approvals.length === 0) {\n return;\n }\n const expected = requestHash?.toLowerCase();\n const keys = new Set<string>();\n for (const envelope of approvals as unknown[]) {\n const info = inspect(envelope);\n if (!info.signature_valid) {\n continue;\n }\n if (expected !== undefined && info.request_hash.toLowerCase() !== expected) {\n continue;\n }\n keys.add(approvalKey(info));\n }\n for (const key of keys) {\n await admitNonce(store, key, onNonceStoreError, () =>\n new AuthorizationDeniedError(\n \"TENUO_INSUFFICIENT_APPROVALS\",\n `Approval already used: an approval for ${tool} was consumed by an earlier call. Request a new approval.`,\n ),\n );\n }\n}\n\nexport function snapshotApprovals(approvals: unknown): unknown {\n if (!Array.isArray(approvals)) {\n return approvals;\n }\n return approvals.map((envelope) =>\n envelope instanceof Uint8Array ? new Uint8Array(envelope) : envelope,\n );\n}\n\nfunction inspect(envelope: unknown): WasmApprovalInfo {\n if (typeof envelope !== \"string\" && !(envelope instanceof Uint8Array)) {\n throw new TenuoConfigurationError(\"could not inspect an authorized approval for replay protection\");\n }\n try {\n return loadWasm().sdkInspectApproval(envelope);\n } catch (error) {\n const wrapped = new TenuoConfigurationError(\n \"could not inspect an authorized approval for replay protection\",\n );\n wrapped.cause = error;\n throw wrapped;\n }\n}\n\nfunction approvalKey(info: WasmApprovalInfo): string {\n const digest = createHash(\"sha256\")\n .update(\n JSON.stringify([\n info.approver_public_key.toLowerCase(),\n info.request_hash.toLowerCase(),\n info.nonce.toLowerCase(),\n ]),\n )\n .digest(\"hex\");\n return `tenuo-approval-v1:${digest}`;\n}\n\nfunction replayStoreUnavailable(\n cause: unknown,\n onNonceStoreError?: (error: unknown) => void | Promise<void>,\n): TenuoConfigurationError {\n if (onNonceStoreError !== undefined) {\n try {\n const result = onNonceStoreError(cause);\n if (isThenable(result)) {\n void Promise.resolve(result).catch(() => undefined);\n }\n } catch {\n // Isolated — must not change the public error.\n }\n }\n const error = new TenuoConfigurationError(REPLAY_STORE_UNAVAILABLE);\n if (cause !== undefined) {\n error.cause = cause;\n }\n return error;\n}\n\nfunction isThenable(value: unknown): value is Promise<unknown> {\n return value !== null && typeof value === \"object\" && \"then\" in value && typeof value.then === \"function\";\n}\n"]}
|
package/dist/session.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare class Session implements SessionContract {
|
|
|
11
11
|
toString(): string;
|
|
12
12
|
[inspect](): string;
|
|
13
13
|
toWire(): string[];
|
|
14
|
+
toWireString(): string;
|
|
14
15
|
dedupKey(tool: string, args: Readonly<Record<string, unknown>>): string;
|
|
15
16
|
inspect(): SessionInfo;
|
|
16
17
|
/**
|
package/dist/session.js
CHANGED
|
@@ -30,6 +30,17 @@ export class Session {
|
|
|
30
30
|
}
|
|
31
31
|
return tokens;
|
|
32
32
|
}
|
|
33
|
+
toWireString() {
|
|
34
|
+
const native = nativeSessions.get(this);
|
|
35
|
+
if (typeof native?.toStackWire !== "function") {
|
|
36
|
+
throw new TenuoConfigurationError("session is not bound to the WASM core");
|
|
37
|
+
}
|
|
38
|
+
const stack = native.toStackWire();
|
|
39
|
+
if (typeof stack !== "string" || stack.length === 0) {
|
|
40
|
+
throw new TenuoConfigurationError("toWireString() did not return a warrant stack");
|
|
41
|
+
}
|
|
42
|
+
return stack;
|
|
43
|
+
}
|
|
33
44
|
dedupKey(tool, args) {
|
|
34
45
|
const native = nativeSessions.get(this);
|
|
35
46
|
if (typeof native?.dedupKey !== "function") {
|
package/dist/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
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 toWireString(): string {\n const native = nativeSessions.get(this) as { toStackWire?: () => unknown } | undefined;\n if (typeof native?.toStackWire !== \"function\") {\n throw new TenuoConfigurationError(\"session is not bound to the WASM core\");\n }\n const stack = native.toStackWire();\n if (typeof stack !== \"string\" || stack.length === 0) {\n throw new TenuoConfigurationError(\"toWireString() did not return a warrant stack\");\n }\n return stack;\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
|
@@ -193,6 +193,7 @@ export type WasmAttestation = {
|
|
|
193
193
|
export type WasmApprovalInfo = {
|
|
194
194
|
approver_public_key: string;
|
|
195
195
|
request_hash: string;
|
|
196
|
+
nonce: string;
|
|
196
197
|
external_id: string;
|
|
197
198
|
approved_at: number;
|
|
198
199
|
expires_at: number;
|
|
@@ -223,6 +224,15 @@ export type WasmContext = {
|
|
|
223
224
|
loadRevocationList(srl: string): void;
|
|
224
225
|
signRevocationList(ids: string[]): string;
|
|
225
226
|
signPop(session: WasmSession, tool: string, args: unknown): string;
|
|
227
|
+
signMeta(session: WasmSession, tool: string, argsJson: string, timestamp: number, approvals?: unknown): {
|
|
228
|
+
warrant: string;
|
|
229
|
+
signature: string;
|
|
230
|
+
approvals?: string[];
|
|
231
|
+
};
|
|
232
|
+
/** Holder proof only; does not authorize execution. */
|
|
233
|
+
verifyMetaPop(warrant: string, signature: string, tool: string, argsJson: string, timestamp: number): boolean;
|
|
234
|
+
/** Compatibility alias for verifyMetaPop. */
|
|
235
|
+
verifyMeta(warrant: string, signature: string, tool: string, argsJson: string, timestamp: number): boolean;
|
|
226
236
|
authorizePresented(warrants: unknown, tool: string, args: unknown, pop: string, approvals?: unknown, toolAllow?: unknown, requestId?: string): WasmDecision;
|
|
227
237
|
};
|
|
228
238
|
type Generated = {
|
|
@@ -242,7 +252,7 @@ type Generated = {
|
|
|
242
252
|
sdkPublicKeyFromHolderKey(holderSecret: Uint8Array): string;
|
|
243
253
|
sdkSignApproval(session: WasmSession, tool: string, args: unknown, approverSecret: Uint8Array, externalId: string, asOf?: number): string;
|
|
244
254
|
sdkSignApprovalForRequest(requestHashHex: string, approverSecret: Uint8Array, externalId: string, ttlSeconds?: number, warrantExpiresAt?: number): string;
|
|
245
|
-
sdkInspectApproval(envelope: string): WasmApprovalInfo;
|
|
255
|
+
sdkInspectApproval(envelope: string | Uint8Array): WasmApprovalInfo;
|
|
246
256
|
sdkSignRevocationList(ids: string[], issuerSecret: Uint8Array): string;
|
|
247
257
|
sdkSignRevocationListVersioned(ids: string[], version: number | undefined, issuerSecret: Uint8Array): string;
|
|
248
258
|
sdkSignPublishedRevocationList(ids: string[], version: number, issuerSecret: Uint8Array): string;
|
|
@@ -260,6 +270,7 @@ type Generated = {
|
|
|
260
270
|
tool: string;
|
|
261
271
|
error?: string;
|
|
262
272
|
};
|
|
273
|
+
parse_strict_json(jsonText: string): void;
|
|
263
274
|
};
|
|
264
275
|
export declare function wasmAvailable(): boolean;
|
|
265
276
|
export declare function loadWasm(): Generated;
|
|
@@ -291,6 +302,15 @@ export type ApprovalGateInspection = {
|
|
|
291
302
|
arguments: string[];
|
|
292
303
|
message?: string;
|
|
293
304
|
};
|
|
305
|
+
/**
|
|
306
|
+
* Parse JSON text and reject a repeated key in any object.
|
|
307
|
+
*
|
|
308
|
+
* `verify()` receives an object the host already parsed. A duplicate key is
|
|
309
|
+
* gone by then. Call this while the text is still available. After the check,
|
|
310
|
+
* the value is `JSON.parse` of the original text, so each key is an own data
|
|
311
|
+
* property and `null` stays `null`.
|
|
312
|
+
*/
|
|
313
|
+
export declare function parseStrictJson(text: string): unknown;
|
|
294
314
|
/**
|
|
295
315
|
* Typed preflight of a warrant's approval gates for `(tool, args)`.
|
|
296
316
|
*
|
package/dist/wasm.js
CHANGED
|
@@ -91,6 +91,18 @@ function throwIfGateError(error) {
|
|
|
91
91
|
throw new TenuoConfigurationError(error);
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* Parse JSON text and reject a repeated key in any object.
|
|
96
|
+
*
|
|
97
|
+
* `verify()` receives an object the host already parsed. A duplicate key is
|
|
98
|
+
* gone by then. Call this while the text is still available. After the check,
|
|
99
|
+
* the value is `JSON.parse` of the original text, so each key is an own data
|
|
100
|
+
* property and `null` stays `null`.
|
|
101
|
+
*/
|
|
102
|
+
export function parseStrictJson(text) {
|
|
103
|
+
loadWasm().parse_strict_json(text);
|
|
104
|
+
return JSON.parse(text);
|
|
105
|
+
}
|
|
94
106
|
/**
|
|
95
107
|
* Typed preflight of a warrant's approval gates for `(tool, args)`.
|
|
96
108
|
*
|
package/dist/wasm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasm.js","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from \"node:module\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { TenuoConfigurationError } from \"./errors.ts\";\nimport type { TenuoErrorCode } from \"./api.ts\";\n\nexport type WasmDecision = {\n outcome: \"allow\" | \"deny\" | \"approval_required\";\n code?: TenuoErrorCode;\n field?: string;\n message?: string;\n args?: Record<string, unknown>;\n tool?: string;\n required?: number;\n received?: number;\n receipt?: string;\n};\n\nexport type WasmInspect = {\n payload_hex: string;\n signature_hex: string;\n id: string;\n};\n\nexport type WasmReceipt = {\n authentic: true;\n /** Hex key the receipt is signed under — resolve against your authorizer set. */\n signer_key: string;\n outcome: \"allow\" | \"deny\";\n action: string;\n decision_code?: string;\n request_id: string;\n /** Version of the revocation list in force, when it carried one. */\n srl_version?: number;\n /**\n * SHA-256 (hex) of the revocation list bytes in force at decision time.\n * Absent means no revocation data was loaded — a different claim from a\n * loaded list that revoked nothing.\n */\n srl_hash?: string;\n /**\n * SHA-256 (hex) commitment to the canonical invocation this decision was\n * made over. Absent when the arguments could not be canonicalized — never\n * zero-filled, so absence is a claim rather than a value.\n */\n request_hash?: string;\n /** SHA-256 (hex) of the host ceiling applied to this decision. */\n policy_definition_hash?: string;\n /**\n * SHA-256 (hex) of the previous receipt from this signer. Absent on the\n * first receipt, or when the deployment does not chain. A broken link means\n * a receipt was removed from the stream.\n */\n prev_receipt_hash?: string;\n /** SHA-256 (hex) of the trusted root set in force at decision time. */\n trusted_roots_hash?: string;\n};\n\nexport type WasmReceiptChain = {\n signer_key: string;\n outcome: \"allow\" | \"deny\";\n decision_code?: string;\n timestamp: number;\n /** The embedded chain verifies to a supplied root at the decision instant. */\n chain_valid: boolean;\n /** Canonical error name when it does not. */\n chain_error?: string;\n /**\n * Deny receipts only: the chain failure matches the stated decision_code,\n * so the embedded authority independently corroborates the refusal.\n */\n corroborates_denial?: boolean;\n root_issuer?: string;\n leaf_holder?: string;\n};\n\nexport type WasmSession = object;\n\n/** Mirrors `SessionInfoDto` in tenuo-wasm. Snake case is the WASM boundary. */\nexport type WasmSessionInfo = {\n kind: \"execution\" | \"issuer\";\n holder_public_key: string;\n root_public_key: string;\n depth: number;\n max_depth: number;\n terminal: boolean;\n expires_at: number;\n tools: string[];\n warrant_ids: string[];\n can_authorize: boolean;\n clearance?: number;\n session_id?: string;\n agent_id?: string;\n issuable_tools?: string[];\n max_issue_depth?: number;\n required_approvers?: string[];\n min_approvals?: number;\n approval_gated_tools: string[];\n};\n\n/** Security limits exported by tenuo-core; TypeScript must not redefine them. */\nexport type WasmProtocolLimits = {\n max_delegation_depth: number;\n max_warrant_ttl_seconds: number;\n};\n\n/** Mirrors `NarrowOptions` in tenuo-wasm. Unknown keys are rejected there. */\nexport type WasmNarrowOptions = {\n holder?: string;\n ttlSeconds?: number;\n terminal?: boolean;\n maxDepth?: number;\n clearance?: number | string;\n agentId?: string;\n addApprovers?: string[];\n minApprovals?: number;\n};\n\nexport type WasmRequireApproval = {\n approvers: string[];\n min: number;\n tools?: string[];\n gates?: Record<string, { message?: string; args?: Record<string, unknown> }>;\n};\n\n/** Mirrors `MintOptions` in tenuo-wasm. */\nexport type WasmMintOptions = {\n kind?: \"execution\" | \"issuer\";\n allow?: unknown;\n ttlSeconds?: number;\n holder?: string;\n maxDepth?: number;\n clearance?: number | string;\n sessionId?: string;\n agentId?: string;\n requireApproval?: WasmRequireApproval;\n issuableTools?: string[];\n constraintBounds?: unknown;\n maxIssueDepth?: number;\n};\n\n/** Mirrors `IssueOptions` in tenuo-wasm. */\nexport type WasmIssueOptions = {\n allow: unknown;\n holder: string;\n ttlSeconds?: number;\n maxDepth?: number;\n clearance?: number | string;\n sessionId?: string;\n agentId?: string;\n requireApproval?: { approvers: string[]; min: number };\n};\n\nexport type WasmExplainField = {\n field: string;\n kind: string;\n constraint: unknown;\n value?: unknown;\n satisfied: boolean;\n reason_code?: string;\n reason?: string;\n};\n\nexport type WasmExplain = {\n tool: string;\n kind: \"execution\" | \"issuer\";\n outcome: \"allow\" | \"deny\";\n code?: TenuoErrorCode;\n field?: string;\n message?: string;\n tool_granted: boolean;\n fields: WasmExplainField[];\n unknown_fields: string[];\n missing_fields: string[];\n expired: boolean;\n expires_at: number;\n chain_valid: boolean;\n chain_error?: TenuoErrorCode;\n};\n\nexport type WasmApprovalRequest = {\n request_id: string;\n warrant_id: string;\n tool: string;\n args: Record<string, unknown>;\n request_hash: string;\n holder_public_key: string;\n required_approvers: string[];\n min_approvals: number;\n warrant_expires_at: number;\n created_at: number;\n message: string;\n};\n\nexport type WasmAttestation = {\n version: number;\n canonicalization: string;\n warrant_id: string;\n tool: string;\n request_hash: string;\n holder_key_hex: string;\n args_canonical_cbor_b64: string;\n signer_key_hex: string;\n signature_b64: string;\n};\n\nexport type WasmApprovalInfo = {\n approver_public_key: string;\n request_hash: string;\n external_id: string;\n approved_at: number;\n expires_at: number;\n expired: boolean;\n signature_valid: boolean;\n error?: string;\n};\n\nexport type WasmSrlInfo = {\n version: number;\n issued_at: number;\n issuer_public_key: string;\n revoked_ids: string[];\n signature_valid: boolean;\n};\n\nexport type WasmContext = {\n withReceiptSigner(secret: Uint8Array): WasmContext;\n mint(\n allow: unknown,\n ttlSeconds: number,\n requireApproval?: unknown,\n holderHex?: string,\n maxDepth?: number,\n ): WasmSession;\n mintExtended(options: WasmMintOptions): WasmSession;\n narrow(session: WasmSession, allow: unknown, options?: WasmNarrowOptions): WasmSession;\n issue(issuer: WasmSession, options: WasmIssueOptions): WasmSession;\n issuerPublicKey(): string;\n explain(session: WasmSession, tool: string, args: unknown): WasmExplain;\n approvalRequest(session: WasmSession, tool: string, args: unknown): WasmApprovalRequest;\n approvalContextAttestation(session: WasmSession, tool: string, args: unknown): WasmAttestation;\n signRevocationListVersioned(ids: string[], version?: number): string;\n authorize(\n session: WasmSession,\n tool: string,\n args: unknown,\n approvals?: unknown,\n toolAllow?: unknown,\n requestId?: string,\n ): WasmDecision;\n authorizeAsOf(\n session: WasmSession,\n tool: string,\n args: unknown,\n asOf: number,\n approvals?: unknown,\n toolAllow?: unknown,\n ): WasmDecision;\n loadRevocationList(srl: string): void;\n signRevocationList(ids: string[]): string;\n signPop(session: WasmSession, tool: string, args: unknown): string;\n authorizePresented(\n warrants: unknown,\n tool: string,\n args: unknown,\n pop: string,\n approvals?: unknown,\n toolAllow?: unknown,\n requestId?: string,\n ): WasmDecision;\n};\n\ntype Generated = {\n SdkContext: {\n new (): WasmContext;\n fromTrustedRoots(roots: string[]): WasmContext;\n fromIssuerSecret(secret: Uint8Array, extraRoots?: string[]): WasmContext;\n };\n SdkSession: {\n fromWire(warrant: string, holder: Uint8Array): WasmSession;\n fromParts(payloadHex: string, signatureHex: string, holder: Uint8Array): WasmSession;\n fromChain(parts: unknown, holder: Uint8Array): WasmSession;\n };\n sdkInspectWarrant(wire: string): WasmInspect;\n sdkInspectParts(payloadHex: string, signatureHex: string): WasmInspect;\n sdkProtocolLimits(): WasmProtocolLimits;\n sdkPublicKeyFromHolderKey(holderSecret: Uint8Array): string;\n sdkSignApproval(\n session: WasmSession,\n tool: string,\n args: unknown,\n approverSecret: Uint8Array,\n externalId: string,\n asOf?: number,\n ): string;\n sdkSignApprovalForRequest(\n requestHashHex: string,\n approverSecret: Uint8Array,\n externalId: string,\n ttlSeconds?: number,\n warrantExpiresAt?: number,\n ): string;\n sdkInspectApproval(envelope: string): WasmApprovalInfo;\n sdkSignRevocationList(ids: string[], issuerSecret: Uint8Array): string;\n sdkSignRevocationListVersioned(ids: string[], version: number | undefined, issuerSecret: Uint8Array): string;\n sdkSignPublishedRevocationList(ids: string[], version: number, issuerSecret: Uint8Array): string;\n sdkInspectRevocationList(wire: string): WasmSrlInfo;\n sdkVerifyReceipt(wire: string): WasmReceipt;\n sdkVerifyReceiptChain(wire: string, roots: string[]): WasmReceiptChain;\n approval_requirement(\n warrantB64: string,\n tool: string,\n args: unknown,\n ): ApprovalRequirement & { error?: string };\n inspect_approval_gate(\n warrantB64: string,\n tool: string,\n ): ApprovalGateInspection & { error?: string };\n evaluate_approval_gates(\n warrantB64: string,\n tool: string,\n args: unknown,\n ): { approval_required: boolean; tool: string; error?: string };\n};\n\nlet loaded: Generated | undefined;\n\nfunction generatedPath(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n return join(here, \"generated\", \"tenuo_wasm.js\");\n}\n\nexport function wasmAvailable(): boolean {\n return existsSync(generatedPath());\n}\n\nconst WASM_LOAD_HINT =\n \"WASM core is missing from this @tenuo/core install. @tenuo/core is Node 20+ only (not a bundler target). If this is Next.js/webpack, set serverExternalPackages: ['@tenuo/core']. Do not run wasm-pack in the consuming app.\";\n\nexport function loadWasm(): Generated {\n if (loaded) {\n return loaded;\n }\n const path = generatedPath();\n if (!existsSync(path)) {\n throw new TenuoConfigurationError(WASM_LOAD_HINT, \"TENUO_NOT_READY\");\n }\n try {\n const require = createRequire(import.meta.url);\n loaded = require(path) as Generated;\n return loaded;\n } catch (error) {\n const wrapped = new TenuoConfigurationError(WASM_LOAD_HINT, \"TENUO_NOT_READY\");\n wrapped.cause = error;\n throw wrapped;\n }\n}\n\nexport function createDevContext(receiptSigner?: Uint8Array): WasmContext {\n const { SdkContext } = loadWasm();\n let context: WasmContext = new SdkContext();\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n return context;\n}\n\nexport function protocolLimits(): WasmProtocolLimits {\n return loadWasm().sdkProtocolLimits();\n}\n\nexport function createVerifierContext(\n rootHexes: readonly string[],\n revocationList?: string,\n receiptSigner?: Uint8Array,\n): WasmContext {\n const { SdkContext } = loadWasm();\n let context = SdkContext.fromTrustedRoots([...rootHexes]);\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n if (revocationList !== undefined && revocationList.length > 0) {\n context.loadRevocationList(revocationList);\n }\n return context;\n}\n\nexport function createIssuerContext(\n secret: Uint8Array,\n extraRootHexes: readonly string[],\n receiptSigner?: Uint8Array,\n): WasmContext {\n const { SdkContext } = loadWasm();\n let context = SdkContext.fromIssuerSecret(secret, [...extraRootHexes]);\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n return context;\n}\n\nexport function importSessionFromWire(warrant: string, holderKey: Uint8Array): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromWire(warrant, holderKey);\n}\n\nexport function importSessionFromParts(\n payloadHex: string,\n signatureHex: string,\n holderKey: Uint8Array,\n): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromParts(payloadHex, signatureHex, holderKey);\n}\n\nexport function importSessionFromChain(parts: unknown, holderKey: Uint8Array): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromChain(parts, holderKey);\n}\n\nexport function inspectWarrant(wire: string): WasmInspect {\n return loadWasm().sdkInspectWarrant(wire);\n}\n\nexport function inspectParts(payloadHex: string, signatureHex: string): WasmInspect {\n return loadWasm().sdkInspectParts(payloadHex, signatureHex);\n}\n\n/** Hex public key for a 32-byte holder secret. Ed25519, derived in Rust. */\nexport function publicKeyHexFromHolderKey(holderSecret: Uint8Array): string {\n return loadWasm().sdkPublicKeyFromHolderKey(holderSecret);\n}\n\nexport type ApprovalRequirementStatus = \"not_gated\" | \"exempt\" | \"required\" | \"denied\";\n\nexport type ApprovalRequirement = {\n status: ApprovalRequirementStatus;\n tool: string;\n kind?: \"whole_tool\" | \"argument\";\n argument?: string;\n arguments: string[];\n message?: string;\n code?: string;\n reason?: string;\n};\n\nexport type ApprovalGateInspection = {\n kind: \"none\" | \"whole_tool\" | \"conditional\" | \"unknown\";\n tool: string;\n arguments: string[];\n message?: string;\n};\n\nfunction loadApprovalWasm() {\n return loadWasm();\n}\n\nfunction throwIfGateError(error: string | undefined): void {\n if (error) {\n throw new TenuoConfigurationError(error);\n }\n}\n\n/**\n * Typed preflight of a warrant's approval gates for `(tool, args)`.\n *\n * Capability constraints are checked first. `denied` means the authorizer\n * will refuse the call — do not collect approval. Malformed encodings throw\n * (fail-closed).\n */\nexport function approvalRequirement(\n warrantB64: string,\n tool: string,\n args: Record<string, unknown>,\n): ApprovalRequirement {\n const result = loadApprovalWasm().approval_requirement(warrantB64, tool, args);\n throwIfGateError(result.error);\n return result;\n}\n\n/** Inspect how a warrant gates `tool`, without evaluating arguments. */\nexport function inspectApprovalGate(warrantB64: string, tool: string): ApprovalGateInspection {\n const result = loadApprovalWasm().inspect_approval_gate(warrantB64, tool);\n throwIfGateError(result.error);\n return result;\n}\n\n/**\n * Gate-map-only boolean. Does not run capability checks, so split-view\n * callers (PoP args vs constraint args) still see a firing gate. Prefer\n * {@link approvalRequirement} when the caller must distinguish `denied`.\n */\nexport function evaluateApprovalGates(\n warrantB64: string,\n tool: string,\n args: Record<string, unknown>,\n): boolean {\n const result = loadApprovalWasm().evaluate_approval_gates(warrantB64, tool, args);\n throwIfGateError(result.error);\n return result.approval_required;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"wasm.js","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from \"node:module\";\nimport { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { TenuoConfigurationError } from \"./errors.ts\";\nimport type { TenuoErrorCode } from \"./api.ts\";\n\nexport type WasmDecision = {\n outcome: \"allow\" | \"deny\" | \"approval_required\";\n code?: TenuoErrorCode;\n field?: string;\n message?: string;\n args?: Record<string, unknown>;\n tool?: string;\n required?: number;\n received?: number;\n receipt?: string;\n};\n\nexport type WasmInspect = {\n payload_hex: string;\n signature_hex: string;\n id: string;\n};\n\nexport type WasmReceipt = {\n authentic: true;\n /** Hex key the receipt is signed under — resolve against your authorizer set. */\n signer_key: string;\n outcome: \"allow\" | \"deny\";\n action: string;\n decision_code?: string;\n request_id: string;\n /** Version of the revocation list in force, when it carried one. */\n srl_version?: number;\n /**\n * SHA-256 (hex) of the revocation list bytes in force at decision time.\n * Absent means no revocation data was loaded — a different claim from a\n * loaded list that revoked nothing.\n */\n srl_hash?: string;\n /**\n * SHA-256 (hex) commitment to the canonical invocation this decision was\n * made over. Absent when the arguments could not be canonicalized — never\n * zero-filled, so absence is a claim rather than a value.\n */\n request_hash?: string;\n /** SHA-256 (hex) of the host ceiling applied to this decision. */\n policy_definition_hash?: string;\n /**\n * SHA-256 (hex) of the previous receipt from this signer. Absent on the\n * first receipt, or when the deployment does not chain. A broken link means\n * a receipt was removed from the stream.\n */\n prev_receipt_hash?: string;\n /** SHA-256 (hex) of the trusted root set in force at decision time. */\n trusted_roots_hash?: string;\n};\n\nexport type WasmReceiptChain = {\n signer_key: string;\n outcome: \"allow\" | \"deny\";\n decision_code?: string;\n timestamp: number;\n /** The embedded chain verifies to a supplied root at the decision instant. */\n chain_valid: boolean;\n /** Canonical error name when it does not. */\n chain_error?: string;\n /**\n * Deny receipts only: the chain failure matches the stated decision_code,\n * so the embedded authority independently corroborates the refusal.\n */\n corroborates_denial?: boolean;\n root_issuer?: string;\n leaf_holder?: string;\n};\n\nexport type WasmSession = object;\n\n/** Mirrors `SessionInfoDto` in tenuo-wasm. Snake case is the WASM boundary. */\nexport type WasmSessionInfo = {\n kind: \"execution\" | \"issuer\";\n holder_public_key: string;\n root_public_key: string;\n depth: number;\n max_depth: number;\n terminal: boolean;\n expires_at: number;\n tools: string[];\n warrant_ids: string[];\n can_authorize: boolean;\n clearance?: number;\n session_id?: string;\n agent_id?: string;\n issuable_tools?: string[];\n max_issue_depth?: number;\n required_approvers?: string[];\n min_approvals?: number;\n approval_gated_tools: string[];\n};\n\n/** Security limits exported by tenuo-core; TypeScript must not redefine them. */\nexport type WasmProtocolLimits = {\n max_delegation_depth: number;\n max_warrant_ttl_seconds: number;\n};\n\n/** Mirrors `NarrowOptions` in tenuo-wasm. Unknown keys are rejected there. */\nexport type WasmNarrowOptions = {\n holder?: string;\n ttlSeconds?: number;\n terminal?: boolean;\n maxDepth?: number;\n clearance?: number | string;\n agentId?: string;\n addApprovers?: string[];\n minApprovals?: number;\n};\n\nexport type WasmRequireApproval = {\n approvers: string[];\n min: number;\n tools?: string[];\n gates?: Record<string, { message?: string; args?: Record<string, unknown> }>;\n};\n\n/** Mirrors `MintOptions` in tenuo-wasm. */\nexport type WasmMintOptions = {\n kind?: \"execution\" | \"issuer\";\n allow?: unknown;\n ttlSeconds?: number;\n holder?: string;\n maxDepth?: number;\n clearance?: number | string;\n sessionId?: string;\n agentId?: string;\n requireApproval?: WasmRequireApproval;\n issuableTools?: string[];\n constraintBounds?: unknown;\n maxIssueDepth?: number;\n};\n\n/** Mirrors `IssueOptions` in tenuo-wasm. */\nexport type WasmIssueOptions = {\n allow: unknown;\n holder: string;\n ttlSeconds?: number;\n maxDepth?: number;\n clearance?: number | string;\n sessionId?: string;\n agentId?: string;\n requireApproval?: { approvers: string[]; min: number };\n};\n\nexport type WasmExplainField = {\n field: string;\n kind: string;\n constraint: unknown;\n value?: unknown;\n satisfied: boolean;\n reason_code?: string;\n reason?: string;\n};\n\nexport type WasmExplain = {\n tool: string;\n kind: \"execution\" | \"issuer\";\n outcome: \"allow\" | \"deny\";\n code?: TenuoErrorCode;\n field?: string;\n message?: string;\n tool_granted: boolean;\n fields: WasmExplainField[];\n unknown_fields: string[];\n missing_fields: string[];\n expired: boolean;\n expires_at: number;\n chain_valid: boolean;\n chain_error?: TenuoErrorCode;\n};\n\nexport type WasmApprovalRequest = {\n request_id: string;\n warrant_id: string;\n tool: string;\n args: Record<string, unknown>;\n request_hash: string;\n holder_public_key: string;\n required_approvers: string[];\n min_approvals: number;\n warrant_expires_at: number;\n created_at: number;\n message: string;\n};\n\nexport type WasmAttestation = {\n version: number;\n canonicalization: string;\n warrant_id: string;\n tool: string;\n request_hash: string;\n holder_key_hex: string;\n args_canonical_cbor_b64: string;\n signer_key_hex: string;\n signature_b64: string;\n};\n\nexport type WasmApprovalInfo = {\n approver_public_key: string;\n request_hash: string;\n nonce: string;\n external_id: string;\n approved_at: number;\n expires_at: number;\n expired: boolean;\n signature_valid: boolean;\n error?: string;\n};\n\nexport type WasmSrlInfo = {\n version: number;\n issued_at: number;\n issuer_public_key: string;\n revoked_ids: string[];\n signature_valid: boolean;\n};\n\nexport type WasmContext = {\n withReceiptSigner(secret: Uint8Array): WasmContext;\n mint(\n allow: unknown,\n ttlSeconds: number,\n requireApproval?: unknown,\n holderHex?: string,\n maxDepth?: number,\n ): WasmSession;\n mintExtended(options: WasmMintOptions): WasmSession;\n narrow(session: WasmSession, allow: unknown, options?: WasmNarrowOptions): WasmSession;\n issue(issuer: WasmSession, options: WasmIssueOptions): WasmSession;\n issuerPublicKey(): string;\n explain(session: WasmSession, tool: string, args: unknown): WasmExplain;\n approvalRequest(session: WasmSession, tool: string, args: unknown): WasmApprovalRequest;\n approvalContextAttestation(session: WasmSession, tool: string, args: unknown): WasmAttestation;\n signRevocationListVersioned(ids: string[], version?: number): string;\n authorize(\n session: WasmSession,\n tool: string,\n args: unknown,\n approvals?: unknown,\n toolAllow?: unknown,\n requestId?: string,\n ): WasmDecision;\n authorizeAsOf(\n session: WasmSession,\n tool: string,\n args: unknown,\n asOf: number,\n approvals?: unknown,\n toolAllow?: unknown,\n ): WasmDecision;\n loadRevocationList(srl: string): void;\n signRevocationList(ids: string[]): string;\n signPop(session: WasmSession, tool: string, args: unknown): string;\n signMeta(\n session: WasmSession,\n tool: string,\n argsJson: string,\n timestamp: number,\n approvals?: unknown,\n ): { warrant: string; signature: string; approvals?: string[] };\n /** Holder proof only; does not authorize execution. */\n verifyMetaPop(\n warrant: string,\n signature: string,\n tool: string,\n argsJson: string,\n timestamp: number,\n ): boolean;\n /** Compatibility alias for verifyMetaPop. */\n verifyMeta(\n warrant: string,\n signature: string,\n tool: string,\n argsJson: string,\n timestamp: number,\n ): boolean;\n authorizePresented(\n warrants: unknown,\n tool: string,\n args: unknown,\n pop: string,\n approvals?: unknown,\n toolAllow?: unknown,\n requestId?: string,\n ): WasmDecision;\n};\n\ntype Generated = {\n SdkContext: {\n new (): WasmContext;\n fromTrustedRoots(roots: string[]): WasmContext;\n fromIssuerSecret(secret: Uint8Array, extraRoots?: string[]): WasmContext;\n };\n SdkSession: {\n fromWire(warrant: string, holder: Uint8Array): WasmSession;\n fromParts(payloadHex: string, signatureHex: string, holder: Uint8Array): WasmSession;\n fromChain(parts: unknown, holder: Uint8Array): WasmSession;\n };\n sdkInspectWarrant(wire: string): WasmInspect;\n sdkInspectParts(payloadHex: string, signatureHex: string): WasmInspect;\n sdkProtocolLimits(): WasmProtocolLimits;\n sdkPublicKeyFromHolderKey(holderSecret: Uint8Array): string;\n sdkSignApproval(\n session: WasmSession,\n tool: string,\n args: unknown,\n approverSecret: Uint8Array,\n externalId: string,\n asOf?: number,\n ): string;\n sdkSignApprovalForRequest(\n requestHashHex: string,\n approverSecret: Uint8Array,\n externalId: string,\n ttlSeconds?: number,\n warrantExpiresAt?: number,\n ): string;\n sdkInspectApproval(envelope: string | Uint8Array): WasmApprovalInfo;\n sdkSignRevocationList(ids: string[], issuerSecret: Uint8Array): string;\n sdkSignRevocationListVersioned(ids: string[], version: number | undefined, issuerSecret: Uint8Array): string;\n sdkSignPublishedRevocationList(ids: string[], version: number, issuerSecret: Uint8Array): string;\n sdkInspectRevocationList(wire: string): WasmSrlInfo;\n sdkVerifyReceipt(wire: string): WasmReceipt;\n sdkVerifyReceiptChain(wire: string, roots: string[]): WasmReceiptChain;\n approval_requirement(\n warrantB64: string,\n tool: string,\n args: unknown,\n ): ApprovalRequirement & { error?: string };\n inspect_approval_gate(\n warrantB64: string,\n tool: string,\n ): ApprovalGateInspection & { error?: string };\n evaluate_approval_gates(\n warrantB64: string,\n tool: string,\n args: unknown,\n ): { approval_required: boolean; tool: string; error?: string };\n parse_strict_json(jsonText: string): void;\n};\n\nlet loaded: Generated | undefined;\n\nfunction generatedPath(): string {\n const here = dirname(fileURLToPath(import.meta.url));\n return join(here, \"generated\", \"tenuo_wasm.js\");\n}\n\nexport function wasmAvailable(): boolean {\n return existsSync(generatedPath());\n}\n\nconst WASM_LOAD_HINT =\n \"WASM core is missing from this @tenuo/core install. @tenuo/core is Node 20+ only (not a bundler target). If this is Next.js/webpack, set serverExternalPackages: ['@tenuo/core']. Do not run wasm-pack in the consuming app.\";\n\nexport function loadWasm(): Generated {\n if (loaded) {\n return loaded;\n }\n const path = generatedPath();\n if (!existsSync(path)) {\n throw new TenuoConfigurationError(WASM_LOAD_HINT, \"TENUO_NOT_READY\");\n }\n try {\n const require = createRequire(import.meta.url);\n loaded = require(path) as Generated;\n return loaded;\n } catch (error) {\n const wrapped = new TenuoConfigurationError(WASM_LOAD_HINT, \"TENUO_NOT_READY\");\n wrapped.cause = error;\n throw wrapped;\n }\n}\n\nexport function createDevContext(receiptSigner?: Uint8Array): WasmContext {\n const { SdkContext } = loadWasm();\n let context: WasmContext = new SdkContext();\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n return context;\n}\n\nexport function protocolLimits(): WasmProtocolLimits {\n return loadWasm().sdkProtocolLimits();\n}\n\nexport function createVerifierContext(\n rootHexes: readonly string[],\n revocationList?: string,\n receiptSigner?: Uint8Array,\n): WasmContext {\n const { SdkContext } = loadWasm();\n let context = SdkContext.fromTrustedRoots([...rootHexes]);\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n if (revocationList !== undefined && revocationList.length > 0) {\n context.loadRevocationList(revocationList);\n }\n return context;\n}\n\nexport function createIssuerContext(\n secret: Uint8Array,\n extraRootHexes: readonly string[],\n receiptSigner?: Uint8Array,\n): WasmContext {\n const { SdkContext } = loadWasm();\n let context = SdkContext.fromIssuerSecret(secret, [...extraRootHexes]);\n if (receiptSigner !== undefined) {\n context = context.withReceiptSigner(receiptSigner);\n }\n return context;\n}\n\nexport function importSessionFromWire(warrant: string, holderKey: Uint8Array): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromWire(warrant, holderKey);\n}\n\nexport function importSessionFromParts(\n payloadHex: string,\n signatureHex: string,\n holderKey: Uint8Array,\n): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromParts(payloadHex, signatureHex, holderKey);\n}\n\nexport function importSessionFromChain(parts: unknown, holderKey: Uint8Array): WasmSession {\n const { SdkSession } = loadWasm();\n return SdkSession.fromChain(parts, holderKey);\n}\n\nexport function inspectWarrant(wire: string): WasmInspect {\n return loadWasm().sdkInspectWarrant(wire);\n}\n\nexport function inspectParts(payloadHex: string, signatureHex: string): WasmInspect {\n return loadWasm().sdkInspectParts(payloadHex, signatureHex);\n}\n\n/** Hex public key for a 32-byte holder secret. Ed25519, derived in Rust. */\nexport function publicKeyHexFromHolderKey(holderSecret: Uint8Array): string {\n return loadWasm().sdkPublicKeyFromHolderKey(holderSecret);\n}\n\nexport type ApprovalRequirementStatus = \"not_gated\" | \"exempt\" | \"required\" | \"denied\";\n\nexport type ApprovalRequirement = {\n status: ApprovalRequirementStatus;\n tool: string;\n kind?: \"whole_tool\" | \"argument\";\n argument?: string;\n arguments: string[];\n message?: string;\n code?: string;\n reason?: string;\n};\n\nexport type ApprovalGateInspection = {\n kind: \"none\" | \"whole_tool\" | \"conditional\" | \"unknown\";\n tool: string;\n arguments: string[];\n message?: string;\n};\n\nfunction loadApprovalWasm() {\n return loadWasm();\n}\n\nfunction throwIfGateError(error: string | undefined): void {\n if (error) {\n throw new TenuoConfigurationError(error);\n }\n}\n\n/**\n * Parse JSON text and reject a repeated key in any object.\n *\n * `verify()` receives an object the host already parsed. A duplicate key is\n * gone by then. Call this while the text is still available. After the check,\n * the value is `JSON.parse` of the original text, so each key is an own data\n * property and `null` stays `null`.\n */\nexport function parseStrictJson(text: string): unknown {\n loadWasm().parse_strict_json(text);\n return JSON.parse(text);\n}\n\n/**\n * Typed preflight of a warrant's approval gates for `(tool, args)`.\n *\n * Capability constraints are checked first. `denied` means the authorizer\n * will refuse the call — do not collect approval. Malformed encodings throw\n * (fail-closed).\n */\nexport function approvalRequirement(\n warrantB64: string,\n tool: string,\n args: Record<string, unknown>,\n): ApprovalRequirement {\n const result = loadApprovalWasm().approval_requirement(warrantB64, tool, args);\n throwIfGateError(result.error);\n return result;\n}\n\n/** Inspect how a warrant gates `tool`, without evaluating arguments. */\nexport function inspectApprovalGate(warrantB64: string, tool: string): ApprovalGateInspection {\n const result = loadApprovalWasm().inspect_approval_gate(warrantB64, tool);\n throwIfGateError(result.error);\n return result;\n}\n\n/**\n * Gate-map-only boolean. Does not run capability checks, so split-view\n * callers (PoP args vs constraint args) still see a firing gate. Prefer\n * {@link approvalRequirement} when the caller must distinguish `denied`.\n */\nexport function evaluateApprovalGates(\n warrantB64: string,\n tool: string,\n args: Record<string, unknown>,\n): boolean {\n const result = loadApprovalWasm().evaluate_approval_gates(warrantB64, tool, args);\n throwIfGateError(result.error);\n return result.approval_required;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tenuo/core",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.3-beta.0",
|
|
4
|
+
"description": "Task-scoped authorization for AI agents in TypeScript: signed warrants limit which tools an agent can call and with which arguments, verified by the Tenuo Rust core compiled to WASM (beta).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Tenuo Contributors",
|
|
7
7
|
"homepage": "https://github.com/tenuo-ai/tenuo/tree/main/tenuo-ts/packages/core",
|
|
@@ -16,10 +16,17 @@
|
|
|
16
16
|
"keywords": [
|
|
17
17
|
"tenuo",
|
|
18
18
|
"authorization",
|
|
19
|
-
"agents",
|
|
19
|
+
"ai-agents",
|
|
20
|
+
"agent-security",
|
|
21
|
+
"llm-security",
|
|
22
|
+
"access-control",
|
|
23
|
+
"capabilities",
|
|
24
|
+
"warrants",
|
|
25
|
+
"delegation",
|
|
26
|
+
"prompt-injection",
|
|
20
27
|
"mcp",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
28
|
+
"model-context-protocol",
|
|
29
|
+
"wasm"
|
|
23
30
|
],
|
|
24
31
|
"publishConfig": {
|
|
25
32
|
"access": "public"
|