@vellumai/assistant 0.4.17 → 0.4.19

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 (528) hide show
  1. package/docs/runbook-trusted-contacts.md +5 -3
  2. package/eslint.config.mjs +2 -2
  3. package/package.json +1 -1
  4. package/src/__tests__/access-request-decision.test.ts +128 -120
  5. package/src/__tests__/account-registry.test.ts +121 -110
  6. package/src/__tests__/active-skill-tools.test.ts +200 -172
  7. package/src/__tests__/actor-token-service.test.ts +341 -274
  8. package/src/__tests__/agent-loop-thinking.test.ts +28 -19
  9. package/src/__tests__/agent-loop.test.ts +798 -378
  10. package/src/__tests__/anthropic-provider.test.ts +405 -247
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
  12. package/src/__tests__/app-bundler.test.ts +112 -79
  13. package/src/__tests__/app-executors.test.ts +205 -178
  14. package/src/__tests__/app-git-history.test.ts +90 -73
  15. package/src/__tests__/app-git-service.test.ts +67 -53
  16. package/src/__tests__/app-open-proxy.test.ts +29 -25
  17. package/src/__tests__/approval-conversation-turn.test.ts +100 -81
  18. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
  19. package/src/__tests__/approval-message-composer.test.ts +119 -119
  20. package/src/__tests__/approval-primitive.test.ts +264 -233
  21. package/src/__tests__/approval-routes-http.test.ts +4 -3
  22. package/src/__tests__/asset-materialize-tool.test.ts +250 -178
  23. package/src/__tests__/asset-search-tool.test.ts +251 -191
  24. package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
  25. package/src/__tests__/assistant-attachments.test.ts +254 -186
  26. package/src/__tests__/assistant-event-hub.test.ts +105 -63
  27. package/src/__tests__/assistant-event.test.ts +66 -58
  28. package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
  29. package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
  30. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
  32. package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
  33. package/src/__tests__/attachments-store.test.ts +240 -183
  34. package/src/__tests__/attachments.test.ts +70 -62
  35. package/src/__tests__/audit-log-rotation.test.ts +50 -35
  36. package/src/__tests__/browser-fill-credential.test.ts +169 -101
  37. package/src/__tests__/browser-manager.test.ts +97 -75
  38. package/src/__tests__/browser-runtime-check.test.ts +16 -15
  39. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
  40. package/src/__tests__/browser-skill-endstate.test.ts +97 -72
  41. package/src/__tests__/bundle-scanner.test.ts +47 -22
  42. package/src/__tests__/bundled-asset.test.ts +74 -47
  43. package/src/__tests__/call-constants.test.ts +19 -19
  44. package/src/__tests__/call-controller.test.ts +0 -1
  45. package/src/__tests__/call-conversation-messages.test.ts +90 -65
  46. package/src/__tests__/call-domain.test.ts +149 -121
  47. package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
  48. package/src/__tests__/call-pointer-messages.test.ts +213 -154
  49. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
  50. package/src/__tests__/call-recovery.test.ts +232 -212
  51. package/src/__tests__/call-routes-http.test.ts +0 -1
  52. package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
  53. package/src/__tests__/call-state-machine.test.ts +62 -51
  54. package/src/__tests__/call-state.test.ts +89 -75
  55. package/src/__tests__/call-store.test.ts +387 -316
  56. package/src/__tests__/callback-handoff-copy.test.ts +84 -82
  57. package/src/__tests__/canonical-guardian-store.test.ts +331 -280
  58. package/src/__tests__/channel-approval-routes.test.ts +1643 -1115
  59. package/src/__tests__/channel-approval.test.ts +139 -137
  60. package/src/__tests__/channel-approvals.test.ts +7 -2
  61. package/src/__tests__/channel-delivery-store.test.ts +232 -194
  62. package/src/__tests__/channel-guardian.test.ts +5 -3
  63. package/src/__tests__/channel-invite-transport.test.ts +107 -92
  64. package/src/__tests__/channel-policy.test.ts +42 -38
  65. package/src/__tests__/channel-readiness-service.test.ts +119 -102
  66. package/src/__tests__/channel-reply-delivery.test.ts +147 -118
  67. package/src/__tests__/channel-retry-sweep.test.ts +153 -110
  68. package/src/__tests__/checker.test.ts +3309 -1850
  69. package/src/__tests__/clarification-resolver.test.ts +91 -79
  70. package/src/__tests__/classifier.test.ts +64 -54
  71. package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
  72. package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
  73. package/src/__tests__/clawhub.test.ts +92 -82
  74. package/src/__tests__/cli.test.ts +30 -30
  75. package/src/__tests__/clipboard.test.ts +53 -46
  76. package/src/__tests__/commit-guarantee.test.ts +59 -52
  77. package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
  78. package/src/__tests__/compaction.benchmark.test.ts +33 -31
  79. package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
  80. package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
  81. package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
  82. package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
  83. package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
  84. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
  85. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
  86. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
  87. package/src/__tests__/computer-use-tools.test.ts +121 -98
  88. package/src/__tests__/config-schema.test.ts +443 -347
  89. package/src/__tests__/config-watcher.test.ts +96 -81
  90. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
  91. package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
  92. package/src/__tests__/conflict-policy.test.ts +151 -80
  93. package/src/__tests__/conflict-store.test.ts +203 -157
  94. package/src/__tests__/connection-policy.test.ts +89 -59
  95. package/src/__tests__/contacts-tools.test.ts +247 -178
  96. package/src/__tests__/context-memory-e2e.test.ts +306 -214
  97. package/src/__tests__/context-token-estimator.test.ts +114 -74
  98. package/src/__tests__/context-window-manager.test.ts +269 -167
  99. package/src/__tests__/contradiction-checker.test.ts +161 -135
  100. package/src/__tests__/conversation-attention-store.test.ts +350 -290
  101. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  102. package/src/__tests__/conversation-pairing.test.ts +220 -113
  103. package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
  104. package/src/__tests__/conversation-store.test.ts +390 -235
  105. package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
  106. package/src/__tests__/credential-broker-server-use.test.ts +283 -243
  107. package/src/__tests__/credential-broker.test.ts +128 -74
  108. package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
  109. package/src/__tests__/credential-metadata-store.test.ts +360 -311
  110. package/src/__tests__/credential-policy-validate.test.ts +81 -65
  111. package/src/__tests__/credential-resolve.test.ts +212 -145
  112. package/src/__tests__/credential-security-e2e.test.ts +144 -103
  113. package/src/__tests__/credential-security-invariants.test.ts +253 -208
  114. package/src/__tests__/credential-selection.test.ts +254 -146
  115. package/src/__tests__/credential-vault-unit.test.ts +531 -341
  116. package/src/__tests__/credential-vault.test.ts +761 -484
  117. package/src/__tests__/daemon-assistant-events.test.ts +91 -66
  118. package/src/__tests__/daemon-lifecycle.test.ts +258 -190
  119. package/src/__tests__/daemon-server-session-init.test.ts +2 -1
  120. package/src/__tests__/date-context.test.ts +314 -249
  121. package/src/__tests__/db-migration-rollback.test.ts +259 -130
  122. package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
  123. package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
  124. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  125. package/src/__tests__/dictation-mode-detection.test.ts +77 -55
  126. package/src/__tests__/dictation-profile-store.test.ts +70 -56
  127. package/src/__tests__/dictation-text-processing.test.ts +53 -35
  128. package/src/__tests__/diff.test.ts +102 -98
  129. package/src/__tests__/domain-normalize.test.ts +54 -54
  130. package/src/__tests__/domain-policy.test.ts +71 -55
  131. package/src/__tests__/dynamic-page-surface.test.ts +31 -33
  132. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
  133. package/src/__tests__/edit-engine.test.ts +56 -56
  134. package/src/__tests__/elevenlabs-client.test.ts +117 -91
  135. package/src/__tests__/elevenlabs-config.test.ts +32 -31
  136. package/src/__tests__/email-classifier.test.ts +15 -12
  137. package/src/__tests__/email-cli.test.ts +121 -108
  138. package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
  139. package/src/__tests__/encrypted-store.test.ts +180 -154
  140. package/src/__tests__/entity-extractor.test.ts +108 -87
  141. package/src/__tests__/entity-search.test.ts +664 -258
  142. package/src/__tests__/ephemeral-permissions.test.ts +224 -188
  143. package/src/__tests__/event-bus.test.ts +81 -77
  144. package/src/__tests__/extract-email.test.ts +29 -20
  145. package/src/__tests__/file-edit-tool.test.ts +62 -44
  146. package/src/__tests__/file-ops-service.test.ts +131 -114
  147. package/src/__tests__/file-read-tool.test.ts +48 -31
  148. package/src/__tests__/file-write-tool.test.ts +43 -37
  149. package/src/__tests__/filesystem-tools.test.ts +238 -209
  150. package/src/__tests__/followup-tools.test.ts +237 -162
  151. package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
  152. package/src/__tests__/frontmatter.test.ts +96 -81
  153. package/src/__tests__/fuzzy-match-property.test.ts +75 -81
  154. package/src/__tests__/fuzzy-match.test.ts +71 -65
  155. package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
  156. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  157. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  158. package/src/__tests__/gemini-image-service.test.ts +113 -100
  159. package/src/__tests__/gemini-provider.test.ts +297 -220
  160. package/src/__tests__/get-weather.test.ts +188 -114
  161. package/src/__tests__/gmail-integration.test.ts +13 -5
  162. package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
  163. package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
  164. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  165. package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
  166. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
  167. package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
  168. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
  169. package/src/__tests__/guardian-action-store.test.ts +158 -109
  170. package/src/__tests__/guardian-action-sweep.test.ts +114 -100
  171. package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
  172. package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
  173. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
  174. package/src/__tests__/guardian-dispatch.test.ts +316 -256
  175. package/src/__tests__/guardian-grant-minting.test.ts +247 -178
  176. package/src/__tests__/guardian-outbound-http.test.ts +5 -3
  177. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
  178. package/src/__tests__/guardian-question-copy.test.ts +17 -17
  179. package/src/__tests__/guardian-question-mode.test.ts +134 -100
  180. package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
  181. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  182. package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
  183. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  184. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
  185. package/src/__tests__/handle-user-message-secret-resume.test.ts +7 -2
  186. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
  187. package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
  188. package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
  189. package/src/__tests__/handlers-slack-config.test.ts +63 -54
  190. package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
  191. package/src/__tests__/handlers-telegram-config.test.ts +662 -329
  192. package/src/__tests__/handlers-twitter-config.test.ts +525 -298
  193. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +5 -2
  194. package/src/__tests__/headless-browser-interactions.test.ts +444 -280
  195. package/src/__tests__/headless-browser-navigate.test.ts +116 -79
  196. package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
  197. package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
  198. package/src/__tests__/heartbeat-service.test.ts +76 -58
  199. package/src/__tests__/history-repair-observability.test.ts +14 -14
  200. package/src/__tests__/history-repair.test.ts +171 -167
  201. package/src/__tests__/home-base-bootstrap.test.ts +30 -27
  202. package/src/__tests__/hooks-blocking.test.ts +86 -37
  203. package/src/__tests__/hooks-cli.test.ts +104 -68
  204. package/src/__tests__/hooks-config.test.ts +81 -43
  205. package/src/__tests__/hooks-discovery.test.ts +106 -96
  206. package/src/__tests__/hooks-integration.test.ts +78 -72
  207. package/src/__tests__/hooks-manager.test.ts +99 -61
  208. package/src/__tests__/hooks-runner.test.ts +94 -71
  209. package/src/__tests__/hooks-settings.test.ts +69 -64
  210. package/src/__tests__/hooks-templates.test.ts +85 -54
  211. package/src/__tests__/hooks-ts-runner.test.ts +82 -45
  212. package/src/__tests__/hooks-watch.test.ts +32 -22
  213. package/src/__tests__/host-file-edit-tool.test.ts +190 -148
  214. package/src/__tests__/host-file-read-tool.test.ts +86 -63
  215. package/src/__tests__/host-file-write-tool.test.ts +98 -64
  216. package/src/__tests__/host-shell-tool.test.ts +342 -233
  217. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  218. package/src/__tests__/ingress-member-store.test.ts +163 -159
  219. package/src/__tests__/ingress-reconcile.test.ts +13 -6
  220. package/src/__tests__/ingress-routes-http.test.ts +441 -356
  221. package/src/__tests__/ingress-url-consistency.test.ts +125 -64
  222. package/src/__tests__/integration-status.test.ts +93 -73
  223. package/src/__tests__/intent-routing.test.ts +148 -118
  224. package/src/__tests__/invite-redemption-service.test.ts +163 -121
  225. package/src/__tests__/ipc-blob-store.test.ts +104 -91
  226. package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
  227. package/src/__tests__/ipc-contract.test.ts +24 -23
  228. package/src/__tests__/ipc-protocol.test.ts +52 -46
  229. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
  230. package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
  231. package/src/__tests__/ipc-validate.test.ts +240 -179
  232. package/src/__tests__/key-migration.test.ts +123 -90
  233. package/src/__tests__/keychain.test.ts +150 -123
  234. package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
  235. package/src/__tests__/llm-usage-store.test.ts +112 -87
  236. package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
  237. package/src/__tests__/managed-store.test.ts +411 -360
  238. package/src/__tests__/mcp-cli.test.ts +190 -124
  239. package/src/__tests__/mcp-health-check.test.ts +26 -21
  240. package/src/__tests__/media-generate-image.test.ts +122 -99
  241. package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
  242. package/src/__tests__/media-visibility-policy.test.ts +86 -38
  243. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
  244. package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
  245. package/src/__tests__/memory-query-builder.test.ts +32 -33
  246. package/src/__tests__/memory-recall-quality.test.ts +761 -407
  247. package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
  248. package/src/__tests__/memory-regressions.test.ts +3725 -2642
  249. package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
  250. package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
  251. package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
  252. package/src/__tests__/messaging-send-tool.test.ts +36 -29
  253. package/src/__tests__/migration-cli-flows.test.ts +69 -53
  254. package/src/__tests__/migration-ordering.test.ts +103 -86
  255. package/src/__tests__/mime-builder.test.ts +55 -32
  256. package/src/__tests__/mock-signup-server.test.ts +384 -246
  257. package/src/__tests__/model-intents.test.ts +61 -37
  258. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
  259. package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
  260. package/src/__tests__/non-member-access-request.test.ts +3 -2
  261. package/src/__tests__/notification-broadcaster.test.ts +99 -81
  262. package/src/__tests__/notification-decision-fallback.test.ts +223 -178
  263. package/src/__tests__/notification-decision-strategy.test.ts +375 -337
  264. package/src/__tests__/notification-deep-link.test.ts +67 -61
  265. package/src/__tests__/notification-guardian-path.test.ts +248 -206
  266. package/src/__tests__/notification-routing-intent.test.ts +166 -93
  267. package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
  268. package/src/__tests__/notification-thread-candidates.test.ts +64 -61
  269. package/src/__tests__/oauth-callback-registry.test.ts +40 -30
  270. package/src/__tests__/oauth-connect-handler.test.ts +109 -89
  271. package/src/__tests__/oauth-scope-policy.test.ts +63 -55
  272. package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
  273. package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
  274. package/src/__tests__/onboarding-template-contract.test.ts +93 -94
  275. package/src/__tests__/openai-provider.test.ts +366 -274
  276. package/src/__tests__/pairing-concurrent.test.ts +18 -12
  277. package/src/__tests__/pairing-routes.test.ts +45 -41
  278. package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
  279. package/src/__tests__/parser.test.ts +316 -226
  280. package/src/__tests__/path-classifier.test.ts +24 -25
  281. package/src/__tests__/path-policy.test.ts +187 -147
  282. package/src/__tests__/phone.test.ts +36 -36
  283. package/src/__tests__/platform-move-helper.test.ts +48 -40
  284. package/src/__tests__/platform-socket-path.test.ts +23 -24
  285. package/src/__tests__/platform-workspace-migration.test.ts +464 -414
  286. package/src/__tests__/platform.test.ts +61 -53
  287. package/src/__tests__/playbook-execution.test.ts +397 -265
  288. package/src/__tests__/playbook-tools.test.ts +267 -196
  289. package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
  290. package/src/__tests__/pricing.test.ts +316 -136
  291. package/src/__tests__/profile-compiler.test.ts +206 -188
  292. package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
  293. package/src/__tests__/provider-error-scenarios.test.ts +212 -158
  294. package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
  295. package/src/__tests__/provider-registry-ollama.test.ts +13 -9
  296. package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
  297. package/src/__tests__/proxy-approval-callback.test.ts +180 -119
  298. package/src/__tests__/public-ingress-urls.test.ts +112 -94
  299. package/src/__tests__/qdrant-manager.test.ts +147 -98
  300. package/src/__tests__/ratelimit.test.ts +152 -82
  301. package/src/__tests__/recording-handler.test.ts +273 -151
  302. package/src/__tests__/recording-intent-fallback.test.ts +94 -75
  303. package/src/__tests__/recording-intent-handler.test.ts +9 -2
  304. package/src/__tests__/recording-intent.test.ts +578 -379
  305. package/src/__tests__/recording-state-machine.test.ts +530 -316
  306. package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
  307. package/src/__tests__/recurrence-engine.test.ts +81 -41
  308. package/src/__tests__/recurrence-types.test.ts +63 -44
  309. package/src/__tests__/relay-server.test.ts +2131 -1602
  310. package/src/__tests__/reminder-store.test.ts +158 -80
  311. package/src/__tests__/reminder.test.ts +113 -109
  312. package/src/__tests__/remote-skill-policy.test.ts +96 -72
  313. package/src/__tests__/request-file-tool.test.ts +74 -67
  314. package/src/__tests__/response-tier.test.ts +131 -74
  315. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  316. package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
  317. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  318. package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
  319. package/src/__tests__/sandbox-host-parity.test.ts +377 -301
  320. package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
  321. package/src/__tests__/schedule-store.test.ts +268 -205
  322. package/src/__tests__/schedule-tools.test.ts +702 -524
  323. package/src/__tests__/scheduler-recurrence.test.ts +240 -130
  324. package/src/__tests__/scoped-approval-grants.test.ts +258 -168
  325. package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
  326. package/src/__tests__/script-proxy-certs.test.ts +38 -35
  327. package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
  328. package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
  329. package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
  330. package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
  331. package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
  332. package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
  333. package/src/__tests__/script-proxy-policy.test.ts +308 -153
  334. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
  335. package/src/__tests__/script-proxy-router.test.ts +111 -77
  336. package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
  337. package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
  338. package/src/__tests__/secret-allowlist.test.ts +105 -90
  339. package/src/__tests__/secret-ingress-handler.test.ts +41 -30
  340. package/src/__tests__/secret-onetime-send.test.ts +67 -50
  341. package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
  342. package/src/__tests__/secret-response-routing.test.ts +50 -41
  343. package/src/__tests__/secret-scanner-executor.test.ts +152 -111
  344. package/src/__tests__/secret-scanner.test.ts +495 -413
  345. package/src/__tests__/secure-keys.test.ts +132 -121
  346. package/src/__tests__/send-endpoint-busy.test.ts +8 -3
  347. package/src/__tests__/send-notification-tool.test.ts +43 -42
  348. package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
  349. package/src/__tests__/sequence-store.test.ts +335 -167
  350. package/src/__tests__/server-history-render.test.ts +341 -202
  351. package/src/__tests__/session-abort-tool-results.test.ts +133 -70
  352. package/src/__tests__/session-confirmation-signals.test.ts +252 -160
  353. package/src/__tests__/session-conflict-gate.test.ts +775 -585
  354. package/src/__tests__/session-error.test.ts +222 -191
  355. package/src/__tests__/session-evictor.test.ts +79 -62
  356. package/src/__tests__/session-init.benchmark.test.ts +170 -108
  357. package/src/__tests__/session-load-history-repair.test.ts +273 -139
  358. package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
  359. package/src/__tests__/session-pre-run-repair.test.ts +106 -59
  360. package/src/__tests__/session-profile-injection.test.ts +198 -130
  361. package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
  362. package/src/__tests__/session-queue.test.ts +624 -321
  363. package/src/__tests__/session-runtime-assembly.test.ts +425 -329
  364. package/src/__tests__/session-runtime-workspace.test.ts +69 -61
  365. package/src/__tests__/session-skill-tools.test.ts +973 -678
  366. package/src/__tests__/session-slash-known.test.ts +185 -133
  367. package/src/__tests__/session-slash-queue.test.ts +147 -81
  368. package/src/__tests__/session-slash-unknown.test.ts +135 -90
  369. package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
  370. package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
  371. package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
  372. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
  373. package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
  374. package/src/__tests__/session-undo.test.ts +43 -30
  375. package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
  376. package/src/__tests__/session-workspace-injection.test.ts +245 -117
  377. package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
  378. package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
  379. package/src/__tests__/shell-credential-ref.test.ts +126 -90
  380. package/src/__tests__/shell-identity.test.ts +134 -111
  381. package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
  382. package/src/__tests__/shell-parser-property.test.ts +435 -288
  383. package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
  384. package/src/__tests__/size-guard.test.ts +42 -44
  385. package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
  386. package/src/__tests__/skill-feature-flags.test.ts +75 -47
  387. package/src/__tests__/skill-include-graph.test.ts +143 -148
  388. package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
  389. package/src/__tests__/skill-load-tool.test.ts +371 -199
  390. package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
  391. package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
  392. package/src/__tests__/skill-script-runner-host.test.ts +460 -250
  393. package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
  394. package/src/__tests__/skill-script-runner.test.ts +115 -74
  395. package/src/__tests__/skill-tool-factory.test.ts +140 -96
  396. package/src/__tests__/skill-tool-manifest.test.ts +306 -210
  397. package/src/__tests__/skill-version-hash.test.ts +70 -56
  398. package/src/__tests__/skills.test.ts +0 -1
  399. package/src/__tests__/slack-channel-config.test.ts +127 -84
  400. package/src/__tests__/slack-skill.test.ts +60 -47
  401. package/src/__tests__/slash-commands-catalog.test.ts +37 -31
  402. package/src/__tests__/slash-commands-parser.test.ts +71 -64
  403. package/src/__tests__/slash-commands-resolver.test.ts +143 -107
  404. package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
  405. package/src/__tests__/sms-messaging-provider.test.ts +4 -0
  406. package/src/__tests__/speaker-identification.test.ts +28 -25
  407. package/src/__tests__/starter-bundle.test.ts +27 -23
  408. package/src/__tests__/starter-task-flow.test.ts +67 -52
  409. package/src/__tests__/subagent-manager-notify.test.ts +154 -108
  410. package/src/__tests__/subagent-tools.test.ts +311 -270
  411. package/src/__tests__/subagent-types.test.ts +40 -40
  412. package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
  413. package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
  414. package/src/__tests__/swarm-orchestrator.test.ts +135 -101
  415. package/src/__tests__/swarm-plan-validator.test.ts +125 -73
  416. package/src/__tests__/swarm-recursion.test.ts +58 -46
  417. package/src/__tests__/swarm-router-planner.test.ts +99 -74
  418. package/src/__tests__/swarm-session-integration.test.ts +148 -91
  419. package/src/__tests__/swarm-tool.test.ts +65 -45
  420. package/src/__tests__/swarm-worker-backend.test.ts +59 -45
  421. package/src/__tests__/swarm-worker-runner.test.ts +133 -118
  422. package/src/__tests__/system-prompt.test.ts +311 -256
  423. package/src/__tests__/task-compiler.test.ts +176 -120
  424. package/src/__tests__/task-management-tools.test.ts +561 -456
  425. package/src/__tests__/task-memory-cleanup.test.ts +627 -362
  426. package/src/__tests__/task-runner.test.ts +117 -94
  427. package/src/__tests__/task-scheduler.test.ts +113 -84
  428. package/src/__tests__/task-tools.test.ts +349 -264
  429. package/src/__tests__/terminal-sandbox.test.ts +138 -108
  430. package/src/__tests__/terminal-tools.test.ts +350 -305
  431. package/src/__tests__/thread-seed-composer.test.ts +307 -180
  432. package/src/__tests__/tool-approval-handler.test.ts +238 -137
  433. package/src/__tests__/tool-audit-listener.test.ts +69 -69
  434. package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
  435. package/src/__tests__/tool-execution-abort-cleanup.test.ts +155 -146
  436. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
  437. package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
  438. package/src/__tests__/tool-executor-redaction.test.ts +112 -109
  439. package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
  440. package/src/__tests__/tool-executor.test.ts +1274 -674
  441. package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
  442. package/src/__tests__/tool-metrics-listener.test.ts +97 -85
  443. package/src/__tests__/tool-notification-listener.test.ts +42 -25
  444. package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
  445. package/src/__tests__/tool-policy.test.ts +44 -25
  446. package/src/__tests__/tool-profiling-listener.test.ts +99 -93
  447. package/src/__tests__/tool-result-truncation.test.ts +5 -4
  448. package/src/__tests__/tool-trace-listener.test.ts +131 -111
  449. package/src/__tests__/top-level-renderer.test.ts +62 -58
  450. package/src/__tests__/top-level-scanner.test.ts +68 -64
  451. package/src/__tests__/trace-emitter.test.ts +56 -56
  452. package/src/__tests__/trust-context-guards.test.ts +65 -65
  453. package/src/__tests__/trust-store.test.ts +1239 -806
  454. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  455. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  456. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +3 -2
  457. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -2
  458. package/src/__tests__/trusted-contact-verification.test.ts +251 -231
  459. package/src/__tests__/turn-commit.test.ts +259 -200
  460. package/src/__tests__/twilio-provider.test.ts +140 -126
  461. package/src/__tests__/twilio-rest.test.ts +22 -18
  462. package/src/__tests__/twilio-routes-elevenlabs.test.ts +0 -1
  463. package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
  464. package/src/__tests__/twilio-routes.test.ts +0 -1
  465. package/src/__tests__/twitter-auth-handler.test.ts +184 -139
  466. package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
  467. package/src/__tests__/twitter-cli-routing.test.ts +146 -99
  468. package/src/__tests__/twitter-oauth-client.test.ts +82 -65
  469. package/src/__tests__/update-bulletin-format.test.ts +69 -66
  470. package/src/__tests__/update-bulletin-state.test.ts +66 -60
  471. package/src/__tests__/update-bulletin.test.ts +150 -114
  472. package/src/__tests__/update-template-contract.test.ts +15 -10
  473. package/src/__tests__/url-safety.test.ts +288 -265
  474. package/src/__tests__/user-reference.test.ts +32 -32
  475. package/src/__tests__/view-image-tool.test.ts +118 -96
  476. package/src/__tests__/voice-invite-redemption.test.ts +111 -106
  477. package/src/__tests__/voice-quality.test.ts +117 -102
  478. package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
  479. package/src/__tests__/voice-session-bridge.test.ts +351 -216
  480. package/src/__tests__/weather-skill-regression.test.ts +170 -120
  481. package/src/__tests__/web-fetch.test.ts +664 -526
  482. package/src/__tests__/web-search.test.ts +379 -213
  483. package/src/__tests__/work-item-output.test.ts +90 -53
  484. package/src/__tests__/workspace-git-service.test.ts +437 -356
  485. package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
  486. package/src/__tests__/workspace-lifecycle.test.ts +98 -64
  487. package/src/__tests__/workspace-policy.test.ts +139 -71
  488. package/src/cli/mcp.ts +81 -28
  489. package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
  490. package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
  491. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +25 -10
  492. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
  493. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +6 -11
  494. package/src/config/bundled-skills/messaging/SKILL.md +4 -3
  495. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
  496. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
  497. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -2
  498. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
  499. package/src/config/bundled-skills/sms-setup/SKILL.md +8 -16
  500. package/src/config/bundled-skills/telegram-setup/SKILL.md +3 -3
  501. package/src/config/bundled-skills/trusted-contacts/SKILL.md +13 -25
  502. package/src/config/bundled-skills/twilio-setup/SKILL.md +13 -23
  503. package/src/config/bundled-tool-registry.ts +2 -0
  504. package/src/config/env.ts +3 -4
  505. package/src/config/system-prompt.ts +32 -0
  506. package/src/mcp/client.ts +2 -7
  507. package/src/memory/db-connection.ts +16 -10
  508. package/src/messaging/providers/gmail/adapter.ts +10 -3
  509. package/src/messaging/providers/gmail/client.ts +280 -72
  510. package/src/runtime/auth/__tests__/context.test.ts +75 -65
  511. package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
  512. package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
  513. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
  514. package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
  515. package/src/runtime/auth/__tests__/policy.test.ts +9 -9
  516. package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
  517. package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
  518. package/src/runtime/auth/__tests__/subject.test.ts +54 -54
  519. package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
  520. package/src/runtime/auth/scopes.ts +3 -0
  521. package/src/runtime/auth/token-service.ts +4 -1
  522. package/src/runtime/auth/types.ts +2 -1
  523. package/src/runtime/http-server.ts +2 -1
  524. package/src/security/secure-keys.ts +120 -54
  525. package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
  526. package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
  527. package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
  528. package/src/tools/terminal/safe-env.ts +7 -0
@@ -5,11 +5,13 @@ Operational procedures for inspecting, managing, and debugging the trusted conta
5
5
  ## Prerequisites
6
6
 
7
7
  ```bash
8
- # Read the bearer token
9
- TOKEN=$(cat ~/.vellum/http-token)
10
-
11
8
  # Base URL (adjust if using a non-default port)
12
9
  BASE=http://localhost:7830
10
+
11
+ # Bearer token: if running via the assistant's shell tools, $GATEWAY_AUTH_TOKEN
12
+ # is injected automatically. For manual operator use, mint a token via the CLI
13
+ # or use one from the daemon (e.g. from a recent shell env export).
14
+ TOKEN=$GATEWAY_AUTH_TOKEN
13
15
  ```
14
16
 
15
17
  ## 1. Inspect Trusted Contacts (Members)
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.17",
3
+ "version": "0.4.19",
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
  });