skillscript-runtime 0.19.16 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +11 -1
  2. package/dist/approval.d.ts +80 -54
  3. package/dist/approval.d.ts.map +1 -1
  4. package/dist/approval.js +156 -120
  5. package/dist/approval.js.map +1 -1
  6. package/dist/bootstrap.d.ts +41 -0
  7. package/dist/bootstrap.d.ts.map +1 -1
  8. package/dist/bootstrap.js +59 -2
  9. package/dist/bootstrap.js.map +1 -1
  10. package/dist/cli.js +277 -24
  11. package/dist/cli.js.map +1 -1
  12. package/dist/compile.js +7 -0
  13. package/dist/compile.js.map +1 -1
  14. package/dist/composition.d.ts.map +1 -1
  15. package/dist/composition.js +13 -1
  16. package/dist/composition.js.map +1 -1
  17. package/dist/connectors/skill-store.d.ts.map +1 -1
  18. package/dist/connectors/skill-store.js +41 -13
  19. package/dist/connectors/skill-store.js.map +1 -1
  20. package/dist/connectors/sqlite-skill-store.d.ts.map +1 -1
  21. package/dist/connectors/sqlite-skill-store.js +21 -12
  22. package/dist/connectors/sqlite-skill-store.js.map +1 -1
  23. package/dist/connectors/types.d.ts +9 -0
  24. package/dist/connectors/types.d.ts.map +1 -1
  25. package/dist/connectors/types.js.map +1 -1
  26. package/dist/dashboard/server.d.ts +26 -0
  27. package/dist/dashboard/server.d.ts.map +1 -1
  28. package/dist/dashboard/server.js +70 -2
  29. package/dist/dashboard/server.js.map +1 -1
  30. package/dist/dashboard/spa/app.js +200 -8
  31. package/dist/dashboard/spa/index.html +2 -0
  32. package/dist/dashboard/spa/styles.css +42 -0
  33. package/dist/errors.d.ts +25 -0
  34. package/dist/errors.d.ts.map +1 -1
  35. package/dist/errors.js +49 -0
  36. package/dist/errors.js.map +1 -1
  37. package/dist/index.d.ts +1 -1
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +2 -2
  40. package/dist/index.js.map +1 -1
  41. package/dist/lint.d.ts.map +1 -1
  42. package/dist/lint.js +24 -7
  43. package/dist/lint.js.map +1 -1
  44. package/dist/mcp-server.d.ts +3 -0
  45. package/dist/mcp-server.d.ts.map +1 -1
  46. package/dist/mcp-server.js +19 -2
  47. package/dist/mcp-server.js.map +1 -1
  48. package/dist/parser.js +2 -2
  49. package/dist/parser.js.map +1 -1
  50. package/dist/runtime-config.d.ts +6 -0
  51. package/dist/runtime-config.d.ts.map +1 -1
  52. package/dist/runtime-config.js +8 -0
  53. package/dist/runtime-config.js.map +1 -1
  54. package/dist/runtime-env-resolver.d.ts +4 -0
  55. package/dist/runtime-env-resolver.d.ts.map +1 -1
  56. package/dist/runtime-env-resolver.js +27 -0
  57. package/dist/runtime-env-resolver.js.map +1 -1
  58. package/dist/runtime.d.ts +18 -0
  59. package/dist/runtime.d.ts.map +1 -1
  60. package/dist/runtime.js +84 -17
  61. package/dist/runtime.js.map +1 -1
  62. package/dist/safe-path.d.ts +22 -0
  63. package/dist/safe-path.d.ts.map +1 -1
  64. package/dist/safe-path.js +72 -1
  65. package/dist/safe-path.js.map +1 -1
  66. package/dist/scheduler.d.ts +3 -0
  67. package/dist/scheduler.d.ts.map +1 -1
  68. package/dist/scheduler.js +8 -0
  69. package/dist/scheduler.js.map +1 -1
  70. package/dist/skill-catalog.d.ts.map +1 -1
  71. package/dist/skill-catalog.js +10 -2
  72. package/dist/skill-catalog.js.map +1 -1
  73. package/docs/adopter-playbook.md +75 -25
  74. package/docs/configuration.md +5 -1
  75. package/docs/connector-contract-reference.md +5 -1
  76. package/docs/language-reference.md +83 -130
  77. package/docs/sqlite-skill-store.md +5 -1
  78. package/examples/skillscripts/classify-support-ticket.skill.md +1 -1
  79. package/examples/skillscripts/data-store-roundtrip.skill.md +1 -1
  80. package/examples/skillscripts/doc-qa-with-citations.skill.md +1 -1
  81. package/examples/skillscripts/feedback-sentiment-scan.skill.md +1 -1
  82. package/examples/skillscripts/hello-world.skill.md +1 -1
  83. package/examples/skillscripts/hello-world.skill.provenance.json +1 -1
  84. package/examples/skillscripts/morning-brief.skill.md +1 -1
  85. package/examples/skillscripts/queue-length-monitor.skill.md +1 -1
  86. package/examples/skillscripts/service-health-watch.skill.md +1 -1
  87. package/examples/skillscripts/skill-store-roundtrip.skill.md +1 -1
  88. package/examples/skillscripts/youtrack-morning-sweep.skill.md +1 -1
  89. package/package.json +1 -1
  90. package/scaffold/skills/data-store-roundtrip.skill.md +1 -1
  91. package/scaffold/skills/hello-world.skill.md +1 -1
  92. package/scaffold/skills/skill-store-roundtrip.skill.md +1 -1
package/README.md CHANGED
@@ -1,6 +1,16 @@
1
- # Skillscript
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>&nbsp; • &nbsp;
11
+ <a href="https://skillscript.mintlify.app/docs">docs</a>&nbsp;
12
+ </p>
13
+
4
14
 
5
15
  [![npm version](https://img.shields.io/npm/v/skillscript-runtime.svg)](https://www.npmjs.com/package/skillscript-runtime)
6
16
  [![tests](https://img.shields.io/badge/tests-passing-green)](#)
@@ -1,67 +1,87 @@
1
1
  /**
2
- * v0.9.0 — skill-approval mechanism.
2
+ * Skill-approval mechanism (v1.0 Gate #7).
3
3
  *
4
- * Canonical model (per thread 29b6208e):
5
- * - Draft : authored, lint+compile+view ok, cannot execute
6
- * - Approved + valid hash-token : can execute (manual / trigger / composition)
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
- * Approval token = `vN:<hex>` where N picks the hash function:
9
- * v0 reserved, rejected (naked "Approved" fails fast)
10
- * v1 CRC32 (bundled default; discipline-barrier strength)
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
- * Token is computed over the body *excluding* the `# Status:` line, so
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
- * Set the version used by `stampApprovalToken(body)` when no explicit
20
- * version is passed. Adopter bootstraps that register `v2` HMAC (or
21
- * stronger) call this to make the dashboard's approval flow stamp with
22
- * the upgraded function. Default stays `v1` (bundled CRC32).
23
- */
24
- export declare function setPreferredApprovalVersion(version: string): void;
25
- export declare function getPreferredApprovalVersion(): string;
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: ApprovalToken;
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
- * Compute the canonical approval token for a body at a given version. The
58
- * dashboard calls this when stamping `# Status: Approved <token>`.
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). Returns ok
85
- * iff status is Approved AND the body's stamped token re-computes correctly.
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
- * v0.9.0 — supersedes the v0.8.x "status === Approved" check; that check
88
- * remains the first gate, but a stamped + verified token is now required.
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 <token>` into a skill body. Called by the
93
- * dashboard's approval flow + by test helpers that need to produce a
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
- * v0.15.0 only replaces a `# Status:` line in the HEADER BLOCK (lines
99
- * from start until the first blank line or first non-`#`-comment line).
100
- * Pre-v0.15.0 the unbounded `/^# Status:/m` regex matched any line in
101
- * the body — including `# Status:` text inside string literals (e.g.
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 stampApprovalToken(body: string, version?: string): string;
133
+ export declare function stampApprovalEd25519(body: string, privateKeyPem: string): string;
108
134
  //# sourceMappingURL=approval.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAUjE;AAED,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,oBAAoB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,GAClC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAQtF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,CAEhF;AAED,wBAAgB,0BAA0B,IAAI,MAAM,EAAE,CAErD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAIpE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,MAAa,GAAG,aAAa,CAWxF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,oBAAoB,CA0BxF;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;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAkBvE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAczE"}
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
- * v0.9.0 — skill-approval mechanism.
2
+ * Skill-approval mechanism (v1.0 Gate #7).
3
3
  *
4
- * Canonical model (per thread 29b6208e):
5
- * - Draft : authored, lint+compile+view ok, cannot execute
6
- * - Approved + valid hash-token : can execute (manual / trigger / composition)
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
- * Approval token = `vN:<hex>` where N picks the hash function:
9
- * v0 reserved, rejected (naked "Approved" fails fast)
10
- * v1 CRC32 (bundled default; discipline-barrier strength)
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
- * Token is computed over the body *excluding* the `# Status:` line, so
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
- const APPROVAL_FNS = new Map();
19
- let PREFERRED_VERSION = "v1";
20
- /**
21
- * Set the version used by `stampApprovalToken(body)` when no explicit
22
- * version is passed. Adopter bootstraps that register `v2` HMAC (or
23
- * stronger) call this to make the dashboard's approval flow stamp with
24
- * the upgraded function. Default stays `v1` (bundled CRC32).
25
- */
26
- export function setPreferredApprovalVersion(version) {
27
- if (version === "v0") {
28
- throw new Error(`approval version 'v0' is reserved`);
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
- * Register an approval function for a version slot. Adopter-extension API;
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
- export function getApprovalFn(version) {
53
- return APPROVAL_FNS.get(version) ?? null;
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 registeredApprovalVersions() {
56
- return [...APPROVAL_FNS.keys()].sort();
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
- * Compute the canonical approval token for a body at a given version. The
81
- * dashboard calls this when stamping `# Status: Approved <token>`.
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
- const fn = APPROVAL_FNS.get(parsed.version);
110
- if (!fn) {
111
- return {
112
- ok: false,
113
- reason: `approval version '${parsed.version}' is not registered (available: ${registeredApprovalVersions().join(", ") || "none"})`,
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: `approval token mismatch — skill body has been edited since approval; re-approve via dashboard`,
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
- return { ok: true, token: parsed };
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). Returns ok
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
- * v0.9.0 supersedes the v0.8.x "status === Approved" check; that check
161
- * remains the first gate, but a stamped + verified token is now required.
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 { ok: false, reason: `skill status is 'Draft' — approve via dashboard before executing` };
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 missing approval token — re-approve via dashboard to stamp '# Status: Approved v1:<token>'`,
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 <token>` into a skill body. Called by the
184
- * dashboard's approval flow + by test helpers that need to produce a
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
- * v0.15.0 only replaces a `# Status:` line in the HEADER BLOCK (lines
190
- * from start until the first blank line or first non-`#`-comment line).
191
- * Pre-v0.15.0 the unbounded `/^# Status:/m` regex matched any line in
192
- * the body — including `# Status:` text inside string literals (e.g.
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 stampApprovalToken(body, version) {
199
- const v = version ?? PREFERRED_VERSION;
200
- const token = computeApprovalToken(body, v);
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
@@ -1 +1 @@
1
- {"version":3,"file":"approval.js","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"approval.js","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"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"}