codexgpt 1.0.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 (654) hide show
  1. package/AGENTS.example.md +20 -0
  2. package/CHANGELOG.md +342 -0
  3. package/CHATGPT_PROMPT.md +12 -0
  4. package/CLOUDFLARED_VERIFIED_INSTALL.md +94 -0
  5. package/CODEX_PROMPT.md +12 -0
  6. package/CONTRIBUTING.md +62 -0
  7. package/DOMAIN_SETUP.md +275 -0
  8. package/FAQ.md +366 -0
  9. package/FAQ_ZH.md +329 -0
  10. package/LICENSE +21 -0
  11. package/PUBLIC_LAUNCH_CHECKLIST.md +111 -0
  12. package/README.md +490 -0
  13. package/README_ZH.md +747 -0
  14. package/SECURITY.md +295 -0
  15. package/config.example.env +103 -0
  16. package/dist/access/fullAccessLease.js +148 -0
  17. package/dist/access/fullAccessLease.js.map +1 -0
  18. package/dist/access/protectedRoots.js +122 -0
  19. package/dist/access/protectedRoots.js.map +1 -0
  20. package/dist/access/rootAdmission.js +347 -0
  21. package/dist/access/rootAdmission.js.map +1 -0
  22. package/dist/analysis/cache.js +27 -0
  23. package/dist/analysis/cache.js.map +1 -0
  24. package/dist/analysis/classify.js +102 -0
  25. package/dist/analysis/classify.js.map +1 -0
  26. package/dist/analysis/extract.js +139 -0
  27. package/dist/analysis/extract.js.map +1 -0
  28. package/dist/analysis/graph.js +22 -0
  29. package/dist/analysis/graph.js.map +1 -0
  30. package/dist/analysis/impact.js +167 -0
  31. package/dist/analysis/impact.js.map +1 -0
  32. package/dist/analysis/index.js +215 -0
  33. package/dist/analysis/index.js.map +1 -0
  34. package/dist/analysis/inventory.js +51 -0
  35. package/dist/analysis/inventory.js.map +1 -0
  36. package/dist/analysis/providers.js +24 -0
  37. package/dist/analysis/providers.js.map +1 -0
  38. package/dist/analysis/rank.js +27 -0
  39. package/dist/analysis/rank.js.map +1 -0
  40. package/dist/analysis/types.js +8 -0
  41. package/dist/analysis/types.js.map +1 -0
  42. package/dist/audit/canonicalJson.js +79 -0
  43. package/dist/audit/canonicalJson.js.map +1 -0
  44. package/dist/audit/diagnostics.js +128 -0
  45. package/dist/audit/diagnostics.js.map +1 -0
  46. package/dist/audit/index.js +12 -0
  47. package/dist/audit/index.js.map +1 -0
  48. package/dist/audit/lifecycleV3.js +53 -0
  49. package/dist/audit/lifecycleV3.js.map +1 -0
  50. package/dist/audit/lifecycleV4.js +70 -0
  51. package/dist/audit/lifecycleV4.js.map +1 -0
  52. package/dist/audit/lock.js +195 -0
  53. package/dist/audit/lock.js.map +1 -0
  54. package/dist/audit/queryTool.js +120 -0
  55. package/dist/audit/queryTool.js.map +1 -0
  56. package/dist/audit/runtime.js +48 -0
  57. package/dist/audit/runtime.js.map +1 -0
  58. package/dist/audit/schemas.js +640 -0
  59. package/dist/audit/schemas.js.map +1 -0
  60. package/dist/audit/store.js +1309 -0
  61. package/dist/audit/store.js.map +1 -0
  62. package/dist/audit/transactionParticipant.js +45 -0
  63. package/dist/audit/transactionParticipant.js.map +1 -0
  64. package/dist/audit/types.js +11 -0
  65. package/dist/audit/types.js.map +1 -0
  66. package/dist/auth/audit.js +44 -0
  67. package/dist/auth/audit.js.map +1 -0
  68. package/dist/auth/authorizationStore.js +333 -0
  69. package/dist/auth/authorizationStore.js.map +1 -0
  70. package/dist/auth/challenges.js +25 -0
  71. package/dist/auth/challenges.js.map +1 -0
  72. package/dist/auth/clientStore.js +469 -0
  73. package/dist/auth/clientStore.js.map +1 -0
  74. package/dist/auth/cloudflareConfig.js +112 -0
  75. package/dist/auth/cloudflareConfig.js.map +1 -0
  76. package/dist/auth/configuration.js +167 -0
  77. package/dist/auth/configuration.js.map +1 -0
  78. package/dist/auth/credentialStore.js +65 -0
  79. package/dist/auth/credentialStore.js.map +1 -0
  80. package/dist/auth/deploymentLock.js +220 -0
  81. package/dist/auth/deploymentLock.js.map +1 -0
  82. package/dist/auth/deploymentRegistry.js +149 -0
  83. package/dist/auth/deploymentRegistry.js.map +1 -0
  84. package/dist/auth/errors.js +26 -0
  85. package/dist/auth/errors.js.map +1 -0
  86. package/dist/auth/grantStore.js +307 -0
  87. package/dist/auth/grantStore.js.map +1 -0
  88. package/dist/auth/index.js +39 -0
  89. package/dist/auth/index.js.map +1 -0
  90. package/dist/auth/keyManager.js +148 -0
  91. package/dist/auth/keyManager.js.map +1 -0
  92. package/dist/auth/localAdminSession.js +173 -0
  93. package/dist/auth/localAdminSession.js.map +1 -0
  94. package/dist/auth/metadata.js +69 -0
  95. package/dist/auth/metadata.js.map +1 -0
  96. package/dist/auth/oauthProvider.js +589 -0
  97. package/dist/auth/oauthProvider.js.map +1 -0
  98. package/dist/auth/ownerApproval.js +51 -0
  99. package/dist/auth/ownerApproval.js.map +1 -0
  100. package/dist/auth/policyIdentity.js +189 -0
  101. package/dist/auth/policyIdentity.js.map +1 -0
  102. package/dist/auth/rateLimits.js +66 -0
  103. package/dist/auth/rateLimits.js.map +1 -0
  104. package/dist/auth/recovery.js +275 -0
  105. package/dist/auth/recovery.js.map +1 -0
  106. package/dist/auth/requestContext.js +34 -0
  107. package/dist/auth/requestContext.js.map +1 -0
  108. package/dist/auth/resourceMiddleware.js +147 -0
  109. package/dist/auth/resourceMiddleware.js.map +1 -0
  110. package/dist/auth/runtimeStatus.js +51 -0
  111. package/dist/auth/runtimeStatus.js.map +1 -0
  112. package/dist/auth/schemas.js +84 -0
  113. package/dist/auth/schemas.js.map +1 -0
  114. package/dist/auth/stateStore.js +468 -0
  115. package/dist/auth/stateStore.js.map +1 -0
  116. package/dist/auth/tokenService.js +631 -0
  117. package/dist/auth/tokenService.js.map +1 -0
  118. package/dist/auth/toolSecurity.js +108 -0
  119. package/dist/auth/toolSecurity.js.map +1 -0
  120. package/dist/auth/types.js +6 -0
  121. package/dist/auth/types.js.map +1 -0
  122. package/dist/auth/windowsDpapi.js +193 -0
  123. package/dist/auth/windowsDpapi.js.map +1 -0
  124. package/dist/bashOps.js +292 -0
  125. package/dist/bashOps.js.map +1 -0
  126. package/dist/capabilitiesOps.js +412 -0
  127. package/dist/capabilitiesOps.js.map +1 -0
  128. package/dist/changesets/crypto.js +92 -0
  129. package/dist/changesets/crypto.js.map +1 -0
  130. package/dist/changesets/index.js +9 -0
  131. package/dist/changesets/index.js.map +1 -0
  132. package/dist/changesets/moveStore.js +237 -0
  133. package/dist/changesets/moveStore.js.map +1 -0
  134. package/dist/changesets/moveUndo.js +386 -0
  135. package/dist/changesets/moveUndo.js.map +1 -0
  136. package/dist/changesets/schemas.js +234 -0
  137. package/dist/changesets/schemas.js.map +1 -0
  138. package/dist/changesets/store.js +573 -0
  139. package/dist/changesets/store.js.map +1 -0
  140. package/dist/changesets/types.js +9 -0
  141. package/dist/changesets/types.js.map +1 -0
  142. package/dist/changesets/undo.js +525 -0
  143. package/dist/changesets/undo.js.map +1 -0
  144. package/dist/changesets/unifiedUndo.js +31 -0
  145. package/dist/changesets/unifiedUndo.js.map +1 -0
  146. package/dist/cliEnvironment.js +85 -0
  147. package/dist/cliEnvironment.js.map +1 -0
  148. package/dist/codexSessions.js +733 -0
  149. package/dist/codexSessions.js.map +1 -0
  150. package/dist/codexgptSupertool.js +216 -0
  151. package/dist/codexgptSupertool.js.map +1 -0
  152. package/dist/codexproSupertool.js +204 -0
  153. package/dist/codexproSupertool.js.map +1 -0
  154. package/dist/config.js +733 -0
  155. package/dist/config.js.map +1 -0
  156. package/dist/control/localApprovalClient.js +287 -0
  157. package/dist/control/localApprovalClient.js.map +1 -0
  158. package/dist/control/localApprovalServer.js +466 -0
  159. package/dist/control/localApprovalServer.js.map +1 -0
  160. package/dist/control/runtime.js +178 -0
  161. package/dist/control/runtime.js.map +1 -0
  162. package/dist/control/schemas.js +184 -0
  163. package/dist/control/schemas.js.map +1 -0
  164. package/dist/control/windowsLocalControl.js +348 -0
  165. package/dist/control/windowsLocalControl.js.map +1 -0
  166. package/dist/fsOps.js +541 -0
  167. package/dist/fsOps.js.map +1 -0
  168. package/dist/git/admission.js +26 -0
  169. package/dist/git/admission.js.map +1 -0
  170. package/dist/git/branchService.js +51 -0
  171. package/dist/git/branchService.js.map +1 -0
  172. package/dist/git/capabilities.js +143 -0
  173. package/dist/git/capabilities.js.map +1 -0
  174. package/dist/git/commitService.js +344 -0
  175. package/dist/git/commitService.js.map +1 -0
  176. package/dist/git/durableState.js +151 -0
  177. package/dist/git/durableState.js.map +1 -0
  178. package/dist/git/execution.js +451 -0
  179. package/dist/git/execution.js.map +1 -0
  180. package/dist/git/fileTransaction.js +50 -0
  181. package/dist/git/fileTransaction.js.map +1 -0
  182. package/dist/git/indexService.js +421 -0
  183. package/dist/git/indexService.js.map +1 -0
  184. package/dist/git/integrations.js +653 -0
  185. package/dist/git/integrations.js.map +1 -0
  186. package/dist/git/locks.js +287 -0
  187. package/dist/git/locks.js.map +1 -0
  188. package/dist/git/mutationContext.js +92 -0
  189. package/dist/git/mutationContext.js.map +1 -0
  190. package/dist/git/mutationJournal.js +91 -0
  191. package/dist/git/mutationJournal.js.map +1 -0
  192. package/dist/git/mutationService.js +352 -0
  193. package/dist/git/mutationService.js.map +1 -0
  194. package/dist/git/normalization.js +57 -0
  195. package/dist/git/normalization.js.map +1 -0
  196. package/dist/git/objectQuarantine.js +243 -0
  197. package/dist/git/objectQuarantine.js.map +1 -0
  198. package/dist/git/opaqueRecordStore.js +187 -0
  199. package/dist/git/opaqueRecordStore.js.map +1 -0
  200. package/dist/git/operationStore.js +287 -0
  201. package/dist/git/operationStore.js.map +1 -0
  202. package/dist/git/parsers.js +311 -0
  203. package/dist/git/parsers.js.map +1 -0
  204. package/dist/git/privateIndex.js +79 -0
  205. package/dist/git/privateIndex.js.map +1 -0
  206. package/dist/git/productionBootstrap.js +39 -0
  207. package/dist/git/productionBootstrap.js.map +1 -0
  208. package/dist/git/readService.js +846 -0
  209. package/dist/git/readService.js.map +1 -0
  210. package/dist/git/recovery.js +417 -0
  211. package/dist/git/recovery.js.map +1 -0
  212. package/dist/git/repositoryIdentity.js +611 -0
  213. package/dist/git/repositoryIdentity.js.map +1 -0
  214. package/dist/git/repositoryStore.js +237 -0
  215. package/dist/git/repositoryStore.js.map +1 -0
  216. package/dist/git/resources.js +113 -0
  217. package/dist/git/resources.js.map +1 -0
  218. package/dist/git/restoreService.js +178 -0
  219. package/dist/git/restoreService.js.map +1 -0
  220. package/dist/git/reviewToken.js +86 -0
  221. package/dist/git/reviewToken.js.map +1 -0
  222. package/dist/git/stashService.js +566 -0
  223. package/dist/git/stashService.js.map +1 -0
  224. package/dist/git/stateToken.js +139 -0
  225. package/dist/git/stateToken.js.map +1 -0
  226. package/dist/gitOps.js +147 -0
  227. package/dist/gitOps.js.map +1 -0
  228. package/dist/guard.js +608 -0
  229. package/dist/guard.js.map +1 -0
  230. package/dist/guidance/diagnostics.js +14 -0
  231. package/dist/guidance/diagnostics.js.map +1 -0
  232. package/dist/guidance/instructions.js +167 -0
  233. package/dist/guidance/instructions.js.map +1 -0
  234. package/dist/guidance/mode.js +18 -0
  235. package/dist/guidance/mode.js.map +1 -0
  236. package/dist/guidance/openaiSkillMetadata.js +29 -0
  237. package/dist/guidance/openaiSkillMetadata.js.map +1 -0
  238. package/dist/guidance/safeTextReader.js +171 -0
  239. package/dist/guidance/safeTextReader.js.map +1 -0
  240. package/dist/guidance/skillCatalog.js +70 -0
  241. package/dist/guidance/skillCatalog.js.map +1 -0
  242. package/dist/guidance/skillDiscovery.js +353 -0
  243. package/dist/guidance/skillDiscovery.js.map +1 -0
  244. package/dist/guidance/skillMetadata.js +115 -0
  245. package/dist/guidance/skillMetadata.js.map +1 -0
  246. package/dist/guidance/skillResources.js +146 -0
  247. package/dist/guidance/skillResources.js.map +1 -0
  248. package/dist/handoffOps.js +449 -0
  249. package/dist/handoffOps.js.map +1 -0
  250. package/dist/http/localAdminApp.js +203 -0
  251. package/dist/http/localAdminApp.js.map +1 -0
  252. package/dist/http/oauthMcpRuntime.js +294 -0
  253. package/dist/http/oauthMcpRuntime.js.map +1 -0
  254. package/dist/http/publicApp.js +350 -0
  255. package/dist/http/publicApp.js.map +1 -0
  256. package/dist/http/securityHeaders.js +11 -0
  257. package/dist/http/securityHeaders.js.map +1 -0
  258. package/dist/http.js +2076 -0
  259. package/dist/http.js.map +1 -0
  260. package/dist/moves/engine.js +1079 -0
  261. package/dist/moves/engine.js.map +1 -0
  262. package/dist/moves/index.js +6 -0
  263. package/dist/moves/index.js.map +1 -0
  264. package/dist/moves/planner.js +270 -0
  265. package/dist/moves/planner.js.map +1 -0
  266. package/dist/moves/recovery.js +557 -0
  267. package/dist/moves/recovery.js.map +1 -0
  268. package/dist/moves/service.js +300 -0
  269. package/dist/moves/service.js.map +1 -0
  270. package/dist/moves/types.js +11 -0
  271. package/dist/moves/types.js.map +1 -0
  272. package/dist/mutations/index.js +4 -0
  273. package/dist/mutations/index.js.map +1 -0
  274. package/dist/mutations/lifecycle.js +165 -0
  275. package/dist/mutations/lifecycle.js.map +1 -0
  276. package/dist/mutations/localService.js +163 -0
  277. package/dist/mutations/localService.js.map +1 -0
  278. package/dist/mutations/runtime.js +322 -0
  279. package/dist/mutations/runtime.js.map +1 -0
  280. package/dist/mutations/types.js +2 -0
  281. package/dist/mutations/types.js.map +1 -0
  282. package/dist/mutations/writers.js +360 -0
  283. package/dist/mutations/writers.js.map +1 -0
  284. package/dist/patchOps.js +420 -0
  285. package/dist/patchOps.js.map +1 -0
  286. package/dist/policy/approval.js +306 -0
  287. package/dist/policy/approval.js.map +1 -0
  288. package/dist/policy/audit.js +88 -0
  289. package/dist/policy/audit.js.map +1 -0
  290. package/dist/policy/authorizationFacts.js +187 -0
  291. package/dist/policy/authorizationFacts.js.map +1 -0
  292. package/dist/policy/compat.js +104 -0
  293. package/dist/policy/compat.js.map +1 -0
  294. package/dist/policy/context.js +31 -0
  295. package/dist/policy/context.js.map +1 -0
  296. package/dist/policy/enforcement.js +46 -0
  297. package/dist/policy/enforcement.js.map +1 -0
  298. package/dist/policy/evaluator.js +338 -0
  299. package/dist/policy/evaluator.js.map +1 -0
  300. package/dist/policy/executionCapabilities.js +80 -0
  301. package/dist/policy/executionCapabilities.js.map +1 -0
  302. package/dist/policy/executionResources.js +192 -0
  303. package/dist/policy/executionResources.js.map +1 -0
  304. package/dist/policy/fullAccessResources.js +23 -0
  305. package/dist/policy/fullAccessResources.js.map +1 -0
  306. package/dist/policy/hardPolicy.js +50 -0
  307. package/dist/policy/hardPolicy.js.map +1 -0
  308. package/dist/policy/identity.js +142 -0
  309. package/dist/policy/identity.js.map +1 -0
  310. package/dist/policy/integration.js +331 -0
  311. package/dist/policy/integration.js.map +1 -0
  312. package/dist/policy/pendingApprovals.js +301 -0
  313. package/dist/policy/pendingApprovals.js.map +1 -0
  314. package/dist/policy/profileStore.js +367 -0
  315. package/dist/policy/profileStore.js.map +1 -0
  316. package/dist/policy/resources.js +249 -0
  317. package/dist/policy/resources.js.map +1 -0
  318. package/dist/policy/runtime.js +713 -0
  319. package/dist/policy/runtime.js.map +1 -0
  320. package/dist/policy/schemas.js +625 -0
  321. package/dist/policy/schemas.js.map +1 -0
  322. package/dist/policy/toolPolicy.js +141 -0
  323. package/dist/policy/toolPolicy.js.map +1 -0
  324. package/dist/policy/transport.js +10 -0
  325. package/dist/policy/transport.js.map +1 -0
  326. package/dist/policy/types.js +31 -0
  327. package/dist/policy/types.js.map +1 -0
  328. package/dist/proContext.js +675 -0
  329. package/dist/proContext.js.map +1 -0
  330. package/dist/process/authority.js +18 -0
  331. package/dist/process/authority.js.map +1 -0
  332. package/dist/process/backendDiscovery.js +83 -0
  333. package/dist/process/backendDiscovery.js.map +1 -0
  334. package/dist/process/commandCompiler.js +71 -0
  335. package/dist/process/commandCompiler.js.map +1 -0
  336. package/dist/process/outputCursor.js +67 -0
  337. package/dist/process/outputCursor.js.map +1 -0
  338. package/dist/process/outputQuota.js +94 -0
  339. package/dist/process/outputQuota.js.map +1 -0
  340. package/dist/process/outputRing.js +138 -0
  341. package/dist/process/outputRing.js.map +1 -0
  342. package/dist/process/processAuditCoordinator.js +52 -0
  343. package/dist/process/processAuditCoordinator.js.map +1 -0
  344. package/dist/process/processManager.js +311 -0
  345. package/dist/process/processManager.js.map +1 -0
  346. package/dist/process/runCommand.js +332 -0
  347. package/dist/process/runCommand.js.map +1 -0
  348. package/dist/process/streamingRedactor.js +105 -0
  349. package/dist/process/streamingRedactor.js.map +1 -0
  350. package/dist/process/types.js +2 -0
  351. package/dist/process/types.js.map +1 -0
  352. package/dist/process/windowsHostClient.js +604 -0
  353. package/dist/process/windowsHostClient.js.map +1 -0
  354. package/dist/process/windowsHostProtocol.js +270 -0
  355. package/dist/process/windowsHostProtocol.js.map +1 -0
  356. package/dist/process/windowsPersistentBackend.js +263 -0
  357. package/dist/process/windowsPersistentBackend.js.map +1 -0
  358. package/dist/productionRuntime.js +907 -0
  359. package/dist/productionRuntime.js.map +1 -0
  360. package/dist/profileStore.js +231 -0
  361. package/dist/profileStore.js.map +1 -0
  362. package/dist/redact.js +124 -0
  363. package/dist/redact.js.map +1 -0
  364. package/dist/searchOps.js +186 -0
  365. package/dist/searchOps.js.map +1 -0
  366. package/dist/selfTestOps.js +786 -0
  367. package/dist/selfTestOps.js.map +1 -0
  368. package/dist/semantic/budgets.js +12 -0
  369. package/dist/semantic/budgets.js.map +1 -0
  370. package/dist/semantic/builtin/typescriptAssets.js +68 -0
  371. package/dist/semantic/builtin/typescriptAssets.js.map +1 -0
  372. package/dist/semantic/builtin/typescriptProvider.js +211 -0
  373. package/dist/semantic/builtin/typescriptProvider.js.map +1 -0
  374. package/dist/semantic/builtin/typescriptWorker.js +365 -0
  375. package/dist/semantic/builtin/typescriptWorker.js.map +1 -0
  376. package/dist/semantic/diffPreview.js +36 -0
  377. package/dist/semantic/diffPreview.js.map +1 -0
  378. package/dist/semantic/index.js +11 -0
  379. package/dist/semantic/index.js.map +1 -0
  380. package/dist/semantic/manager.js +522 -0
  381. package/dist/semantic/manager.js.map +1 -0
  382. package/dist/semantic/positions.js +86 -0
  383. package/dist/semantic/positions.js.map +1 -0
  384. package/dist/semantic/previewStore.js +276 -0
  385. package/dist/semantic/previewStore.js.map +1 -0
  386. package/dist/semantic/projectResolver.js +309 -0
  387. package/dist/semantic/projectResolver.js.map +1 -0
  388. package/dist/semantic/sourceSnapshot.js +54 -0
  389. package/dist/semantic/sourceSnapshot.js.map +1 -0
  390. package/dist/semantic/status.js +46 -0
  391. package/dist/semantic/status.js.map +1 -0
  392. package/dist/semantic/types.js +2 -0
  393. package/dist/semantic/types.js.map +1 -0
  394. package/dist/server.js +8676 -0
  395. package/dist/server.js.map +1 -0
  396. package/dist/stdio.js +64 -0
  397. package/dist/stdio.js.map +1 -0
  398. package/dist/toolCardWidget.js +2000 -0
  399. package/dist/toolCardWidget.js.map +1 -0
  400. package/dist/tools/contracts/catalog.js +111 -0
  401. package/dist/tools/contracts/catalog.js.map +1 -0
  402. package/dist/tools/contracts/index.js +8 -0
  403. package/dist/tools/contracts/index.js.map +1 -0
  404. package/dist/tools/contracts/registration.js +27 -0
  405. package/dist/tools/contracts/registration.js.map +1 -0
  406. package/dist/tools/contracts/schemas.js +11 -0
  407. package/dist/tools/contracts/schemas.js.map +1 -0
  408. package/dist/tools/contracts/types.js +2 -0
  409. package/dist/tools/contracts/types.js.map +1 -0
  410. package/dist/tools/contracts/v3.js +76 -0
  411. package/dist/tools/contracts/v3.js.map +1 -0
  412. package/dist/tools/contracts/v4.js +39 -0
  413. package/dist/tools/contracts/v4.js.map +1 -0
  414. package/dist/tools/contracts/v5.js +20 -0
  415. package/dist/tools/contracts/v5.js.map +1 -0
  416. package/dist/tools/phase3dServer.js +350 -0
  417. package/dist/tools/phase3dServer.js.map +1 -0
  418. package/dist/tools/schemas/applyPatch.js +388 -0
  419. package/dist/tools/schemas/applyPatch.js.map +1 -0
  420. package/dist/tools/schemas/bash.js +202 -0
  421. package/dist/tools/schemas/bash.js.map +1 -0
  422. package/dist/tools/schemas/closeWorkspace.js +105 -0
  423. package/dist/tools/schemas/closeWorkspace.js.map +1 -0
  424. package/dist/tools/schemas/codexContext.js +402 -0
  425. package/dist/tools/schemas/codexContext.js.map +1 -0
  426. package/dist/tools/schemas/codexSessions.js +328 -0
  427. package/dist/tools/schemas/codexSessions.js.map +1 -0
  428. package/dist/tools/schemas/codexgpt.js +1068 -0
  429. package/dist/tools/schemas/codexgpt.js.map +1 -0
  430. package/dist/tools/schemas/codexgptInventory.js +359 -0
  431. package/dist/tools/schemas/codexgptInventory.js.map +1 -0
  432. package/dist/tools/schemas/codexgptSelfTest.js +563 -0
  433. package/dist/tools/schemas/codexgptSelfTest.js.map +1 -0
  434. package/dist/tools/schemas/codexpro.js +917 -0
  435. package/dist/tools/schemas/codexpro.js.map +1 -0
  436. package/dist/tools/schemas/codexproInventory.js +352 -0
  437. package/dist/tools/schemas/codexproInventory.js.map +1 -0
  438. package/dist/tools/schemas/codexproSelfTest.js +546 -0
  439. package/dist/tools/schemas/codexproSelfTest.js.map +1 -0
  440. package/dist/tools/schemas/common.js +21 -0
  441. package/dist/tools/schemas/common.js.map +1 -0
  442. package/dist/tools/schemas/createTaskWorktree.js +51 -0
  443. package/dist/tools/schemas/createTaskWorktree.js.map +1 -0
  444. package/dist/tools/schemas/edit.js +321 -0
  445. package/dist/tools/schemas/edit.js.map +1 -0
  446. package/dist/tools/schemas/execution.js +330 -0
  447. package/dist/tools/schemas/execution.js.map +1 -0
  448. package/dist/tools/schemas/exportProContext.js +370 -0
  449. package/dist/tools/schemas/exportProContext.js.map +1 -0
  450. package/dist/tools/schemas/getTaskWorktree.js +19 -0
  451. package/dist/tools/schemas/getTaskWorktree.js.map +1 -0
  452. package/dist/tools/schemas/gitBranch.js +42 -0
  453. package/dist/tools/schemas/gitBranch.js.map +1 -0
  454. package/dist/tools/schemas/gitCommit.js +40 -0
  455. package/dist/tools/schemas/gitCommit.js.map +1 -0
  456. package/dist/tools/schemas/gitCreateBranch.js +22 -0
  457. package/dist/tools/schemas/gitCreateBranch.js.map +1 -0
  458. package/dist/tools/schemas/gitDiff.js +222 -0
  459. package/dist/tools/schemas/gitDiff.js.map +1 -0
  460. package/dist/tools/schemas/gitLog.js +41 -0
  461. package/dist/tools/schemas/gitLog.js.map +1 -0
  462. package/dist/tools/schemas/gitRestore.js +47 -0
  463. package/dist/tools/schemas/gitRestore.js.map +1 -0
  464. package/dist/tools/schemas/gitStage.js +33 -0
  465. package/dist/tools/schemas/gitStage.js.map +1 -0
  466. package/dist/tools/schemas/gitStash.js +102 -0
  467. package/dist/tools/schemas/gitStash.js.map +1 -0
  468. package/dist/tools/schemas/gitStatus.js +226 -0
  469. package/dist/tools/schemas/gitStatus.js.map +1 -0
  470. package/dist/tools/schemas/gitV4Common.js +205 -0
  471. package/dist/tools/schemas/gitV4Common.js.map +1 -0
  472. package/dist/tools/schemas/guidance.js +40 -0
  473. package/dist/tools/schemas/guidance.js.map +1 -0
  474. package/dist/tools/schemas/handoffToAgent.js +276 -0
  475. package/dist/tools/schemas/handoffToAgent.js.map +1 -0
  476. package/dist/tools/schemas/handoffToCodex.js +137 -0
  477. package/dist/tools/schemas/handoffToCodex.js.map +1 -0
  478. package/dist/tools/schemas/inspectWorkspace.js +379 -0
  479. package/dist/tools/schemas/inspectWorkspace.js.map +1 -0
  480. package/dist/tools/schemas/listTaskWorktrees.js +21 -0
  481. package/dist/tools/schemas/listTaskWorktrees.js.map +1 -0
  482. package/dist/tools/schemas/listWorkspaces.js +134 -0
  483. package/dist/tools/schemas/listWorkspaces.js.map +1 -0
  484. package/dist/tools/schemas/loadSkill.js +619 -0
  485. package/dist/tools/schemas/loadSkill.js.map +1 -0
  486. package/dist/tools/schemas/mergeTaskWorktree.js +105 -0
  487. package/dist/tools/schemas/mergeTaskWorktree.js.map +1 -0
  488. package/dist/tools/schemas/movePaths.js +175 -0
  489. package/dist/tools/schemas/movePaths.js.map +1 -0
  490. package/dist/tools/schemas/openCurrentWorkspace.js +174 -0
  491. package/dist/tools/schemas/openCurrentWorkspace.js.map +1 -0
  492. package/dist/tools/schemas/openFullAccessWorkspace.js +81 -0
  493. package/dist/tools/schemas/openFullAccessWorkspace.js.map +1 -0
  494. package/dist/tools/schemas/openWorkspace.js +193 -0
  495. package/dist/tools/schemas/openWorkspace.js.map +1 -0
  496. package/dist/tools/schemas/queryAuditEvents.js +193 -0
  497. package/dist/tools/schemas/queryAuditEvents.js.map +1 -0
  498. package/dist/tools/schemas/read.js +199 -0
  499. package/dist/tools/schemas/read.js.map +1 -0
  500. package/dist/tools/schemas/readCodexSession.js +353 -0
  501. package/dist/tools/schemas/readCodexSession.js.map +1 -0
  502. package/dist/tools/schemas/readHandoff.js +446 -0
  503. package/dist/tools/schemas/readHandoff.js.map +1 -0
  504. package/dist/tools/schemas/removeTaskWorktree.js +40 -0
  505. package/dist/tools/schemas/removeTaskWorktree.js.map +1 -0
  506. package/dist/tools/schemas/search.js +235 -0
  507. package/dist/tools/schemas/search.js.map +1 -0
  508. package/dist/tools/schemas/semantic.js +195 -0
  509. package/dist/tools/schemas/semantic.js.map +1 -0
  510. package/dist/tools/schemas/serverConfig.js +157 -0
  511. package/dist/tools/schemas/serverConfig.js.map +1 -0
  512. package/dist/tools/schemas/showChanges.js +283 -0
  513. package/dist/tools/schemas/showChanges.js.map +1 -0
  514. package/dist/tools/schemas/transactionResult.js +11 -0
  515. package/dist/tools/schemas/transactionResult.js.map +1 -0
  516. package/dist/tools/schemas/tree.js +136 -0
  517. package/dist/tools/schemas/tree.js.map +1 -0
  518. package/dist/tools/schemas/undoChangeSet.js +152 -0
  519. package/dist/tools/schemas/undoChangeSet.js.map +1 -0
  520. package/dist/tools/schemas/waitForHandoff.js +462 -0
  521. package/dist/tools/schemas/waitForHandoff.js.map +1 -0
  522. package/dist/tools/schemas/workspaceSnapshot.js +145 -0
  523. package/dist/tools/schemas/workspaceSnapshot.js.map +1 -0
  524. package/dist/tools/schemas/write.js +285 -0
  525. package/dist/tools/schemas/write.js.map +1 -0
  526. package/dist/transactions/atomicFs.js +438 -0
  527. package/dist/transactions/atomicFs.js.map +1 -0
  528. package/dist/transactions/atomicStateFile.js +190 -0
  529. package/dist/transactions/atomicStateFile.js.map +1 -0
  530. package/dist/transactions/engine.js +574 -0
  531. package/dist/transactions/engine.js.map +1 -0
  532. package/dist/transactions/index.js +12 -0
  533. package/dist/transactions/index.js.map +1 -0
  534. package/dist/transactions/installation.js +158 -0
  535. package/dist/transactions/installation.js.map +1 -0
  536. package/dist/transactions/manifestV2Store.js +96 -0
  537. package/dist/transactions/manifestV2Store.js.map +1 -0
  538. package/dist/transactions/participantRecovery.js +98 -0
  539. package/dist/transactions/participantRecovery.js.map +1 -0
  540. package/dist/transactions/recovery.js +513 -0
  541. package/dist/transactions/recovery.js.map +1 -0
  542. package/dist/transactions/schemas.js +365 -0
  543. package/dist/transactions/schemas.js.map +1 -0
  544. package/dist/transactions/stateRoot.js +63 -0
  545. package/dist/transactions/stateRoot.js.map +1 -0
  546. package/dist/transactions/types.js +11 -0
  547. package/dist/transactions/types.js.map +1 -0
  548. package/dist/transactions/workspaceLock.js +201 -0
  549. package/dist/transactions/workspaceLock.js.map +1 -0
  550. package/dist/workspaceOps.js +924 -0
  551. package/dist/workspaceOps.js.map +1 -0
  552. package/dist/worktrees/candidateWorkspace.js +566 -0
  553. package/dist/worktrees/candidateWorkspace.js.map +1 -0
  554. package/dist/worktrees/manager.js +258 -0
  555. package/dist/worktrees/manager.js.map +1 -0
  556. package/dist/worktrees/materializer.js +60 -0
  557. package/dist/worktrees/materializer.js.map +1 -0
  558. package/dist/worktrees/mergeExecute.js +498 -0
  559. package/dist/worktrees/mergeExecute.js.map +1 -0
  560. package/dist/worktrees/mergePlanStore.js +247 -0
  561. package/dist/worktrees/mergePlanStore.js.map +1 -0
  562. package/dist/worktrees/mergePrepare.js +709 -0
  563. package/dist/worktrees/mergePrepare.js.map +1 -0
  564. package/dist/worktrees/recovery.js +294 -0
  565. package/dist/worktrees/recovery.js.map +1 -0
  566. package/dist/worktrees/remove.js +296 -0
  567. package/dist/worktrees/remove.js.map +1 -0
  568. package/dist/worktrees/remover.js +57 -0
  569. package/dist/worktrees/remover.js.map +1 -0
  570. package/dist/worktrees/root.js +47 -0
  571. package/dist/worktrees/root.js.map +1 -0
  572. package/dist/worktrees/service.js +245 -0
  573. package/dist/worktrees/service.js.map +1 -0
  574. package/dist/worktrees/store.js +156 -0
  575. package/dist/worktrees/store.js.map +1 -0
  576. package/dist/worktrees/treeManifest.js +106 -0
  577. package/dist/worktrees/treeManifest.js.map +1 -0
  578. package/dist/worktrees/verificationReceipts.js +215 -0
  579. package/dist/worktrees/verificationReceipts.js.map +1 -0
  580. package/dist/worktrees/verificationTerminal.js +23 -0
  581. package/dist/worktrees/verificationTerminal.js.map +1 -0
  582. package/dist/worktrees/workspaceAuthority.js +64 -0
  583. package/dist/worktrees/workspaceAuthority.js.map +1 -0
  584. package/docs/favicon.svg +5 -0
  585. package/docs/index.html +624 -0
  586. package/docs/og.svg +52 -0
  587. package/docs/script.js +33 -0
  588. package/docs/star.svg +11 -0
  589. package/docs/styles.css +1571 -0
  590. package/docs/zh.html +428 -0
  591. package/package.json +121 -0
  592. package/scripts/analysis-cli-smoke.mjs +81 -0
  593. package/scripts/analysis-smoke.mjs +179 -0
  594. package/scripts/atomic-file.mjs +137 -0
  595. package/scripts/ci-change-classifier.mjs +59 -0
  596. package/scripts/ci-failure-summary.mjs +92 -0
  597. package/scripts/cloudflared-installer.mjs +215 -0
  598. package/scripts/cloudflared-release.mjs +63 -0
  599. package/scripts/codexgpt-entry.mjs +235 -0
  600. package/scripts/codexgpt.mjs +4987 -0
  601. package/scripts/connector-auth-output-shim.cjs +66 -0
  602. package/scripts/doctor-smoke.mjs +90 -0
  603. package/scripts/doctor.mjs +165 -0
  604. package/scripts/exact-head-ci.mjs +126 -0
  605. package/scripts/execute-handoff-smoke-platform-compat.mjs +38 -0
  606. package/scripts/execute-handoff-smoke.mjs +1117 -0
  607. package/scripts/g8-u-live-probe.mjs +208 -0
  608. package/scripts/http-smoke-compat.mjs +151 -0
  609. package/scripts/http-smoke.mjs +776 -0
  610. package/scripts/long-task-runner.mjs +1037 -0
  611. package/scripts/oauth-admin.mjs +1608 -0
  612. package/scripts/output-bounds.mjs +29 -0
  613. package/scripts/owned-temp-root.d.mts +50 -0
  614. package/scripts/owned-temp-root.mjs +567 -0
  615. package/scripts/phase-4a-smoke.mjs +36 -0
  616. package/scripts/policy-windows-spike.mjs +135 -0
  617. package/scripts/pro-apply.mjs +152 -0
  618. package/scripts/pro-bundle.mjs +121 -0
  619. package/scripts/pro-smoke.mjs +97 -0
  620. package/scripts/process-identity.mjs +67 -0
  621. package/scripts/repository-policy.mjs +166 -0
  622. package/scripts/run-and-summarize.mjs +134 -0
  623. package/scripts/run-smoke.mjs +52 -0
  624. package/scripts/run-with-cleanup.mjs +98 -0
  625. package/scripts/settings-smoke-platform-compat.mjs +85 -0
  626. package/scripts/settings-smoke.mjs +769 -0
  627. package/scripts/smoke-platform-compat.mjs +302 -0
  628. package/scripts/smoke.mjs +1180 -0
  629. package/scripts/stress-contract-compat.mjs +94 -0
  630. package/scripts/stress.mjs +882 -0
  631. package/scripts/test-domains.mjs +247 -0
  632. package/scripts/test-execution-profile-manifest.mjs +273 -0
  633. package/scripts/test-execution-profiles.mjs +147 -0
  634. package/scripts/test-performance-reporter.mjs +291 -0
  635. package/scripts/toolchain-manager.mjs +266 -0
  636. package/scripts/toolchains.json +19 -0
  637. package/scripts/windows-conpty-probe-child.mjs +82 -0
  638. package/scripts/windows-conpty-worker.ps1 +24 -0
  639. package/scripts/windows-credential-host-manifest.json +16 -0
  640. package/scripts/windows-credential-host-protocol-v1.json +16 -0
  641. package/scripts/windows-credential-host.cs +256 -0
  642. package/scripts/windows-credential-host.ps1 +26 -0
  643. package/scripts/windows-local-control-manifest.json +23 -0
  644. package/scripts/windows-local-control-spike.cs +738 -0
  645. package/scripts/windows-local-control-spike.mjs +415 -0
  646. package/scripts/windows-local-control-spike.ps1 +35 -0
  647. package/scripts/windows-local-control.cs +738 -0
  648. package/scripts/windows-local-control.ps1 +35 -0
  649. package/scripts/windows-native-api-inventory-v1.json +90 -0
  650. package/scripts/windows-process-host-manifest.json +20 -0
  651. package/scripts/windows-process-host-protocol-v1.json +59 -0
  652. package/scripts/windows-process-host.cs +2385 -0
  653. package/scripts/windows-process-host.ps1 +59 -0
  654. package/scripts/windows-realpath-shim.cjs +78 -0
@@ -0,0 +1,1309 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createHash, createHmac, randomBytes as nodeRandomBytes, timingSafeEqual } from "node:crypto";
4
+ import { AtomicJsonFileStore } from "../transactions/atomicStateFile.js";
5
+ import { installationMasterKey, loadOrCreateInstallationState } from "../transactions/installation.js";
6
+ import { transactionStateDirectories } from "../transactions/stateRoot.js";
7
+ import { auditRecordMac, canonicalJson, deriveAuditCursorKey, deriveAuditQueryV3CursorKey, deriveAuditQueryV4CursorKey, deriveAuditRecordKey } from "./canonicalJson.js";
8
+ import { AuditWriterLock } from "./lock.js";
9
+ import { auditQueryFilterDigest, auditQueryFilterDigestV3, auditQueryFilterDigestV4 } from "./queryTool.js";
10
+ import { auditEnvelopeV1Schema, auditIndexV1Schema, persistedAuditEventSchema, queryAuditEventsInputV2Schema, queryAuditEventsInputV3Schema, queryAuditEventsInputV4Schema } from "./schemas.js";
11
+ import { AuditError } from "./types.js";
12
+ const ZERO_MAC = "0".repeat(64);
13
+ const DEFAULT_SEGMENT_BYTES = 10 * 1024 * 1024;
14
+ function syncDirectoryBestEffort(directory) {
15
+ let fd;
16
+ try {
17
+ fd = fs.openSync(directory, "r");
18
+ fs.fsyncSync(fd);
19
+ }
20
+ catch {
21
+ // Directory fsync is not portable on Windows. File fsync remains mandatory.
22
+ }
23
+ finally {
24
+ if (fd !== undefined)
25
+ fs.closeSync(fd);
26
+ }
27
+ }
28
+ function delay(milliseconds) {
29
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
30
+ }
31
+ function safeParseJson(text) {
32
+ try {
33
+ return JSON.parse(text);
34
+ }
35
+ catch {
36
+ throw new AuditError("AUDIT_RECORD_INVALID", "Audit record is not valid JSON.");
37
+ }
38
+ }
39
+ function segmentDate(segmentId) {
40
+ return segmentId.slice(6, 16);
41
+ }
42
+ function segmentFileName(segmentId) {
43
+ return `${segmentId}.jsonl`;
44
+ }
45
+ function compareIndexWithScan(index, scan) {
46
+ if (index.state === "integrity_failed") {
47
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit store is in integrity-failed state.");
48
+ }
49
+ if (index.chainAnchorSequence > index.lastSequence) {
50
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit chain anchor is beyond the index tail.");
51
+ }
52
+ if (index.chainAnchorSequence === 0 && index.chainAnchorMac !== ZERO_MAC) {
53
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Initial audit chain anchor is invalid.");
54
+ }
55
+ const last = scan.envelopes.at(-1);
56
+ const scannedLastSequence = last?.sequence ?? index.chainAnchorSequence;
57
+ if (index.lastSequence > scannedLastSequence) {
58
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit index claims records that are not present.");
59
+ }
60
+ if (index.lastSequence === index.chainAnchorSequence) {
61
+ if (index.lastMac !== index.chainAnchorMac) {
62
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit index chain anchor conflicts with its tail.");
63
+ }
64
+ return;
65
+ }
66
+ const indexed = scan.envelopes.find((envelope) => envelope.sequence === index.lastSequence);
67
+ if (!indexed || indexed.recordMac !== index.lastMac) {
68
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit index conflicts with persisted records.");
69
+ }
70
+ }
71
+ export class PersistentAuditStore {
72
+ stateRoot;
73
+ auditDirectory;
74
+ segmentsDirectory;
75
+ quarantineDirectory;
76
+ indexFile;
77
+ recordKey;
78
+ cursorKey;
79
+ cursorKeyV3;
80
+ cursorKeyV4;
81
+ indexStore;
82
+ writerLock;
83
+ now;
84
+ randomBytes;
85
+ maxSegmentBytes;
86
+ lockRetryCount;
87
+ retention;
88
+ constructor(options) {
89
+ this.stateRoot = path.resolve(options.stateRoot);
90
+ const directories = transactionStateDirectories(this.stateRoot);
91
+ this.auditDirectory = directories.audit;
92
+ this.segmentsDirectory = path.join(this.auditDirectory, "segments");
93
+ this.quarantineDirectory = path.join(this.auditDirectory, "quarantine");
94
+ this.indexFile = path.join(this.auditDirectory, "index.json");
95
+ this.now = options.now ?? Date.now;
96
+ this.randomBytes = options.randomBytes ?? nodeRandomBytes;
97
+ this.maxSegmentBytes = options.maxSegmentBytes ?? DEFAULT_SEGMENT_BYTES;
98
+ this.lockRetryCount = options.lockRetryCount ?? 500;
99
+ this.retention = {
100
+ maxAgeDays: Math.max(1, Math.min(365, Math.floor(options.retention.maxAgeDays))),
101
+ maxClosedBytes: Math.max(1, Math.min(2 * 1024 * 1024 * 1024, Math.floor(options.retention.maxClosedBytes)))
102
+ };
103
+ if (!Number.isSafeInteger(this.maxSegmentBytes) || this.maxSegmentBytes < 4096) {
104
+ throw new AuditError("AUDIT_UNAVAILABLE", "Audit segment size limit is invalid.");
105
+ }
106
+ const installation = loadOrCreateInstallationState({
107
+ stateRoot: this.stateRoot,
108
+ randomBytes: this.randomBytes,
109
+ now: this.now
110
+ });
111
+ const masterKey = installationMasterKey(installation);
112
+ try {
113
+ this.recordKey = deriveAuditRecordKey(masterKey);
114
+ this.cursorKey = deriveAuditCursorKey(masterKey);
115
+ this.cursorKeyV3 = deriveAuditQueryV3CursorKey(masterKey);
116
+ this.cursorKeyV4 = deriveAuditQueryV4CursorKey(masterKey);
117
+ }
118
+ finally {
119
+ masterKey.fill(0);
120
+ }
121
+ fs.mkdirSync(this.segmentsDirectory, { recursive: true, mode: 0o700 });
122
+ fs.mkdirSync(this.quarantineDirectory, { recursive: true, mode: 0o700 });
123
+ this.indexStore = new AtomicJsonFileStore(this.stateRoot, auditIndexV1Schema);
124
+ this.writerLock = new AuditWriterLock(this.stateRoot, options.registry, {
125
+ randomBytes: this.randomBytes,
126
+ now: this.now
127
+ });
128
+ }
129
+ static open(options) {
130
+ return new PersistentAuditStore(options);
131
+ }
132
+ dispose() {
133
+ this.recordKey.fill(0);
134
+ this.cursorKey.fill(0);
135
+ this.cursorKeyV3.fill(0);
136
+ this.cursorKeyV4.fill(0);
137
+ }
138
+ randomHex(bytes) {
139
+ const value = this.randomBytes(bytes);
140
+ if (!Buffer.isBuffer(value) || value.length !== bytes) {
141
+ throw new AuditError("AUDIT_UNAVAILABLE", "Audit random source returned an invalid value.");
142
+ }
143
+ return value.toString("hex");
144
+ }
145
+ eventId() {
146
+ return `event_${this.randomHex(16)}`;
147
+ }
148
+ timestamp() {
149
+ return new Date(this.now()).toISOString();
150
+ }
151
+ emptyIndex() {
152
+ return {
153
+ storeVersion: 1,
154
+ state: "healthy",
155
+ activeSegmentId: null,
156
+ chainAnchorSequence: 0,
157
+ chainAnchorMac: ZERO_MAC,
158
+ lastSequence: 0,
159
+ lastMac: ZERO_MAC,
160
+ lastAppendAt: null,
161
+ failureCode: null,
162
+ segments: []
163
+ };
164
+ }
165
+ readIndex() {
166
+ if (!fs.existsSync(this.indexFile))
167
+ return this.emptyIndex();
168
+ try {
169
+ return this.indexStore.read(this.indexFile);
170
+ }
171
+ catch {
172
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit index is missing or invalid.");
173
+ }
174
+ }
175
+ writeIndex(index) {
176
+ try {
177
+ this.indexStore.write(this.indexFile, auditIndexV1Schema.parse(index));
178
+ }
179
+ catch (error) {
180
+ if (error instanceof AuditError)
181
+ throw error;
182
+ throw new AuditError("AUDIT_UNAVAILABLE", "Audit index could not be persisted.");
183
+ }
184
+ }
185
+ markIntegrityFailure() {
186
+ try {
187
+ const previous = this.readIndex();
188
+ this.writeIndex({
189
+ ...previous,
190
+ state: "integrity_failed",
191
+ failureCode: "AUDIT_INTEGRITY_FAILURE"
192
+ });
193
+ }
194
+ catch {
195
+ // Preserve original evidence if bounded degraded metadata cannot be written.
196
+ }
197
+ }
198
+ scanSegments(chainAnchorSequence, chainAnchorMac, allowIncompleteTail) {
199
+ const names = fs.readdirSync(this.segmentsDirectory)
200
+ .filter((name) => /^audit-[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{6}\.jsonl$/.test(name))
201
+ .sort();
202
+ const envelopes = [];
203
+ const segments = [];
204
+ let expectedSequence = chainAnchorSequence + 1;
205
+ let expectedPreviousMac = chainAnchorMac;
206
+ const eventIds = new Set();
207
+ let incompleteTail = null;
208
+ for (let fileIndex = 0; fileIndex < names.length; fileIndex += 1) {
209
+ const name = names[fileIndex];
210
+ const file = path.join(this.segmentsDirectory, name);
211
+ const bytes = fs.readFileSync(file);
212
+ const isLastFile = fileIndex === names.length - 1;
213
+ let completeBytes = bytes;
214
+ if (bytes.length === 0 || bytes[bytes.length - 1] !== 0x0a) {
215
+ if (!allowIncompleteTail || !isLastFile) {
216
+ throw new AuditError("AUDIT_RECORD_INVALID", "Audit segment has an incomplete final record.");
217
+ }
218
+ const lastNewline = bytes.lastIndexOf(0x0a);
219
+ const prefixByteLength = lastNewline < 0 ? 0 : lastNewline + 1;
220
+ const tail = Buffer.from(bytes.subarray(prefixByteLength));
221
+ incompleteTail = {
222
+ file,
223
+ segmentId: name.slice(0, -6),
224
+ prefixByteLength,
225
+ bytes: tail
226
+ };
227
+ completeBytes = bytes.subarray(0, prefixByteLength);
228
+ }
229
+ const text = completeBytes.toString("utf8");
230
+ const lines = text.length === 0 ? [] : text.slice(0, -1).split("\n").filter((line) => line.length > 0);
231
+ if (lines.length === 0) {
232
+ if (incompleteTail?.file === file)
233
+ continue;
234
+ throw new AuditError("AUDIT_RECORD_INVALID", "Audit segment is empty.");
235
+ }
236
+ const segmentId = name.slice(0, -6);
237
+ let first;
238
+ let last;
239
+ for (const line of lines) {
240
+ let envelope;
241
+ try {
242
+ envelope = auditEnvelopeV1Schema.parse(safeParseJson(line));
243
+ }
244
+ catch (error) {
245
+ if (error instanceof AuditError)
246
+ throw error;
247
+ throw new AuditError("AUDIT_RECORD_INVALID", "Audit record violates its strict schema.");
248
+ }
249
+ if (canonicalJson(envelope) !== line) {
250
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit record is not canonically encoded.");
251
+ }
252
+ if (envelope.segmentId !== segmentId) {
253
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit record segment identity is inconsistent.");
254
+ }
255
+ if (envelope.sequence !== expectedSequence || envelope.previousMac !== expectedPreviousMac) {
256
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit sequence or chain continuity is invalid.");
257
+ }
258
+ const { recordMac, ...withoutMac } = envelope;
259
+ if (auditRecordMac(this.recordKey, withoutMac) !== recordMac) {
260
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit record authentication failed.");
261
+ }
262
+ if (eventIds.has(envelope.event.eventId)) {
263
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit event identity is duplicated.");
264
+ }
265
+ eventIds.add(envelope.event.eventId);
266
+ envelopes.push(envelope);
267
+ first ??= envelope;
268
+ last = envelope;
269
+ expectedSequence += 1;
270
+ expectedPreviousMac = recordMac;
271
+ }
272
+ if (!first || !last) {
273
+ throw new AuditError("AUDIT_RECORD_INVALID", "Audit segment contains no records.");
274
+ }
275
+ segments.push({
276
+ segmentId,
277
+ fileName: name,
278
+ state: "closed",
279
+ firstSequence: first.sequence,
280
+ lastSequence: last.sequence,
281
+ firstTimestamp: first.event.timestamp,
282
+ lastTimestamp: last.event.timestamp,
283
+ firstMac: first.recordMac,
284
+ lastMac: last.recordMac,
285
+ recordCount: lines.length,
286
+ byteSize: completeBytes.length
287
+ });
288
+ }
289
+ if (segments.length > 0)
290
+ segments[segments.length - 1].state = "active";
291
+ return { envelopes, segments, incompleteTail };
292
+ }
293
+ indexFromScan(scan, previous) {
294
+ const previousStates = new Map(previous.segments.map((segment) => [segment.segmentId, segment.state]));
295
+ const segments = scan.segments.map((segment, index) => ({
296
+ ...segment,
297
+ state: previousStates.get(segment.segmentId) === "delete_pending"
298
+ ? "delete_pending"
299
+ : index === scan.segments.length - 1
300
+ ? "active"
301
+ : "closed"
302
+ }));
303
+ const last = scan.envelopes.at(-1);
304
+ const active = [...segments].reverse().find((segment) => segment.state === "active");
305
+ return {
306
+ storeVersion: 1,
307
+ state: "healthy",
308
+ activeSegmentId: active?.segmentId ?? null,
309
+ chainAnchorSequence: previous.chainAnchorSequence,
310
+ chainAnchorMac: previous.chainAnchorMac,
311
+ lastSequence: last?.sequence ?? previous.chainAnchorSequence,
312
+ lastMac: last?.recordMac ?? previous.chainAnchorMac,
313
+ lastAppendAt: previous.lastAppendAt,
314
+ failureCode: null,
315
+ segments
316
+ };
317
+ }
318
+ nextSegmentId(date) {
319
+ const prefix = `audit-${date}-`;
320
+ const serials = fs.readdirSync(this.segmentsDirectory)
321
+ .filter((name) => name.startsWith(prefix) && name.endsWith(".jsonl"))
322
+ .map((name) => Number(name.slice(prefix.length, prefix.length + 6)))
323
+ .filter((value) => Number.isInteger(value));
324
+ const next = (serials.length === 0 ? 0 : Math.max(...serials)) + 1;
325
+ if (next > 999999) {
326
+ throw new AuditError("AUDIT_UNAVAILABLE", "Audit segment sequence is exhausted for the UTC day.");
327
+ }
328
+ return `${prefix}${String(next).padStart(6, "0")}`;
329
+ }
330
+ appendLine(file, line, create) {
331
+ const bytes = Buffer.from(`${line}\n`, "utf8");
332
+ let fd;
333
+ try {
334
+ fd = fs.openSync(file, create ? "wx" : "a", 0o600);
335
+ let offset = 0;
336
+ while (offset < bytes.length) {
337
+ offset += fs.writeSync(fd, bytes, offset, bytes.length - offset, null);
338
+ }
339
+ fs.fsyncSync(fd);
340
+ }
341
+ catch {
342
+ throw new AuditError("AUDIT_UNAVAILABLE", "Audit record append could not be made durable.");
343
+ }
344
+ finally {
345
+ bytes.fill(0);
346
+ if (fd !== undefined)
347
+ fs.closeSync(fd);
348
+ }
349
+ if (create)
350
+ syncDirectoryBestEffort(this.segmentsDirectory);
351
+ }
352
+ envelopeFor(index, event, segmentId) {
353
+ const withoutMac = {
354
+ storeVersion: 1,
355
+ sequence: index.lastSequence + 1,
356
+ segmentId,
357
+ previousMac: index.lastMac,
358
+ event: persistedAuditEventSchema.parse(event)
359
+ };
360
+ return auditEnvelopeV1Schema.parse({
361
+ ...withoutMac,
362
+ recordMac: auditRecordMac(this.recordKey, withoutMac)
363
+ });
364
+ }
365
+ appendEnvelope(index, event, segmentId, create) {
366
+ const envelope = this.envelopeFor(index, event, segmentId);
367
+ this.appendLine(path.join(this.segmentsDirectory, segmentFileName(segmentId)), canonicalJson(envelope), create);
368
+ const scan = this.scanSegments(index.chainAnchorSequence, index.chainAnchorMac, false);
369
+ compareIndexWithScan(index, scan);
370
+ const nextIndex = this.indexFromScan(scan, index);
371
+ nextIndex.lastAppendAt = this.timestamp();
372
+ this.writeIndex(nextIndex);
373
+ return { envelope, index: nextIndex, scan };
374
+ }
375
+ estimateEnvelopeBytes(index, event, segmentId) {
376
+ return Buffer.byteLength(canonicalJson(this.envelopeFor(index, event, segmentId)), "utf8") + 1;
377
+ }
378
+ commonAdministrative(action, canonicalAction) {
379
+ return {
380
+ schemaVersion: 2,
381
+ eventId: this.eventId(),
382
+ eventType: "administrative",
383
+ timestamp: this.timestamp(),
384
+ requestId: null,
385
+ authorizationEventId: null,
386
+ decisionId: null,
387
+ credentialRef: null,
388
+ transportSessionId: null,
389
+ toolName: null,
390
+ canonicalAction,
391
+ workspaceId: null,
392
+ workspaceRef: null,
393
+ policyRevision: null,
394
+ administrativeAction: action,
395
+ filterDigest: null,
396
+ resultCount: null,
397
+ segmentIds: [],
398
+ firstSequence: null,
399
+ lastSequence: null,
400
+ firstTimestamp: null,
401
+ lastTimestamp: null,
402
+ recordCount: null,
403
+ firstMac: null,
404
+ lastMac: null,
405
+ policyReason: null,
406
+ resultCode: null
407
+ };
408
+ }
409
+ rotationEvent(segment, reason) {
410
+ return {
411
+ ...this.commonAdministrative("segment_rotation", "audit_segment_rotation"),
412
+ segmentIds: [segment.segmentId],
413
+ firstSequence: segment.firstSequence,
414
+ lastSequence: segment.lastSequence,
415
+ firstTimestamp: segment.firstTimestamp,
416
+ lastTimestamp: segment.lastTimestamp,
417
+ recordCount: segment.recordCount,
418
+ firstMac: segment.firstMac,
419
+ lastMac: segment.lastMac,
420
+ policyReason: reason,
421
+ resultCode: "ROTATED"
422
+ };
423
+ }
424
+ recoveryEvent() {
425
+ return {
426
+ schemaVersion: 2,
427
+ eventId: this.eventId(),
428
+ eventType: "recovery",
429
+ timestamp: this.timestamp(),
430
+ requestId: null,
431
+ authorizationEventId: null,
432
+ decisionId: null,
433
+ credentialRef: null,
434
+ transportSessionId: null,
435
+ toolName: null,
436
+ canonicalAction: "audit_tail_recovery",
437
+ workspaceId: null,
438
+ workspaceRef: null,
439
+ policyRevision: null,
440
+ recoveryAction: "tail_quarantined",
441
+ transactionId: null,
442
+ changeSetId: null,
443
+ operationCount: 0,
444
+ resultCode: "TAIL_QUARANTINED"
445
+ };
446
+ }
447
+ reconcilePendingDeletion(index) {
448
+ let anchorSequence = index.chainAnchorSequence;
449
+ let anchorMac = index.chainAnchorMac;
450
+ let removed = 0;
451
+ for (const segment of index.segments) {
452
+ if (segment.state !== "delete_pending")
453
+ break;
454
+ const file = path.join(this.segmentsDirectory, segment.fileName);
455
+ if (fs.existsSync(file))
456
+ break;
457
+ anchorSequence = segment.lastSequence;
458
+ anchorMac = segment.lastMac;
459
+ removed += 1;
460
+ }
461
+ if (removed === 0)
462
+ return index;
463
+ const next = {
464
+ ...index,
465
+ chainAnchorSequence: anchorSequence,
466
+ chainAnchorMac: anchorMac,
467
+ segments: index.segments.slice(removed)
468
+ };
469
+ this.writeIndex(next);
470
+ return next;
471
+ }
472
+ quarantineTail(tail) {
473
+ const quarantineFile = path.join(this.quarantineDirectory, `tail-${this.timestamp().replace(/[^0-9]/g, "").slice(0, 17)}-${this.randomHex(8)}.bin`);
474
+ let quarantineFd;
475
+ try {
476
+ quarantineFd = fs.openSync(quarantineFile, "wx", 0o600);
477
+ let offset = 0;
478
+ while (offset < tail.bytes.length) {
479
+ offset += fs.writeSync(quarantineFd, tail.bytes, offset, tail.bytes.length - offset, null);
480
+ }
481
+ fs.fsyncSync(quarantineFd);
482
+ }
483
+ catch {
484
+ throw new AuditError("AUDIT_UNAVAILABLE", "Incomplete audit tail could not be quarantined durably.");
485
+ }
486
+ finally {
487
+ if (quarantineFd !== undefined)
488
+ fs.closeSync(quarantineFd);
489
+ }
490
+ syncDirectoryBestEffort(this.quarantineDirectory);
491
+ let segmentFd;
492
+ try {
493
+ segmentFd = fs.openSync(tail.file, "r+");
494
+ fs.ftruncateSync(segmentFd, tail.prefixByteLength);
495
+ fs.fsyncSync(segmentFd);
496
+ }
497
+ catch {
498
+ throw new AuditError("AUDIT_UNAVAILABLE", "Incomplete audit tail could not be truncated safely.");
499
+ }
500
+ finally {
501
+ if (segmentFd !== undefined)
502
+ fs.closeSync(segmentFd);
503
+ tail.bytes.fill(0);
504
+ }
505
+ if (tail.prefixByteLength === 0) {
506
+ fs.unlinkSync(tail.file);
507
+ syncDirectoryBestEffort(this.segmentsDirectory);
508
+ }
509
+ }
510
+ loadVerifiedState(recoverTail) {
511
+ let index = this.reconcilePendingDeletion(this.readIndex());
512
+ let scan = this.scanSegments(index.chainAnchorSequence, index.chainAnchorMac, recoverTail);
513
+ compareIndexWithScan(index, scan);
514
+ if (scan.incompleteTail) {
515
+ if (!recoverTail) {
516
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit evidence contains an incomplete final record.");
517
+ }
518
+ this.quarantineTail(scan.incompleteTail);
519
+ scan = this.scanSegments(index.chainAnchorSequence, index.chainAnchorMac, false);
520
+ index = this.indexFromScan(scan, index);
521
+ this.writeIndex(index);
522
+ const date = this.timestamp().slice(0, 10);
523
+ const segmentId = index.activeSegmentId ?? this.nextSegmentId(date);
524
+ const recovered = this.appendEnvelope(index, this.recoveryEvent(), segmentId, index.activeSegmentId === null);
525
+ return { index: recovered.index, scan: recovered.scan };
526
+ }
527
+ const current = this.indexFromScan(scan, index);
528
+ if (canonicalJson(current) !== canonicalJson(index))
529
+ this.writeIndex(current);
530
+ return { index: current, scan };
531
+ }
532
+ async withWriterLock(action) {
533
+ for (let attempt = 0; attempt <= this.lockRetryCount; attempt += 1) {
534
+ let handle;
535
+ try {
536
+ handle = this.writerLock.acquire();
537
+ }
538
+ catch (error) {
539
+ if (error instanceof AuditError && error.code === "AUDIT_BUSY" && attempt < this.lockRetryCount) {
540
+ await delay(Math.min(20, 1 + Math.floor(attempt / 20)));
541
+ continue;
542
+ }
543
+ throw error;
544
+ }
545
+ try {
546
+ return await action();
547
+ }
548
+ finally {
549
+ handle.release();
550
+ }
551
+ }
552
+ throw new AuditError("AUDIT_BUSY", "Audit writer lock remained unavailable.");
553
+ }
554
+ async append(event) {
555
+ const parsedEvent = persistedAuditEventSchema.parse(event);
556
+ return this.withWriterLock(() => {
557
+ try {
558
+ let { index, scan } = this.loadVerifiedState(true);
559
+ const identicalEvent = scan.envelopes.find((envelope) => envelope.event.eventId === parsedEvent.eventId);
560
+ if (identicalEvent) {
561
+ if (canonicalJson(identicalEvent.event) === canonicalJson(parsedEvent))
562
+ return identicalEvent;
563
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit event identity was reused with conflicting facts.");
564
+ }
565
+ if (parsedEvent.schemaVersion === 2 && parsedEvent.eventType === "execution") {
566
+ const existingTerminal = scan.envelopes.find((envelope) => (envelope.event.schemaVersion === 2 &&
567
+ envelope.event.eventType === "execution" &&
568
+ envelope.event.authorizationEventId === parsedEvent.authorizationEventId));
569
+ if (existingTerminal) {
570
+ if (canonicalJson(existingTerminal.event) === canonicalJson(parsedEvent))
571
+ return existingTerminal;
572
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Authorization already has a conflicting terminal audit event.");
573
+ }
574
+ }
575
+ if (parsedEvent.schemaVersion === 4 && parsedEvent.eventType === "terminal") {
576
+ const authorizationEnvelope = scan.envelopes.find((envelope) => (envelope.event.schemaVersion === 4 &&
577
+ envelope.event.eventType === "authorization" &&
578
+ envelope.event.eventId === parsedEvent.authorizationEventId));
579
+ if (!authorizationEnvelope || authorizationEnvelope.event.schemaVersion !== 4 || authorizationEnvelope.event.eventType !== "authorization") {
580
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "V4 terminal audit references missing authorization evidence.");
581
+ }
582
+ const authorization = authorizationEnvelope.event;
583
+ if (authorization.requestId !== parsedEvent.requestId ||
584
+ authorization.decisionId !== parsedEvent.decisionId ||
585
+ authorization.toolName !== parsedEvent.toolName ||
586
+ authorization.canonicalAction !== parsedEvent.canonicalAction ||
587
+ authorization.workspaceId !== parsedEvent.workspaceId ||
588
+ authorization.policyRevision !== parsedEvent.policyRevision ||
589
+ authorization.subjectFingerprint !== parsedEvent.subjectFingerprint ||
590
+ authorization.contextFingerprint !== parsedEvent.contextFingerprint ||
591
+ authorization.repositoryId !== parsedEvent.repositoryId ||
592
+ authorization.taskWorktreeId !== parsedEvent.taskWorktreeId ||
593
+ (parsedEvent.status !== "not_executed" && authorization.outcome !== "allow")) {
594
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "V4 terminal audit does not match its authorization evidence.");
595
+ }
596
+ const existingTerminal = scan.envelopes.find((envelope) => (envelope.event.schemaVersion === 4 &&
597
+ envelope.event.eventType === "terminal" &&
598
+ (envelope.event.authorizationEventId === parsedEvent.authorizationEventId ||
599
+ envelope.event.operationId === parsedEvent.operationId)));
600
+ if (existingTerminal) {
601
+ if (canonicalJson(existingTerminal.event) === canonicalJson(parsedEvent))
602
+ return existingTerminal;
603
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "V4 authorization or operation already has conflicting terminal audit evidence.");
604
+ }
605
+ }
606
+ const date = this.timestamp().slice(0, 10);
607
+ let segmentId = index.activeSegmentId;
608
+ let create = segmentId === null;
609
+ if (!segmentId)
610
+ segmentId = this.nextSegmentId(date);
611
+ if (!create) {
612
+ const active = index.segments.find((segment) => segment.segmentId === segmentId);
613
+ if (!active) {
614
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit active segment metadata is missing.");
615
+ }
616
+ const activeFile = path.join(this.segmentsDirectory, active.fileName);
617
+ const dateRotation = segmentDate(segmentId) !== date;
618
+ const sizeRotation = fs.statSync(activeFile).size + this.estimateEnvelopeBytes(index, parsedEvent, segmentId) > this.maxSegmentBytes;
619
+ if (dateRotation || sizeRotation) {
620
+ const rotation = this.appendEnvelope(index, this.rotationEvent(active, dateRotation ? "utc_date" : "size_limit"), segmentId, false);
621
+ index = rotation.index;
622
+ segmentId = this.nextSegmentId(date);
623
+ create = true;
624
+ }
625
+ }
626
+ return this.appendEnvelope(index, parsedEvent, segmentId, create).envelope;
627
+ }
628
+ catch (error) {
629
+ if (error instanceof AuditError && (error.code === "AUDIT_INTEGRITY_FAILURE" || error.code === "AUDIT_RECORD_INVALID")) {
630
+ this.markIntegrityFailure();
631
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit evidence failed integrity verification.");
632
+ }
633
+ if (error instanceof AuditError)
634
+ throw error;
635
+ throw new AuditError("AUDIT_UNAVAILABLE", "Audit append failed safely.");
636
+ }
637
+ });
638
+ }
639
+ async verify() {
640
+ return this.withWriterLock(() => {
641
+ try {
642
+ return this.loadVerifiedState(true).scan.envelopes;
643
+ }
644
+ catch (error) {
645
+ if (error instanceof AuditError && (error.code === "AUDIT_INTEGRITY_FAILURE" || error.code === "AUDIT_RECORD_INVALID")) {
646
+ this.markIntegrityFailure();
647
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit evidence failed integrity verification.");
648
+ }
649
+ throw error;
650
+ }
651
+ });
652
+ }
653
+ async runRetention() {
654
+ return this.withWriterLock(() => {
655
+ try {
656
+ let { index } = this.loadVerifiedState(true);
657
+ const closed = index.segments.filter((segment) => segment.state === "closed");
658
+ if (closed.length === 0 || !index.activeSegmentId)
659
+ return [];
660
+ const cutoff = this.now() - this.retention.maxAgeDays * 24 * 60 * 60 * 1000;
661
+ let ageCount = 0;
662
+ while (ageCount < closed.length && Date.parse(closed[ageCount].lastTimestamp) < cutoff)
663
+ ageCount += 1;
664
+ let totalClosedBytes = closed.reduce((total, segment) => total + segment.byteSize, 0);
665
+ let sizeCount = 0;
666
+ while (sizeCount < closed.length && totalClosedBytes > this.retention.maxClosedBytes) {
667
+ totalClosedBytes -= closed[sizeCount].byteSize;
668
+ sizeCount += 1;
669
+ }
670
+ const selected = closed.slice(0, Math.max(ageCount, sizeCount));
671
+ if (selected.length === 0)
672
+ return [];
673
+ const tombstone = {
674
+ ...this.commonAdministrative("retention_prune", "audit_retention_prune"),
675
+ segmentIds: selected.map((segment) => segment.segmentId),
676
+ firstSequence: selected[0].firstSequence,
677
+ lastSequence: selected.at(-1).lastSequence,
678
+ firstTimestamp: selected[0].firstTimestamp,
679
+ lastTimestamp: selected.at(-1).lastTimestamp,
680
+ recordCount: selected.reduce((total, segment) => total + segment.recordCount, 0),
681
+ firstMac: selected[0].firstMac,
682
+ lastMac: selected.at(-1).lastMac,
683
+ policyReason: ageCount > 0 && sizeCount > 0
684
+ ? "age_and_size"
685
+ : ageCount > 0
686
+ ? "age"
687
+ : "size",
688
+ resultCode: "PRUNE_AUTHORIZED"
689
+ };
690
+ index = this.appendEnvelope(index, tombstone, index.activeSegmentId, false).index;
691
+ const selectedIds = new Set(selected.map((segment) => segment.segmentId));
692
+ index = {
693
+ ...index,
694
+ segments: index.segments.map((segment) => selectedIds.has(segment.segmentId)
695
+ ? { ...segment, state: "delete_pending" }
696
+ : segment)
697
+ };
698
+ this.writeIndex(index);
699
+ const deleted = [];
700
+ for (const segment of selected) {
701
+ try {
702
+ fs.unlinkSync(path.join(this.segmentsDirectory, segment.fileName));
703
+ syncDirectoryBestEffort(this.segmentsDirectory);
704
+ deleted.push(segment.segmentId);
705
+ }
706
+ catch {
707
+ break;
708
+ }
709
+ }
710
+ index = this.reconcilePendingDeletion(index);
711
+ const scan = this.scanSegments(index.chainAnchorSequence, index.chainAnchorMac, false);
712
+ compareIndexWithScan(index, scan);
713
+ const current = this.indexFromScan(scan, index);
714
+ this.writeIndex(current);
715
+ if (deleted.length !== selected.length) {
716
+ throw new AuditError("AUDIT_UNAVAILABLE", "Audit retention deletion remains pending.");
717
+ }
718
+ return deleted;
719
+ }
720
+ catch (error) {
721
+ if (error instanceof AuditError && (error.code === "AUDIT_INTEGRITY_FAILURE" || error.code === "AUDIT_RECORD_INVALID")) {
722
+ this.markIntegrityFailure();
723
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit evidence failed integrity verification.");
724
+ }
725
+ if (error instanceof AuditError)
726
+ throw error;
727
+ throw new AuditError("AUDIT_UNAVAILABLE", "Audit retention failed safely.");
728
+ }
729
+ });
730
+ }
731
+ encodeCursor(filterDigest, lastSequence) {
732
+ const payload = {
733
+ version: 1,
734
+ filterDigest,
735
+ lastSequence,
736
+ expiresAt: new Date(this.now() + 15 * 60 * 1000).toISOString()
737
+ };
738
+ const encoded = Buffer.from(canonicalJson(payload), "utf8").toString("base64url");
739
+ const mac = createHmac("sha256", this.cursorKey).update(encoded, "utf8").digest("hex");
740
+ return `${encoded}.${mac}`;
741
+ }
742
+ decodeCursor(cursor, filterDigest) {
743
+ try {
744
+ const [encoded, suppliedMac, extra] = cursor.split(".");
745
+ if (!encoded || !suppliedMac || extra !== undefined || !/^[a-f0-9]{64}$/.test(suppliedMac)) {
746
+ throw new Error("invalid shape");
747
+ }
748
+ const expectedMac = createHmac("sha256", this.cursorKey).update(encoded, "utf8").digest("hex");
749
+ const supplied = Buffer.from(suppliedMac, "hex");
750
+ const expected = Buffer.from(expectedMac, "hex");
751
+ if (supplied.length !== expected.length || !timingSafeEqual(supplied, expected)) {
752
+ throw new Error("invalid mac");
753
+ }
754
+ const payload = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
755
+ if (payload.version !== 1 ||
756
+ payload.filterDigest !== filterDigest ||
757
+ !Number.isSafeInteger(payload.lastSequence) ||
758
+ Number(payload.lastSequence) < 1 ||
759
+ typeof payload.expiresAt !== "string" ||
760
+ !Number.isFinite(Date.parse(payload.expiresAt)) ||
761
+ Date.parse(payload.expiresAt) < this.now() ||
762
+ Object.keys(payload).sort().join(",") !== "expiresAt,filterDigest,lastSequence,version") {
763
+ throw new Error("invalid payload");
764
+ }
765
+ return Number(payload.lastSequence);
766
+ }
767
+ catch {
768
+ throw new AuditError("AUDIT_CURSOR_INVALID", "Audit query cursor is invalid or expired.");
769
+ }
770
+ }
771
+ encodeCursorV3(filterDigest, lastSequence) {
772
+ const payload = {
773
+ projectionVersion: 3,
774
+ filterDigest,
775
+ lastSequence,
776
+ expiresAt: new Date(this.now() + 15 * 60 * 1000).toISOString()
777
+ };
778
+ const encoded = Buffer.from(canonicalJson(payload), "utf8").toString("base64url");
779
+ const mac = createHmac("sha256", this.cursorKeyV3).update(encoded, "utf8").digest("hex");
780
+ return `${encoded}.${mac}`;
781
+ }
782
+ decodeCursorV3(cursor, filterDigest) {
783
+ try {
784
+ const [encoded, suppliedMac, extra] = cursor.split(".");
785
+ if (!encoded || !suppliedMac || extra !== undefined || !/^[a-f0-9]{64}$/.test(suppliedMac)) {
786
+ throw new Error("invalid shape");
787
+ }
788
+ const expectedMac = createHmac("sha256", this.cursorKeyV3).update(encoded, "utf8").digest("hex");
789
+ const supplied = Buffer.from(suppliedMac, "hex");
790
+ const expected = Buffer.from(expectedMac, "hex");
791
+ if (supplied.length !== expected.length || !timingSafeEqual(supplied, expected)) {
792
+ throw new Error("invalid mac");
793
+ }
794
+ const payload = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
795
+ if (payload.projectionVersion !== 3 ||
796
+ payload.filterDigest !== filterDigest ||
797
+ !Number.isSafeInteger(payload.lastSequence) ||
798
+ Number(payload.lastSequence) < 1 ||
799
+ typeof payload.expiresAt !== "string" ||
800
+ !Number.isFinite(Date.parse(payload.expiresAt)) ||
801
+ Date.parse(payload.expiresAt) < this.now() ||
802
+ Object.keys(payload).sort().join(",") !== "expiresAt,filterDigest,lastSequence,projectionVersion") {
803
+ throw new Error("invalid payload");
804
+ }
805
+ return Number(payload.lastSequence);
806
+ }
807
+ catch {
808
+ throw new AuditError("AUDIT_CURSOR_INVALID", "Audit query cursor is invalid or expired.");
809
+ }
810
+ }
811
+ encodeCursorV4(filterDigest, lastSequence) {
812
+ const payload = {
813
+ projectionVersion: 4,
814
+ filterDigest,
815
+ lastSequence,
816
+ expiresAt: new Date(this.now() + 15 * 60 * 1000).toISOString()
817
+ };
818
+ const encoded = Buffer.from(canonicalJson(payload), "utf8").toString("base64url");
819
+ const mac = createHmac("sha256", this.cursorKeyV4)
820
+ .update("audit-query-v4-cursor\0", "utf8")
821
+ .update(encoded, "utf8")
822
+ .digest("hex");
823
+ return `v4:${encoded}.${mac}`;
824
+ }
825
+ decodeCursorV4(cursor, filterDigest) {
826
+ try {
827
+ if (!cursor.startsWith("v4:"))
828
+ throw new Error("invalid version");
829
+ const [encoded, suppliedMac, extra] = cursor.slice(3).split(".");
830
+ if (!encoded || !suppliedMac || extra !== undefined || !/^[a-f0-9]{64}$/.test(suppliedMac)) {
831
+ throw new Error("invalid shape");
832
+ }
833
+ const expectedMac = createHmac("sha256", this.cursorKeyV4)
834
+ .update("audit-query-v4-cursor\0", "utf8")
835
+ .update(encoded, "utf8")
836
+ .digest("hex");
837
+ const supplied = Buffer.from(suppliedMac, "hex");
838
+ const expected = Buffer.from(expectedMac, "hex");
839
+ if (supplied.length !== expected.length || !timingSafeEqual(supplied, expected))
840
+ throw new Error("invalid mac");
841
+ const payload = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
842
+ if (payload.projectionVersion !== 4 ||
843
+ payload.filterDigest !== filterDigest ||
844
+ !Number.isSafeInteger(payload.lastSequence) ||
845
+ Number(payload.lastSequence) < 1 ||
846
+ typeof payload.expiresAt !== "string" ||
847
+ !Number.isFinite(Date.parse(payload.expiresAt)) ||
848
+ Date.parse(payload.expiresAt) < this.now() ||
849
+ Object.keys(payload).sort().join(",") !== "expiresAt,filterDigest,lastSequence,projectionVersion")
850
+ throw new Error("invalid payload");
851
+ return Number(payload.lastSequence);
852
+ }
853
+ catch {
854
+ throw new AuditError("AUDIT_CURSOR_INVALID", "V4 audit query cursor is invalid or expired.");
855
+ }
856
+ }
857
+ projectEventV4(event) {
858
+ if (event.schemaVersion === 5) {
859
+ return {
860
+ schemaVersion: 4,
861
+ sourceSchemaVersion: 5,
862
+ sourceContractVersion: 5,
863
+ eventId: event.eventId,
864
+ timestamp: event.timestamp,
865
+ eventType: event.eventType,
866
+ requestId: event.requestId,
867
+ toolName: event.toolName,
868
+ canonicalAction: event.canonicalAction,
869
+ repositoryId: null,
870
+ taskWorktreeId: null,
871
+ subjectFingerprint: event.subjectFingerprint,
872
+ contextFingerprint: event.contextFingerprint,
873
+ resultCode: event.resultCode,
874
+ counts: event.counts
875
+ };
876
+ }
877
+ if (event.schemaVersion === 4) {
878
+ return {
879
+ schemaVersion: 4,
880
+ sourceSchemaVersion: 4,
881
+ sourceContractVersion: 4,
882
+ eventId: event.eventId,
883
+ timestamp: event.timestamp,
884
+ eventType: event.eventType,
885
+ requestId: event.requestId,
886
+ toolName: event.toolName,
887
+ canonicalAction: event.canonicalAction,
888
+ repositoryId: event.repositoryId,
889
+ taskWorktreeId: event.taskWorktreeId,
890
+ subjectFingerprint: event.subjectFingerprint,
891
+ contextFingerprint: event.contextFingerprint,
892
+ resultCode: event.resultCode,
893
+ counts: event.counts
894
+ };
895
+ }
896
+ if (event.schemaVersion === 3) {
897
+ return {
898
+ schemaVersion: 4,
899
+ sourceSchemaVersion: 3,
900
+ sourceContractVersion: 3,
901
+ eventId: event.eventId,
902
+ timestamp: event.timestamp,
903
+ eventType: event.eventType,
904
+ requestId: event.requestId,
905
+ toolName: event.toolName,
906
+ canonicalAction: event.canonicalAction,
907
+ repositoryId: null,
908
+ taskWorktreeId: null,
909
+ subjectFingerprint: event.subjectFingerprint,
910
+ contextFingerprint: event.contextFingerprint,
911
+ resultCode: event.resultCode,
912
+ counts: event.counts
913
+ };
914
+ }
915
+ let resultCode = null;
916
+ let counts = {};
917
+ if (event.eventType === "authorization")
918
+ resultCode = event.reasonCode;
919
+ else if (event.eventType === "execution") {
920
+ resultCode = event.resultCode;
921
+ counts = event.boundedByteCounts;
922
+ }
923
+ else if (event.eventType === "recovery") {
924
+ resultCode = event.resultCode;
925
+ counts = { operationCount: event.operationCount };
926
+ }
927
+ else {
928
+ resultCode = event.resultCode;
929
+ counts = event.resultCount === null ? {} : { resultCount: event.resultCount };
930
+ }
931
+ return {
932
+ schemaVersion: 4,
933
+ sourceSchemaVersion: 2,
934
+ sourceContractVersion: null,
935
+ eventId: event.eventId,
936
+ timestamp: event.timestamp,
937
+ eventType: event.eventType,
938
+ requestId: event.requestId,
939
+ toolName: event.toolName,
940
+ canonicalAction: event.canonicalAction,
941
+ repositoryId: null,
942
+ taskWorktreeId: null,
943
+ subjectFingerprint: null,
944
+ contextFingerprint: null,
945
+ resultCode,
946
+ counts
947
+ };
948
+ }
949
+ async probeIntegrity() {
950
+ await this.withWriterLock(() => {
951
+ try {
952
+ const index = this.readIndex();
953
+ const scan = this.scanSegments(index.chainAnchorSequence, index.chainAnchorMac, false);
954
+ compareIndexWithScan(index, scan);
955
+ }
956
+ catch (error) {
957
+ if (error instanceof AuditError && error.code === "AUDIT_RECORD_INVALID") {
958
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit tail verification failed.");
959
+ }
960
+ throw error;
961
+ }
962
+ });
963
+ }
964
+ async query(input) {
965
+ const parsedResult = queryAuditEventsInputV2Schema.safeParse(input);
966
+ if (!parsedResult.success) {
967
+ throw new AuditError(input && typeof input === "object" && "cursor" in input
968
+ ? "AUDIT_CURSOR_INVALID"
969
+ : "AUDIT_RANGE_INVALID", "Audit query input is invalid.");
970
+ }
971
+ const parsed = parsedResult.data;
972
+ const limit = parsed.limit ?? 50;
973
+ const endMs = parsed.endTime === undefined ? this.now() : Date.parse(parsed.endTime);
974
+ const startMs = parsed.startTime === undefined
975
+ ? endMs - 24 * 60 * 60 * 1000
976
+ : Date.parse(parsed.startTime);
977
+ if (!Number.isFinite(startMs) ||
978
+ !Number.isFinite(endMs) ||
979
+ startMs > endMs ||
980
+ endMs - startMs > 7 * 24 * 60 * 60 * 1000) {
981
+ throw new AuditError("AUDIT_RANGE_INVALID", "Audit query range is invalid or exceeds seven days.");
982
+ }
983
+ const filterDigest = auditQueryFilterDigest({ ...parsed, limit });
984
+ const beforeSequence = parsed.cursor === undefined
985
+ ? Number.POSITIVE_INFINITY
986
+ : this.decodeCursor(parsed.cursor, filterDigest);
987
+ const eventTypes = parsed.eventTypes ? new Set(parsed.eventTypes) : null;
988
+ const toolNames = parsed.toolNames ? new Set(parsed.toolNames) : null;
989
+ const requestIds = parsed.requestIds ? new Set(parsed.requestIds) : null;
990
+ const changeSetIds = parsed.changeSetIds ? new Set(parsed.changeSetIds) : null;
991
+ const workspaceRefs = parsed.workspaceRefs ? new Set(parsed.workspaceRefs) : null;
992
+ const statuses = parsed.statuses ? new Set(parsed.statuses) : null;
993
+ return this.withWriterLock(() => {
994
+ try {
995
+ const { index, scan } = this.loadVerifiedState(true);
996
+ const matched = scan.envelopes
997
+ .filter((envelope) => envelope.event.schemaVersion === 2)
998
+ .filter((envelope) => {
999
+ const event = envelope.event;
1000
+ const timestamp = Date.parse(event.timestamp);
1001
+ if (envelope.sequence >= beforeSequence || timestamp < startMs || timestamp > endMs)
1002
+ return false;
1003
+ if (eventTypes && !eventTypes.has(event.eventType))
1004
+ return false;
1005
+ if (toolNames && (event.toolName === null || !toolNames.has(event.toolName)))
1006
+ return false;
1007
+ if (requestIds && (event.requestId === null || !requestIds.has(event.requestId)))
1008
+ return false;
1009
+ if (workspaceRefs && (event.workspaceRef === null || !workspaceRefs.has(event.workspaceRef)))
1010
+ return false;
1011
+ if (changeSetIds) {
1012
+ if (event.eventType !== "execution" && event.eventType !== "recovery")
1013
+ return false;
1014
+ if (event.changeSetId === null || !changeSetIds.has(event.changeSetId))
1015
+ return false;
1016
+ }
1017
+ if (statuses) {
1018
+ if (event.eventType !== "execution" || !statuses.has(event.status))
1019
+ return false;
1020
+ }
1021
+ return true;
1022
+ })
1023
+ .sort((left, right) => right.sequence - left.sequence);
1024
+ const page = matched.slice(0, limit);
1025
+ const nextCursor = matched.length > limit && page.length > 0
1026
+ ? this.encodeCursor(filterDigest, page.at(-1).sequence)
1027
+ : null;
1028
+ return {
1029
+ schemaVersion: 2,
1030
+ records: page.map((envelope) => ({ sequence: envelope.sequence, event: envelope.event })),
1031
+ nextCursor,
1032
+ filterDigest,
1033
+ startTime: new Date(startMs).toISOString(),
1034
+ endTime: new Date(endMs).toISOString(),
1035
+ limit,
1036
+ integrityState: index.state
1037
+ };
1038
+ }
1039
+ catch (error) {
1040
+ if (error instanceof AuditError && (error.code === "AUDIT_INTEGRITY_FAILURE" || error.code === "AUDIT_RECORD_INVALID")) {
1041
+ this.markIntegrityFailure();
1042
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit evidence failed integrity verification.");
1043
+ }
1044
+ throw error;
1045
+ }
1046
+ });
1047
+ }
1048
+ async queryV3(input) {
1049
+ const parsedResult = queryAuditEventsInputV3Schema.safeParse(input);
1050
+ if (!parsedResult.success) {
1051
+ throw new AuditError(input && typeof input === "object" && "cursor" in input
1052
+ ? "AUDIT_CURSOR_INVALID"
1053
+ : "AUDIT_RANGE_INVALID", "Audit query input is invalid.");
1054
+ }
1055
+ const parsed = parsedResult.data;
1056
+ const limit = parsed.limit ?? 50;
1057
+ const endMs = parsed.endTime === undefined ? this.now() : Date.parse(parsed.endTime);
1058
+ const startMs = parsed.startTime === undefined
1059
+ ? endMs - 24 * 60 * 60 * 1000
1060
+ : Date.parse(parsed.startTime);
1061
+ if (!Number.isFinite(startMs) ||
1062
+ !Number.isFinite(endMs) ||
1063
+ startMs > endMs ||
1064
+ endMs - startMs > 7 * 24 * 60 * 60 * 1000) {
1065
+ throw new AuditError("AUDIT_RANGE_INVALID", "Audit query range is invalid or exceeds seven days.");
1066
+ }
1067
+ const filterDigest = auditQueryFilterDigestV3({ ...parsed, limit });
1068
+ const beforeSequence = parsed.cursor === undefined
1069
+ ? Number.POSITIVE_INFINITY
1070
+ : this.decodeCursorV3(parsed.cursor, filterDigest);
1071
+ const eventTypes = parsed.eventTypes ? new Set(parsed.eventTypes) : null;
1072
+ const toolNames = parsed.toolNames ? new Set(parsed.toolNames) : null;
1073
+ const requestIds = parsed.requestIds ? new Set(parsed.requestIds) : null;
1074
+ const changeSetIds = parsed.changeSetIds ? new Set(parsed.changeSetIds) : null;
1075
+ const workspaceRefs = parsed.workspaceRefs ? new Set(parsed.workspaceRefs) : null;
1076
+ const statuses = parsed.statuses ? new Set(parsed.statuses) : null;
1077
+ return this.withWriterLock(() => {
1078
+ try {
1079
+ const { index, scan } = this.loadVerifiedState(true);
1080
+ const matched = scan.envelopes
1081
+ .filter((envelope) => envelope.event.schemaVersion === 2 || envelope.event.schemaVersion === 3)
1082
+ .filter((envelope) => {
1083
+ const event = envelope.event;
1084
+ const timestamp = Date.parse(event.timestamp);
1085
+ if (envelope.sequence >= beforeSequence || timestamp < startMs || timestamp > endMs)
1086
+ return false;
1087
+ if (eventTypes && !eventTypes.has(event.eventType))
1088
+ return false;
1089
+ if (toolNames && (event.toolName === null || !toolNames.has(event.toolName)))
1090
+ return false;
1091
+ if (requestIds && (event.requestId === null || !requestIds.has(event.requestId)))
1092
+ return false;
1093
+ if (workspaceRefs && (event.workspaceRef === null || !workspaceRefs.has(event.workspaceRef)))
1094
+ return false;
1095
+ if (changeSetIds) {
1096
+ if (event.schemaVersion !== 2 ||
1097
+ (event.eventType !== "execution" && event.eventType !== "recovery"))
1098
+ return false;
1099
+ if (event.changeSetId === null || !changeSetIds.has(event.changeSetId))
1100
+ return false;
1101
+ }
1102
+ if (statuses) {
1103
+ if (event.schemaVersion !== 2 || event.eventType !== "execution" || !statuses.has(event.status))
1104
+ return false;
1105
+ }
1106
+ return true;
1107
+ })
1108
+ .sort((left, right) => right.sequence - left.sequence);
1109
+ const page = matched.slice(0, limit);
1110
+ const nextCursor = matched.length > limit && page.length > 0
1111
+ ? this.encodeCursorV3(filterDigest, page.at(-1).sequence)
1112
+ : null;
1113
+ return {
1114
+ schemaVersion: 3,
1115
+ records: page.map((envelope) => ({ sequence: envelope.sequence, event: envelope.event })),
1116
+ nextCursor,
1117
+ filterDigest,
1118
+ startTime: new Date(startMs).toISOString(),
1119
+ endTime: new Date(endMs).toISOString(),
1120
+ limit,
1121
+ integrityState: index.state
1122
+ };
1123
+ }
1124
+ catch (error) {
1125
+ if (error instanceof AuditError && (error.code === "AUDIT_INTEGRITY_FAILURE" || error.code === "AUDIT_RECORD_INVALID")) {
1126
+ this.markIntegrityFailure();
1127
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit evidence failed integrity verification.");
1128
+ }
1129
+ throw error;
1130
+ }
1131
+ });
1132
+ }
1133
+ async queryV4(input) {
1134
+ const parsedResult = queryAuditEventsInputV4Schema.safeParse(input);
1135
+ if (!parsedResult.success) {
1136
+ throw new AuditError(input && typeof input === "object" && "cursor" in input
1137
+ ? "AUDIT_CURSOR_INVALID"
1138
+ : "AUDIT_RANGE_INVALID", "V4 audit query input is invalid.");
1139
+ }
1140
+ const parsed = parsedResult.data;
1141
+ const limit = parsed.limit ?? 50;
1142
+ const endMs = parsed.endTime === undefined ? this.now() : Date.parse(parsed.endTime);
1143
+ const startMs = parsed.startTime === undefined
1144
+ ? endMs - 24 * 60 * 60 * 1000
1145
+ : Date.parse(parsed.startTime);
1146
+ if (!Number.isFinite(startMs) ||
1147
+ !Number.isFinite(endMs) ||
1148
+ startMs > endMs ||
1149
+ endMs - startMs > 7 * 24 * 60 * 60 * 1000) {
1150
+ throw new AuditError("AUDIT_RANGE_INVALID", "V4 audit query range is invalid or exceeds seven days.");
1151
+ }
1152
+ const filterDigest = auditQueryFilterDigestV4({ ...parsed, limit });
1153
+ const beforeSequence = parsed.cursor === undefined
1154
+ ? Number.POSITIVE_INFINITY
1155
+ : this.decodeCursorV4(parsed.cursor, filterDigest);
1156
+ const eventTypes = parsed.eventTypes ? new Set(parsed.eventTypes) : null;
1157
+ const toolNames = parsed.toolNames ? new Set(parsed.toolNames) : null;
1158
+ const requestIds = parsed.requestIds ? new Set(parsed.requestIds) : null;
1159
+ const repositoryIds = parsed.repositoryIds ? new Set(parsed.repositoryIds) : null;
1160
+ const taskWorktreeIds = parsed.taskWorktreeIds ? new Set(parsed.taskWorktreeIds) : null;
1161
+ const resultCodes = parsed.resultCodes ? new Set(parsed.resultCodes) : null;
1162
+ return this.withWriterLock(() => {
1163
+ try {
1164
+ const { index, scan } = this.loadVerifiedState(true);
1165
+ const matched = scan.envelopes
1166
+ .filter((envelope) => {
1167
+ const projected = this.projectEventV4(envelope.event);
1168
+ const timestamp = Date.parse(projected.timestamp);
1169
+ if (envelope.sequence >= beforeSequence || timestamp < startMs || timestamp > endMs)
1170
+ return false;
1171
+ if (eventTypes && !eventTypes.has(projected.eventType))
1172
+ return false;
1173
+ if (toolNames && (projected.toolName === null || !toolNames.has(projected.toolName)))
1174
+ return false;
1175
+ if (requestIds && (projected.requestId === null || !requestIds.has(projected.requestId)))
1176
+ return false;
1177
+ if (repositoryIds && (projected.repositoryId === null || !repositoryIds.has(projected.repositoryId)))
1178
+ return false;
1179
+ if (taskWorktreeIds && (projected.taskWorktreeId === null || !taskWorktreeIds.has(projected.taskWorktreeId)))
1180
+ return false;
1181
+ if (resultCodes && (projected.resultCode === null || !resultCodes.has(projected.resultCode)))
1182
+ return false;
1183
+ return true;
1184
+ })
1185
+ .sort((left, right) => right.sequence - left.sequence);
1186
+ const page = matched.slice(0, limit);
1187
+ const nextCursor = matched.length > limit && page.length > 0
1188
+ ? this.encodeCursorV4(filterDigest, page.at(-1).sequence)
1189
+ : null;
1190
+ return {
1191
+ schemaVersion: 4,
1192
+ records: page.map((envelope) => ({
1193
+ sequence: envelope.sequence,
1194
+ event: this.projectEventV4(envelope.event)
1195
+ })),
1196
+ nextCursor,
1197
+ filterDigest,
1198
+ startTime: new Date(startMs).toISOString(),
1199
+ endTime: new Date(endMs).toISOString(),
1200
+ limit,
1201
+ integrityState: index.state
1202
+ };
1203
+ }
1204
+ catch (error) {
1205
+ if (error instanceof AuditError && (error.code === "AUDIT_INTEGRITY_FAILURE" || error.code === "AUDIT_RECORD_INVALID")) {
1206
+ this.markIntegrityFailure();
1207
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit evidence failed integrity verification.");
1208
+ }
1209
+ throw error;
1210
+ }
1211
+ });
1212
+ }
1213
+ async findTerminalEventV4(operationId) {
1214
+ if (!/^gop_[a-f0-9]{32}$/u.test(operationId)) {
1215
+ throw new AuditError("AUDIT_RANGE_INVALID", "V4 operation identity is invalid.");
1216
+ }
1217
+ return this.withWriterLock(() => {
1218
+ try {
1219
+ const { scan } = this.loadVerifiedState(true);
1220
+ const matches = scan.envelopes.filter((envelope) => envelope.event.schemaVersion === 4 &&
1221
+ envelope.event.eventType === "terminal" &&
1222
+ envelope.event.operationId === operationId);
1223
+ if (matches.length > 1) {
1224
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "V4 operation has conflicting terminal evidence.");
1225
+ }
1226
+ return matches[0]?.event.eventId ?? null;
1227
+ }
1228
+ catch (error) {
1229
+ if (error instanceof AuditError && (error.code === "AUDIT_INTEGRITY_FAILURE" || error.code === "AUDIT_RECORD_INVALID")) {
1230
+ this.markIntegrityFailure();
1231
+ throw new AuditError("AUDIT_INTEGRITY_FAILURE", "Audit evidence failed integrity verification.");
1232
+ }
1233
+ throw error;
1234
+ }
1235
+ });
1236
+ }
1237
+ async probeExecutionParticipant(changeSetId) {
1238
+ if (!/^cs_[a-f0-9]{32}$/.test(changeSetId))
1239
+ return "unknown";
1240
+ try {
1241
+ const records = await this.verify();
1242
+ return records.some((envelope) => envelope.event.eventType === "execution" &&
1243
+ envelope.event.changeSetId === changeSetId &&
1244
+ envelope.event.status === "succeeded") ? "present" : "absent";
1245
+ }
1246
+ catch {
1247
+ return "unknown";
1248
+ }
1249
+ }
1250
+ async recordTransactionRecovery(input) {
1251
+ const eventId = `event_${createHash("sha256").update(`${input.transactionId}\0${input.action}\0${input.resultCode}`, "utf8").digest("hex").slice(0, 32)}`;
1252
+ await this.append({
1253
+ schemaVersion: 2,
1254
+ eventId,
1255
+ eventType: "recovery",
1256
+ timestamp: input.timestamp,
1257
+ requestId: null,
1258
+ authorizationEventId: null,
1259
+ decisionId: null,
1260
+ credentialRef: null,
1261
+ transportSessionId: null,
1262
+ toolName: null,
1263
+ canonicalAction: "transaction_recovery",
1264
+ workspaceId: null,
1265
+ workspaceRef: null,
1266
+ policyRevision: null,
1267
+ recoveryAction: input.action,
1268
+ transactionId: input.transactionId,
1269
+ changeSetId: input.changeSetId,
1270
+ operationCount: input.operationCount,
1271
+ resultCode: input.resultCode
1272
+ });
1273
+ }
1274
+ async recordQuery(filterDigest, resultCount) {
1275
+ if (!/^[a-f0-9]{64}$/.test(filterDigest) || !Number.isSafeInteger(resultCount) || resultCount < 0 || resultCount > 100) {
1276
+ throw new AuditError("AUDIT_RECORD_INVALID", "Audit query summary is invalid.");
1277
+ }
1278
+ await this.append({
1279
+ ...this.commonAdministrative("audit_query", "audit_query_events"),
1280
+ filterDigest,
1281
+ resultCount,
1282
+ resultCode: "OK"
1283
+ });
1284
+ }
1285
+ diagnostics() {
1286
+ try {
1287
+ const index = this.readIndex();
1288
+ return {
1289
+ state: index.state,
1290
+ activeSegmentId: index.activeSegmentId,
1291
+ lastCommittedSequence: index.lastSequence,
1292
+ lastSuccessfulAppendTime: index.lastAppendAt,
1293
+ retention: { ...this.retention },
1294
+ failureCode: index.failureCode
1295
+ };
1296
+ }
1297
+ catch {
1298
+ return {
1299
+ state: "integrity_failed",
1300
+ activeSegmentId: null,
1301
+ lastCommittedSequence: 0,
1302
+ lastSuccessfulAppendTime: null,
1303
+ retention: { ...this.retention },
1304
+ failureCode: "AUDIT_INTEGRITY_FAILURE"
1305
+ };
1306
+ }
1307
+ }
1308
+ }
1309
+ //# sourceMappingURL=store.js.map