skillscript-runtime 0.19.15 → 0.20.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 +35 -2
- package/dist/approval.d.ts +80 -54
- package/dist/approval.d.ts.map +1 -1
- package/dist/approval.js +156 -120
- package/dist/approval.js.map +1 -1
- package/dist/bootstrap.d.ts +41 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +59 -2
- package/dist/bootstrap.js.map +1 -1
- package/dist/cli.js +245 -24
- package/dist/cli.js.map +1 -1
- package/dist/compile.js +7 -0
- package/dist/compile.js.map +1 -1
- package/dist/composition.d.ts.map +1 -1
- package/dist/composition.js +13 -1
- package/dist/composition.js.map +1 -1
- package/dist/connectors/skill-store.d.ts.map +1 -1
- package/dist/connectors/skill-store.js +41 -13
- package/dist/connectors/skill-store.js.map +1 -1
- package/dist/connectors/sqlite-skill-store.d.ts.map +1 -1
- package/dist/connectors/sqlite-skill-store.js +21 -12
- package/dist/connectors/sqlite-skill-store.js.map +1 -1
- package/dist/dashboard/spa/app.js +186 -8
- package/dist/dashboard/spa/index.html +2 -0
- package/dist/dashboard/spa/styles.css +42 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +49 -0
- package/dist/errors.js.map +1 -1
- package/dist/help-content.d.ts.map +1 -1
- package/dist/help-content.js +2 -0
- package/dist/help-content.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/lint.d.ts.map +1 -1
- package/dist/lint.js +24 -7
- package/dist/lint.js.map +1 -1
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +21 -4
- package/dist/mcp-server.js.map +1 -1
- package/dist/parser.js +2 -2
- package/dist/parser.js.map +1 -1
- package/dist/runtime-config.d.ts +6 -0
- package/dist/runtime-config.d.ts.map +1 -1
- package/dist/runtime-config.js +8 -0
- package/dist/runtime-config.js.map +1 -1
- package/dist/runtime-env-resolver.d.ts +4 -0
- package/dist/runtime-env-resolver.d.ts.map +1 -1
- package/dist/runtime-env-resolver.js +27 -0
- package/dist/runtime-env-resolver.js.map +1 -1
- package/dist/runtime.d.ts +18 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +84 -17
- package/dist/runtime.js.map +1 -1
- package/dist/safe-path.d.ts +22 -0
- package/dist/safe-path.d.ts.map +1 -1
- package/dist/safe-path.js +72 -1
- package/dist/safe-path.js.map +1 -1
- package/dist/scheduler.d.ts +3 -0
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +8 -0
- package/dist/scheduler.js.map +1 -1
- package/docs/adopter-playbook.md +190 -30
- package/docs/configuration.md +5 -1
- package/docs/connector-contract-reference.md +5 -1
- package/docs/language-reference.md +83 -130
- package/docs/sqlite-skill-store.md +5 -1
- package/examples/skillscripts/classify-support-ticket.skill.md +1 -1
- package/examples/skillscripts/data-store-roundtrip.skill.md +1 -1
- package/examples/skillscripts/doc-qa-with-citations.skill.md +1 -1
- package/examples/skillscripts/feedback-sentiment-scan.skill.md +1 -1
- package/examples/skillscripts/hello-world.skill.md +1 -1
- package/examples/skillscripts/hello-world.skill.provenance.json +1 -1
- package/examples/skillscripts/morning-brief.skill.md +1 -1
- package/examples/skillscripts/queue-length-monitor.skill.md +1 -1
- package/examples/skillscripts/service-health-watch.skill.md +1 -1
- package/examples/skillscripts/skill-store-roundtrip.skill.md +1 -1
- package/examples/skillscripts/youtrack-morning-sweep.skill.md +1 -1
- package/package.json +1 -1
- package/scaffold/skills/data-store-roundtrip.skill.md +1 -1
- package/scaffold/skills/hello-world.skill.md +1 -1
- package/scaffold/skills/skill-store-roundtrip.skill.md +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/skillscript_logo.png" alt="Skillscript" width="400">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
5
|
+
<p align="center">
|
|
3
6
|
*A language for agents to write themselves in.*
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://skillscript.ai">skillscript.ai</a> •
|
|
11
|
+
<a href="https://skillscript.mintlify.app/docs">docs</a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
4
14
|
|
|
5
15
|
[](https://www.npmjs.com/package/skillscript-runtime)
|
|
6
16
|
[](#)
|
|
@@ -259,8 +269,31 @@ docker run -p 7878:7878 -v $(pwd)/skills:/skills \
|
|
|
259
269
|
ghcr.io/sshwarts/skillscript-runtime:latest
|
|
260
270
|
```
|
|
261
271
|
|
|
262
|
-
|
|
272
|
+
Then add the MCP to your agent. The simplest path on Claude Code (and similar hosts) is to just ask: *"Add the skillscript MCP server at `http://localhost:7878/rpc`"* — the host writes the config for you. Or wire it manually:
|
|
273
|
+
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"mcpServers": {
|
|
277
|
+
"skillscript": {
|
|
278
|
+
"type": "http",
|
|
279
|
+
"url": "http://localhost:7878/rpc"
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
```
|
|
263
284
|
|
|
285
|
+
For stdio-only clients, bridge it the same way you'd bridge any HTTP MCP — via `mcp-remote`:
|
|
286
|
+
|
|
287
|
+
```json
|
|
288
|
+
{
|
|
289
|
+
"mcpServers": {
|
|
290
|
+
"skillscript": {
|
|
291
|
+
"command": "npx",
|
|
292
|
+
"args": ["mcp-remote", "http://localhost:7878/rpc"]
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
```
|
|
264
297
|
### A canonical autonomous skill
|
|
265
298
|
|
|
266
299
|
The hello example is a single static target. A more representative shape is a cron-fired skill that pulls data, processes it, and delivers via file. The example below uses only runtime-intrinsic ops (`shell`, `file_write`, `emit`) — no adopter-wired connectors required, so it runs against a fresh install:
|
package/dist/approval.d.ts
CHANGED
|
@@ -1,67 +1,87 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Skill-approval mechanism (v1.0 Gate #7).
|
|
3
3
|
*
|
|
4
|
-
* Canonical model
|
|
5
|
-
* - Draft
|
|
6
|
-
* - Approved
|
|
4
|
+
* Canonical model:
|
|
5
|
+
* - Draft / Disabled : cannot execute (lint + compile + view still ok).
|
|
6
|
+
* - Approved : executes. The runtime MODE decides whether that
|
|
7
|
+
* approval must be cryptographically KEYED:
|
|
8
|
+
* • unsecured — UNKEYED. A bare `# Status: Approved` is sufficient; no
|
|
9
|
+
* token, no signature. (No tamper-evidence — that's the keyless cost.)
|
|
10
|
+
* • secured — KEYED. The body must carry a valid `v3:<sig>` Ed25519
|
|
11
|
+
* signature (sign with the operator's private key at approve-time;
|
|
12
|
+
* verify with the public key at runtime — the private key never reaches
|
|
13
|
+
* the runtime). Unforgeable without the private key.
|
|
7
14
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* v2 — reserved for HMAC-SHA256
|
|
12
|
-
* v3 — reserved for Ed25519 signature
|
|
13
|
-
* adopter-extensible past v3 via `registerApprovalFn`
|
|
15
|
+
* Only v3 exists. The legacy symmetric hash-token scheme (v1 CRC32 + the
|
|
16
|
+
* per-version `registerApprovalFn` registry) is retired — pre-1.0 it had no
|
|
17
|
+
* install base, and unsecured mode no longer uses tokens at all.
|
|
14
18
|
*
|
|
15
|
-
*
|
|
19
|
+
* The signature is computed over the body *excluding* its `# Status:` line, so
|
|
16
20
|
* stamping the token doesn't perturb its own input.
|
|
17
21
|
*/
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export declare function
|
|
22
|
+
/** The asymmetric (Ed25519) version slot — the only approval credential. */
|
|
23
|
+
export declare const ED25519_VERSION = "v3";
|
|
24
|
+
export declare function setSecuredMode(on: boolean): void;
|
|
25
|
+
export declare function isSecuredMode(): boolean;
|
|
26
|
+
/** Configure the Ed25519 PUBLIC key (PEM) used to verify v3 tokens. The private
|
|
27
|
+
* key is never set here — it lives in the operator's keyfile, read only by the
|
|
28
|
+
* approve flow, never by the runtime. */
|
|
29
|
+
export declare function setApprovalPublicKey(pem: string | null): void;
|
|
30
|
+
export declare function hasApprovalPublicKey(): boolean;
|
|
26
31
|
export interface ApprovalToken {
|
|
27
32
|
version: string;
|
|
28
33
|
token: string;
|
|
29
34
|
}
|
|
30
35
|
export type ApprovalVerification = {
|
|
31
36
|
ok: true;
|
|
32
|
-
token
|
|
37
|
+
token?: ApprovalToken;
|
|
33
38
|
} | {
|
|
34
39
|
ok: false;
|
|
35
40
|
reason: string;
|
|
36
41
|
};
|
|
37
|
-
/**
|
|
38
|
-
* Register an approval function for a version slot. Adopter-extension API;
|
|
39
|
-
* intended for substituting cryptographic strength (HMAC, Ed25519) without
|
|
40
|
-
* touching language internals. `v0` is reserved and cannot be registered.
|
|
41
|
-
*/
|
|
42
|
-
export declare function registerApprovalFn(version: string, fn: (body: string) => string): void;
|
|
43
|
-
export declare function getApprovalFn(version: string): ((body: string) => string) | null;
|
|
44
|
-
export declare function registeredApprovalVersions(): string[];
|
|
45
42
|
/**
|
|
46
43
|
* Strip the `# Status:` header line from a skill body. The hash input is the
|
|
47
44
|
* body MINUS this line — renaming or re-versioning a skill doesn't invalidate
|
|
48
45
|
* approval, only body edits do. Per spec point 3 in 29b6208e.
|
|
49
46
|
*/
|
|
50
47
|
export declare function stripStatusLineForHashing(body: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Canonical form signed/verified by the asymmetric (v3) scheme.
|
|
50
|
+
*
|
|
51
|
+
* STRUCTURAL whitespace only (per Perry's confirm): normalize line endings to
|
|
52
|
+
* `\n` and exclude the `# Status:` line (where the signature lives — solves the
|
|
53
|
+
* sign-its-own-input chicken-egg). It deliberately does NOT strip or collapse
|
|
54
|
+
* trailing/interior whitespace — that could alter content INSIDE a string-literal
|
|
55
|
+
* value (e.g. `$set X = "a b"`), letting two distinct bodies canonicalize the
|
|
56
|
+
* same or breaking a legitimate re-sign. Only `\r\n`/`\r` → `\n` is normalized,
|
|
57
|
+
* so a body signed on one platform verifies on another; every real edit still
|
|
58
|
+
* invalidates the signature (re-approval required — tamper-evidence preserved).
|
|
59
|
+
*/
|
|
60
|
+
export declare function canonicalizeForSigning(body: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* Sign a body with the operator's Ed25519 private key (PEM). Returns the
|
|
63
|
+
* `v3:<base64url>` token the dashboard/CLI approve flow stamps. APPROVE-TIME
|
|
64
|
+
* ONLY — the private key never enters the runtime's verification path.
|
|
65
|
+
*/
|
|
66
|
+
export declare function signApprovalEd25519(body: string, privateKeyPem: string): ApprovalToken;
|
|
67
|
+
/**
|
|
68
|
+
* Generate a fresh Ed25519 keypair for first-run provisioning. Returns PEM
|
|
69
|
+
* strings: the private key goes to the operator's keyfile (never the runtime),
|
|
70
|
+
* the public key into runtime config.
|
|
71
|
+
*/
|
|
72
|
+
export declare function generateApprovalKeypair(): {
|
|
73
|
+
publicKeyPem: string;
|
|
74
|
+
privateKeyPem: string;
|
|
75
|
+
};
|
|
51
76
|
/**
|
|
52
77
|
* Parse a token string of the form `vN:<token>` into its parts. Returns
|
|
53
78
|
* null on shape mismatch — caller surfaces a clear error to the operator.
|
|
54
79
|
*/
|
|
55
80
|
export declare function parseApprovalToken(raw: string): ApprovalToken | null;
|
|
56
81
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
|
|
60
|
-
export declare function computeApprovalToken(body: string, version?: string): ApprovalToken;
|
|
61
|
-
/**
|
|
62
|
-
* Verify a stored token against the current body. Called by runtime at every
|
|
63
|
-
* execution entry point. A mismatch means the body was edited since approval,
|
|
64
|
-
* so the human-approval gate must run again.
|
|
82
|
+
* Verify a stored token against the current body. Called in secured mode at
|
|
83
|
+
* every execution entry point. Only a v3 Ed25519 signature is accepted; an
|
|
84
|
+
* invalid signature (edited body, wrong key) or any other version is refused.
|
|
65
85
|
*/
|
|
66
86
|
export declare function verifyApprovalToken(body: string, rawToken: string): ApprovalVerification;
|
|
67
87
|
/**
|
|
@@ -81,28 +101,34 @@ export declare function extractStatusFromBody(body: string): {
|
|
|
81
101
|
/**
|
|
82
102
|
* Universal execution-time gate. Called at every dispatch entry point
|
|
83
103
|
* (scheduler.dispatchSkill, MCP execute_skill handler, in-skill
|
|
84
|
-
* `$ execute_skill` op, compile-time `&` data-skill inline).
|
|
85
|
-
*
|
|
104
|
+
* `$ execute_skill` op, compile-time `&` data-skill inline).
|
|
105
|
+
*
|
|
106
|
+
* The Draft-vs-Approved status gate applies in BOTH modes — only an Approved
|
|
107
|
+
* skill runs. The mode decides whether that approval must be KEYED:
|
|
108
|
+
*
|
|
109
|
+
* • unsecured — approval is UNKEYED. A bare `# Status: Approved` header is
|
|
110
|
+
* sufficient: a co-located human/agent marked it Approved, with no
|
|
111
|
+
* signature. (No tamper-evidence — that's the cost of running keyless;
|
|
112
|
+
* adopters who want tamper-evidence run secured mode.)
|
|
113
|
+
* • secured — approval must be a valid v3 signature minted by the operator's
|
|
114
|
+
* key. A bare, unsigned, or legacy (v1) Approved is refused → re-approve
|
|
115
|
+
* with the key (`skillfile approve` / the dashboard).
|
|
86
116
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
117
|
+
* v1.0 Gate #7 — supersedes the v0.9.0 "stamped v1 token required in both
|
|
118
|
+
* modes" model. v1 hash-stamps are retired: unsecured no longer mints or
|
|
119
|
+
* requires them; secured requires v3. (Pre-1.0, the only v1 skills are our own
|
|
120
|
+
* harness + examples, so there's no install base to preserve — `reapprove`
|
|
121
|
+
* re-blesses any that move into a secured runtime.)
|
|
89
122
|
*/
|
|
90
123
|
export declare function evaluateApprovalGate(body: string): ApprovalVerification;
|
|
91
124
|
/**
|
|
92
|
-
* Stamp `# Status: Approved
|
|
93
|
-
*
|
|
94
|
-
* runnable fixture body programmatically. The function recomputes the
|
|
95
|
-
* token over the body MINUS its `# Status:` line so the stamp is
|
|
96
|
-
* idempotent regardless of the body's current header state.
|
|
125
|
+
* Stamp `# Status: Approved v3:<sig>` into a body, signing with the operator's
|
|
126
|
+
* Ed25519 private key — APPROVE-TIME ONLY (dashboard / `skillfile approve`).
|
|
97
127
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* a parent skill that writes a child via `$ skill_write source="...# Status: Approved..."`).
|
|
103
|
-
* Bug surfaced by the skill-store-roundtrip demo (cold-adopter probe,
|
|
104
|
-
* 2026-06-01): the stamper mutated the inner string content + skipped
|
|
105
|
-
* stamping the parent.
|
|
128
|
+
* Only the HEADER-BLOCK `# Status:` line is rewritten (lines from the start
|
|
129
|
+
* until the first blank or non-`#` line), so `# Status:` text inside a string
|
|
130
|
+
* literal (e.g. a parent that writes a child via `$ skill_write source="..."`)
|
|
131
|
+
* is left untouched.
|
|
106
132
|
*/
|
|
107
|
-
export declare function
|
|
133
|
+
export declare function stampApprovalEd25519(body: string, privateKeyPem: string): string;
|
|
108
134
|
//# sourceMappingURL=approval.d.ts.map
|
package/dist/approval.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,4EAA4E;AAC5E,eAAO,MAAM,eAAe,OAAO,CAAC;AASpC,wBAAgB,cAAc,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAEhD;AACD,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AACD;;yCAEyC;AACzC,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE7D;AACD,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,oBAAoB,GAG5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAE,GACnC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG3D;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,aAAa,CAItF;AAoBD;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAMzF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAIpE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,oBAAoB,CAgCxF;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;IAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,IAAI,CAatI;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CA8BvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAEhF"}
|
package/dist/approval.js
CHANGED
|
@@ -1,59 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Skill-approval mechanism (v1.0 Gate #7).
|
|
3
3
|
*
|
|
4
|
-
* Canonical model
|
|
5
|
-
* - Draft
|
|
6
|
-
* - Approved
|
|
4
|
+
* Canonical model:
|
|
5
|
+
* - Draft / Disabled : cannot execute (lint + compile + view still ok).
|
|
6
|
+
* - Approved : executes. The runtime MODE decides whether that
|
|
7
|
+
* approval must be cryptographically KEYED:
|
|
8
|
+
* • unsecured — UNKEYED. A bare `# Status: Approved` is sufficient; no
|
|
9
|
+
* token, no signature. (No tamper-evidence — that's the keyless cost.)
|
|
10
|
+
* • secured — KEYED. The body must carry a valid `v3:<sig>` Ed25519
|
|
11
|
+
* signature (sign with the operator's private key at approve-time;
|
|
12
|
+
* verify with the public key at runtime — the private key never reaches
|
|
13
|
+
* the runtime). Unforgeable without the private key.
|
|
7
14
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* v2 — reserved for HMAC-SHA256
|
|
12
|
-
* v3 — reserved for Ed25519 signature
|
|
13
|
-
* adopter-extensible past v3 via `registerApprovalFn`
|
|
15
|
+
* Only v3 exists. The legacy symmetric hash-token scheme (v1 CRC32 + the
|
|
16
|
+
* per-version `registerApprovalFn` registry) is retired — pre-1.0 it had no
|
|
17
|
+
* install base, and unsecured mode no longer uses tokens at all.
|
|
14
18
|
*
|
|
15
|
-
*
|
|
19
|
+
* The signature is computed over the body *excluding* its `# Status:` line, so
|
|
16
20
|
* stamping the token doesn't perturb its own input.
|
|
17
21
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
if (!APPROVAL_FNS.has(version)) {
|
|
31
|
-
throw new Error(`approval version '${version}' is not registered; call registerApprovalFn first`);
|
|
32
|
-
}
|
|
33
|
-
PREFERRED_VERSION = version;
|
|
34
|
-
}
|
|
35
|
-
export function getPreferredApprovalVersion() {
|
|
36
|
-
return PREFERRED_VERSION;
|
|
22
|
+
import { sign as edSign, verify as edVerify, generateKeyPairSync } from "node:crypto";
|
|
23
|
+
/** The asymmetric (Ed25519) version slot — the only approval credential. */
|
|
24
|
+
export const ED25519_VERSION = "v3";
|
|
25
|
+
// ─── Secured-mode config (process-wide, set at boot) ─────────────────────────
|
|
26
|
+
// When secured mode is ON, the gate requires a valid v3 signature for an
|
|
27
|
+
// Approved skill to execute effectfully. The public key verifies v3; the
|
|
28
|
+
// runtime never holds the private key. Set from runtime config in bootstrap.
|
|
29
|
+
let SECURED_MODE = false;
|
|
30
|
+
let APPROVAL_PUBLIC_KEY_PEM = null;
|
|
31
|
+
export function setSecuredMode(on) {
|
|
32
|
+
SECURED_MODE = on;
|
|
37
33
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
* intended for substituting cryptographic strength (HMAC, Ed25519) without
|
|
41
|
-
* touching language internals. `v0` is reserved and cannot be registered.
|
|
42
|
-
*/
|
|
43
|
-
export function registerApprovalFn(version, fn) {
|
|
44
|
-
if (version === "v0") {
|
|
45
|
-
throw new Error(`approval version 'v0' is reserved and cannot be registered`);
|
|
46
|
-
}
|
|
47
|
-
if (!/^v\d+$/.test(version)) {
|
|
48
|
-
throw new Error(`approval version must match /^v\\d+$/ (got '${version}')`);
|
|
49
|
-
}
|
|
50
|
-
APPROVAL_FNS.set(version, fn);
|
|
34
|
+
export function isSecuredMode() {
|
|
35
|
+
return SECURED_MODE;
|
|
51
36
|
}
|
|
52
|
-
|
|
53
|
-
|
|
37
|
+
/** Configure the Ed25519 PUBLIC key (PEM) used to verify v3 tokens. The private
|
|
38
|
+
* key is never set here — it lives in the operator's keyfile, read only by the
|
|
39
|
+
* approve flow, never by the runtime. */
|
|
40
|
+
export function setApprovalPublicKey(pem) {
|
|
41
|
+
APPROVAL_PUBLIC_KEY_PEM = pem;
|
|
54
42
|
}
|
|
55
|
-
export function
|
|
56
|
-
return
|
|
43
|
+
export function hasApprovalPublicKey() {
|
|
44
|
+
return APPROVAL_PUBLIC_KEY_PEM !== null;
|
|
57
45
|
}
|
|
58
46
|
/**
|
|
59
47
|
* Strip the `# Status:` header line from a skill body. The hash input is the
|
|
@@ -66,6 +54,66 @@ export function stripStatusLineForHashing(body) {
|
|
|
66
54
|
.filter((line) => !/^\s*#\s*Status\s*:/i.test(line))
|
|
67
55
|
.join("\n");
|
|
68
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Canonical form signed/verified by the asymmetric (v3) scheme.
|
|
59
|
+
*
|
|
60
|
+
* STRUCTURAL whitespace only (per Perry's confirm): normalize line endings to
|
|
61
|
+
* `\n` and exclude the `# Status:` line (where the signature lives — solves the
|
|
62
|
+
* sign-its-own-input chicken-egg). It deliberately does NOT strip or collapse
|
|
63
|
+
* trailing/interior whitespace — that could alter content INSIDE a string-literal
|
|
64
|
+
* value (e.g. `$set X = "a b"`), letting two distinct bodies canonicalize the
|
|
65
|
+
* same or breaking a legitimate re-sign. Only `\r\n`/`\r` → `\n` is normalized,
|
|
66
|
+
* so a body signed on one platform verifies on another; every real edit still
|
|
67
|
+
* invalidates the signature (re-approval required — tamper-evidence preserved).
|
|
68
|
+
*/
|
|
69
|
+
export function canonicalizeForSigning(body) {
|
|
70
|
+
const lf = body.replace(/\r\n?/g, "\n");
|
|
71
|
+
return stripStatusLineForHashing(lf);
|
|
72
|
+
}
|
|
73
|
+
// ─── v3: Ed25519 asymmetric signature ─────────────────────────────────────────
|
|
74
|
+
/**
|
|
75
|
+
* Sign a body with the operator's Ed25519 private key (PEM). Returns the
|
|
76
|
+
* `v3:<base64url>` token the dashboard/CLI approve flow stamps. APPROVE-TIME
|
|
77
|
+
* ONLY — the private key never enters the runtime's verification path.
|
|
78
|
+
*/
|
|
79
|
+
export function signApprovalEd25519(body, privateKeyPem) {
|
|
80
|
+
const canonical = canonicalizeForSigning(body);
|
|
81
|
+
const sig = edSign(null, Buffer.from(canonical, "utf8"), privateKeyPem);
|
|
82
|
+
return { version: ED25519_VERSION, token: sig.toString("base64url") };
|
|
83
|
+
}
|
|
84
|
+
/** Verify a v3 token against the body using the configured public key. */
|
|
85
|
+
function verifyEd25519(body, tokenB64url) {
|
|
86
|
+
if (APPROVAL_PUBLIC_KEY_PEM === null)
|
|
87
|
+
return false;
|
|
88
|
+
const canonical = canonicalizeForSigning(body);
|
|
89
|
+
let sig;
|
|
90
|
+
try {
|
|
91
|
+
sig = Buffer.from(tokenB64url, "base64url");
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
if (sig.length === 0)
|
|
97
|
+
return false;
|
|
98
|
+
try {
|
|
99
|
+
return edVerify(null, Buffer.from(canonical, "utf8"), APPROVAL_PUBLIC_KEY_PEM, sig);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Generate a fresh Ed25519 keypair for first-run provisioning. Returns PEM
|
|
107
|
+
* strings: the private key goes to the operator's keyfile (never the runtime),
|
|
108
|
+
* the public key into runtime config.
|
|
109
|
+
*/
|
|
110
|
+
export function generateApprovalKeypair() {
|
|
111
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
|
112
|
+
return {
|
|
113
|
+
publicKeyPem: publicKey.export({ type: "spki", format: "pem" }),
|
|
114
|
+
privateKeyPem: privateKey.export({ type: "pkcs8", format: "pem" }),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
69
117
|
/**
|
|
70
118
|
* Parse a token string of the form `vN:<token>` into its parts. Returns
|
|
71
119
|
* null on shape mismatch — caller surfaces a clear error to the operator.
|
|
@@ -77,23 +125,9 @@ export function parseApprovalToken(raw) {
|
|
|
77
125
|
return { version: m[1], token: m[2] };
|
|
78
126
|
}
|
|
79
127
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
|
|
83
|
-
export function computeApprovalToken(body, version = "v1") {
|
|
84
|
-
if (version === "v0") {
|
|
85
|
-
throw new Error(`approval version 'v0' is reserved`);
|
|
86
|
-
}
|
|
87
|
-
const fn = APPROVAL_FNS.get(version);
|
|
88
|
-
if (!fn) {
|
|
89
|
-
throw new Error(`approval version '${version}' is not registered (available: ${registeredApprovalVersions().join(", ") || "none"})`);
|
|
90
|
-
}
|
|
91
|
-
return { version, token: fn(stripStatusLineForHashing(body)) };
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Verify a stored token against the current body. Called by runtime at every
|
|
95
|
-
* execution entry point. A mismatch means the body was edited since approval,
|
|
96
|
-
* so the human-approval gate must run again.
|
|
128
|
+
* Verify a stored token against the current body. Called in secured mode at
|
|
129
|
+
* every execution entry point. Only a v3 Ed25519 signature is accepted; an
|
|
130
|
+
* invalid signature (edited body, wrong key) or any other version is refused.
|
|
97
131
|
*/
|
|
98
132
|
export function verifyApprovalToken(body, rawToken) {
|
|
99
133
|
const parsed = parseApprovalToken(rawToken);
|
|
@@ -106,21 +140,25 @@ export function verifyApprovalToken(body, rawToken) {
|
|
|
106
140
|
if (parsed.version === "v0") {
|
|
107
141
|
return { ok: false, reason: `approval version 'v0' is reserved` };
|
|
108
142
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
const expected = fn(stripStatusLineForHashing(body));
|
|
117
|
-
if (expected !== parsed.token) {
|
|
143
|
+
// v3 — asymmetric Ed25519 (the secured-mode credential). Verify the signature
|
|
144
|
+
// with the configured public key; the private key never reaches this path.
|
|
145
|
+
if (parsed.version === ED25519_VERSION) {
|
|
146
|
+
if (verifyEd25519(body, parsed.token)) {
|
|
147
|
+
return { ok: true, token: parsed };
|
|
148
|
+
}
|
|
118
149
|
return {
|
|
119
150
|
ok: false,
|
|
120
|
-
reason:
|
|
151
|
+
reason: APPROVAL_PUBLIC_KEY_PEM === null
|
|
152
|
+
? `approval signature cannot be verified — no approval public key is configured`
|
|
153
|
+
: `approval signature is invalid — the body was edited since approval, or signed with a different key; re-approve via the dashboard`,
|
|
121
154
|
};
|
|
122
155
|
}
|
|
123
|
-
|
|
156
|
+
// Only v3 is accepted. Any other version (a retired v1, or a forged scheme)
|
|
157
|
+
// is refused — re-approve with the operator's key.
|
|
158
|
+
return {
|
|
159
|
+
ok: false,
|
|
160
|
+
reason: `approval token version '${parsed.version}' is not accepted — a v3 signed approval is required; re-approve via the dashboard`,
|
|
161
|
+
};
|
|
124
162
|
}
|
|
125
163
|
/**
|
|
126
164
|
* Extract the status + (optional) approval token from a skill body's
|
|
@@ -154,11 +192,24 @@ export function extractStatusFromBody(body) {
|
|
|
154
192
|
/**
|
|
155
193
|
* Universal execution-time gate. Called at every dispatch entry point
|
|
156
194
|
* (scheduler.dispatchSkill, MCP execute_skill handler, in-skill
|
|
157
|
-
* `$ execute_skill` op, compile-time `&` data-skill inline).
|
|
158
|
-
* iff status is Approved AND the body's stamped token re-computes correctly.
|
|
195
|
+
* `$ execute_skill` op, compile-time `&` data-skill inline).
|
|
159
196
|
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
197
|
+
* The Draft-vs-Approved status gate applies in BOTH modes — only an Approved
|
|
198
|
+
* skill runs. The mode decides whether that approval must be KEYED:
|
|
199
|
+
*
|
|
200
|
+
* • unsecured — approval is UNKEYED. A bare `# Status: Approved` header is
|
|
201
|
+
* sufficient: a co-located human/agent marked it Approved, with no
|
|
202
|
+
* signature. (No tamper-evidence — that's the cost of running keyless;
|
|
203
|
+
* adopters who want tamper-evidence run secured mode.)
|
|
204
|
+
* • secured — approval must be a valid v3 signature minted by the operator's
|
|
205
|
+
* key. A bare, unsigned, or legacy (v1) Approved is refused → re-approve
|
|
206
|
+
* with the key (`skillfile approve` / the dashboard).
|
|
207
|
+
*
|
|
208
|
+
* v1.0 Gate #7 — supersedes the v0.9.0 "stamped v1 token required in both
|
|
209
|
+
* modes" model. v1 hash-stamps are retired: unsecured no longer mints or
|
|
210
|
+
* requires them; secured requires v3. (Pre-1.0, the only v1 skills are our own
|
|
211
|
+
* harness + examples, so there's no install base to preserve — `reapprove`
|
|
212
|
+
* re-blesses any that move into a secured runtime.)
|
|
162
213
|
*/
|
|
163
214
|
export function evaluateApprovalGate(body) {
|
|
164
215
|
const extracted = extractStatusFromBody(body);
|
|
@@ -169,35 +220,43 @@ export function evaluateApprovalGate(body) {
|
|
|
169
220
|
return { ok: false, reason: `skill status is 'Disabled' — execution refused` };
|
|
170
221
|
}
|
|
171
222
|
if (extracted.status === "Draft") {
|
|
172
|
-
return {
|
|
223
|
+
return {
|
|
224
|
+
ok: false,
|
|
225
|
+
reason: SECURED_MODE
|
|
226
|
+
? `skill status is 'Draft' — this is an intentional safety gate, not an error to work around. A human must review and approve it via the dashboard before it can execute. Preview it with mechanical mode, or keep iterating as a Draft.`
|
|
227
|
+
: `skill status is 'Draft' — approve via dashboard before executing`,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// Approved. Unsecured: unkeyed approval — the status header alone is enough.
|
|
231
|
+
if (!SECURED_MODE) {
|
|
232
|
+
return { ok: true };
|
|
173
233
|
}
|
|
234
|
+
// Secured: a valid v3 signature is required.
|
|
174
235
|
if (extracted.approvalToken === null) {
|
|
236
|
+
// Deliberately does NOT disclose the token format (an attacker who learns
|
|
237
|
+
// `vN:<token>` gets the exact shape to forge).
|
|
175
238
|
return {
|
|
176
239
|
ok: false,
|
|
177
|
-
reason: `skill is Approved but
|
|
240
|
+
reason: `skill is marked Approved but carries no valid approval signature — re-approve via the dashboard`,
|
|
178
241
|
};
|
|
179
242
|
}
|
|
180
243
|
return verifyApprovalToken(body, extracted.approvalToken);
|
|
181
244
|
}
|
|
182
245
|
/**
|
|
183
|
-
* Stamp `# Status: Approved
|
|
184
|
-
*
|
|
185
|
-
* runnable fixture body programmatically. The function recomputes the
|
|
186
|
-
* token over the body MINUS its `# Status:` line so the stamp is
|
|
187
|
-
* idempotent regardless of the body's current header state.
|
|
246
|
+
* Stamp `# Status: Approved v3:<sig>` into a body, signing with the operator's
|
|
247
|
+
* Ed25519 private key — APPROVE-TIME ONLY (dashboard / `skillfile approve`).
|
|
188
248
|
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* a parent skill that writes a child via `$ skill_write source="...# Status: Approved..."`).
|
|
194
|
-
* Bug surfaced by the skill-store-roundtrip demo (cold-adopter probe,
|
|
195
|
-
* 2026-06-01): the stamper mutated the inner string content + skipped
|
|
196
|
-
* stamping the parent.
|
|
249
|
+
* Only the HEADER-BLOCK `# Status:` line is rewritten (lines from the start
|
|
250
|
+
* until the first blank or non-`#` line), so `# Status:` text inside a string
|
|
251
|
+
* literal (e.g. a parent that writes a child via `$ skill_write source="..."`)
|
|
252
|
+
* is left untouched.
|
|
197
253
|
*/
|
|
198
|
-
export function
|
|
199
|
-
|
|
200
|
-
|
|
254
|
+
export function stampApprovalEd25519(body, privateKeyPem) {
|
|
255
|
+
return writeApprovedStatusLine(body, signApprovalEd25519(body, privateKeyPem));
|
|
256
|
+
}
|
|
257
|
+
/** Write `# Status: Approved <version>:<token>` into the header block, replacing
|
|
258
|
+
* an existing header `# Status:` line or inserting after `# Skill:`. */
|
|
259
|
+
function writeApprovedStatusLine(body, token) {
|
|
201
260
|
const line = `# Status: Approved ${token.version}:${token.token}`;
|
|
202
261
|
const headerStatusLine = findHeaderStatusLine(body);
|
|
203
262
|
if (headerStatusLine !== null) {
|
|
@@ -231,27 +290,4 @@ function findHeaderStatusLine(body) {
|
|
|
231
290
|
}
|
|
232
291
|
return null;
|
|
233
292
|
}
|
|
234
|
-
// ─── v1: CRC32 reference impl ─────────────────────────────────────────────────
|
|
235
|
-
const CRC32_TABLE = (() => {
|
|
236
|
-
const table = new Array(256);
|
|
237
|
-
for (let i = 0; i < 256; i++) {
|
|
238
|
-
let c = i;
|
|
239
|
-
for (let k = 0; k < 8; k++) {
|
|
240
|
-
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
241
|
-
}
|
|
242
|
-
table[i] = c >>> 0;
|
|
243
|
-
}
|
|
244
|
-
return table;
|
|
245
|
-
})();
|
|
246
|
-
function crc32Utf8(input) {
|
|
247
|
-
const bytes = new TextEncoder().encode(input);
|
|
248
|
-
let crc = 0xffffffff;
|
|
249
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
250
|
-
const idx = (crc ^ (bytes[i] ?? 0)) & 0xff;
|
|
251
|
-
crc = (CRC32_TABLE[idx] ?? 0) ^ (crc >>> 8);
|
|
252
|
-
}
|
|
253
|
-
crc = (crc ^ 0xffffffff) >>> 0;
|
|
254
|
-
return crc.toString(16).padStart(8, "0");
|
|
255
|
-
}
|
|
256
|
-
registerApprovalFn("v1", crc32Utf8);
|
|
257
293
|
//# sourceMappingURL=approval.js.map
|
package/dist/approval.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"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"}
|