skillscript-runtime 0.24.0 → 0.25.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +2 -1
  3. package/UPGRADING.md +9 -1
  4. package/dist/bootstrap.d.ts +10 -0
  5. package/dist/bootstrap.d.ts.map +1 -1
  6. package/dist/bootstrap.js +7 -0
  7. package/dist/bootstrap.js.map +1 -1
  8. package/dist/cli.js +4 -0
  9. package/dist/cli.js.map +1 -1
  10. package/dist/connectors/types.d.ts +8 -0
  11. package/dist/connectors/types.d.ts.map +1 -1
  12. package/dist/connectors/types.js.map +1 -1
  13. package/dist/help-content.d.ts.map +1 -1
  14. package/dist/help-content.js +3 -0
  15. package/dist/help-content.js.map +1 -1
  16. package/dist/lint.d.ts +1 -1
  17. package/dist/lint.d.ts.map +1 -1
  18. package/dist/lint.js +145 -0
  19. package/dist/lint.js.map +1 -1
  20. package/dist/mcp-server.d.ts +8 -0
  21. package/dist/mcp-server.d.ts.map +1 -1
  22. package/dist/mcp-server.js +2 -0
  23. package/dist/mcp-server.js.map +1 -1
  24. package/dist/parser.d.ts +9 -0
  25. package/dist/parser.d.ts.map +1 -1
  26. package/dist/parser.js +22 -6
  27. package/dist/parser.js.map +1 -1
  28. package/dist/runtime.d.ts +20 -0
  29. package/dist/runtime.d.ts.map +1 -1
  30. package/dist/runtime.js +147 -24
  31. package/dist/runtime.js.map +1 -1
  32. package/dist/scheduler.d.ts +8 -0
  33. package/dist/scheduler.d.ts.map +1 -1
  34. package/dist/scheduler.js +3 -0
  35. package/dist/scheduler.js.map +1 -1
  36. package/dist/secrets.d.ts +119 -0
  37. package/dist/secrets.d.ts.map +1 -0
  38. package/dist/secrets.js +153 -0
  39. package/dist/secrets.js.map +1 -0
  40. package/dist/skill-catalog.d.ts.map +1 -1
  41. package/dist/skill-catalog.js +2 -0
  42. package/dist/skill-catalog.js.map +1 -1
  43. package/docs/adopter-playbook.md +41 -0
  44. package/docs/language-reference.md +82 -5
  45. package/examples/skillscripts/hello-world.skill.provenance.json +1 -1
  46. package/package.json +1 -1
  47. package/scaffold/.env.example +13 -0
@@ -1 +1 @@
1
- {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
package/dist/lint.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { parse, tokenizeKeywordArgs } from "./parser.js";
2
+ import { extractSecretRefs, findMalformedSecretMarkers } from "./secrets.js";
2
3
  import { classifyMutation, authorizationGranted } from "./mutation-gate.js";
3
4
  import { KNOWN_FILTERS } from "./filters.js";
4
5
  // ─── lint() entry point ────────────────────────────────────────────────────
@@ -1458,6 +1459,147 @@ const CREDENTIAL_IN_ARGS = {
1458
1459
  return findings;
1459
1460
  },
1460
1461
  };
1462
+ // ─── secret references (v0.25.0) ──────────────────────────────────────────
1463
+ // A `{{secret.NAME}}` marker is USE-ONLY: legal only in a sink op (a
1464
+ // `shell(...)` op or a `$ connector.tool` dispatch), never where its value
1465
+ // could be read, bound, or emitted. These two tier-1 rules enforce the
1466
+ // contract at compile time; the runtime resolves markers at the sink
1467
+ // (src/secrets.ts holds SECRET_SINK_OP_KINDS, the shared sink list).
1468
+ /** True when this `$` op is an unqualified built-in intercept (execute_skill /
1469
+ * json_parse) — a `$`-kind op that is NOT a real external sink. A secret
1470
+ * marker in it would flow into a child skill's scope or a parsed/bound var,
1471
+ * never an external credential, so it's a use-only violation. A *qualified*
1472
+ * `$ conn.execute_skill` is a real connector dispatch and not excluded. */
1473
+ function isBuiltinNonSinkDollar(op) {
1474
+ if (op.kind !== "$" || op.mcpConnector !== undefined)
1475
+ return false;
1476
+ const tool = /^([A-Za-z_][\w:-]*)/.exec(op.body.trimStart())?.[1];
1477
+ return tool === "execute_skill" || tool === "json_parse";
1478
+ }
1479
+ /** Text positions of `op` where a secret marker is a legal sink injection. */
1480
+ function secretSinkText(op) {
1481
+ if (op.kind === "shell")
1482
+ return `${op.body ?? ""} ${op.argv?.join(" ") ?? ""}`;
1483
+ if (op.kind === "$" && !isBuiltinNonSinkDollar(op))
1484
+ return op.body ?? "";
1485
+ return "";
1486
+ }
1487
+ /** Text positions of `op` where a secret marker is ILLEGAL (would expose the
1488
+ * value): every author-controlled field except the sink positions above —
1489
+ * the body of a non-sink op, `$set`/`$append` values, foreach lists, op
1490
+ * fallbacks, and condition expressions. */
1491
+ function secretNonSinkText(op) {
1492
+ const parts = [];
1493
+ const bodyIsSink = op.kind === "shell" || (op.kind === "$" && !isBuiltinNonSinkDollar(op));
1494
+ if (!bodyIsSink && op.body)
1495
+ parts.push(op.body);
1496
+ if (op.setValue !== undefined)
1497
+ parts.push(op.setValue);
1498
+ if (op.foreachList !== undefined)
1499
+ parts.push(op.foreachList);
1500
+ if (op.fallback !== undefined)
1501
+ parts.push(op.fallback);
1502
+ if (op.ifBranches !== undefined)
1503
+ for (const b of op.ifBranches)
1504
+ parts.push(b.cond);
1505
+ return parts.join(" ");
1506
+ }
1507
+ const SECRET_USE_ONLY = {
1508
+ id: "secret-use-only",
1509
+ severity: "error",
1510
+ description: "A `{{secret.NAME}}` marker appears outside a secret sink (a `shell(...)` op or a `$ connector.tool` dispatch). Secrets are use-only: the runtime injects the value at the sink and never lets it reach a readable, bindable, or emittable surface.",
1511
+ remediation: "Use the secret only inside a `shell(command=\"... {{secret.NAME}} ...\")` op or a `$ connector.tool arg={{secret.NAME}}` dispatch. Never put it in `$set`, `emit`, a condition, a `# Output:` template, a `file_*`/`notify` op, or an op `(fallback: ...)` — those would expose the value.",
1512
+ check: (ctx) => {
1513
+ const findings = [];
1514
+ for (const [targetName, target] of ctx.parsed.targets) {
1515
+ walkOps(target.ops, (op) => {
1516
+ for (const name of extractSecretRefs(secretNonSinkText(op))) {
1517
+ findings.push({
1518
+ rule: "secret-use-only",
1519
+ severity: "error",
1520
+ block: targetName,
1521
+ message: `Secret marker {{secret.${name}}} appears in a '${op.kind}' op position that is not a secret sink. A secret may only be injected into a shell(...) op or a '$ connector.tool' dispatch — never where its value could be read, bound, or emitted.`,
1522
+ });
1523
+ }
1524
+ });
1525
+ }
1526
+ if (ctx.parsed.outputTemplate !== null) {
1527
+ for (const name of extractSecretRefs(ctx.parsed.outputTemplate)) {
1528
+ findings.push({
1529
+ rule: "secret-use-only",
1530
+ severity: "error",
1531
+ message: `Secret marker {{secret.${name}}} appears in the body-text output template. A secret value must never reach an output surface; reference it only inside a shell(...) or '$ connector.tool' sink op.`,
1532
+ });
1533
+ }
1534
+ }
1535
+ return findings;
1536
+ },
1537
+ };
1538
+ const SECRET_UNDECLARED = {
1539
+ id: "secret-undeclared",
1540
+ severity: "error",
1541
+ description: "A `{{secret.NAME}}` marker is used without a matching `# Requires: secret.NAME` declaration. Secrets are declared before use so an approver sees which credentials the skill reaches.",
1542
+ remediation: "Add `# Requires: secret.NAME` to the frontmatter for every secret the skill references.",
1543
+ check: (ctx) => {
1544
+ const declared = new Set(ctx.parsed.secretRequires);
1545
+ const findings = [];
1546
+ const seen = new Set();
1547
+ const checkText = (text, block) => {
1548
+ for (const name of extractSecretRefs(text)) {
1549
+ if (declared.has(name) || seen.has(name))
1550
+ continue;
1551
+ seen.add(name);
1552
+ findings.push({
1553
+ rule: "secret-undeclared",
1554
+ severity: "error",
1555
+ message: `Secret marker {{secret.${name}}} is used but not declared. Add \`# Requires: secret.${name}\` to the frontmatter so an approver can see which secrets this skill reaches.`,
1556
+ ...(block !== undefined ? { block } : {}),
1557
+ });
1558
+ }
1559
+ };
1560
+ for (const [targetName, target] of ctx.parsed.targets) {
1561
+ walkOps(target.ops, (op) => {
1562
+ checkText(secretSinkText(op), targetName);
1563
+ checkText(secretNonSinkText(op), targetName);
1564
+ });
1565
+ }
1566
+ if (ctx.parsed.outputTemplate !== null)
1567
+ checkText(ctx.parsed.outputTemplate);
1568
+ return findings;
1569
+ },
1570
+ };
1571
+ const SECRET_DYNAMIC_NAME = {
1572
+ id: "secret-dynamic-name",
1573
+ severity: "error",
1574
+ description: "A `{{secret.…}}` marker has a non-literal name (e.g. `{{secret.${VAR}}}`) or is otherwise malformed. The secret name must be a compile-time literal so the declare-before-spend gate and the approver-visible `# Requires` reach cannot be evaded by building the name at runtime.",
1575
+ remediation: "Use a literal secret name: `{{secret.NAME}}` where NAME matches a `# Requires: secret.NAME` declaration. Do not interpolate (`{{secret.${VAR}}}`) — the runtime refuses dynamically-named secrets.",
1576
+ check: (ctx) => {
1577
+ const findings = [];
1578
+ const seen = new Set();
1579
+ const scan = (text, block) => {
1580
+ for (const bad of findMalformedSecretMarkers(text)) {
1581
+ if (seen.has(bad))
1582
+ continue;
1583
+ seen.add(bad);
1584
+ findings.push({
1585
+ rule: "secret-dynamic-name",
1586
+ severity: "error",
1587
+ message: `Malformed/dynamic secret marker '${bad}' — the secret name must be a compile-time literal (\`{{secret.NAME}}\`), not interpolated or built at runtime.`,
1588
+ ...(block !== undefined ? { block } : {}),
1589
+ });
1590
+ }
1591
+ };
1592
+ for (const [targetName, target] of ctx.parsed.targets) {
1593
+ walkOps(target.ops, (op) => {
1594
+ scan(secretSinkText(op), targetName);
1595
+ scan(secretNonSinkText(op), targetName);
1596
+ });
1597
+ }
1598
+ if (ctx.parsed.outputTemplate !== null)
1599
+ scan(ctx.parsed.outputTemplate);
1600
+ return findings;
1601
+ },
1602
+ };
1461
1603
  const STATUS_DISABLED = {
1462
1604
  id: "status-disabled",
1463
1605
  severity: "error",
@@ -3410,6 +3552,9 @@ const RULES = [
3410
3552
  APPEND_TO_NON_LIST,
3411
3553
  DISABLED_SKILL_REFERENCE,
3412
3554
  CREDENTIAL_IN_ARGS,
3555
+ SECRET_USE_ONLY,
3556
+ SECRET_UNDECLARED,
3557
+ SECRET_DYNAMIC_NAME,
3413
3558
  STATUS_DISABLED,
3414
3559
  CIRCULAR_DEPENDENCY,
3415
3560
  MISSING_DEPENDENCY,