usertrust 1.3.0 → 1.5.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 (94) hide show
  1. package/README.md +9 -9
  2. package/dist/anomaly/detector.d.ts.map +1 -1
  3. package/dist/anomaly/detector.js +36 -11
  4. package/dist/anomaly/detector.js.map +1 -1
  5. package/dist/anomaly/signals/spend-velocity.d.ts +39 -12
  6. package/dist/anomaly/signals/spend-velocity.d.ts.map +1 -1
  7. package/dist/anomaly/signals/spend-velocity.js +66 -43
  8. package/dist/anomaly/signals/spend-velocity.js.map +1 -1
  9. package/dist/anomaly/signals/token-rate.d.ts +33 -13
  10. package/dist/anomaly/signals/token-rate.d.ts.map +1 -1
  11. package/dist/anomaly/signals/token-rate.js +124 -38
  12. package/dist/anomaly/signals/token-rate.js.map +1 -1
  13. package/dist/anomaly/types.d.ts +28 -6
  14. package/dist/anomaly/types.d.ts.map +1 -1
  15. package/dist/audit/chain.d.ts +9 -0
  16. package/dist/audit/chain.d.ts.map +1 -1
  17. package/dist/audit/chain.js +65 -9
  18. package/dist/audit/chain.js.map +1 -1
  19. package/dist/audit/verify.d.ts +19 -0
  20. package/dist/audit/verify.d.ts.map +1 -1
  21. package/dist/audit/verify.js +216 -14
  22. package/dist/audit/verify.js.map +1 -1
  23. package/dist/cli/init.d.ts.map +1 -1
  24. package/dist/cli/init.js +107 -2
  25. package/dist/cli/init.js.map +1 -1
  26. package/dist/cli/main.js +0 -0
  27. package/dist/cli/skill.d.ts.map +1 -1
  28. package/dist/cli/skill.js +35 -5
  29. package/dist/cli/skill.js.map +1 -1
  30. package/dist/cli/snapshot.d.ts.map +1 -1
  31. package/dist/cli/snapshot.js +20 -2
  32. package/dist/cli/snapshot.js.map +1 -1
  33. package/dist/cli/verify.d.ts.map +1 -1
  34. package/dist/cli/verify.js +20 -11
  35. package/dist/cli/verify.js.map +1 -1
  36. package/dist/detect.d.ts +34 -1
  37. package/dist/detect.d.ts.map +1 -1
  38. package/dist/detect.js +124 -0
  39. package/dist/detect.js.map +1 -1
  40. package/dist/govern.d.ts +13 -2
  41. package/dist/govern.d.ts.map +1 -1
  42. package/dist/govern.js +475 -127
  43. package/dist/govern.js.map +1 -1
  44. package/dist/headless.d.ts +41 -2
  45. package/dist/headless.d.ts.map +1 -1
  46. package/dist/headless.js +203 -35
  47. package/dist/headless.js.map +1 -1
  48. package/dist/index.d.ts +4 -3
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +3 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/ledger/client.d.ts +14 -0
  53. package/dist/ledger/client.d.ts.map +1 -1
  54. package/dist/ledger/client.js +56 -0
  55. package/dist/ledger/client.js.map +1 -1
  56. package/dist/ledger/pricing.d.ts +54 -0
  57. package/dist/ledger/pricing.d.ts.map +1 -1
  58. package/dist/ledger/pricing.js +134 -8
  59. package/dist/ledger/pricing.js.map +1 -1
  60. package/dist/policy/default-rules.d.ts +18 -3
  61. package/dist/policy/default-rules.d.ts.map +1 -1
  62. package/dist/policy/default-rules.js +33 -15
  63. package/dist/policy/default-rules.js.map +1 -1
  64. package/dist/policy/gate.d.ts.map +1 -1
  65. package/dist/policy/gate.js +114 -16
  66. package/dist/policy/gate.js.map +1 -1
  67. package/dist/policy/injection.d.ts.map +1 -1
  68. package/dist/policy/injection.js +25 -16
  69. package/dist/policy/injection.js.map +1 -1
  70. package/dist/policy/pii.d.ts +20 -0
  71. package/dist/policy/pii.d.ts.map +1 -1
  72. package/dist/policy/pii.js +45 -2
  73. package/dist/policy/pii.js.map +1 -1
  74. package/dist/shared/types.d.ts +191 -0
  75. package/dist/shared/types.d.ts.map +1 -1
  76. package/dist/shared/types.js +67 -6
  77. package/dist/shared/types.js.map +1 -1
  78. package/dist/snapshot/checkpoint.d.ts +18 -2
  79. package/dist/snapshot/checkpoint.d.ts.map +1 -1
  80. package/dist/snapshot/checkpoint.js +101 -17
  81. package/dist/snapshot/checkpoint.js.map +1 -1
  82. package/dist/streaming.d.ts +8 -3
  83. package/dist/streaming.d.ts.map +1 -1
  84. package/dist/streaming.js +75 -31
  85. package/dist/streaming.js.map +1 -1
  86. package/dist/supply-chain/permissions.d.ts +16 -3
  87. package/dist/supply-chain/permissions.d.ts.map +1 -1
  88. package/dist/supply-chain/permissions.js +59 -9
  89. package/dist/supply-chain/permissions.js.map +1 -1
  90. package/dist/supply-chain/sign.d.ts +5 -2
  91. package/dist/supply-chain/sign.d.ts.map +1 -1
  92. package/dist/supply-chain/sign.js +10 -2
  93. package/dist/supply-chain/sign.js.map +1 -1
  94. package/package.json +2 -4
@@ -1,7 +1,9 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // Copyright 2026 Usertools, Inc.
3
- import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
4
- import { join, relative, resolve } from "node:path";
3
+ import { existsSync } from "node:fs";
4
+ import { mkdir, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
5
+ import { dirname, join, relative, resolve } from "node:path";
6
+ import { withAuditWriterLock } from "../audit/chain.js";
5
7
  // ── Constants ──
6
8
  const SNAPSHOTS_DIR = "snapshots";
7
9
  /** Directories to exclude from snapshots */
@@ -13,7 +15,13 @@ const INCLUDED_PATHS = new Set([
13
15
  "patterns",
14
16
  "usertrust.config.json",
15
17
  "leases.json",
18
+ // SNAP-1: the durable money mirror. Captured so a restore rolls the audit chain
19
+ // and the money ledger back together, never one without the other.
20
+ "spend-ledger.json",
16
21
  ]);
22
+ /** Never captured: advisory lock file living inside audit/. */
23
+ const NEVER_CAPTURE = new Set([".audit-writer.lock"]);
24
+ const LOCK_FILE_NAME = ".audit-writer.lock";
17
25
  // ── Internals ──
18
26
  /**
19
27
  * Recursively collect all files under a directory, returning relative paths.
@@ -35,6 +43,10 @@ async function collectFiles(basePath, currentPath) {
35
43
  results.push(...nested);
36
44
  }
37
45
  else if (entry.isFile()) {
46
+ // Never capture the audit-writer advisory lock — restoring a stale lock
47
+ // would falsely block a future writer.
48
+ if (NEVER_CAPTURE.has(entry.name))
49
+ continue;
38
50
  results.push(relPath);
39
51
  }
40
52
  }
@@ -103,11 +115,34 @@ export async function createSnapshot(vaultPath, name) {
103
115
  entries[relPath] = content.toString("base64");
104
116
  totalSize += content.length;
105
117
  }
118
+ // Forensic head anchors: the audit chain head and money-mirror value at capture
119
+ // time. Best-effort (a fresh vault has neither); the desync guard on restore keys
120
+ // off payload presence, not these fields, so their absence never weakens it.
121
+ let auditHead;
122
+ try {
123
+ const metaRaw = await readFile(join(vaultPath, "audit", "events.jsonl.meta"), "utf-8");
124
+ const m = JSON.parse(metaRaw);
125
+ auditHead = { lastHash: m.lastHash, sequence: m.sequence };
126
+ }
127
+ catch {
128
+ /* no audit head yet */
129
+ }
130
+ let budgetSpent;
131
+ try {
132
+ const led = JSON.parse(await readFile(join(vaultPath, "spend-ledger.json"), "utf-8"));
133
+ if (typeof led.budgetSpent === "number")
134
+ budgetSpent = led.budgetSpent;
135
+ }
136
+ catch {
137
+ /* no ledger yet */
138
+ }
106
139
  const meta = {
107
140
  name,
108
141
  timestamp: new Date().toISOString(),
109
142
  files,
110
143
  size: totalSize,
144
+ ...(auditHead !== undefined ? { auditHead } : {}),
145
+ ...(budgetSpent !== undefined ? { budgetSpent } : {}),
111
146
  };
112
147
  const payload = { meta, entries };
113
148
  const dir = snapshotsDir(vaultPath);
@@ -118,28 +153,77 @@ export async function createSnapshot(vaultPath, name) {
118
153
  }
119
154
  /**
120
155
  * Restore the vault state from a named snapshot.
121
- * Overwrites existing files with snapshot contents.
156
+ *
157
+ * Atomic (stage-then-commit), audit-writer-lock-aware, and refuses any restore
158
+ * that would sever money<->audit correspondence:
159
+ * - a snapshot that rolls back the audit chain MUST carry spend-ledger.json;
160
+ * - a live TigerBeetle store (which cannot be file-rolled-back) blocks an audit
161
+ * rollback unless the operator passes `forceLedgerDesync`.
122
162
  */
123
- export async function restoreSnapshot(vaultPath, name) {
163
+ export async function restoreSnapshot(vaultPath, name, opts) {
124
164
  validateSnapshotName(name);
125
165
  const filePath = snapshotFilePath(vaultPath, name);
126
166
  const raw = await readFile(filePath, "utf-8");
127
167
  const payload = JSON.parse(raw);
128
- for (const [relPath, b64Content] of Object.entries(payload.entries)) {
129
- if (relPath === "" || relPath === ".") {
130
- throw new Error("Invalid empty path in snapshot entry");
131
- }
132
- const fullPath = join(vaultPath, relPath);
133
- const resolvedPath = resolve(fullPath);
168
+ const entries = Object.entries(payload.entries);
169
+ const rollsBackAudit = entries.some(([p]) => p.startsWith("audit/"));
170
+ const hasLedger = Object.prototype.hasOwnProperty.call(payload.entries, "spend-ledger.json");
171
+ // Desync guard 1: a snapshot that rolls the audit chain back MUST carry the money
172
+ // mirror, or restoring audit alone deletes spend events whose money still exists.
173
+ if (rollsBackAudit && !hasLedger) {
174
+ throw new Error("Refusing restore: snapshot rolls back the audit chain but has no spend-ledger.json — money and audit would desync. Re-create the snapshot with a version that captures spend-ledger.json.");
175
+ }
176
+ // Desync guard 2: TigerBeetle is a live append-only ledger that cannot be file-
177
+ // rolled-back to the snapshot point. Rolling audit back while TB moves on forks
178
+ // money<->audit. Refuse unless the operator explicitly acknowledges.
179
+ if (rollsBackAudit && existsSync(join(vaultPath, "tigerbeetle")) && !opts?.forceLedgerDesync) {
180
+ throw new Error("Refusing restore: a live TigerBeetle ledger is present and cannot be rolled back to match the restored audit chain. Reconcile TB first, then re-run with --force.");
181
+ }
182
+ // The advisory lock lives in audit/; ensure the dir exists so we can take it.
183
+ const auditDir = join(vaultPath, "audit");
184
+ await mkdir(auditDir, { recursive: true });
185
+ const logPath = join(auditDir, "events.jsonl");
186
+ await withAuditWriterLock(logPath, async () => {
134
187
  const resolvedVault = resolve(vaultPath);
135
- if (!resolvedPath.startsWith(`${resolvedVault}/`)) {
136
- throw new Error(`Path traversal detected in snapshot: ${relPath}`);
188
+ const staged = [];
189
+ try {
190
+ // Phase 1: validate every path and materialize each target as a temp file.
191
+ for (const [relPath, b64Content] of entries) {
192
+ if (relPath === "" || relPath === ".") {
193
+ throw new Error("Invalid empty path in snapshot entry");
194
+ }
195
+ // Never restore an advisory lock captured by an older snapshot.
196
+ if (relPath.split("/").pop() === LOCK_FILE_NAME)
197
+ continue;
198
+ const fullPath = join(vaultPath, relPath);
199
+ const resolvedPath = resolve(fullPath);
200
+ if (!resolvedPath.startsWith(`${resolvedVault}/`)) {
201
+ throw new Error(`Path traversal detected in snapshot: ${relPath}`);
202
+ }
203
+ await mkdir(dirname(fullPath), { recursive: true });
204
+ const tmpPath = `${fullPath}.restore-tmp`;
205
+ await writeFile(tmpPath, Buffer.from(b64Content, "base64"));
206
+ staged.push({ finalPath: fullPath, tmpPath });
207
+ }
208
+ // Phase 2: commit — rename staged temps into place. Renames are fast and
209
+ // same-filesystem-atomic, bounding the crash window to the rename loop.
210
+ for (const s of staged) {
211
+ await rename(s.tmpPath, s.finalPath);
212
+ }
137
213
  }
138
- const dir = join(fullPath, "..");
139
- await mkdir(dir, { recursive: true });
140
- const content = Buffer.from(b64Content, "base64");
141
- await writeFile(fullPath, content);
142
- }
214
+ catch (err) {
215
+ // Any failure before/at commit: remove uncommitted temps, leaving originals intact.
216
+ for (const s of staged) {
217
+ try {
218
+ await rm(s.tmpPath, { force: true });
219
+ }
220
+ catch {
221
+ /* best effort */
222
+ }
223
+ }
224
+ throw err;
225
+ }
226
+ });
143
227
  }
144
228
  /**
145
229
  * List all snapshots in the vault, sorted by timestamp (oldest first).
@@ -1 +1 @@
1
- {"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/snapshot/checkpoint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checkpoint.js","sourceRoot":"","sources":["../../src/snapshot/checkpoint.ts"],"names":[],"mappings":"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"}
@@ -6,9 +6,14 @@
6
6
  * the yielded data.
7
7
  *
8
8
  * Provider-specific extraction:
9
- * - Anthropic: message_start (input_tokens), message_delta (output_tokens)
10
- * - OpenAI: usage field on final chunk (prompt_tokens, completion_tokens)
11
- * - Google: usageMetadata field (promptTokenCount, candidatesTokenCount)
9
+ * - Anthropic: message_start (input_tokens), message_delta (output_tokens)
10
+ * incremental fields on distinct chunk types, accumulated as before.
11
+ * - OpenAI: usage field (prompt_tokens, completion_tokens) — REPLACE-WITH-LATEST:
12
+ * every usage-bearing chunk is an absolute snapshot. vLLM's
13
+ * continuous_usage_stats stamps RUNNING totals on every chunk, so summing
14
+ * would multiply-count (M2 design decision 5.2 / plan Task 2).
15
+ * - Google: usageMetadata field (promptTokenCount, candidatesTokenCount) —
16
+ * same replace-with-latest snapshot semantics.
12
17
  *
13
18
  * Usage:
14
19
  * ```ts
@@ -1 +1 @@
1
- {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIrE,MAAM,WAAW,WAAW;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,WAAW,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;IAC1D,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/B;AAqDD;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,sBAAsB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC3B,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,IAAI,EAAE,aAAa,EACnB,UAAU,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAClD,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,KAAK,IAAI,EAC5D,OAAO,CAAC,EAAE,SAAS,GACjB,aAAa,CAAC,CAAC,CAAC,CAElB;AAqDD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACrC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,IAAI,EAAE,aAAa,EACnB,cAAc,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,OAAO,CAAC,YAAY,CAAC,EACvE,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,KAAK,IAAI,EAClE,OAAO,CAAC,EAAE,SAAS,GACjB,cAAc,CAAC,CAAC,CAAC,CA+BnB"}
1
+ {"version":3,"file":"streaming.d.ts","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIrE,MAAM,WAAW,WAAW;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,WAAW,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;IAC1D,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/B;AAkED;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,sBAAsB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC3B,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,IAAI,EAAE,aAAa,EACnB,UAAU,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,EAClD,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,KAAK,IAAI,EAC5D,OAAO,CAAC,EAAE,SAAS,GACjB,aAAa,CAAC,CAAC,CAAC,CAElB;AAkFD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACrC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EACxB,IAAI,EAAE,aAAa,EACnB,cAAc,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,OAAO,CAAC,YAAY,CAAC,EACvE,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,KAAK,IAAI,EAClE,OAAO,CAAC,EAAE,SAAS,GACjB,cAAc,CAAC,CAAC,CAAC,CA+BnB"}
package/dist/streaming.js CHANGED
@@ -1,46 +1,59 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // Copyright 2026 Usertools, Inc.
3
3
  // ── Token extraction ──
4
- function extractTokensFromChunk(chunk, kind) {
4
+ /** Anthropic chunks carry incremental fields on distinct chunk types. */
5
+ function extractAnthropicTokens(chunk) {
5
6
  if (chunk == null || typeof chunk !== "object") {
6
7
  return { inputTokens: 0, outputTokens: 0 };
7
8
  }
8
9
  const c = chunk;
9
- if (kind === "anthropic") {
10
- if (c.type === "message_start" && c.message != null && typeof c.message === "object") {
11
- const msg = c.message;
12
- if (msg.usage != null && typeof msg.usage === "object") {
13
- const usage = msg.usage;
14
- return { inputTokens: usage.input_tokens ?? 0, outputTokens: 0 };
15
- }
10
+ if (c.type === "message_start" && c.message != null && typeof c.message === "object") {
11
+ const msg = c.message;
12
+ if (msg.usage != null && typeof msg.usage === "object") {
13
+ const usage = msg.usage;
14
+ return { inputTokens: usage.input_tokens ?? 0, outputTokens: 0 };
16
15
  }
17
- if (c.type === "message_delta") {
18
- if (c.usage != null && typeof c.usage === "object") {
19
- const usage = c.usage;
20
- return { inputTokens: 0, outputTokens: usage.output_tokens ?? 0 };
21
- }
16
+ }
17
+ if (c.type === "message_delta") {
18
+ if (c.usage != null && typeof c.usage === "object") {
19
+ const usage = c.usage;
20
+ return { inputTokens: 0, outputTokens: usage.output_tokens ?? 0 };
22
21
  }
23
- return { inputTokens: 0, outputTokens: 0 };
24
22
  }
23
+ return { inputTokens: 0, outputTokens: 0 };
24
+ }
25
+ /** A7 sanitation: non-finite or negative provider counts are clamped to 0. */
26
+ function sanitizeCount(value) {
27
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
28
+ }
29
+ /**
30
+ * Extract an ABSOLUTE usage snapshot from an OpenAI/Google chunk, or null when
31
+ * the chunk carries no usage object at all. A present-but-empty usage object IS
32
+ * a snapshot (explicit zeros count as reported usage — A11).
33
+ */
34
+ function extractUsageSnapshot(chunk, kind) {
35
+ if (chunk == null || typeof chunk !== "object")
36
+ return null;
37
+ const c = chunk;
25
38
  if (kind === "openai") {
26
39
  if (c.usage != null && typeof c.usage === "object") {
27
40
  const usage = c.usage;
28
41
  return {
29
- inputTokens: usage.prompt_tokens ?? 0,
30
- outputTokens: usage.completion_tokens ?? 0,
42
+ inputTokens: sanitizeCount(usage.prompt_tokens),
43
+ outputTokens: sanitizeCount(usage.completion_tokens),
31
44
  };
32
45
  }
33
- return { inputTokens: 0, outputTokens: 0 };
46
+ return null;
34
47
  }
35
48
  // google
36
49
  if (c.usageMetadata != null && typeof c.usageMetadata === "object") {
37
50
  const meta = c.usageMetadata;
38
51
  return {
39
- inputTokens: meta.promptTokenCount ?? 0,
40
- outputTokens: meta.candidatesTokenCount ?? 0,
52
+ inputTokens: sanitizeCount(meta.promptTokenCount),
53
+ outputTokens: sanitizeCount(meta.candidatesTokenCount),
41
54
  };
42
55
  }
43
- return { inputTokens: 0, outputTokens: 0 };
56
+ return null;
44
57
  }
45
58
  /**
46
59
  * Wraps a provider stream with token counting.
@@ -57,21 +70,44 @@ async function* wrapStreamImpl(stream, kind, onComplete, onError, onChunk) {
57
70
  let outputTokens = 0;
58
71
  let chunksDelivered = 0;
59
72
  let usageReported = false;
73
+ // P4-STREAM-LEAK: settlement runs in `finally` so that a consumer who breaks
74
+ // out of the `for await` early (which drives generator `.return()`) settles the
75
+ // consumed cost EXACTLY like a normal end-of-stream — the hold is released, the
76
+ // audit event is written, and `.receipt` resolves. Only a thrown error voids.
77
+ let errored = false;
60
78
  try {
61
79
  for await (const chunk of stream) {
62
- const tokens = extractTokensFromChunk(chunk, kind);
63
80
  let deltaInput = 0;
64
81
  let deltaOutput = 0;
65
- // Use latest non-zero value (providers report cumulative or final)
66
- if (tokens.inputTokens > 0) {
67
- deltaInput = Math.max(0, tokens.inputTokens - inputTokens);
68
- inputTokens = tokens.inputTokens;
69
- usageReported = true;
82
+ if (kind === "openai" || kind === "google") {
83
+ // M2 REPLACE-WITH-LATEST (design decision 5.2 / plan Task 2): each
84
+ // usage-bearing chunk is an absolute snapshot, assigned wholesale.
85
+ // Fixes double-counting under vLLM continuous_usage_stats (running
86
+ // totals on every chunk); a decreasing final total takes the last
87
+ // chunk's values (A7); explicit zeros count as reported usage (A11).
88
+ const snapshot = extractUsageSnapshot(chunk, kind);
89
+ if (snapshot != null) {
90
+ deltaInput = Math.max(0, snapshot.inputTokens - inputTokens);
91
+ deltaOutput = Math.max(0, snapshot.outputTokens - outputTokens);
92
+ inputTokens = snapshot.inputTokens;
93
+ outputTokens = snapshot.outputTokens;
94
+ usageReported = true;
95
+ }
70
96
  }
71
- if (tokens.outputTokens > 0) {
72
- deltaOutput = Math.max(0, tokens.outputTokens - outputTokens);
73
- outputTokens = tokens.outputTokens;
74
- usageReported = true;
97
+ else {
98
+ // Anthropic: message_start carries input, message_delta carries output —
99
+ // genuinely incremental chunk types; keep the latest non-zero value.
100
+ const tokens = extractAnthropicTokens(chunk);
101
+ if (tokens.inputTokens > 0) {
102
+ deltaInput = Math.max(0, tokens.inputTokens - inputTokens);
103
+ inputTokens = tokens.inputTokens;
104
+ usageReported = true;
105
+ }
106
+ if (tokens.outputTokens > 0) {
107
+ deltaOutput = Math.max(0, tokens.outputTokens - outputTokens);
108
+ outputTokens = tokens.outputTokens;
109
+ usageReported = true;
110
+ }
75
111
  }
76
112
  // Run hook BEFORE yielding so a throw aborts before the consumer sees it.
77
113
  if (onChunk != null) {
@@ -85,12 +121,20 @@ async function* wrapStreamImpl(stream, kind, onComplete, onError, onChunk) {
85
121
  yield chunk;
86
122
  chunksDelivered++;
87
123
  }
88
- onComplete({ usage: { inputTokens, outputTokens }, chunksDelivered, usageReported });
89
124
  }
90
125
  catch (err) {
126
+ errored = true;
91
127
  onError(err, { usage: { inputTokens, outputTokens }, chunksDelivered, usageReported });
92
128
  throw err;
93
129
  }
130
+ finally {
131
+ // Normal completion AND early termination (consumer break → generator
132
+ // `.return()`) both settle here. A thrown error already ran `onError` and set
133
+ // `errored`, so it is the only path that skips settlement (it voids instead).
134
+ if (!errored) {
135
+ onComplete({ usage: { inputTokens, outputTokens }, chunksDelivered, usageReported });
136
+ }
137
+ }
94
138
  }
95
139
  // ── GovernedStream factory ──
96
140
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"streaming.js","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"streaming.js","sourceRoot":"","sources":["../src/streaming.ts"],"names":[],"mappings":"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"}
@@ -2,11 +2,24 @@ import type { SkillManifest, SkillVerification, TrustConfig } from "../shared/ty
2
2
  /**
3
3
  * Checks whether a manifest's permissions are allowed by the config policy.
4
4
  * Trusted publishers bypass permission restrictions.
5
+ *
6
+ * NOTE: this does NOT verify identity — it is only reached from `enforceSkillLoad`
7
+ * after the signature has been checked against a REGISTERED key, so the trusted-
8
+ * publisher bypass here cannot be triggered by a forged-publisher manifest.
9
+ * `integrityVerified` is set to false here; `enforceSkillLoad` overrides it once
10
+ * source bytes have been re-hashed.
5
11
  */
6
12
  export declare function checkPermissions(manifest: SkillManifest, config: TrustConfig): SkillVerification;
7
13
  /**
8
- * Full verification pipeline: validate schema, verify signature, check permissions, check trusted publishers.
9
- * Returns a SkillVerification result. Throws SkillVerificationError on hard failures.
14
+ * Full verification pipeline: validate schema, verify signature against the
15
+ * REGISTERED publisher key(s), re-hash the loaded source against the signed
16
+ * entryHash, then check permissions. Returns a SkillVerification result.
17
+ * Throws SkillVerificationError on hard (schema) failures.
18
+ *
19
+ * @param entrySource The exact bytes to be executed. When provided, they are
20
+ * re-hashed and compared to the signed `entryHash` (SC-2). A call WITHOUT
21
+ * `entrySource` yields `integrityVerified:false` and MUST be treated by any
22
+ * executor as "integrity unverified — do not execute".
10
23
  */
11
- export declare function enforceSkillLoad(manifest: SkillManifest, config: TrustConfig): SkillVerification;
24
+ export declare function enforceSkillLoad(manifest: SkillManifest, config: TrustConfig, entrySource?: string | Buffer): SkillVerification;
12
25
  //# sourceMappingURL=permissions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/supply-chain/permissions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACX,aAAa,EAEb,iBAAiB,EACjB,WAAW,EACX,MAAM,oBAAoB,CAAC;AAY5B;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAuBhG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAqDhG"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/supply-chain/permissions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACX,aAAa,EAEb,iBAAiB,EACjB,WAAW,EACX,MAAM,oBAAoB,CAAC;AAY5B;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAyBhG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC/B,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,WAAW,EACnB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAC3B,iBAAiB,CA0FnB"}
@@ -15,6 +15,12 @@ function computeManifestHash(manifest) {
15
15
  /**
16
16
  * Checks whether a manifest's permissions are allowed by the config policy.
17
17
  * Trusted publishers bypass permission restrictions.
18
+ *
19
+ * NOTE: this does NOT verify identity — it is only reached from `enforceSkillLoad`
20
+ * after the signature has been checked against a REGISTERED key, so the trusted-
21
+ * publisher bypass here cannot be triggered by a forged-publisher manifest.
22
+ * `integrityVerified` is set to false here; `enforceSkillLoad` overrides it once
23
+ * source bytes have been re-hashed.
18
24
  */
19
25
  export function checkPermissions(manifest, config) {
20
26
  const sc = config.supplyChain;
@@ -26,6 +32,7 @@ export function checkPermissions(manifest, config) {
26
32
  permissionsAllowed: true,
27
33
  deniedPermissions: [],
28
34
  manifestHash,
35
+ integrityVerified: false,
29
36
  };
30
37
  }
31
38
  const allowed = new Set(sc.allowedPermissions);
@@ -35,21 +42,31 @@ export function checkPermissions(manifest, config) {
35
42
  permissionsAllowed: denied.length === 0,
36
43
  deniedPermissions: denied,
37
44
  manifestHash,
45
+ integrityVerified: false,
38
46
  };
39
47
  }
40
48
  /**
41
- * Full verification pipeline: validate schema, verify signature, check permissions, check trusted publishers.
42
- * Returns a SkillVerification result. Throws SkillVerificationError on hard failures.
49
+ * Full verification pipeline: validate schema, verify signature against the
50
+ * REGISTERED publisher key(s), re-hash the loaded source against the signed
51
+ * entryHash, then check permissions. Returns a SkillVerification result.
52
+ * Throws SkillVerificationError on hard (schema) failures.
53
+ *
54
+ * @param entrySource The exact bytes to be executed. When provided, they are
55
+ * re-hashed and compared to the signed `entryHash` (SC-2). A call WITHOUT
56
+ * `entrySource` yields `integrityVerified:false` and MUST be treated by any
57
+ * executor as "integrity unverified — do not execute".
43
58
  */
44
- export function enforceSkillLoad(manifest, config) {
59
+ export function enforceSkillLoad(manifest, config, entrySource) {
45
60
  const sc = config.supplyChain;
46
- // Guard: if supply chain is disabled, allow everything
61
+ // Guard: if supply chain is disabled, allow everything (deliberate operator
62
+ // override — only reachable once the operator has explicitly set enabled:false).
47
63
  if (!sc.enabled) {
48
64
  return {
49
65
  valid: true,
50
66
  permissionsAllowed: true,
51
67
  deniedPermissions: [],
52
68
  manifestHash: computeManifestHash(manifest),
69
+ integrityVerified: false,
53
70
  };
54
71
  }
55
72
  // Step 1: Validate schema
@@ -58,12 +75,24 @@ export function enforceSkillLoad(manifest, config) {
58
75
  const reason = parseResult.error.issues.map((i) => i.message).join("; ");
59
76
  throw new SkillVerificationError(manifest.id ?? "unknown", `Schema validation failed: ${reason}`);
60
77
  }
61
- // Step 2: Verify signature
62
- // Always verify signature for trusted publishers (prevent publisher forgery)
63
- // Also verify if requireSignature is true
78
+ // Step 2: Verify signature against the REGISTERED key(s) for the claimed
79
+ // publisher. The publisher->key registry is the trust anchor; an unregistered
80
+ // publisher or a self-signed key cannot be trusted.
81
+ const registeredKeys = sc.publisherKeys[manifest.publisher] ?? [];
64
82
  const isTrusted = sc.trustedPublishers.includes(manifest.publisher);
65
83
  if (sc.requireSignature || isTrusted) {
66
- const sigValid = verifySignature(manifest);
84
+ if (registeredKeys.length === 0) {
85
+ const manifestHash = computeManifestHash(manifest);
86
+ return {
87
+ valid: false,
88
+ permissionsAllowed: false,
89
+ deniedPermissions: manifest.permissions,
90
+ manifestHash,
91
+ integrityVerified: false,
92
+ error: `No registered signing key for publisher "${manifest.publisher}"`,
93
+ };
94
+ }
95
+ const sigValid = verifySignature(manifest, registeredKeys);
67
96
  if (!sigValid) {
68
97
  const manifestHash = computeManifestHash(manifest);
69
98
  return {
@@ -71,19 +100,40 @@ export function enforceSkillLoad(manifest, config) {
71
100
  permissionsAllowed: false,
72
101
  deniedPermissions: manifest.permissions,
73
102
  manifestHash,
103
+ integrityVerified: false,
74
104
  error: "Invalid manifest signature",
75
105
  };
76
106
  }
77
107
  }
108
+ // Step 2b: Code integrity — the bytes being loaded MUST hash to the signed
109
+ // entryHash. A valid signature over a manifest is worthless if it can be
110
+ // paired with other (malicious) code.
111
+ let integrityVerified = false;
112
+ if (entrySource !== undefined) {
113
+ const actualHash = createHash("sha256").update(entrySource).digest("hex");
114
+ if (actualHash !== manifest.entryHash) {
115
+ const manifestHash = computeManifestHash(manifest);
116
+ return {
117
+ valid: false,
118
+ permissionsAllowed: false,
119
+ deniedPermissions: manifest.permissions,
120
+ manifestHash,
121
+ integrityVerified: false,
122
+ error: "entryHash mismatch — skill source does not match signed manifest",
123
+ };
124
+ }
125
+ integrityVerified = true;
126
+ }
78
127
  // Step 3: Check permissions and trusted publishers
79
128
  const result = checkPermissions(manifest, config);
80
129
  if (!result.permissionsAllowed) {
81
130
  return {
82
131
  ...result,
83
132
  valid: false,
133
+ integrityVerified,
84
134
  error: `Denied permissions: ${result.deniedPermissions.join(", ")}`,
85
135
  };
86
136
  }
87
- return result;
137
+ return { ...result, integrityVerified };
88
138
  }
89
139
  //# sourceMappingURL=permissions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/supply-chain/permissions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/supply-chain/permissions.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,10 @@ export declare function generateKeyPair(): {
11
11
  */
12
12
  export declare function signManifest(manifest: Omit<SkillManifest, "signature" | "publicKey" | "signedAt">, privateKeyHex: string): SkillManifest;
13
13
  /**
14
- * Verifies the Ed25519 signature on a signed manifest.
14
+ * Verifies the Ed25519 signature on a signed manifest against the REGISTERED
15
+ * public key(s) for the claimed publisher. The key embedded in the manifest is
16
+ * NOT trusted as an authority: it is accepted only if it is one of `trustedKeys`.
17
+ * Passing an empty `trustedKeys` list always fails closed.
15
18
  */
16
- export declare function verifySignature(manifest: SkillManifest): boolean;
19
+ export declare function verifySignature(manifest: SkillManifest, trustedKeys: string[]): boolean;
17
20
  //# sourceMappingURL=sign.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sign.d.ts","sourceRoot":"","sources":["../../src/supply-chain/sign.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;GAEG;AACH,wBAAgB,eAAe,IAAI;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAU3E;AAuBD;;GAEG;AACH,wBAAgB,YAAY,CAC3B,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC,EACrE,aAAa,EAAE,MAAM,GACnB,aAAa,CA+Bf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CA+BhE"}
1
+ {"version":3,"file":"sign.d.ts","sourceRoot":"","sources":["../../src/supply-chain/sign.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;GAEG;AACH,wBAAgB,eAAe,IAAI;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAU3E;AAuBD;;GAEG;AACH,wBAAgB,YAAY,CAC3B,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC,EACrE,aAAa,EAAE,MAAM,GACnB,aAAa,CA+Bf;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAqCvF"}