@vellumai/assistant 0.4.16 → 0.4.18

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 (536) hide show
  1. package/Dockerfile +6 -6
  2. package/README.md +1 -2
  3. package/eslint.config.mjs +2 -2
  4. package/package.json +1 -1
  5. package/src/__tests__/access-request-decision.test.ts +128 -120
  6. package/src/__tests__/account-registry.test.ts +121 -110
  7. package/src/__tests__/active-skill-tools.test.ts +200 -172
  8. package/src/__tests__/actor-token-service.test.ts +341 -274
  9. package/src/__tests__/agent-loop-thinking.test.ts +28 -19
  10. package/src/__tests__/agent-loop.test.ts +798 -378
  11. package/src/__tests__/anthropic-provider.test.ts +405 -247
  12. package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
  13. package/src/__tests__/app-bundler.test.ts +112 -79
  14. package/src/__tests__/app-executors.test.ts +205 -178
  15. package/src/__tests__/app-git-history.test.ts +90 -73
  16. package/src/__tests__/app-git-service.test.ts +67 -53
  17. package/src/__tests__/app-open-proxy.test.ts +29 -25
  18. package/src/__tests__/approval-conversation-turn.test.ts +100 -81
  19. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
  20. package/src/__tests__/approval-message-composer.test.ts +119 -119
  21. package/src/__tests__/approval-primitive.test.ts +264 -233
  22. package/src/__tests__/approval-routes-http.test.ts +4 -3
  23. package/src/__tests__/asset-materialize-tool.test.ts +250 -178
  24. package/src/__tests__/asset-search-tool.test.ts +251 -191
  25. package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
  26. package/src/__tests__/assistant-attachments.test.ts +254 -186
  27. package/src/__tests__/assistant-event-hub.test.ts +105 -63
  28. package/src/__tests__/assistant-event.test.ts +66 -58
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
  30. package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
  31. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
  32. package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
  33. package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
  34. package/src/__tests__/attachments-store.test.ts +240 -183
  35. package/src/__tests__/attachments.test.ts +70 -62
  36. package/src/__tests__/audit-log-rotation.test.ts +50 -35
  37. package/src/__tests__/browser-fill-credential.test.ts +169 -101
  38. package/src/__tests__/browser-manager.test.ts +97 -75
  39. package/src/__tests__/browser-runtime-check.test.ts +16 -15
  40. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
  41. package/src/__tests__/browser-skill-endstate.test.ts +97 -72
  42. package/src/__tests__/bundle-scanner.test.ts +47 -22
  43. package/src/__tests__/bundled-asset.test.ts +74 -47
  44. package/src/__tests__/call-constants.test.ts +19 -19
  45. package/src/__tests__/call-controller.test.ts +1073 -751
  46. package/src/__tests__/call-conversation-messages.test.ts +90 -65
  47. package/src/__tests__/call-domain.test.ts +149 -121
  48. package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
  49. package/src/__tests__/call-pointer-messages.test.ts +213 -154
  50. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
  51. package/src/__tests__/call-recovery.test.ts +232 -212
  52. package/src/__tests__/call-routes-http.test.ts +328 -279
  53. package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
  54. package/src/__tests__/call-state-machine.test.ts +62 -51
  55. package/src/__tests__/call-state.test.ts +89 -75
  56. package/src/__tests__/call-store.test.ts +387 -316
  57. package/src/__tests__/callback-handoff-copy.test.ts +84 -82
  58. package/src/__tests__/canonical-guardian-store.test.ts +331 -280
  59. package/src/__tests__/channel-approval-routes.test.ts +1643 -1126
  60. package/src/__tests__/channel-approval.test.ts +139 -137
  61. package/src/__tests__/channel-approvals.test.ts +226 -182
  62. package/src/__tests__/channel-delivery-store.test.ts +232 -194
  63. package/src/__tests__/channel-guardian.test.ts +6 -3
  64. package/src/__tests__/channel-invite-transport.test.ts +107 -92
  65. package/src/__tests__/channel-policy.test.ts +42 -38
  66. package/src/__tests__/channel-readiness-service.test.ts +119 -102
  67. package/src/__tests__/channel-reply-delivery.test.ts +147 -118
  68. package/src/__tests__/channel-retry-sweep.test.ts +153 -110
  69. package/src/__tests__/checker.test.ts +3309 -1850
  70. package/src/__tests__/clarification-resolver.test.ts +91 -79
  71. package/src/__tests__/classifier.test.ts +64 -54
  72. package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
  73. package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
  74. package/src/__tests__/clawhub.test.ts +92 -82
  75. package/src/__tests__/cli.test.ts +30 -30
  76. package/src/__tests__/clipboard.test.ts +53 -46
  77. package/src/__tests__/commit-guarantee.test.ts +59 -52
  78. package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
  79. package/src/__tests__/compaction.benchmark.test.ts +33 -31
  80. package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
  81. package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
  82. package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
  83. package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
  84. package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
  85. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
  86. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
  87. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
  88. package/src/__tests__/computer-use-tools.test.ts +121 -98
  89. package/src/__tests__/config-schema.test.ts +443 -347
  90. package/src/__tests__/config-watcher.test.ts +96 -81
  91. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
  92. package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
  93. package/src/__tests__/conflict-policy.test.ts +151 -80
  94. package/src/__tests__/conflict-store.test.ts +203 -157
  95. package/src/__tests__/connection-policy.test.ts +89 -59
  96. package/src/__tests__/contacts-tools.test.ts +247 -178
  97. package/src/__tests__/context-memory-e2e.test.ts +306 -214
  98. package/src/__tests__/context-token-estimator.test.ts +114 -74
  99. package/src/__tests__/context-window-manager.test.ts +269 -167
  100. package/src/__tests__/contradiction-checker.test.ts +161 -135
  101. package/src/__tests__/conversation-attention-store.test.ts +350 -290
  102. package/src/__tests__/conversation-attention-telegram.test.ts +156 -114
  103. package/src/__tests__/conversation-pairing.test.ts +220 -113
  104. package/src/__tests__/conversation-routes-guardian-reply.test.ts +164 -104
  105. package/src/__tests__/conversation-routes.test.ts +71 -41
  106. package/src/__tests__/conversation-store.test.ts +390 -235
  107. package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
  108. package/src/__tests__/credential-broker-server-use.test.ts +283 -243
  109. package/src/__tests__/credential-broker.test.ts +128 -74
  110. package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
  111. package/src/__tests__/credential-metadata-store.test.ts +360 -311
  112. package/src/__tests__/credential-policy-validate.test.ts +81 -65
  113. package/src/__tests__/credential-resolve.test.ts +212 -145
  114. package/src/__tests__/credential-security-e2e.test.ts +144 -103
  115. package/src/__tests__/credential-security-invariants.test.ts +253 -208
  116. package/src/__tests__/credential-selection.test.ts +254 -146
  117. package/src/__tests__/credential-vault-unit.test.ts +531 -341
  118. package/src/__tests__/credential-vault.test.ts +761 -484
  119. package/src/__tests__/daemon-assistant-events.test.ts +91 -66
  120. package/src/__tests__/daemon-lifecycle.test.ts +258 -190
  121. package/src/__tests__/daemon-server-session-init.test.ts +257 -191
  122. package/src/__tests__/date-context.test.ts +314 -249
  123. package/src/__tests__/db-migration-rollback.test.ts +259 -130
  124. package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
  125. package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
  126. package/src/__tests__/deterministic-verification-control-plane.test.ts +183 -135
  127. package/src/__tests__/dictation-mode-detection.test.ts +77 -55
  128. package/src/__tests__/dictation-profile-store.test.ts +70 -56
  129. package/src/__tests__/dictation-text-processing.test.ts +53 -35
  130. package/src/__tests__/diff.test.ts +102 -98
  131. package/src/__tests__/domain-normalize.test.ts +54 -54
  132. package/src/__tests__/domain-policy.test.ts +71 -55
  133. package/src/__tests__/dynamic-page-surface.test.ts +31 -33
  134. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
  135. package/src/__tests__/edit-engine.test.ts +56 -56
  136. package/src/__tests__/elevenlabs-client.test.ts +117 -91
  137. package/src/__tests__/elevenlabs-config.test.ts +32 -31
  138. package/src/__tests__/email-classifier.test.ts +15 -12
  139. package/src/__tests__/email-cli.test.ts +121 -108
  140. package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
  141. package/src/__tests__/encrypted-store.test.ts +180 -154
  142. package/src/__tests__/entity-extractor.test.ts +108 -87
  143. package/src/__tests__/entity-search.test.ts +664 -258
  144. package/src/__tests__/ephemeral-permissions.test.ts +224 -188
  145. package/src/__tests__/event-bus.test.ts +81 -77
  146. package/src/__tests__/extract-email.test.ts +51 -0
  147. package/src/__tests__/file-edit-tool.test.ts +62 -44
  148. package/src/__tests__/file-ops-service.test.ts +131 -114
  149. package/src/__tests__/file-read-tool.test.ts +48 -31
  150. package/src/__tests__/file-write-tool.test.ts +43 -37
  151. package/src/__tests__/filesystem-tools.test.ts +238 -209
  152. package/src/__tests__/followup-tools.test.ts +237 -162
  153. package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
  154. package/src/__tests__/frontmatter.test.ts +96 -81
  155. package/src/__tests__/fuzzy-match-property.test.ts +75 -81
  156. package/src/__tests__/fuzzy-match.test.ts +71 -65
  157. package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
  158. package/src/__tests__/gateway-only-enforcement.test.ts +467 -369
  159. package/src/__tests__/gateway-only-guard.test.ts +54 -56
  160. package/src/__tests__/gemini-image-service.test.ts +113 -100
  161. package/src/__tests__/gemini-provider.test.ts +297 -220
  162. package/src/__tests__/get-weather.test.ts +188 -114
  163. package/src/__tests__/gmail-integration.test.ts +47 -46
  164. package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
  165. package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
  166. package/src/__tests__/guardian-action-followup-executor.test.ts +215 -151
  167. package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
  168. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
  169. package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
  170. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
  171. package/src/__tests__/guardian-action-store.test.ts +158 -109
  172. package/src/__tests__/guardian-action-sweep.test.ts +114 -100
  173. package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
  174. package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
  175. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
  176. package/src/__tests__/guardian-dispatch.test.ts +316 -256
  177. package/src/__tests__/guardian-grant-minting.test.ts +247 -178
  178. package/src/__tests__/guardian-outbound-http.test.ts +337 -209
  179. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
  180. package/src/__tests__/guardian-question-copy.test.ts +17 -17
  181. package/src/__tests__/guardian-question-mode.test.ts +134 -100
  182. package/src/__tests__/guardian-routing-invariants.test.ts +679 -613
  183. package/src/__tests__/guardian-routing-state.test.ts +256 -209
  184. package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
  185. package/src/__tests__/guardian-verification-voice-binding.test.ts +47 -41
  186. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
  187. package/src/__tests__/handle-user-message-secret-resume.test.ts +43 -21
  188. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
  189. package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
  190. package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
  191. package/src/__tests__/handlers-slack-config.test.ts +63 -54
  192. package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
  193. package/src/__tests__/handlers-telegram-config.test.ts +662 -329
  194. package/src/__tests__/handlers-twitter-config.test.ts +525 -298
  195. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +270 -195
  196. package/src/__tests__/headless-browser-interactions.test.ts +444 -280
  197. package/src/__tests__/headless-browser-navigate.test.ts +116 -79
  198. package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
  199. package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
  200. package/src/__tests__/heartbeat-service.test.ts +76 -58
  201. package/src/__tests__/history-repair-observability.test.ts +14 -14
  202. package/src/__tests__/history-repair.test.ts +171 -167
  203. package/src/__tests__/home-base-bootstrap.test.ts +30 -27
  204. package/src/__tests__/hooks-blocking.test.ts +86 -37
  205. package/src/__tests__/hooks-cli.test.ts +104 -68
  206. package/src/__tests__/hooks-config.test.ts +81 -43
  207. package/src/__tests__/hooks-discovery.test.ts +106 -96
  208. package/src/__tests__/hooks-integration.test.ts +78 -72
  209. package/src/__tests__/hooks-manager.test.ts +99 -61
  210. package/src/__tests__/hooks-runner.test.ts +94 -71
  211. package/src/__tests__/hooks-settings.test.ts +69 -64
  212. package/src/__tests__/hooks-templates.test.ts +85 -54
  213. package/src/__tests__/hooks-ts-runner.test.ts +82 -45
  214. package/src/__tests__/hooks-watch.test.ts +32 -22
  215. package/src/__tests__/host-file-edit-tool.test.ts +190 -148
  216. package/src/__tests__/host-file-read-tool.test.ts +86 -63
  217. package/src/__tests__/host-file-write-tool.test.ts +98 -64
  218. package/src/__tests__/host-shell-tool.test.ts +342 -233
  219. package/src/__tests__/inbound-invite-redemption.test.ts +194 -152
  220. package/src/__tests__/ingress-member-store.test.ts +163 -159
  221. package/src/__tests__/ingress-reconcile.test.ts +183 -142
  222. package/src/__tests__/ingress-routes-http.test.ts +441 -356
  223. package/src/__tests__/ingress-url-consistency.test.ts +125 -64
  224. package/src/__tests__/integration-status.test.ts +93 -73
  225. package/src/__tests__/intent-routing.test.ts +148 -118
  226. package/src/__tests__/invite-redemption-service.test.ts +163 -121
  227. package/src/__tests__/ipc-blob-store.test.ts +104 -91
  228. package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
  229. package/src/__tests__/ipc-contract.test.ts +24 -23
  230. package/src/__tests__/ipc-protocol.test.ts +52 -46
  231. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
  232. package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
  233. package/src/__tests__/ipc-validate.test.ts +240 -179
  234. package/src/__tests__/key-migration.test.ts +123 -90
  235. package/src/__tests__/keychain.test.ts +150 -123
  236. package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
  237. package/src/__tests__/llm-usage-store.test.ts +112 -87
  238. package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
  239. package/src/__tests__/managed-store.test.ts +411 -360
  240. package/src/__tests__/mcp-cli.test.ts +189 -123
  241. package/src/__tests__/mcp-health-check.test.ts +26 -21
  242. package/src/__tests__/media-generate-image.test.ts +122 -99
  243. package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
  244. package/src/__tests__/media-visibility-policy.test.ts +86 -38
  245. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
  246. package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
  247. package/src/__tests__/memory-query-builder.test.ts +32 -33
  248. package/src/__tests__/memory-recall-quality.test.ts +761 -407
  249. package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
  250. package/src/__tests__/memory-regressions.test.ts +3725 -2642
  251. package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
  252. package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
  253. package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
  254. package/src/__tests__/messaging-send-tool.test.ts +36 -29
  255. package/src/__tests__/migration-cli-flows.test.ts +69 -53
  256. package/src/__tests__/migration-ordering.test.ts +103 -86
  257. package/src/__tests__/mime-builder.test.ts +55 -32
  258. package/src/__tests__/mock-signup-server.test.ts +384 -246
  259. package/src/__tests__/model-intents.test.ts +61 -37
  260. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
  261. package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
  262. package/src/__tests__/non-member-access-request.test.ts +294 -249
  263. package/src/__tests__/notification-broadcaster.test.ts +99 -81
  264. package/src/__tests__/notification-decision-fallback.test.ts +223 -178
  265. package/src/__tests__/notification-decision-strategy.test.ts +375 -337
  266. package/src/__tests__/notification-deep-link.test.ts +67 -61
  267. package/src/__tests__/notification-guardian-path.test.ts +248 -206
  268. package/src/__tests__/notification-routing-intent.test.ts +166 -93
  269. package/src/__tests__/notification-telegram-adapter.test.ts +60 -46
  270. package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
  271. package/src/__tests__/notification-thread-candidates.test.ts +64 -61
  272. package/src/__tests__/oauth-callback-registry.test.ts +40 -30
  273. package/src/__tests__/oauth-connect-handler.test.ts +109 -89
  274. package/src/__tests__/oauth-scope-policy.test.ts +63 -55
  275. package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
  276. package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
  277. package/src/__tests__/onboarding-template-contract.test.ts +93 -94
  278. package/src/__tests__/openai-provider.test.ts +366 -274
  279. package/src/__tests__/pairing-concurrent.test.ts +18 -12
  280. package/src/__tests__/pairing-routes.test.ts +45 -41
  281. package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
  282. package/src/__tests__/parser.test.ts +316 -226
  283. package/src/__tests__/path-classifier.test.ts +24 -25
  284. package/src/__tests__/path-policy.test.ts +187 -147
  285. package/src/__tests__/phone.test.ts +36 -36
  286. package/src/__tests__/platform-move-helper.test.ts +48 -40
  287. package/src/__tests__/platform-socket-path.test.ts +23 -24
  288. package/src/__tests__/platform-workspace-migration.test.ts +464 -414
  289. package/src/__tests__/platform.test.ts +61 -53
  290. package/src/__tests__/playbook-execution.test.ts +397 -265
  291. package/src/__tests__/playbook-tools.test.ts +267 -196
  292. package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
  293. package/src/__tests__/pricing.test.ts +316 -136
  294. package/src/__tests__/profile-compiler.test.ts +206 -188
  295. package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
  296. package/src/__tests__/provider-error-scenarios.test.ts +212 -158
  297. package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
  298. package/src/__tests__/provider-registry-ollama.test.ts +13 -9
  299. package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
  300. package/src/__tests__/proxy-approval-callback.test.ts +180 -119
  301. package/src/__tests__/public-ingress-urls.test.ts +112 -94
  302. package/src/__tests__/qdrant-manager.test.ts +147 -98
  303. package/src/__tests__/ratelimit.test.ts +152 -82
  304. package/src/__tests__/recording-handler.test.ts +273 -151
  305. package/src/__tests__/recording-intent-fallback.test.ts +94 -75
  306. package/src/__tests__/recording-intent-handler.test.ts +422 -292
  307. package/src/__tests__/recording-intent.test.ts +578 -379
  308. package/src/__tests__/recording-state-machine.test.ts +530 -316
  309. package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
  310. package/src/__tests__/recurrence-engine.test.ts +81 -41
  311. package/src/__tests__/recurrence-types.test.ts +63 -44
  312. package/src/__tests__/relay-server.test.ts +2131 -1602
  313. package/src/__tests__/reminder-store.test.ts +158 -80
  314. package/src/__tests__/reminder.test.ts +113 -109
  315. package/src/__tests__/remote-skill-policy.test.ts +96 -72
  316. package/src/__tests__/request-file-tool.test.ts +74 -67
  317. package/src/__tests__/response-tier.test.ts +131 -74
  318. package/src/__tests__/runtime-attachment-metadata.test.ts +107 -70
  319. package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
  320. package/src/__tests__/runtime-events-sse.test.ts +67 -51
  321. package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
  322. package/src/__tests__/sandbox-host-parity.test.ts +377 -301
  323. package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
  324. package/src/__tests__/schedule-store.test.ts +268 -205
  325. package/src/__tests__/schedule-tools.test.ts +702 -524
  326. package/src/__tests__/scheduler-recurrence.test.ts +240 -130
  327. package/src/__tests__/scoped-approval-grants.test.ts +258 -168
  328. package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
  329. package/src/__tests__/script-proxy-certs.test.ts +38 -35
  330. package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
  331. package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
  332. package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
  333. package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
  334. package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
  335. package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
  336. package/src/__tests__/script-proxy-policy.test.ts +308 -153
  337. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
  338. package/src/__tests__/script-proxy-router.test.ts +111 -77
  339. package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
  340. package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
  341. package/src/__tests__/secret-allowlist.test.ts +105 -90
  342. package/src/__tests__/secret-ingress-handler.test.ts +41 -30
  343. package/src/__tests__/secret-onetime-send.test.ts +67 -50
  344. package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
  345. package/src/__tests__/secret-response-routing.test.ts +50 -41
  346. package/src/__tests__/secret-scanner-executor.test.ts +152 -111
  347. package/src/__tests__/secret-scanner.test.ts +495 -413
  348. package/src/__tests__/secure-keys.test.ts +132 -121
  349. package/src/__tests__/send-endpoint-busy.test.ts +313 -232
  350. package/src/__tests__/send-notification-tool.test.ts +43 -42
  351. package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
  352. package/src/__tests__/sequence-store.test.ts +335 -167
  353. package/src/__tests__/server-history-render.test.ts +341 -202
  354. package/src/__tests__/session-abort-tool-results.test.ts +133 -70
  355. package/src/__tests__/session-approval-overrides.test.ts +93 -91
  356. package/src/__tests__/session-confirmation-signals.test.ts +252 -160
  357. package/src/__tests__/session-conflict-gate.test.ts +775 -585
  358. package/src/__tests__/session-error.test.ts +222 -191
  359. package/src/__tests__/session-evictor.test.ts +79 -62
  360. package/src/__tests__/session-init.benchmark.test.ts +170 -108
  361. package/src/__tests__/session-load-history-repair.test.ts +273 -139
  362. package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
  363. package/src/__tests__/session-pre-run-repair.test.ts +106 -59
  364. package/src/__tests__/session-profile-injection.test.ts +198 -130
  365. package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
  366. package/src/__tests__/session-queue.test.ts +624 -321
  367. package/src/__tests__/session-runtime-assembly.test.ts +425 -329
  368. package/src/__tests__/session-runtime-workspace.test.ts +69 -61
  369. package/src/__tests__/session-skill-tools.test.ts +973 -678
  370. package/src/__tests__/session-slash-known.test.ts +185 -133
  371. package/src/__tests__/session-slash-queue.test.ts +147 -81
  372. package/src/__tests__/session-slash-unknown.test.ts +135 -90
  373. package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
  374. package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
  375. package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
  376. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
  377. package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
  378. package/src/__tests__/session-undo.test.ts +43 -30
  379. package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
  380. package/src/__tests__/session-workspace-injection.test.ts +245 -117
  381. package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
  382. package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
  383. package/src/__tests__/shell-credential-ref.test.ts +126 -90
  384. package/src/__tests__/shell-identity.test.ts +134 -111
  385. package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
  386. package/src/__tests__/shell-parser-property.test.ts +435 -288
  387. package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
  388. package/src/__tests__/size-guard.test.ts +42 -44
  389. package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
  390. package/src/__tests__/skill-feature-flags.test.ts +75 -47
  391. package/src/__tests__/skill-include-graph.test.ts +143 -148
  392. package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
  393. package/src/__tests__/skill-load-tool.test.ts +371 -199
  394. package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
  395. package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
  396. package/src/__tests__/skill-script-runner-host.test.ts +460 -250
  397. package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
  398. package/src/__tests__/skill-script-runner.test.ts +115 -74
  399. package/src/__tests__/skill-tool-factory.test.ts +140 -96
  400. package/src/__tests__/skill-tool-manifest.test.ts +306 -210
  401. package/src/__tests__/skill-version-hash.test.ts +70 -56
  402. package/src/__tests__/skills.test.ts +0 -1
  403. package/src/__tests__/slack-channel-config.test.ts +127 -84
  404. package/src/__tests__/slack-skill.test.ts +60 -47
  405. package/src/__tests__/slash-commands-catalog.test.ts +37 -31
  406. package/src/__tests__/slash-commands-parser.test.ts +71 -64
  407. package/src/__tests__/slash-commands-resolver.test.ts +143 -107
  408. package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
  409. package/src/__tests__/sms-messaging-provider.test.ts +74 -47
  410. package/src/__tests__/speaker-identification.test.ts +28 -25
  411. package/src/__tests__/starter-bundle.test.ts +27 -23
  412. package/src/__tests__/starter-task-flow.test.ts +67 -52
  413. package/src/__tests__/subagent-manager-notify.test.ts +154 -108
  414. package/src/__tests__/subagent-tools.test.ts +311 -270
  415. package/src/__tests__/subagent-types.test.ts +40 -40
  416. package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
  417. package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
  418. package/src/__tests__/swarm-orchestrator.test.ts +135 -101
  419. package/src/__tests__/swarm-plan-validator.test.ts +125 -73
  420. package/src/__tests__/swarm-recursion.test.ts +58 -46
  421. package/src/__tests__/swarm-router-planner.test.ts +99 -74
  422. package/src/__tests__/swarm-session-integration.test.ts +148 -91
  423. package/src/__tests__/swarm-tool.test.ts +65 -45
  424. package/src/__tests__/swarm-worker-backend.test.ts +59 -45
  425. package/src/__tests__/swarm-worker-runner.test.ts +133 -118
  426. package/src/__tests__/system-prompt.test.ts +290 -256
  427. package/src/__tests__/task-compiler.test.ts +176 -120
  428. package/src/__tests__/task-management-tools.test.ts +561 -456
  429. package/src/__tests__/task-memory-cleanup.test.ts +627 -362
  430. package/src/__tests__/task-runner.test.ts +117 -94
  431. package/src/__tests__/task-scheduler.test.ts +113 -84
  432. package/src/__tests__/task-tools.test.ts +349 -264
  433. package/src/__tests__/terminal-sandbox.test.ts +138 -108
  434. package/src/__tests__/terminal-tools.test.ts +350 -305
  435. package/src/__tests__/thread-seed-composer.test.ts +307 -180
  436. package/src/__tests__/tool-approval-handler.test.ts +238 -137
  437. package/src/__tests__/tool-audit-listener.test.ts +69 -69
  438. package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
  439. package/src/__tests__/tool-execution-abort-cleanup.test.ts +153 -146
  440. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
  441. package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
  442. package/src/__tests__/tool-executor-redaction.test.ts +112 -109
  443. package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
  444. package/src/__tests__/tool-executor.test.ts +1274 -674
  445. package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
  446. package/src/__tests__/tool-metrics-listener.test.ts +97 -85
  447. package/src/__tests__/tool-notification-listener.test.ts +42 -25
  448. package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
  449. package/src/__tests__/tool-policy.test.ts +44 -25
  450. package/src/__tests__/tool-profiling-listener.test.ts +99 -93
  451. package/src/__tests__/tool-result-truncation.test.ts +5 -4
  452. package/src/__tests__/tool-trace-listener.test.ts +131 -111
  453. package/src/__tests__/top-level-renderer.test.ts +62 -58
  454. package/src/__tests__/top-level-scanner.test.ts +68 -64
  455. package/src/__tests__/trace-emitter.test.ts +56 -56
  456. package/src/__tests__/trust-context-guards.test.ts +65 -65
  457. package/src/__tests__/trust-store.test.ts +1239 -806
  458. package/src/__tests__/trusted-contact-approval-notifier.test.ts +339 -275
  459. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +484 -373
  460. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +264 -241
  461. package/src/__tests__/trusted-contact-multichannel.test.ts +182 -142
  462. package/src/__tests__/trusted-contact-verification.test.ts +251 -231
  463. package/src/__tests__/turn-commit.test.ts +259 -200
  464. package/src/__tests__/twilio-config.test.ts +49 -41
  465. package/src/__tests__/twilio-provider.test.ts +140 -126
  466. package/src/__tests__/twilio-rest.test.ts +22 -18
  467. package/src/__tests__/twilio-routes-elevenlabs.test.ts +188 -162
  468. package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
  469. package/src/__tests__/twilio-routes.test.ts +389 -281
  470. package/src/__tests__/twitter-auth-handler.test.ts +184 -139
  471. package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
  472. package/src/__tests__/twitter-cli-routing.test.ts +146 -99
  473. package/src/__tests__/twitter-oauth-client.test.ts +82 -65
  474. package/src/__tests__/update-bulletin-format.test.ts +69 -66
  475. package/src/__tests__/update-bulletin-state.test.ts +66 -60
  476. package/src/__tests__/update-bulletin.test.ts +150 -114
  477. package/src/__tests__/update-template-contract.test.ts +15 -10
  478. package/src/__tests__/url-safety.test.ts +288 -265
  479. package/src/__tests__/user-reference.test.ts +32 -32
  480. package/src/__tests__/view-image-tool.test.ts +118 -96
  481. package/src/__tests__/voice-invite-redemption.test.ts +111 -106
  482. package/src/__tests__/voice-quality.test.ts +117 -102
  483. package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
  484. package/src/__tests__/voice-session-bridge.test.ts +351 -216
  485. package/src/__tests__/weather-skill-regression.test.ts +170 -120
  486. package/src/__tests__/web-fetch.test.ts +664 -526
  487. package/src/__tests__/web-search.test.ts +379 -213
  488. package/src/__tests__/work-item-output.test.ts +90 -53
  489. package/src/__tests__/workspace-git-service.test.ts +437 -356
  490. package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
  491. package/src/__tests__/workspace-lifecycle.test.ts +98 -64
  492. package/src/__tests__/workspace-policy.test.ts +139 -71
  493. package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
  494. package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
  495. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +44 -4
  496. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
  497. package/src/config/bundled-skills/messaging/SKILL.md +9 -7
  498. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
  499. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
  500. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +11 -7
  501. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
  502. package/src/config/bundled-tool-registry.ts +2 -0
  503. package/src/config/env.ts +38 -29
  504. package/src/daemon/handlers/skills.ts +18 -10
  505. package/src/daemon/ipc-contract/messages.ts +1 -0
  506. package/src/daemon/ipc-contract/surfaces.ts +7 -1
  507. package/src/daemon/session-agent-loop-handlers.ts +5 -0
  508. package/src/daemon/session-agent-loop.ts +1 -1
  509. package/src/daemon/session-process.ts +1 -1
  510. package/src/daemon/session-surfaces.ts +42 -2
  511. package/src/memory/db-connection.ts +16 -10
  512. package/src/messaging/providers/gmail/adapter.ts +10 -3
  513. package/src/messaging/providers/gmail/client.ts +280 -72
  514. package/src/runtime/auth/__tests__/context.test.ts +75 -65
  515. package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
  516. package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
  517. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
  518. package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
  519. package/src/runtime/auth/__tests__/policy.test.ts +9 -9
  520. package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
  521. package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
  522. package/src/runtime/auth/__tests__/subject.test.ts +54 -54
  523. package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
  524. package/src/runtime/auth/scopes.ts +3 -0
  525. package/src/runtime/auth/token-service.ts +78 -48
  526. package/src/runtime/auth/types.ts +2 -1
  527. package/src/runtime/http-server.ts +2 -1
  528. package/src/security/secure-keys.ts +103 -53
  529. package/src/sequence/reply-matcher.ts +10 -6
  530. package/src/skills/frontmatter.ts +9 -6
  531. package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
  532. package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
  533. package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
  534. package/src/tools/ui-surface/definitions.ts +2 -1
  535. package/src/util/platform.ts +0 -12
  536. package/docs/architecture/http-token-refresh.md +0 -274
package/Dockerfile CHANGED
@@ -22,9 +22,6 @@ COPY package.json bun.lock ./
22
22
  # Install dependencies
23
23
  RUN bun install --frozen-lockfile
24
24
 
25
- # Copy source
26
- COPY . .
27
-
28
25
  # Final stage
29
26
  FROM debian:trixie@sha256:3615a749858a1cba49b408fb49c37093db813321355a9ab7c1f9f4836341e9db AS runner
30
27
 
@@ -55,9 +52,6 @@ RUN groupadd --system --gid 1001 assistant && \
55
52
  useradd --system --uid 1001 --gid assistant --create-home --shell /bin/bash assistant && \
56
53
  echo "assistant ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
57
54
 
58
- # Copy from builder
59
- COPY --from=builder /app /app
60
-
61
55
  # Set up data directory
62
56
  RUN mkdir -p /home/assistant/.vellum /data && \
63
57
  chown -R assistant:assistant /home/assistant/.vellum /data && \
@@ -98,5 +92,11 @@ ENV VELLUM_DAEMON_SOCKET=/home/assistant/.vellum/vellum.sock
98
92
  ENV BASE_DATA_DIR=/data
99
93
  ENV IS_CONTAINERIZED=true
100
94
 
95
+ # Copy from builder
96
+ COPY --from=builder /app /app
97
+
98
+ # Copy source
99
+ COPY . .
100
+
101
101
  # Run the daemon + http server
102
102
  CMD ["bun", "run", "src/daemon/main.ts"]
package/README.md CHANGED
@@ -47,7 +47,6 @@ cp .env.example .env
47
47
  | `OLLAMA_API_KEY` | No | — | API key for authenticated Ollama deployments |
48
48
  | `OLLAMA_BASE_URL` | No | `http://127.0.0.1:11434/v1` | Ollama base URL |
49
49
  | `RUNTIME_HTTP_PORT` | No | — | Enable the HTTP server (required for gateway/web) |
50
- | `RUNTIME_GATEWAY_ORIGIN_SECRET` | No | — | **Deprecated.** Gateway origin is now proven by JWT principal type (`svc_gateway`), not a separate header. |
51
50
  | `VELLUM_DAEMON_SOCKET` | No | `~/.vellum/vellum.sock` | Override the daemon socket path |
52
51
 
53
52
  ## Update Bulletin
@@ -228,7 +227,7 @@ The runtime exposes a RESTful HTTP API for Twilio configuration, credential mana
228
227
  | POST | `/v1/integrations/twilio/sms/test` | Sends a test SMS and polls for delivery status |
229
228
  | POST | `/v1/integrations/twilio/sms/doctor` | Runs comprehensive SMS health diagnostics |
230
229
 
231
- All endpoints are bearer-authenticated via the runtime HTTP token. Skills and clients should call the gateway URL (default `http://localhost:7830`) rather than the runtime port directly, as the gateway proxies all `/v1/integrations/twilio/*` routes.
230
+ All endpoints are JWT-authenticated (require a valid JWT with appropriate scopes). Skills and clients should call the gateway URL (default `http://localhost:7830`) rather than the runtime port directly, as the gateway proxies all `/v1/integrations/twilio/*` routes.
232
231
 
233
232
  ### Ingress Webhook Reconciliation
234
233
 
package/eslint.config.mjs CHANGED
@@ -14,8 +14,8 @@ const eslintConfig = defineConfig([
14
14
  "error",
15
15
  {
16
16
  groups: [
17
- // Node.js builtins
18
- ["^node:"],
17
+ // Runtime builtins (Node.js and Bun)
18
+ ["^node:", "^bun:"],
19
19
  // External packages
20
20
  ["^@?\\w"],
21
21
  // Internal/relative imports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.4.16",
3
+ "version": "0.4.18",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "vellum": "./src/index.ts"
@@ -8,43 +8,49 @@
8
8
  * - Stale: handles already-resolved requests gracefully.
9
9
  * - Idempotent: approving same request twice does not create duplicate sessions.
10
10
  */
11
- import { mkdtempSync, rmSync } from 'node:fs';
12
- import { tmpdir } from 'node:os';
13
- import { join } from 'node:path';
14
-
15
- import { afterAll, beforeEach, describe, expect, mock, test } from 'bun:test';
11
+ import { mkdtempSync, rmSync } from "node:fs";
12
+ import { tmpdir } from "node:os";
13
+ import { join } from "node:path";
14
+ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
16
15
 
17
16
  // ---------------------------------------------------------------------------
18
17
  // Test isolation: in-memory SQLite via temp directory
19
18
  // ---------------------------------------------------------------------------
20
19
 
21
- const testDir = mkdtempSync(join(tmpdir(), 'access-request-decision-test-'));
20
+ const testDir = mkdtempSync(join(tmpdir(), "access-request-decision-test-"));
22
21
 
23
- mock.module('../util/platform.js', () => ({
22
+ mock.module("../util/platform.js", () => ({
24
23
  getRootDir: () => testDir,
25
24
  getDataDir: () => testDir,
26
- isMacOS: () => process.platform === 'darwin',
27
- isLinux: () => process.platform === 'linux',
28
- isWindows: () => process.platform === 'win32',
29
- getSocketPath: () => join(testDir, 'test.sock'),
30
- getPidPath: () => join(testDir, 'test.pid'),
31
- getDbPath: () => join(testDir, 'test.db'),
32
- getLogPath: () => join(testDir, 'test.log'),
25
+ isMacOS: () => process.platform === "darwin",
26
+ isLinux: () => process.platform === "linux",
27
+ isWindows: () => process.platform === "win32",
28
+ getSocketPath: () => join(testDir, "test.sock"),
29
+ getPidPath: () => join(testDir, "test.pid"),
30
+ getDbPath: () => join(testDir, "test.db"),
31
+ getLogPath: () => join(testDir, "test.log"),
33
32
  ensureDataDir: () => {},
34
- readHttpToken: () => 'test-bearer-token',
33
+ readHttpToken: () => "test-bearer-token",
35
34
  }));
36
35
 
37
- mock.module('../util/logger.js', () => ({
38
- getLogger: () => new Proxy({} as Record<string, unknown>, {
39
- get: () => () => {},
40
- }),
36
+ mock.module("../util/logger.js", () => ({
37
+ getLogger: () =>
38
+ new Proxy({} as Record<string, unknown>, {
39
+ get: () => () => {},
40
+ }),
41
41
  }));
42
42
 
43
43
  // Track deliverChannelReply calls and allow injecting failures
44
- const deliverReplyCalls: Array<{ url: string; payload: Record<string, unknown> }> = [];
44
+ const deliverReplyCalls: Array<{
45
+ url: string;
46
+ payload: Record<string, unknown>;
47
+ }> = [];
45
48
  let deliverReplyError: Error | null = null;
46
- mock.module('../runtime/gateway-client.js', () => ({
47
- deliverChannelReply: async (url: string, payload: Record<string, unknown>) => {
49
+ mock.module("../runtime/gateway-client.js", () => ({
50
+ deliverChannelReply: async (
51
+ url: string,
52
+ payload: Record<string, unknown>,
53
+ ) => {
48
54
  if (deliverReplyError) {
49
55
  throw deliverReplyError;
50
56
  }
@@ -55,24 +61,26 @@ mock.module('../runtime/gateway-client.js', () => ({
55
61
  import {
56
62
  createApprovalRequest,
57
63
  getApprovalRequestById,
58
- } from '../memory/channel-guardian-store.js';
59
- import { getDb, initializeDb, resetDb } from '../memory/db.js';
60
- import {
61
- findActiveSession,
62
- } from '../runtime/channel-guardian-service.js';
64
+ } from "../memory/channel-guardian-store.js";
65
+ import { getDb, initializeDb, resetDb } from "../memory/db.js";
66
+ import { findActiveSession } from "../runtime/channel-guardian-service.js";
63
67
  import {
64
68
  deliverVerificationCodeToGuardian,
65
69
  handleAccessRequestDecision,
66
70
  notifyRequesterOfApproval,
67
71
  notifyRequesterOfDeliveryFailure,
68
72
  notifyRequesterOfDenial,
69
- } from '../runtime/routes/access-request-decision.js';
73
+ } from "../runtime/routes/access-request-decision.js";
70
74
 
71
75
  initializeDb();
72
76
 
73
77
  afterAll(() => {
74
78
  resetDb();
75
- try { rmSync(testDir, { recursive: true }); } catch { /* best effort */ }
79
+ try {
80
+ rmSync(testDir, { recursive: true });
81
+ } catch {
82
+ /* best effort */
83
+ }
76
84
  });
77
85
 
78
86
  // ---------------------------------------------------------------------------
@@ -83,9 +91,9 @@ const GUARDIAN_APPROVAL_TTL_MS = 5 * 60 * 1000;
83
91
 
84
92
  function resetState(): void {
85
93
  const db = getDb();
86
- db.run('DELETE FROM channel_guardian_approval_requests');
87
- db.run('DELETE FROM channel_guardian_bindings');
88
- db.run('DELETE FROM channel_guardian_verification_challenges');
94
+ db.run("DELETE FROM channel_guardian_approval_requests");
95
+ db.run("DELETE FROM channel_guardian_bindings");
96
+ db.run("DELETE FROM channel_guardian_verification_challenges");
89
97
  deliverReplyCalls.length = 0;
90
98
  }
91
99
 
@@ -93,15 +101,15 @@ function createTestApproval(overrides: Record<string, unknown> = {}) {
93
101
  return createApprovalRequest({
94
102
  runId: `ingress-access-request-${Date.now()}`,
95
103
  conversationId: `access-req-telegram-user-unknown-456`,
96
- assistantId: 'self',
97
- channel: 'telegram',
98
- requesterExternalUserId: 'user-unknown-456',
99
- requesterChatId: 'chat-123',
100
- guardianExternalUserId: 'guardian-user-789',
101
- guardianChatId: 'guardian-chat-789',
102
- toolName: 'ingress_access_request',
103
- riskLevel: 'access_request',
104
- reason: 'Alice Unknown is requesting access to the assistant',
104
+ assistantId: "self",
105
+ channel: "telegram",
106
+ requesterExternalUserId: "user-unknown-456",
107
+ requesterChatId: "chat-123",
108
+ guardianExternalUserId: "guardian-user-789",
109
+ guardianChatId: "guardian-chat-789",
110
+ toolName: "ingress_access_request",
111
+ riskLevel: "access_request",
112
+ reason: "Alice Unknown is requesting access to the assistant",
105
113
  expiresAt: Date.now() + GUARDIAN_APPROVAL_TTL_MS,
106
114
  ...overrides,
107
115
  });
@@ -111,22 +119,22 @@ function createTestApproval(overrides: Record<string, unknown> = {}) {
111
119
  // Tests
112
120
  // ---------------------------------------------------------------------------
113
121
 
114
- describe('access request decision handler', () => {
122
+ describe("access request decision handler", () => {
115
123
  beforeEach(() => {
116
124
  resetState();
117
125
  });
118
126
 
119
- test('guardian approve creates a verification session', () => {
127
+ test("guardian approve creates a verification session", () => {
120
128
  const approval = createTestApproval();
121
129
 
122
130
  const result = handleAccessRequestDecision(
123
131
  approval,
124
- 'approve',
125
- 'guardian-user-789',
132
+ "approve",
133
+ "guardian-user-789",
126
134
  );
127
135
 
128
136
  expect(result.handled).toBe(true);
129
- expect(result.type).toBe('approved');
137
+ expect(result.type).toBe("approved");
130
138
  expect(result.verificationSessionId).toBeDefined();
131
139
  expect(result.verificationCode).toBeDefined();
132
140
  // Verification code should be a 6-digit numeric string
@@ -135,89 +143,89 @@ describe('access request decision handler', () => {
135
143
  // Approval record should be updated to 'approved'
136
144
  const updated = getApprovalRequestById(approval.id);
137
145
  expect(updated).not.toBeNull();
138
- expect(updated!.status).toBe('approved');
139
- expect(updated!.decidedByExternalUserId).toBe('guardian-user-789');
146
+ expect(updated!.status).toBe("approved");
147
+ expect(updated!.decidedByExternalUserId).toBe("guardian-user-789");
140
148
  });
141
149
 
142
- test('verification session is identity-bound to the requester', () => {
150
+ test("verification session is identity-bound to the requester", () => {
143
151
  const approval = createTestApproval();
144
152
 
145
153
  const result = handleAccessRequestDecision(
146
154
  approval,
147
- 'approve',
148
- 'guardian-user-789',
155
+ "approve",
156
+ "guardian-user-789",
149
157
  );
150
158
 
151
- expect(result.type).toBe('approved');
159
+ expect(result.type).toBe("approved");
152
160
 
153
161
  // There should be an active session for this channel
154
- const session = findActiveSession('self', 'telegram');
162
+ const session = findActiveSession("self", "telegram");
155
163
  expect(session).not.toBeNull();
156
- expect(session!.expectedExternalUserId).toBe('user-unknown-456');
157
- expect(session!.expectedChatId).toBe('chat-123');
158
- expect(session!.identityBindingStatus).toBe('bound');
159
- expect(session!.status).toBe('awaiting_response');
164
+ expect(session!.expectedExternalUserId).toBe("user-unknown-456");
165
+ expect(session!.expectedChatId).toBe("chat-123");
166
+ expect(session!.identityBindingStatus).toBe("bound");
167
+ expect(session!.status).toBe("awaiting_response");
160
168
  });
161
169
 
162
- test('guardian deny marks approval as denied', () => {
170
+ test("guardian deny marks approval as denied", () => {
163
171
  const approval = createTestApproval();
164
172
 
165
173
  const result = handleAccessRequestDecision(
166
174
  approval,
167
- 'deny',
168
- 'guardian-user-789',
175
+ "deny",
176
+ "guardian-user-789",
169
177
  );
170
178
 
171
179
  expect(result.handled).toBe(true);
172
- expect(result.type).toBe('denied');
180
+ expect(result.type).toBe("denied");
173
181
  expect(result.verificationSessionId).toBeUndefined();
174
182
  expect(result.verificationCode).toBeUndefined();
175
183
 
176
184
  // Approval record should be updated to 'denied'
177
185
  const updated = getApprovalRequestById(approval.id);
178
186
  expect(updated).not.toBeNull();
179
- expect(updated!.status).toBe('denied');
180
- expect(updated!.decidedByExternalUserId).toBe('guardian-user-789');
187
+ expect(updated!.status).toBe("denied");
188
+ expect(updated!.decidedByExternalUserId).toBe("guardian-user-789");
181
189
 
182
190
  // No verification session should be created
183
- const session = findActiveSession('self', 'telegram');
191
+ const session = findActiveSession("self", "telegram");
184
192
  expect(session).toBeNull();
185
193
  });
186
194
 
187
- test('stale decision (already resolved) returns stale', () => {
195
+ test("stale decision (already resolved) returns stale", () => {
188
196
  const approval = createTestApproval();
189
197
 
190
198
  // Approve first
191
- handleAccessRequestDecision(approval, 'approve', 'guardian-user-789');
199
+ handleAccessRequestDecision(approval, "approve", "guardian-user-789");
192
200
 
193
201
  // Try to deny the same approval — should be stale
194
202
  const result = handleAccessRequestDecision(
195
203
  approval,
196
- 'deny',
197
- 'guardian-user-789',
204
+ "deny",
205
+ "guardian-user-789",
198
206
  );
199
207
 
200
208
  expect(result.handled).toBe(true);
201
- expect(result.type).toBe('stale');
209
+ expect(result.type).toBe("stale");
202
210
  });
203
211
 
204
- test('idempotent approval does not create duplicate verification sessions', () => {
212
+ test("idempotent approval does not create duplicate verification sessions", () => {
205
213
  const approval = createTestApproval();
206
214
 
207
215
  // Approve first
208
216
  const result1 = handleAccessRequestDecision(
209
217
  approval,
210
- 'approve',
211
- 'guardian-user-789',
218
+ "approve",
219
+ "guardian-user-789",
212
220
  );
213
- expect(result1.type).toBe('approved');
221
+ expect(result1.type).toBe("approved");
214
222
  const _sessionId1 = result1.verificationSessionId;
215
223
 
216
224
  // Approve again — should be idempotent (already resolved with same decision)
217
225
  const result2 = handleAccessRequestDecision(
218
226
  approval,
219
- 'approve',
220
- 'guardian-user-789',
227
+ "approve",
228
+ "guardian-user-789",
221
229
  );
222
230
 
223
231
  // resolveApprovalRequest returns the existing record for same-decision idempotency,
@@ -231,97 +239,97 @@ describe('access request decision handler', () => {
231
239
  });
232
240
  });
233
241
 
234
- describe('access request notification delivery', () => {
242
+ describe("access request notification delivery", () => {
235
243
  beforeEach(() => {
236
244
  deliverReplyCalls.length = 0;
237
245
  deliverReplyError = null;
238
246
  });
239
247
 
240
- test('delivers verification code to guardian and returns ok', async () => {
248
+ test("delivers verification code to guardian and returns ok", async () => {
241
249
  const result = await deliverVerificationCodeToGuardian({
242
- replyCallbackUrl: 'http://localhost:7830/deliver/telegram',
243
- guardianChatId: 'guardian-chat-789',
244
- requesterIdentifier: 'user-unknown-456',
245
- verificationCode: '123456',
246
- assistantId: 'self',
247
- bearerToken: 'test-token',
250
+ replyCallbackUrl: "http://localhost:7830/deliver/telegram",
251
+ guardianChatId: "guardian-chat-789",
252
+ requesterIdentifier: "user-unknown-456",
253
+ verificationCode: "123456",
254
+ assistantId: "self",
255
+ bearerToken: "test-token",
248
256
  });
249
257
 
250
258
  expect(result.ok).toBe(true);
251
259
  expect(deliverReplyCalls.length).toBe(1);
252
260
  const call = deliverReplyCalls[0];
253
- expect(call.payload.chatId).toBe('guardian-chat-789');
261
+ expect(call.payload.chatId).toBe("guardian-chat-789");
254
262
  const text = call.payload.text as string;
255
- expect(text).toContain('123456');
256
- expect(text).toContain('user-unknown-456');
257
- expect(text).toContain('10 minutes');
263
+ expect(text).toContain("123456");
264
+ expect(text).toContain("user-unknown-456");
265
+ expect(text).toContain("10 minutes");
258
266
  });
259
267
 
260
- test('returns failure result when guardian code delivery fails', async () => {
261
- deliverReplyError = new Error('Gateway timeout');
268
+ test("returns failure result when guardian code delivery fails", async () => {
269
+ deliverReplyError = new Error("Gateway timeout");
262
270
 
263
271
  const result = await deliverVerificationCodeToGuardian({
264
- replyCallbackUrl: 'http://localhost:7830/deliver/telegram',
265
- guardianChatId: 'guardian-chat-789',
266
- requesterIdentifier: 'user-unknown-456',
267
- verificationCode: '123456',
268
- assistantId: 'self',
269
- bearerToken: 'test-token',
272
+ replyCallbackUrl: "http://localhost:7830/deliver/telegram",
273
+ guardianChatId: "guardian-chat-789",
274
+ requesterIdentifier: "user-unknown-456",
275
+ verificationCode: "123456",
276
+ assistantId: "self",
277
+ bearerToken: "test-token",
270
278
  });
271
279
 
272
280
  expect(result.ok).toBe(false);
273
281
  if (!result.ok) {
274
- expect(result.reason).toBe('Gateway timeout');
282
+ expect(result.reason).toBe("Gateway timeout");
275
283
  }
276
284
  // No calls should have been recorded (error thrown before push)
277
285
  expect(deliverReplyCalls.length).toBe(0);
278
286
  });
279
287
 
280
- test('notifies requester of approval', async () => {
288
+ test("notifies requester of approval", async () => {
281
289
  await notifyRequesterOfApproval({
282
- replyCallbackUrl: 'http://localhost:7830/deliver/telegram',
283
- requesterChatId: 'chat-123',
284
- assistantId: 'self',
285
- bearerToken: 'test-token',
290
+ replyCallbackUrl: "http://localhost:7830/deliver/telegram",
291
+ requesterChatId: "chat-123",
292
+ assistantId: "self",
293
+ bearerToken: "test-token",
286
294
  });
287
295
 
288
296
  expect(deliverReplyCalls.length).toBe(1);
289
297
  const call = deliverReplyCalls[0];
290
- expect(call.payload.chatId).toBe('chat-123');
298
+ expect(call.payload.chatId).toBe("chat-123");
291
299
  const text = call.payload.text as string;
292
- expect(text).toContain('approved');
293
- expect(text).toContain('verification code');
300
+ expect(text).toContain("approved");
301
+ expect(text).toContain("verification code");
294
302
  });
295
303
 
296
- test('notifies requester of denial', async () => {
304
+ test("notifies requester of denial", async () => {
297
305
  await notifyRequesterOfDenial({
298
- replyCallbackUrl: 'http://localhost:7830/deliver/telegram',
299
- requesterChatId: 'chat-123',
300
- assistantId: 'self',
301
- bearerToken: 'test-token',
306
+ replyCallbackUrl: "http://localhost:7830/deliver/telegram",
307
+ requesterChatId: "chat-123",
308
+ assistantId: "self",
309
+ bearerToken: "test-token",
302
310
  });
303
311
 
304
312
  expect(deliverReplyCalls.length).toBe(1);
305
313
  const call = deliverReplyCalls[0];
306
- expect(call.payload.chatId).toBe('chat-123');
314
+ expect(call.payload.chatId).toBe("chat-123");
307
315
  const text = call.payload.text as string;
308
- expect(text).toContain('denied');
316
+ expect(text).toContain("denied");
309
317
  });
310
318
 
311
- test('notifies requester of delivery failure', async () => {
319
+ test("notifies requester of delivery failure", async () => {
312
320
  await notifyRequesterOfDeliveryFailure({
313
- replyCallbackUrl: 'http://localhost:7830/deliver/telegram',
314
- requesterChatId: 'chat-123',
315
- assistantId: 'self',
316
- bearerToken: 'test-token',
321
+ replyCallbackUrl: "http://localhost:7830/deliver/telegram",
322
+ requesterChatId: "chat-123",
323
+ assistantId: "self",
324
+ bearerToken: "test-token",
317
325
  });
318
326
 
319
327
  expect(deliverReplyCalls.length).toBe(1);
320
328
  const call = deliverReplyCalls[0];
321
- expect(call.payload.chatId).toBe('chat-123');
329
+ expect(call.payload.chatId).toBe("chat-123");
322
330
  const text = call.payload.text as string;
323
- expect(text).toContain('approved');
324
- expect(text).toContain('unable to deliver');
325
- expect(text).toContain('try again');
331
+ expect(text).toContain("approved");
332
+ expect(text).toContain("unable to deliver");
333
+ expect(text).toContain("try again");
326
334
  });
327
335
  });