@intutic/cli 1.10.0 → 2.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 (357) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +868 -30
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/attenuate.d.ts +39 -0
  5. package/dist/commands/attenuate.d.ts.map +1 -0
  6. package/dist/commands/attenuate.js +98 -0
  7. package/dist/commands/attenuate.js.map +1 -0
  8. package/dist/commands/budget.d.ts +80 -0
  9. package/dist/commands/budget.d.ts.map +1 -1
  10. package/dist/commands/budget.js +119 -3
  11. package/dist/commands/budget.js.map +1 -1
  12. package/dist/commands/connect.d.ts +10 -0
  13. package/dist/commands/connect.d.ts.map +1 -1
  14. package/dist/commands/connect.js +358 -48
  15. package/dist/commands/connect.js.map +1 -1
  16. package/dist/commands/credentials.d.ts +31 -0
  17. package/dist/commands/credentials.d.ts.map +1 -0
  18. package/dist/commands/credentials.js +134 -0
  19. package/dist/commands/credentials.js.map +1 -0
  20. package/dist/commands/decision.d.ts +37 -0
  21. package/dist/commands/decision.d.ts.map +1 -0
  22. package/dist/commands/decision.js +56 -0
  23. package/dist/commands/decision.js.map +1 -0
  24. package/dist/commands/doctor.d.ts +38 -1
  25. package/dist/commands/doctor.d.ts.map +1 -1
  26. package/dist/commands/doctor.js +228 -18
  27. package/dist/commands/doctor.js.map +1 -1
  28. package/dist/commands/enforce.d.ts +33 -0
  29. package/dist/commands/enforce.d.ts.map +1 -0
  30. package/dist/commands/enforce.js +150 -0
  31. package/dist/commands/enforce.js.map +1 -0
  32. package/dist/commands/enterprise.d.ts +29 -0
  33. package/dist/commands/enterprise.d.ts.map +1 -0
  34. package/dist/commands/enterprise.js +141 -0
  35. package/dist/commands/enterprise.js.map +1 -0
  36. package/dist/commands/env.d.ts +7 -0
  37. package/dist/commands/env.d.ts.map +1 -0
  38. package/dist/commands/env.js +55 -0
  39. package/dist/commands/env.js.map +1 -0
  40. package/dist/commands/exec.d.ts +38 -2
  41. package/dist/commands/exec.d.ts.map +1 -1
  42. package/dist/commands/exec.js +247 -10
  43. package/dist/commands/exec.js.map +1 -1
  44. package/dist/commands/findings.d.ts +84 -0
  45. package/dist/commands/findings.d.ts.map +1 -0
  46. package/dist/commands/findings.js +329 -0
  47. package/dist/commands/findings.js.map +1 -0
  48. package/dist/commands/gateway.d.ts +62 -0
  49. package/dist/commands/gateway.d.ts.map +1 -0
  50. package/dist/commands/gateway.js +298 -0
  51. package/dist/commands/gateway.js.map +1 -0
  52. package/dist/commands/guardrails.d.ts +81 -0
  53. package/dist/commands/guardrails.d.ts.map +1 -0
  54. package/dist/commands/guardrails.js +735 -0
  55. package/dist/commands/guardrails.js.map +1 -0
  56. package/dist/commands/init.d.ts +8 -0
  57. package/dist/commands/init.d.ts.map +1 -1
  58. package/dist/commands/init.js +14 -2
  59. package/dist/commands/init.js.map +1 -1
  60. package/dist/commands/install-daemon.d.ts +70 -3
  61. package/dist/commands/install-daemon.d.ts.map +1 -1
  62. package/dist/commands/install-daemon.js +482 -47
  63. package/dist/commands/install-daemon.js.map +1 -1
  64. package/dist/commands/integrity.d.ts +205 -0
  65. package/dist/commands/integrity.d.ts.map +1 -0
  66. package/dist/commands/integrity.js +620 -0
  67. package/dist/commands/integrity.js.map +1 -0
  68. package/dist/commands/judge.d.ts +31 -0
  69. package/dist/commands/judge.d.ts.map +1 -0
  70. package/dist/commands/judge.js +118 -0
  71. package/dist/commands/judge.js.map +1 -0
  72. package/dist/commands/org.d.ts +31 -0
  73. package/dist/commands/org.d.ts.map +1 -0
  74. package/dist/commands/org.js +159 -0
  75. package/dist/commands/org.js.map +1 -0
  76. package/dist/commands/policy.d.ts +138 -4
  77. package/dist/commands/policy.d.ts.map +1 -1
  78. package/dist/commands/policy.js +538 -97
  79. package/dist/commands/policy.js.map +1 -1
  80. package/dist/commands/predict-cost.d.ts +45 -0
  81. package/dist/commands/predict-cost.d.ts.map +1 -0
  82. package/dist/commands/predict-cost.js +123 -0
  83. package/dist/commands/predict-cost.js.map +1 -0
  84. package/dist/commands/rollback.d.ts +5 -0
  85. package/dist/commands/rollback.d.ts.map +1 -0
  86. package/dist/commands/rollback.js +142 -0
  87. package/dist/commands/rollback.js.map +1 -0
  88. package/dist/commands/routing.d.ts +62 -0
  89. package/dist/commands/routing.d.ts.map +1 -0
  90. package/dist/commands/routing.js +121 -0
  91. package/dist/commands/routing.js.map +1 -0
  92. package/dist/commands/setup.d.ts +62 -0
  93. package/dist/commands/setup.d.ts.map +1 -0
  94. package/dist/commands/setup.js +238 -0
  95. package/dist/commands/setup.js.map +1 -0
  96. package/dist/commands/skill.d.ts +268 -1
  97. package/dist/commands/skill.d.ts.map +1 -1
  98. package/dist/commands/skill.js +744 -39
  99. package/dist/commands/skill.js.map +1 -1
  100. package/dist/commands/sops.d.ts +95 -0
  101. package/dist/commands/sops.d.ts.map +1 -1
  102. package/dist/commands/sops.js +334 -34
  103. package/dist/commands/sops.js.map +1 -1
  104. package/dist/commands/start.d.ts.map +1 -1
  105. package/dist/commands/start.js +1 -18
  106. package/dist/commands/start.js.map +1 -1
  107. package/dist/commands/status.d.ts.map +1 -1
  108. package/dist/commands/status.js +44 -1
  109. package/dist/commands/status.js.map +1 -1
  110. package/dist/commands/team.d.ts +38 -0
  111. package/dist/commands/team.d.ts.map +1 -0
  112. package/dist/commands/team.js +140 -0
  113. package/dist/commands/team.js.map +1 -0
  114. package/dist/commands/traces.d.ts +8 -1
  115. package/dist/commands/traces.d.ts.map +1 -1
  116. package/dist/commands/traces.js +114 -15
  117. package/dist/commands/traces.js.map +1 -1
  118. package/dist/commands/whoami.d.ts.map +1 -1
  119. package/dist/commands/whoami.js +2 -1
  120. package/dist/commands/whoami.js.map +1 -1
  121. package/dist/config/keychain.d.ts +10 -2
  122. package/dist/config/keychain.d.ts.map +1 -1
  123. package/dist/config/keychain.js +83 -14
  124. package/dist/config/keychain.js.map +1 -1
  125. package/dist/config/paths.d.ts +27 -0
  126. package/dist/config/paths.d.ts.map +1 -1
  127. package/dist/config/paths.js +37 -6
  128. package/dist/config/paths.js.map +1 -1
  129. package/dist/config/store.d.ts.map +1 -1
  130. package/dist/config/store.js +19 -3
  131. package/dist/config/store.js.map +1 -1
  132. package/dist/harness/ag2.d.ts +22 -0
  133. package/dist/harness/ag2.d.ts.map +1 -0
  134. package/dist/harness/ag2.js +34 -0
  135. package/dist/harness/ag2.js.map +1 -0
  136. package/dist/harness/agentcore.d.ts +55 -0
  137. package/dist/harness/agentcore.d.ts.map +1 -0
  138. package/dist/harness/agentcore.js +119 -0
  139. package/dist/harness/agentcore.js.map +1 -0
  140. package/dist/harness/agenticOrchestrator.d.ts +52 -0
  141. package/dist/harness/agenticOrchestrator.d.ts.map +1 -0
  142. package/dist/harness/agenticOrchestrator.js +115 -0
  143. package/dist/harness/agenticOrchestrator.js.map +1 -0
  144. package/dist/harness/aiSdkHarness.d.ts +30 -0
  145. package/dist/harness/aiSdkHarness.d.ts.map +1 -0
  146. package/dist/harness/aiSdkHarness.js +51 -0
  147. package/dist/harness/aiSdkHarness.js.map +1 -0
  148. package/dist/harness/aiSdkWorkflow.d.ts +26 -0
  149. package/dist/harness/aiSdkWorkflow.d.ts.map +1 -0
  150. package/dist/harness/aiSdkWorkflow.js +39 -0
  151. package/dist/harness/aiSdkWorkflow.js.map +1 -0
  152. package/dist/harness/autogen.d.ts +24 -0
  153. package/dist/harness/autogen.d.ts.map +1 -0
  154. package/dist/harness/autogen.js +36 -0
  155. package/dist/harness/autogen.js.map +1 -0
  156. package/dist/harness/base.js.map +1 -1
  157. package/dist/harness/continue.d.ts.map +1 -1
  158. package/dist/harness/continue.js +2 -1
  159. package/dist/harness/continue.js.map +1 -1
  160. package/dist/harness/crewai.d.ts +15 -0
  161. package/dist/harness/crewai.d.ts.map +1 -0
  162. package/dist/harness/crewai.js +26 -0
  163. package/dist/harness/crewai.js.map +1 -0
  164. package/dist/harness/detector.d.ts +1 -1
  165. package/dist/harness/detector.d.ts.map +1 -1
  166. package/dist/harness/detector.js +47 -1
  167. package/dist/harness/detector.js.map +1 -1
  168. package/dist/harness/dsh.d.ts +19 -0
  169. package/dist/harness/dsh.d.ts.map +1 -0
  170. package/dist/harness/dsh.js +93 -0
  171. package/dist/harness/dsh.js.map +1 -0
  172. package/dist/harness/eve.d.ts +40 -0
  173. package/dist/harness/eve.d.ts.map +1 -0
  174. package/dist/harness/eve.js +67 -0
  175. package/dist/harness/eve.js.map +1 -0
  176. package/dist/harness/googleAdk.d.ts +18 -0
  177. package/dist/harness/googleAdk.d.ts.map +1 -0
  178. package/dist/harness/googleAdk.js +29 -0
  179. package/dist/harness/googleAdk.js.map +1 -0
  180. package/dist/harness/goose.d.ts.map +1 -1
  181. package/dist/harness/goose.js +5 -1
  182. package/dist/harness/goose.js.map +1 -1
  183. package/dist/harness/grok.d.ts +16 -0
  184. package/dist/harness/grok.d.ts.map +1 -0
  185. package/dist/harness/grok.js +78 -0
  186. package/dist/harness/grok.js.map +1 -0
  187. package/dist/harness/jsSdkGatedAdapter.d.ts +102 -0
  188. package/dist/harness/jsSdkGatedAdapter.d.ts.map +1 -0
  189. package/dist/harness/jsSdkGatedAdapter.js +139 -0
  190. package/dist/harness/jsSdkGatedAdapter.js.map +1 -0
  191. package/dist/harness/langchain.d.ts +22 -0
  192. package/dist/harness/langchain.d.ts.map +1 -0
  193. package/dist/harness/langchain.js +33 -0
  194. package/dist/harness/langchain.js.map +1 -0
  195. package/dist/harness/langgraph.d.ts +22 -0
  196. package/dist/harness/langgraph.d.ts.map +1 -0
  197. package/dist/harness/langgraph.js +80 -0
  198. package/dist/harness/langgraph.js.map +1 -0
  199. package/dist/harness/mastra.d.ts +21 -0
  200. package/dist/harness/mastra.d.ts.map +1 -0
  201. package/dist/harness/mastra.js +33 -0
  202. package/dist/harness/mastra.js.map +1 -0
  203. package/dist/harness/muse.d.ts +22 -0
  204. package/dist/harness/muse.d.ts.map +1 -0
  205. package/dist/harness/muse.js +92 -0
  206. package/dist/harness/muse.js.map +1 -0
  207. package/dist/harness/n8n.d.ts.map +1 -1
  208. package/dist/harness/n8n.js +36 -11
  209. package/dist/harness/n8n.js.map +1 -1
  210. package/dist/harness/openaiAgents.d.ts +40 -0
  211. package/dist/harness/openaiAgents.d.ts.map +1 -0
  212. package/dist/harness/openaiAgents.js +107 -0
  213. package/dist/harness/openaiAgents.js.map +1 -0
  214. package/dist/harness/opencode.d.ts +24 -0
  215. package/dist/harness/opencode.d.ts.map +1 -0
  216. package/dist/harness/opencode.js +97 -0
  217. package/dist/harness/opencode.js.map +1 -0
  218. package/dist/harness/pydanticAi.d.ts +19 -0
  219. package/dist/harness/pydanticAi.d.ts.map +1 -0
  220. package/dist/harness/pydanticAi.js +30 -0
  221. package/dist/harness/pydanticAi.js.map +1 -0
  222. package/dist/harness/sdkGatedAdapter.d.ts +55 -0
  223. package/dist/harness/sdkGatedAdapter.d.ts.map +1 -0
  224. package/dist/harness/sdkGatedAdapter.js +85 -0
  225. package/dist/harness/sdkGatedAdapter.js.map +1 -0
  226. package/dist/harness/smolagents.d.ts +22 -0
  227. package/dist/harness/smolagents.d.ts.map +1 -0
  228. package/dist/harness/smolagents.js +33 -0
  229. package/dist/harness/smolagents.js.map +1 -0
  230. package/dist/harness/strands.d.ts +22 -0
  231. package/dist/harness/strands.d.ts.map +1 -0
  232. package/dist/harness/strands.js +35 -0
  233. package/dist/harness/strands.js.map +1 -0
  234. package/dist/harness/trueforge.d.ts +25 -0
  235. package/dist/harness/trueforge.d.ts.map +1 -0
  236. package/dist/harness/trueforge.js +40 -0
  237. package/dist/harness/trueforge.js.map +1 -0
  238. package/dist/harness/types.d.ts.map +1 -1
  239. package/dist/harness/types.js +70 -0
  240. package/dist/harness/types.js.map +1 -1
  241. package/dist/harness/vercelAiSdk.d.ts +31 -0
  242. package/dist/harness/vercelAiSdk.d.ts.map +1 -0
  243. package/dist/harness/vercelAiSdk.js +44 -0
  244. package/dist/harness/vercelAiSdk.js.map +1 -0
  245. package/dist/harness/xirp.d.ts +43 -0
  246. package/dist/harness/xirp.d.ts.map +1 -0
  247. package/dist/harness/xirp.js +95 -0
  248. package/dist/harness/xirp.js.map +1 -0
  249. package/dist/lib/api.d.ts +68 -0
  250. package/dist/lib/api.d.ts.map +1 -1
  251. package/dist/lib/api.js +108 -67
  252. package/dist/lib/api.js.map +1 -1
  253. package/dist/lib/authMessages.d.ts +19 -0
  254. package/dist/lib/authMessages.d.ts.map +1 -0
  255. package/dist/lib/authMessages.js +20 -0
  256. package/dist/lib/authMessages.js.map +1 -0
  257. package/dist/lib/binaryChecksum.d.ts +12 -0
  258. package/dist/lib/binaryChecksum.d.ts.map +1 -0
  259. package/dist/lib/binaryChecksum.js +45 -0
  260. package/dist/lib/binaryChecksum.js.map +1 -0
  261. package/dist/lib/binaryOnPath.d.ts +24 -0
  262. package/dist/lib/binaryOnPath.d.ts.map +1 -0
  263. package/dist/lib/binaryOnPath.js +31 -0
  264. package/dist/lib/binaryOnPath.js.map +1 -0
  265. package/dist/lib/caTrust.d.ts +69 -0
  266. package/dist/lib/caTrust.d.ts.map +1 -0
  267. package/dist/lib/caTrust.js +169 -0
  268. package/dist/lib/caTrust.js.map +1 -0
  269. package/dist/lib/ciscoScanner.d.ts +178 -0
  270. package/dist/lib/ciscoScanner.d.ts.map +1 -0
  271. package/dist/lib/ciscoScanner.js +292 -0
  272. package/dist/lib/ciscoScanner.js.map +1 -0
  273. package/dist/lib/decisionsLogRefresh.d.ts +28 -0
  274. package/dist/lib/decisionsLogRefresh.d.ts.map +1 -0
  275. package/dist/lib/decisionsLogRefresh.js +54 -0
  276. package/dist/lib/decisionsLogRefresh.js.map +1 -0
  277. package/dist/lib/deviceReport.d.ts +26 -0
  278. package/dist/lib/deviceReport.d.ts.map +1 -0
  279. package/dist/lib/deviceReport.js +55 -0
  280. package/dist/lib/deviceReport.js.map +1 -0
  281. package/dist/lib/elevation.d.ts +58 -0
  282. package/dist/lib/elevation.d.ts.map +1 -0
  283. package/dist/lib/elevation.js +83 -0
  284. package/dist/lib/elevation.js.map +1 -0
  285. package/dist/lib/enforcementState.d.ts +69 -0
  286. package/dist/lib/enforcementState.d.ts.map +1 -0
  287. package/dist/lib/enforcementState.js +113 -0
  288. package/dist/lib/enforcementState.js.map +1 -0
  289. package/dist/lib/ensureValkey.d.ts.map +1 -1
  290. package/dist/lib/ensureValkey.js +2 -2
  291. package/dist/lib/ensureValkey.js.map +1 -1
  292. package/dist/lib/envInjector.d.ts.map +1 -1
  293. package/dist/lib/envInjector.js +22 -4
  294. package/dist/lib/envInjector.js.map +1 -1
  295. package/dist/lib/gitHooks.d.ts +7 -2
  296. package/dist/lib/gitHooks.d.ts.map +1 -1
  297. package/dist/lib/gitHooks.js +180 -13
  298. package/dist/lib/gitHooks.js.map +1 -1
  299. package/dist/lib/gracefulShutdown.d.ts +37 -0
  300. package/dist/lib/gracefulShutdown.d.ts.map +1 -0
  301. package/dist/lib/gracefulShutdown.js +57 -0
  302. package/dist/lib/gracefulShutdown.js.map +1 -0
  303. package/dist/lib/graphIdentity.d.ts +80 -0
  304. package/dist/lib/graphIdentity.d.ts.map +1 -0
  305. package/dist/lib/graphIdentity.js +120 -0
  306. package/dist/lib/graphIdentity.js.map +1 -0
  307. package/dist/lib/localTraces.d.ts +61 -0
  308. package/dist/lib/localTraces.d.ts.map +1 -0
  309. package/dist/lib/localTraces.js +173 -0
  310. package/dist/lib/localTraces.js.map +1 -0
  311. package/dist/lib/mdmManifest.d.ts +73 -0
  312. package/dist/lib/mdmManifest.d.ts.map +1 -0
  313. package/dist/lib/mdmManifest.js +190 -0
  314. package/dist/lib/mdmManifest.js.map +1 -0
  315. package/dist/lib/onboarding.d.ts.map +1 -1
  316. package/dist/lib/onboarding.js +60 -1
  317. package/dist/lib/onboarding.js.map +1 -1
  318. package/dist/lib/otelPropagation.d.ts +26 -0
  319. package/dist/lib/otelPropagation.d.ts.map +1 -0
  320. package/dist/lib/otelPropagation.js +40 -0
  321. package/dist/lib/otelPropagation.js.map +1 -0
  322. package/dist/lib/policySnapshot.d.ts +92 -0
  323. package/dist/lib/policySnapshot.d.ts.map +1 -0
  324. package/dist/lib/policySnapshot.js +173 -0
  325. package/dist/lib/policySnapshot.js.map +1 -0
  326. package/dist/lib/process.d.ts.map +1 -1
  327. package/dist/lib/process.js +60 -0
  328. package/dist/lib/process.js.map +1 -1
  329. package/dist/lib/providerProbe.d.ts +28 -0
  330. package/dist/lib/providerProbe.d.ts.map +1 -0
  331. package/dist/lib/providerProbe.js +57 -0
  332. package/dist/lib/providerProbe.js.map +1 -0
  333. package/dist/lib/proxyBinary.d.ts +19 -0
  334. package/dist/lib/proxyBinary.d.ts.map +1 -0
  335. package/dist/lib/proxyBinary.js +30 -0
  336. package/dist/lib/proxyBinary.js.map +1 -0
  337. package/dist/lib/sandbox/firecracker.d.ts +89 -0
  338. package/dist/lib/sandbox/firecracker.d.ts.map +1 -0
  339. package/dist/lib/sandbox/firecracker.js +135 -0
  340. package/dist/lib/sandbox/firecracker.js.map +1 -0
  341. package/dist/lib/sandbox/index.d.ts +34 -0
  342. package/dist/lib/sandbox/index.d.ts.map +1 -0
  343. package/dist/lib/sandbox/index.js +54 -0
  344. package/dist/lib/sandbox/index.js.map +1 -0
  345. package/dist/lib/sandbox/oci.d.ts +38 -0
  346. package/dist/lib/sandbox/oci.d.ts.map +1 -0
  347. package/dist/lib/sandbox/oci.js +108 -0
  348. package/dist/lib/sandbox/oci.js.map +1 -0
  349. package/dist/lib/sandbox/types.d.ts +48 -0
  350. package/dist/lib/sandbox/types.d.ts.map +1 -0
  351. package/dist/lib/sandbox/types.js +12 -0
  352. package/dist/lib/sandbox/types.js.map +1 -0
  353. package/dist/lib/sopFrontMatter.d.ts +50 -0
  354. package/dist/lib/sopFrontMatter.d.ts.map +1 -0
  355. package/dist/lib/sopFrontMatter.js +129 -0
  356. package/dist/lib/sopFrontMatter.js.map +1 -0
  357. package/package.json +11 -6
@@ -0,0 +1,620 @@
1
+ /**
2
+ * `intutic integrity` — check that sealed trace roots still re-derive.
3
+ *
4
+ * Subcommands:
5
+ * - `intutic integrity roots [--loop-run <id>] [--json]`
6
+ * - `intutic integrity verify <root_id> [--json]`
7
+ * - `intutic integrity chain [--json]`
8
+ * - `intutic integrity config-chain [--json]`
9
+ *
10
+ * The exit status is the point. This is what a customer puts in CI, so the
11
+ * findings that mean "the record no longer matches what was sealed" — a
12
+ * re-derivation mismatch, a covered trace that is gone, a signature a published
13
+ * key rejects, a break in the root chain, a break or an edited body in the
14
+ * config snapshot chain — leave with 1. Everything else leaves with 0,
15
+ * including the states that look alarming and are not: a root sealed under a
16
+ * key that is no longer published, and a root or snapshot that names no
17
+ * predecessor. See `failsIntegrity`.
18
+ *
19
+ * Server side: services/control-plane/src/routes/integrity.ts.
20
+ *
21
+ * @module
22
+ */
23
+ import { createPublicKey, verify as nodeVerify } from 'node:crypto';
24
+ import { log } from '../lib/logger.js';
25
+ import { NOT_AUTHENTICATED } from '../lib/authMessages.js';
26
+ import { loadCredentials } from '../config/store.js';
27
+ import { resolveControlPlaneUrl } from '../config/paths.js';
28
+ import { createApiClient } from '../lib/api.js';
29
+ import pc from 'picocolors';
30
+ /** The version to rebuild a root's preimage under. See the field's note above. */
31
+ function preimageVersionOf(root) {
32
+ return root.signing_preimage_version ?? 1;
33
+ }
34
+ /**
35
+ * Domain tag per preimage version, mirroring `SIGN_DOMAIN` in
36
+ * services/control-plane/src/lib/rootSigner.ts. This map is also the list of
37
+ * versions this build can rebuild — kept as one thing rather than two, because
38
+ * two lists of the same fact drift and the drift is silent.
39
+ */
40
+ const SIGN_DOMAIN = {
41
+ 1: 'intutic.merkle-root.v1',
42
+ 2: 'intutic.merkle-root.v2',
43
+ };
44
+ /**
45
+ * Whether a finding should fail the command, and therefore the customer's CI.
46
+ *
47
+ * `unverifiable` deliberately does not. A root whose `signing_key_id` is not in
48
+ * the published JWKS says the operator dropped a rotated-out key from
49
+ * `TRACE_SIGNING_RETIRED_KEYS`; a root whose `signing_preimage_version` this
50
+ * build does not know says the CLI is older than the control plane. Neither
51
+ * says anything is wrong with the root. Failing on either accuses them of
52
+ * rewriting history over a key-management gap or a version skew, which is the
53
+ * distinction rootSigner.ts exists to preserve.
54
+ *
55
+ * `keys_unavailable` does not either — a control plane we could not reach for
56
+ * the JWKS is a fact about the network, not about the root.
57
+ *
58
+ * A chain finding reads `breaks` and never `unchainedRootIds`: an unchained
59
+ * root claimed no predecessor, so it contradicts nothing. It is also what a
60
+ * pre-migration-108 writer produces during a rolling deploy, so failing on it
61
+ * would make every deploy red.
62
+ *
63
+ * `configChain` fails on either of its two findings, and they are carried as
64
+ * two counts rather than one total because they have different causes: a break
65
+ * means a snapshot beside this one went missing, a content mismatch means this
66
+ * snapshot's own body was rewritten under its stored hash. Both contradict a
67
+ * claim the writer made, so both are failures — but a caller that had only a
68
+ * sum could not tell an operator which happened.
69
+ */
70
+ export function failsIntegrity(finding) {
71
+ switch (finding.kind) {
72
+ case 'recompute':
73
+ return finding.verdict !== 'match';
74
+ case 'signature':
75
+ return finding.state === 'invalid';
76
+ case 'chain':
77
+ return finding.breaks > 0;
78
+ case 'configChain':
79
+ return finding.breaks > 0 || finding.contentMismatches > 0;
80
+ }
81
+ }
82
+ // ─── Signature verification ─────────────────────────────────────────
83
+ /**
84
+ * The exact bytes the control plane signs, per preimage version.
85
+ *
86
+ * Must stay byte-identical to `signingPreimage` in
87
+ * services/control-plane/src/lib/rootSigner.ts — this is an independent
88
+ * verifier, so it rebuilds the preimage rather than being handed it. The scope
89
+ * fields are in the preimage because a signature over the bare 32-byte root
90
+ * would be portable to another workspace's row.
91
+ *
92
+ * v1 is the encoding of migration 107 and is retained verbatim: roots sealed
93
+ * under it are still in the ledger, and rebuilding them any other way reports a
94
+ * forgery on rows nobody touched. v2 adds `previous_root` behind a presence
95
+ * tag, because without it the chain link that makes root deletion detectable
96
+ * sat outside the signature and could be rewritten freely.
97
+ *
98
+ * The version comes off the root itself and is never a parameter. A caller that
99
+ * could pass one is a caller that can pass the wrong one, and the wrong one
100
+ * produces `invalid` — the verdict that accuses an operator of forgery.
101
+ */
102
+ export function signingPreimage(root) {
103
+ const US = '\x1f';
104
+ const version = preimageVersionOf(root);
105
+ const domain = SIGN_DOMAIN[version];
106
+ if (domain === undefined) {
107
+ // Unreachable from `verifyRootSignature`, which reports an unknown version
108
+ // as unverifiable before it gets here. It throws rather than falling back
109
+ // to the newest encoding because a fallback would confidently produce bytes
110
+ // that were never signed, and the key would then say "forged".
111
+ throw new RangeError(`integrity: unknown signing preimage version ${version}`);
112
+ }
113
+ const fields = [
114
+ domain,
115
+ root.workspace_id,
116
+ root.loop_run_id ?? '',
117
+ String(root.leaf_schema_version),
118
+ root.merkle_root,
119
+ ];
120
+ if (version >= 2) {
121
+ // Presence tag then value, matching rootSigner.ts. "No predecessor" is a
122
+ // claim about the chain, not a missing field, so it must not encode the
123
+ // same as some value could.
124
+ //
125
+ // Normalised through `?? null` rather than compared against `null` directly:
126
+ // this row is parsed from JSON, and a server that omits the key rather than
127
+ // serialising a null would otherwise be tagged present-with-empty-value here
128
+ // while the control plane and the dashboard both tag it absent. Two of our
129
+ // own verifiers disagreeing on one root is how an auditor gets handed a
130
+ // forgery verdict we manufactured.
131
+ const previous = root.previous_root ?? null;
132
+ fields.push(previous === null ? '0' : '1', previous ?? '');
133
+ }
134
+ return fields.join(US);
135
+ }
136
+ /**
137
+ * Check a root's signature against the key the root itself names.
138
+ *
139
+ * Selection is by `signing_key_id`, never "any key that works": a root sealed
140
+ * under a rotated-out key must verify against that key years later, and a root
141
+ * that verifies under some *other* published key is not the same claim.
142
+ */
143
+ export function verifyRootSignature(root, jwks) {
144
+ if (!root.signature || !root.signing_key_id)
145
+ return 'unsigned';
146
+ if (!jwks)
147
+ return 'keys_unavailable';
148
+ const jwk = jwks.keys.find((k) => k['kid'] === root.signing_key_id);
149
+ if (!jwk)
150
+ return 'unverifiable';
151
+ // An algorithm this build cannot compute is another "no verdict", not a
152
+ // rejection. Only EdDSA is ever written today (rootSigner.ts signs nothing
153
+ // else), so this is the forward-compatible branch.
154
+ if (root.signature_alg !== 'EdDSA')
155
+ return 'unverifiable';
156
+ // And exactly the same for a preimage this build cannot rebuild. A newer
157
+ // control plane sealing under v3 while a customer's CI still runs last
158
+ // quarter's CLI is the ordinary case. Whatever bytes we produced for it would
159
+ // not be the bytes that were signed, so we would either print INVALID and
160
+ // exit 1 over a version skew, or — worse — reconstruct something that happens
161
+ // to match and report `valid` for a check we did not actually perform.
162
+ // Nothing here settles it either way, which is what `unverifiable` means.
163
+ if (SIGN_DOMAIN[preimageVersionOf(root)] === undefined)
164
+ return 'unverifiable';
165
+ try {
166
+ const key = createPublicKey({ key: jwk, format: 'jwk' });
167
+ const ok = nodeVerify(null, Buffer.from(signingPreimage(root), 'utf8'), key, Buffer.from(root.signature, 'base64'));
168
+ return ok ? 'valid' : 'invalid';
169
+ }
170
+ catch {
171
+ // A published key we cannot load is a key we do not effectively hold. That
172
+ // is the unverifiable case, not a rejection by a key we do hold.
173
+ return 'unverifiable';
174
+ }
175
+ }
176
+ /** Where the verification keys are published. Unauthenticated by design. */
177
+ const JWKS_PATH = '/.well-known/intutic-trace-signing.json';
178
+ /**
179
+ * Fetch the published verification keys, or null when they cannot be had.
180
+ *
181
+ * No credentials: an auditor who must hold your API key to obtain the verifying
182
+ * key is not an external auditor, and this command must exercise the same path
183
+ * one of them would.
184
+ */
185
+ async function fetchSigningKeys(controlPlaneUrl) {
186
+ try {
187
+ const res = await fetch(`${controlPlaneUrl}${JWKS_PATH}`);
188
+ if (!res.ok)
189
+ return null;
190
+ const body = (await res.json());
191
+ return Array.isArray(body?.keys) ? body : null;
192
+ }
193
+ catch {
194
+ return null;
195
+ }
196
+ }
197
+ // ─── Formatting helpers ─────────────────────────────────────────────
198
+ /** Truncate an id for table display. */
199
+ function truncateId(id) {
200
+ if (id.length <= 20)
201
+ return id;
202
+ return id.slice(0, 17) + '...';
203
+ }
204
+ /** Format ISO timestamp for compact table display. */
205
+ function formatTimestamp(iso) {
206
+ if (!iso)
207
+ return '—';
208
+ const d = new Date(iso);
209
+ const pad2 = (n) => String(n).padStart(2, '0');
210
+ return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
211
+ }
212
+ /** Pad a string to a fixed width (right-pad with spaces). */
213
+ /**
214
+ * ANSI escapes are zero-width. Measuring and slicing raw string length counts
215
+ * them, so a coloured cell is both mis-padded and cut mid-escape.
216
+ *
217
+ * `pc.yellow('unverifiable')` is 22 characters of which 12 are visible. Against
218
+ * a 13-wide column the old `slice(0, width)` cut after `ESC[33munver`, leaving a
219
+ * truncated word and an unterminated escape sequence that bleeds colour into
220
+ * everything after it. It looked fine locally only because picocolors disables
221
+ * colour when stdout is not a TTY — so the bug was invisible in a pipe and
222
+ * present in every real terminal.
223
+ */
224
+ // eslint-disable-next-line no-control-regex -- ESC (\u001b) opens every SGR colour sequence; matching it is this pattern's whole purpose.
225
+ const ANSI = /\u001b\[[0-9;]*m/g;
226
+ function visibleLength(str) {
227
+ return str.replace(ANSI, '').length;
228
+ }
229
+ /** Cut to `width` VISIBLE characters, keeping escapes and closing any left open. */
230
+ function truncateVisible(str, width) {
231
+ let out = '';
232
+ let seen = 0;
233
+ let i = 0;
234
+ let coloured = false;
235
+ while (i < str.length && seen < width) {
236
+ ANSI.lastIndex = i;
237
+ const m = ANSI.exec(str);
238
+ if (m && m.index === i) {
239
+ out += m[0];
240
+ coloured = m[0] !== '\u001b[39m' && m[0] !== '\u001b[0m';
241
+ i += m[0].length;
242
+ continue;
243
+ }
244
+ out += str[i];
245
+ seen += 1;
246
+ i += 1;
247
+ }
248
+ // Never leave a colour open — it would tint the border and every later row.
249
+ return coloured ? out + '\u001b[0m' : out;
250
+ }
251
+ export function padCell(str, width) {
252
+ const visible = visibleLength(str);
253
+ if (visible >= width)
254
+ return truncateVisible(str, width);
255
+ return str + ' '.repeat(width - visible);
256
+ }
257
+ /** Render a simple table with borders. */
258
+ function renderTable(headers, widths, rows) {
259
+ const top = '┌' + widths.map((w) => '─'.repeat(w + 2)).join('┬') + '┐';
260
+ const mid = '├' + widths.map((w) => '─'.repeat(w + 2)).join('┼') + '┤';
261
+ const bot = '└' + widths.map((w) => '─'.repeat(w + 2)).join('┴') + '┘';
262
+ const fmtRow = (cells) => '│ ' + cells.map((c, i) => padCell(c, widths[i])).join(' │ ') + ' │';
263
+ console.log(top);
264
+ console.log(fmtRow(headers));
265
+ console.log(mid);
266
+ for (const row of rows) {
267
+ console.log(fmtRow(row));
268
+ }
269
+ console.log(bot);
270
+ }
271
+ export function keyPublication(row, jwks) {
272
+ if (!row.signing_key_id)
273
+ return 'unsigned';
274
+ if (!jwks)
275
+ return 'keys_unavailable';
276
+ return jwks.keys.some((k) => k['kid'] === row.signing_key_id) ? 'published' : 'not_published';
277
+ }
278
+ /** Colour a key-publication state for the listing. */
279
+ function colorPublication(state) {
280
+ switch (state) {
281
+ case 'published':
282
+ return pc.cyan('key published');
283
+ case 'not_published':
284
+ return pc.yellow('unverifiable');
285
+ case 'keys_unavailable':
286
+ return pc.yellow('keys unread');
287
+ case 'unsigned':
288
+ return pc.dim('unsigned');
289
+ }
290
+ }
291
+ /** Colour a signature state. Amber for "no verdict", red only for a rejection. */
292
+ function colorSignature(state) {
293
+ switch (state) {
294
+ case 'valid':
295
+ return pc.green('valid');
296
+ case 'invalid':
297
+ return pc.red('INVALID');
298
+ case 'unverifiable':
299
+ return pc.yellow('unverifiable');
300
+ case 'keys_unavailable':
301
+ return pc.yellow('not checked');
302
+ case 'unsigned':
303
+ return pc.dim('unsigned');
304
+ }
305
+ }
306
+ /** What each signature state means, and what the operator does about it. */
307
+ function signatureNote(state, controlPlaneUrl) {
308
+ switch (state) {
309
+ case 'valid':
310
+ return 'Signed by a key this deployment publishes. That proves the root came from this deployment — not that its history is true, since the same party holds the key.';
311
+ case 'invalid':
312
+ return 'The key this root names REJECTED its signature. The root does not say what it was sealed saying.';
313
+ case 'unverifiable':
314
+ return `Nothing here settles this either way: either the key id it was sealed under is not published at ${controlPlaneUrl}${JWKS_PATH} — put the rotated-out PEM back into TRACE_SIGNING_RETIRED_KEYS — or the root records a signing preimage version this CLI cannot rebuild, in which case upgrade the CLI.`;
315
+ case 'keys_unavailable':
316
+ return `Could not read ${controlPlaneUrl}${JWKS_PATH}, so the signature was not checked.`;
317
+ case 'unsigned':
318
+ return 'Sealed with no signing key configured. Supported — the root still re-derives; it just cannot be attributed to this deployment by a third party.';
319
+ }
320
+ }
321
+ /** Cap a long id list so a mismatch over 4,000 traces stays readable. */
322
+ function sampleIds(ids, limit = 10) {
323
+ if (ids.length <= limit)
324
+ return ids.join(', ');
325
+ return `${ids.slice(0, limit).join(', ')} … and ${ids.length - limit} more`;
326
+ }
327
+ // ─── Commands ───────────────────────────────────────────────────────
328
+ /**
329
+ * `intutic integrity roots` — the sealed roots for the workspace, newest first.
330
+ */
331
+ export async function runIntegrityRoots(opts) {
332
+ const creds = await loadCredentials();
333
+ if (!creds) {
334
+ log.error(NOT_AUTHENTICATED);
335
+ process.exit(1);
336
+ }
337
+ const controlPlaneUrl = resolveControlPlaneUrl(opts.dev);
338
+ const client = createApiClient(controlPlaneUrl, creds.apiKey);
339
+ try {
340
+ const query = opts.loopRun ? `?loopRunId=${encodeURIComponent(opts.loopRun)}` : '';
341
+ const data = await client.get(`/api/v1/integrity/roots${query}`);
342
+ const roots = data.data ?? [];
343
+ if (opts.json) {
344
+ console.log(JSON.stringify(data, null, 2));
345
+ return;
346
+ }
347
+ log.header('Intutic — Sealed Trace Roots');
348
+ if (roots.length === 0) {
349
+ log.dim(' No roots sealed yet.');
350
+ log.dim(' An hourly sweep seals a loop run once it is terminal and has been quiet for');
351
+ log.dim(' fifteen minutes. Until then its traces are recorded but under no root.');
352
+ return;
353
+ }
354
+ // Fetched once for the whole listing. Without it the signature column could
355
+ // only report presence, and "signed" would be indistinguishable from
356
+ // "signed by a key nobody can obtain".
357
+ const jwks = await fetchSigningKeys(controlPlaneUrl);
358
+ const headers = ['Root ID', 'Sealed', 'Loop Run', 'Traces', 'Leaf v', 'Signature'];
359
+ const widths = [20, 16, 20, 6, 6, 13];
360
+ const rows = roots.map((r) => [
361
+ truncateId(r.root_id),
362
+ formatTimestamp(r.sealed_at),
363
+ r.loop_run_id ? truncateId(r.loop_run_id) : '—',
364
+ String(r.leaf_count),
365
+ `v${r.leaf_schema_version}`,
366
+ // The list endpoint does not carry the signature itself, so this column
367
+ // reports key publication and nothing more. `verify` checks the bytes.
368
+ colorPublication(keyPublication(r, jwks)),
369
+ ]);
370
+ renderTable(headers, widths, rows);
371
+ console.log(pc.dim(`Showing ${roots.length} root${roots.length === 1 ? '' : 's'}. The Signature column reports whether the sealing key is published,\n` +
372
+ 'not whether the signature verifies — `intutic integrity verify <root_id>` checks the bytes.'));
373
+ }
374
+ catch (err) {
375
+ log.error(`Failed to list roots: ${err instanceof Error ? err.message : String(err)}`);
376
+ process.exit(1);
377
+ }
378
+ }
379
+ /**
380
+ * `intutic integrity verify <root_id>` — re-derive one root from the live rows
381
+ * and check its signature.
382
+ *
383
+ * Exits 1 on a mismatch, on missing traces, or on a signature a published key
384
+ * rejects.
385
+ */
386
+ export async function runIntegrityVerify(rootId, opts) {
387
+ const creds = await loadCredentials();
388
+ if (!creds) {
389
+ log.error(NOT_AUTHENTICATED);
390
+ process.exit(1);
391
+ }
392
+ const controlPlaneUrl = resolveControlPlaneUrl(opts.dev);
393
+ const client = createApiClient(controlPlaneUrl, creds.apiKey);
394
+ const encoded = encodeURIComponent(rootId);
395
+ let detail;
396
+ let recompute;
397
+ try {
398
+ detail = await client.get(`/api/v1/integrity/roots/${encoded}`);
399
+ // Always 200, whatever the verdict: a mismatch is a successful check that
400
+ // found something, and an HTTP error here would be retried and then ignored.
401
+ recompute = await client.post(`/api/v1/integrity/roots/${encoded}/recompute`, {});
402
+ }
403
+ catch (err) {
404
+ log.error(`Failed to verify root: ${err instanceof Error ? err.message : String(err)}`);
405
+ process.exit(1);
406
+ }
407
+ const signature = verifyRootSignature(detail.root, await fetchSigningKeys(controlPlaneUrl));
408
+ const findings = [
409
+ { kind: 'recompute', verdict: recompute.verdict },
410
+ { kind: 'signature', state: signature },
411
+ ];
412
+ const failed = findings.some(failsIntegrity);
413
+ if (opts.json) {
414
+ console.log(JSON.stringify({
415
+ rootId,
416
+ verdict: recompute.verdict,
417
+ storedRoot: recompute.storedRoot,
418
+ recomputedRoot: recompute.recomputedRoot,
419
+ changedTraceIds: recompute.changedTraceIds,
420
+ missingTraceIds: recompute.missingTraceIds,
421
+ signature,
422
+ leafSchemaVersion: detail.root.leaf_schema_version,
423
+ leafCount: detail.root.leaf_count,
424
+ failed,
425
+ }, null, 2));
426
+ }
427
+ else {
428
+ log.header('Intutic — Root Verification');
429
+ log.field('Root ID', detail.root.root_id);
430
+ log.field('Loop run', detail.root.loop_run_id ?? '— (not scoped to a run)');
431
+ log.field('Sealed', formatTimestamp(detail.root.sealed_at));
432
+ log.field('Traces covered', `${detail.leaves.length} of ${detail.root.leaf_count} enumerated`);
433
+ log.field('Leaf schema', `v${detail.root.leaf_schema_version}`);
434
+ console.log('');
435
+ switch (recompute.verdict) {
436
+ case 'match':
437
+ log.success('Re-derivation: match — every covered trace still hashes to what was sealed.');
438
+ break;
439
+ case 'mismatch':
440
+ log.error(`Re-derivation: MISMATCH — ${recompute.changedTraceIds.length} trace(s) changed after sealing.`);
441
+ log.field('Changed', sampleIds(recompute.changedTraceIds));
442
+ log.field('Sealed root', recompute.storedRoot);
443
+ log.field('Re-derived', recompute.recomputedRoot ?? '—');
444
+ break;
445
+ case 'missing_traces':
446
+ log.error(`Re-derivation: MISSING TRACES — ${recompute.missingTraceIds.length} covered trace(s) are gone.`);
447
+ log.field('Missing', sampleIds(recompute.missingTraceIds));
448
+ break;
449
+ }
450
+ console.log('');
451
+ console.log(` ${pc.dim('Signature:')} ${colorSignature(signature)}`);
452
+ log.dim(` ${signatureNote(signature, controlPlaneUrl)}`);
453
+ }
454
+ if (failed)
455
+ process.exit(1);
456
+ }
457
+ /**
458
+ * `intutic integrity chain` — walk the `previous_root` chain.
459
+ *
460
+ * Exits 1 on a break. Re-derivation cannot see a root that was deleted outright
461
+ * — the survivors all verify perfectly — so this walk is the only check that
462
+ * notices one is missing.
463
+ */
464
+ export async function runIntegrityChain(opts) {
465
+ const creds = await loadCredentials();
466
+ if (!creds) {
467
+ log.error(NOT_AUTHENTICATED);
468
+ process.exit(1);
469
+ }
470
+ const controlPlaneUrl = resolveControlPlaneUrl(opts.dev);
471
+ const client = createApiClient(controlPlaneUrl, creds.apiKey);
472
+ let status;
473
+ let body;
474
+ try {
475
+ // The break case answers 409 with the walk in the body, so the status
476
+ // cannot be allowed to throw past the reporting.
477
+ const res = await client.getWithStatus('/api/v1/integrity/chain');
478
+ status = res.status;
479
+ body = res.body;
480
+ }
481
+ catch (err) {
482
+ log.error(`Failed to walk the chain: ${err instanceof Error ? err.message : String(err)}`);
483
+ process.exit(1);
484
+ }
485
+ if (status !== 200 && status !== 409) {
486
+ log.error(`Chain walk failed (${status}): ${JSON.stringify(body)}`);
487
+ process.exit(1);
488
+ }
489
+ const breaks = body.breaks ?? [];
490
+ const unchained = body.unchainedRootIds ?? [];
491
+ if (opts.json) {
492
+ console.log(JSON.stringify({ ...body, failed: failsIntegrity({ kind: 'chain', breaks: breaks.length }) }, null, 2));
493
+ }
494
+ else {
495
+ log.header('Intutic — Root Chain Walk');
496
+ log.field('Roots walked', String(body.rootsWalked));
497
+ if (body.rootsNotWalked > 0) {
498
+ // An unwalked tail is not an intact one, and the endpoint says so rather
499
+ // than letting the caller read "no breaks" as "no breaks anywhere".
500
+ log.field('Older, not walked', `${body.rootsNotWalked} (outside the 500-root window)`);
501
+ }
502
+ if (breaks.length === 0) {
503
+ log.success('No breaks: every walked root names the root that actually precedes it.');
504
+ }
505
+ else {
506
+ log.error(`${breaks.length} break(s) — a root names a predecessor that is not the root before it.`);
507
+ for (const b of breaks) {
508
+ log.field(b.rootId, `names ${b.namedPrevious}, but ${b.precedingRootId} (${b.precedingMerkleRoot}) precedes it`);
509
+ }
510
+ }
511
+ if (unchained.length > 0) {
512
+ log.warn(`${unchained.length} root(s) name no predecessor. Not a break — nothing was claimed, so ` +
513
+ 'nothing contradicts. It means a deletion at that point would go unseen.');
514
+ log.field('Unchained', sampleIds(unchained));
515
+ }
516
+ }
517
+ if (failsIntegrity({ kind: 'chain', breaks: breaks.length }))
518
+ process.exit(1);
519
+ }
520
+ /**
521
+ * `intutic integrity config-chain` — walk the harness config snapshot chain.
522
+ *
523
+ * The TD-232 verifier, reached from the product rather than from a hand-written
524
+ * curl. `content_hash` and `previous_hash` are written on every config snapshot
525
+ * and were read only to find a diff predecessor, so for months a snapshot could
526
+ * be deleted, or its body rewritten under its stored hash, and every reader
527
+ * returned exactly what it returned before.
528
+ *
529
+ * Exits 1 on either finding. They are reported apart because they have
530
+ * different causes and different remedies: a break says a snapshot next to this
531
+ * one is gone, a content mismatch says this snapshot's own stored body no
532
+ * longer hashes to the hash recorded with it. Collapsing them into one count is
533
+ * the mistake the `audit_log_integrity` probe made by averaging independent
534
+ * controls into a single score.
535
+ */
536
+ export async function runIntegrityConfigChain(opts) {
537
+ const creds = await loadCredentials();
538
+ if (!creds) {
539
+ log.error(NOT_AUTHENTICATED);
540
+ process.exit(1);
541
+ }
542
+ const controlPlaneUrl = resolveControlPlaneUrl(opts.dev);
543
+ const client = createApiClient(controlPlaneUrl, creds.apiKey);
544
+ let status;
545
+ let body;
546
+ try {
547
+ // Same reason as `chain` above: the contradicted case answers 409 with the
548
+ // walk in the body, so the status must not throw past the reporting.
549
+ const res = await client.getWithStatus('/api/v1/integrity/config-chain');
550
+ status = res.status;
551
+ body = res.body;
552
+ }
553
+ catch (err) {
554
+ log.error(`Failed to walk the config chain: ${err instanceof Error ? err.message : String(err)}`);
555
+ process.exit(1);
556
+ }
557
+ if (status !== 200 && status !== 409) {
558
+ log.error(`Config chain walk failed (${status}): ${JSON.stringify(body)}`);
559
+ process.exit(1);
560
+ }
561
+ const breaks = body.breaks ?? [];
562
+ const mismatches = body.contentMismatches ?? [];
563
+ const unchained = body.unchainedSnapshotIds ?? [];
564
+ const walked = body.snapshotsWalked ?? 0;
565
+ const failed = failsIntegrity({
566
+ kind: 'configChain',
567
+ breaks: breaks.length,
568
+ contentMismatches: mismatches.length,
569
+ });
570
+ if (opts.json) {
571
+ console.log(JSON.stringify({ ...body, failed }, null, 2));
572
+ }
573
+ else {
574
+ log.header('Intutic — Config Snapshot Chain Walk');
575
+ log.field('Snapshots walked', String(walked));
576
+ if (body.snapshotsNotWalked > 0) {
577
+ // Never printed as a count: the server stops counting at one. An
578
+ // unwalked tail is still not an intact one, so it is stated.
579
+ log.field('Older, not walked', 'yes — snapshots past the 500-snapshot window were not examined');
580
+ }
581
+ if (walked === 0) {
582
+ // Not a pass, and it must not read as one. Nothing was checked, so
583
+ // "no breaks" here would be the same sentence an intact chain prints
584
+ // while standing for nothing at all.
585
+ log.warn('No config snapshots for this workspace, so nothing was verified. This is not a clean ' +
586
+ 'chain — it is an absent one. A workspace whose harness configs are being captured ' +
587
+ 'has snapshots; if this one should, the sync daemon is not reaching the control plane.');
588
+ }
589
+ else if (breaks.length === 0 && mismatches.length === 0) {
590
+ log.success(`No breaks and no content mismatches across ${walked} snapshot(s): every walked snapshot ` +
591
+ 'names the snapshot that actually precedes it, and every stored body still hashes to its ' +
592
+ 'recorded content_hash.');
593
+ }
594
+ if (breaks.length > 0) {
595
+ log.error(`${breaks.length} break(s) — a snapshot names a predecessor that is not the snapshot ` +
596
+ 'before it. That is what deleting a snapshot leaves behind.');
597
+ for (const b of breaks) {
598
+ log.field(`${b.snapshotId} (${b.harnessType} ${b.filePath})`, `names ${b.namedPrevious}, but ${b.precedingSnapshotId} (${b.precedingContentHash}) precedes it`);
599
+ }
600
+ }
601
+ if (mismatches.length > 0) {
602
+ // Deliberately not called a break, and deliberately printed as its own
603
+ // finding: the links here are all intact. The body under one of them was
604
+ // edited, which link-checking alone cannot see.
605
+ log.error(`${mismatches.length} content mismatch(es) — a stored snapshot body no longer hashes to ` +
606
+ 'the content_hash recorded with it. The body was rewritten in place.');
607
+ for (const m of mismatches) {
608
+ log.field(`${m.snapshotId} (${m.harnessType} ${m.filePath})`, `recorded ${m.storedHash}, body now hashes to ${m.recomputedHash}`);
609
+ }
610
+ }
611
+ if (unchained.length > 0) {
612
+ log.warn(`${unchained.length} snapshot(s) name no predecessor mid-chain. Nothing was claimed, so ` +
613
+ 'nothing contradicts — but a deletion at that point would go unseen.');
614
+ log.field('Unchained', sampleIds(unchained));
615
+ }
616
+ }
617
+ if (failed)
618
+ process.exit(1);
619
+ }
620
+ //# sourceMappingURL=integrity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity.js","sourceRoot":"","sources":["../../src/commands/integrity.ts"],"names":[],"mappings":"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"}