@tenuo/core 0.2.5-beta.0 → 0.3.1-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/README.md +18 -6
- package/dist/api.d.ts +32 -5
- package/dist/api.js.map +1 -1
- package/dist/build-info.json +8 -0
- package/dist/client.d.ts +7 -1
- package/dist/client.js +32 -22
- package/dist/client.js.map +1 -1
- package/dist/connect.d.ts +53 -0
- package/dist/connect.js +177 -0
- package/dist/connect.js.map +1 -0
- package/dist/constraints.d.ts +29 -2
- package/dist/constraints.js +68 -19
- package/dist/constraints.js.map +1 -1
- package/dist/errors.d.ts +0 -1
- package/dist/errors.js.map +1 -1
- package/dist/generated/tenuo_wasm.d.ts +31 -4
- package/dist/generated/tenuo_wasm.js +65 -4
- package/dist/generated/tenuo_wasm_bg.wasm +0 -0
- package/dist/generated/tenuo_wasm_bg.wasm.d.ts +3 -0
- package/dist/identity.d.ts +25 -0
- package/dist/identity.js +61 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +3 -4
- package/dist/mcp.js +11 -20
- package/dist/mcp.js.map +1 -1
- package/dist/nonce.d.ts +0 -1
- package/dist/nonce.js.map +1 -1
- package/dist/receipts.d.ts +27 -0
- package/dist/receipts.js +128 -0
- package/dist/receipts.js.map +1 -0
- package/dist/runtime.d.ts +51 -0
- package/dist/runtime.js +102 -0
- package/dist/runtime.js.map +1 -0
- package/dist/session.d.ts +7 -1
- package/dist/session.js +14 -0
- package/dist/session.js.map +1 -1
- package/dist/wasm.d.ts +49 -4
- package/dist/wasm.js +53 -6
- package/dist/wasm.js.map +1 -1
- package/package.json +2 -2
- package/dist/api.d.ts.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/constraints.d.ts.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/mcp.d.ts.map +0 -1
- package/dist/nonce.d.ts.map +0 -1
- package/dist/session.d.ts.map +0 -1
- package/dist/wasm.d.ts.map +0 -1
package/dist/constraints.js
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
|
+
import { TenuoConfigurationError } from "./errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Builders throw on a misspelled option instead of dropping it: an option
|
|
4
|
+
* that vanishes silently (`urlSafe({ domains })`) widens authority. The core
|
|
5
|
+
* applies the same rule to raw constraint objects when the policy compiles.
|
|
6
|
+
*/
|
|
7
|
+
function rejectUnknownOptions(builder, options, allowed) {
|
|
8
|
+
if (options === undefined || options === null) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (typeof options !== "object" || Array.isArray(options)) {
|
|
12
|
+
throw new TenuoConfigurationError(`tenuo.${builder}() expects an options object`);
|
|
13
|
+
}
|
|
14
|
+
const unknown = Object.keys(options).find((key) => !allowed.includes(key));
|
|
15
|
+
if (unknown !== undefined) {
|
|
16
|
+
throw new TenuoConfigurationError(`tenuo.${builder}() received unknown option "${unknown}"; allowed options: ${allowed.join(", ")}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
1
19
|
/**
|
|
2
20
|
* Constraint builders. These produce plain marker objects; every one is
|
|
3
21
|
* evaluated by the Rust core, never in TypeScript. The set matches the
|
|
4
|
-
* Python SDK and the core `Constraint` enum one for one.
|
|
22
|
+
* Python SDK and the core `Constraint` enum one for one. Builders that
|
|
23
|
+
* validate their input throw `TenuoConfigurationError` at the call site.
|
|
24
|
+
* Deeper checks, such as regex syntax, run in the core when `session()`
|
|
25
|
+
* compiles the policy. Nothing here makes an authorization decision.
|
|
5
26
|
*/
|
|
6
27
|
/** Directory prefix. Evaluated in core as Subpath — not a string prefix check in TS. */
|
|
7
28
|
export function under(root, options) {
|
|
29
|
+
rejectUnknownOptions("under", options, ["caseSensitive", "allowEqual"]);
|
|
8
30
|
if (!root.startsWith("/")) {
|
|
9
|
-
throw new
|
|
31
|
+
throw new TenuoConfigurationError("tenuo.under() expects an absolute path (start with /)");
|
|
10
32
|
}
|
|
11
33
|
const out = {
|
|
12
34
|
kind: "under",
|
|
@@ -21,32 +43,34 @@ export function under(root, options) {
|
|
|
21
43
|
return out;
|
|
22
44
|
}
|
|
23
45
|
export function email(options) {
|
|
46
|
+
rejectUnknownOptions("email", options, ["domain"]);
|
|
24
47
|
return { kind: "email", domain: options.domain };
|
|
25
48
|
}
|
|
26
49
|
export function max(value) {
|
|
27
50
|
if (!Number.isFinite(value)) {
|
|
28
|
-
throw new
|
|
51
|
+
throw new TenuoConfigurationError("tenuo.max() requires a finite number");
|
|
29
52
|
}
|
|
30
53
|
return { kind: "max", value };
|
|
31
54
|
}
|
|
32
55
|
export function min(value) {
|
|
33
56
|
if (!Number.isFinite(value)) {
|
|
34
|
-
throw new
|
|
57
|
+
throw new TenuoConfigurationError("tenuo.min() requires a finite number");
|
|
35
58
|
}
|
|
36
59
|
return { kind: "min", value };
|
|
37
60
|
}
|
|
38
61
|
/** Numeric interval. Bounds are inclusive unless `minExclusive` / `maxExclusive`. */
|
|
39
62
|
export function range(options) {
|
|
63
|
+
rejectUnknownOptions("range", options, ["min", "max", "minExclusive", "maxExclusive"]);
|
|
40
64
|
if (options.min === undefined && options.max === undefined) {
|
|
41
|
-
throw new
|
|
65
|
+
throw new TenuoConfigurationError("tenuo.range() requires min, max, or both");
|
|
42
66
|
}
|
|
43
67
|
for (const bound of [options.min, options.max]) {
|
|
44
68
|
if (bound !== undefined && !Number.isFinite(bound)) {
|
|
45
|
-
throw new
|
|
69
|
+
throw new TenuoConfigurationError("tenuo.range() bounds must be finite numbers");
|
|
46
70
|
}
|
|
47
71
|
}
|
|
48
72
|
if (options.min !== undefined && options.max !== undefined && options.min > options.max) {
|
|
49
|
-
throw new
|
|
73
|
+
throw new TenuoConfigurationError("tenuo.range() min must not exceed max");
|
|
50
74
|
}
|
|
51
75
|
const out = { kind: "range" };
|
|
52
76
|
if (options.min !== undefined) {
|
|
@@ -65,27 +89,51 @@ export function range(options) {
|
|
|
65
89
|
}
|
|
66
90
|
export function oneOf(values) {
|
|
67
91
|
if (values.length === 0) {
|
|
68
|
-
throw new
|
|
92
|
+
throw new TenuoConfigurationError("tenuo.oneOf() requires at least one value");
|
|
69
93
|
}
|
|
70
94
|
return { kind: "oneOf", values };
|
|
71
95
|
}
|
|
72
96
|
/** Any value except these. */
|
|
73
97
|
export function notOneOf(values) {
|
|
74
98
|
if (values.length === 0) {
|
|
75
|
-
throw new
|
|
99
|
+
throw new TenuoConfigurationError("tenuo.notOneOf() requires at least one value");
|
|
76
100
|
}
|
|
77
101
|
return { kind: "notOneOf", values };
|
|
78
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Generic string glob. `*` matches `/`; this is not path containment.
|
|
105
|
+
* For filesystem arguments, use `pathGlob(root, glob)`.
|
|
106
|
+
*/
|
|
79
107
|
export function pattern(pattern) {
|
|
80
108
|
if (pattern.length === 0) {
|
|
81
|
-
throw new
|
|
109
|
+
throw new TenuoConfigurationError("tenuo.pattern() requires a non-empty pattern");
|
|
82
110
|
}
|
|
83
111
|
return { kind: "pattern", pattern };
|
|
84
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* A traversal-safe filesystem glob: the value must stay under `root` and
|
|
115
|
+
* match `glob`.
|
|
116
|
+
*
|
|
117
|
+
* The glob is tested against the whole path, not against the part below
|
|
118
|
+
* `root`, so it matches at any depth:
|
|
119
|
+
*
|
|
120
|
+
* ```ts
|
|
121
|
+
* pathGlob("/workspace", "*.json");
|
|
122
|
+
* // /workspace/reports/q3.json allowed
|
|
123
|
+
* // /workspace/secrets.env denied (glob)
|
|
124
|
+
* // /etc/passwd.json denied (root)
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* A delegatee can narrow this to a tighter `pathGlob`, or to an `exact()`
|
|
128
|
+
* path the parent already admits.
|
|
129
|
+
*/
|
|
130
|
+
export function pathGlob(root, glob, options) {
|
|
131
|
+
return all([under(root, options), pattern(glob)]);
|
|
132
|
+
}
|
|
85
133
|
/** Regular expression, compiled and evaluated in core. */
|
|
86
134
|
export function regex(source) {
|
|
87
135
|
if (source.length === 0) {
|
|
88
|
-
throw new
|
|
136
|
+
throw new TenuoConfigurationError("tenuo.regex() requires a non-empty expression");
|
|
89
137
|
}
|
|
90
138
|
return { kind: "regex", source };
|
|
91
139
|
}
|
|
@@ -99,14 +147,14 @@ export function wildcard() {
|
|
|
99
147
|
/** IP address inside a network, e.g. `cidr("10.0.0.0/8")`. */
|
|
100
148
|
export function cidr(network) {
|
|
101
149
|
if (!network.includes("/")) {
|
|
102
|
-
throw new
|
|
150
|
+
throw new TenuoConfigurationError("tenuo.cidr() expects CIDR notation like 10.0.0.0/8");
|
|
103
151
|
}
|
|
104
152
|
return { kind: "cidr", network };
|
|
105
153
|
}
|
|
106
154
|
/** URL glob, e.g. `urlPattern("https://*.example.com/api/*")`. Parsed as a URL, not a string. */
|
|
107
155
|
export function urlPattern(pattern) {
|
|
108
156
|
if (pattern.length === 0) {
|
|
109
|
-
throw new
|
|
157
|
+
throw new TenuoConfigurationError("tenuo.urlPattern() requires a non-empty pattern");
|
|
110
158
|
}
|
|
111
159
|
return { kind: "urlPattern", pattern };
|
|
112
160
|
}
|
|
@@ -115,6 +163,7 @@ export function urlPattern(pattern) {
|
|
|
115
163
|
* hosts rejected, optional allow and deny domain lists (`*.example.com`).
|
|
116
164
|
*/
|
|
117
165
|
export function urlSafe(options) {
|
|
166
|
+
rejectUnknownOptions("urlSafe", options, ["schemes", "allowDomains", "denyDomains"]);
|
|
118
167
|
const out = { kind: "urlSafe" };
|
|
119
168
|
if (options?.schemes !== undefined) {
|
|
120
169
|
out.schemes = options.schemes;
|
|
@@ -130,35 +179,35 @@ export function urlSafe(options) {
|
|
|
130
179
|
/** Shell command whose first word must be one of `allow`. Parsed with shell quoting rules in core. */
|
|
131
180
|
export function shlex(allow) {
|
|
132
181
|
if (allow.length === 0) {
|
|
133
|
-
throw new
|
|
182
|
+
throw new TenuoConfigurationError("tenuo.shlex() requires at least one allowed command");
|
|
134
183
|
}
|
|
135
184
|
return { kind: "shlex", allow };
|
|
136
185
|
}
|
|
137
186
|
/** List argument that must include every one of these values. */
|
|
138
187
|
export function contains(values) {
|
|
139
188
|
if (values.length === 0) {
|
|
140
|
-
throw new
|
|
189
|
+
throw new TenuoConfigurationError("tenuo.contains() requires at least one value");
|
|
141
190
|
}
|
|
142
191
|
return { kind: "contains", values };
|
|
143
192
|
}
|
|
144
193
|
/** List argument whose every element must be one of these values. */
|
|
145
194
|
export function subset(values) {
|
|
146
195
|
if (values.length === 0) {
|
|
147
|
-
throw new
|
|
196
|
+
throw new TenuoConfigurationError("tenuo.subset() requires at least one value");
|
|
148
197
|
}
|
|
149
198
|
return { kind: "subset", values };
|
|
150
199
|
}
|
|
151
200
|
/** Satisfied when at least one inner constraint is. */
|
|
152
201
|
export function anyOf(constraints) {
|
|
153
202
|
if (constraints.length === 0) {
|
|
154
|
-
throw new
|
|
203
|
+
throw new TenuoConfigurationError("tenuo.anyOf() requires at least one constraint");
|
|
155
204
|
}
|
|
156
205
|
return { kind: "anyOf", constraints };
|
|
157
206
|
}
|
|
158
207
|
/** Satisfied only when every inner constraint is. */
|
|
159
208
|
export function all(constraints) {
|
|
160
209
|
if (constraints.length === 0) {
|
|
161
|
-
throw new
|
|
210
|
+
throw new TenuoConfigurationError("tenuo.all() requires at least one constraint");
|
|
162
211
|
}
|
|
163
212
|
return { kind: "all", constraints };
|
|
164
213
|
}
|
|
@@ -169,7 +218,7 @@ export function not(constraint) {
|
|
|
169
218
|
/** Common Expression Language predicate over the argument value, evaluated in core. */
|
|
170
219
|
export function cel(expression) {
|
|
171
220
|
if (expression.trim().length === 0) {
|
|
172
|
-
throw new
|
|
221
|
+
throw new TenuoConfigurationError("tenuo.cel() requires a non-empty expression");
|
|
173
222
|
}
|
|
174
223
|
return { kind: "cel", expression };
|
|
175
224
|
}
|
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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"}
|
|
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"]}
|
package/dist/errors.d.ts
CHANGED
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,UAAW,SAAQ,KAAK;IAC1B,IAAI,CAAiB;IAE9B,YAAY,IAAoB,EAAE,OAAe;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,UAAU;IACrD,YAAY,OAAe,EAAE,OAAuB,qBAAqB;QACvE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,UAAU;IAC7C,KAAK,CAAU;IAExB,YAAY,IAAoB,EAAE,OAAe,EAAE,KAAc;QAC/D,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,UAAU;IAC1C,IAAI,CAAS;IACb,QAAQ,CAAS;IACjB,QAAQ,CAAS;IAC1B;;;;OAIG;IACM,OAAO,CAAmB;IAEnC,YAAY,IAAY,EAAE,QAAgB,EAAE,QAAgB,EAAE,OAAgB,EAAE,OAAyB;QACvG,KAAK,CAAC,yBAAyB,EAAE,OAAO,IAAI,yBAAyB,IAAI,EAAE,CAAC,CAAC;QAC7E,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACzB,CAAC;IACH,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,UAAW,SAAQ,KAAK;IAC1B,IAAI,CAAiB;IAE9B,YAAY,IAAoB,EAAE,OAAe;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,UAAU;IACrD,YAAY,OAAe,EAAE,OAAuB,qBAAqB;QACvE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,UAAU;IAC7C,KAAK,CAAU;IAExB,YAAY,IAAoB,EAAE,OAAe,EAAE,KAAc;QAC/D,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,UAAU;IAC1C,IAAI,CAAS;IACb,QAAQ,CAAS;IACjB,QAAQ,CAAS;IAC1B;;;;OAIG;IACM,OAAO,CAAmB;IAEnC,YAAY,IAAY,EAAE,QAAgB,EAAE,QAAgB,EAAE,OAAgB,EAAE,OAAyB;QACvG,KAAK,CAAC,yBAAyB,EAAE,OAAO,IAAI,yBAAyB,IAAI,EAAE,CAAC,CAAC;QAC7E,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACzB,CAAC;IACH,CAAC;CACF","sourcesContent":["import type { ApprovalRequest, TenuoErrorCode } from \"./api.ts\";\n\nexport class TenuoError extends Error {\n readonly code: TenuoErrorCode;\n\n constructor(code: TenuoErrorCode, message: string) {\n super(message);\n this.name = \"TenuoError\";\n this.code = code;\n }\n}\n\nexport class TenuoConfigurationError extends TenuoError {\n constructor(message: string, code: TenuoErrorCode = \"TENUO_CONFIGURATION\") {\n super(code, message);\n this.name = \"TenuoConfigurationError\";\n }\n}\n\nexport class AuthorizationDeniedError extends TenuoError {\n readonly field?: string;\n\n constructor(code: TenuoErrorCode, message: string, field?: string) {\n super(code, message);\n this.name = \"AuthorizationDeniedError\";\n if (field !== undefined) {\n this.field = field;\n }\n }\n}\n\nexport class ApprovalRequiredError extends TenuoError {\n readonly tool: string;\n readonly required: number;\n readonly received: number;\n /**\n * What to send to an approval service, when the SDK had the session at\n * hand. Absent on the server-side verify path, where only the caller can\n * build it.\n */\n readonly request?: ApprovalRequest;\n\n constructor(tool: string, required: number, received: number, message?: string, request?: ApprovalRequest) {\n super(\"TENUO_APPROVAL_REQUIRED\", message ?? `Approval required for ${tool}`);\n this.name = \"ApprovalRequiredError\";\n this.tool = tool;\n this.required = required;\n this.received = received;\n if (request !== undefined) {\n this.request = request;\n }\n }\n}\n"]}
|
|
@@ -118,6 +118,11 @@ export class SdkContext {
|
|
|
118
118
|
* `loadRevocationList` anywhere this issuer is a trusted root.
|
|
119
119
|
*/
|
|
120
120
|
signRevocationListVersioned(ids: any, version?: number | null): string;
|
|
121
|
+
/**
|
|
122
|
+
* Sign verifier receipts with this 32-byte holder secret instead of an
|
|
123
|
+
* ephemeral key. Used by the TypeScript `Runtime`.
|
|
124
|
+
*/
|
|
125
|
+
withReceiptSigner(secret: Uint8Array): SdkContext;
|
|
121
126
|
}
|
|
122
127
|
|
|
123
128
|
/**
|
|
@@ -172,6 +177,16 @@ export class SdkSession {
|
|
|
172
177
|
warrantIds(): any;
|
|
173
178
|
}
|
|
174
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Typed preflight of a warrant's approval gates for `(tool, args)`.
|
|
182
|
+
*
|
|
183
|
+
* Returns `{ status: "not_gated"|"exempt"|"required"|"denied", tool, kind?,
|
|
184
|
+
* argument?, arguments, message?, code?, reason?, error? }`. Parse errors
|
|
185
|
+
* fail closed with `status: "required"` and `error` set (no fabricated
|
|
186
|
+
* `kind`). `denied` means the warrant's constraints refuse the call.
|
|
187
|
+
*/
|
|
188
|
+
export function approval_requirement(warrant_b64: string, tool: string, args_json: any): any;
|
|
189
|
+
|
|
175
190
|
export function check_access(warrant_b64: string, tool: string, args_json: any, trusted_root_hex: string, dry_run: boolean): any;
|
|
176
191
|
|
|
177
192
|
/**
|
|
@@ -248,6 +263,9 @@ export function decode_warrant(base64_warrant: string): any;
|
|
|
248
263
|
* Returns `{ approval_required: true/false, tool, error }`.
|
|
249
264
|
* This reads `extensions["tenuo.approval_gates"]` from the warrant, parses it,
|
|
250
265
|
* and runs the gate evaluation logic from tenuo-core.
|
|
266
|
+
*
|
|
267
|
+
* Malformed warrants, gate maps, or arguments fail closed (`approval_required: true`).
|
|
268
|
+
* Prefer `approval_requirement` when the caller must distinguish exemptions.
|
|
251
269
|
*/
|
|
252
270
|
export function evaluate_approval_gates(warrant_b64: string, tool: string, args_json: any): any;
|
|
253
271
|
|
|
@@ -259,11 +277,20 @@ export function generate_keypair(): any;
|
|
|
259
277
|
export function init_panic_hook(): void;
|
|
260
278
|
|
|
261
279
|
/**
|
|
262
|
-
*
|
|
280
|
+
* Inspect how a warrant gates `tool`, without evaluating arguments.
|
|
281
|
+
*
|
|
282
|
+
* Returns `{ kind: "none"|"whole_tool"|"conditional", tool, arguments, message?, error? }`.
|
|
283
|
+
* Parse errors fail closed with `kind: "unknown"` and `error` set so callers
|
|
284
|
+
* cannot treat a malformed map as ungated.
|
|
285
|
+
*/
|
|
286
|
+
export function inspect_approval_gate(warrant_b64: string, tool: string): any;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Parse a complete `tenuo_ct_…` token into its component fields.
|
|
263
290
|
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
291
|
+
* Accepts padded and unpadded Base64URL. Version must be 1; omitted `v`
|
|
292
|
+
* is an error. Trailing `/v1` is stripped from `e`.
|
|
293
|
+
* Registration-token aliases: `t`, `r`, `registration_token`.
|
|
267
294
|
*
|
|
268
295
|
* Returns `{ endpoint, apiKey, agentId?, registrationToken?, error? }`.
|
|
269
296
|
*/
|
|
@@ -371,6 +371,22 @@ class SdkContext {
|
|
|
371
371
|
wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* Sign verifier receipts with this 32-byte holder secret instead of an
|
|
376
|
+
* ephemeral key. Used by the TypeScript `Runtime`.
|
|
377
|
+
* @param {Uint8Array} secret
|
|
378
|
+
* @returns {SdkContext}
|
|
379
|
+
*/
|
|
380
|
+
withReceiptSigner(secret) {
|
|
381
|
+
const ptr = this.__destroy_into_raw();
|
|
382
|
+
const ptr0 = passArray8ToWasm0(secret, wasm.__wbindgen_malloc);
|
|
383
|
+
const len0 = WASM_VECTOR_LEN;
|
|
384
|
+
const ret = wasm.sdkcontext_withReceiptSigner(ptr, ptr0, len0);
|
|
385
|
+
if (ret[2]) {
|
|
386
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
387
|
+
}
|
|
388
|
+
return SdkContext.__wrap(ret[0]);
|
|
389
|
+
}
|
|
374
390
|
}
|
|
375
391
|
if (Symbol.dispose) SdkContext.prototype[Symbol.dispose] = SdkContext.prototype.free;
|
|
376
392
|
exports.SdkContext = SdkContext;
|
|
@@ -550,6 +566,28 @@ class SdkSession {
|
|
|
550
566
|
if (Symbol.dispose) SdkSession.prototype[Symbol.dispose] = SdkSession.prototype.free;
|
|
551
567
|
exports.SdkSession = SdkSession;
|
|
552
568
|
|
|
569
|
+
/**
|
|
570
|
+
* Typed preflight of a warrant's approval gates for `(tool, args)`.
|
|
571
|
+
*
|
|
572
|
+
* Returns `{ status: "not_gated"|"exempt"|"required"|"denied", tool, kind?,
|
|
573
|
+
* argument?, arguments, message?, code?, reason?, error? }`. Parse errors
|
|
574
|
+
* fail closed with `status: "required"` and `error` set (no fabricated
|
|
575
|
+
* `kind`). `denied` means the warrant's constraints refuse the call.
|
|
576
|
+
* @param {string} warrant_b64
|
|
577
|
+
* @param {string} tool
|
|
578
|
+
* @param {any} args_json
|
|
579
|
+
* @returns {any}
|
|
580
|
+
*/
|
|
581
|
+
function approval_requirement(warrant_b64, tool, args_json) {
|
|
582
|
+
const ptr0 = passStringToWasm0(warrant_b64, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
583
|
+
const len0 = WASM_VECTOR_LEN;
|
|
584
|
+
const ptr1 = passStringToWasm0(tool, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
585
|
+
const len1 = WASM_VECTOR_LEN;
|
|
586
|
+
const ret = wasm.approval_requirement(ptr0, len0, ptr1, len1, args_json);
|
|
587
|
+
return ret;
|
|
588
|
+
}
|
|
589
|
+
exports.approval_requirement = approval_requirement;
|
|
590
|
+
|
|
553
591
|
/**
|
|
554
592
|
* @param {string} warrant_b64
|
|
555
593
|
* @param {string} tool
|
|
@@ -767,6 +805,9 @@ exports.decode_warrant = decode_warrant;
|
|
|
767
805
|
* Returns `{ approval_required: true/false, tool, error }`.
|
|
768
806
|
* This reads `extensions["tenuo.approval_gates"]` from the warrant, parses it,
|
|
769
807
|
* and runs the gate evaluation logic from tenuo-core.
|
|
808
|
+
*
|
|
809
|
+
* Malformed warrants, gate maps, or arguments fail closed (`approval_required: true`).
|
|
810
|
+
* Prefer `approval_requirement` when the caller must distinguish exemptions.
|
|
770
811
|
* @param {string} warrant_b64
|
|
771
812
|
* @param {string} tool
|
|
772
813
|
* @param {any} args_json
|
|
@@ -798,11 +839,31 @@ function init_panic_hook() {
|
|
|
798
839
|
exports.init_panic_hook = init_panic_hook;
|
|
799
840
|
|
|
800
841
|
/**
|
|
801
|
-
*
|
|
842
|
+
* Inspect how a warrant gates `tool`, without evaluating arguments.
|
|
843
|
+
*
|
|
844
|
+
* Returns `{ kind: "none"|"whole_tool"|"conditional", tool, arguments, message?, error? }`.
|
|
845
|
+
* Parse errors fail closed with `kind: "unknown"` and `error` set so callers
|
|
846
|
+
* cannot treat a malformed map as ungated.
|
|
847
|
+
* @param {string} warrant_b64
|
|
848
|
+
* @param {string} tool
|
|
849
|
+
* @returns {any}
|
|
850
|
+
*/
|
|
851
|
+
function inspect_approval_gate(warrant_b64, tool) {
|
|
852
|
+
const ptr0 = passStringToWasm0(warrant_b64, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
853
|
+
const len0 = WASM_VECTOR_LEN;
|
|
854
|
+
const ptr1 = passStringToWasm0(tool, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
855
|
+
const len1 = WASM_VECTOR_LEN;
|
|
856
|
+
const ret = wasm.inspect_approval_gate(ptr0, len0, ptr1, len1);
|
|
857
|
+
return ret;
|
|
858
|
+
}
|
|
859
|
+
exports.inspect_approval_gate = inspect_approval_gate;
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Parse a complete `tenuo_ct_…` token into its component fields.
|
|
802
863
|
*
|
|
803
|
-
*
|
|
804
|
-
*
|
|
805
|
-
*
|
|
864
|
+
* Accepts padded and unpadded Base64URL. Version must be 1; omitted `v`
|
|
865
|
+
* is an error. Trailing `/v1` is stripped from `e`.
|
|
866
|
+
* Registration-token aliases: `t`, `r`, `registration_token`.
|
|
806
867
|
*
|
|
807
868
|
* Returns `{ endpoint, apiKey, agentId?, registrationToken?, error? }`.
|
|
808
869
|
* @param {string} token
|
|
Binary file
|
|
@@ -23,6 +23,7 @@ export const sdkcontext_narrow: (a: number, b: number, c: any, d: any) => [numbe
|
|
|
23
23
|
export const sdkcontext_new: () => number;
|
|
24
24
|
export const sdkcontext_signPop: (a: number, b: number, c: number, d: number, e: any) => [number, number, number, number];
|
|
25
25
|
export const sdkcontext_signRevocationList: (a: number, b: any) => [number, number, number, number];
|
|
26
|
+
export const sdkcontext_withReceiptSigner: (a: number, b: number, c: number) => [number, number, number];
|
|
26
27
|
export const sdksession_dedupKey: (a: number, b: number, c: number, d: any) => [number, number, number, number];
|
|
27
28
|
export const sdksession_describe: (a: number) => [number, number, number];
|
|
28
29
|
export const sdksession_exportWire: (a: number) => [number, number, number];
|
|
@@ -32,6 +33,7 @@ export const sdksession_fromWire: (a: number, b: number, c: number, d: number) =
|
|
|
32
33
|
export const sdksession_toStackWire: (a: number) => [number, number, number, number];
|
|
33
34
|
export const sdksession_toWire: (a: number) => [number, number, number];
|
|
34
35
|
export const sdksession_warrantIds: (a: number) => [number, number, number];
|
|
36
|
+
export const approval_requirement: (a: number, b: number, c: number, d: number, e: any) => any;
|
|
35
37
|
export const check_access: (a: number, b: number, c: number, d: number, e: any, f: number, g: number, h: number) => any;
|
|
36
38
|
export const check_access_with_pop: (a: number, b: number, c: number, d: number, e: any, f: number, g: number, h: number, i: number) => any;
|
|
37
39
|
export const check_chain_access: (a: number, b: number, c: number, d: number, e: any, f: number, g: number, h: number) => any;
|
|
@@ -45,6 +47,7 @@ export const decode_pem_chain_wasm: (a: number, b: number) => any;
|
|
|
45
47
|
export const decode_warrant: (a: number, b: number) => any;
|
|
46
48
|
export const evaluate_approval_gates: (a: number, b: number, c: number, d: number, e: any) => any;
|
|
47
49
|
export const generate_keypair: () => any;
|
|
50
|
+
export const inspect_approval_gate: (a: number, b: number, c: number, d: number) => any;
|
|
48
51
|
export const parse_connect_token: (a: number, b: number) => any;
|
|
49
52
|
export const sign: (a: number, b: number, c: number, d: number, e: number, f: number, g: any) => any;
|
|
50
53
|
export const sign_receipt: (a: any, b: number, c: number) => any;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PublicKeyHandle } from "./api.ts";
|
|
2
|
+
declare const inspect: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* Holder keypair. Core owns the representation; persistence is the caller's
|
|
5
|
+
* job (or a later Node adapter). The secret never appears in stringification,
|
|
6
|
+
* inspection, or JSON.
|
|
7
|
+
*/
|
|
8
|
+
export declare class HolderIdentity {
|
|
9
|
+
readonly publicKey: PublicKeyHandle;
|
|
10
|
+
constructor(holderKey: Uint8Array);
|
|
11
|
+
/** Copy of the 32-byte Ed25519 secret. */
|
|
12
|
+
get holderKey(): Uint8Array;
|
|
13
|
+
toJSON(): {
|
|
14
|
+
readonly publicKey: string;
|
|
15
|
+
};
|
|
16
|
+
toString(): string;
|
|
17
|
+
[inspect](): {
|
|
18
|
+
readonly publicKey: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Import a 32-byte holder secret. */
|
|
22
|
+
export declare function identityFromKey(holderKey: Uint8Array): HolderIdentity;
|
|
23
|
+
/** Fresh holder identity. Uses Web Crypto; does not touch the filesystem. */
|
|
24
|
+
export declare function generateIdentity(): HolderIdentity;
|
|
25
|
+
export {};
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { TenuoConfigurationError } from "./errors.js";
|
|
2
|
+
import { loadWasm, publicKeyHexFromHolderKey } from "./wasm.js";
|
|
3
|
+
const inspect = Symbol.for("nodejs.util.inspect.custom");
|
|
4
|
+
const secrets = new WeakMap();
|
|
5
|
+
/**
|
|
6
|
+
* Holder keypair. Core owns the representation; persistence is the caller's
|
|
7
|
+
* job (or a later Node adapter). The secret never appears in stringification,
|
|
8
|
+
* inspection, or JSON.
|
|
9
|
+
*/
|
|
10
|
+
export class HolderIdentity {
|
|
11
|
+
publicKey;
|
|
12
|
+
constructor(holderKey) {
|
|
13
|
+
if (!(holderKey instanceof Uint8Array) || holderKey.length !== 32) {
|
|
14
|
+
throw new TenuoConfigurationError("HolderIdentity requires a 32-byte holder key");
|
|
15
|
+
}
|
|
16
|
+
loadWasm();
|
|
17
|
+
secrets.set(this, new Uint8Array(holderKey));
|
|
18
|
+
this.publicKey = {
|
|
19
|
+
kind: "public-key",
|
|
20
|
+
source: "bytes",
|
|
21
|
+
hex: publicKeyHexFromHolderKey(holderKey),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/** Copy of the 32-byte Ed25519 secret. */
|
|
25
|
+
get holderKey() {
|
|
26
|
+
const secret = secrets.get(this);
|
|
27
|
+
if (secret === undefined) {
|
|
28
|
+
throw new TenuoConfigurationError("identity is not bound to a holder key");
|
|
29
|
+
}
|
|
30
|
+
return new Uint8Array(secret);
|
|
31
|
+
}
|
|
32
|
+
toJSON() {
|
|
33
|
+
return { publicKey: this.publicKey.hex };
|
|
34
|
+
}
|
|
35
|
+
toString() {
|
|
36
|
+
return `TenuoIdentity(${this.publicKey.hex.slice(0, 8)}…)`;
|
|
37
|
+
}
|
|
38
|
+
[inspect]() {
|
|
39
|
+
return this.toJSON();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Import a 32-byte holder secret. */
|
|
43
|
+
export function identityFromKey(holderKey) {
|
|
44
|
+
if (!(holderKey instanceof Uint8Array) || holderKey.length !== 32) {
|
|
45
|
+
throw new TenuoConfigurationError("identity() requires a 32-byte holder key");
|
|
46
|
+
}
|
|
47
|
+
loadWasm();
|
|
48
|
+
return new HolderIdentity(holderKey);
|
|
49
|
+
}
|
|
50
|
+
/** Fresh holder identity. Uses Web Crypto; does not touch the filesystem. */
|
|
51
|
+
export function generateIdentity() {
|
|
52
|
+
return identityFromKey(randomSecret());
|
|
53
|
+
}
|
|
54
|
+
function randomSecret() {
|
|
55
|
+
const cryptoObj = globalThis.crypto;
|
|
56
|
+
if (cryptoObj === undefined || typeof cryptoObj.getRandomValues !== "function") {
|
|
57
|
+
throw new TenuoConfigurationError("generateIdentity() needs Web Crypto (globalThis.crypto.getRandomValues).");
|
|
58
|
+
}
|
|
59
|
+
return cryptoObj.getRandomValues(new Uint8Array(32));
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAEhE,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AACzD,MAAM,OAAO,GAAG,IAAI,OAAO,EAA8B,CAAC;AAE1D;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAChB,SAAS,CAAkB;IAEpC,YAAY,SAAqB;QAC/B,IAAI,CAAC,CAAC,SAAS,YAAY,UAAU,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;YAClE,MAAM,IAAI,uBAAuB,CAAC,8CAA8C,CAAC,CAAC;QACpF,CAAC;QACD,QAAQ,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS,GAAG;YACf,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,OAAO;YACf,GAAG,EAAE,yBAAyB,CAAC,SAAS,CAAC;SAC1C,CAAC;IACJ,CAAC;IAED,0CAA0C;IAC1C,IAAI,SAAS;QACX,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,uBAAuB,CAAC,uCAAuC,CAAC,CAAC;QAC7E,CAAC;QACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAED,MAAM;QACJ,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;IAC3C,CAAC;IAED,QAAQ;QACN,OAAO,iBAAiB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC;IAC7D,CAAC;IAED,CAAC,OAAO,CAAC;QACP,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;CACF;AAED,sCAAsC;AACtC,MAAM,UAAU,eAAe,CAAC,SAAqB;IACnD,IAAI,CAAC,CAAC,SAAS,YAAY,UAAU,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAClE,MAAM,IAAI,uBAAuB,CAAC,0CAA0C,CAAC,CAAC;IAChF,CAAC;IACD,QAAQ,EAAE,CAAC;IACX,OAAO,IAAI,cAAc,CAAC,SAAS,CAAC,CAAC;AACvC,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,gBAAgB;IAC9B,OAAO,eAAe,CAAC,YAAY,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,YAAY;IACnB,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC;IACpC,IAAI,SAAS,KAAK,SAAS,IAAI,OAAO,SAAS,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;QAC/E,MAAM,IAAI,uBAAuB,CAC/B,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;AACvD,CAAC","sourcesContent":["import type { PublicKeyHandle } from \"./api.ts\";\nimport { TenuoConfigurationError } from \"./errors.ts\";\nimport { loadWasm, publicKeyHexFromHolderKey } from \"./wasm.ts\";\n\nconst inspect = Symbol.for(\"nodejs.util.inspect.custom\");\nconst secrets = new WeakMap<HolderIdentity, Uint8Array>();\n\n/**\n * Holder keypair. Core owns the representation; persistence is the caller's\n * job (or a later Node adapter). The secret never appears in stringification,\n * inspection, or JSON.\n */\nexport class HolderIdentity {\n readonly publicKey: PublicKeyHandle;\n\n constructor(holderKey: Uint8Array) {\n if (!(holderKey instanceof Uint8Array) || holderKey.length !== 32) {\n throw new TenuoConfigurationError(\"HolderIdentity requires a 32-byte holder key\");\n }\n loadWasm();\n secrets.set(this, new Uint8Array(holderKey));\n this.publicKey = {\n kind: \"public-key\",\n source: \"bytes\",\n hex: publicKeyHexFromHolderKey(holderKey),\n };\n }\n\n /** Copy of the 32-byte Ed25519 secret. */\n get holderKey(): Uint8Array {\n const secret = secrets.get(this);\n if (secret === undefined) {\n throw new TenuoConfigurationError(\"identity is not bound to a holder key\");\n }\n return new Uint8Array(secret);\n }\n\n toJSON(): { readonly publicKey: string } {\n return { publicKey: this.publicKey.hex };\n }\n\n toString(): string {\n return `TenuoIdentity(${this.publicKey.hex.slice(0, 8)}…)`;\n }\n\n [inspect](): { readonly publicKey: string } {\n return this.toJSON();\n }\n}\n\n/** Import a 32-byte holder secret. */\nexport function identityFromKey(holderKey: Uint8Array): HolderIdentity {\n if (!(holderKey instanceof Uint8Array) || holderKey.length !== 32) {\n throw new TenuoConfigurationError(\"identity() requires a 32-byte holder key\");\n }\n loadWasm();\n return new HolderIdentity(holderKey);\n}\n\n/** Fresh holder identity. Uses Web Crypto; does not touch the filesystem. */\nexport function generateIdentity(): HolderIdentity {\n return identityFromKey(randomSecret());\n}\n\nfunction randomSecret(): Uint8Array {\n const cryptoObj = globalThis.crypto;\n if (cryptoObj === undefined || typeof cryptoObj.getRandomValues !== \"function\") {\n throw new TenuoConfigurationError(\n \"generateIdentity() needs Web Crypto (globalThis.crypto.getRandomValues).\",\n );\n }\n return cryptoObj.getRandomValues(new Uint8Array(32));\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
export type {
|
|
1
|
+
export type { ApprovalGateInspection, ApprovalRequirement, ApprovalRequirementStatus, } from "./wasm.ts";
|
|
2
|
+
export { approvalRequirement, evaluateApprovalGates, inspectApprovalGate } from "./wasm.ts";
|
|
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";
|
|
2
4
|
export { ApprovalRequiredError, AuthorizationDeniedError, TenuoConfigurationError, TenuoError, } from "./errors.ts";
|
|
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.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";
|
|
4
6
|
export { memoryNonceStore } from "./nonce.ts";
|
|
5
7
|
export { Session as SessionHandle, isSession } from "./session.ts";
|
|
8
|
+
export { ConnectToken, parseConnectToken } from "./connect.ts";
|
|
9
|
+
export type { ResolveEndpointOptions } from "./connect.ts";
|
|
10
|
+
export { HolderIdentity, generateIdentity, identityFromKey } from "./identity.ts";
|
|
11
|
+
export { Runtime } from "./runtime.ts";
|
|
12
|
+
export type { ReceiptsMode, RuntimeOptions, SessionWarrant } from "./runtime.ts";
|
|
6
13
|
export { createTenuo } from "./client.ts";
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
export { approvalRequirement, evaluateApprovalGates, inspectApprovalGate } from "./wasm.js";
|
|
1
2
|
export { ApprovalRequiredError, AuthorizationDeniedError, TenuoConfigurationError, TenuoError, } from "./errors.js";
|
|
2
|
-
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";
|
|
3
4
|
export { memoryNonceStore } from "./nonce.js";
|
|
4
5
|
export { Session as SessionHandle, isSession } from "./session.js";
|
|
6
|
+
export { ConnectToken, parseConnectToken } from "./connect.js";
|
|
7
|
+
export { HolderIdentity, generateIdentity, identityFromKey } from "./identity.js";
|
|
8
|
+
export { Runtime } from "./runtime.js";
|
|
5
9
|
export { createTenuo } from "./client.js";
|
|
6
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AA4E5F,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 { approvalRequirement, evaluateApprovalGates, inspectApprovalGate } 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.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type Decide = (decision: WasmDecision, tool: string, native?: object, arg
|
|
|
6
6
|
* proof-of-possession over the call. Shared by `tenuo.present()` and
|
|
7
7
|
* `tenuo.mcp.attach()`.
|
|
8
8
|
*/
|
|
9
|
-
export declare function presentCall(context: WasmContext, decide: Decide, session: SessionContract, name: string, args: Readonly<Record<string, unknown>>, options: McpAttachOptions | undefined, label: string): {
|
|
9
|
+
export declare function presentCall(context: WasmContext, decide: Decide, session: SessionContract, name: string, args: Readonly<Record<string, unknown>>, options: McpAttachOptions | undefined, label: string, host?: object): {
|
|
10
10
|
readonly presented: PresentedCall;
|
|
11
11
|
readonly wireArgs: Record<string, unknown>;
|
|
12
12
|
};
|
|
@@ -15,6 +15,5 @@ export declare function presentCall(context: WasmContext, decide: Decide, sessio
|
|
|
15
15
|
* proof-of-possession, then apply the host ceiling. Shared by
|
|
16
16
|
* `tenuo.verify()` and `tenuo.mcp.verify()`.
|
|
17
17
|
*/
|
|
18
|
-
export declare function verifyPresented(context: WasmContext, decide: Decide, presented: PresentedCall, name: string, args: Readonly<Record<string, unknown>>, options: McpVerifyOptions | undefined, label: string): Promise<Readonly<Record<string, unknown>>>;
|
|
19
|
-
export declare function createMcp(context: WasmContext, decide: Decide): TenuoMcp;
|
|
20
|
-
//# sourceMappingURL=mcp.d.ts.map
|
|
18
|
+
export declare function verifyPresented(context: WasmContext, decide: Decide, presented: PresentedCall, name: string, args: Readonly<Record<string, unknown>>, options: McpVerifyOptions | undefined, label: string, host?: object): Promise<Readonly<Record<string, unknown>>>;
|
|
19
|
+
export declare function createMcp(context: WasmContext, decide: Decide, host?: object): TenuoMcp;
|