@vellumai/assistant 0.7.0 → 0.7.1

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 (666) hide show
  1. package/ARCHITECTURE.md +6 -7
  2. package/Dockerfile +1 -0
  3. package/README.md +2 -2
  4. package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
  5. package/bun.lock +3 -0
  6. package/docs/architecture/security.md +18 -16
  7. package/knip.json +1 -0
  8. package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
  9. package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
  10. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
  11. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
  12. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
  13. package/node_modules/@vellumai/slack-text/bun.lock +24 -0
  14. package/node_modules/@vellumai/slack-text/package.json +18 -0
  15. package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
  16. package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
  17. package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
  18. package/openapi.yaml +294 -107
  19. package/package.json +4 -2
  20. package/scripts/generate-openapi.ts +16 -111
  21. package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
  22. package/src/__tests__/anthropic-provider.test.ts +56 -13
  23. package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
  24. package/src/__tests__/app-conversation-ids.test.ts +151 -0
  25. package/src/__tests__/approval-cascade.test.ts +0 -15
  26. package/src/__tests__/approval-routes-http.test.ts +6 -17
  27. package/src/__tests__/assistant-event-hub.test.ts +126 -77
  28. package/src/__tests__/assistant-event.test.ts +0 -5
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
  31. package/src/__tests__/background-shell-host-bash.test.ts +34 -43
  32. package/src/__tests__/call-controller.test.ts +1 -1
  33. package/src/__tests__/call-site-routing-provider.test.ts +193 -0
  34. package/src/__tests__/channel-approval-routes.test.ts +10 -296
  35. package/src/__tests__/channel-approvals.test.ts +25 -17
  36. package/src/__tests__/channel-guardian.test.ts +100 -146
  37. package/src/__tests__/checker.test.ts +20 -34
  38. package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/config-schema.test.ts +6 -48
  41. package/src/__tests__/config-watcher.test.ts +12 -0
  42. package/src/__tests__/connection-policy.test.ts +1 -52
  43. package/src/__tests__/contacts-write.test.ts +2 -64
  44. package/src/__tests__/context-image-dimensions.test.ts +1 -1
  45. package/src/__tests__/context-search-memory-source.test.ts +120 -1
  46. package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
  47. package/src/__tests__/context-search-pkb-source.test.ts +49 -0
  48. package/src/__tests__/context-search-workspace-source.test.ts +9 -22
  49. package/src/__tests__/context-window-manager.test.ts +46 -0
  50. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  51. package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
  52. package/src/__tests__/conversation-agent-loop.test.ts +980 -13
  53. package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
  54. package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
  55. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
  56. package/src/__tests__/conversation-history-web-search.test.ts +4 -3
  57. package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
  58. package/src/__tests__/conversation-lifecycle.test.ts +4 -4
  59. package/src/__tests__/conversation-process-callsite.test.ts +79 -2
  60. package/src/__tests__/conversation-queue.test.ts +3 -8
  61. package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
  62. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
  63. package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
  64. package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
  65. package/src/__tests__/conversation-slash-commands.test.ts +24 -4
  66. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +0 -3
  68. package/src/__tests__/conversation-starter-routes.test.ts +79 -2
  69. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
  70. package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
  71. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
  72. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
  73. package/src/__tests__/conversation-usage.test.ts +253 -3
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
  75. package/src/__tests__/credential-health-service.test.ts +68 -0
  76. package/src/__tests__/credential-security-e2e.test.ts +4 -3
  77. package/src/__tests__/credential-security-invariants.test.ts +1 -5
  78. package/src/__tests__/credential-token-resolver.test.ts +180 -0
  79. package/src/__tests__/cu-unified-flow.test.ts +33 -16
  80. package/src/__tests__/daemon-assistant-events.test.ts +34 -21
  81. package/src/__tests__/daemon-credential-client.test.ts +4 -1
  82. package/src/__tests__/db-connection-isolation.test.ts +125 -0
  83. package/src/__tests__/db-migration-rollback.test.ts +101 -0
  84. package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
  85. package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
  86. package/src/__tests__/document-conversations.test.ts +332 -0
  87. package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
  88. package/src/__tests__/emit-event-signal.test.ts +4 -6
  89. package/src/__tests__/events-client-registration.test.ts +193 -49
  90. package/src/__tests__/filing-service.test.ts +58 -7
  91. package/src/__tests__/first-greeting.test.ts +156 -150
  92. package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
  93. package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
  94. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  95. package/src/__tests__/guardian-dispatch.test.ts +1 -1
  96. package/src/__tests__/guardian-grant-minting.test.ts +7 -2
  97. package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
  98. package/src/__tests__/guardian-routing-state.test.ts +1 -1
  99. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
  100. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
  101. package/src/__tests__/headless-browser-mode.test.ts +4 -9
  102. package/src/__tests__/headless-browser-navigate.test.ts +21 -20
  103. package/src/__tests__/heartbeat-service.test.ts +289 -7
  104. package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
  105. package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
  106. package/src/__tests__/host-bash-proxy.test.ts +46 -122
  107. package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
  108. package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
  109. package/src/__tests__/host-browser-proxy.test.ts +111 -185
  110. package/src/__tests__/host-browser-routes.test.ts +45 -75
  111. package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
  112. package/src/__tests__/host-cu-proxy.test.ts +56 -111
  113. package/src/__tests__/host-file-proxy.test.ts +44 -98
  114. package/src/__tests__/host-file-read-tool.test.ts +42 -21
  115. package/src/__tests__/host-shell-tool.test.ts +33 -68
  116. package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
  117. package/src/__tests__/host-transfer-proxy.test.ts +43 -53
  118. package/src/__tests__/http-user-message-parity.test.ts +0 -6
  119. package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
  120. package/src/__tests__/injector-chain.test.ts +10 -5
  121. package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
  122. package/src/__tests__/inline-command-runner.test.ts +0 -66
  123. package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
  124. package/src/__tests__/install-skill-routing.test.ts +1 -13
  125. package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
  126. package/src/__tests__/llm-catalog-parity.test.ts +90 -0
  127. package/src/__tests__/llm-context-resolution.test.ts +180 -0
  128. package/src/__tests__/llm-resolver.test.ts +80 -12
  129. package/src/__tests__/llm-usage-store.test.ts +269 -4
  130. package/src/__tests__/log-export-routes.test.ts +89 -0
  131. package/src/__tests__/managed-profile-guard.test.ts +225 -0
  132. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
  133. package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
  134. package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
  135. package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
  136. package/src/__tests__/migration-export-http.test.ts +33 -26
  137. package/src/__tests__/migration-export-streaming.test.ts +18 -10
  138. package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
  139. package/src/__tests__/migration-import-commit-http.test.ts +66 -21
  140. package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
  141. package/src/__tests__/migration-import-from-url.test.ts +20 -6
  142. package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
  143. package/src/__tests__/migration-parity-persistence.test.ts +62 -25
  144. package/src/__tests__/migration-transport.test.ts +115 -23
  145. package/src/__tests__/migration-validate-http.test.ts +105 -80
  146. package/src/__tests__/migration-wizard.test.ts +133 -27
  147. package/src/__tests__/non-member-access-request.test.ts +1 -1
  148. package/src/__tests__/notification-guardian-path.test.ts +1 -1
  149. package/src/__tests__/oauth-store.test.ts +19 -0
  150. package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
  151. package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
  152. package/src/__tests__/pricing.test.ts +68 -4
  153. package/src/__tests__/process-message-background-slack.test.ts +331 -0
  154. package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
  155. package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
  156. package/src/__tests__/provider-usage-tracking.test.ts +208 -0
  157. package/src/__tests__/reaction-persistence.test.ts +9 -6
  158. package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
  159. package/src/__tests__/recording-handler.test.ts +64 -81
  160. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
  161. package/src/__tests__/relay-server.test.ts +18 -13
  162. package/src/__tests__/require-fresh-approval.test.ts +13 -22
  163. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
  164. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  165. package/src/__tests__/runtime-events-sse.test.ts +3 -12
  166. package/src/__tests__/search-skills-unified.test.ts +9 -15
  167. package/src/__tests__/secret-ingress-cli.test.ts +2 -5
  168. package/src/__tests__/secret-ingress-http.test.ts +0 -4
  169. package/src/__tests__/secret-onetime-send.test.ts +4 -2
  170. package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
  171. package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
  172. package/src/__tests__/secret-response-routing.test.ts +29 -15
  173. package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
  174. package/src/__tests__/secret-scanner.test.ts +2 -545
  175. package/src/__tests__/send-endpoint-busy.test.ts +9 -24
  176. package/src/__tests__/settings-routes.test.ts +1 -1
  177. package/src/__tests__/shell-credential-ref.test.ts +0 -8
  178. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
  179. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
  180. package/src/__tests__/skill-tool-factory.test.ts +97 -0
  181. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
  182. package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
  183. package/src/__tests__/slack-inbound-verification.test.ts +1 -62
  184. package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
  185. package/src/__tests__/subagent-manager-notify.test.ts +70 -70
  186. package/src/__tests__/subagent-notify-parent.test.ts +80 -83
  187. package/src/__tests__/system-prompt.test.ts +115 -13
  188. package/src/__tests__/terminal-tools.test.ts +0 -89
  189. package/src/__tests__/thread-backfill.test.ts +945 -31
  190. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
  191. package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
  192. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
  193. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
  194. package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
  195. package/src/__tests__/tool-executor.test.ts +12 -19
  196. package/src/__tests__/tool-metrics-listener.test.ts +0 -35
  197. package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
  198. package/src/__tests__/tool-trace-listener.test.ts +0 -17
  199. package/src/__tests__/transfer-progress-screen.test.ts +63 -26
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
  202. package/src/__tests__/trusted-contact-verification.test.ts +1 -1
  203. package/src/__tests__/tts-catalog-parity.test.ts +16 -5
  204. package/src/__tests__/usage-attribution.test.ts +247 -0
  205. package/src/__tests__/usage-cli.test.ts +143 -0
  206. package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
  207. package/src/__tests__/usage-routes.test.ts +150 -0
  208. package/src/__tests__/validation-results-screen.test.ts +39 -16
  209. package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
  210. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
  211. package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
  212. package/src/__tests__/voice-session-bridge.test.ts +5 -5
  213. package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
  214. package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
  215. package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
  216. package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
  217. package/src/acp/index.ts +0 -15
  218. package/src/acp/session-manager.ts +37 -34
  219. package/src/agent/loop.ts +16 -1
  220. package/src/approvals/AGENTS.md +4 -0
  221. package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
  222. package/src/approvals/guardian-request-resolvers.ts +10 -2
  223. package/src/backup/__tests__/backup-worker.test.ts +36 -8
  224. package/src/backup/__tests__/paths.test.ts +2 -2
  225. package/src/backup/__tests__/restore.test.ts +45 -28
  226. package/src/backup/backup-worker.ts +36 -2
  227. package/src/backup/paths.ts +9 -6
  228. package/src/browser-session/events.ts +0 -9
  229. package/src/calls/call-store.ts +1 -34
  230. package/src/calls/guardian-question-copy.ts +0 -108
  231. package/src/calls/relay-server.ts +0 -24
  232. package/src/calls/twilio-rest.ts +0 -38
  233. package/src/calls/twilio-routes.ts +1 -1
  234. package/src/calls/voice-session-bridge.ts +7 -38
  235. package/src/channels/types.ts +1 -36
  236. package/src/cli/commands/__tests__/cache.test.ts +152 -5
  237. package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
  238. package/src/cli/commands/__tests__/trust.test.ts +21 -387
  239. package/src/cli/commands/backup.ts +4 -4
  240. package/src/cli/commands/cache-fs.ts +8 -0
  241. package/src/cli/commands/cache.ts +153 -82
  242. package/src/cli/commands/clients.ts +63 -5
  243. package/src/cli/commands/completions.ts +3 -3
  244. package/src/cli/commands/contacts.ts +231 -76
  245. package/src/cli/commands/keys.ts +4 -1
  246. package/src/cli/commands/memory-v2.ts +24 -52
  247. package/src/cli/commands/oauth/shared.ts +2 -29
  248. package/src/cli/commands/pending.ts +102 -0
  249. package/src/cli/commands/skills.ts +77 -35
  250. package/src/cli/commands/trust.ts +70 -430
  251. package/src/cli/commands/usage.ts +25 -16
  252. package/src/cli/lib/daemon-credential-client.ts +14 -0
  253. package/src/cli/program.ts +2 -0
  254. package/src/cli.ts +0 -21
  255. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  256. package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
  257. package/src/config/env-registry.ts +12 -2
  258. package/src/config/env.ts +3 -14
  259. package/src/config/feature-flag-registry.json +30 -30
  260. package/src/config/llm-callsite-catalog.ts +12 -0
  261. package/src/config/llm-context-resolution.ts +80 -0
  262. package/src/config/llm-resolver.ts +58 -22
  263. package/src/config/loader.ts +3 -3
  264. package/src/config/schema.ts +2 -158
  265. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  266. package/src/config/schemas/call-site-catalog.ts +271 -0
  267. package/src/config/schemas/calls.ts +5 -5
  268. package/src/config/schemas/inference.ts +1 -1
  269. package/src/config/schemas/ingress.ts +1 -1
  270. package/src/config/schemas/llm.ts +31 -3
  271. package/src/config/schemas/memory-retrieval.ts +2 -2
  272. package/src/config/schemas/memory-v2.ts +9 -0
  273. package/src/config/schemas/security.ts +1 -42
  274. package/src/config/schemas/services.ts +6 -6
  275. package/src/config/schemas/skills.ts +5 -5
  276. package/src/config/schemas/tts.ts +1 -1
  277. package/src/config/seed-inference-profiles.ts +117 -0
  278. package/src/config/skills.ts +0 -90
  279. package/src/config/types.ts +3 -6
  280. package/src/contacts/contact-store.ts +0 -17
  281. package/src/contacts/contacts-write.ts +1 -105
  282. package/src/context/window-manager.ts +44 -5
  283. package/src/credential-execution/process-manager.ts +34 -10
  284. package/src/credential-health/credential-health-service.ts +21 -16
  285. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
  286. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
  287. package/src/daemon/connection-policy.ts +1 -26
  288. package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
  289. package/src/daemon/conversation-agent-loop.ts +277 -36
  290. package/src/daemon/conversation-history.ts +8 -8
  291. package/src/daemon/conversation-launch.ts +20 -135
  292. package/src/daemon/conversation-lifecycle.ts +1 -1
  293. package/src/daemon/conversation-messaging.ts +1 -0
  294. package/src/daemon/conversation-process.ts +83 -163
  295. package/src/daemon/conversation-runtime-assembly.ts +219 -76
  296. package/src/daemon/conversation-slash.ts +47 -5
  297. package/src/daemon/conversation-store.ts +7 -31
  298. package/src/daemon/conversation-surfaces.ts +22 -28
  299. package/src/daemon/conversation-tool-setup.ts +3 -33
  300. package/src/daemon/conversation-usage.ts +36 -0
  301. package/src/daemon/conversation.ts +117 -233
  302. package/src/daemon/daemon-control.ts +3 -71
  303. package/src/daemon/daemon-skill-host.ts +8 -11
  304. package/src/daemon/dictation-profile-store.ts +2 -26
  305. package/src/daemon/first-greeting.ts +44 -156
  306. package/src/daemon/handlers/config-channels.ts +12 -12
  307. package/src/daemon/handlers/config-ingress.ts +4 -165
  308. package/src/daemon/handlers/config-model.ts +1 -1
  309. package/src/daemon/handlers/config-voice.ts +0 -42
  310. package/src/daemon/handlers/conversations.ts +11 -190
  311. package/src/daemon/handlers/recording.ts +26 -158
  312. package/src/daemon/handlers/shared.ts +23 -71
  313. package/src/daemon/handlers/skills.ts +42 -93
  314. package/src/daemon/host-bash-proxy.ts +67 -45
  315. package/src/daemon/host-browser-proxy.ts +65 -27
  316. package/src/daemon/host-cu-proxy.ts +40 -39
  317. package/src/daemon/host-file-proxy.ts +58 -37
  318. package/src/daemon/host-transfer-proxy.ts +84 -46
  319. package/src/daemon/lifecycle.ts +49 -15
  320. package/src/daemon/message-types/conversations.ts +7 -0
  321. package/src/daemon/message-types/host-bash.ts +1 -0
  322. package/src/daemon/message-types/host-cu.ts +1 -0
  323. package/src/daemon/message-types/host-file.ts +1 -0
  324. package/src/daemon/message-types/host-transfer.ts +1 -0
  325. package/src/daemon/message-types/messages.ts +10 -9
  326. package/src/daemon/message-types/workspace.ts +1 -1
  327. package/src/daemon/process-message.ts +102 -239
  328. package/src/daemon/server.ts +13 -462
  329. package/src/daemon/shutdown-handlers.ts +2 -2
  330. package/src/daemon/tool-side-effects.ts +125 -107
  331. package/src/daemon/trust-context.ts +13 -0
  332. package/src/daemon/wake-target-adapter.ts +4 -9
  333. package/src/events/domain-events.ts +0 -8
  334. package/src/events/tool-audit-listener.ts +3 -1
  335. package/src/events/tool-domain-event-publisher.ts +0 -10
  336. package/src/events/tool-metrics-listener.ts +0 -17
  337. package/src/events/tool-trace-listener.ts +0 -14
  338. package/src/filing/filing-service.ts +13 -1
  339. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
  340. package/src/heartbeat/heartbeat-service.ts +23 -5
  341. package/src/home/__tests__/feed-writer.test.ts +0 -4
  342. package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
  343. package/src/home/feed-writer.ts +1 -2
  344. package/src/home/relationship-state-writer.ts +16 -3
  345. package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
  346. package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
  347. package/src/ipc/assistant-server.ts +3 -10
  348. package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
  349. package/src/ipc/routes/route-adapter.ts +1 -1
  350. package/src/ipc/routes/trust-rules.test.ts +0 -95
  351. package/src/ipc/skill-ipc-types.ts +41 -0
  352. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
  353. package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
  354. package/src/ipc/skill-routes/events.ts +12 -23
  355. package/src/ipc/skill-routes/identity.ts +4 -17
  356. package/src/ipc/skill-routes/index.ts +1 -1
  357. package/src/ipc/skill-server.ts +6 -39
  358. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
  359. package/src/live-voice/protocol.ts +4 -13
  360. package/src/mcp/manager.ts +0 -5
  361. package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
  362. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
  363. package/src/memory/app-git-service.ts +0 -32
  364. package/src/memory/app-store.ts +154 -0
  365. package/src/memory/attachments-store.ts +6 -0
  366. package/src/memory/context-search/sources/memory-v2.ts +578 -0
  367. package/src/memory/context-search/sources/memory.ts +5 -0
  368. package/src/memory/context-search/sources/pkb.ts +10 -1
  369. package/src/memory/context-search/sources/workspace.ts +3 -2
  370. package/src/memory/conversation-crud.ts +29 -4
  371. package/src/memory/conversation-disk-view.ts +1 -5
  372. package/src/memory/conversation-starter-checkpoints.ts +63 -0
  373. package/src/memory/db-connection.ts +62 -0
  374. package/src/memory/db-init.ts +14 -0
  375. package/src/memory/embedding-backend.ts +3 -21
  376. package/src/memory/embedding-gemini.ts +0 -2
  377. package/src/memory/embedding-local.ts +6 -6
  378. package/src/memory/embedding-ollama.ts +6 -6
  379. package/src/memory/embedding-openai.ts +6 -6
  380. package/src/memory/embedding-types.ts +21 -0
  381. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
  382. package/src/memory/graph/conversation-graph-memory.ts +35 -13
  383. package/src/memory/graph/injection.test.ts +2 -2
  384. package/src/memory/graph/injection.ts +1 -1
  385. package/src/memory/guardian-action-store.ts +0 -83
  386. package/src/memory/guardian-approvals.ts +0 -48
  387. package/src/memory/indexer.ts +1 -15
  388. package/src/memory/job-handlers/conversation-starters.ts +36 -53
  389. package/src/memory/job-utils.ts +0 -6
  390. package/src/memory/jobs-store.ts +0 -1
  391. package/src/memory/jobs-worker.ts +2 -16
  392. package/src/memory/llm-request-log-store.ts +0 -41
  393. package/src/memory/llm-usage-store.ts +129 -43
  394. package/src/memory/memory-v2-activation-log-store.ts +115 -0
  395. package/src/memory/migrations/233-document-conversations.ts +54 -0
  396. package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
  397. package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
  398. package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
  399. package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
  400. package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
  401. package/src/memory/migrations/index.ts +14 -0
  402. package/src/memory/migrations/registry.ts +24 -0
  403. package/src/memory/raw-query.ts +2 -68
  404. package/src/memory/schema/conversations.ts +7 -0
  405. package/src/memory/schema/infrastructure.ts +25 -0
  406. package/src/memory/search/semantic.ts +5 -16
  407. package/src/memory/tool-usage-store.ts +2 -0
  408. package/src/memory/usage-buckets.ts +40 -1
  409. package/src/memory/usage-grouped-buckets.ts +127 -0
  410. package/src/memory/v2/__tests__/activation.test.ts +289 -90
  411. package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
  412. package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
  413. package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
  414. package/src/memory/v2/__tests__/injection.test.ts +384 -15
  415. package/src/memory/v2/__tests__/migration.test.ts +64 -36
  416. package/src/memory/v2/__tests__/page-store.test.ts +191 -8
  417. package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
  418. package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
  419. package/src/memory/v2/__tests__/static-context.test.ts +153 -0
  420. package/src/memory/v2/activation.ts +168 -97
  421. package/src/memory/v2/backfill-jobs.ts +15 -100
  422. package/src/memory/v2/consolidation-job.ts +14 -12
  423. package/src/memory/v2/edge-index.ts +191 -0
  424. package/src/memory/v2/injection.ts +182 -58
  425. package/src/memory/v2/migration.ts +57 -64
  426. package/src/memory/v2/now-text.ts +2 -3
  427. package/src/memory/v2/page-store.ts +168 -31
  428. package/src/memory/v2/prompts/consolidation.ts +118 -42
  429. package/src/memory/v2/prompts/sweep.ts +3 -3
  430. package/src/memory/v2/skill-store.ts +55 -7
  431. package/src/memory/v2/static-context.ts +62 -0
  432. package/src/memory/v2/types.ts +10 -20
  433. package/src/memory/validation.ts +0 -11
  434. package/src/messaging/draft-store.ts +0 -6
  435. package/src/messaging/provider-types.ts +8 -0
  436. package/src/messaging/provider.ts +7 -0
  437. package/src/messaging/providers/gmail/client.ts +1 -121
  438. package/src/messaging/providers/outlook/client.ts +0 -73
  439. package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
  440. package/src/messaging/providers/slack/adapter.ts +122 -21
  441. package/src/messaging/providers/slack/backfill.test.ts +95 -6
  442. package/src/messaging/providers/slack/backfill.ts +89 -11
  443. package/src/messaging/providers/slack/client.ts +10 -124
  444. package/src/messaging/providers/slack/message-metadata.ts +12 -2
  445. package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
  446. package/src/messaging/providers/slack/render-transcript.ts +126 -25
  447. package/src/messaging/providers/slack/types.ts +1 -0
  448. package/src/oauth/connection-resolver.test.ts +8 -0
  449. package/src/oauth/connection-resolver.ts +8 -16
  450. package/src/oauth/credential-token-resolver.ts +97 -0
  451. package/src/oauth/manual-token-connection.ts +30 -34
  452. package/src/oauth/oauth-store.ts +6 -4
  453. package/src/outbound-proxy/certs.ts +0 -7
  454. package/src/outbound-proxy/config.ts +0 -74
  455. package/src/outbound-proxy/health.ts +0 -44
  456. package/src/outbound-proxy/index.ts +0 -22
  457. package/src/permissions/approval-provenance.test.ts +184 -0
  458. package/src/permissions/approval-provenance.ts +70 -0
  459. package/src/permissions/checker.ts +4 -1
  460. package/src/permissions/gateway-threshold-reader.ts +4 -1
  461. package/src/permissions/prompter.ts +9 -2
  462. package/src/permissions/secret-prompter.ts +21 -48
  463. package/src/permissions/types.ts +33 -0
  464. package/src/permissions/workspace-policy.ts +0 -5
  465. package/src/platform/sync-identity.ts +0 -8
  466. package/src/plugins/defaults/injectors.ts +69 -2
  467. package/src/plugins/defaults/overflow-reduce.ts +3 -2
  468. package/src/plugins/types.ts +8 -0
  469. package/src/prompts/system-prompt.ts +34 -70
  470. package/src/prompts/templates/BOOTSTRAP.md +52 -6
  471. package/src/prompts/update-bulletin-job.ts +2 -0
  472. package/src/providers/__tests__/retry-callsite.test.ts +138 -1
  473. package/src/providers/anthropic/client.ts +72 -33
  474. package/src/providers/call-site-routing.ts +42 -3
  475. package/src/providers/gemini/client.ts +18 -2
  476. package/src/providers/managed-proxy/context.ts +0 -5
  477. package/src/providers/model-catalog.ts +105 -19
  478. package/src/providers/openai/chat-completions-provider.ts +6 -0
  479. package/src/providers/openai/responses-provider.ts +7 -1
  480. package/src/providers/provider-send-message.ts +45 -2
  481. package/src/providers/ratelimit.ts +7 -2
  482. package/src/providers/registry.ts +14 -9
  483. package/src/providers/retry.ts +96 -8
  484. package/src/providers/types.ts +13 -0
  485. package/src/providers/usage-tracking.ts +96 -0
  486. package/src/runtime/AGENTS.md +10 -6
  487. package/src/runtime/__tests__/agent-wake.test.ts +89 -0
  488. package/src/runtime/agent-wake.ts +39 -2
  489. package/src/runtime/assistant-event-hub.ts +541 -45
  490. package/src/runtime/assistant-event.ts +1 -6
  491. package/src/runtime/auth/context.ts +0 -9
  492. package/src/runtime/auth/middleware.ts +1 -1
  493. package/src/runtime/auth/route-policy.ts +11 -9
  494. package/src/runtime/auth/token-service.ts +0 -11
  495. package/src/runtime/channel-approvals.ts +6 -2
  496. package/src/runtime/channel-verification-service.ts +3 -5
  497. package/src/runtime/http-errors.ts +0 -34
  498. package/src/runtime/http-router.ts +6 -3
  499. package/src/runtime/http-server.ts +22 -82
  500. package/src/runtime/http-types.ts +5 -0
  501. package/src/runtime/interactive-ui.ts +0 -1
  502. package/src/runtime/middleware/auth.ts +0 -20
  503. package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
  504. package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
  505. package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
  506. package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
  507. package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
  508. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
  509. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
  510. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
  511. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
  512. package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
  513. package/src/runtime/migrations/migration-transport.ts +46 -13
  514. package/src/runtime/migrations/migration-wizard.ts +2 -2
  515. package/src/runtime/migrations/origin-mode.ts +40 -0
  516. package/src/runtime/migrations/vbundle-builder.ts +133 -79
  517. package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
  518. package/src/runtime/migrations/vbundle-importer.ts +7 -7
  519. package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
  520. package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
  521. package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
  522. package/src/runtime/migrations/vbundle-validator.ts +214 -41
  523. package/src/runtime/pending-interactions.ts +13 -4
  524. package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
  525. package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
  526. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
  527. package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
  528. package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
  529. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
  530. package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
  531. package/src/runtime/routes/acp-routes.test.ts +0 -3
  532. package/src/runtime/routes/acp-routes.ts +3 -7
  533. package/src/runtime/routes/app-management-routes.ts +18 -9
  534. package/src/runtime/routes/approval-routes.ts +55 -14
  535. package/src/runtime/routes/avatar-routes.ts +3 -5
  536. package/src/runtime/routes/browser-routes.ts +1 -15
  537. package/src/runtime/routes/channel-guardian-routes.ts +1 -5
  538. package/src/runtime/routes/channel-readiness-routes.ts +3 -7
  539. package/src/runtime/routes/channel-route-shared.ts +2 -28
  540. package/src/runtime/routes/client-routes.ts +45 -12
  541. package/src/runtime/routes/consolidation-routes.ts +115 -0
  542. package/src/runtime/routes/conversation-list-routes.ts +12 -29
  543. package/src/runtime/routes/conversation-management-routes.ts +14 -51
  544. package/src/runtime/routes/conversation-query-routes.ts +120 -8
  545. package/src/runtime/routes/conversation-routes.ts +44 -528
  546. package/src/runtime/routes/conversation-starter-routes.ts +19 -40
  547. package/src/runtime/routes/documents-routes.ts +53 -18
  548. package/src/runtime/routes/events-routes.ts +59 -91
  549. package/src/runtime/routes/filing-routes.ts +18 -1
  550. package/src/runtime/routes/guardian-action-routes.ts +4 -9
  551. package/src/runtime/routes/host-bash-routes.ts +3 -2
  552. package/src/runtime/routes/host-browser-routes.ts +9 -33
  553. package/src/runtime/routes/host-cu-routes.ts +6 -1
  554. package/src/runtime/routes/host-file-routes.ts +3 -2
  555. package/src/runtime/routes/host-transfer-routes.ts +11 -15
  556. package/src/runtime/routes/identity-routes.ts +78 -6
  557. package/src/runtime/routes/inbound-message-handler.ts +580 -137
  558. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
  559. package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
  560. package/src/runtime/routes/index.ts +4 -0
  561. package/src/runtime/routes/integrations/slack/channel.ts +0 -24
  562. package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
  563. package/src/runtime/routes/memory-v2-routes.ts +10 -15
  564. package/src/runtime/routes/migration-routes.ts +188 -31
  565. package/src/runtime/routes/playground/guard.ts +1 -1
  566. package/src/runtime/routes/playground/index.ts +0 -2
  567. package/src/runtime/routes/recording-routes.ts +4 -24
  568. package/src/runtime/routes/rename-conversation-routes.ts +2 -6
  569. package/src/runtime/routes/schedule-routes.ts +3 -6
  570. package/src/runtime/routes/secret-routes.ts +87 -18
  571. package/src/runtime/routes/settings-routes.ts +29 -28
  572. package/src/runtime/routes/skills-routes.ts +12 -31
  573. package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
  574. package/src/runtime/routes/task-routes.ts +6 -6
  575. package/src/runtime/routes/trust-rules-routes.ts +3 -94
  576. package/src/runtime/routes/types.ts +4 -4
  577. package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
  578. package/src/runtime/routes/usage-routes.ts +87 -10
  579. package/src/runtime/routes/user-routes.ts +17 -31
  580. package/src/runtime/routes/work-items-routes.ts +1 -4
  581. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
  582. package/src/runtime/services/analyze-conversation.ts +7 -17
  583. package/src/runtime/services/conversation-serializer.ts +2 -4
  584. package/src/runtime/verification-outbound-actions.ts +1 -1
  585. package/src/runtime/verification-rate-limiter.ts +1 -1
  586. package/src/schedule/schedule-store.ts +0 -16
  587. package/src/security/secret-scanner.ts +14 -547
  588. package/src/security/secure-keys.ts +31 -11
  589. package/src/security/token-manager.ts +7 -3
  590. package/src/signals/cancel.ts +16 -25
  591. package/src/signals/conversation-undo.ts +2 -27
  592. package/src/signals/emit-event.ts +1 -2
  593. package/src/signals/user-message.ts +108 -22
  594. package/src/skills/catalog-install.ts +1 -0
  595. package/src/skills/clawhub.ts +2 -2
  596. package/src/skills/inline-command-runner.ts +1 -7
  597. package/src/subagent/manager.ts +67 -84
  598. package/src/tasks/task-store.ts +1 -28
  599. package/src/telemetry/types.ts +6 -0
  600. package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
  601. package/src/telemetry/usage-telemetry-reporter.ts +3 -5
  602. package/src/tools/acp/spawn.test.ts +1 -2
  603. package/src/tools/acp/steer.test.ts +1 -2
  604. package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
  605. package/src/tools/browser/browser-execution.ts +31 -147
  606. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
  607. package/src/tools/browser/cdp-client/factory.ts +48 -76
  608. package/src/tools/browser/cdp-client/index.ts +1 -14
  609. package/src/tools/executor.ts +44 -31
  610. package/src/tools/host-filesystem/edit.ts +3 -2
  611. package/src/tools/host-filesystem/read.ts +3 -2
  612. package/src/tools/host-filesystem/transfer.test.ts +45 -42
  613. package/src/tools/host-filesystem/transfer.ts +4 -3
  614. package/src/tools/host-filesystem/write.ts +3 -2
  615. package/src/tools/host-terminal/host-shell.ts +4 -3
  616. package/src/tools/network/script-proxy/index.ts +1 -10
  617. package/src/tools/permission-checker.ts +66 -1
  618. package/src/tools/skills/sandbox-runner.ts +1 -6
  619. package/src/tools/skills/skill-tool-factory.ts +32 -0
  620. package/src/tools/terminal/safe-env.ts +1 -0
  621. package/src/tools/terminal/shell.ts +2 -78
  622. package/src/tools/types.ts +12 -39
  623. package/src/tts/__tests__/provider-catalog.test.ts +2 -2
  624. package/src/tts/provider-catalog.ts +1 -1
  625. package/src/usage/actors.ts +2 -1
  626. package/src/usage/attribution.ts +185 -0
  627. package/src/usage/pricing.ts +166 -0
  628. package/src/usage/types.ts +14 -0
  629. package/src/util/json.ts +13 -0
  630. package/src/util/logger.ts +3 -3
  631. package/src/util/pricing.ts +50 -3
  632. package/src/work-items/work-item-runner.ts +15 -42
  633. package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
  634. package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
  635. package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
  636. package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
  637. package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
  638. package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
  639. package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
  640. package/src/workspace/migrations/registry.ts +8 -0
  641. package/src/workspace/provider-commit-message-generator.ts +3 -3
  642. package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
  643. package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
  644. package/src/__tests__/secret-detection-handler.test.ts +0 -67
  645. package/src/__tests__/secret-scanner-executor.test.ts +0 -450
  646. package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
  647. package/src/__tests__/terminal-sandbox.test.ts +0 -374
  648. package/src/__tests__/tool-notification-listener.test.ts +0 -65
  649. package/src/context/__tests__/microcompact.test.ts +0 -805
  650. package/src/context/microcompact.ts +0 -443
  651. package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
  652. package/src/events/tool-notification-listener.ts +0 -17
  653. package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
  654. package/src/memory/v2/__tests__/edges.test.ts +0 -435
  655. package/src/memory/v2/edges.ts +0 -217
  656. package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
  657. package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
  658. package/src/runtime/__tests__/client-registry.test.ts +0 -271
  659. package/src/runtime/chrome-extension-registry.ts +0 -368
  660. package/src/runtime/client-registry.ts +0 -254
  661. package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
  662. package/src/tools/secret-detection-handler.ts +0 -269
  663. package/src/tools/terminal/backends/native.ts +0 -327
  664. package/src/tools/terminal/backends/types.ts +0 -37
  665. package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
  666. package/src/tools/terminal/sandbox.ts +0 -40
@@ -9,7 +9,7 @@
9
9
  * This module lets a caller validate a bundle while streaming:
10
10
  * - `readAndValidateManifest` consumes the first tar entry (which must be
11
11
  * `manifest.json`), validates the schema, and verifies the self-referencing
12
- * `manifest_sha256` against the canonicalized JSON.
12
+ * `checksum` against the canonicalized JSON.
13
13
  * - `createHashVerifier` returns a passthrough `Transform` that hashes bytes
14
14
  * flowing through it and errors the pipeline if the final digest or byte
15
15
  * count does not match the expected values from the manifest.
@@ -24,9 +24,12 @@ import { Transform, type TransformCallback } from "node:stream";
24
24
 
25
25
  import type { StreamedTarEntry } from "./vbundle-tar-stream.js";
26
26
  import {
27
- computeManifestSha256,
27
+ computeLegacyManifestSha256,
28
+ computeManifestChecksum,
29
+ LegacyManifestSchema,
28
30
  ManifestSchema,
29
31
  type ManifestType,
32
+ translateLegacyManifest,
30
33
  } from "./vbundle-validator.js";
31
34
 
32
35
  // ---------------------------------------------------------------------------
@@ -35,7 +38,7 @@ import {
35
38
 
36
39
  export interface ManifestReadResult {
37
40
  manifest: ManifestType;
38
- /** Fast lookup from archive path -> expected sha256 + size (from manifest.files). */
41
+ /** Fast lookup from archive path -> expected sha256 + size (from manifest.contents). */
39
42
  expected: Map<string, { sha256: string; size: number }>;
40
43
  }
41
44
 
@@ -75,7 +78,7 @@ const MANIFEST_MAX_BYTES = 1 * 1024 * 1024;
75
78
  * 2. Size cap (1 MiB).
76
79
  * 3. JSON parse.
77
80
  * 4. Zod schema validation.
78
- * 5. Self-referencing `manifest_sha256` verification against the
81
+ * 5. Self-referencing `checksum` verification against the
79
82
  * canonicalized JSON (minus that field).
80
83
  *
81
84
  * On success, returns the parsed manifest plus a `Map` keyed by archive
@@ -131,39 +134,58 @@ export async function readAndValidateManifest(
131
134
  );
132
135
  }
133
136
 
137
+ // Try the v1 schema first; fall back to the legacy six-field shape so
138
+ // existing on-disk bundles (backup snapshots, cross-version migrations)
139
+ // keep streaming-validating after upgrade. AGENTS.md prohibits silent
140
+ // breaks of persisted state.
134
141
  const parseResult = ManifestSchema.safeParse(manifestRaw);
135
- if (!parseResult.success) {
136
- const issues = parseResult.error.issues
137
- .map((i) => `${i.path.join(".") || "<root>"}: ${i.message}`)
138
- .join("; ");
139
- throw new StreamingValidationError(
140
- "manifest_schema",
141
- `manifest.json failed schema validation: ${issues}`,
142
- );
143
- }
144
-
145
- const manifest = parseResult.data;
142
+ let manifest: ManifestType;
146
143
 
147
- // Recompute the self-referencing checksum using the exact canonicalization
148
- // that vbundle-validator.ts uses. Any drift here would silently reject
149
- // valid bundles produced by buildVBundle.
150
- const computed = computeManifestSha256(manifestRaw);
151
- if (computed !== manifest.manifest_sha256) {
152
- throw new StreamingValidationError(
153
- "manifest_sha256",
154
- `Manifest checksum mismatch: expected ${manifest.manifest_sha256}, computed ${computed}`,
155
- );
144
+ if (parseResult.success) {
145
+ manifest = parseResult.data;
146
+ // Recompute the self-referencing checksum using the exact canonicalization
147
+ // that vbundle-validator.ts uses. Any drift here would silently reject
148
+ // valid bundles produced by buildVBundle.
149
+ const computed = computeManifestChecksum(manifestRaw);
150
+ if (computed !== manifest.checksum) {
151
+ throw new StreamingValidationError(
152
+ "manifest_sha256",
153
+ `Manifest checksum mismatch: expected ${manifest.checksum}, computed ${computed}`,
154
+ );
155
+ }
156
+ } else {
157
+ const legacyParse = LegacyManifestSchema.safeParse(manifestRaw);
158
+ if (!legacyParse.success) {
159
+ const issues = parseResult.error.issues
160
+ .map((i) => `${i.path.join(".") || "<root>"}: ${i.message}`)
161
+ .join("; ");
162
+ throw new StreamingValidationError(
163
+ "manifest_schema",
164
+ `manifest.json failed schema validation: ${issues}`,
165
+ );
166
+ }
167
+ const legacy = legacyParse.data;
168
+ // Verify the legacy checksum using the OLD canonicalization (strip the
169
+ // field entirely; do NOT replace with "").
170
+ const computedLegacy = computeLegacyManifestSha256(manifestRaw);
171
+ if (computedLegacy !== legacy.manifest_sha256) {
172
+ throw new StreamingValidationError(
173
+ "manifest_sha256",
174
+ `Manifest checksum mismatch: expected ${legacy.manifest_sha256}, computed ${computedLegacy}`,
175
+ );
176
+ }
177
+ manifest = translateLegacyManifest(legacy);
156
178
  }
157
179
 
158
180
  const expected = new Map<string, { sha256: string; size: number }>();
159
- for (const file of manifest.files) {
181
+ for (const file of manifest.contents) {
160
182
  if (expected.has(file.path)) {
161
183
  throw new StreamingValidationError(
162
184
  "manifest_duplicate_path",
163
185
  `Manifest contains duplicate entry for path: ${file.path}`,
164
186
  );
165
187
  }
166
- expected.set(file.path, { sha256: file.sha256, size: file.size });
188
+ expected.set(file.path, { sha256: file.sha256, size: file.size_bytes });
167
189
  }
168
190
 
169
191
  return { manifest, expected };
@@ -5,7 +5,6 @@
5
5
  * - manifest.json: metadata with schema_version, checksums, and bundle info
6
6
  * - workspace/: the entire workspace directory tree (new format), OR
7
7
  * data/db/assistant.db + config/settings.json (old format)
8
- * - trust/trust.json: trust rules (optional)
9
8
  *
10
9
  * Validation steps:
11
10
  * 1. Archive structure: valid gzip tar with required entries
@@ -14,32 +13,179 @@
14
13
  * 4. Per-file content integrity: SHA-256 of each file matches manifest checksums
15
14
  */
16
15
 
17
- import { createHash } from "node:crypto";
16
+ import { createHash, randomUUID } from "node:crypto";
18
17
  import { gunzipSync } from "node:zlib";
19
18
 
20
19
  import { z } from "zod";
21
20
 
22
21
  // ---------------------------------------------------------------------------
23
- // Manifest schema
22
+ // Manifest schema (v1)
24
23
  // ---------------------------------------------------------------------------
25
24
 
26
25
  const ManifestFileEntry = z.object({
26
+ path: z.string().min(1),
27
+ sha256: z.string().regex(/^[0-9a-f]{64}$/),
28
+ size_bytes: z.number().int().nonnegative(),
29
+ });
30
+
31
+ const AssistantInfo = z.object({
32
+ id: z.string().min(1),
33
+ name: z.string().min(1),
34
+ runtime_version: z.string().min(1),
35
+ });
36
+
37
+ const Origin = z.object({
38
+ mode: z.enum(["managed", "self-hosted-remote", "self-hosted-local"]),
39
+ platform_version: z.string().optional(),
40
+ hostname: z.string().optional(),
41
+ });
42
+
43
+ const Compatibility = z.object({
44
+ min_runtime_version: z.string().min(1),
45
+ max_runtime_version: z.string().nullable(),
46
+ });
47
+
48
+ const ExportOptions = z.object({
49
+ include_logs: z.boolean(),
50
+ include_browser_state: z.boolean(),
51
+ include_memory_vectors: z.boolean(),
52
+ });
53
+
54
+ export const ManifestSchema = z
55
+ .object({
56
+ schema_version: z.literal(1),
57
+ bundle_id: z.string().uuid(),
58
+ created_at: z.string().datetime({ offset: true }),
59
+ assistant: AssistantInfo,
60
+ origin: Origin,
61
+ compatibility: Compatibility,
62
+ contents: z.array(ManifestFileEntry),
63
+ checksum: z.string().regex(/^[0-9a-f]{64}$/),
64
+ secrets_redacted: z.boolean(),
65
+ export_options: ExportOptions,
66
+ })
67
+ .refine((m) => m.origin.mode !== "managed" || m.secrets_redacted === true, {
68
+ message: "secrets_redacted must be true when origin.mode is 'managed'",
69
+ path: ["secrets_redacted"],
70
+ })
71
+ .refine(
72
+ (m) =>
73
+ m.contents.some(
74
+ (f) =>
75
+ f.path === "data/db/assistant.db" ||
76
+ f.path === "workspace/data/db/assistant.db",
77
+ ),
78
+ {
79
+ message:
80
+ "contents must include an entry for data/db/assistant.db (legacy format) or workspace/data/db/assistant.db (current format)",
81
+ path: ["contents"],
82
+ },
83
+ );
84
+
85
+ export type ManifestFileEntryType = z.infer<typeof ManifestFileEntry>;
86
+ export type ManifestType = z.infer<typeof ManifestSchema>;
87
+
88
+ // ---------------------------------------------------------------------------
89
+ // Legacy manifest schema (pre-v1, six-field shape)
90
+ // ---------------------------------------------------------------------------
91
+ //
92
+ // Older runtime versions wrote a six-field manifest with `schema_version: "1.0"`,
93
+ // `files`, `size` (per-entry), and a self-referencing `manifest_sha256` field.
94
+ // Existing on-disk artifacts produced by those versions — backup snapshots,
95
+ // cross-version migration bundles — must keep validating after upgrade,
96
+ // per AGENTS.md "no silent breaks of persisted state".
97
+ //
98
+ // We accept legacy bundles via a fallback parse + translator so the rest of
99
+ // the validation pipeline (per-file hash + size verification) only ever sees
100
+ // the v1 shape.
101
+
102
+ const LegacyManifestFileEntry = z.object({
27
103
  path: z.string(),
28
104
  sha256: z.string(),
29
105
  size: z.number().int().nonnegative(),
30
106
  });
31
107
 
32
- export const ManifestSchema = z.object({
108
+ export const LegacyManifestSchema = z.object({
33
109
  schema_version: z.string(),
34
110
  created_at: z.string(),
35
111
  source: z.string().optional(),
36
112
  description: z.string().optional(),
37
- files: z.array(ManifestFileEntry),
113
+ files: z.array(LegacyManifestFileEntry),
38
114
  manifest_sha256: z.string(),
39
115
  });
40
116
 
41
- export type ManifestFileEntryType = z.infer<typeof ManifestFileEntry>;
42
- export type ManifestType = z.infer<typeof ManifestSchema>;
117
+ export type LegacyManifestType = z.infer<typeof LegacyManifestSchema>;
118
+
119
+ /**
120
+ * Recompute the legacy `manifest_sha256` field — strips the field entirely
121
+ * (rather than emptying it) before canonicalizing, matching the pre-v1
122
+ * producer behavior. Required so legacy bundles whose checksum was computed
123
+ * the old way still verify after upgrade.
124
+ */
125
+ export function computeLegacyManifestSha256(manifest: unknown): string {
126
+ const copy = { ...(manifest as Record<string, unknown>) };
127
+ delete copy.manifest_sha256;
128
+ return sha256Hex(canonicalizeJson(copy));
129
+ }
130
+
131
+ /**
132
+ * Coerce a legacy ISO-ish `created_at` into the v1 datetime regex shape.
133
+ * Pre-v1 producers always wrote `new Date().toISOString()`, which already
134
+ * has the `Z` suffix the v1 regex requires; this helper is defensive against
135
+ * any historical producer that omitted the offset/`Z`.
136
+ */
137
+ function coerceLegacyCreatedAt(raw: string): string {
138
+ // If the string already parses as a Date, keep it as the canonical ISO form.
139
+ const parsed = new Date(raw);
140
+ if (!Number.isNaN(parsed.getTime())) {
141
+ // `toISOString()` always emits the `...Z` form the v1 regex accepts.
142
+ return parsed.toISOString();
143
+ }
144
+ return raw;
145
+ }
146
+
147
+ /**
148
+ * Translate a parsed legacy manifest into a v1 `ManifestType` so the rest of
149
+ * the validator pipeline can operate on a uniform shape.
150
+ *
151
+ * Legacy bundles never carried assistant identity, origin, compatibility, or
152
+ * export-option signals; we substitute conservative placeholders that satisfy
153
+ * the v1 schema's `.refine()` rules without misrepresenting the source bundle.
154
+ */
155
+ export function translateLegacyManifest(
156
+ legacy: LegacyManifestType,
157
+ ): ManifestType {
158
+ return {
159
+ schema_version: 1,
160
+ bundle_id: randomUUID(),
161
+ created_at: coerceLegacyCreatedAt(legacy.created_at),
162
+ assistant: {
163
+ id: "self",
164
+ name: "Assistant",
165
+ runtime_version: "0.0.0-legacy",
166
+ },
167
+ // Legacy bundles came from the local self-hosted exporter; the
168
+ // conservative default is "self-hosted-local" so the v1 managed/secrets
169
+ // refine never trips on a translated legacy bundle.
170
+ origin: { mode: "self-hosted-local" },
171
+ compatibility: {
172
+ min_runtime_version: "0.0.0-legacy",
173
+ max_runtime_version: null,
174
+ },
175
+ contents: legacy.files.map((f) => ({
176
+ path: f.path,
177
+ sha256: f.sha256,
178
+ size_bytes: f.size,
179
+ })),
180
+ checksum: legacy.manifest_sha256,
181
+ secrets_redacted: false,
182
+ export_options: {
183
+ include_logs: false,
184
+ include_browser_state: false,
185
+ include_memory_vectors: false,
186
+ },
187
+ };
188
+ }
43
189
 
44
190
  // ---------------------------------------------------------------------------
45
191
  // Validation result types
@@ -190,14 +336,16 @@ export function canonicalizeJson(obj: unknown): string {
190
336
  }
191
337
 
192
338
  /**
193
- * Recompute the `manifest_sha256` field for a manifest object. Strips the
194
- * `manifest_sha256` property, canonicalizes the remaining JSON, and returns
195
- * the SHA-256 hex digest. Centralized here so the streaming validator and
196
- * the in-memory validator agree on the exact canonicalization.
339
+ * Recompute the `checksum` field for a manifest object.
340
+ *
341
+ * The v1 schema spec says the checksum is computed over the canonicalized
342
+ * manifest with the `checksum` field set to the empty string (not absent),
343
+ * so we replace it before canonicalizing — both producers and validators
344
+ * must agree on this exact wire shape. Centralized here so the streaming
345
+ * validator and the in-memory validator agree on the exact canonicalization.
197
346
  */
198
- export function computeManifestSha256(manifest: unknown): string {
199
- const copy = { ...(manifest as Record<string, unknown>) };
200
- delete copy.manifest_sha256;
347
+ export function computeManifestChecksum(manifest: unknown): string {
348
+ const copy = { ...(manifest as Record<string, unknown>), checksum: "" };
201
349
  return sha256Hex(canonicalizeJson(copy));
202
350
  }
203
351
 
@@ -218,7 +366,7 @@ const MAX_DECOMPRESSED_SIZE = 2 * 1024 * 1024 * 1024;
218
366
  * Performs four validation passes:
219
367
  * 1. Archive structure (gzip decompression, tar parsing, required entries)
220
368
  * 2. Manifest schema (Zod validation of manifest.json)
221
- * 3. Manifest checksum (SHA-256 of canonicalized JSON without manifest_sha256)
369
+ * 3. Manifest checksum (SHA-256 of canonicalized JSON with the `checksum` field set to empty string)
222
370
  * 4. Per-file content integrity (SHA-256 of each file vs manifest declaration)
223
371
  */
224
372
  export function validateVBundle(data: Uint8Array): VBundleValidationResult {
@@ -293,39 +441,64 @@ export function validateVBundle(data: Uint8Array): VBundleValidationResult {
293
441
  return { is_valid: false, errors };
294
442
  }
295
443
 
444
+ // Try the v1 schema first. If that fails, fall back to the legacy six-field
445
+ // shape so existing on-disk bundles (backup snapshots, cross-version
446
+ // migrations) keep validating after upgrade. AGENTS.md prohibits silent
447
+ // breaks of persisted state.
296
448
  const parseResult = ManifestSchema.safeParse(manifestRaw);
297
- if (!parseResult.success) {
298
- for (const issue of parseResult.error.issues) {
449
+ let manifest: ManifestType;
450
+
451
+ if (parseResult.success) {
452
+ manifest = parseResult.data;
453
+
454
+ // Step 5 (v1): Verify manifest checksum — SHA-256 of canonicalized JSON
455
+ // with the `checksum` field replaced by an empty string.
456
+ const computedChecksum = computeManifestChecksum(manifestRaw);
457
+ if (computedChecksum !== manifest.checksum) {
299
458
  errors.push({
300
- code: "MANIFEST_SCHEMA_ERROR",
301
- message: `Manifest validation error at ${issue.path.join(".")}: ${
302
- issue.message
303
- }`,
304
- path: `manifest.json/${issue.path.join(".")}`,
459
+ code: "MANIFEST_CHECKSUM_MISMATCH",
460
+ message: `Manifest checksum mismatch: expected ${manifest.checksum}, computed ${computedChecksum}`,
461
+ path: "manifest.json",
305
462
  });
306
463
  }
307
- return { is_valid: false, errors };
308
- }
309
-
310
- const manifest = parseResult.data;
464
+ } else {
465
+ const legacyParse = LegacyManifestSchema.safeParse(manifestRaw);
466
+ if (!legacyParse.success) {
467
+ // Truly malformed — surface the v1 error for the clearer error trail.
468
+ for (const issue of parseResult.error.issues) {
469
+ errors.push({
470
+ code: "MANIFEST_SCHEMA_ERROR",
471
+ message: `Manifest validation error at ${issue.path.join(".")}: ${
472
+ issue.message
473
+ }`,
474
+ path: `manifest.json/${issue.path.join(".")}`,
475
+ });
476
+ }
477
+ return { is_valid: false, errors };
478
+ }
311
479
 
312
- // Step 5: Verify manifest checksum
313
- // The manifest_sha256 field is the SHA-256 of the canonicalized JSON
314
- // with the manifest_sha256 field itself excluded.
315
- const computedManifestSha256 = computeManifestSha256(manifestRaw);
480
+ // Step 5 (legacy): Verify the legacy `manifest_sha256` using the OLD
481
+ // canonicalization (strip the field entirely; do NOT replace with "").
482
+ const legacy = legacyParse.data;
483
+ const computedLegacyChecksum = computeLegacyManifestSha256(manifestRaw);
484
+ if (computedLegacyChecksum !== legacy.manifest_sha256) {
485
+ errors.push({
486
+ code: "MANIFEST_CHECKSUM_MISMATCH",
487
+ message: `Manifest checksum mismatch: expected ${legacy.manifest_sha256}, computed ${computedLegacyChecksum}`,
488
+ path: "manifest.json",
489
+ });
490
+ return { is_valid: false, errors };
491
+ }
316
492
 
317
- if (computedManifestSha256 !== manifest.manifest_sha256) {
318
- errors.push({
319
- code: "MANIFEST_CHECKSUM_MISMATCH",
320
- message: `Manifest checksum mismatch: expected ${manifest.manifest_sha256}, computed ${computedManifestSha256}`,
321
- path: "manifest.json",
322
- });
493
+ // Translate to v1 so the rest of the pipeline (per-file hash + size
494
+ // verification, refine rules) sees a uniform shape.
495
+ manifest = translateLegacyManifest(legacy);
323
496
  }
324
497
 
325
498
  // Step 6: Verify per-file content integrity
326
- const manifestFilePaths = new Set(manifest.files.map((f) => f.path));
499
+ const manifestFilePaths = new Set(manifest.contents.map((f) => f.path));
327
500
 
328
- for (const fileEntry of manifest.files) {
501
+ for (const fileEntry of manifest.contents) {
329
502
  const archiveEntry = entryMap.get(fileEntry.path);
330
503
  if (!archiveEntry) {
331
504
  errors.push({
@@ -337,10 +510,10 @@ export function validateVBundle(data: Uint8Array): VBundleValidationResult {
337
510
  }
338
511
 
339
512
  // Verify size
340
- if (archiveEntry.size !== fileEntry.size) {
513
+ if (archiveEntry.size !== fileEntry.size_bytes) {
341
514
  errors.push({
342
515
  code: "FILE_SIZE_MISMATCH",
343
- message: `Size mismatch for ${fileEntry.path}: manifest declares ${fileEntry.size} bytes, archive has ${archiveEntry.size} bytes`,
516
+ message: `Size mismatch for ${fileEntry.path}: manifest declares ${fileEntry.size_bytes} bytes, archive has ${archiveEntry.size} bytes`,
344
517
  path: fileEntry.path,
345
518
  });
346
519
  }
@@ -364,7 +537,7 @@ export function validateVBundle(data: Uint8Array): VBundleValidationResult {
364
537
  if (!manifestFilePaths.has(required)) {
365
538
  errors.push({
366
539
  code: "REQUIRED_FILE_NOT_IN_MANIFEST",
367
- message: `Required file ${required} exists in archive but has no checksum entry in manifest.files`,
540
+ message: `Required file ${required} exists in archive but has no checksum entry in manifest.contents`,
368
541
  path: required,
369
542
  });
370
543
  }
@@ -13,7 +13,6 @@
13
13
  * resolve the interaction.
14
14
  */
15
15
 
16
- import type { Conversation } from "../daemon/conversation.js";
17
16
  import type { UserDecision } from "../permissions/types.js";
18
17
 
19
18
  export interface ConfirmationDetails {
@@ -39,7 +38,6 @@ export interface ConfirmationDetails {
39
38
  }
40
39
 
41
40
  export interface PendingInteraction {
42
- conversation: Conversation | null;
43
41
  conversationId: string;
44
42
  kind:
45
43
  | "confirmation"
@@ -112,10 +110,10 @@ export function getByConversation(
112
110
  * /v1/host-transfer-result after completing the operation, get a 404, and the
113
111
  * proxy timer would fire with a spurious timeout error.
114
112
  */
115
- export function removeByConversation(conversation: Conversation): void {
113
+ export function removeByConversation(conversationId: string): void {
116
114
  for (const [requestId, interaction] of pending) {
117
115
  if (
118
- interaction.conversation === conversation &&
116
+ interaction.conversationId === conversationId &&
119
117
  interaction.kind !== "host_bash" &&
120
118
  interaction.kind !== "host_file" &&
121
119
  interaction.kind !== "host_cu" &&
@@ -143,6 +141,17 @@ export function getByKind(
143
141
  return results;
144
142
  }
145
143
 
144
+ /**
145
+ * Return all pending interactions across all conversations.
146
+ */
147
+ export function getAll(): Array<{ requestId: string } & PendingInteraction> {
148
+ const results: Array<{ requestId: string } & PendingInteraction> = [];
149
+ for (const [requestId, interaction] of pending) {
150
+ results.push({ requestId, ...interaction });
151
+ }
152
+ return results;
153
+ }
154
+
146
155
  /** Clear all pending interactions. Useful for testing. */
147
156
  export function clear(): void {
148
157
  pending.clear();
@@ -41,7 +41,6 @@ mock.module("../../../acp/index.js", () => ({
41
41
  getAcpSessionManager: () => ({
42
42
  getStatus: () => fakeInMemorySessions,
43
43
  }),
44
- broadcastToAllClients: null,
45
44
  }));
46
45
 
47
46
  import { getSqlite } from "../../../memory/db-connection.js";
@@ -26,6 +26,7 @@ import type { BackupRunResult } from "../../../backup/backup-worker.js";
26
26
  import type { RestoreResult, VerifyResult } from "../../../backup/restore.js";
27
27
  import type { BackupConfig } from "../../../config/schema.js";
28
28
  import { BackupConfigSchema } from "../../../config/schema.js";
29
+ import type { ManifestType } from "../../migrations/vbundle-validator.js";
29
30
 
30
31
  // ---------------------------------------------------------------------------
31
32
  // Module mocks — must appear before any imports of the module under test
@@ -144,13 +145,31 @@ interface VerifyCall {
144
145
 
145
146
  let lastRestoreArgs: RestoreCall | null = null;
146
147
  let lastVerifyArgs: VerifyCall | null = null;
147
- let mockRestoreResult: RestoreResult = {
148
- manifest: {
149
- schema_version: "1.0",
148
+
149
+ function makeV1Manifest(): ManifestType {
150
+ return {
151
+ schema_version: 1,
152
+ bundle_id: "00000000-0000-4000-8000-000000000000",
150
153
  created_at: "2026-04-11T10:00:00.000Z",
151
- files: [],
152
- manifest_sha256: "0".repeat(64),
153
- } as unknown as RestoreResult["manifest"],
154
+ assistant: { id: "self", name: "Test", runtime_version: "0.0.0-test" },
155
+ origin: { mode: "self-hosted-local" },
156
+ compatibility: {
157
+ min_runtime_version: "0.0.0-test",
158
+ max_runtime_version: null,
159
+ },
160
+ contents: [],
161
+ checksum: "0".repeat(64),
162
+ secrets_redacted: false,
163
+ export_options: {
164
+ include_logs: false,
165
+ include_browser_state: false,
166
+ include_memory_vectors: false,
167
+ },
168
+ };
169
+ }
170
+
171
+ let mockRestoreResult: RestoreResult = {
172
+ manifest: makeV1Manifest(),
154
173
  restoredFiles: 0,
155
174
  };
156
175
  let mockRestoreError: Error | null = null;
@@ -236,12 +255,7 @@ beforeEach(() => {
236
255
  lastVerifyArgs = null;
237
256
  mockRestoreError = null;
238
257
  mockRestoreResult = {
239
- manifest: {
240
- schema_version: "1.0",
241
- created_at: "2026-04-11T10:00:00.000Z",
242
- files: [],
243
- manifest_sha256: "0".repeat(64),
244
- } as unknown as RestoreResult["manifest"],
258
+ manifest: makeV1Manifest(),
245
259
  restoredFiles: 0,
246
260
  };
247
261
  mockVerifyResult = { valid: true };
@@ -465,7 +479,7 @@ describe("handleBackupCreate", () => {
465
479
  await handleBackupCreate();
466
480
  expect(mockReadBackupKeyCalls).toBe(0);
467
481
  const keyFileExists = await import("node:fs").then((m) =>
468
- m.existsSync(join(ROOT, "workspace", "protected", "backup.key")),
482
+ m.existsSync(join(ROOT, "workspace", ".backup.key")),
469
483
  );
470
484
  expect(keyFileExists).toBe(false);
471
485
  });
@@ -768,12 +782,7 @@ describe("handleBackupVerify", () => {
768
782
  mockReadBackupKeyCalls = 0;
769
783
  mockVerifyResult = {
770
784
  valid: true,
771
- manifest: {
772
- schema_version: "1.0",
773
- created_at: "2026-04-11T10:00:00.000Z",
774
- files: [],
775
- manifest_sha256: "0".repeat(64),
776
- } as unknown as VerifyResult["manifest"],
785
+ manifest: makeV1Manifest(),
777
786
  };
778
787
 
779
788
  const result = (await handleBackupVerify({