@tenuo/core 0.3.0-beta.0 → 0.3.2-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/dist/api.d.ts +12 -3
- package/dist/api.js.map +1 -1
- package/dist/build-info.json +8 -0
- package/dist/client.js +10 -4
- package/dist/client.js.map +1 -1
- package/dist/constraints.d.ts +25 -0
- package/dist/constraints.js +45 -0
- package/dist/constraints.js.map +1 -1
- package/dist/generated/tenuo_wasm.d.ts +27 -1
- package/dist/generated/tenuo_wasm.js +93 -1
- package/dist/generated/tenuo_wasm_bg.wasm +0 -0
- package/dist/generated/tenuo_wasm_bg.wasm.d.ts +4 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +33 -65
- package/dist/mcp.js.map +1 -1
- package/dist/wasm.d.ts +20 -0
- package/dist/wasm.js +12 -0
- package/dist/wasm.js.map +1 -1
- package/package.json +13 -6
package/dist/constraints.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constraints.js","sourceRoot":"","sources":["../src/constraints.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AllConstraint,\n AnyOfConstraint,\n CelConstraint,\n CidrConstraint,\n ConstraintExpr,\n ContainsConstraint,\n EmailConstraint,\n ExactConstraint,\n MaxConstraint,\n MinConstraint,\n NotConstraint,\n NotOneOfConstraint,\n OneOfConstraint,\n PatternConstraint,\n RangeConstraint,\n RegexConstraint,\n ShlexConstraint,\n SubsetConstraint,\n UnderConstraint,\n UrlPatternConstraint,\n UrlSafeConstraint,\n WildcardConstraint,\n} from \"./api.ts\";\nimport { TenuoConfigurationError } from \"./errors.ts\";\n\n/**\n * Constraint builders. These produce plain marker objects; every one is\n * evaluated by the Rust core, never in TypeScript. The set matches the\n * Python SDK and the core `Constraint` enum one for one. Builders that\n * validate their input throw `TenuoConfigurationError` at the call site.\n * Deeper checks, such as regex syntax, run in the core when `session()`\n * compiles the policy. Nothing here makes an authorization decision.\n */\n\n/** Directory prefix. Evaluated in core as Subpath — not a string prefix check in TS. */\nexport function under(\n root: string,\n options?: { readonly caseSensitive?: boolean; readonly allowEqual?: boolean },\n): UnderConstraint {\n if (!root.startsWith(\"/\")) {\n throw new TenuoConfigurationError(\"tenuo.under() expects an absolute path (start with /)\");\n }\n const out: { kind: \"under\"; root: string; caseSensitive?: boolean; allowEqual?: boolean } = {\n kind: \"under\",\n root,\n };\n if (options?.caseSensitive !== undefined) {\n out.caseSensitive = options.caseSensitive;\n }\n if (options?.allowEqual !== undefined) {\n out.allowEqual = options.allowEqual;\n }\n return out;\n}\n\nexport function email(options: { domain: string }): EmailConstraint {\n return { kind: \"email\", domain: options.domain };\n}\n\nexport function max(value: number): MaxConstraint {\n if (!Number.isFinite(value)) {\n throw new TenuoConfigurationError(\"tenuo.max() requires a finite number\");\n }\n return { kind: \"max\", value };\n}\n\nexport function min(value: number): MinConstraint {\n if (!Number.isFinite(value)) {\n throw new TenuoConfigurationError(\"tenuo.min() requires a finite number\");\n }\n return { kind: \"min\", value };\n}\n\n/** Numeric interval. Bounds are inclusive unless `minExclusive` / `maxExclusive`. */\nexport function range(options: {\n readonly min?: number;\n readonly max?: number;\n readonly minExclusive?: boolean;\n readonly maxExclusive?: boolean;\n}): RangeConstraint {\n if (options.min === undefined && options.max === undefined) {\n throw new TenuoConfigurationError(\"tenuo.range() requires min, max, or both\");\n }\n for (const bound of [options.min, options.max]) {\n if (bound !== undefined && !Number.isFinite(bound)) {\n throw new TenuoConfigurationError(\"tenuo.range() bounds must be finite numbers\");\n }\n }\n if (options.min !== undefined && options.max !== undefined && options.min > options.max) {\n throw new TenuoConfigurationError(\"tenuo.range() min must not exceed max\");\n }\n const out: {\n kind: \"range\";\n min?: number;\n max?: number;\n minExclusive?: boolean;\n maxExclusive?: boolean;\n } = { kind: \"range\" };\n if (options.min !== undefined) {\n out.min = options.min;\n }\n if (options.max !== undefined) {\n out.max = options.max;\n }\n if (options.minExclusive === true) {\n out.minExclusive = true;\n }\n if (options.maxExclusive === true) {\n out.maxExclusive = true;\n }\n return out;\n}\n\nexport function oneOf(values: readonly string[]): OneOfConstraint {\n if (values.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.oneOf() requires at least one value\");\n }\n return { kind: \"oneOf\", values };\n}\n\n/** Any value except these. */\nexport function notOneOf(values: readonly string[]): NotOneOfConstraint {\n if (values.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.notOneOf() requires at least one value\");\n }\n return { kind: \"notOneOf\", values };\n}\n\nexport function pattern(pattern: string): PatternConstraint {\n if (pattern.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.pattern() requires a non-empty pattern\");\n }\n return { kind: \"pattern\", pattern };\n}\n\n/** Regular expression, compiled and evaluated in core. */\nexport function regex(source: string): RegexConstraint {\n if (source.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.regex() requires a non-empty expression\");\n }\n return { kind: \"regex\", source };\n}\n\nexport function exact(value: string | number | boolean): ExactConstraint {\n return { kind: \"exact\", value };\n}\n\n/** Any value at all. Name it in a zero-trust policy to allow an argument without constraining it. */\nexport function wildcard(): WildcardConstraint {\n return { kind: \"wildcard\" };\n}\n\n/** IP address inside a network, e.g. `cidr(\"10.0.0.0/8\")`. */\nexport function cidr(network: string): CidrConstraint {\n if (!network.includes(\"/\")) {\n throw new TenuoConfigurationError(\"tenuo.cidr() expects CIDR notation like 10.0.0.0/8\");\n }\n return { kind: \"cidr\", network };\n}\n\n/** URL glob, e.g. `urlPattern(\"https://*.example.com/api/*\")`. Parsed as a URL, not a string. */\nexport function urlPattern(pattern: string): UrlPatternConstraint {\n if (pattern.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.urlPattern() requires a non-empty pattern\");\n }\n return { kind: \"urlPattern\", pattern };\n}\n\n/**\n * SSRF-aware URL check: http/https only by default, private and link-local\n * hosts rejected, optional allow and deny domain lists (`*.example.com`).\n */\nexport function urlSafe(options?: {\n readonly schemes?: readonly string[];\n readonly allowDomains?: readonly string[];\n readonly denyDomains?: readonly string[];\n}): UrlSafeConstraint {\n const out: {\n kind: \"urlSafe\";\n schemes?: readonly string[];\n allowDomains?: readonly string[];\n denyDomains?: readonly string[];\n } = { kind: \"urlSafe\" };\n if (options?.schemes !== undefined) {\n out.schemes = options.schemes;\n }\n if (options?.allowDomains !== undefined) {\n out.allowDomains = options.allowDomains;\n }\n if (options?.denyDomains !== undefined) {\n out.denyDomains = options.denyDomains;\n }\n return out;\n}\n\n/** Shell command whose first word must be one of `allow`. Parsed with shell quoting rules in core. */\nexport function shlex(allow: readonly string[]): ShlexConstraint {\n if (allow.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.shlex() requires at least one allowed command\");\n }\n return { kind: \"shlex\", allow };\n}\n\n/** List argument that must include every one of these values. */\nexport function contains(values: readonly (string | number | boolean)[]): ContainsConstraint {\n if (values.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.contains() requires at least one value\");\n }\n return { kind: \"contains\", values };\n}\n\n/** List argument whose every element must be one of these values. */\nexport function subset(values: readonly (string | number | boolean)[]): SubsetConstraint {\n if (values.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.subset() requires at least one value\");\n }\n return { kind: \"subset\", values };\n}\n\n/** Satisfied when at least one inner constraint is. */\nexport function anyOf(constraints: readonly ConstraintExpr[]): AnyOfConstraint {\n if (constraints.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.anyOf() requires at least one constraint\");\n }\n return { kind: \"anyOf\", constraints };\n}\n\n/** Satisfied only when every inner constraint is. */\nexport function all(constraints: readonly ConstraintExpr[]): AllConstraint {\n if (constraints.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.all() requires at least one constraint\");\n }\n return { kind: \"all\", constraints };\n}\n\n/** Satisfied when the inner constraint is not. Delegation cannot narrow a `not`; prefer `notOneOf`. */\nexport function not(constraint: ConstraintExpr): NotConstraint {\n return { kind: \"not\", constraint };\n}\n\n/** Common Expression Language predicate over the argument value, evaluated in core. */\nexport function cel(expression: string): CelConstraint {\n if (expression.trim().length === 0) {\n throw new TenuoConfigurationError(\"tenuo.cel() requires a non-empty expression\");\n }\n return { kind: \"cel\", expression };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"constraints.js","sourceRoot":"","sources":["../src/constraints.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AllConstraint,\n AnyOfConstraint,\n CelConstraint,\n CidrConstraint,\n ConstraintExpr,\n ContainsConstraint,\n EmailConstraint,\n ExactConstraint,\n MaxConstraint,\n MinConstraint,\n NotConstraint,\n NotOneOfConstraint,\n OneOfConstraint,\n PatternConstraint,\n RangeConstraint,\n RegexConstraint,\n ShlexConstraint,\n SubsetConstraint,\n UnderConstraint,\n UrlPatternConstraint,\n UrlSafeConstraint,\n WildcardConstraint,\n} from \"./api.ts\";\nimport { TenuoConfigurationError } from \"./errors.ts\";\n\n/**\n * Builders throw on a misspelled option instead of dropping it: an option\n * that vanishes silently (`urlSafe({ domains })`) widens authority. The core\n * applies the same rule to raw constraint objects when the policy compiles.\n */\nfunction rejectUnknownOptions(\n builder: string,\n options: unknown,\n allowed: readonly string[],\n): void {\n if (options === undefined || options === null) {\n return;\n }\n if (typeof options !== \"object\" || Array.isArray(options)) {\n throw new TenuoConfigurationError(`tenuo.${builder}() expects an options object`);\n }\n const unknown = Object.keys(options).find((key) => !allowed.includes(key));\n if (unknown !== undefined) {\n throw new TenuoConfigurationError(\n `tenuo.${builder}() received unknown option \"${unknown}\"; allowed options: ${allowed.join(\", \")}`,\n );\n }\n}\n\n/**\n * Constraint builders. These produce plain marker objects; every one is\n * evaluated by the Rust core, never in TypeScript. The set matches the\n * Python SDK and the core `Constraint` enum one for one. Builders that\n * validate their input throw `TenuoConfigurationError` at the call site.\n * Deeper checks, such as regex syntax, run in the core when `session()`\n * compiles the policy. Nothing here makes an authorization decision.\n */\n\n/** Directory prefix. Evaluated in core as Subpath — not a string prefix check in TS. */\nexport function under(\n root: string,\n options?: { readonly caseSensitive?: boolean; readonly allowEqual?: boolean },\n): UnderConstraint {\n rejectUnknownOptions(\"under\", options, [\"caseSensitive\", \"allowEqual\"]);\n if (!root.startsWith(\"/\")) {\n throw new TenuoConfigurationError(\"tenuo.under() expects an absolute path (start with /)\");\n }\n const out: { kind: \"under\"; root: string; caseSensitive?: boolean; allowEqual?: boolean } = {\n kind: \"under\",\n root,\n };\n if (options?.caseSensitive !== undefined) {\n out.caseSensitive = options.caseSensitive;\n }\n if (options?.allowEqual !== undefined) {\n out.allowEqual = options.allowEqual;\n }\n return out;\n}\n\nexport function email(options: { domain: string }): EmailConstraint {\n rejectUnknownOptions(\"email\", options, [\"domain\"]);\n return { kind: \"email\", domain: options.domain };\n}\n\nexport function max(value: number): MaxConstraint {\n if (!Number.isFinite(value)) {\n throw new TenuoConfigurationError(\"tenuo.max() requires a finite number\");\n }\n return { kind: \"max\", value };\n}\n\nexport function min(value: number): MinConstraint {\n if (!Number.isFinite(value)) {\n throw new TenuoConfigurationError(\"tenuo.min() requires a finite number\");\n }\n return { kind: \"min\", value };\n}\n\n/** Numeric interval. Bounds are inclusive unless `minExclusive` / `maxExclusive`. */\nexport function range(options: {\n readonly min?: number;\n readonly max?: number;\n readonly minExclusive?: boolean;\n readonly maxExclusive?: boolean;\n}): RangeConstraint {\n rejectUnknownOptions(\"range\", options, [\"min\", \"max\", \"minExclusive\", \"maxExclusive\"]);\n if (options.min === undefined && options.max === undefined) {\n throw new TenuoConfigurationError(\"tenuo.range() requires min, max, or both\");\n }\n for (const bound of [options.min, options.max]) {\n if (bound !== undefined && !Number.isFinite(bound)) {\n throw new TenuoConfigurationError(\"tenuo.range() bounds must be finite numbers\");\n }\n }\n if (options.min !== undefined && options.max !== undefined && options.min > options.max) {\n throw new TenuoConfigurationError(\"tenuo.range() min must not exceed max\");\n }\n const out: {\n kind: \"range\";\n min?: number;\n max?: number;\n minExclusive?: boolean;\n maxExclusive?: boolean;\n } = { kind: \"range\" };\n if (options.min !== undefined) {\n out.min = options.min;\n }\n if (options.max !== undefined) {\n out.max = options.max;\n }\n if (options.minExclusive === true) {\n out.minExclusive = true;\n }\n if (options.maxExclusive === true) {\n out.maxExclusive = true;\n }\n return out;\n}\n\nexport function oneOf(values: readonly string[]): OneOfConstraint {\n if (values.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.oneOf() requires at least one value\");\n }\n return { kind: \"oneOf\", values };\n}\n\n/** Any value except these. */\nexport function notOneOf(values: readonly string[]): NotOneOfConstraint {\n if (values.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.notOneOf() requires at least one value\");\n }\n return { kind: \"notOneOf\", values };\n}\n\n/**\n * Generic string glob. `*` matches `/`; this is not path containment.\n * For filesystem arguments, use `pathGlob(root, glob)`.\n */\nexport function pattern(pattern: string): PatternConstraint {\n if (pattern.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.pattern() requires a non-empty pattern\");\n }\n return { kind: \"pattern\", pattern };\n}\n\n/**\n * A traversal-safe filesystem glob: the value must stay under `root` and\n * match `glob`.\n *\n * The glob is tested against the whole path, not against the part below\n * `root`, so it matches at any depth:\n *\n * ```ts\n * pathGlob(\"/workspace\", \"*.json\");\n * // /workspace/reports/q3.json allowed\n * // /workspace/secrets.env denied (glob)\n * // /etc/passwd.json denied (root)\n * ```\n *\n * A delegatee can narrow this to a tighter `pathGlob`, or to an `exact()`\n * path the parent already admits.\n */\nexport function pathGlob(\n root: string,\n glob: string,\n options?: { readonly caseSensitive?: boolean; readonly allowEqual?: boolean },\n): AllConstraint {\n return all([under(root, options), pattern(glob)]);\n}\n\n/** Regular expression, compiled and evaluated in core. */\nexport function regex(source: string): RegexConstraint {\n if (source.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.regex() requires a non-empty expression\");\n }\n return { kind: \"regex\", source };\n}\n\nexport function exact(value: string | number | boolean): ExactConstraint {\n return { kind: \"exact\", value };\n}\n\n/** Any value at all. Name it in a zero-trust policy to allow an argument without constraining it. */\nexport function wildcard(): WildcardConstraint {\n return { kind: \"wildcard\" };\n}\n\n/** IP address inside a network, e.g. `cidr(\"10.0.0.0/8\")`. */\nexport function cidr(network: string): CidrConstraint {\n if (!network.includes(\"/\")) {\n throw new TenuoConfigurationError(\"tenuo.cidr() expects CIDR notation like 10.0.0.0/8\");\n }\n return { kind: \"cidr\", network };\n}\n\n/** URL glob, e.g. `urlPattern(\"https://*.example.com/api/*\")`. Parsed as a URL, not a string. */\nexport function urlPattern(pattern: string): UrlPatternConstraint {\n if (pattern.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.urlPattern() requires a non-empty pattern\");\n }\n return { kind: \"urlPattern\", pattern };\n}\n\n/**\n * SSRF-aware URL check: http/https only by default, private and link-local\n * hosts rejected, optional allow and deny domain lists (`*.example.com`).\n */\nexport function urlSafe(options?: {\n readonly schemes?: readonly string[];\n readonly allowDomains?: readonly string[];\n readonly denyDomains?: readonly string[];\n}): UrlSafeConstraint {\n rejectUnknownOptions(\"urlSafe\", options, [\"schemes\", \"allowDomains\", \"denyDomains\"]);\n const out: {\n kind: \"urlSafe\";\n schemes?: readonly string[];\n allowDomains?: readonly string[];\n denyDomains?: readonly string[];\n } = { kind: \"urlSafe\" };\n if (options?.schemes !== undefined) {\n out.schemes = options.schemes;\n }\n if (options?.allowDomains !== undefined) {\n out.allowDomains = options.allowDomains;\n }\n if (options?.denyDomains !== undefined) {\n out.denyDomains = options.denyDomains;\n }\n return out;\n}\n\n/** Shell command whose first word must be one of `allow`. Parsed with shell quoting rules in core. */\nexport function shlex(allow: readonly string[]): ShlexConstraint {\n if (allow.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.shlex() requires at least one allowed command\");\n }\n return { kind: \"shlex\", allow };\n}\n\n/** List argument that must include every one of these values. */\nexport function contains(values: readonly (string | number | boolean)[]): ContainsConstraint {\n if (values.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.contains() requires at least one value\");\n }\n return { kind: \"contains\", values };\n}\n\n/** List argument whose every element must be one of these values. */\nexport function subset(values: readonly (string | number | boolean)[]): SubsetConstraint {\n if (values.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.subset() requires at least one value\");\n }\n return { kind: \"subset\", values };\n}\n\n/** Satisfied when at least one inner constraint is. */\nexport function anyOf(constraints: readonly ConstraintExpr[]): AnyOfConstraint {\n if (constraints.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.anyOf() requires at least one constraint\");\n }\n return { kind: \"anyOf\", constraints };\n}\n\n/** Satisfied only when every inner constraint is. */\nexport function all(constraints: readonly ConstraintExpr[]): AllConstraint {\n if (constraints.length === 0) {\n throw new TenuoConfigurationError(\"tenuo.all() requires at least one constraint\");\n }\n return { kind: \"all\", constraints };\n}\n\n/** Satisfied when the inner constraint is not. Delegation cannot narrow a `not`; prefer `notOneOf`. */\nexport function not(constraint: ConstraintExpr): NotConstraint {\n return { kind: \"not\", constraint };\n}\n\n/** Common Expression Language predicate over the argument value, evaluated in core. */\nexport function cel(expression: string): CelConstraint {\n if (expression.trim().length === 0) {\n throw new TenuoConfigurationError(\"tenuo.cel() requires a non-empty expression\");\n }\n return { kind: \"cel\", expression };\n}\n"]}
|
|
@@ -105,6 +105,12 @@ export class SdkContext {
|
|
|
105
105
|
*/
|
|
106
106
|
narrow(session: SdkSession, allow_json: any, options: any): SdkSession;
|
|
107
107
|
constructor();
|
|
108
|
+
/**
|
|
109
|
+
* `_meta.tenuo` for argument JSON text at `timestamp` (unix seconds).
|
|
110
|
+
*
|
|
111
|
+
* The proof covers the core's parse of `args_json`, including JSON null.
|
|
112
|
+
*/
|
|
113
|
+
signMeta(session: SdkSession, tool: string, args_json: string, timestamp: number, approvals: any): any;
|
|
108
114
|
/**
|
|
109
115
|
* Holder PoP only. Does not authorize. Used to fill `_meta.tenuo.signature`.
|
|
110
116
|
*/
|
|
@@ -118,6 +124,14 @@ export class SdkContext {
|
|
|
118
124
|
* `loadRevocationList` anywhere this issuer is a trusted root.
|
|
119
125
|
*/
|
|
120
126
|
signRevocationListVersioned(ids: any, version?: number | null): string;
|
|
127
|
+
/**
|
|
128
|
+
* Compatibility alias for verifyMetaPop. NOT an authorization check.
|
|
129
|
+
*/
|
|
130
|
+
verifyMeta(warrant: string, signature: string, tool: string, args_json: string, timestamp: number): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Check ONLY the holder proof, not trust, expiry, constraints, approvals or replay.
|
|
133
|
+
*/
|
|
134
|
+
verifyMetaPop(warrant: string, signature: string, tool: string, args_json: string, timestamp: number): boolean;
|
|
121
135
|
/**
|
|
122
136
|
* Sign verifier receipts with this 32-byte holder secret instead of an
|
|
123
137
|
* ephemeral key. Used by the TypeScript `Runtime`.
|
|
@@ -164,7 +178,7 @@ export class SdkSession {
|
|
|
164
178
|
*/
|
|
165
179
|
static fromWire(warrant: string, holder_secret: Uint8Array): SdkSession;
|
|
166
180
|
/**
|
|
167
|
-
* CBOR warrant stack as
|
|
181
|
+
* CBOR warrant stack as unpadded URL-safe base64. Same bytes as `_meta.tenuo.warrant`.
|
|
168
182
|
*/
|
|
169
183
|
toStackWire(): string;
|
|
170
184
|
/**
|
|
@@ -296,6 +310,18 @@ export function inspect_approval_gate(warrant_b64: string, tool: string): any;
|
|
|
296
310
|
*/
|
|
297
311
|
export function parse_connect_token(token: string): any;
|
|
298
312
|
|
|
313
|
+
/**
|
|
314
|
+
* Reject a repeated key in any object.
|
|
315
|
+
*
|
|
316
|
+
* A tools/call the host has already turned into an object cannot be checked:
|
|
317
|
+
* the duplicate key is gone. Call this while the text is still available.
|
|
318
|
+
* Nested objects are checked too. On success the caller parses `json_text`
|
|
319
|
+
* with the host parser. This function does not build a JavaScript object:
|
|
320
|
+
* that conversion turns `__proto__` into a prototype change and `null` into
|
|
321
|
+
* `undefined`.
|
|
322
|
+
*/
|
|
323
|
+
export function parse_strict_json(json_text: string): void;
|
|
324
|
+
|
|
299
325
|
/**
|
|
300
326
|
* Decode and check an approval envelope. Not authorization.
|
|
301
327
|
*/
|
|
@@ -295,6 +295,29 @@ class SdkContext {
|
|
|
295
295
|
SdkContextFinalization.register(this, this.__wbg_ptr, this);
|
|
296
296
|
return this;
|
|
297
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* `_meta.tenuo` for argument JSON text at `timestamp` (unix seconds).
|
|
300
|
+
*
|
|
301
|
+
* The proof covers the core's parse of `args_json`, including JSON null.
|
|
302
|
+
* @param {SdkSession} session
|
|
303
|
+
* @param {string} tool
|
|
304
|
+
* @param {string} args_json
|
|
305
|
+
* @param {number} timestamp
|
|
306
|
+
* @param {any} approvals
|
|
307
|
+
* @returns {any}
|
|
308
|
+
*/
|
|
309
|
+
signMeta(session, tool, args_json, timestamp, approvals) {
|
|
310
|
+
_assertClass(session, SdkSession);
|
|
311
|
+
const ptr0 = passStringToWasm0(tool, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
312
|
+
const len0 = WASM_VECTOR_LEN;
|
|
313
|
+
const ptr1 = passStringToWasm0(args_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
314
|
+
const len1 = WASM_VECTOR_LEN;
|
|
315
|
+
const ret = wasm.sdkcontext_signMeta(this.__wbg_ptr, session.__wbg_ptr, ptr0, len0, ptr1, len1, timestamp, approvals);
|
|
316
|
+
if (ret[2]) {
|
|
317
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
318
|
+
}
|
|
319
|
+
return takeFromExternrefTable0(ret[0]);
|
|
320
|
+
}
|
|
298
321
|
/**
|
|
299
322
|
* Holder PoP only. Does not authorize. Used to fill `_meta.tenuo.signature`.
|
|
300
323
|
* @param {SdkSession} session
|
|
@@ -371,6 +394,54 @@ class SdkContext {
|
|
|
371
394
|
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
372
395
|
}
|
|
373
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* Compatibility alias for verifyMetaPop. NOT an authorization check.
|
|
399
|
+
* @param {string} warrant
|
|
400
|
+
* @param {string} signature
|
|
401
|
+
* @param {string} tool
|
|
402
|
+
* @param {string} args_json
|
|
403
|
+
* @param {number} timestamp
|
|
404
|
+
* @returns {boolean}
|
|
405
|
+
*/
|
|
406
|
+
verifyMeta(warrant, signature, tool, args_json, timestamp) {
|
|
407
|
+
const ptr0 = passStringToWasm0(warrant, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
408
|
+
const len0 = WASM_VECTOR_LEN;
|
|
409
|
+
const ptr1 = passStringToWasm0(signature, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
410
|
+
const len1 = WASM_VECTOR_LEN;
|
|
411
|
+
const ptr2 = passStringToWasm0(tool, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
412
|
+
const len2 = WASM_VECTOR_LEN;
|
|
413
|
+
const ptr3 = passStringToWasm0(args_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
414
|
+
const len3 = WASM_VECTOR_LEN;
|
|
415
|
+
const ret = wasm.sdkcontext_verifyMeta(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, timestamp);
|
|
416
|
+
if (ret[2]) {
|
|
417
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
418
|
+
}
|
|
419
|
+
return ret[0] !== 0;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Check ONLY the holder proof, not trust, expiry, constraints, approvals or replay.
|
|
423
|
+
* @param {string} warrant
|
|
424
|
+
* @param {string} signature
|
|
425
|
+
* @param {string} tool
|
|
426
|
+
* @param {string} args_json
|
|
427
|
+
* @param {number} timestamp
|
|
428
|
+
* @returns {boolean}
|
|
429
|
+
*/
|
|
430
|
+
verifyMetaPop(warrant, signature, tool, args_json, timestamp) {
|
|
431
|
+
const ptr0 = passStringToWasm0(warrant, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
432
|
+
const len0 = WASM_VECTOR_LEN;
|
|
433
|
+
const ptr1 = passStringToWasm0(signature, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
434
|
+
const len1 = WASM_VECTOR_LEN;
|
|
435
|
+
const ptr2 = passStringToWasm0(tool, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
436
|
+
const len2 = WASM_VECTOR_LEN;
|
|
437
|
+
const ptr3 = passStringToWasm0(args_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
438
|
+
const len3 = WASM_VECTOR_LEN;
|
|
439
|
+
const ret = wasm.sdkcontext_verifyMetaPop(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, timestamp);
|
|
440
|
+
if (ret[2]) {
|
|
441
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
442
|
+
}
|
|
443
|
+
return ret[0] !== 0;
|
|
444
|
+
}
|
|
374
445
|
/**
|
|
375
446
|
* Sign verifier receipts with this 32-byte holder secret instead of an
|
|
376
447
|
* ephemeral key. Used by the TypeScript `Runtime`.
|
|
@@ -519,7 +590,7 @@ class SdkSession {
|
|
|
519
590
|
return SdkSession.__wrap(ret[0]);
|
|
520
591
|
}
|
|
521
592
|
/**
|
|
522
|
-
* CBOR warrant stack as
|
|
593
|
+
* CBOR warrant stack as unpadded URL-safe base64. Same bytes as `_meta.tenuo.warrant`.
|
|
523
594
|
* @returns {string}
|
|
524
595
|
*/
|
|
525
596
|
toStackWire() {
|
|
@@ -877,6 +948,27 @@ function parse_connect_token(token) {
|
|
|
877
948
|
}
|
|
878
949
|
exports.parse_connect_token = parse_connect_token;
|
|
879
950
|
|
|
951
|
+
/**
|
|
952
|
+
* Reject a repeated key in any object.
|
|
953
|
+
*
|
|
954
|
+
* A tools/call the host has already turned into an object cannot be checked:
|
|
955
|
+
* the duplicate key is gone. Call this while the text is still available.
|
|
956
|
+
* Nested objects are checked too. On success the caller parses `json_text`
|
|
957
|
+
* with the host parser. This function does not build a JavaScript object:
|
|
958
|
+
* that conversion turns `__proto__` into a prototype change and `null` into
|
|
959
|
+
* `undefined`.
|
|
960
|
+
* @param {string} json_text
|
|
961
|
+
*/
|
|
962
|
+
function parse_strict_json(json_text) {
|
|
963
|
+
const ptr0 = passStringToWasm0(json_text, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
964
|
+
const len0 = WASM_VECTOR_LEN;
|
|
965
|
+
const ret = wasm.parse_strict_json(ptr0, len0);
|
|
966
|
+
if (ret[1]) {
|
|
967
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
exports.parse_strict_json = parse_strict_json;
|
|
971
|
+
|
|
880
972
|
/**
|
|
881
973
|
* Decode and check an approval envelope. Not authorization.
|
|
882
974
|
* @param {string} envelope
|
|
Binary file
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
4
|
export const __wbg_sdkcontext_free: (a: number, b: number) => void;
|
|
5
5
|
export const __wbg_sdksession_free: (a: number, b: number) => void;
|
|
6
|
+
export const parse_strict_json: (a: number, b: number) => [number, number];
|
|
6
7
|
export const sdkInspectParts: (a: number, b: number, c: number, d: number) => [number, number, number];
|
|
7
8
|
export const sdkInspectWarrant: (a: number, b: number) => [number, number, number];
|
|
8
9
|
export const sdkProtocolLimits: () => [number, number, number];
|
|
@@ -21,8 +22,11 @@ export const sdkcontext_loadRevocationList: (a: number, b: number, c: number) =>
|
|
|
21
22
|
export const sdkcontext_mint: (a: number, b: any, c: number, d: any, e: number, f: number, g: number) => [number, number, number];
|
|
22
23
|
export const sdkcontext_narrow: (a: number, b: number, c: any, d: any) => [number, number, number];
|
|
23
24
|
export const sdkcontext_new: () => number;
|
|
25
|
+
export const sdkcontext_signMeta: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: any) => [number, number, number];
|
|
24
26
|
export const sdkcontext_signPop: (a: number, b: number, c: number, d: number, e: any) => [number, number, number, number];
|
|
25
27
|
export const sdkcontext_signRevocationList: (a: number, b: any) => [number, number, number, number];
|
|
28
|
+
export const sdkcontext_verifyMeta: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => [number, number, number];
|
|
29
|
+
export const sdkcontext_verifyMetaPop: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => [number, number, number];
|
|
26
30
|
export const sdkcontext_withReceiptSigner: (a: number, b: number, c: number) => [number, number, number];
|
|
27
31
|
export const sdksession_dedupKey: (a: number, b: number, c: number, d: any) => [number, number, number, number];
|
|
28
32
|
export const sdksession_describe: (a: number) => [number, number, number];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export type { ApprovalGateInspection, ApprovalRequirement, ApprovalRequirementStatus, } from "./wasm.ts";
|
|
2
|
-
export { approvalRequirement, evaluateApprovalGates, inspectApprovalGate } from "./wasm.ts";
|
|
2
|
+
export { approvalRequirement, evaluateApprovalGates, inspectApprovalGate, parseStrictJson, } from "./wasm.ts";
|
|
3
3
|
export type { AllConstraint, AllowPolicy, AnyOfConstraint, ApprovalContextAttestation, ApprovalInfo, ApprovalRequest, ApprovalRequestSummary, ArgApprovalGate, CelConstraint, CidrConstraint, Clearance, ConstraintExpr, ContainsConstraint, ControlPlaneApprovalRequestV1, ControlPlaneApprovalResponseV1, CreateTenuoOptions, Decision, DevRoot, EmailConstraint, ExactConstraint, ExecuteOptions, ExplainedField, Explanation, IssueInput, IssuerKey, MaxConstraint, McpAttachOptions, McpCallParams, McpHandlerPolicy, McpJsonRpcError, McpVerifyOptions, MinConstraint, NarrowInput, NarrowOptions, NonceStore, NotConstraint, NotOneOfConstraint, OneOfConstraint, PatternConstraint, PresentedCall, ProtectedTool, PublicKeyHandle, RangeConstraint, ReceiptChainInfo, ReceiptInfo, RegexConstraint, RequireApproval, RevocationListInfo, RevocationListInput, Session, SessionAllow, SessionFromWireInput, SessionInfo, SessionInput, ShlexConstraint, SignApprovalOptions, SubsetConstraint, Tenuo, LegacyTenuoErrorCode, ProtocolDenialCode, TenuoErrorCode, TenuoMcp, TenuoMcpMeta, ToolApprovalGate, ToolLike, ToolPolicy, UnderConstraint, UrlPatternConstraint, UrlSafeConstraint, WarrantPart, WildcardConstraint, } from "./api.ts";
|
|
4
4
|
export { ApprovalRequiredError, AuthorizationDeniedError, TenuoConfigurationError, TenuoError, } from "./errors.ts";
|
|
5
|
-
export { all, anyOf, cel, cidr, contains, email, exact, max, min, not, notOneOf, oneOf, pattern, range, regex, shlex, subset, under, urlPattern, urlSafe, wildcard, } from "./constraints.ts";
|
|
5
|
+
export { all, anyOf, cel, cidr, contains, email, exact, max, min, not, notOneOf, oneOf, pathGlob, pattern, range, regex, shlex, subset, under, urlPattern, urlSafe, wildcard, } from "./constraints.ts";
|
|
6
6
|
export { memoryNonceStore } from "./nonce.ts";
|
|
7
7
|
export { Session as SessionHandle, isSession } from "./session.ts";
|
|
8
8
|
export { ConnectToken, parseConnectToken } from "./connect.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { approvalRequirement, evaluateApprovalGates, inspectApprovalGate } from "./wasm.js";
|
|
1
|
+
export { approvalRequirement, evaluateApprovalGates, inspectApprovalGate, parseStrictJson, } from "./wasm.js";
|
|
2
2
|
export { ApprovalRequiredError, AuthorizationDeniedError, TenuoConfigurationError, TenuoError, } from "./errors.js";
|
|
3
|
-
export { all, anyOf, cel, cidr, contains, email, exact, max, min, not, notOneOf, oneOf, pattern, range, regex, shlex, subset, under, urlPattern, urlSafe, wildcard, } from "./constraints.js";
|
|
3
|
+
export { all, anyOf, cel, cidr, contains, email, exact, max, min, not, notOneOf, oneOf, pathGlob, pattern, range, regex, shlex, subset, under, urlPattern, urlSafe, wildcard, } from "./constraints.js";
|
|
4
4
|
export { memoryNonceStore } from "./nonce.js";
|
|
5
5
|
export { Session as SessionHandle, isSession } from "./session.js";
|
|
6
6
|
export { ConnectToken, parseConnectToken } from "./connect.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,GAChB,MAAM,WAAW,CAAC;AA4EnB,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,GAAG,EACH,KAAK,EACL,GAAG,EACH,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,KAAK,EACL,GAAG,EACH,GAAG,EACH,GAAG,EACH,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,OAAO,EACP,KAAK,EACL,KAAK,EACL,KAAK,EACL,MAAM,EACN,KAAK,EACL,UAAU,EACV,OAAO,EACP,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAElF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export type {\n ApprovalGateInspection,\n ApprovalRequirement,\n ApprovalRequirementStatus,\n} from \"./wasm.ts\";\n\nexport {\n approvalRequirement,\n evaluateApprovalGates,\n inspectApprovalGate,\n parseStrictJson,\n} from \"./wasm.ts\";\n\nexport type {\n AllConstraint,\n AllowPolicy,\n AnyOfConstraint,\n ApprovalContextAttestation,\n ApprovalInfo,\n ApprovalRequest,\n ApprovalRequestSummary,\n ArgApprovalGate,\n CelConstraint,\n CidrConstraint,\n Clearance,\n ConstraintExpr,\n ContainsConstraint,\n ControlPlaneApprovalRequestV1,\n ControlPlaneApprovalResponseV1,\n CreateTenuoOptions,\n Decision,\n DevRoot,\n EmailConstraint,\n ExactConstraint,\n ExecuteOptions,\n ExplainedField,\n Explanation,\n IssueInput,\n IssuerKey,\n MaxConstraint,\n McpAttachOptions,\n McpCallParams,\n McpHandlerPolicy,\n McpJsonRpcError,\n McpVerifyOptions,\n MinConstraint,\n NarrowInput,\n NarrowOptions,\n NonceStore,\n NotConstraint,\n NotOneOfConstraint,\n OneOfConstraint,\n PatternConstraint,\n PresentedCall,\n ProtectedTool,\n PublicKeyHandle,\n RangeConstraint,\n ReceiptChainInfo,\n ReceiptInfo,\n RegexConstraint,\n RequireApproval,\n RevocationListInfo,\n RevocationListInput,\n Session,\n SessionAllow,\n SessionFromWireInput,\n SessionInfo,\n SessionInput,\n ShlexConstraint,\n SignApprovalOptions,\n SubsetConstraint,\n Tenuo,\n LegacyTenuoErrorCode,\n ProtocolDenialCode,\n TenuoErrorCode,\n TenuoMcp,\n TenuoMcpMeta,\n ToolApprovalGate,\n ToolLike,\n ToolPolicy,\n UnderConstraint,\n UrlPatternConstraint,\n UrlSafeConstraint,\n WarrantPart,\n WildcardConstraint,\n} from \"./api.ts\";\n\nexport {\n ApprovalRequiredError,\n AuthorizationDeniedError,\n TenuoConfigurationError,\n TenuoError,\n} from \"./errors.ts\";\n\nexport {\n all,\n anyOf,\n cel,\n cidr,\n contains,\n email,\n exact,\n max,\n min,\n not,\n notOneOf,\n oneOf,\n pathGlob,\n pattern,\n range,\n regex,\n shlex,\n subset,\n under,\n urlPattern,\n urlSafe,\n wildcard,\n} from \"./constraints.ts\";\n\nexport { memoryNonceStore } from \"./nonce.ts\";\n\nexport { Session as SessionHandle, isSession } from \"./session.ts\";\n\nexport { ConnectToken, parseConnectToken } from \"./connect.ts\";\nexport type { ResolveEndpointOptions } from \"./connect.ts\";\n\nexport { HolderIdentity, generateIdentity, identityFromKey } from \"./identity.ts\";\n\nexport { Runtime } from \"./runtime.ts\";\nexport type { ReceiptsMode, RuntimeOptions, SessionWarrant } from \"./runtime.ts\";\n\nexport { createTenuo } from \"./client.ts\";\n"]}
|
package/dist/mcp.js
CHANGED
|
@@ -11,19 +11,19 @@ export function presentCall(context, decide, session, name, args, options, label
|
|
|
11
11
|
assertKnownKeys(options, ATTACH_OPTION_KEYS, `${label} options`);
|
|
12
12
|
}
|
|
13
13
|
const native = nativeSession(session);
|
|
14
|
-
const
|
|
15
|
-
const local = context.authorize(native, name,
|
|
14
|
+
const snapshot = captureArguments(args);
|
|
15
|
+
const local = context.authorize(native, name, snapshot.json, options?.approvals, undefined, options?.requestId);
|
|
16
16
|
emitReceipt(options?.onReceipt, local.receipt, session, host);
|
|
17
|
-
decide(local, name, native,
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
return { presented
|
|
17
|
+
decide(local, name, native, snapshot.executionArgs());
|
|
18
|
+
const envelope = context.signMeta(native, name, snapshot.json, Math.floor(Date.now() / 1000), options?.approvals ?? null);
|
|
19
|
+
const presented = {
|
|
20
|
+
warrant: envelope.warrant,
|
|
21
|
+
signature: envelope.signature,
|
|
22
|
+
...(envelope.approvals !== undefined && envelope.approvals.length > 0
|
|
23
|
+
? { approvals: envelope.approvals }
|
|
24
|
+
: {}),
|
|
25
|
+
};
|
|
26
|
+
return { presented, wireArgs: snapshot.executionArgs() };
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* Transport-agnostic half of `verify`: check a presented warrant chain and
|
|
@@ -38,7 +38,10 @@ export async function verifyPresented(context, decide, presented, name, args, op
|
|
|
38
38
|
if (envelope === undefined) {
|
|
39
39
|
throw new TenuoConfigurationError(`${label} needs { warrant, signature } from tenuo.present() or tenuo.mcp.attach()`);
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
// Capture once: replay admission and receipt callbacks may yield or mutate
|
|
42
|
+
// the caller's object. Execution must use the exact snapshot verified here.
|
|
43
|
+
const snapshot = captureArguments(args);
|
|
44
|
+
const decision = context.authorizePresented(envelope.warrant, name, snapshot.json, envelope.signature, envelope.approvals, options?.allow, options?.requestId);
|
|
42
45
|
// Rust already signed this envelope. Emit before the nonce store can
|
|
43
46
|
// refuse a replay — otherwise an attacker leaves no audit artifact.
|
|
44
47
|
emitReceipt(options?.onReceipt, decision.receipt, undefined, host);
|
|
@@ -46,7 +49,9 @@ export async function verifyPresented(context, decide, presented, name, args, op
|
|
|
46
49
|
await admitPop(options?.nonceStore, envelope.signature, options?.onNonceStoreError);
|
|
47
50
|
}
|
|
48
51
|
decide(decision, name);
|
|
49
|
-
|
|
52
|
+
// Run the host parse of the JSON text the proof covers. The raw host
|
|
53
|
+
// object can contain values that JSON drops.
|
|
54
|
+
return snapshot.executionArgs();
|
|
50
55
|
}
|
|
51
56
|
export function createMcp(context, decide, host) {
|
|
52
57
|
const mcp = {
|
|
@@ -83,22 +88,16 @@ export function createMcp(context, decide, host) {
|
|
|
83
88
|
};
|
|
84
89
|
return mcp;
|
|
85
90
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const wire = session.toStackWire();
|
|
92
|
-
if (typeof wire !== "string" || wire.length === 0) {
|
|
93
|
-
throw new TenuoConfigurationError("toStackWire() did not return a warrant stack");
|
|
94
|
-
}
|
|
95
|
-
return wire;
|
|
96
|
-
}
|
|
97
|
-
function approvalWire(value) {
|
|
98
|
-
if (typeof value === "string") {
|
|
99
|
-
return value;
|
|
91
|
+
/** A private immutable input snapshot, not an authorization token. */
|
|
92
|
+
function captureArguments(args) {
|
|
93
|
+
const text = JSON.stringify(args);
|
|
94
|
+
if (typeof text !== "string") {
|
|
95
|
+
throw new TenuoConfigurationError("arguments must be JSON");
|
|
100
96
|
}
|
|
101
|
-
return
|
|
97
|
+
return Object.freeze({
|
|
98
|
+
json: text,
|
|
99
|
+
executionArgs: () => plainArgs(JSON.parse(text)),
|
|
100
|
+
});
|
|
102
101
|
}
|
|
103
102
|
function presentedEnvelope(value) {
|
|
104
103
|
if (value === null || typeof value !== "object") {
|
|
@@ -111,9 +110,11 @@ function presentedEnvelope(value) {
|
|
|
111
110
|
if (typeof tenuo.signature !== "string" || tenuo.signature.length === 0) {
|
|
112
111
|
return undefined;
|
|
113
112
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
if (tenuo.approvals != null &&
|
|
114
|
+
(!Array.isArray(tenuo.approvals) || tenuo.approvals.some((item) => typeof item !== "string"))) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
const approvals = tenuo.approvals ?? undefined;
|
|
117
118
|
return {
|
|
118
119
|
warrant: tenuo.warrant,
|
|
119
120
|
signature: tenuo.signature,
|
|
@@ -138,8 +139,6 @@ const VERIFY_OPTION_KEYS = new Set([
|
|
|
138
139
|
]);
|
|
139
140
|
const REPLAY_STORE_UNAVAILABLE = "Replay store unavailable";
|
|
140
141
|
const ATTACH_OPTION_KEYS = new Set(["approvals", "onReceipt", "requestId"]);
|
|
141
|
-
const MAX_STRIP_DEPTH = 32;
|
|
142
|
-
const MAX_STRIP_LEN = 1024;
|
|
143
142
|
function assertKnownKeys(value, known, label) {
|
|
144
143
|
const unknown = Object.keys(value).filter((key) => !known.has(key));
|
|
145
144
|
if (unknown[0] !== undefined) {
|
|
@@ -223,37 +222,6 @@ function plainArgs(value) {
|
|
|
223
222
|
}
|
|
224
223
|
return {};
|
|
225
224
|
}
|
|
226
|
-
/** Same rule as Python `strip_none_values`: drop null so optional MCP args do not break PoP. */
|
|
227
|
-
function stripNulls(args) {
|
|
228
|
-
const keys = Object.keys(args);
|
|
229
|
-
if (keys.length > MAX_STRIP_LEN) {
|
|
230
|
-
throw new TenuoConfigurationError("arguments exceed the TypeScript input budget");
|
|
231
|
-
}
|
|
232
|
-
const out = {};
|
|
233
|
-
for (const [key, value] of Object.entries(args)) {
|
|
234
|
-
if (value === null || value === undefined) {
|
|
235
|
-
continue;
|
|
236
|
-
}
|
|
237
|
-
out[key] = Array.isArray(value) ? cleanList(value, 1) : value;
|
|
238
|
-
}
|
|
239
|
-
return out;
|
|
240
|
-
}
|
|
241
|
-
function cleanList(value, depth) {
|
|
242
|
-
if (depth > MAX_STRIP_DEPTH) {
|
|
243
|
-
throw new TenuoConfigurationError("arguments exceed the TypeScript nesting budget");
|
|
244
|
-
}
|
|
245
|
-
if (value.length > MAX_STRIP_LEN) {
|
|
246
|
-
throw new TenuoConfigurationError("arguments exceed the TypeScript input budget");
|
|
247
|
-
}
|
|
248
|
-
const cleaned = [];
|
|
249
|
-
for (const item of value) {
|
|
250
|
-
if (item === null || item === undefined) {
|
|
251
|
-
continue;
|
|
252
|
-
}
|
|
253
|
-
cleaned.push(Array.isArray(item) ? cleanList(item, depth + 1) : item);
|
|
254
|
-
}
|
|
255
|
-
return cleaned;
|
|
256
|
-
}
|
|
257
225
|
function jsonRpcError(error) {
|
|
258
226
|
if (error instanceof TenuoError) {
|
|
259
227
|
const code = error.code;
|
package/dist/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n McpAttachOptions,\n McpCallParams,\n McpHandlerPolicy,\n McpJsonRpcError,\n McpVerifyOptions,\n PresentedCall,\n Session as SessionContract,\n TenuoErrorCode,\n TenuoMcp,\n} from \"./api.ts\";\nimport { AuthorizationDeniedError, TenuoConfigurationError, TenuoError } from \"./errors.ts\";\nimport { collectReceipt, emitIsolatedReceipt } from \"./receipts.ts\";\nimport { nativeSession, type Session } from \"./session.ts\";\nimport type { WasmContext, WasmDecision } from \"./wasm.ts\";\n\nexport type Decide = (decision: WasmDecision, tool: string, native?: object, args?: Record<string, unknown>) => void;\n\n/**\n * Transport-agnostic half of `attach`: authorize locally, then sign\n * proof-of-possession over the call. Shared by `tenuo.present()` and\n * `tenuo.mcp.attach()`.\n */\nexport function presentCall(\n context: WasmContext,\n decide: Decide,\n session: SessionContract,\n name: string,\n args: Readonly<Record<string, unknown>>,\n options: McpAttachOptions | undefined,\n label: string,\n host?: object,\n): { readonly presented: PresentedCall; readonly wireArgs: Record<string, unknown> } {\n if (options !== undefined) {\n assertKnownKeys(options, ATTACH_OPTION_KEYS, `${label} options`);\n }\n const native = nativeSession(session as Session);\n const wireArgs = stripNulls(args);\n const local = context.authorize(\n native,\n name,\n wireArgs,\n options?.approvals,\n undefined,\n options?.requestId,\n );\n emitReceipt(options?.onReceipt, local.receipt, session, host);\n decide(local, name, native, wireArgs);\n const signature = context.signPop(native, name, wireArgs);\n const warrant = stackWire(native);\n if (options?.approvals !== undefined && options.approvals.length > 0) {\n return {\n presented: { warrant, signature, approvals: options.approvals.map(approvalWire) },\n wireArgs,\n };\n }\n return { presented: { warrant, signature }, wireArgs };\n}\n\n/**\n * Transport-agnostic half of `verify`: check a presented warrant chain and\n * proof-of-possession, then apply the host ceiling. Shared by\n * `tenuo.verify()` and `tenuo.mcp.verify()`.\n */\nexport async function verifyPresented(\n context: WasmContext,\n decide: Decide,\n presented: PresentedCall,\n name: string,\n args: Readonly<Record<string, unknown>>,\n options: McpVerifyOptions | undefined,\n label: string,\n host?: object,\n): Promise<Readonly<Record<string, unknown>>> {\n if (options !== undefined) {\n assertKnownKeys(options, VERIFY_OPTION_KEYS, `${label} options`);\n }\n const envelope = presentedEnvelope(presented);\n if (envelope === undefined) {\n throw new TenuoConfigurationError(\n `${label} needs { warrant, signature } from tenuo.present() or tenuo.mcp.attach()`,\n );\n }\n const decision = context.authorizePresented(\n envelope.warrant,\n name,\n stripNulls(args),\n envelope.signature,\n envelope.approvals,\n options?.allow,\n options?.requestId,\n );\n // Rust already signed this envelope. Emit before the nonce store can\n // refuse a replay — otherwise an attacker leaves no audit artifact.\n emitReceipt(options?.onReceipt, decision.receipt, undefined, host);\n if (decision.outcome === \"allow\") {\n await admitPop(options?.nonceStore, envelope.signature, options?.onNonceStoreError);\n }\n decide(decision, name);\n return plainArgs(decision.args);\n}\n\nexport function createMcp(context: WasmContext, decide: Decide, host?: object): TenuoMcp {\n const mcp: TenuoMcp = {\n attach(session, name, args, options) {\n const { presented, wireArgs } = presentCall(\n context,\n decide,\n session,\n name,\n args,\n options,\n \"mcp.attach()\",\n host,\n );\n return { name, arguments: wireArgs, _meta: { tenuo: presented } };\n },\n\n async verify(name, args, meta, options) {\n const envelope = tenuoEnvelope(meta);\n if (envelope === undefined) {\n throw new TenuoConfigurationError(\n \"MCP call is missing _meta.tenuo. The client must call tenuo.mcp.attach().\",\n );\n }\n return verifyPresented(context, decide, envelope, name, args, options, \"mcp.verify()\", host);\n },\n\n handler(name, policyOrExecute, maybeExecute?) {\n const policy = isHandlerPolicy(policyOrExecute) ? policyOrExecute : undefined;\n const execute = isHandlerPolicy(policyOrExecute) ? maybeExecute : policyOrExecute;\n if (typeof execute !== \"function\") {\n throw new TenuoConfigurationError(\"mcp.handler() requires an execute function\");\n }\n return async (args, extra) => {\n const authorized = await mcp.verify(name, args, extra?._meta ?? extra?.meta, {\n ...(policy?.allow !== undefined ? { allow: policy.allow } : {}),\n ...(policy?.onReceipt !== undefined ? { onReceipt: policy.onReceipt } : {}),\n ...(policy?.nonceStore !== undefined ? { nonceStore: policy.nonceStore } : {}),\n ...(policy?.onNonceStoreError !== undefined ? { onNonceStoreError: policy.onNonceStoreError } : {}),\n });\n return execute(authorized as never);\n };\n },\n\n jsonRpcError(error) {\n return jsonRpcError(error);\n },\n };\n return mcp;\n}\n\nfunction stackWire(native: object): string {\n const session = native as { toStackWire?: () => unknown };\n if (typeof session.toStackWire !== \"function\") {\n throw new TenuoConfigurationError(\"session is not bound to the WASM core\");\n }\n const wire = session.toStackWire();\n if (typeof wire !== \"string\" || wire.length === 0) {\n throw new TenuoConfigurationError(\"toStackWire() did not return a warrant stack\");\n }\n return wire;\n}\n\nfunction approvalWire(value: string | Uint8Array): string {\n if (typeof value === \"string\") {\n return value;\n }\n return Buffer.from(value).toString(\"base64\");\n}\n\nfunction presentedEnvelope(\n value: unknown,\n): { warrant: string; signature: string; approvals?: string[] } | undefined {\n if (value === null || typeof value !== \"object\") {\n return undefined;\n }\n const tenuo = value as { warrant?: unknown; signature?: unknown; approvals?: unknown };\n if (typeof tenuo.warrant !== \"string\" || tenuo.warrant.length === 0) {\n return undefined;\n }\n if (typeof tenuo.signature !== \"string\" || tenuo.signature.length === 0) {\n return undefined;\n }\n const approvals = Array.isArray(tenuo.approvals)\n ? tenuo.approvals.filter((item): item is string => typeof item === \"string\")\n : undefined;\n return {\n warrant: tenuo.warrant,\n signature: tenuo.signature,\n ...(approvals !== undefined && approvals.length > 0 ? { approvals } : {}),\n };\n}\n\nfunction tenuoEnvelope(\n meta: unknown,\n): { warrant: string; signature: string; approvals?: string[] } | undefined {\n if (meta === null || typeof meta !== \"object\") {\n return undefined;\n }\n const root = meta as { tenuo?: unknown; _meta?: unknown };\n const block = root.tenuo ?? (root._meta as { tenuo?: unknown } | undefined)?.tenuo;\n return presentedEnvelope(block);\n}\n\nconst HANDLER_POLICY_KEYS = new Set([\"allow\", \"onReceipt\", \"nonceStore\", \"onNonceStoreError\"]);\nconst VERIFY_OPTION_KEYS = new Set([\n \"allow\",\n \"onReceipt\",\n \"nonceStore\",\n \"onNonceStoreError\",\n \"requestId\",\n]);\nconst REPLAY_STORE_UNAVAILABLE = \"Replay store unavailable\";\nconst ATTACH_OPTION_KEYS = new Set([\"approvals\", \"onReceipt\", \"requestId\"]);\nconst MAX_STRIP_DEPTH = 32;\nconst MAX_STRIP_LEN = 1024;\n\nfunction assertKnownKeys(value: object, known: ReadonlySet<string>, label: string): void {\n const unknown = Object.keys(value).filter((key) => !known.has(key));\n if (unknown[0] !== undefined) {\n throw new TenuoConfigurationError(\n `${label} has unknown key '${unknown[0]}'. Use ${[...known].join(\", \")}.`,\n );\n }\n}\n\nfunction isHandlerPolicy(value: unknown): value is McpHandlerPolicy {\n if (value === null || typeof value !== \"object\" || Array.isArray(value) || typeof value === \"function\") {\n return false;\n }\n const keys = Object.keys(value);\n assertKnownKeys(value, HANDLER_POLICY_KEYS, \"mcp.handler() policy\");\n const record = value as {\n allow?: unknown;\n onReceipt?: unknown;\n nonceStore?: unknown;\n onNonceStoreError?: unknown;\n };\n const hasAllow =\n \"allow\" in record && record.allow !== null && typeof record.allow === \"object\" && !Array.isArray(record.allow);\n const hasReceipt = \"onReceipt\" in record && typeof record.onReceipt === \"function\";\n const hasNonce = \"nonceStore\" in record && record.nonceStore !== null && typeof record.nonceStore === \"object\";\n const hasStoreError = \"onNonceStoreError\" in record && typeof record.onNonceStoreError === \"function\";\n return keys.length === 0 || hasAllow || hasReceipt || hasNonce || hasStoreError;\n}\n\nasync function admitPop(\n store: { checkAndRecord(popSignature: string): boolean | Promise<boolean> } | undefined,\n signature: string,\n onNonceStoreError?: (error: unknown) => void | Promise<void>,\n): Promise<void> {\n if (store === undefined) {\n return;\n }\n let admitted: boolean | Promise<boolean>;\n try {\n admitted = store.checkAndRecord(signature);\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 new AuthorizationDeniedError(\n \"TENUO_INVALID_POP\",\n \"PoP replay detected — this exact authorization token was already consumed.\",\n );\n }\n}\n\nfunction replayStoreUnavailable(\n cause: unknown,\n onNonceStoreError?: (error: unknown) => void | Promise<void>,\n): TenuoConfigurationError {\n emitIsolated(onNonceStoreError, cause);\n const error = new TenuoConfigurationError(REPLAY_STORE_UNAVAILABLE);\n if (cause !== undefined) {\n error.cause = cause;\n }\n return error;\n}\n\nfunction emitIsolated(\n hook: ((error: unknown) => void | Promise<void>) | undefined,\n error: unknown,\n): void {\n if (hook === undefined) {\n return;\n }\n try {\n const result = hook(error);\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\nfunction isThenable(value: unknown): value is Promise<boolean> {\n return value !== null && typeof value === \"object\" && \"then\" in value && typeof value.then === \"function\";\n}\n\nfunction emitReceipt(\n onReceipt: ((receipt: string) => void | Promise<void>) | undefined,\n receipt: string | undefined,\n session?: SessionContract,\n host?: object,\n): void {\n collectReceipt(receipt, session, host);\n emitIsolatedReceipt(onReceipt, receipt);\n}\n\nfunction plainArgs(value: unknown): Record<string, unknown> {\n if (value instanceof Map) {\n return Object.fromEntries(value);\n }\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return { ...(value as Record<string, unknown>) };\n }\n return {};\n}\n\n/** Same rule as Python `strip_none_values`: drop null so optional MCP args do not break PoP. */\nfunction stripNulls(args: Readonly<Record<string, unknown>>): Record<string, unknown> {\n const keys = Object.keys(args);\n if (keys.length > MAX_STRIP_LEN) {\n throw new TenuoConfigurationError(\"arguments exceed the TypeScript input budget\");\n }\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(args)) {\n if (value === null || value === undefined) {\n continue;\n }\n out[key] = Array.isArray(value) ? cleanList(value, 1) : value;\n }\n return out;\n}\n\nfunction cleanList(value: readonly unknown[], depth: number): unknown[] {\n if (depth > MAX_STRIP_DEPTH) {\n throw new TenuoConfigurationError(\"arguments exceed the TypeScript nesting budget\");\n }\n if (value.length > MAX_STRIP_LEN) {\n throw new TenuoConfigurationError(\"arguments exceed the TypeScript input budget\");\n }\n const cleaned: unknown[] = [];\n for (const item of value) {\n if (item === null || item === undefined) {\n continue;\n }\n cleaned.push(Array.isArray(item) ? cleanList(item, depth + 1) : item);\n }\n return cleaned;\n}\n\nfunction jsonRpcError(error: unknown): McpJsonRpcError {\n if (error instanceof TenuoError) {\n const code: TenuoErrorCode = error.code;\n const rpc = code === \"TENUO_APPROVAL_REQUIRED\" ? -32002 : code === \"TENUO_CANONICALIZATION\" ? -32602 : -32001;\n return { code: rpc, message: error.message, data: { tenuo: { code } } };\n }\n const message = error instanceof Error ? error.message : String(error);\n return { code: -32001, message };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,aAAa,EAAgB,MAAM,cAAc,CAAC;AAK3D;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,OAAoB,EACpB,MAAc,EACd,OAAwB,EACxB,IAAY,EACZ,IAAuC,EACvC,OAAqC,EACrC,KAAa,EACb,IAAa;IAEb,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,eAAe,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,KAAK,UAAU,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,MAAM,GAAG,aAAa,CAAC,OAAkB,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAC7B,MAAM,EACN,IAAI,EACJ,QAAQ,CAAC,IAAI,EACb,OAAO,EAAE,SAAS,EAClB,SAAS,EACT,OAAO,EAAE,SAAS,CACnB,CAAC;IACF,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAC/B,MAAM,EACN,IAAI,EACJ,QAAQ,CAAC,IAAI,EACb,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAC7B,OAAO,EAAE,SAAS,IAAI,IAAI,CAC3B,CAAC;IACF,MAAM,SAAS,GAAG;QAChB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,GAAG,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;YACnE,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE;YACnC,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IACF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC;AAC3D,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAoB,EACpB,MAAc,EACd,SAAwB,EACxB,IAAY,EACZ,IAAuC,EACvC,OAAqC,EACrC,KAAa,EACb,IAAa;IAEb,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,eAAe,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,KAAK,UAAU,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,IAAI,uBAAuB,CAC/B,GAAG,KAAK,0EAA0E,CACnF,CAAC;IACJ,CAAC;IACD,2EAA2E;IAC3E,4EAA4E;IAC5E,MAAM,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,kBAAkB,CACzC,QAAQ,CAAC,OAAO,EAChB,IAAI,EACJ,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,SAAS,EAClB,QAAQ,CAAC,SAAS,EAClB,OAAO,EAAE,KAAK,EACd,OAAO,EAAE,SAAS,CACnB,CAAC;IACF,qEAAqE;IACrE,oEAAoE;IACpE,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACnE,IAAI,QAAQ,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;IACtF,CAAC;IACD,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACvB,qEAAqE;IACrE,6CAA6C;IAC7C,OAAO,QAAQ,CAAC,aAAa,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAoB,EAAE,MAAc,EAAE,IAAa;IAC3E,MAAM,GAAG,GAAa;QACpB,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO;YACjC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,WAAW,CACzC,OAAO,EACP,MAAM,EACN,OAAO,EACP,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,cAAc,EACd,IAAI,CACL,CAAC;YACF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC;QACpE,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO;YACpC,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAM,IAAI,uBAAuB,CAC/B,2EAA2E,CAC5E,CAAC;YACJ,CAAC;YACD,OAAO,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,CAAC,CAAC;QAC/F,CAAC;QAED,OAAO,CAAC,IAAI,EAAE,eAAe,EAAE,YAAa;YAC1C,MAAM,MAAM,GAAG,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9E,MAAM,OAAO,GAAG,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC;YAClF,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;gBAClC,MAAM,IAAI,uBAAuB,CAAC,4CAA4C,CAAC,CAAC;YAClF,CAAC;YACD,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;gBAC3B,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,IAAI,KAAK,EAAE,IAAI,EAAE;oBAC3E,GAAG,CAAC,MAAM,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/D,GAAG,CAAC,MAAM,EAAE,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC3E,GAAG,CAAC,MAAM,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC9E,GAAG,CAAC,MAAM,EAAE,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;iBACpG,CAAC,CAAC;gBACH,OAAO,OAAO,CAAC,UAAmB,CAAC,CAAC;YACtC,CAAC,CAAC;QACJ,CAAC;QAED,YAAY,CAAC,KAAK;YAChB,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;IACF,OAAO,GAAG,CAAC;AACb,CAAC;AAED,sEAAsE;AACtE,SAAS,gBAAgB,CAAC,IAAuC;IAI/D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,uBAAuB,CAAC,wBAAwB,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,IAAI;QACV,aAAa,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;KACjD,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAc;IAEd,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAG,KAAwE,CAAC;IACvF,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,IAAI,IAAI;QACvB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,EAAE,CAAC;QAClG,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,SAAS,CAAC;IAC/C,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CACpB,IAAa;IAEb,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,GAAG,IAA4C,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAK,IAAI,CAAC,KAAyC,EAAE,KAAK,CAAC;IACnF,OAAO,iBAAiB,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC,CAAC;AAC/F,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,OAAO;IACP,WAAW;IACX,YAAY;IACZ,mBAAmB;IACnB,WAAW;CACZ,CAAC,CAAC;AACH,MAAM,wBAAwB,GAAG,0BAA0B,CAAC;AAC5D,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;AAC5E,SAAS,eAAe,CAAC,KAAa,EAAE,KAA0B,EAAE,KAAa;IAC/E,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,uBAAuB,CAC/B,GAAG,KAAK,qBAAqB,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QACvG,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,eAAe,CAAC,KAAK,EAAE,mBAAmB,EAAE,sBAAsB,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,KAKd,CAAC;IACF,MAAM,QAAQ,GACZ,OAAO,IAAI,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjH,MAAM,UAAU,GAAG,WAAW,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,UAAU,CAAC;IACnF,MAAM,QAAQ,GAAG,YAAY,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC;IAC/G,MAAM,aAAa,GAAG,mBAAmB,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,iBAAiB,KAAK,UAAU,CAAC;IACtG,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,IAAI,UAAU,IAAI,QAAQ,IAAI,aAAa,CAAC;AAClF,CAAC;AAED,KAAK,UAAU,QAAQ,CACrB,KAAuF,EACvF,SAAiB,EACjB,iBAA4D;IAE5D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO;IACT,CAAC;IACD,IAAI,QAAoC,CAAC;IACzC,IAAI,CAAC;QACH,QAAQ,GAAG,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,sBAAsB,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,QAAQ,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,sBAAsB,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,sBAAsB,CAC1B,IAAI,uBAAuB,CAAC,qEAAqE,CAAC,EAClG,iBAAiB,CAClB,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,wBAAwB,CAChC,mBAAmB,EACnB,4EAA4E,CAC7E,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAC7B,KAAc,EACd,iBAA4D;IAE5D,YAAY,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,uBAAuB,CAAC,wBAAwB,CAAC,CAAC;IACpE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IACtB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,YAAY,CACnB,IAA4D,EAC5D,KAAc;IAEd,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,KAAK,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;AAC5G,CAAC;AAED,SAAS,WAAW,CAClB,SAAkE,EAClE,OAA2B,EAC3B,OAAyB,EACzB,IAAa;IAEb,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACvC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzE,OAAO,EAAE,GAAI,KAAiC,EAAE,CAAC;IACnD,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,GAAmB,KAAK,CAAC,IAAI,CAAC;QACxC,MAAM,GAAG,GAAG,IAAI,KAAK,yBAAyB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,wBAAwB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC9G,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAC1E,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import type {\n McpAttachOptions,\n McpCallParams,\n McpHandlerPolicy,\n McpJsonRpcError,\n McpVerifyOptions,\n PresentedCall,\n Session as SessionContract,\n TenuoErrorCode,\n TenuoMcp,\n} from \"./api.ts\";\nimport { AuthorizationDeniedError, TenuoConfigurationError, TenuoError } from \"./errors.ts\";\nimport { collectReceipt, emitIsolatedReceipt } from \"./receipts.ts\";\nimport { nativeSession, type Session } from \"./session.ts\";\nimport type { WasmContext, WasmDecision } from \"./wasm.ts\";\n\nexport type Decide = (decision: WasmDecision, tool: string, native?: object, args?: Record<string, unknown>) => void;\n\n/**\n * Transport-agnostic half of `attach`: authorize locally, then sign\n * proof-of-possession over the call. Shared by `tenuo.present()` and\n * `tenuo.mcp.attach()`.\n */\nexport function presentCall(\n context: WasmContext,\n decide: Decide,\n session: SessionContract,\n name: string,\n args: Readonly<Record<string, unknown>>,\n options: McpAttachOptions | undefined,\n label: string,\n host?: object,\n): { readonly presented: PresentedCall; readonly wireArgs: Record<string, unknown> } {\n if (options !== undefined) {\n assertKnownKeys(options, ATTACH_OPTION_KEYS, `${label} options`);\n }\n const native = nativeSession(session as Session);\n const snapshot = captureArguments(args);\n const local = context.authorize(\n native,\n name,\n snapshot.json,\n options?.approvals,\n undefined,\n options?.requestId,\n );\n emitReceipt(options?.onReceipt, local.receipt, session, host);\n decide(local, name, native, snapshot.executionArgs());\n const envelope = context.signMeta(\n native,\n name,\n snapshot.json,\n Math.floor(Date.now() / 1000),\n options?.approvals ?? null,\n );\n const presented = {\n warrant: envelope.warrant,\n signature: envelope.signature,\n ...(envelope.approvals !== undefined && envelope.approvals.length > 0\n ? { approvals: envelope.approvals }\n : {}),\n };\n return { presented, wireArgs: snapshot.executionArgs() };\n}\n\n/**\n * Transport-agnostic half of `verify`: check a presented warrant chain and\n * proof-of-possession, then apply the host ceiling. Shared by\n * `tenuo.verify()` and `tenuo.mcp.verify()`.\n */\nexport async function verifyPresented(\n context: WasmContext,\n decide: Decide,\n presented: PresentedCall,\n name: string,\n args: Readonly<Record<string, unknown>>,\n options: McpVerifyOptions | undefined,\n label: string,\n host?: object,\n): Promise<Readonly<Record<string, unknown>>> {\n if (options !== undefined) {\n assertKnownKeys(options, VERIFY_OPTION_KEYS, `${label} options`);\n }\n const envelope = presentedEnvelope(presented);\n if (envelope === undefined) {\n throw new TenuoConfigurationError(\n `${label} needs { warrant, signature } from tenuo.present() or tenuo.mcp.attach()`,\n );\n }\n // Capture once: replay admission and receipt callbacks may yield or mutate\n // the caller's object. Execution must use the exact snapshot verified here.\n const snapshot = captureArguments(args);\n const decision = context.authorizePresented(\n envelope.warrant,\n name,\n snapshot.json,\n envelope.signature,\n envelope.approvals,\n options?.allow,\n options?.requestId,\n );\n // Rust already signed this envelope. Emit before the nonce store can\n // refuse a replay — otherwise an attacker leaves no audit artifact.\n emitReceipt(options?.onReceipt, decision.receipt, undefined, host);\n if (decision.outcome === \"allow\") {\n await admitPop(options?.nonceStore, envelope.signature, options?.onNonceStoreError);\n }\n decide(decision, name);\n // Run the host parse of the JSON text the proof covers. The raw host\n // object can contain values that JSON drops.\n return snapshot.executionArgs();\n}\n\nexport function createMcp(context: WasmContext, decide: Decide, host?: object): TenuoMcp {\n const mcp: TenuoMcp = {\n attach(session, name, args, options) {\n const { presented, wireArgs } = presentCall(\n context,\n decide,\n session,\n name,\n args,\n options,\n \"mcp.attach()\",\n host,\n );\n return { name, arguments: wireArgs, _meta: { tenuo: presented } };\n },\n\n async verify(name, args, meta, options) {\n const envelope = tenuoEnvelope(meta);\n if (envelope === undefined) {\n throw new TenuoConfigurationError(\n \"MCP call is missing _meta.tenuo. The client must call tenuo.mcp.attach().\",\n );\n }\n return verifyPresented(context, decide, envelope, name, args, options, \"mcp.verify()\", host);\n },\n\n handler(name, policyOrExecute, maybeExecute?) {\n const policy = isHandlerPolicy(policyOrExecute) ? policyOrExecute : undefined;\n const execute = isHandlerPolicy(policyOrExecute) ? maybeExecute : policyOrExecute;\n if (typeof execute !== \"function\") {\n throw new TenuoConfigurationError(\"mcp.handler() requires an execute function\");\n }\n return async (args, extra) => {\n const authorized = await mcp.verify(name, args, extra?._meta ?? extra?.meta, {\n ...(policy?.allow !== undefined ? { allow: policy.allow } : {}),\n ...(policy?.onReceipt !== undefined ? { onReceipt: policy.onReceipt } : {}),\n ...(policy?.nonceStore !== undefined ? { nonceStore: policy.nonceStore } : {}),\n ...(policy?.onNonceStoreError !== undefined ? { onNonceStoreError: policy.onNonceStoreError } : {}),\n });\n return execute(authorized as never);\n };\n },\n\n jsonRpcError(error) {\n return jsonRpcError(error);\n },\n };\n return mcp;\n}\n\n/** A private immutable input snapshot, not an authorization token. */\nfunction captureArguments(args: Readonly<Record<string, unknown>>): {\n readonly json: string;\n executionArgs(): Record<string, unknown>;\n} {\n const text = JSON.stringify(args);\n if (typeof text !== \"string\") {\n throw new TenuoConfigurationError(\"arguments must be JSON\");\n }\n return Object.freeze({\n json: text,\n executionArgs: () => plainArgs(JSON.parse(text)),\n });\n}\n\nfunction presentedEnvelope(\n value: unknown,\n): { warrant: string; signature: string; approvals?: string[] } | undefined {\n if (value === null || typeof value !== \"object\") {\n return undefined;\n }\n const tenuo = value as { warrant?: unknown; signature?: unknown; approvals?: unknown };\n if (typeof tenuo.warrant !== \"string\" || tenuo.warrant.length === 0) {\n return undefined;\n }\n if (typeof tenuo.signature !== \"string\" || tenuo.signature.length === 0) {\n return undefined;\n }\n if (tenuo.approvals != null &&\n (!Array.isArray(tenuo.approvals) || tenuo.approvals.some((item) => typeof item !== \"string\"))) {\n return undefined;\n }\n const approvals = tenuo.approvals ?? undefined;\n return {\n warrant: tenuo.warrant,\n signature: tenuo.signature,\n ...(approvals !== undefined && approvals.length > 0 ? { approvals } : {}),\n };\n}\n\nfunction tenuoEnvelope(\n meta: unknown,\n): { warrant: string; signature: string; approvals?: string[] } | undefined {\n if (meta === null || typeof meta !== \"object\") {\n return undefined;\n }\n const root = meta as { tenuo?: unknown; _meta?: unknown };\n const block = root.tenuo ?? (root._meta as { tenuo?: unknown } | undefined)?.tenuo;\n return presentedEnvelope(block);\n}\n\nconst HANDLER_POLICY_KEYS = new Set([\"allow\", \"onReceipt\", \"nonceStore\", \"onNonceStoreError\"]);\nconst VERIFY_OPTION_KEYS = new Set([\n \"allow\",\n \"onReceipt\",\n \"nonceStore\",\n \"onNonceStoreError\",\n \"requestId\",\n]);\nconst REPLAY_STORE_UNAVAILABLE = \"Replay store unavailable\";\nconst ATTACH_OPTION_KEYS = new Set([\"approvals\", \"onReceipt\", \"requestId\"]);\nfunction assertKnownKeys(value: object, known: ReadonlySet<string>, label: string): void {\n const unknown = Object.keys(value).filter((key) => !known.has(key));\n if (unknown[0] !== undefined) {\n throw new TenuoConfigurationError(\n `${label} has unknown key '${unknown[0]}'. Use ${[...known].join(\", \")}.`,\n );\n }\n}\n\nfunction isHandlerPolicy(value: unknown): value is McpHandlerPolicy {\n if (value === null || typeof value !== \"object\" || Array.isArray(value) || typeof value === \"function\") {\n return false;\n }\n const keys = Object.keys(value);\n assertKnownKeys(value, HANDLER_POLICY_KEYS, \"mcp.handler() policy\");\n const record = value as {\n allow?: unknown;\n onReceipt?: unknown;\n nonceStore?: unknown;\n onNonceStoreError?: unknown;\n };\n const hasAllow =\n \"allow\" in record && record.allow !== null && typeof record.allow === \"object\" && !Array.isArray(record.allow);\n const hasReceipt = \"onReceipt\" in record && typeof record.onReceipt === \"function\";\n const hasNonce = \"nonceStore\" in record && record.nonceStore !== null && typeof record.nonceStore === \"object\";\n const hasStoreError = \"onNonceStoreError\" in record && typeof record.onNonceStoreError === \"function\";\n return keys.length === 0 || hasAllow || hasReceipt || hasNonce || hasStoreError;\n}\n\nasync function admitPop(\n store: { checkAndRecord(popSignature: string): boolean | Promise<boolean> } | undefined,\n signature: string,\n onNonceStoreError?: (error: unknown) => void | Promise<void>,\n): Promise<void> {\n if (store === undefined) {\n return;\n }\n let admitted: boolean | Promise<boolean>;\n try {\n admitted = store.checkAndRecord(signature);\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 new AuthorizationDeniedError(\n \"TENUO_INVALID_POP\",\n \"PoP replay detected — this exact authorization token was already consumed.\",\n );\n }\n}\n\nfunction replayStoreUnavailable(\n cause: unknown,\n onNonceStoreError?: (error: unknown) => void | Promise<void>,\n): TenuoConfigurationError {\n emitIsolated(onNonceStoreError, cause);\n const error = new TenuoConfigurationError(REPLAY_STORE_UNAVAILABLE);\n if (cause !== undefined) {\n error.cause = cause;\n }\n return error;\n}\n\nfunction emitIsolated(\n hook: ((error: unknown) => void | Promise<void>) | undefined,\n error: unknown,\n): void {\n if (hook === undefined) {\n return;\n }\n try {\n const result = hook(error);\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\nfunction isThenable(value: unknown): value is Promise<boolean> {\n return value !== null && typeof value === \"object\" && \"then\" in value && typeof value.then === \"function\";\n}\n\nfunction emitReceipt(\n onReceipt: ((receipt: string) => void | Promise<void>) | undefined,\n receipt: string | undefined,\n session?: SessionContract,\n host?: object,\n): void {\n collectReceipt(receipt, session, host);\n emitIsolatedReceipt(onReceipt, receipt);\n}\n\nfunction plainArgs(value: unknown): Record<string, unknown> {\n if (value instanceof Map) {\n return Object.fromEntries(value);\n }\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n return { ...(value as Record<string, unknown>) };\n }\n return {};\n}\n\nfunction jsonRpcError(error: unknown): McpJsonRpcError {\n if (error instanceof TenuoError) {\n const code: TenuoErrorCode = error.code;\n const rpc = code === \"TENUO_APPROVAL_REQUIRED\" ? -32002 : code === \"TENUO_CANONICALIZATION\" ? -32602 : -32001;\n return { code: rpc, message: error.message, data: { tenuo: { code } } };\n }\n const message = error instanceof Error ? error.message : String(error);\n return { code: -32001, message };\n}\n"]}
|
package/dist/wasm.d.ts
CHANGED
|
@@ -147,6 +147,7 @@ export type WasmExplainField = {
|
|
|
147
147
|
constraint: unknown;
|
|
148
148
|
value?: unknown;
|
|
149
149
|
satisfied: boolean;
|
|
150
|
+
reason_code?: string;
|
|
150
151
|
reason?: string;
|
|
151
152
|
};
|
|
152
153
|
export type WasmExplain = {
|
|
@@ -222,6 +223,15 @@ export type WasmContext = {
|
|
|
222
223
|
loadRevocationList(srl: string): void;
|
|
223
224
|
signRevocationList(ids: string[]): string;
|
|
224
225
|
signPop(session: WasmSession, tool: string, args: unknown): string;
|
|
226
|
+
signMeta(session: WasmSession, tool: string, argsJson: string, timestamp: number, approvals?: unknown): {
|
|
227
|
+
warrant: string;
|
|
228
|
+
signature: string;
|
|
229
|
+
approvals?: string[];
|
|
230
|
+
};
|
|
231
|
+
/** Holder proof only; does not authorize execution. */
|
|
232
|
+
verifyMetaPop(warrant: string, signature: string, tool: string, argsJson: string, timestamp: number): boolean;
|
|
233
|
+
/** Compatibility alias for verifyMetaPop. */
|
|
234
|
+
verifyMeta(warrant: string, signature: string, tool: string, argsJson: string, timestamp: number): boolean;
|
|
225
235
|
authorizePresented(warrants: unknown, tool: string, args: unknown, pop: string, approvals?: unknown, toolAllow?: unknown, requestId?: string): WasmDecision;
|
|
226
236
|
};
|
|
227
237
|
type Generated = {
|
|
@@ -259,6 +269,7 @@ type Generated = {
|
|
|
259
269
|
tool: string;
|
|
260
270
|
error?: string;
|
|
261
271
|
};
|
|
272
|
+
parse_strict_json(jsonText: string): void;
|
|
262
273
|
};
|
|
263
274
|
export declare function wasmAvailable(): boolean;
|
|
264
275
|
export declare function loadWasm(): Generated;
|
|
@@ -290,6 +301,15 @@ export type ApprovalGateInspection = {
|
|
|
290
301
|
arguments: string[];
|
|
291
302
|
message?: string;
|
|
292
303
|
};
|
|
304
|
+
/**
|
|
305
|
+
* Parse JSON text and reject a repeated key in any object.
|
|
306
|
+
*
|
|
307
|
+
* `verify()` receives an object the host already parsed. A duplicate key is
|
|
308
|
+
* gone by then. Call this while the text is still available. After the check,
|
|
309
|
+
* the value is `JSON.parse` of the original text, so each key is an own data
|
|
310
|
+
* property and `null` stays `null`.
|
|
311
|
+
*/
|
|
312
|
+
export declare function parseStrictJson(text: string): unknown;
|
|
293
313
|
/**
|
|
294
314
|
* Typed preflight of a warrant's approval gates for `(tool, args)`.
|
|
295
315
|
*
|