open-multi-agent-kit 0.90.8 → 0.90.9

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 (306) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +7 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +4 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/commands/doctor-provider-cli.d.ts +33 -0
  7. package/dist/commands/doctor-provider-cli.d.ts.map +1 -0
  8. package/dist/commands/doctor-provider-cli.js +215 -0
  9. package/dist/commands/doctor-provider-cli.js.map +1 -0
  10. package/dist/commands/doctor-provider-transport.d.ts +35 -0
  11. package/dist/commands/doctor-provider-transport.d.ts.map +1 -0
  12. package/dist/commands/doctor-provider-transport.js +185 -0
  13. package/dist/commands/doctor-provider-transport.js.map +1 -0
  14. package/dist/commands/doctor-provider.d.ts +121 -7
  15. package/dist/commands/doctor-provider.d.ts.map +1 -1
  16. package/dist/commands/doctor-provider.js +1295 -102
  17. package/dist/commands/doctor-provider.js.map +1 -1
  18. package/dist/commands/session-doctor-cli.d.ts +43 -0
  19. package/dist/commands/session-doctor-cli.d.ts.map +1 -0
  20. package/dist/commands/session-doctor-cli.js +494 -0
  21. package/dist/commands/session-doctor-cli.js.map +1 -0
  22. package/dist/commands/verify-ci.d.ts +21 -0
  23. package/dist/commands/verify-ci.d.ts.map +1 -0
  24. package/dist/commands/verify-ci.js +66 -0
  25. package/dist/commands/verify-ci.js.map +1 -0
  26. package/dist/core/agent-session-services.d.ts +3 -0
  27. package/dist/core/agent-session-services.d.ts.map +1 -1
  28. package/dist/core/agent-session-services.js +3 -0
  29. package/dist/core/agent-session-services.js.map +1 -1
  30. package/dist/core/agent-session.d.ts +113 -2
  31. package/dist/core/agent-session.d.ts.map +1 -1
  32. package/dist/core/agent-session.js +993 -72
  33. package/dist/core/agent-session.js.map +1 -1
  34. package/dist/core/agent-tool-settings.d.ts +35 -0
  35. package/dist/core/agent-tool-settings.d.ts.map +1 -0
  36. package/dist/core/agent-tool-settings.js +155 -0
  37. package/dist/core/agent-tool-settings.js.map +1 -0
  38. package/dist/core/atomic-session-file.d.ts +14 -0
  39. package/dist/core/atomic-session-file.d.ts.map +1 -0
  40. package/dist/core/atomic-session-file.js +104 -0
  41. package/dist/core/atomic-session-file.js.map +1 -0
  42. package/dist/core/compaction/compaction.d.ts +6 -0
  43. package/dist/core/compaction/compaction.d.ts.map +1 -1
  44. package/dist/core/compaction/compaction.js +12 -1
  45. package/dist/core/compaction/compaction.js.map +1 -1
  46. package/dist/core/compaction/hysteresis.d.ts +27 -0
  47. package/dist/core/compaction/hysteresis.d.ts.map +1 -0
  48. package/dist/core/compaction/hysteresis.js +84 -0
  49. package/dist/core/compaction/hysteresis.js.map +1 -0
  50. package/dist/core/compaction/index.d.ts +2 -0
  51. package/dist/core/compaction/index.d.ts.map +1 -1
  52. package/dist/core/compaction/index.js +2 -0
  53. package/dist/core/compaction/index.js.map +1 -1
  54. package/dist/core/compaction/transaction.d.ts +172 -0
  55. package/dist/core/compaction/transaction.d.ts.map +1 -0
  56. package/dist/core/compaction/transaction.js +824 -0
  57. package/dist/core/compaction/transaction.js.map +1 -0
  58. package/dist/core/context-budget-governor-v2.d.ts +2 -1
  59. package/dist/core/context-budget-governor-v2.d.ts.map +1 -1
  60. package/dist/core/context-budget-governor-v2.js +2 -1
  61. package/dist/core/context-budget-governor-v2.js.map +1 -1
  62. package/dist/core/context-budget-reserved-tokens.d.ts +110 -0
  63. package/dist/core/context-budget-reserved-tokens.d.ts.map +1 -0
  64. package/dist/core/context-budget-reserved-tokens.js +188 -0
  65. package/dist/core/context-budget-reserved-tokens.js.map +1 -0
  66. package/dist/core/context-budget-v2-cache-invalidation.d.ts +133 -0
  67. package/dist/core/context-budget-v2-cache-invalidation.d.ts.map +1 -0
  68. package/dist/core/context-budget-v2-cache-invalidation.js +452 -0
  69. package/dist/core/context-budget-v2-cache-invalidation.js.map +1 -0
  70. package/dist/core/context-budget-v2-cache-keys.d.ts +3 -0
  71. package/dist/core/context-budget-v2-cache-keys.d.ts.map +1 -1
  72. package/dist/core/context-budget-v2-cache-keys.js +6 -0
  73. package/dist/core/context-budget-v2-cache-keys.js.map +1 -1
  74. package/dist/core/context-budget-v2-cache-provider.d.ts +4 -0
  75. package/dist/core/context-budget-v2-cache-provider.d.ts.map +1 -1
  76. package/dist/core/context-budget-v2-cache-provider.js +19 -0
  77. package/dist/core/context-budget-v2-cache-provider.js.map +1 -1
  78. package/dist/core/context-budget-v2-plan-cache-keys.d.ts.map +1 -1
  79. package/dist/core/context-budget-v2-plan-cache-keys.js +1 -0
  80. package/dist/core/context-budget-v2-plan-cache-keys.js.map +1 -1
  81. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  82. package/dist/core/context-budget-v2-planner.js +1 -0
  83. package/dist/core/context-budget-v2-planner.js.map +1 -1
  84. package/dist/core/context-budget-v2-types.d.ts +4 -0
  85. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  86. package/dist/core/context-budget-v2-types.js.map +1 -1
  87. package/dist/core/durable-file-directory.d.ts +4 -0
  88. package/dist/core/durable-file-directory.d.ts.map +1 -0
  89. package/dist/core/durable-file-directory.js +76 -0
  90. package/dist/core/durable-file-directory.js.map +1 -0
  91. package/dist/core/durable-file-identity.d.ts +26 -0
  92. package/dist/core/durable-file-identity.d.ts.map +1 -0
  93. package/dist/core/durable-file-identity.js +118 -0
  94. package/dist/core/durable-file-identity.js.map +1 -0
  95. package/dist/core/durable-file-io.d.ts +29 -0
  96. package/dist/core/durable-file-io.d.ts.map +1 -0
  97. package/dist/core/durable-file-io.js +179 -0
  98. package/dist/core/durable-file-io.js.map +1 -0
  99. package/dist/core/durable-file-lock-cleanup.d.ts +12 -0
  100. package/dist/core/durable-file-lock-cleanup.d.ts.map +1 -0
  101. package/dist/core/durable-file-lock-cleanup.js +39 -0
  102. package/dist/core/durable-file-lock-cleanup.js.map +1 -0
  103. package/dist/core/durable-file-lock-owner.d.ts +18 -0
  104. package/dist/core/durable-file-lock-owner.d.ts.map +1 -0
  105. package/dist/core/durable-file-lock-owner.js +78 -0
  106. package/dist/core/durable-file-lock-owner.js.map +1 -0
  107. package/dist/core/durable-file-lock-storage.d.ts +35 -0
  108. package/dist/core/durable-file-lock-storage.d.ts.map +1 -0
  109. package/dist/core/durable-file-lock-storage.js +263 -0
  110. package/dist/core/durable-file-lock-storage.js.map +1 -0
  111. package/dist/core/durable-file-mode.d.ts +8 -0
  112. package/dist/core/durable-file-mode.d.ts.map +1 -0
  113. package/dist/core/durable-file-mode.js +41 -0
  114. package/dist/core/durable-file-mode.js.map +1 -0
  115. package/dist/core/extensions/loader.d.ts +12 -0
  116. package/dist/core/extensions/loader.d.ts.map +1 -1
  117. package/dist/core/extensions/loader.js +46 -37
  118. package/dist/core/extensions/loader.js.map +1 -1
  119. package/dist/core/index.d.ts +6 -2
  120. package/dist/core/index.d.ts.map +1 -1
  121. package/dist/core/index.js +5 -0
  122. package/dist/core/index.js.map +1 -1
  123. package/dist/core/model-resolver.d.ts.map +1 -1
  124. package/dist/core/model-resolver.js +1 -1
  125. package/dist/core/model-resolver.js.map +1 -1
  126. package/dist/core/redaction.d.ts +8 -0
  127. package/dist/core/redaction.d.ts.map +1 -0
  128. package/dist/core/redaction.js +31 -0
  129. package/dist/core/redaction.js.map +1 -0
  130. package/dist/core/resource-loader.d.ts.map +1 -1
  131. package/dist/core/resource-loader.js +36 -0
  132. package/dist/core/resource-loader.js.map +1 -1
  133. package/dist/core/run-journal-store.d.ts +53 -0
  134. package/dist/core/run-journal-store.d.ts.map +1 -0
  135. package/dist/core/run-journal-store.js +278 -0
  136. package/dist/core/run-journal-store.js.map +1 -0
  137. package/dist/core/run-journal.d.ts +172 -0
  138. package/dist/core/run-journal.d.ts.map +1 -0
  139. package/dist/core/run-journal.js +1053 -0
  140. package/dist/core/run-journal.js.map +1 -0
  141. package/dist/core/sdk.d.ts +7 -0
  142. package/dist/core/sdk.d.ts.map +1 -1
  143. package/dist/core/sdk.js +94 -3
  144. package/dist/core/sdk.js.map +1 -1
  145. package/dist/core/session-doctor-plan.d.ts +128 -0
  146. package/dist/core/session-doctor-plan.d.ts.map +1 -0
  147. package/dist/core/session-doctor-plan.js +833 -0
  148. package/dist/core/session-doctor-plan.js.map +1 -0
  149. package/dist/core/session-file-compaction.d.ts +6 -0
  150. package/dist/core/session-file-compaction.d.ts.map +1 -0
  151. package/dist/core/session-file-compaction.js +169 -0
  152. package/dist/core/session-file-compaction.js.map +1 -0
  153. package/dist/core/session-file-head.d.ts +10 -0
  154. package/dist/core/session-file-head.d.ts.map +1 -0
  155. package/dist/core/session-file-head.js +78 -0
  156. package/dist/core/session-file-head.js.map +1 -0
  157. package/dist/core/session-file-persistence.d.ts +30 -0
  158. package/dist/core/session-file-persistence.d.ts.map +1 -0
  159. package/dist/core/session-file-persistence.js +106 -0
  160. package/dist/core/session-file-persistence.js.map +1 -0
  161. package/dist/core/session-integrity.d.ts +43 -0
  162. package/dist/core/session-integrity.d.ts.map +1 -0
  163. package/dist/core/session-integrity.js +420 -0
  164. package/dist/core/session-integrity.js.map +1 -0
  165. package/dist/core/session-manager.d.ts +24 -4
  166. package/dist/core/session-manager.d.ts.map +1 -1
  167. package/dist/core/session-manager.js +242 -125
  168. package/dist/core/session-manager.js.map +1 -1
  169. package/dist/core/session-owner-lease.d.ts +22 -0
  170. package/dist/core/session-owner-lease.d.ts.map +1 -0
  171. package/dist/core/session-owner-lease.js +176 -0
  172. package/dist/core/session-owner-lease.js.map +1 -0
  173. package/dist/core/session-path-policy.d.ts +132 -0
  174. package/dist/core/session-path-policy.d.ts.map +1 -0
  175. package/dist/core/session-path-policy.js +780 -0
  176. package/dist/core/session-path-policy.js.map +1 -0
  177. package/dist/core/session-repair-plan.d.ts +49 -0
  178. package/dist/core/session-repair-plan.d.ts.map +1 -0
  179. package/dist/core/session-repair-plan.js +202 -0
  180. package/dist/core/session-repair-plan.js.map +1 -0
  181. package/dist/core/session-termination.d.ts +100 -0
  182. package/dist/core/session-termination.d.ts.map +1 -0
  183. package/dist/core/session-termination.js +403 -0
  184. package/dist/core/session-termination.js.map +1 -0
  185. package/dist/core/settings-manager.d.ts +22 -0
  186. package/dist/core/settings-manager.d.ts.map +1 -1
  187. package/dist/core/settings-manager.js +37 -5
  188. package/dist/core/settings-manager.js.map +1 -1
  189. package/dist/core/system-prompt.d.ts.map +1 -1
  190. package/dist/core/system-prompt.js +1 -1
  191. package/dist/core/system-prompt.js.map +1 -1
  192. package/dist/core/verified-bash-adapter.d.ts +36 -0
  193. package/dist/core/verified-bash-adapter.d.ts.map +1 -0
  194. package/dist/core/verified-bash-adapter.js +90 -0
  195. package/dist/core/verified-bash-adapter.js.map +1 -0
  196. package/dist/guardrails/command-redaction.d.ts +32 -0
  197. package/dist/guardrails/command-redaction.d.ts.map +1 -0
  198. package/dist/guardrails/command-redaction.js +776 -0
  199. package/dist/guardrails/command-redaction.js.map +1 -0
  200. package/dist/guardrails/evidence-attestation.d.ts +31 -0
  201. package/dist/guardrails/evidence-attestation.d.ts.map +1 -0
  202. package/dist/guardrails/evidence-attestation.js +178 -0
  203. package/dist/guardrails/evidence-attestation.js.map +1 -0
  204. package/dist/guardrails/evidence-receipt-store.d.ts +33 -0
  205. package/dist/guardrails/evidence-receipt-store.d.ts.map +1 -0
  206. package/dist/guardrails/evidence-receipt-store.js +446 -0
  207. package/dist/guardrails/evidence-receipt-store.js.map +1 -0
  208. package/dist/guardrails/evidence-receipt.d.ts +58 -0
  209. package/dist/guardrails/evidence-receipt.d.ts.map +1 -0
  210. package/dist/guardrails/evidence-receipt.js +389 -0
  211. package/dist/guardrails/evidence-receipt.js.map +1 -0
  212. package/dist/guardrails/evidence-system.d.ts +39 -15
  213. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  214. package/dist/guardrails/evidence-system.js +255 -97
  215. package/dist/guardrails/evidence-system.js.map +1 -1
  216. package/dist/guardrails/replay-ledger-io.d.ts +6 -0
  217. package/dist/guardrails/replay-ledger-io.d.ts.map +1 -0
  218. package/dist/guardrails/replay-ledger-io.js +42 -0
  219. package/dist/guardrails/replay-ledger-io.js.map +1 -0
  220. package/dist/guardrails/replay-ledger-lock-owner.d.ts +32 -0
  221. package/dist/guardrails/replay-ledger-lock-owner.d.ts.map +1 -0
  222. package/dist/guardrails/replay-ledger-lock-owner.js +138 -0
  223. package/dist/guardrails/replay-ledger-lock-owner.js.map +1 -0
  224. package/dist/guardrails/replay-ledger-lock.d.ts +24 -0
  225. package/dist/guardrails/replay-ledger-lock.d.ts.map +1 -0
  226. package/dist/guardrails/replay-ledger-lock.js +135 -0
  227. package/dist/guardrails/replay-ledger-lock.js.map +1 -0
  228. package/dist/guardrails/replay-ledger-mutation-gate.d.ts +24 -0
  229. package/dist/guardrails/replay-ledger-mutation-gate.d.ts.map +1 -0
  230. package/dist/guardrails/replay-ledger-mutation-gate.js +205 -0
  231. package/dist/guardrails/replay-ledger-mutation-gate.js.map +1 -0
  232. package/dist/guardrails/replay-ledger-quarantine.d.ts +2 -0
  233. package/dist/guardrails/replay-ledger-quarantine.d.ts.map +1 -0
  234. package/dist/guardrails/replay-ledger-quarantine.js +19 -0
  235. package/dist/guardrails/replay-ledger-quarantine.js.map +1 -0
  236. package/dist/guardrails/replay-ledger-store.d.ts +32 -0
  237. package/dist/guardrails/replay-ledger-store.d.ts.map +1 -0
  238. package/dist/guardrails/replay-ledger-store.js +211 -0
  239. package/dist/guardrails/replay-ledger-store.js.map +1 -0
  240. package/dist/guardrails/shell-command-name-glob.d.ts +3 -0
  241. package/dist/guardrails/shell-command-name-glob.d.ts.map +1 -0
  242. package/dist/guardrails/shell-command-name-glob.js +233 -0
  243. package/dist/guardrails/shell-command-name-glob.js.map +1 -0
  244. package/dist/guardrails/shell-command-option.d.ts +7 -0
  245. package/dist/guardrails/shell-command-option.d.ts.map +1 -0
  246. package/dist/guardrails/shell-command-option.js +24 -0
  247. package/dist/guardrails/shell-command-option.js.map +1 -0
  248. package/dist/guardrails/shell-command-tokenizer.d.ts +29 -0
  249. package/dist/guardrails/shell-command-tokenizer.d.ts.map +1 -0
  250. package/dist/guardrails/shell-command-tokenizer.js +145 -0
  251. package/dist/guardrails/shell-command-tokenizer.js.map +1 -0
  252. package/dist/guardrails/shell-command-wrapper.d.ts +18 -0
  253. package/dist/guardrails/shell-command-wrapper.d.ts.map +1 -0
  254. package/dist/guardrails/shell-command-wrapper.js +42 -0
  255. package/dist/guardrails/shell-command-wrapper.js.map +1 -0
  256. package/dist/guardrails/verified-executor.d.ts +65 -0
  257. package/dist/guardrails/verified-executor.d.ts.map +1 -0
  258. package/dist/guardrails/verified-executor.js +171 -0
  259. package/dist/guardrails/verified-executor.js.map +1 -0
  260. package/dist/guardrails/workspace-fingerprint.d.ts +23 -0
  261. package/dist/guardrails/workspace-fingerprint.d.ts.map +1 -0
  262. package/dist/guardrails/workspace-fingerprint.js +634 -0
  263. package/dist/guardrails/workspace-fingerprint.js.map +1 -0
  264. package/dist/index.d.ts +15 -3
  265. package/dist/index.d.ts.map +1 -1
  266. package/dist/index.js +13 -1
  267. package/dist/index.js.map +1 -1
  268. package/dist/main.d.ts.map +1 -1
  269. package/dist/main.js +12 -0
  270. package/dist/main.js.map +1 -1
  271. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  272. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  273. package/dist/modes/interactive/interactive-mode.js +59 -9
  274. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  275. package/dist/modes/print-mode.d.ts.map +1 -1
  276. package/dist/modes/print-mode.js +43 -2
  277. package/dist/modes/print-mode.js.map +1 -1
  278. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  279. package/dist/modes/rpc/rpc-mode.js +23 -5
  280. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  281. package/dist/modes/rpc/rpc-types.d.ts +3 -0
  282. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  283. package/dist/modes/rpc/rpc-types.js.map +1 -1
  284. package/dist/types/evidence.d.ts +211 -1
  285. package/dist/types/evidence.d.ts.map +1 -1
  286. package/dist/types/evidence.js.map +1 -1
  287. package/dist/verify-ci.d.ts +3 -0
  288. package/dist/verify-ci.d.ts.map +1 -0
  289. package/dist/verify-ci.js +30 -0
  290. package/dist/verify-ci.js.map +1 -0
  291. package/docs/compaction.md +38 -4
  292. package/docs/extensions.md +2 -0
  293. package/docs/sdk.md +238 -1
  294. package/docs/settings.md +50 -2
  295. package/docs/usage.md +38 -0
  296. package/examples/extensions/custom-provider-anthropic/package-lock.json +5 -5
  297. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  298. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  299. package/examples/extensions/gondolin/package-lock.json +2 -2
  300. package/examples/extensions/gondolin/package.json +1 -1
  301. package/examples/extensions/sandbox/package-lock.json +2 -2
  302. package/examples/extensions/sandbox/package.json +1 -1
  303. package/examples/extensions/with-deps/package-lock.json +4 -4
  304. package/examples/extensions/with-deps/package.json +1 -1
  305. package/npm-shrinkwrap.json +12 -12
  306. package/package.json +4 -4
@@ -0,0 +1,389 @@
1
+ import { createHash, timingSafeEqual } from "node:crypto";
2
+ import { assertCredentialFreeEvidenceCommand, parseCommandHmacBinding, parseCommandRedactionSummary, parseEvidenceCommandShape, } from "./command-redaction.js";
3
+ import { parseWorkspaceFingerprint } from "./workspace-fingerprint.js";
4
+ const SHA256_HEX = /^[0-9a-f]{64}$/;
5
+ const SAFE_RECEIPT_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
6
+ const CORE_DIGEST_DOMAIN = "omk:evidence:receipt-v3:core\0";
7
+ const COMMAND_DIGEST_DOMAIN = "omk:evidence:receipt-v3:command\0";
8
+ const EXECUTORS = new Set(["bash-tool", "ci-runner", "mcp", "internal"]);
9
+ const ISO_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
10
+ /** Combined stdout/stderr bytes accepted from an already-redacted caller. */
11
+ export const MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES = 64 * 1024;
12
+ export function isSha256Hex(value) {
13
+ return typeof value === "string" && SHA256_HEX.test(value);
14
+ }
15
+ export function parseSha256Hex(value, label = "digest") {
16
+ if (!isSha256Hex(value)) {
17
+ throw new Error(`${label} must be exactly 64 lowercase SHA-256 hexadecimal characters`);
18
+ }
19
+ return value;
20
+ }
21
+ /** Decode validated hex before comparing, avoiding string timing and malformed-buffer pitfalls. */
22
+ export function constantTimeSha256Equal(left, right) {
23
+ if (!isSha256Hex(left) || !isSha256Hex(right))
24
+ return false;
25
+ return timingSafeEqual(Buffer.from(left, "hex"), Buffer.from(right, "hex"));
26
+ }
27
+ export function isSafeEvidenceReceiptId(value) {
28
+ return typeof value === "string" && SAFE_RECEIPT_ID.test(value);
29
+ }
30
+ function exactObject(value, label, requiredKeys, optionalKeys = []) {
31
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
32
+ throw new Error(`${label} must be an object`);
33
+ }
34
+ const record = value;
35
+ const descriptors = Object.getOwnPropertyDescriptors(record);
36
+ const actual = Object.entries(descriptors)
37
+ .filter(([, descriptor]) => descriptor.enumerable)
38
+ .map(([key]) => key)
39
+ .sort();
40
+ const allowed = new Set([...requiredKeys, ...optionalKeys]);
41
+ const isOwnEnumerableDataProperty = (key) => {
42
+ const descriptor = descriptors[key];
43
+ return descriptor !== undefined && descriptor.enumerable === true && "value" in descriptor;
44
+ };
45
+ if (actual.some((key) => !allowed.has(key)) ||
46
+ requiredKeys.some((key) => !isOwnEnumerableDataProperty(key)) ||
47
+ optionalKeys.some((key) => key in record && !isOwnEnumerableDataProperty(key))) {
48
+ throw new Error(`${label} has an invalid key set`);
49
+ }
50
+ const snapshot = {};
51
+ for (const key of actual) {
52
+ const descriptor = descriptors[key];
53
+ if (descriptor === undefined || !("value" in descriptor)) {
54
+ throw new Error(`${label} has an invalid key set`);
55
+ }
56
+ snapshot[key] = descriptor.value;
57
+ }
58
+ return snapshot;
59
+ }
60
+ function nonEmptyString(value, label) {
61
+ if (typeof value !== "string" || value.length === 0 || value.includes("\0")) {
62
+ throw new Error(`${label} must be a non-empty string without NUL bytes`);
63
+ }
64
+ return value;
65
+ }
66
+ function optionalNonEmptyString(value, label) {
67
+ return value === undefined ? undefined : nonEmptyString(value, label);
68
+ }
69
+ function safeNonNegativeInteger(value, label) {
70
+ if (!Number.isSafeInteger(value) || value < 0) {
71
+ throw new Error(`${label} must be a non-negative safe integer`);
72
+ }
73
+ return value;
74
+ }
75
+ function positiveInteger(value, label) {
76
+ if (!Number.isSafeInteger(value) || value <= 0) {
77
+ throw new Error(`${label} must be a positive safe integer`);
78
+ }
79
+ return value;
80
+ }
81
+ function timestamp(value, label) {
82
+ const parsed = nonEmptyString(value, label);
83
+ if (!ISO_TIMESTAMP.test(parsed) || Number.isNaN(Date.parse(parsed))) {
84
+ throw new Error(`${label} must be a canonical ISO-8601 timestamp`);
85
+ }
86
+ return parsed;
87
+ }
88
+ /** Strict structural parse plus the credential-free policy for persisted commands. */
89
+ function parseCommand(value) {
90
+ const command = parseEvidenceCommandShape(value);
91
+ assertCredentialFreeEvidenceCommand(command);
92
+ return command;
93
+ }
94
+ function parseOutputDigest(value, label) {
95
+ const raw = exactObject(value, label, ["sha256", "byteCount"]);
96
+ return Object.freeze({
97
+ sha256: parseSha256Hex(raw.sha256, `${label}.sha256`),
98
+ byteCount: safeNonNegativeInteger(raw.byteCount, `${label}.byteCount`),
99
+ });
100
+ }
101
+ function parseOutput(value) {
102
+ const raw = exactObject(value, "receipt output", ["redactionPolicyId", "stdout", "stderr"]);
103
+ const redactionPolicyId = nonEmptyString(raw.redactionPolicyId, "receipt output redactionPolicyId");
104
+ if (redactionPolicyId.length > 256) {
105
+ throw new Error("receipt output redactionPolicyId is too long");
106
+ }
107
+ const stdout = parseOutputDigest(raw.stdout, "receipt stdout");
108
+ const stderr = parseOutputDigest(raw.stderr, "receipt stderr");
109
+ if (stdout.byteCount + stderr.byteCount > MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES) {
110
+ throw new Error(`receipt output exceeds ${MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES} bytes`);
111
+ }
112
+ return Object.freeze({ redactionPolicyId, stdout, stderr });
113
+ }
114
+ function parseDisposition(status, exitCode) {
115
+ if (status === "passed") {
116
+ if (exitCode !== 0)
117
+ throw new Error("passed receipt status requires exitCode 0");
118
+ return Object.freeze({ status, exitCode: 0 });
119
+ }
120
+ if (status === "failed") {
121
+ if (!Number.isSafeInteger(exitCode) || exitCode === 0) {
122
+ throw new Error("failed receipt status requires a non-zero integer exitCode");
123
+ }
124
+ return Object.freeze({ status, exitCode: exitCode });
125
+ }
126
+ if (status === "timeout" || status === "aborted") {
127
+ if (exitCode !== null)
128
+ throw new Error(`${status} receipt status requires a null exitCode`);
129
+ return Object.freeze({ status, exitCode: null });
130
+ }
131
+ throw new Error("receipt status must be passed, failed, timeout, or aborted");
132
+ }
133
+ /** Strict shape parser for immutable receipt core data. */
134
+ export function parseEvidenceReceiptCore(value) {
135
+ const raw = exactObject(value, "receipt core", [
136
+ "schemaVersion",
137
+ "receiptId",
138
+ "goalId",
139
+ "claim",
140
+ "command",
141
+ "cwd",
142
+ "timeoutMs",
143
+ "startedAt",
144
+ "finishedAt",
145
+ "durationMs",
146
+ "status",
147
+ "exitCode",
148
+ "workspaceBefore",
149
+ "workspaceAfter",
150
+ "output",
151
+ "executor",
152
+ ], ["laneId", "toolCallId", "commandRedaction", "commandBinding"]);
153
+ if (raw.schemaVersion !== 3)
154
+ throw new Error("receipt core schemaVersion must be 3");
155
+ if (!isSafeEvidenceReceiptId(raw.receiptId))
156
+ throw new Error("receiptId is not safe");
157
+ const goalId = nonEmptyString(raw.goalId, "receipt core goalId");
158
+ const laneId = optionalNonEmptyString(raw.laneId, "receipt core laneId");
159
+ const claim = nonEmptyString(raw.claim, "receipt core claim");
160
+ const command = parseCommand(raw.command);
161
+ const cwd = nonEmptyString(raw.cwd, "receipt core cwd");
162
+ const timeoutMs = raw.timeoutMs === null ? null : positiveInteger(raw.timeoutMs, "receipt core timeoutMs");
163
+ const startedAt = timestamp(raw.startedAt, "receipt core startedAt");
164
+ const finishedAt = timestamp(raw.finishedAt, "receipt core finishedAt");
165
+ if (Date.parse(finishedAt) < Date.parse(startedAt)) {
166
+ throw new Error("receipt core finishedAt must not precede startedAt");
167
+ }
168
+ const durationMs = safeNonNegativeInteger(raw.durationMs, "receipt core durationMs");
169
+ if (durationMs !== Date.parse(finishedAt) - Date.parse(startedAt)) {
170
+ throw new Error("receipt core durationMs must match the timestamp interval");
171
+ }
172
+ const workspaceBefore = parseWorkspaceFingerprint(raw.workspaceBefore);
173
+ const workspaceAfter = parseWorkspaceFingerprint(raw.workspaceAfter);
174
+ const output = parseOutput(raw.output);
175
+ if (typeof raw.executor !== "string" || !EXECUTORS.has(raw.executor)) {
176
+ throw new Error("receipt core executor is invalid");
177
+ }
178
+ const executor = raw.executor;
179
+ const toolCallId = optionalNonEmptyString(raw.toolCallId, "receipt core toolCallId");
180
+ const commandRedaction = raw.commandRedaction === undefined ? undefined : parseCommandRedactionSummary(raw.commandRedaction);
181
+ const commandBinding = raw.commandBinding === undefined ? undefined : parseCommandHmacBinding(raw.commandBinding);
182
+ if (commandBinding !== undefined && commandRedaction === undefined) {
183
+ throw new Error("receipt core commandBinding requires commandRedaction");
184
+ }
185
+ if (commandRedaction !== undefined && commandRedaction.placeholders.length > 0 && commandBinding === undefined) {
186
+ throw new Error("receipt core commandRedaction with applied placeholders requires commandBinding");
187
+ }
188
+ const disposition = parseDisposition(raw.status, raw.exitCode);
189
+ const fields = {
190
+ schemaVersion: 3,
191
+ receiptId: raw.receiptId,
192
+ goalId,
193
+ ...(laneId !== undefined ? { laneId } : {}),
194
+ claim,
195
+ command,
196
+ cwd,
197
+ timeoutMs,
198
+ startedAt,
199
+ finishedAt,
200
+ durationMs,
201
+ workspaceBefore,
202
+ workspaceAfter,
203
+ output,
204
+ executor,
205
+ ...(toolCallId !== undefined ? { toolCallId } : {}),
206
+ ...(commandRedaction !== undefined ? { commandRedaction } : {}),
207
+ ...(commandBinding !== undefined ? { commandBinding } : {}),
208
+ };
209
+ return Object.freeze({ ...fields, ...disposition });
210
+ }
211
+ function canonicalJson(value) {
212
+ if (value === null || typeof value === "boolean" || typeof value === "string")
213
+ return JSON.stringify(value);
214
+ if (typeof value === "number") {
215
+ if (!Number.isFinite(value) || Object.is(value, -0))
216
+ throw new Error("canonical JSON requires finite non-negative-zero numbers");
217
+ return JSON.stringify(value);
218
+ }
219
+ if (Array.isArray(value))
220
+ return `[${value.map((item) => canonicalJson(item)).join(",")}]`;
221
+ if (typeof value !== "object" || value === null)
222
+ throw new Error("value is not canonical JSON data");
223
+ const record = value;
224
+ const keys = Object.keys(record).sort();
225
+ return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
226
+ }
227
+ export function serializeEvidenceReceiptCore(core) {
228
+ return canonicalJson(parseEvidenceReceiptCore(core));
229
+ }
230
+ /** Domain-separated SHA-256 of one exact, credential-free structured command descriptor. */
231
+ export function computeEvidenceCommandSha256(command) {
232
+ return createHash("sha256")
233
+ .update(COMMAND_DIGEST_DOMAIN, "utf8")
234
+ .update(canonicalJson(parseCommand(command)), "utf8")
235
+ .digest("hex");
236
+ }
237
+ /** Domain-separated SHA-256 of the immutable canonical core only. */
238
+ export function computeEvidenceReceiptCoreSha256(core) {
239
+ return createHash("sha256")
240
+ .update(CORE_DIGEST_DOMAIN, "utf8")
241
+ .update(serializeEvidenceReceiptCore(core), "utf8")
242
+ .digest("hex");
243
+ }
244
+ function parseLedgerBinding(value) {
245
+ const raw = exactObject(value, "receipt ledger binding", ["seq", "eventHash"]);
246
+ return Object.freeze({
247
+ seq: positiveInteger(raw.seq, "receipt ledger seq"),
248
+ eventHash: parseSha256Hex(raw.eventHash, "receipt ledger eventHash"),
249
+ });
250
+ }
251
+ function parseTrustedAttestation(value) {
252
+ const raw = exactObject(value, "trusted attestation", ["attesterId", "keyId", "algorithm", "signature", "issuedAt"]);
253
+ if (raw.algorithm !== "ed25519")
254
+ throw new Error("trusted attestation algorithm must be ed25519");
255
+ return Object.freeze({
256
+ attesterId: nonEmptyString(raw.attesterId, "trusted attestation attesterId"),
257
+ keyId: nonEmptyString(raw.keyId, "trusted attestation keyId"),
258
+ algorithm: "ed25519",
259
+ signature: nonEmptyString(raw.signature, "trusted attestation signature"),
260
+ issuedAt: timestamp(raw.issuedAt, "trusted attestation issuedAt"),
261
+ });
262
+ }
263
+ function parseEnvelope(value) {
264
+ const raw = exactObject(value, "receipt envelope", ["coreSha256"], ["ledgerBinding", "trustedAttestation"]);
265
+ const coreSha256 = parseSha256Hex(raw.coreSha256, "receipt envelope coreSha256");
266
+ const ledgerBinding = raw.ledgerBinding === undefined ? undefined : parseLedgerBinding(raw.ledgerBinding);
267
+ const trustedAttestation = raw.trustedAttestation === undefined ? undefined : parseTrustedAttestation(raw.trustedAttestation);
268
+ return Object.freeze({
269
+ coreSha256,
270
+ ...(ledgerBinding !== undefined ? { ledgerBinding } : {}),
271
+ ...(trustedAttestation !== undefined ? { trustedAttestation } : {}),
272
+ });
273
+ }
274
+ /** Strict shape and digest validation for an already-decoded receipt value. */
275
+ export function validateEvidenceReceipt(value) {
276
+ const raw = exactObject(value, "evidence receipt", ["core", "envelope"]);
277
+ const core = parseEvidenceReceiptCore(raw.core);
278
+ const envelope = parseEnvelope(raw.envelope);
279
+ const expected = computeEvidenceReceiptCoreSha256(core);
280
+ if (!constantTimeSha256Equal(expected, envelope.coreSha256)) {
281
+ throw new Error("evidence receipt core digest mismatch");
282
+ }
283
+ return Object.freeze({ core, envelope });
284
+ }
285
+ export function parseEvidenceReceipt(serialized) {
286
+ if (typeof serialized !== "string")
287
+ throw new Error("serialized evidence receipt must be a string");
288
+ let value;
289
+ try {
290
+ value = JSON.parse(serialized);
291
+ }
292
+ catch {
293
+ throw new Error("evidence receipt contains invalid JSON");
294
+ }
295
+ return validateEvidenceReceipt(value);
296
+ }
297
+ export function serializeEvidenceReceipt(receipt) {
298
+ return canonicalJson(validateEvidenceReceipt(receipt));
299
+ }
300
+ export function verifyEvidenceReceiptCoreDigest(receipt) {
301
+ try {
302
+ const validated = validateEvidenceReceipt(receipt);
303
+ return constantTimeSha256Equal(computeEvidenceReceiptCoreSha256(validated.core), validated.envelope.coreSha256);
304
+ }
305
+ catch {
306
+ return false;
307
+ }
308
+ }
309
+ function assertByteArray(value, label) {
310
+ if (!(value instanceof Uint8Array))
311
+ throw new Error(`${label} must be a Uint8Array of already-redacted bytes`);
312
+ }
313
+ function outputCapture(output) {
314
+ if (typeof output !== "object" || output === null || Array.isArray(output)) {
315
+ throw new Error("alreadyRedactedOutput must be an object");
316
+ }
317
+ const redactionPolicyId = nonEmptyString(output.redactionPolicyId, "redaction policy id");
318
+ if (redactionPolicyId.length > 256)
319
+ throw new Error("redaction policy id is too long");
320
+ assertByteArray(output.stdout, "already-redacted stdout");
321
+ assertByteArray(output.stderr, "already-redacted stderr");
322
+ const byteCount = output.stdout.byteLength + output.stderr.byteLength;
323
+ if (!Number.isSafeInteger(byteCount) || byteCount > MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES) {
324
+ throw new Error(`receipt output exceeds ${MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES} bytes`);
325
+ }
326
+ return Object.freeze({
327
+ redactionPolicyId,
328
+ stdout: Object.freeze({
329
+ sha256: createHash("sha256").update(output.stdout).digest("hex"),
330
+ byteCount: output.stdout.byteLength,
331
+ }),
332
+ stderr: Object.freeze({
333
+ sha256: createHash("sha256").update(output.stderr).digest("hex"),
334
+ byteCount: output.stderr.byteLength,
335
+ }),
336
+ });
337
+ }
338
+ /** Build a receipt from caller-supplied execution facts without executing a command or activating a gate. */
339
+ export function createEvidenceReceipt(input) {
340
+ const output = outputCapture(input.alreadyRedactedOutput);
341
+ const core = parseEvidenceReceiptCore({
342
+ schemaVersion: 3,
343
+ receiptId: input.receiptId,
344
+ goalId: input.goalId,
345
+ ...(input.laneId !== undefined ? { laneId: input.laneId } : {}),
346
+ claim: input.claim,
347
+ command: input.command,
348
+ cwd: input.cwd,
349
+ timeoutMs: input.timeoutMs,
350
+ startedAt: input.startedAt,
351
+ finishedAt: input.finishedAt,
352
+ durationMs: input.durationMs,
353
+ status: input.status,
354
+ exitCode: input.exitCode,
355
+ workspaceBefore: input.workspaceBefore,
356
+ workspaceAfter: input.workspaceAfter,
357
+ output,
358
+ executor: input.executor,
359
+ ...(input.toolCallId !== undefined ? { toolCallId: input.toolCallId } : {}),
360
+ ...(input.commandRedaction !== undefined ? { commandRedaction: input.commandRedaction } : {}),
361
+ ...(input.commandBinding !== undefined ? { commandBinding: input.commandBinding } : {}),
362
+ });
363
+ const envelope = {
364
+ coreSha256: computeEvidenceReceiptCoreSha256(core),
365
+ ...(input.ledgerBinding !== undefined ? { ledgerBinding: input.ledgerBinding } : {}),
366
+ ...(input.trustedAttestation !== undefined ? { trustedAttestation: input.trustedAttestation } : {}),
367
+ };
368
+ return validateEvidenceReceipt({ core, envelope });
369
+ }
370
+ /** Attach non-core metadata after a ledger commits {receiptId, coreSha256}. */
371
+ export function withEvidenceReceiptEnvelope(receipt, metadata) {
372
+ const validated = validateEvidenceReceipt(receipt);
373
+ return validateEvidenceReceipt({
374
+ core: validated.core,
375
+ envelope: {
376
+ coreSha256: validated.envelope.coreSha256,
377
+ ...(metadata.ledgerBinding !== undefined ? { ledgerBinding: metadata.ledgerBinding } : {}),
378
+ ...(metadata.trustedAttestation !== undefined ? { trustedAttestation: metadata.trustedAttestation } : {}),
379
+ },
380
+ });
381
+ }
382
+ export function evidenceReceiptReplayPayload(receipt) {
383
+ const validated = validateEvidenceReceipt(receipt);
384
+ return Object.freeze({
385
+ receiptId: validated.core.receiptId,
386
+ coreSha256: validated.envelope.coreSha256,
387
+ });
388
+ }
389
+ //# sourceMappingURL=evidence-receipt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence-receipt.js","sourceRoot":"","sources":["../../src/guardrails/evidence-receipt.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, timingSafeEqual } from \"node:crypto\";\nimport type {\n\tCommandHmacBinding,\n\tCommandRedactionSummary,\n\tEvidenceCommandDescriptor,\n\tEvidenceExecutor,\n\tEvidenceOutputCapture,\n\tEvidenceReceipt,\n\tEvidenceReceiptCore,\n\tEvidenceReceiptCoreFields,\n\tEvidenceReceiptDisposition,\n\tEvidenceReceiptEnvelope,\n\tEvidenceReceiptLedgerBinding,\n\tEvidenceReceiptReplayPayload,\n\tSha256Hex,\n\tTrustedEvidenceAttestation,\n\tWorkspaceFingerprint,\n} from \"../types/evidence.ts\";\nimport {\n\tassertCredentialFreeEvidenceCommand,\n\tparseCommandHmacBinding,\n\tparseCommandRedactionSummary,\n\tparseEvidenceCommandShape,\n} from \"./command-redaction.ts\";\nimport { parseWorkspaceFingerprint } from \"./workspace-fingerprint.ts\";\n\nconst SHA256_HEX = /^[0-9a-f]{64}$/;\nconst SAFE_RECEIPT_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;\nconst CORE_DIGEST_DOMAIN = \"omk:evidence:receipt-v3:core\\0\";\nconst COMMAND_DIGEST_DOMAIN = \"omk:evidence:receipt-v3:command\\0\";\nconst EXECUTORS: ReadonlySet<string> = new Set([\"bash-tool\", \"ci-runner\", \"mcp\", \"internal\"]);\nconst ISO_TIMESTAMP = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/;\n\n/** Combined stdout/stderr bytes accepted from an already-redacted caller. */\nexport const MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES = 64 * 1024;\n\nexport interface AlreadyRedactedOutputBytes {\n\treadonly redactionPolicyId: string;\n\treadonly stdout: Uint8Array;\n\treadonly stderr: Uint8Array;\n}\n\nexport interface EvidenceReceiptCoreInputFields {\n\treadonly receiptId: string;\n\treadonly goalId: string;\n\treadonly laneId?: string;\n\treadonly claim: string;\n\treadonly command: EvidenceCommandDescriptor;\n\treadonly cwd: string;\n\treadonly timeoutMs: number | null;\n\treadonly startedAt: string;\n\treadonly finishedAt: string;\n\treadonly durationMs: number;\n\treadonly workspaceBefore: WorkspaceFingerprint;\n\treadonly workspaceAfter: WorkspaceFingerprint;\n\treadonly alreadyRedactedOutput: AlreadyRedactedOutputBytes;\n\treadonly executor: EvidenceExecutor;\n\treadonly toolCallId?: string;\n\treadonly commandRedaction?: CommandRedactionSummary;\n\treadonly commandBinding?: CommandHmacBinding;\n}\n\nexport type CreateEvidenceReceiptInput = EvidenceReceiptCoreInputFields &\n\tEvidenceReceiptDisposition & {\n\t\treadonly ledgerBinding?: EvidenceReceiptLedgerBinding;\n\t\treadonly trustedAttestation?: TrustedEvidenceAttestation;\n\t};\n\nexport interface EvidenceReceiptEnvelopeMetadata {\n\treadonly ledgerBinding?: EvidenceReceiptLedgerBinding;\n\treadonly trustedAttestation?: TrustedEvidenceAttestation;\n}\n\nexport function isSha256Hex(value: unknown): value is Sha256Hex {\n\treturn typeof value === \"string\" && SHA256_HEX.test(value);\n}\n\nexport function parseSha256Hex(value: unknown, label = \"digest\"): Sha256Hex {\n\tif (!isSha256Hex(value)) {\n\t\tthrow new Error(`${label} must be exactly 64 lowercase SHA-256 hexadecimal characters`);\n\t}\n\treturn value;\n}\n\n/** Decode validated hex before comparing, avoiding string timing and malformed-buffer pitfalls. */\nexport function constantTimeSha256Equal(left: unknown, right: unknown): boolean {\n\tif (!isSha256Hex(left) || !isSha256Hex(right)) return false;\n\treturn timingSafeEqual(Buffer.from(left, \"hex\"), Buffer.from(right, \"hex\"));\n}\n\nexport function isSafeEvidenceReceiptId(value: unknown): value is string {\n\treturn typeof value === \"string\" && SAFE_RECEIPT_ID.test(value);\n}\n\nfunction exactObject(\n\tvalue: unknown,\n\tlabel: string,\n\trequiredKeys: readonly string[],\n\toptionalKeys: readonly string[] = [],\n): Record<string, unknown> {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(`${label} must be an object`);\n\t}\n\tconst record = value as Record<string, unknown>;\n\tconst descriptors = Object.getOwnPropertyDescriptors(record);\n\tconst actual = Object.entries(descriptors)\n\t\t.filter(([, descriptor]) => descriptor.enumerable)\n\t\t.map(([key]) => key)\n\t\t.sort();\n\tconst allowed = new Set([...requiredKeys, ...optionalKeys]);\n\tconst isOwnEnumerableDataProperty = (key: string): boolean => {\n\t\tconst descriptor = descriptors[key];\n\t\treturn descriptor !== undefined && descriptor.enumerable === true && \"value\" in descriptor;\n\t};\n\tif (\n\t\tactual.some((key) => !allowed.has(key)) ||\n\t\trequiredKeys.some((key) => !isOwnEnumerableDataProperty(key)) ||\n\t\toptionalKeys.some((key) => key in record && !isOwnEnumerableDataProperty(key))\n\t) {\n\t\tthrow new Error(`${label} has an invalid key set`);\n\t}\n\tconst snapshot: Record<string, unknown> = {};\n\tfor (const key of actual) {\n\t\tconst descriptor = descriptors[key];\n\t\tif (descriptor === undefined || !(\"value\" in descriptor)) {\n\t\t\tthrow new Error(`${label} has an invalid key set`);\n\t\t}\n\t\tsnapshot[key] = descriptor.value;\n\t}\n\treturn snapshot;\n}\n\nfunction nonEmptyString(value: unknown, label: string): string {\n\tif (typeof value !== \"string\" || value.length === 0 || value.includes(\"\\0\")) {\n\t\tthrow new Error(`${label} must be a non-empty string without NUL bytes`);\n\t}\n\treturn value;\n}\n\nfunction optionalNonEmptyString(value: unknown, label: string): string | undefined {\n\treturn value === undefined ? undefined : nonEmptyString(value, label);\n}\n\nfunction safeNonNegativeInteger(value: unknown, label: string): number {\n\tif (!Number.isSafeInteger(value) || (value as number) < 0) {\n\t\tthrow new Error(`${label} must be a non-negative safe integer`);\n\t}\n\treturn value as number;\n}\n\nfunction positiveInteger(value: unknown, label: string): number {\n\tif (!Number.isSafeInteger(value) || (value as number) <= 0) {\n\t\tthrow new Error(`${label} must be a positive safe integer`);\n\t}\n\treturn value as number;\n}\n\nfunction timestamp(value: unknown, label: string): string {\n\tconst parsed = nonEmptyString(value, label);\n\tif (!ISO_TIMESTAMP.test(parsed) || Number.isNaN(Date.parse(parsed))) {\n\t\tthrow new Error(`${label} must be a canonical ISO-8601 timestamp`);\n\t}\n\treturn parsed;\n}\n\n/** Strict structural parse plus the credential-free policy for persisted commands. */\nfunction parseCommand(value: unknown): EvidenceCommandDescriptor {\n\tconst command = parseEvidenceCommandShape(value);\n\tassertCredentialFreeEvidenceCommand(command);\n\treturn command;\n}\n\nfunction parseOutputDigest(value: unknown, label: string): EvidenceOutputCapture[\"stdout\"] {\n\tconst raw = exactObject(value, label, [\"sha256\", \"byteCount\"]);\n\treturn Object.freeze({\n\t\tsha256: parseSha256Hex(raw.sha256, `${label}.sha256`),\n\t\tbyteCount: safeNonNegativeInteger(raw.byteCount, `${label}.byteCount`),\n\t});\n}\n\nfunction parseOutput(value: unknown): EvidenceOutputCapture {\n\tconst raw = exactObject(value, \"receipt output\", [\"redactionPolicyId\", \"stdout\", \"stderr\"]);\n\tconst redactionPolicyId = nonEmptyString(raw.redactionPolicyId, \"receipt output redactionPolicyId\");\n\tif (redactionPolicyId.length > 256) {\n\t\tthrow new Error(\"receipt output redactionPolicyId is too long\");\n\t}\n\tconst stdout = parseOutputDigest(raw.stdout, \"receipt stdout\");\n\tconst stderr = parseOutputDigest(raw.stderr, \"receipt stderr\");\n\tif (stdout.byteCount + stderr.byteCount > MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES) {\n\t\tthrow new Error(`receipt output exceeds ${MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES} bytes`);\n\t}\n\treturn Object.freeze({ redactionPolicyId, stdout, stderr });\n}\n\nfunction parseDisposition(status: unknown, exitCode: unknown): EvidenceReceiptDisposition {\n\tif (status === \"passed\") {\n\t\tif (exitCode !== 0) throw new Error(\"passed receipt status requires exitCode 0\");\n\t\treturn Object.freeze({ status, exitCode: 0 });\n\t}\n\tif (status === \"failed\") {\n\t\tif (!Number.isSafeInteger(exitCode) || exitCode === 0) {\n\t\t\tthrow new Error(\"failed receipt status requires a non-zero integer exitCode\");\n\t\t}\n\t\treturn Object.freeze({ status, exitCode: exitCode as number });\n\t}\n\tif (status === \"timeout\" || status === \"aborted\") {\n\t\tif (exitCode !== null) throw new Error(`${status} receipt status requires a null exitCode`);\n\t\treturn Object.freeze({ status, exitCode: null });\n\t}\n\tthrow new Error(\"receipt status must be passed, failed, timeout, or aborted\");\n}\n\n/** Strict shape parser for immutable receipt core data. */\nexport function parseEvidenceReceiptCore(value: unknown): EvidenceReceiptCore {\n\tconst raw = exactObject(\n\t\tvalue,\n\t\t\"receipt core\",\n\t\t[\n\t\t\t\"schemaVersion\",\n\t\t\t\"receiptId\",\n\t\t\t\"goalId\",\n\t\t\t\"claim\",\n\t\t\t\"command\",\n\t\t\t\"cwd\",\n\t\t\t\"timeoutMs\",\n\t\t\t\"startedAt\",\n\t\t\t\"finishedAt\",\n\t\t\t\"durationMs\",\n\t\t\t\"status\",\n\t\t\t\"exitCode\",\n\t\t\t\"workspaceBefore\",\n\t\t\t\"workspaceAfter\",\n\t\t\t\"output\",\n\t\t\t\"executor\",\n\t\t],\n\t\t[\"laneId\", \"toolCallId\", \"commandRedaction\", \"commandBinding\"],\n\t);\n\tif (raw.schemaVersion !== 3) throw new Error(\"receipt core schemaVersion must be 3\");\n\tif (!isSafeEvidenceReceiptId(raw.receiptId)) throw new Error(\"receiptId is not safe\");\n\tconst goalId = nonEmptyString(raw.goalId, \"receipt core goalId\");\n\tconst laneId = optionalNonEmptyString(raw.laneId, \"receipt core laneId\");\n\tconst claim = nonEmptyString(raw.claim, \"receipt core claim\");\n\tconst command = parseCommand(raw.command);\n\tconst cwd = nonEmptyString(raw.cwd, \"receipt core cwd\");\n\tconst timeoutMs = raw.timeoutMs === null ? null : positiveInteger(raw.timeoutMs, \"receipt core timeoutMs\");\n\tconst startedAt = timestamp(raw.startedAt, \"receipt core startedAt\");\n\tconst finishedAt = timestamp(raw.finishedAt, \"receipt core finishedAt\");\n\tif (Date.parse(finishedAt) < Date.parse(startedAt)) {\n\t\tthrow new Error(\"receipt core finishedAt must not precede startedAt\");\n\t}\n\tconst durationMs = safeNonNegativeInteger(raw.durationMs, \"receipt core durationMs\");\n\tif (durationMs !== Date.parse(finishedAt) - Date.parse(startedAt)) {\n\t\tthrow new Error(\"receipt core durationMs must match the timestamp interval\");\n\t}\n\tconst workspaceBefore = parseWorkspaceFingerprint(raw.workspaceBefore);\n\tconst workspaceAfter = parseWorkspaceFingerprint(raw.workspaceAfter);\n\tconst output = parseOutput(raw.output);\n\tif (typeof raw.executor !== \"string\" || !EXECUTORS.has(raw.executor)) {\n\t\tthrow new Error(\"receipt core executor is invalid\");\n\t}\n\tconst executor = raw.executor as EvidenceExecutor;\n\tconst toolCallId = optionalNonEmptyString(raw.toolCallId, \"receipt core toolCallId\");\n\tconst commandRedaction =\n\t\traw.commandRedaction === undefined ? undefined : parseCommandRedactionSummary(raw.commandRedaction);\n\tconst commandBinding = raw.commandBinding === undefined ? undefined : parseCommandHmacBinding(raw.commandBinding);\n\tif (commandBinding !== undefined && commandRedaction === undefined) {\n\t\tthrow new Error(\"receipt core commandBinding requires commandRedaction\");\n\t}\n\tif (commandRedaction !== undefined && commandRedaction.placeholders.length > 0 && commandBinding === undefined) {\n\t\tthrow new Error(\"receipt core commandRedaction with applied placeholders requires commandBinding\");\n\t}\n\tconst disposition = parseDisposition(raw.status, raw.exitCode);\n\tconst fields: EvidenceReceiptCoreFields = {\n\t\tschemaVersion: 3,\n\t\treceiptId: raw.receiptId,\n\t\tgoalId,\n\t\t...(laneId !== undefined ? { laneId } : {}),\n\t\tclaim,\n\t\tcommand,\n\t\tcwd,\n\t\ttimeoutMs,\n\t\tstartedAt,\n\t\tfinishedAt,\n\t\tdurationMs,\n\t\tworkspaceBefore,\n\t\tworkspaceAfter,\n\t\toutput,\n\t\texecutor,\n\t\t...(toolCallId !== undefined ? { toolCallId } : {}),\n\t\t...(commandRedaction !== undefined ? { commandRedaction } : {}),\n\t\t...(commandBinding !== undefined ? { commandBinding } : {}),\n\t};\n\treturn Object.freeze({ ...fields, ...disposition });\n}\n\nfunction canonicalJson(value: unknown): string {\n\tif (value === null || typeof value === \"boolean\" || typeof value === \"string\") return JSON.stringify(value);\n\tif (typeof value === \"number\") {\n\t\tif (!Number.isFinite(value) || Object.is(value, -0))\n\t\t\tthrow new Error(\"canonical JSON requires finite non-negative-zero numbers\");\n\t\treturn JSON.stringify(value);\n\t}\n\tif (Array.isArray(value)) return `[${value.map((item) => canonicalJson(item)).join(\",\")}]`;\n\tif (typeof value !== \"object\" || value === null) throw new Error(\"value is not canonical JSON data\");\n\tconst record = value as Record<string, unknown>;\n\tconst keys = Object.keys(record).sort();\n\treturn `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(\",\")}}`;\n}\n\nexport function serializeEvidenceReceiptCore(core: EvidenceReceiptCore): string {\n\treturn canonicalJson(parseEvidenceReceiptCore(core));\n}\n\n/** Domain-separated SHA-256 of one exact, credential-free structured command descriptor. */\nexport function computeEvidenceCommandSha256(command: EvidenceCommandDescriptor): Sha256Hex {\n\treturn createHash(\"sha256\")\n\t\t.update(COMMAND_DIGEST_DOMAIN, \"utf8\")\n\t\t.update(canonicalJson(parseCommand(command)), \"utf8\")\n\t\t.digest(\"hex\") as Sha256Hex;\n}\n\n/** Domain-separated SHA-256 of the immutable canonical core only. */\nexport function computeEvidenceReceiptCoreSha256(core: EvidenceReceiptCore): Sha256Hex {\n\treturn createHash(\"sha256\")\n\t\t.update(CORE_DIGEST_DOMAIN, \"utf8\")\n\t\t.update(serializeEvidenceReceiptCore(core), \"utf8\")\n\t\t.digest(\"hex\") as Sha256Hex;\n}\n\nfunction parseLedgerBinding(value: unknown): EvidenceReceiptLedgerBinding {\n\tconst raw = exactObject(value, \"receipt ledger binding\", [\"seq\", \"eventHash\"]);\n\treturn Object.freeze({\n\t\tseq: positiveInteger(raw.seq, \"receipt ledger seq\"),\n\t\teventHash: parseSha256Hex(raw.eventHash, \"receipt ledger eventHash\"),\n\t});\n}\n\nfunction parseTrustedAttestation(value: unknown): TrustedEvidenceAttestation {\n\tconst raw = exactObject(value, \"trusted attestation\", [\"attesterId\", \"keyId\", \"algorithm\", \"signature\", \"issuedAt\"]);\n\tif (raw.algorithm !== \"ed25519\") throw new Error(\"trusted attestation algorithm must be ed25519\");\n\treturn Object.freeze({\n\t\tattesterId: nonEmptyString(raw.attesterId, \"trusted attestation attesterId\"),\n\t\tkeyId: nonEmptyString(raw.keyId, \"trusted attestation keyId\"),\n\t\talgorithm: \"ed25519\",\n\t\tsignature: nonEmptyString(raw.signature, \"trusted attestation signature\"),\n\t\tissuedAt: timestamp(raw.issuedAt, \"trusted attestation issuedAt\"),\n\t});\n}\n\nfunction parseEnvelope(value: unknown): EvidenceReceiptEnvelope {\n\tconst raw = exactObject(value, \"receipt envelope\", [\"coreSha256\"], [\"ledgerBinding\", \"trustedAttestation\"]);\n\tconst coreSha256 = parseSha256Hex(raw.coreSha256, \"receipt envelope coreSha256\");\n\tconst ledgerBinding = raw.ledgerBinding === undefined ? undefined : parseLedgerBinding(raw.ledgerBinding);\n\tconst trustedAttestation =\n\t\traw.trustedAttestation === undefined ? undefined : parseTrustedAttestation(raw.trustedAttestation);\n\treturn Object.freeze({\n\t\tcoreSha256,\n\t\t...(ledgerBinding !== undefined ? { ledgerBinding } : {}),\n\t\t...(trustedAttestation !== undefined ? { trustedAttestation } : {}),\n\t});\n}\n\n/** Strict shape and digest validation for an already-decoded receipt value. */\nexport function validateEvidenceReceipt(value: unknown): EvidenceReceipt {\n\tconst raw = exactObject(value, \"evidence receipt\", [\"core\", \"envelope\"]);\n\tconst core = parseEvidenceReceiptCore(raw.core);\n\tconst envelope = parseEnvelope(raw.envelope);\n\tconst expected = computeEvidenceReceiptCoreSha256(core);\n\tif (!constantTimeSha256Equal(expected, envelope.coreSha256)) {\n\t\tthrow new Error(\"evidence receipt core digest mismatch\");\n\t}\n\treturn Object.freeze({ core, envelope });\n}\n\nexport function parseEvidenceReceipt(serialized: string): EvidenceReceipt {\n\tif (typeof serialized !== \"string\") throw new Error(\"serialized evidence receipt must be a string\");\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(serialized);\n\t} catch {\n\t\tthrow new Error(\"evidence receipt contains invalid JSON\");\n\t}\n\treturn validateEvidenceReceipt(value);\n}\n\nexport function serializeEvidenceReceipt(receipt: EvidenceReceipt): string {\n\treturn canonicalJson(validateEvidenceReceipt(receipt));\n}\n\nexport function verifyEvidenceReceiptCoreDigest(receipt: EvidenceReceipt): boolean {\n\ttry {\n\t\tconst validated = validateEvidenceReceipt(receipt);\n\t\treturn constantTimeSha256Equal(computeEvidenceReceiptCoreSha256(validated.core), validated.envelope.coreSha256);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction assertByteArray(value: unknown, label: string): asserts value is Uint8Array {\n\tif (!(value instanceof Uint8Array)) throw new Error(`${label} must be a Uint8Array of already-redacted bytes`);\n}\n\nfunction outputCapture(output: AlreadyRedactedOutputBytes): EvidenceOutputCapture {\n\tif (typeof output !== \"object\" || output === null || Array.isArray(output)) {\n\t\tthrow new Error(\"alreadyRedactedOutput must be an object\");\n\t}\n\tconst redactionPolicyId = nonEmptyString(output.redactionPolicyId, \"redaction policy id\");\n\tif (redactionPolicyId.length > 256) throw new Error(\"redaction policy id is too long\");\n\tassertByteArray(output.stdout, \"already-redacted stdout\");\n\tassertByteArray(output.stderr, \"already-redacted stderr\");\n\tconst byteCount = output.stdout.byteLength + output.stderr.byteLength;\n\tif (!Number.isSafeInteger(byteCount) || byteCount > MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES) {\n\t\tthrow new Error(`receipt output exceeds ${MAX_EVIDENCE_RECEIPT_OUTPUT_BYTES} bytes`);\n\t}\n\treturn Object.freeze({\n\t\tredactionPolicyId,\n\t\tstdout: Object.freeze({\n\t\t\tsha256: createHash(\"sha256\").update(output.stdout).digest(\"hex\") as Sha256Hex,\n\t\t\tbyteCount: output.stdout.byteLength,\n\t\t}),\n\t\tstderr: Object.freeze({\n\t\t\tsha256: createHash(\"sha256\").update(output.stderr).digest(\"hex\") as Sha256Hex,\n\t\t\tbyteCount: output.stderr.byteLength,\n\t\t}),\n\t});\n}\n\n/** Build a receipt from caller-supplied execution facts without executing a command or activating a gate. */\nexport function createEvidenceReceipt(input: CreateEvidenceReceiptInput): EvidenceReceipt {\n\tconst output = outputCapture(input.alreadyRedactedOutput);\n\tconst core = parseEvidenceReceiptCore({\n\t\tschemaVersion: 3,\n\t\treceiptId: input.receiptId,\n\t\tgoalId: input.goalId,\n\t\t...(input.laneId !== undefined ? { laneId: input.laneId } : {}),\n\t\tclaim: input.claim,\n\t\tcommand: input.command,\n\t\tcwd: input.cwd,\n\t\ttimeoutMs: input.timeoutMs,\n\t\tstartedAt: input.startedAt,\n\t\tfinishedAt: input.finishedAt,\n\t\tdurationMs: input.durationMs,\n\t\tstatus: input.status,\n\t\texitCode: input.exitCode,\n\t\tworkspaceBefore: input.workspaceBefore,\n\t\tworkspaceAfter: input.workspaceAfter,\n\t\toutput,\n\t\texecutor: input.executor,\n\t\t...(input.toolCallId !== undefined ? { toolCallId: input.toolCallId } : {}),\n\t\t...(input.commandRedaction !== undefined ? { commandRedaction: input.commandRedaction } : {}),\n\t\t...(input.commandBinding !== undefined ? { commandBinding: input.commandBinding } : {}),\n\t});\n\tconst envelope: EvidenceReceiptEnvelope = {\n\t\tcoreSha256: computeEvidenceReceiptCoreSha256(core),\n\t\t...(input.ledgerBinding !== undefined ? { ledgerBinding: input.ledgerBinding } : {}),\n\t\t...(input.trustedAttestation !== undefined ? { trustedAttestation: input.trustedAttestation } : {}),\n\t};\n\treturn validateEvidenceReceipt({ core, envelope });\n}\n\n/** Attach non-core metadata after a ledger commits {receiptId, coreSha256}. */\nexport function withEvidenceReceiptEnvelope(\n\treceipt: EvidenceReceipt,\n\tmetadata: EvidenceReceiptEnvelopeMetadata,\n): EvidenceReceipt {\n\tconst validated = validateEvidenceReceipt(receipt);\n\treturn validateEvidenceReceipt({\n\t\tcore: validated.core,\n\t\tenvelope: {\n\t\t\tcoreSha256: validated.envelope.coreSha256,\n\t\t\t...(metadata.ledgerBinding !== undefined ? { ledgerBinding: metadata.ledgerBinding } : {}),\n\t\t\t...(metadata.trustedAttestation !== undefined ? { trustedAttestation: metadata.trustedAttestation } : {}),\n\t\t},\n\t});\n}\n\nexport function evidenceReceiptReplayPayload(receipt: EvidenceReceipt): EvidenceReceiptReplayPayload {\n\tconst validated = validateEvidenceReceipt(receipt);\n\treturn Object.freeze({\n\t\treceiptId: validated.core.receiptId,\n\t\tcoreSha256: validated.envelope.coreSha256,\n\t});\n}\n"]}
@@ -1,4 +1,6 @@
1
- import type { EvidenceItem, EvidenceStatus, MergeGateResult, ReplayEvent, ReplayLedger, TaskContract } from "../types/evidence.ts";
1
+ import type { EvidenceCommandDescriptor, EvidenceItem, EvidenceReceiptMode, EvidenceStatus, MergeGateResult, ReplayEvent, ReplayLedger, ReplayLedgerHead, TaskContract, VerifiedReplayLedgerSnapshot, WorkspaceScope } from "../types/evidence.ts";
2
+ import { type CommandHmacBinder } from "./evidence-attestation.ts";
3
+ export { latestRelevantWorkspaceMutationSeq } from "./evidence-attestation.ts";
2
4
  export declare class TaskContractBuilder {
3
5
  private goalId;
4
6
  private completionClaim;
@@ -20,18 +22,19 @@ export declare class TaskContractBuilder {
20
22
  static toJSON(contract: TaskContract): string;
21
23
  }
22
24
  export declare class ReplayLedgerManager {
23
- private ledger;
24
- private nextSeq;
25
- constructor(goalId: string, ledgerPath: string);
26
- append(event: Omit<ReplayEvent, "seq" | "timestamp" | "payloadHash" | "prevHash" | "eventHash">): ReplayEvent;
27
- persist(): void;
28
- /**
29
- * Load and verify the persisted ledger. Fails closed: any schema violation,
30
- * sequence gap, payload-hash mismatch, or broken event-hash chain throws, so
31
- * a tampered ledger (edited, deleted, inserted, or reordered lines) is never
32
- * loaded silently.
33
- */
34
- load(): void;
25
+ private readonly goalId;
26
+ private readonly ledgerPath;
27
+ private readonly store;
28
+ private events;
29
+ private committedHead;
30
+ constructor(goalId: string, ledgerPath: string, expectedHead?: ReplayLedgerHead);
31
+ private refresh;
32
+ append(event: Omit<ReplayEvent, "seq" | "timestamp" | "payloadHash" | "prevHash" | "eventHash">, expectedHead?: ReplayLedgerHead): ReplayEvent;
33
+ /** Compatibility no-op that still verifies the caller's expected committed head. */
34
+ persist(expectedHead?: ReplayLedgerHead): void;
35
+ load(expectedHead?: ReplayLedgerHead): void;
36
+ getCommittedHead(): ReplayLedgerHead;
37
+ getVerifiedSnapshot(expectedHead?: ReplayLedgerHead): VerifiedReplayLedgerSnapshot;
35
38
  getEvents(): ReadonlyArray<ReplayEvent>;
36
39
  getLedger(): Readonly<ReplayLedger>;
37
40
  replay<T>(handler: (event: ReplayEvent) => T | undefined): T[];
@@ -40,10 +43,31 @@ export declare class ReplayLedgerManager {
40
43
  export interface EvidenceGateOptions {
41
44
  /** Minimum number of satisfied evidence items required. */
42
45
  minEvidenceCount?: number;
43
- /** Require at least one artifact with a SHA-256 hash. */
46
+ /** Require at least one artifact with a SHA-256 hash in explicit legacy mode. */
44
47
  requireHash?: boolean;
45
- /** Require at least one verification command. */
48
+ /** Require at least one verification command in explicit legacy mode. */
46
49
  requireVerificationCommand?: boolean;
50
+ /** Receipt policy. Defaults to prefer; legacy must be selected explicitly. */
51
+ receiptMode?: EvidenceReceiptMode;
52
+ /** Resolve a serialized or decoded receipt by ID. The gate validates the returned value. */
53
+ resolveReceipt?: (receiptId: string) => unknown;
54
+ /** Strict source: one expected-head, file-identity, suffix, and chain-verified snapshot. */
55
+ resolveVerifiedLedgerSnapshot?: () => VerifiedReplayLedgerSnapshot;
56
+ /** Prefer-mode migration source; strict mode requires resolveVerifiedLedgerSnapshot. */
57
+ resolveLedgerEvent?: (seq: number) => ReplayEvent | undefined;
58
+ /** Recapture the receipt's workspace scope (same kind and scope) for freshness comparison. */
59
+ captureWorkspaceFingerprint?: (scope: WorkspaceScope) => unknown;
60
+ /**
61
+ * Optional freshness source: the latest replay-ledger sequence of a workspace mutation
62
+ * relevant to the given scope, or null/undefined when none is known. When configured,
63
+ * the receipt's verified ledger seq must strictly exceed this value; a throwing or
64
+ * out-of-contract source is a hard block (positive safe integers only).
65
+ */
66
+ resolveLatestWorkspaceMutationSeq?: (scope: WorkspaceScope) => number | null | undefined;
67
+ /** Ephemeral trust anchor used to verify the original command's keyed attestation. */
68
+ commandAttestationBinder?: Pick<CommandHmacBinder, "verify">;
69
+ /** Resolve the original command inside the same trust boundary as the binder. */
70
+ resolveAttestedCommand?: (receiptId: string) => EvidenceCommandDescriptor | undefined;
47
71
  }
48
72
  export declare class EvidenceGate {
49
73
  private options;