@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2

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 (430) hide show
  1. package/bun.lock +0 -20
  2. package/docs/workspace-tools.md +33 -42
  3. package/eslint-rules/cli-no-daemon-internals.js +0 -6
  4. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
  5. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
  6. package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
  7. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
  8. package/node_modules/@vellumai/service-contracts/package.json +0 -1
  9. package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
  10. package/openapi.yaml +0 -155
  11. package/package.json +1 -4
  12. package/scripts/test.sh +15 -36
  13. package/src/__tests__/actor-token-service.test.ts +14 -36
  14. package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
  15. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
  16. package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
  17. package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
  18. package/src/__tests__/annotate-risk-options.test.ts +0 -2
  19. package/src/__tests__/approval-cascade.test.ts +0 -2
  20. package/src/__tests__/assistant-attachments.test.ts +0 -42
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  22. package/src/__tests__/btw-routes.test.ts +0 -2
  23. package/src/__tests__/build-persisted-content.test.ts +0 -2
  24. package/src/__tests__/call-controller.test.ts +0 -19
  25. package/src/__tests__/channel-guardian.test.ts +58 -94
  26. package/src/__tests__/channel-reply-delivery.test.ts +0 -2
  27. package/src/__tests__/compaction-events.test.ts +0 -2
  28. package/src/__tests__/compaction.benchmark.test.ts +0 -2
  29. package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
  30. package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
  31. package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
  32. package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
  33. package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
  34. package/src/__tests__/config-loader-backfill.test.ts +10 -123
  35. package/src/__tests__/config-schema.test.ts +0 -1
  36. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
  37. package/src/__tests__/contacts-relay-reads.test.ts +15 -13
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
  39. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  42. package/src/__tests__/conversation-agent-loop.test.ts +0 -134
  43. package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
  44. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
  45. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
  46. package/src/__tests__/conversation-history-web-search.test.ts +0 -2
  47. package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
  48. package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
  49. package/src/__tests__/conversation-pairing.test.ts +0 -2
  50. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +0 -2
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
  53. package/src/__tests__/conversation-queue.test.ts +0 -91
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
  56. package/src/__tests__/conversation-slash-queue.test.ts +0 -2
  57. package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
  58. package/src/__tests__/conversation-speed-override.test.ts +0 -2
  59. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
  60. package/src/__tests__/conversation-title-service.test.ts +0 -2
  61. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
  62. package/src/__tests__/conversation-usage.test.ts +0 -2
  63. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
  64. package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
  65. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
  66. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  67. package/src/__tests__/db-migration-rollback.test.ts +171 -205
  68. package/src/__tests__/db-test-helpers.ts +4 -5
  69. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
  70. package/src/__tests__/disk-pressure-guard.test.ts +0 -41
  71. package/src/__tests__/dm-persistence.test.ts +0 -2
  72. package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
  73. package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
  74. package/src/__tests__/exploration-drift-hook.test.ts +2 -3
  75. package/src/__tests__/filing-service.test.ts +0 -2
  76. package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
  77. package/src/__tests__/guardian-dispatch.test.ts +1 -95
  78. package/src/__tests__/guardian-outbound-http.test.ts +0 -13
  79. package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
  80. package/src/__tests__/heartbeat-service.test.ts +0 -2
  81. package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
  82. package/src/__tests__/host-app-control-routes.test.ts +30 -24
  83. package/src/__tests__/host-bash-routes.test.ts +41 -31
  84. package/src/__tests__/host-browser-routes.test.ts +32 -26
  85. package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
  86. package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
  87. package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
  88. package/src/__tests__/http-user-message-parity.test.ts +8 -290
  89. package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
  90. package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
  91. package/src/__tests__/invite-redemption-service.test.ts +0 -198
  92. package/src/__tests__/llm-context-normalization.test.ts +0 -105
  93. package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
  94. package/src/__tests__/llm-usage-store.test.ts +0 -25
  95. package/src/__tests__/mcp-health-check.test.ts +1 -2
  96. package/src/__tests__/media-stream-server-integration.test.ts +0 -127
  97. package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
  98. package/src/__tests__/messaging-send-tool.test.ts +0 -2
  99. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  100. package/src/__tests__/mtime-cache.test.ts +5 -146
  101. package/src/__tests__/native-web-search.test.ts +0 -2
  102. package/src/__tests__/non-member-access-request.test.ts +17 -189
  103. package/src/__tests__/notification-broadcaster.test.ts +0 -4
  104. package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
  105. package/src/__tests__/notification-deep-link.test.ts +0 -6
  106. package/src/__tests__/notification-guardian-path.test.ts +0 -19
  107. package/src/__tests__/openai-provider.test.ts +12 -22
  108. package/src/__tests__/openai-responses-provider.test.ts +2 -12
  109. package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
  110. package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
  111. package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
  112. package/src/__tests__/plugin-bootstrap.test.ts +73 -3
  113. package/src/__tests__/plugin-route-contribution.test.ts +17 -4
  114. package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
  115. package/src/__tests__/plugin-types.test.ts +2 -0
  116. package/src/__tests__/process-message-background-slack.test.ts +0 -2
  117. package/src/__tests__/process-message-display-content.test.ts +0 -2
  118. package/src/__tests__/provider-error-scenarios.test.ts +4 -5
  119. package/src/__tests__/provider-usage-tracking.test.ts +0 -39
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
  121. package/src/__tests__/registry.test.ts +1 -4
  122. package/src/__tests__/relay-server.test.ts +25 -694
  123. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
  124. package/src/__tests__/secret-ingress-http.test.ts +0 -14
  125. package/src/__tests__/send-endpoint-busy.test.ts +8 -30
  126. package/src/__tests__/skills.test.ts +0 -44
  127. package/src/__tests__/slack-inbound-verification.test.ts +2 -47
  128. package/src/__tests__/stt-hints.test.ts +13 -44
  129. package/src/__tests__/subagent-detail.test.ts +0 -27
  130. package/src/__tests__/subagent-disposal.test.ts +0 -65
  131. package/src/__tests__/subagent-notify-parent.test.ts +0 -2
  132. package/src/__tests__/subagent-role-registry.test.ts +2 -7
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
  134. package/src/__tests__/subagent-tools.test.ts +0 -2
  135. package/src/__tests__/suggestion-routes.test.ts +0 -2
  136. package/src/__tests__/title-generate-hook.test.ts +0 -2
  137. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
  138. package/src/__tests__/tool-executor.test.ts +11 -16
  139. package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
  140. package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
  141. package/src/__tests__/tool-start-timestamp.test.ts +0 -2
  142. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
  143. package/src/__tests__/twilio-routes.test.ts +0 -96
  144. package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
  145. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  146. package/src/__tests__/voice-invite-redemption.test.ts +0 -33
  147. package/src/__tests__/web-search-backend-failure.test.ts +0 -2
  148. package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
  149. package/src/__tests__/workspace-tool-loader.test.ts +2 -195
  150. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  151. package/src/agent/loop.ts +0 -56
  152. package/src/api/index.ts +1 -19
  153. package/src/api/responses/llm-request-log-entry.ts +0 -29
  154. package/src/api/responses/subagent-detail.ts +0 -17
  155. package/src/api/surfaces.ts +3 -39
  156. package/src/approvals/guardian-request-resolvers.ts +11 -1
  157. package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
  158. package/src/calls/call-domain.ts +3 -3
  159. package/src/calls/guardian-dispatch.ts +8 -10
  160. package/src/calls/inbound-trust-reader.ts +1 -17
  161. package/src/calls/media-stream-server.ts +0 -21
  162. package/src/calls/relay-server.ts +50 -167
  163. package/src/calls/relay-setup-router.ts +7 -37
  164. package/src/calls/relay-verification.ts +4 -4
  165. package/src/calls/stt-hints.ts +12 -9
  166. package/src/calls/twilio-routes.ts +4 -14
  167. package/src/channels/types.ts +20 -10
  168. package/src/cli/commands/__tests__/cache.test.ts +1 -8
  169. package/src/cli/commands/cache.ts +181 -194
  170. package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
  171. package/src/cli/commands/db/status.ts +1 -37
  172. package/src/cli/commands/mcp.ts +218 -252
  173. package/src/cli/commands/memory/index.ts +0 -2
  174. package/src/cli/commands/plugins.ts +3 -75
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
  177. package/src/cli/lib/list-installed-plugins.ts +1 -179
  178. package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
  179. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
  180. package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
  181. package/src/config/bundled-skills/subagent/SKILL.md +1 -1
  182. package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
  183. package/src/config/feature-flag-registry.json +13 -5
  184. package/src/config/loader.ts +5 -38
  185. package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
  186. package/src/config/schemas/memory-lifecycle.ts +0 -12
  187. package/src/config/schemas/memory-v3.ts +0 -7
  188. package/src/config/schemas/memory.ts +0 -4
  189. package/src/config/schemas/timeouts.ts +0 -8
  190. package/src/config/seed-inference-profiles.ts +11 -21
  191. package/src/config/skills.ts +5 -27
  192. package/src/config/sync-gated-profiles.ts +13 -12
  193. package/src/contacts/contacts-write.ts +0 -3
  194. package/src/daemon/assistant-attachments.ts +4 -27
  195. package/src/daemon/conversation-agent-loop.ts +0 -28
  196. package/src/daemon/conversation-process.ts +16 -35
  197. package/src/daemon/conversation-surfaces.ts +38 -111
  198. package/src/daemon/conversation-tool-setup.ts +16 -50
  199. package/src/daemon/conversation.ts +1 -13
  200. package/src/daemon/disk-pressure-guard.ts +2 -12
  201. package/src/daemon/event-loop-watchdog.ts +1 -28
  202. package/src/daemon/external-plugins-bootstrap.ts +34 -4
  203. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
  204. package/src/daemon/handlers/config-a2a.ts +14 -6
  205. package/src/daemon/handlers/config-channels.ts +22 -78
  206. package/src/daemon/handlers/conversations.ts +0 -77
  207. package/src/daemon/lifecycle.ts +0 -4
  208. package/src/daemon/mcp-reload-service.ts +0 -10
  209. package/src/daemon/memory-v2-startup.test.ts +0 -72
  210. package/src/daemon/memory-v2-startup.ts +19 -87
  211. package/src/daemon/message-types/conversations.ts +0 -2
  212. package/src/daemon/message-types/surfaces.ts +12 -12
  213. package/src/daemon/server.ts +4 -0
  214. package/src/daemon/shutdown-handlers.ts +0 -20
  215. package/src/daemon/tool-setup-types.ts +0 -9
  216. package/src/daemon/workspace-tools-watcher.ts +328 -0
  217. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  218. package/src/ipc/assistant-server.ts +2 -2
  219. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  220. package/src/mcp/client.ts +1 -15
  221. package/src/mcp/mcp-auth-orchestrator.ts +1 -6
  222. package/src/mcp/mcp-oauth-provider.ts +8 -19
  223. package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
  224. package/src/memory/conversation-crud.ts +0 -38
  225. package/src/memory/db-connection.ts +3 -22
  226. package/src/memory/db-init.ts +502 -36
  227. package/src/memory/db-singleton.ts +4 -6
  228. package/src/memory/jobs-worker.ts +0 -58
  229. package/src/memory/llm-request-log-store.ts +1 -26
  230. package/src/memory/llm-usage-store.ts +20 -48
  231. package/src/memory/memory-retrospective-job.ts +8 -9
  232. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
  233. package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
  234. package/src/memory/migrations/registry.ts +573 -0
  235. package/src/memory/migrations/run-migrations.ts +6 -90
  236. package/src/memory/migrations/validate-migration-state.ts +66 -101
  237. package/src/memory/schema/conversations.ts +0 -9
  238. package/src/memory/schema/infrastructure.ts +0 -20
  239. package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
  240. package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
  241. package/src/memory/v2/cli-command-store.ts +38 -75
  242. package/src/memory/v2/prompts/consolidation.ts +82 -13
  243. package/src/memory/v2/prompts/router.ts +93 -21
  244. package/src/memory/v2/skill-store.ts +31 -68
  245. package/src/notifications/__tests__/broadcaster.test.ts +8 -16
  246. package/src/notifications/__tests__/decision-engine.test.ts +9 -78
  247. package/src/notifications/broadcaster.ts +1 -8
  248. package/src/notifications/decision-engine.ts +7 -15
  249. package/src/notifications/destination-resolver.ts +24 -68
  250. package/src/notifications/emit-signal.ts +14 -39
  251. package/src/permissions/question-prompter.test.ts +1 -1
  252. package/src/permissions/question-prompter.ts +4 -7
  253. package/src/plugin-api/index.ts +6 -6
  254. package/src/plugin-api/types.ts +5 -3
  255. package/src/plugin-api/vision-support.test.ts +4 -28
  256. package/src/plugin-api/vision-support.ts +31 -66
  257. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
  258. package/src/plugins/defaults/advisor/consult.ts +6 -110
  259. package/src/plugins/defaults/advisor/steering.ts +2 -14
  260. package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
  261. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
  262. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
  263. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
  264. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
  265. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
  266. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
  267. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
  268. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
  269. package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
  270. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
  271. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
  272. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
  273. package/src/plugins/mtime-cache.ts +291 -76
  274. package/src/plugins/pipeline.ts +13 -111
  275. package/src/plugins/types.ts +2 -0
  276. package/src/providers/anthropic/client.ts +0 -5
  277. package/src/providers/call-site-routing.ts +0 -4
  278. package/src/providers/model-catalog.ts +0 -16
  279. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  280. package/src/providers/openai/chat-completions-provider.ts +83 -37
  281. package/src/providers/openai/responses-provider.ts +46 -50
  282. package/src/providers/openrouter/client.ts +0 -5
  283. package/src/providers/provider-send-message.ts +0 -4
  284. package/src/providers/ratelimit.ts +0 -4
  285. package/src/providers/retry.ts +0 -4
  286. package/src/providers/types.ts +0 -9
  287. package/src/providers/usage-tracking.ts +0 -4
  288. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
  289. package/src/runtime/access-request-helper.ts +39 -19
  290. package/src/runtime/actor-trust-resolver.ts +2 -2
  291. package/src/runtime/assistant-event-hub.ts +1 -1
  292. package/src/runtime/assistant-stream-state.ts +2 -9
  293. package/src/runtime/auth/require-bound-guardian.ts +11 -21
  294. package/src/runtime/channel-verification-service.ts +31 -56
  295. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
  296. package/src/runtime/guardian-vellum-migration.ts +7 -66
  297. package/src/runtime/invite-redemption-service.ts +187 -198
  298. package/src/runtime/local-actor-identity.ts +11 -76
  299. package/src/runtime/pending-interactions.ts +1 -11
  300. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
  301. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  302. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
  303. package/src/runtime/routes/browser-routes.ts +1 -1
  304. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
  305. package/src/runtime/routes/channel-verification-routes.ts +3 -3
  306. package/src/runtime/routes/contact-routes.ts +32 -8
  307. package/src/runtime/routes/conversation-cli-routes.ts +5 -4
  308. package/src/runtime/routes/conversation-list-routes.ts +7 -4
  309. package/src/runtime/routes/conversation-query-routes.ts +0 -72
  310. package/src/runtime/routes/conversation-routes.ts +85 -84
  311. package/src/runtime/routes/events-routes.ts +2 -2
  312. package/src/runtime/routes/global-search-routes.ts +1 -3
  313. package/src/runtime/routes/guardian-action-routes.ts +5 -4
  314. package/src/runtime/routes/host-app-control-routes.ts +4 -5
  315. package/src/runtime/routes/host-bash-routes.ts +4 -5
  316. package/src/runtime/routes/host-browser-routes.ts +11 -9
  317. package/src/runtime/routes/host-cu-routes.ts +4 -5
  318. package/src/runtime/routes/host-file-routes.ts +4 -5
  319. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  320. package/src/runtime/routes/http-adapter.ts +1 -1
  321. package/src/runtime/routes/identity-routes.ts +2 -3
  322. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  323. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
  324. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
  325. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
  326. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
  327. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
  328. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
  329. package/src/runtime/routes/index.ts +0 -2
  330. package/src/runtime/routes/llm-context-normalization.ts +0 -83
  331. package/src/runtime/routes/mcp-auth-routes.ts +19 -171
  332. package/src/runtime/routes/migration-rollback-routes.ts +3 -4
  333. package/src/runtime/routes/migration-routes.ts +1 -4
  334. package/src/runtime/routes/subagents-routes.ts +0 -5
  335. package/src/runtime/routes/surface-action-routes.ts +56 -42
  336. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
  337. package/src/runtime/services/conversation-serializer.ts +9 -7
  338. package/src/runtime/tool-grant-request-helper.ts +3 -3
  339. package/src/runtime/trust-verdict-consumer.ts +9 -85
  340. package/src/runtime/verification-outbound-actions.ts +18 -18
  341. package/src/signals/user-message.ts +0 -16
  342. package/src/subagent/manager.ts +0 -9
  343. package/src/subagent/types.ts +3 -3
  344. package/src/telemetry/types.ts +1 -34
  345. package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
  346. package/src/telemetry/usage-telemetry-reporter.ts +3 -87
  347. package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
  348. package/src/tools/ask-question/ask-question-tool.ts +0 -13
  349. package/src/tools/executor.ts +4 -4
  350. package/src/tools/registry.ts +0 -18
  351. package/src/tools/shared/filesystem/path-policy.ts +5 -12
  352. package/src/tools/tool-approval-handler.ts +1 -1
  353. package/src/tools/tool-defaults.ts +2 -9
  354. package/src/tools/tool-manifest.ts +0 -3
  355. package/src/tools/types.ts +2 -17
  356. package/src/tools/workspace-tools/loader.ts +244 -348
  357. package/src/util/errors.ts +1 -26
  358. package/src/util/platform.ts +0 -5
  359. package/src/workflows/library.test.ts +0 -140
  360. package/src/workflows/library.ts +28 -82
  361. package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
  362. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
  363. package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
  364. package/src/workspace/migrations/registry.ts +0 -2
  365. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
  366. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
  367. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
  368. package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
  369. package/src/__tests__/code-search-tool.test.ts +0 -585
  370. package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
  371. package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
  372. package/src/__tests__/plugin-pipeline.test.ts +0 -96
  373. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
  374. package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
  375. package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
  376. package/src/agent/loop-exclusive-tool.test.ts +0 -150
  377. package/src/api/constants/sse-replay.ts +0 -41
  378. package/src/api/events/conversation-notice.ts +0 -26
  379. package/src/approvals/guardian-channel-delivery.ts +0 -30
  380. package/src/approvals/guardian-expiry-notifier.ts +0 -148
  381. package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
  382. package/src/cli/commands/memory/worker.ts +0 -175
  383. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
  384. package/src/config/prune-seeded-callsite-defaults.ts +0 -110
  385. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
  386. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
  387. package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
  388. package/src/contacts/guardian-delivery-reader.ts +0 -223
  389. package/src/contacts/member-write-relay.ts +0 -189
  390. package/src/daemon/conversation-notices.ts +0 -60
  391. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
  392. package/src/hooks/hook-loader.ts +0 -341
  393. package/src/mcp/mcp-header-store.ts +0 -134
  394. package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
  395. package/src/memory/__tests__/prompt-override.test.ts +0 -192
  396. package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
  397. package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
  398. package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
  399. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
  400. package/src/memory/prompt-override.ts +0 -129
  401. package/src/memory/steps.ts +0 -573
  402. package/src/memory/watchdog-events-store.ts +0 -87
  403. package/src/memory/worker-control.ts +0 -118
  404. package/src/memory/worker-process.ts +0 -72
  405. package/src/notifications/__tests__/connected-channels.test.ts +0 -114
  406. package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
  407. package/src/onboarding/checkin-event.test.ts +0 -222
  408. package/src/onboarding/checkin-event.ts +0 -321
  409. package/src/onboarding/schedule-checkin.ts +0 -190
  410. package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
  411. package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
  412. package/src/plugins/defaults/advisor/context-pack.ts +0 -288
  413. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
  414. package/src/plugins/surface-import.ts +0 -121
  415. package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
  416. package/src/providers/openai/api-error-normalization.ts +0 -270
  417. package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
  418. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
  419. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
  420. package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
  421. package/src/runtime/anchored-guardian.test.ts +0 -156
  422. package/src/runtime/anchored-guardian.ts +0 -135
  423. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
  424. package/src/runtime/local-principal-trust.ts +0 -52
  425. package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
  426. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
  427. package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
  428. package/src/tools/filesystem/search.ts +0 -543
  429. package/src/util/telemetry-db-path.ts +0 -24
  430. package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
@@ -62,21 +62,6 @@ mock.module("../runtime/guardian-reply-router.js", () => ({
62
62
  routeGuardianReply: routeGuardianReplyMock,
63
63
  }));
64
64
 
65
- // Stub for the shared reset-drift helper. handleSendMessage only consumes its
66
- // result (a guardian TrustContext or null) on a first-pass-unknown actor; the
67
- // gate itself is covered in runtime/__tests__/guardian-vellum-migration.test.ts.
68
- const reResolveCalls: string[] = [];
69
- let mockReResolve: { trustClass: string; sourceChannel: string } | null = null;
70
- mock.module("../runtime/guardian-vellum-migration.js", () => ({
71
- reResolveTrustOnResetDrift: async (
72
- incomingPrincipalId: string,
73
- _sourceChannel: string,
74
- ) => {
75
- reResolveCalls.push(incomingPrincipalId);
76
- return mockReResolve;
77
- },
78
- }));
79
-
80
65
  mock.module("../memory/canonical-guardian-store.js", () => ({
81
66
  createCanonicalGuardianRequest: () => ({
82
67
  id: "canonical-id",
@@ -109,8 +94,6 @@ mock.module("../runtime/confirmation-request-guardian-bridge.js", () => ({
109
94
  }));
110
95
 
111
96
  mock.module("../memory/conversation-crud.js", () => ({
112
- setConversationProcessingStartedAt: () => {},
113
- isConversationProcessing: () => false,
114
97
  addMessage: (
115
98
  conversationId: string,
116
99
  role: string,
@@ -121,70 +104,17 @@ mock.module("../memory/conversation-crud.js", () => ({
121
104
  }));
122
105
 
123
106
  mock.module("../runtime/local-actor-identity.js", () => ({
124
- findLocalGuardianPrincipalId: async () =>
125
- mockGuardians?.find(
126
- (g) => g.channelType === "vellum" && g.status === "active",
127
- )?.principalId as string | undefined,
128
- }));
129
-
130
- // Capture the sourceActorPrincipalId that handleSendMessage threads into
131
- // shouldAttachHostProxyForCapability / preactivateHostProxySkills, so tests
132
- // can assert the dev-bypass translation landed before the CU proxy gate.
133
- // The macOS "native_support" path short-circuits before reading the
134
- // principal, so only web/ios turns exercise the same-actor branch.
135
- const hostProxyAttachCalls: Array<{
136
- capability: string;
137
- sourceInterface: unknown;
138
- sourceActorPrincipalId: string | undefined;
139
- }> = [];
140
- const preactivateCalls: Array<{
141
- sourceInterface: unknown;
142
- sourceActorPrincipalId: string | undefined;
143
- }> = [];
144
- mock.module("../daemon/host-proxy-preactivation.js", () => ({
145
- shouldAttachHostProxyForCapability: (
146
- capability: string,
147
- sourceInterface: unknown,
148
- sourceActorPrincipalId: string | undefined,
149
- ) => {
150
- hostProxyAttachCalls.push({
151
- capability,
152
- sourceInterface,
153
- sourceActorPrincipalId,
154
- });
155
- // Return false so the route skips proxy instantiation; we only care
156
- // that the translated principal reached the gate.
157
- return false;
158
- },
159
- preactivateHostProxySkills: (
160
- _conversation: unknown,
161
- sourceInterface: unknown,
162
- sourceActorPrincipalId: string | undefined,
163
- ) => {
164
- preactivateCalls.push({ sourceInterface, sourceActorPrincipalId });
165
- },
166
- }));
167
-
168
- let mockGuardians: Array<Record<string, unknown>> | null = [
169
- {
170
- channelType: "vellum",
171
- contactId: "guardian-contact",
172
- principalId: "test-user",
173
- address: "test-user",
174
- status: "active",
175
- },
176
- ];
177
-
178
- mock.module("../contacts/guardian-delivery-reader.js", () => ({
179
- getGuardianDelivery: async () => mockGuardians,
180
- guardianForChannel: (
181
- list: Array<Record<string, unknown>>,
182
- channelType: string,
183
- ) => list.find((g) => g.channelType === channelType && g.status === "active"),
107
+ resolveLocalTrustContext: () => ({
108
+ trustClass: "guardian",
109
+ sourceChannel: "vellum",
110
+ }),
184
111
  }));
185
112
 
186
- // handleSendMessage wraps the first-pass resolve with withSourceChannel.
187
113
  mock.module("../runtime/trust-context-resolver.js", () => ({
114
+ resolveTrustContext: () => ({
115
+ trustClass: "guardian",
116
+ sourceChannel: "vellum",
117
+ }),
188
118
  withSourceChannel: (sourceChannel: unknown, ctx: unknown) => ({
189
119
  ...(ctx as Record<string, unknown>),
190
120
  sourceChannel,
@@ -524,215 +454,3 @@ describe("HTTP POST /v1/messages clientTimezone transport metadata", () => {
524
454
  expect(runAgentLoop).toHaveBeenCalledTimes(1);
525
455
  });
526
456
  });
527
-
528
- // ============================================================================
529
- // TRUST CONTEXT — derived from the gateway guardian binding
530
- // ============================================================================
531
- describe("HTTP POST /v1/messages trust context from the gateway binding", () => {
532
- beforeEach(() => {
533
- mockGuardians = [
534
- {
535
- channelType: "vellum",
536
- contactId: "guardian-contact",
537
- principalId: "test-user",
538
- address: "test-user",
539
- status: "active",
540
- },
541
- ];
542
- reResolveCalls.length = 0;
543
- mockReResolve = null;
544
- });
545
-
546
- function requestAs(principalId: string, sourceChannel = "vellum") {
547
- return new Request("http://localhost/v1/messages", {
548
- method: "POST",
549
- headers: {
550
- "Content-Type": "application/json",
551
- "x-vellum-actor-principal-id": principalId,
552
- "x-vellum-principal-type": "actor",
553
- },
554
- body: JSON.stringify({
555
- conversationKey: "trust-test-key",
556
- content: "hi",
557
- sourceChannel,
558
- interface: "macos",
559
- }),
560
- });
561
- }
562
-
563
- async function trustContextFor(
564
- principalId: string,
565
- sourceChannel = "vellum",
566
- ): Promise<Record<string, unknown>> {
567
- let captured: Record<string, unknown> | undefined;
568
- const conversation = makeConversation({
569
- setTrustContext: (ctx: Record<string, unknown>) => {
570
- captured = ctx;
571
- },
572
- });
573
- const res = await callHandler(
574
- (args) =>
575
- handleSendMessage(args, {
576
- sendMessageDeps: {
577
- getOrCreateConversation: async () => conversation,
578
- assistantEventHub: { publish: async () => {} } as any,
579
- resolveAttachments: () => [],
580
- },
581
- }),
582
- requestAs(principalId, sourceChannel),
583
- undefined,
584
- 202,
585
- );
586
- expect(res.status).toBe(202);
587
- return captured ?? {};
588
- }
589
-
590
- async function trustClassFor(principalId: string): Promise<string> {
591
- return (await trustContextFor(principalId)).trustClass as string;
592
- }
593
-
594
- test("guardian principal resolves to guardian context, helper not called", async () => {
595
- expect(await trustClassFor("test-user")).toBe("guardian");
596
- expect(reResolveCalls).toEqual([]);
597
- });
598
-
599
- test("non-guardian principal: helper consulted, null result stays unknown", async () => {
600
- mockReResolve = null;
601
- expect(await trustClassFor("vellum-principal-stranger")).toBe("unknown");
602
- expect(reResolveCalls).toEqual(["vellum-principal-stranger"]);
603
- });
604
-
605
- test("reset drift: helper returns guardian → route adopts it", async () => {
606
- mockGuardians = [
607
- {
608
- channelType: "vellum",
609
- contactId: "guardian-contact",
610
- principalId: "vellum-principal-stale",
611
- address: "vellum-principal-stale",
612
- status: "active",
613
- },
614
- ];
615
- mockReResolve = { trustClass: "guardian", sourceChannel: "vellum" };
616
-
617
- expect(await trustClassFor("vellum-principal-healed")).toBe("guardian");
618
- expect(reResolveCalls).toEqual(["vellum-principal-healed"]);
619
- });
620
-
621
- test("helper returns an unknown-class ctx → trust stays unknown (not adopted)", async () => {
622
- mockGuardians = [
623
- {
624
- channelType: "vellum",
625
- contactId: "guardian-contact",
626
- principalId: "vellum-principal-stale",
627
- address: "vellum-principal-stale",
628
- status: "active",
629
- },
630
- ];
631
- mockReResolve = { trustClass: "unknown", sourceChannel: "vellum" };
632
-
633
- expect(await trustClassFor("vellum-principal-healed")).toBe("unknown");
634
- });
635
-
636
- test("dev-bypass maps the gateway guardian principal to guardian", async () => {
637
- expect(await trustClassFor("dev-bypass")).toBe("guardian");
638
- });
639
-
640
- test("dev-bypass fails closed to unknown on an empty gateway", async () => {
641
- // No active gateway binding: dev-bypass cannot translate to a real guardian,
642
- // and the helper (null) leaves trust unknown — parity with /v1/surface-actions.
643
- mockGuardians = [];
644
- mockReResolve = null;
645
- expect(await trustClassFor("dev-bypass")).toBe("unknown");
646
- });
647
-
648
- test("preserves the request body channel on the guardian-match happy path", async () => {
649
- const ctx = await trustContextFor("test-user", "telegram");
650
- expect(ctx.trustClass).toBe("guardian");
651
- expect(ctx.sourceChannel).toBe("telegram");
652
- });
653
-
654
- // A web turn's "dev-bypass" principal must translate to the real guardian
655
- // principal before the CU/app-control same-actor proxy-attachment gate,
656
- // so it matches the macOS client's SSE-registered principal.
657
- test("dev-bypass is translated to the guardian principal before the CU proxy attach gate (web turn)", async () => {
658
- hostProxyAttachCalls.length = 0;
659
- preactivateCalls.length = 0;
660
- const conversation = makeConversation();
661
- const res = await callHandler(
662
- (args) =>
663
- handleSendMessage(args, {
664
- sendMessageDeps: {
665
- getOrCreateConversation: async () => conversation,
666
- assistantEventHub: { publish: async () => {} } as any,
667
- resolveAttachments: () => [],
668
- },
669
- }),
670
- new Request("http://localhost/v1/messages", {
671
- method: "POST",
672
- headers: {
673
- "Content-Type": "application/json",
674
- "x-vellum-actor-principal-id": "dev-bypass",
675
- "x-vellum-principal-type": "actor",
676
- },
677
- body: JSON.stringify({
678
- conversationKey: "cu-attach-key",
679
- content: "hi",
680
- sourceChannel: "vellum",
681
- interface: "web",
682
- }),
683
- }),
684
- undefined,
685
- 202,
686
- );
687
- expect(res.status).toBe(202);
688
-
689
- // The CU attach gate receives the translated guardian principal, not
690
- // the raw "dev-bypass" string.
691
- const cuCall = hostProxyAttachCalls.find(
692
- (c) => c.capability === "host_cu",
693
- );
694
- expect(cuCall).toBeDefined();
695
- expect(cuCall?.sourceActorPrincipalId).toBe("test-user");
696
- expect(cuCall?.sourceActorPrincipalId).not.toBe("dev-bypass");
697
-
698
- // Preactivation receives the same translated principal.
699
- const preactivateCall = preactivateCalls[0];
700
- expect(preactivateCall?.sourceActorPrincipalId).toBe("test-user");
701
- });
702
-
703
- test("real (non-dev-bypass) principal passes through the CU proxy attach gate unchanged", async () => {
704
- hostProxyAttachCalls.length = 0;
705
- const conversation = makeConversation();
706
- await callHandler(
707
- (args) =>
708
- handleSendMessage(args, {
709
- sendMessageDeps: {
710
- getOrCreateConversation: async () => conversation,
711
- assistantEventHub: { publish: async () => {} } as any,
712
- resolveAttachments: () => [],
713
- },
714
- }),
715
- new Request("http://localhost/v1/messages", {
716
- method: "POST",
717
- headers: {
718
- "Content-Type": "application/json",
719
- "x-vellum-actor-principal-id": "real-jwt-principal",
720
- "x-vellum-principal-type": "actor",
721
- },
722
- body: JSON.stringify({
723
- conversationKey: "cu-attach-real-key",
724
- content: "hi",
725
- sourceChannel: "vellum",
726
- interface: "web",
727
- }),
728
- }),
729
- undefined,
730
- 202,
731
- );
732
-
733
- const cuCall = hostProxyAttachCalls.find(
734
- (c) => c.capability === "host_cu",
735
- );
736
- expect(cuCall?.sourceActorPrincipalId).toBe("real-jwt-principal");
737
- });
738
- });
@@ -64,28 +64,6 @@ mock.module("../runtime/approval-message-composer.js", () => ({
64
64
  composeApprovalMessageGenerative: async () => "mock generative message",
65
65
  }));
66
66
 
67
- // Stub the gateway IPC so redemption claims + activation relays resolve
68
- // deterministically without a running gateway socket.
69
- const gatewayIpcCalls: Array<{
70
- method: string;
71
- params?: Record<string, unknown>;
72
- }> = [];
73
- mock.module("../ipc/gateway-client.js", () => ({
74
- ipcCallPersistent: async (
75
- method: string,
76
- params?: Record<string, unknown>,
77
- ) => {
78
- gatewayIpcCalls.push({ method, params });
79
- if (method === "record_invite_redemption") {
80
- return { ok: true, updated: true, mirrored: true };
81
- }
82
- if (method === "upsert_verified_channel") {
83
- return { ok: true, verified: true };
84
- }
85
- return undefined;
86
- },
87
- }));
88
-
89
67
  import {
90
68
  findContactChannel,
91
69
  upsertContact,
@@ -120,7 +98,6 @@ function resetState(): void {
120
98
  db.run("DELETE FROM contacts");
121
99
  emitSignalCalls.length = 0;
122
100
  deliverReplyCalls.length = 0;
123
- gatewayIpcCalls.length = 0;
124
101
  msgCounter = 0;
125
102
  }
126
103
 
@@ -200,11 +177,6 @@ describe("inbound invite redemption intercept", () => {
200
177
  expect(result).not.toBeNull();
201
178
  expect(result!.channel.status).toBe("active");
202
179
 
203
- // The activation is written to the gateway via upsert_verified_channel.
204
- expect(
205
- gatewayIpcCalls.some((c) => c.method === "upsert_verified_channel"),
206
- ).toBe(true);
207
-
208
180
  // Verify a welcome reply was delivered
209
181
  expect(deliverReplyCalls.length).toBe(1);
210
182
  const replyText = (deliverReplyCalls[0].payload as Record<string, unknown>)
@@ -35,8 +35,6 @@ const addMessageCalls: Array<{
35
35
  }> = [];
36
36
 
37
37
  mock.module("../memory/conversation-crud.js", () => ({
38
- setConversationProcessingStartedAt: () => {},
39
- isConversationProcessing: () => false,
40
38
  addMessage: async (
41
39
  conversationId: string,
42
40
  role: string,
@@ -7,26 +7,6 @@ mock.module("../util/logger.js", () => ({
7
7
  }),
8
8
  }));
9
9
 
10
- // Wrap the real contacts-write so a test can force the best-effort local mirror
11
- // to fail (simulating a gateway-verified activation whose local DB row failed),
12
- // while normal setup keeps the real implementation. Capture the concrete real
13
- // function BEFORE registering the mock so the wrapper never recurses into
14
- // itself via the (now live) module namespace.
15
- const contactsWriteState = { mirrorThrows: false };
16
- const realContactsWrite = await import("../contacts/contacts-write.js");
17
- const realUpsertContactChannel = realContactsWrite.upsertContactChannel;
18
- mock.module("../contacts/contacts-write.js", () => ({
19
- ...realContactsWrite,
20
- upsertContactChannel: (
21
- params: Parameters<typeof realUpsertContactChannel>[0],
22
- ) => {
23
- if (contactsWriteState.mirrorThrows) {
24
- throw new Error("local mirror exploded");
25
- }
26
- return realUpsertContactChannel(params);
27
- },
28
- }));
29
-
30
10
  // Mock the gateway IPC bridge used by the redemption service for the
31
11
  // authoritative pre-mutation claim (record_invite_redemption). Tests drive the
32
12
  // claim result via `gatewayIpc`.
@@ -37,12 +17,6 @@ const gatewayIpc = {
37
17
  mirrored: boolean;
38
18
  },
39
19
  claimThrows: false,
40
- // Drives the upsert_verified_channel relay verdict. When false the gateway
41
- // refuses the actor (blocked/revoked) and the activation is refused.
42
- activationVerified: true,
43
- // Gateway channel returned on a verified activation, surfaced as the memberId
44
- // when the local mirror produces no row.
45
- activationChannelId: "gw-channel-id" as string | undefined,
46
20
  calls: [] as { method: string; params?: Record<string, unknown> }[],
47
21
  };
48
22
 
@@ -54,49 +28,18 @@ mock.module("../ipc/gateway-client.js", () => ({
54
28
  gatewayIpc.calls.push({ method, params });
55
29
  if (method === "record_invite_redemption") {
56
30
  if (gatewayIpc.claimThrows) throw new Error("gateway unreachable");
57
- onGatewayClaim?.();
58
31
  return gatewayIpc.claim;
59
32
  }
60
- if (method === "upsert_verified_channel") {
61
- if (!gatewayIpc.activationVerified) {
62
- return { ok: true, verified: false };
63
- }
64
- return {
65
- ok: true,
66
- verified: true,
67
- channel: gatewayIpc.activationChannelId
68
- ? {
69
- id: gatewayIpc.activationChannelId,
70
- contactId: (params?.contactId as string) ?? "gw-contact",
71
- type: (params?.type as string) ?? "telegram",
72
- address: (params?.address as string) ?? "gw-addr",
73
- status: "active",
74
- verifiedAt: 1,
75
- verifiedVia: (params?.verifiedVia as string) ?? "invite",
76
- }
77
- : undefined,
78
- };
79
- }
80
33
  return undefined;
81
34
  },
82
35
  }));
83
36
 
84
- // Lets a test inject a side-effect into the gateway claim — runs after the
85
- // service's pre-validation but before the assistant use-bump, so it can race a
86
- // revoke into the window that makes `recordInviteUse` return false.
87
- let onGatewayClaim: (() => void) | null = null;
88
-
89
37
  function resetGatewayIpc() {
90
38
  gatewayIpc.claim = { ok: true, updated: true, mirrored: true };
91
39
  gatewayIpc.claimThrows = false;
92
- gatewayIpc.activationVerified = true;
93
- gatewayIpc.activationChannelId = "gw-channel-id";
94
40
  gatewayIpc.calls = [];
95
- onGatewayClaim = null;
96
41
  }
97
42
 
98
- import type { TrustVerdict } from "@vellumai/gateway-client";
99
-
100
43
  import {
101
44
  findContactChannel,
102
45
  getContact,
@@ -113,7 +56,6 @@ import {
113
56
  type InviteRedemptionOutcome,
114
57
  redeemInvite,
115
58
  redeemInviteByCode,
116
- resolveMemberGateStatus,
117
59
  } from "../runtime/invite-redemption-service.js";
118
60
  import { hashVoiceCode } from "../util/voice-code.js";
119
61
 
@@ -134,7 +76,6 @@ describe("invite-redemption-service", () => {
134
76
  beforeEach(() => {
135
77
  resetTables();
136
78
  resetGatewayIpc();
137
- contactsWriteState.mirrorThrows = false;
138
79
  });
139
80
 
140
81
  test("redeems a valid invite and returns typed outcome", async () => {
@@ -158,11 +99,6 @@ describe("invite-redemption-service", () => {
158
99
  memberId: expect.any(String),
159
100
  inviteId: invite.id,
160
101
  });
161
-
162
- // The activation is written to the gateway via upsert_verified_channel.
163
- expect(
164
- gatewayIpc.calls.some((c) => c.method === "upsert_verified_channel"),
165
- ).toBe(true);
166
102
  });
167
103
 
168
104
  test("marks channel as verified via invite on redemption", async () => {
@@ -421,18 +357,6 @@ describe("invite-redemption-service", () => {
421
357
  expect(outcome.ok).toBe(true);
422
358
  expect((outcome as { type: string }).type).toBe("redeemed");
423
359
 
424
- // Gateway-first: the activation relays the target contactId so the gateway
425
- // binds the channel to Mom (not the guardian) — the binding is not lost.
426
- const upsert = gatewayIpc.calls.find(
427
- (c) => c.method === "upsert_verified_channel",
428
- );
429
- expect(upsert).toBeDefined();
430
- expect(upsert!.params).toMatchObject({
431
- type: "telegram",
432
- address: "guardian-tg-id",
433
- contactId: momContact.id,
434
- });
435
-
436
360
  // Verify the redeemer's Telegram ID is now bound to Mom's contact
437
361
  const result = findContactChannel({
438
362
  channelType: "telegram",
@@ -704,39 +628,6 @@ describe("invite-redemption-service", () => {
704
628
  ).toBeNull();
705
629
  });
706
630
 
707
- test("does not activate the member when recordInviteUse loses the race (returns false)", async () => {
708
- const targetContactId = createTargetContact();
709
- const { rawToken, invite } = createInvite({
710
- sourceChannel: "telegram",
711
- contactId: targetContactId,
712
- maxUses: 1,
713
- });
714
-
715
- // Legacy gateway row so the claim proceeds past the gateway gate. Revoke
716
- // the assistant invite during the claim — after pre-validation, before the
717
- // use-bump — so `recordInviteUse` sees a non-active row and returns false.
718
- gatewayIpc.claim = { ok: true, updated: false, mirrored: false };
719
- onGatewayClaim = () => {
720
- revokeStoreFn(invite.id);
721
- };
722
-
723
- const outcome = await redeemInvite({
724
- rawToken,
725
- sourceChannel: "telegram",
726
- externalUserId: "raced-user",
727
- });
728
-
729
- expect(outcome).toEqual({ ok: false, reason: "invalid_token" });
730
-
731
- // The member was NOT activated: no gateway upsert and no active channel.
732
- expect(
733
- gatewayIpc.calls.some((c) => c.method === "upsert_verified_channel"),
734
- ).toBe(false);
735
- expect(
736
- findContactChannel({ channelType: "telegram", address: "raced-user" }),
737
- ).toBeNull();
738
- });
739
-
740
631
  test("proceeds and mutates when the gateway claim is consumed (updated:true)", async () => {
741
632
  const targetContactId = createTargetContact();
742
633
  const { rawToken, invite } = createInvite({
@@ -871,93 +762,4 @@ describe("invite-redemption-service", () => {
871
762
  }),
872
763
  ).toBeNull();
873
764
  });
874
-
875
- test("returns invalid_token (no throw) when the gateway refuses the activation", async () => {
876
- const targetContactId = createTargetContact();
877
- const { rawToken } = createInvite({
878
- sourceChannel: "telegram",
879
- contactId: targetContactId,
880
- maxUses: 1,
881
- });
882
-
883
- // Gateway claim consumes the row, then refuses the channel activation
884
- // (blocked/revoked actor). The committed use is acceptable for this rare
885
- // blocked-backstop path; the outcome must be the branch failure, not a 500.
886
- gatewayIpc.activationVerified = false;
887
-
888
- const outcome = await redeemInvite({
889
- rawToken,
890
- sourceChannel: "telegram",
891
- externalUserId: "refused-user",
892
- });
893
-
894
- expect(outcome).toEqual({ ok: false, reason: "invalid_token" });
895
- });
896
-
897
- test("redeems with the gateway channel id when the gateway verifies but the local mirror fails", async () => {
898
- const targetContactId = createTargetContact();
899
- const { rawToken, invite } = createInvite({
900
- sourceChannel: "telegram",
901
- contactId: targetContactId,
902
- maxUses: 1,
903
- });
904
-
905
- // Gateway verifies and returns its channel; the best-effort local mirror
906
- // throws. The activation must still stand using the gateway channel id.
907
- gatewayIpc.activationChannelId = "gw-verified-channel";
908
- contactsWriteState.mirrorThrows = true;
909
-
910
- const outcome = await redeemInvite({
911
- rawToken,
912
- sourceChannel: "telegram",
913
- externalUserId: "mirrorless-user",
914
- });
915
-
916
- expect(outcome).toEqual({
917
- ok: true,
918
- type: "redeemed",
919
- memberId: "gw-verified-channel",
920
- inviteId: invite.id,
921
- });
922
- });
923
- });
924
-
925
- describe("resolveMemberGateStatus", () => {
926
- const memberlessVerdict: TrustVerdict = {
927
- trustClass: "unverified_contact",
928
- canonicalSenderId: "telegram:blocked-user",
929
- };
930
- const memberVerdict: TrustVerdict = {
931
- trustClass: "trusted_contact",
932
- canonicalSenderId: "telegram:active-user",
933
- contactId: "contact-1",
934
- channelId: "channel-1",
935
- type: "telegram",
936
- address: "active-user",
937
- status: "active",
938
- policy: "allow",
939
- };
940
-
941
- test("uses the verdict member status when the verdict resolves a member", async () => {
942
- expect(await resolveMemberGateStatus(memberVerdict, "blocked")).toBe(
943
- "active",
944
- );
945
- });
946
-
947
- test("falls back to local status when a non-null verdict carries no member", async () => {
948
- // A previously blocked contact with a valid invite must stay blocked even
949
- // when the verdict is non-null but memberless (externalChatId-only match /
950
- // resolutionFailed), so it can't bypass the gate.
951
- expect(await resolveMemberGateStatus(memberlessVerdict, "blocked")).toBe(
952
- "blocked",
953
- );
954
- });
955
-
956
- test("falls back to local status when the verdict is null", async () => {
957
- expect(await resolveMemberGateStatus(null, "blocked")).toBe("blocked");
958
- });
959
-
960
- test("returns null when neither verdict member nor local status is present", async () => {
961
- expect(await resolveMemberGateStatus(memberlessVerdict, null)).toBeNull();
962
- });
963
765
  });