@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
@@ -2,7 +2,6 @@ import { describe, expect, test } from "bun:test";
2
2
 
3
3
  import type { TrustVerdict } from "@vellumai/gateway-client";
4
4
 
5
- import { channelStatusToMemberStatus } from "../../contacts/member-status.js";
6
5
  import type {
7
6
  ContactChannel,
8
7
  ContactWithChannels,
@@ -10,12 +9,8 @@ import type {
10
9
  import type { ActorTrustContext } from "../actor-trust-resolver.js";
11
10
  import { toTrustContext } from "../actor-trust-resolver.js";
12
11
  import {
13
- actorTrustContextFromVerdict,
14
12
  resolvedMemberFromVerdict,
15
13
  trustContextFromVerdict,
16
- verdictHasMemberIdentity,
17
- verdictMemberFromVerdict,
18
- verdictMemberUnresolvable,
19
14
  } from "../trust-verdict-consumer.js";
20
15
 
21
16
  const CONV = "conv-123";
@@ -168,195 +163,6 @@ describe("trustContextFromVerdict", () => {
168
163
  });
169
164
  });
170
165
 
171
- describe("actorTrustContextFromVerdict", () => {
172
- test("maps guardian verdict fields", () => {
173
- const verdict = {
174
- trustClass: "guardian",
175
- canonicalSenderId: "+15550100",
176
- guardianExternalUserId: "+15550100",
177
- guardianDeliveryChatId: "chat-9",
178
- guardianPrincipalId: "vellum-principal-abc",
179
- memberDisplayName: "Alice",
180
- } satisfies TrustVerdict;
181
-
182
- const ctx = actorTrustContextFromVerdict(verdict, {
183
- sourceChannel: "phone",
184
- conversationExternalId: CONV,
185
- actorUsername: "alice",
186
- actorDisplayName: "Alice Sender",
187
- });
188
-
189
- expect(ctx).toEqual({
190
- canonicalSenderId: "+15550100",
191
- guardianBindingMatch: {
192
- guardianExternalUserId: "+15550100",
193
- guardianDeliveryChatId: "chat-9",
194
- },
195
- guardianPrincipalId: "vellum-principal-abc",
196
- memberRecord: null,
197
- trustClass: "guardian",
198
- actorMetadata: {
199
- identifier: "@alice",
200
- displayName: "Alice",
201
- senderDisplayName: "Alice Sender",
202
- memberDisplayName: "Alice",
203
- username: "alice",
204
- channel: "phone",
205
- trustStatus: "guardian",
206
- },
207
- });
208
- });
209
-
210
- test("guardianBindingMatch is null without guardianExternalUserId", () => {
211
- const verdict = {
212
- trustClass: "trusted_contact",
213
- canonicalSenderId: "+15550101",
214
- memberDisplayName: "Bob",
215
- } satisfies TrustVerdict;
216
-
217
- const ctx = actorTrustContextFromVerdict(verdict, {
218
- sourceChannel: "phone",
219
- conversationExternalId: CONV,
220
- });
221
-
222
- expect(ctx.guardianBindingMatch).toBeNull();
223
- expect(ctx.trustClass).toBe("trusted_contact");
224
- // identifier falls back to canonicalSenderId when no username.
225
- expect(ctx.actorMetadata.identifier).toBe("+15550101");
226
- // displayName uses memberDisplayName when present.
227
- expect(ctx.actorMetadata.displayName).toBe("Bob");
228
- expect(ctx.actorMetadata.channel).toBe("phone");
229
- expect(ctx.memberRecord).toBeNull();
230
- });
231
-
232
- test("displayName falls back to actorDisplayName; identifier uses @username", () => {
233
- const verdict = {
234
- trustClass: "unverified_contact",
235
- canonicalSenderId: "u-1",
236
- } satisfies TrustVerdict;
237
-
238
- const ctx = actorTrustContextFromVerdict(verdict, {
239
- sourceChannel: "slack",
240
- conversationExternalId: CONV,
241
- actorUsername: "carol",
242
- actorDisplayName: "Carol Display",
243
- });
244
-
245
- expect(ctx.trustClass).toBe("unverified_contact");
246
- expect(ctx.actorMetadata.identifier).toBe("@carol");
247
- expect(ctx.actorMetadata.displayName).toBe("Carol Display");
248
- expect(ctx.actorMetadata.memberDisplayName).toBeUndefined();
249
- expect(ctx.actorMetadata.trustStatus).toBe("unverified_contact");
250
- });
251
-
252
- test("maps unknown verdict with no identity overrides", () => {
253
- const verdict = {
254
- trustClass: "unknown",
255
- canonicalSenderId: "u-2",
256
- } satisfies TrustVerdict;
257
-
258
- const ctx = actorTrustContextFromVerdict(verdict, {
259
- sourceChannel: "slack",
260
- conversationExternalId: CONV,
261
- });
262
-
263
- expect(ctx.trustClass).toBe("unknown");
264
- expect(ctx.guardianBindingMatch).toBeNull();
265
- expect(ctx.guardianPrincipalId).toBeUndefined();
266
- expect(ctx.memberRecord).toBeNull();
267
- expect(ctx.actorMetadata.identifier).toBe("u-2");
268
- expect(ctx.actorMetadata.displayName).toBeUndefined();
269
- });
270
-
271
- test("member verdict populates memberRecord from the verdict (voice ACL)", () => {
272
- const verdict = {
273
- trustClass: "trusted_contact",
274
- canonicalSenderId: "u-1",
275
- contactId: "contact-1",
276
- channelId: "channel-1",
277
- type: "slack",
278
- address: "u-1",
279
- status: "blocked",
280
- policy: "deny",
281
- } satisfies TrustVerdict;
282
-
283
- const ctx = actorTrustContextFromVerdict(verdict, {
284
- sourceChannel: "slack",
285
- conversationExternalId: CONV,
286
- });
287
-
288
- expect(ctx.memberRecord).not.toBeNull();
289
- expect(ctx.memberRecord!.contact.id).toBe("contact-1");
290
- expect(ctx.memberRecord!.channel.id).toBe("channel-1");
291
- expect(ctx.memberRecord!.channel.status).toBe("blocked");
292
- expect(ctx.memberRecord!.channel.policy).toBe("deny");
293
- });
294
-
295
- test("stranger verdict (no contactId/channelId) leaves memberRecord null", () => {
296
- const verdict = {
297
- trustClass: "unknown",
298
- canonicalSenderId: "u-9",
299
- } satisfies TrustVerdict;
300
-
301
- const ctx = actorTrustContextFromVerdict(verdict, {
302
- sourceChannel: "slack",
303
- conversationExternalId: CONV,
304
- });
305
-
306
- expect(ctx.memberRecord).toBeNull();
307
- });
308
-
309
- test("malformed member verdict (unknown status) leaves memberRecord null (fail-closed)", () => {
310
- const verdict = {
311
- trustClass: "trusted_contact",
312
- canonicalSenderId: "u-10",
313
- contactId: "contact-10",
314
- channelId: "channel-10",
315
- status: "quarantined",
316
- policy: "allow",
317
- } satisfies TrustVerdict;
318
-
319
- const ctx = actorTrustContextFromVerdict(verdict, {
320
- sourceChannel: "slack",
321
- conversationExternalId: CONV,
322
- });
323
-
324
- expect(ctx.memberRecord).toBeNull();
325
- });
326
-
327
- test("trustContextFromVerdict equals member stamp applied to toTrustContext(actorTrustContextFromVerdict)", () => {
328
- const verdict = {
329
- trustClass: "trusted_contact",
330
- canonicalSenderId: "u-1",
331
- contactId: "contact-1",
332
- channelId: "channel-1",
333
- type: "slack",
334
- address: "u-1",
335
- status: "unverified",
336
- policy: "escalate",
337
- memberDisplayName: "Dora",
338
- } satisfies TrustVerdict;
339
- const input = {
340
- sourceChannel: "slack",
341
- conversationExternalId: CONV,
342
- actorUsername: "dora",
343
- actorDisplayName: "Dora Display",
344
- } as const;
345
-
346
- const expected = toTrustContext(
347
- actorTrustContextFromVerdict(verdict, input),
348
- input.conversationExternalId,
349
- );
350
- const member = resolvedMemberFromVerdict(verdict);
351
- expect(member).not.toBeNull();
352
- expected.requesterContactId = member!.contact.id;
353
- expected.memberStatus = channelStatusToMemberStatus(member!.channel.status);
354
- expected.memberPolicy = member!.channel.policy;
355
-
356
- expect(trustContextFromVerdict(verdict, input)).toEqual(expected);
357
- });
358
- });
359
-
360
166
  describe("toTrustContext member grounding", () => {
361
167
  function memberChannel(
362
168
  overrides: Partial<ContactChannel> = {},
@@ -401,7 +207,9 @@ describe("toTrustContext member grounding", () => {
401
207
  };
402
208
  }
403
209
 
404
- function ctxWithMember(channel: ContactChannel): ActorTrustContext {
210
+ function ctxWithMember(
211
+ channel: ContactChannel,
212
+ ): ActorTrustContext {
405
213
  return {
406
214
  canonicalSenderId: "+15550100",
407
215
  guardianBindingMatch: null,
@@ -607,143 +415,3 @@ describe("resolvedMemberFromVerdict", () => {
607
415
  }
608
416
  });
609
417
  });
610
-
611
- describe("verdictMemberFromVerdict", () => {
612
- test("active member verdict yields the narrow ACL view", () => {
613
- const verdict = {
614
- trustClass: "trusted_contact",
615
- canonicalSenderId: "u-1",
616
- contactId: "contact-1",
617
- channelId: "channel-1",
618
- type: "slack",
619
- address: "u-1",
620
- status: "active",
621
- policy: "allow",
622
- verifiedAt: 1700000000,
623
- memberDisplayName: "Dora",
624
- } satisfies TrustVerdict;
625
-
626
- expect(verdictMemberFromVerdict(verdict)).toEqual({
627
- contactId: "contact-1",
628
- channelId: "channel-1",
629
- status: "active",
630
- policy: "allow",
631
- verifiedAt: 1700000000,
632
- displayName: "Dora",
633
- });
634
- });
635
-
636
- test("blocked member verdict surfaces status/policy verbatim, null defaults", () => {
637
- const verdict = {
638
- trustClass: "unknown",
639
- canonicalSenderId: "u-3",
640
- contactId: "contact-3",
641
- channelId: "channel-3",
642
- status: "blocked",
643
- policy: "deny",
644
- } satisfies TrustVerdict;
645
-
646
- expect(verdictMemberFromVerdict(verdict)).toEqual({
647
- contactId: "contact-3",
648
- channelId: "channel-3",
649
- status: "blocked",
650
- policy: "deny",
651
- verifiedAt: null,
652
- displayName: null,
653
- });
654
- });
655
-
656
- test("memberless verdict (no contactId/channelId) returns null", () => {
657
- expect(
658
- verdictMemberFromVerdict({
659
- trustClass: "unknown",
660
- canonicalSenderId: "u-2",
661
- } satisfies TrustVerdict),
662
- ).toBeNull();
663
- });
664
-
665
- test("invalid enum (unknown status/policy) returns null (fail-closed)", () => {
666
- expect(
667
- verdictMemberFromVerdict({
668
- trustClass: "trusted_contact",
669
- canonicalSenderId: "u-7",
670
- contactId: "contact-7",
671
- channelId: "channel-7",
672
- status: "quarantined",
673
- policy: "allow",
674
- } satisfies TrustVerdict),
675
- ).toBeNull();
676
- expect(
677
- verdictMemberFromVerdict({
678
- trustClass: "trusted_contact",
679
- canonicalSenderId: "u-6",
680
- contactId: "contact-6",
681
- channelId: "channel-6",
682
- status: "active",
683
- policy: "bogus",
684
- } satisfies TrustVerdict),
685
- ).toBeNull();
686
- });
687
- });
688
-
689
- describe("verdict predicates", () => {
690
- test("verdictHasMemberIdentity is true with contactId or channelId", () => {
691
- expect(
692
- verdictHasMemberIdentity({
693
- trustClass: "unknown",
694
- canonicalSenderId: "u-1",
695
- contactId: "contact-1",
696
- } satisfies TrustVerdict),
697
- ).toBe(true);
698
- expect(
699
- verdictHasMemberIdentity({
700
- trustClass: "unknown",
701
- canonicalSenderId: "u-1",
702
- channelId: "channel-1",
703
- } satisfies TrustVerdict),
704
- ).toBe(true);
705
- });
706
-
707
- test("verdictHasMemberIdentity is false for a memberless verdict", () => {
708
- expect(
709
- verdictHasMemberIdentity({
710
- trustClass: "unknown",
711
- canonicalSenderId: "u-1",
712
- } satisfies TrustVerdict),
713
- ).toBe(false);
714
- });
715
-
716
- test("verdictMemberUnresolvable is true when member identity present but ACL unsynthesizable", () => {
717
- expect(
718
- verdictMemberUnresolvable({
719
- trustClass: "trusted_contact",
720
- canonicalSenderId: "u-1",
721
- contactId: "contact-1",
722
- channelId: "channel-1",
723
- policy: "allow",
724
- } satisfies TrustVerdict),
725
- ).toBe(true);
726
- });
727
-
728
- test("verdictMemberUnresolvable is false for a usable member verdict", () => {
729
- expect(
730
- verdictMemberUnresolvable({
731
- trustClass: "trusted_contact",
732
- canonicalSenderId: "u-1",
733
- contactId: "contact-1",
734
- channelId: "channel-1",
735
- status: "active",
736
- policy: "allow",
737
- } satisfies TrustVerdict),
738
- ).toBe(false);
739
- });
740
-
741
- test("verdictMemberUnresolvable is false for a memberless verdict", () => {
742
- expect(
743
- verdictMemberUnresolvable({
744
- trustClass: "unknown",
745
- canonicalSenderId: "u-1",
746
- } satisfies TrustVerdict),
747
- ).toBe(false);
748
- });
749
- });
@@ -12,7 +12,7 @@
12
12
  */
13
13
 
14
14
  import type { ChannelId } from "../channels/types.js";
15
- import { getGuardianDelivery } from "../contacts/guardian-delivery-reader.js";
15
+ import { findGuardianForChannel } from "../contacts/contact-store.js";
16
16
  import type { ChannelStatus } from "../contacts/types.js";
17
17
  import {
18
18
  createCanonicalGuardianRequest,
@@ -25,7 +25,6 @@ import {
25
25
  import { emitNotificationSignal } from "../notifications/emit-signal.js";
26
26
  import type { GuardianResolutionSource } from "../notifications/signal.js";
27
27
  import { getLogger } from "../util/logger.js";
28
- import { resolveAnchoredGuardian } from "./anchored-guardian.js";
29
28
  import { GUARDIAN_APPROVAL_TTL_MS } from "./routes/channel-route-shared.js";
30
29
 
31
30
  const log = getLogger("access-request-helper");
@@ -71,12 +70,12 @@ export type AccessRequestResult =
71
70
  * trust anchor and only accepts source-channel contacts that match it. This
72
71
  * prevents stale or cross-assistant contacts from being bound to the request.
73
72
  *
74
- * The canonical store writes complete before this resolves; the notification
75
- * signal emission is fire-and-forget.
73
+ * This is intentionally synchronous with respect to the canonical store writes
74
+ * and fire-and-forget for the notification signal emission.
76
75
  */
77
- export async function notifyGuardianOfAccessRequest(
76
+ export function notifyGuardianOfAccessRequest(
78
77
  params: AccessRequestParams,
79
- ): Promise<AccessRequestResult> {
78
+ ): AccessRequestResult {
80
79
  const {
81
80
  canonicalAssistantId,
82
81
  sourceChannel,
@@ -95,19 +94,40 @@ export async function notifyGuardianOfAccessRequest(
95
94
  return { notified: false, reason: "no_sender_id" };
96
95
  }
97
96
 
98
- // Resolve guardian identity with the assistant-anchored strategy (gateway
99
- // source-channel match validated against the vellum anchor, else the vellum
100
- // anchor), with a LOCAL-store fallback when the gateway read is empty.
101
- const anchored = resolveAnchoredGuardian({
102
- guardians: await getGuardianDelivery(),
103
- sourceChannel,
104
- useLocalFallback: true,
105
- });
106
- const guardianExternalUserId = anchored?.address ?? null;
107
- const guardianPrincipalId = anchored?.principalId ?? null;
108
- const guardianBindingChannel = anchored?.channelType ?? null;
109
- const guardianResolutionSource: GuardianResolutionSource =
110
- anchored?.source ?? "none";
97
+ // Resolve guardian identity with assistant-anchored strategy:
98
+ // 1. Ensure the assistant has a vellum guardian principal (trust anchor)
99
+ // 2. Use source-channel guardian only when principal matches anchor
100
+ // 3. Fallback to vellum guardian identity for this assistant principal
101
+ let guardianExternalUserId: string | null = null;
102
+ let guardianPrincipalId: string | null = null;
103
+ let guardianBindingChannel: string | null = null;
104
+ let guardianResolutionSource: GuardianResolutionSource = "none";
105
+
106
+ const vellumGuardian = findGuardianForChannel("vellum");
107
+ const assistantGuardianPrincipalId = vellumGuardian?.contact.principalId;
108
+
109
+ // Try source-channel guardian, but only if it maps to the assistant's
110
+ // anchored principal. This blocks cross-assistant/stale contact selection.
111
+ const sourceGuardian = findGuardianForChannel(sourceChannel);
112
+ if (
113
+ assistantGuardianPrincipalId &&
114
+ sourceGuardian &&
115
+ sourceGuardian.contact.principalId === assistantGuardianPrincipalId
116
+ ) {
117
+ guardianExternalUserId = sourceGuardian.channel.address;
118
+ guardianPrincipalId = sourceGuardian.contact.principalId;
119
+ guardianBindingChannel = sourceGuardian.channel.type;
120
+ guardianResolutionSource = "source-channel-contact";
121
+ }
122
+
123
+ // Access requests always require a principal. If source-channel resolution
124
+ // did not match the assistant anchor, use the anchored vellum identity.
125
+ if (!guardianPrincipalId && vellumGuardian) {
126
+ guardianExternalUserId = vellumGuardian.channel.address;
127
+ guardianPrincipalId = assistantGuardianPrincipalId ?? null;
128
+ guardianBindingChannel = guardianBindingChannel ?? "vellum";
129
+ guardianResolutionSource = "vellum-anchor";
130
+ }
111
131
 
112
132
  log.debug(
113
133
  {
@@ -323,8 +323,8 @@ export function toTrustContext(
323
323
  requesterMemberDisplayName: ctx.actorMetadata.memberDisplayName,
324
324
  requesterExternalUserId: ctx.canonicalSenderId ?? undefined,
325
325
  requesterChatId: conversationExternalId,
326
- // Member grounding from the resolved memberRecord (voice + verdict paths
327
- // both populate it).
326
+ // Member grounding from a real memberRecord (voice path); the verdict path
327
+ // (memberRecord=null) stamps these from the verdict instead.
328
328
  requesterContactId: ctx.memberRecord?.contact.id,
329
329
  memberStatus: ctx.memberRecord
330
330
  ? channelStatusToMemberStatus(ctx.memberRecord.channel.status)
@@ -749,7 +749,7 @@ async function createCanonicalRequestForConfirmation(
749
749
  });
750
750
 
751
751
  if (trustContext && conversation) {
752
- await bridgeConfirmationRequestToGuardian({
752
+ bridgeConfirmationRequestToGuardian({
753
753
  canonicalRequest,
754
754
  trustContext,
755
755
  conversationId,
@@ -50,21 +50,14 @@
50
50
  import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
51
51
  import { dirname, join } from "node:path";
52
52
 
53
- import {
54
- SSE_REPLAY_RING_AGE_LIMIT_MS,
55
- SSE_REPLAY_RING_COUNT_LIMIT,
56
- } from "../api/constants/sse-replay.js";
57
53
  import { getWorkspaceDir } from "../util/platform.js";
58
54
  import type { AssistantEvent } from "./assistant-event.js";
59
55
 
60
56
  // ── Tunables ─────────────────────────────────────────────────────────
61
57
 
62
- // Count and age bounds on the replay ring. Shared with the web client
63
- // (via `@vellumai/assistant-api`) so its seq-gap tolerance is sized
64
- // against the same numbers the daemon buffers against.
65
- const RING_COUNT_LIMIT = SSE_REPLAY_RING_COUNT_LIMIT;
58
+ const RING_COUNT_LIMIT = 200;
66
59
  const RING_SIZE_LIMIT_BYTES = 256 * 1024;
67
- const RING_AGE_LIMIT_MS = SSE_REPLAY_RING_AGE_LIMIT_MS;
60
+ const RING_AGE_LIMIT_MS = 30_000;
68
61
 
69
62
  /**
70
63
  * Cap on how many conversations retain a persisted-seq entry. Unlike the
@@ -1,20 +1,15 @@
1
1
  import { isHttpAuthDisabled } from "../../config/env.js";
2
- import {
3
- getGuardianDelivery,
4
- guardianForChannel,
5
- } from "../../contacts/guardian-delivery-reader.js";
2
+ import { findGuardianForChannel } from "../../contacts/contact-store.js";
6
3
  import { httpError } from "../http-errors.js";
7
4
  import type { AuthContext } from "./types.js";
8
5
 
9
6
  /**
10
7
  * Verify the actor from AuthContext is the bound guardian for the vellum channel.
11
- * Sources the guardian from the gateway binding and fails closed when the
12
- * gateway is unreachable (null list). Returns an error Response if not
13
- * authorized, or null if allowed.
8
+ * Returns an error Response if not, or null if allowed.
14
9
  */
15
- export async function requireBoundGuardian(
10
+ export function requireBoundGuardian(
16
11
  authContext: AuthContext,
17
- ): Promise<Response | null> {
12
+ ): Response | null {
18
13
  // Dev bypass: when auth is disabled, skip guardian binding check
19
14
  // (mirrors enforcePolicy dev bypass in route-policy.ts)
20
15
  if (isHttpAuthDisabled()) {
@@ -27,22 +22,17 @@ export async function requireBoundGuardian(
27
22
  403,
28
23
  );
29
24
  }
30
- const guardians = await getGuardianDelivery({ channelTypes: ["vellum"] });
31
- if (!guardians) {
32
- // Gateway unreachablefail closed.
25
+ const guardianResult = findGuardianForChannel("vellum");
26
+ if (!guardianResult) {
27
+ // No guardian yet in pre-bootstrap state, allow through
28
+ return null;
29
+ }
30
+ if (guardianResult.channel.address !== authContext.actorPrincipalId) {
33
31
  return httpError(
34
32
  "FORBIDDEN",
35
33
  "Actor is not the bound guardian for this channel",
36
34
  403,
37
35
  );
38
36
  }
39
- const guardian = guardianForChannel(guardians, "vellum");
40
- if (guardian && guardian.principalId === authContext.actorPrincipalId) {
41
- return null;
42
- }
43
- return httpError(
44
- "FORBIDDEN",
45
- "Actor is not the bound guardian for this channel",
46
- 403,
47
- );
37
+ return null;
48
38
  }
@@ -9,12 +9,8 @@
9
9
  import { createHash, randomBytes } from "crypto";
10
10
  import { v4 as uuid } from "uuid";
11
11
 
12
+ import { findGuardianForChannel } from "../contacts/contact-store.js";
12
13
  import { revokeGuardianBinding } from "../contacts/contacts-write.js";
13
- import {
14
- getGuardianDelivery,
15
- getGuardianDeliveryFresh,
16
- guardianForChannel,
17
- } from "../contacts/guardian-delivery-reader.js";
18
14
  import type {
19
15
  GuardianBinding,
20
16
  IdentityBindingStatus,
@@ -323,71 +319,50 @@ export function validateAndConsumeVerification(
323
319
 
324
320
  /**
325
321
  * Look up the active guardian binding for a given assistant and channel.
326
- * Reads the gateway-owned GuardianDelivery and synthesizes a
327
- * GuardianBinding-shaped object. Returns null when no guardian is bound or
328
- * the gateway is unreachable.
322
+ * Reads from the contacts table via findGuardianForChannel and
323
+ * synthesizes a GuardianBinding-shaped object.
324
+ * Returns null when no contacts match.
329
325
  */
330
- export async function getGuardianBinding(
326
+ export function getGuardianBinding(
331
327
  assistantId: string,
332
328
  channel: string,
333
- ): Promise<GuardianBinding | null> {
334
- const list = await getGuardianDelivery({ channelTypes: [channel] });
335
- const delivery = list ? guardianForChannel(list, channel) : undefined;
336
- if (!delivery) return null;
337
-
338
- const now = Date.now();
339
- return {
340
- id: delivery.contactId,
341
- assistantId,
342
- channel,
343
- guardianExternalUserId: delivery.address,
344
- guardianDeliveryChatId: delivery.externalChatId ?? "",
345
- guardianPrincipalId: delivery.principalId ?? "",
346
- status: "active" as const,
347
- verifiedAt: delivery.verifiedAt ?? 0,
348
- // verifiedVia is not carried on the delivery contract; a bound guardian
349
- // is verified by definition.
350
- verifiedVia: "verified",
351
- metadataJson: null,
352
- createdAt: now,
353
- updatedAt: now,
354
- };
355
- }
329
+ ): GuardianBinding | null {
330
+ const result = findGuardianForChannel(channel);
331
+ if (result) {
332
+ return {
333
+ id: result.channel.id,
334
+ assistantId,
335
+ channel,
336
+ guardianExternalUserId: result.channel.address,
337
+ guardianDeliveryChatId: result.channel.externalChatId ?? "",
338
+ guardianPrincipalId: result.contact.principalId ?? "",
339
+ status: "active" as const,
340
+ verifiedAt: result.channel.verifiedAt ?? 0,
341
+ verifiedVia: result.channel.verifiedVia ?? "",
342
+ metadataJson: null,
343
+ createdAt: result.channel.createdAt,
344
+ updatedAt: result.channel.updatedAt ?? result.channel.createdAt,
345
+ };
346
+ }
356
347
 
357
- /**
358
- * Gateway-backed guardian-existence check: is a guardian already bound for
359
- * this channel? Presence-only idempotency guard, NOT an ACL-field read.
360
- *
361
- * Null-list fail direction: a `null` from the gateway (unreachable / malformed)
362
- * is "unknown" — returns `true` so an unreachable gateway is treated as
363
- * already-bound. Callers gate session creation on a falsy result, so this
364
- * blocks a new binding on a transient miss rather than spuriously creating a
365
- * second one.
366
- */
367
- export async function isGuardianBoundForChannel(
368
- channel: string,
369
- ): Promise<boolean> {
370
- // Existence guards read fresh because gateway-side binding writes don't
371
- // invalidate the daemon cache.
372
- const list = await getGuardianDeliveryFresh({ channelTypes: [channel] });
373
- if (list === null) return true;
374
- return !!guardianForChannel(list, channel);
348
+ return null;
375
349
  }
376
350
 
377
351
  /**
378
352
  * Check whether the given external user is the active guardian for
379
353
  * the specified assistant and channel.
380
354
  */
381
- export async function isGuardian(
355
+ export function isGuardian(
382
356
  assistantId: string,
383
357
  channel: string,
384
358
  address: string,
385
- ): Promise<boolean> {
386
- const list = await getGuardianDelivery({ channelTypes: [channel] });
387
- const delivery = list ? guardianForChannel(list, channel) : undefined;
388
- if (!delivery) return false;
359
+ ): boolean {
360
+ const result = findGuardianForChannel(channel);
361
+ if (result) {
362
+ return result.channel.address.toLowerCase() === address.toLowerCase();
363
+ }
389
364
 
390
- return delivery.address.toLowerCase() === address.toLowerCase();
365
+ return false;
391
366
  }
392
367
 
393
368
  /**