@vellumai/assistant 0.9.0 → 0.10.0-dev.202606192226.8ed8a6a

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 (624) hide show
  1. package/ARCHITECTURE.md +19 -35
  2. package/bun.lock +7 -8
  3. package/docs/activation-funnel-telemetry.md +28 -22
  4. package/docs/architecture/security.md +29 -28
  5. package/docs/stt-provider-onboarding.md +3 -5
  6. package/docs/workflows-testing.md +13 -44
  7. package/docs/workflows.md +3 -5
  8. package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
  9. package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
  10. package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
  11. package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
  12. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
  13. package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
  14. package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
  15. package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
  16. package/openapi.yaml +1128 -119
  17. package/package.json +2 -1
  18. package/scripts/sync-llm-catalog.ts +6 -15
  19. package/scripts/sync-web-search-catalog.ts +3 -11
  20. package/src/__tests__/access-request-card-view.test.ts +98 -0
  21. package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
  22. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
  23. package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
  24. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
  25. package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
  26. package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
  27. package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +306 -0
  28. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
  29. package/src/__tests__/app-compiler.test.ts +15 -1
  30. package/src/__tests__/app-dir-path-guard.test.ts +0 -1
  31. package/src/__tests__/approval-cascade.test.ts +6 -0
  32. package/src/__tests__/approval-routes-http.test.ts +128 -0
  33. package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
  34. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  35. package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
  36. package/src/__tests__/avatar-identity-sync.test.ts +2 -27
  37. package/src/__tests__/btw-routes.test.ts +6 -8
  38. package/src/__tests__/call-pointer-messages.test.ts +28 -0
  39. package/src/__tests__/cancel-clears-processing.test.ts +89 -0
  40. package/src/__tests__/channel-approval-routes.test.ts +0 -4
  41. package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
  42. package/src/__tests__/checker.test.ts +0 -3
  43. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
  44. package/src/__tests__/compaction-events.test.ts +6 -0
  45. package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
  46. package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
  47. package/src/__tests__/config-loader-backfill.test.ts +268 -27
  48. package/src/__tests__/config-schema.test.ts +35 -0
  49. package/src/__tests__/config-watcher.test.ts +0 -18
  50. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
  51. package/src/__tests__/contact-store-user-file.test.ts +0 -6
  52. package/src/__tests__/contacts-tools.test.ts +29 -0
  53. package/src/__tests__/conversation-abort-tool-results.test.ts +6 -0
  54. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
  55. package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
  56. package/src/__tests__/conversation-agent-loop.test.ts +58 -0
  57. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  58. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -0
  59. package/src/__tests__/conversation-lifecycle.test.ts +7 -9
  60. package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
  61. package/src/__tests__/conversation-process-callsite.test.ts +6 -0
  62. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  63. package/src/__tests__/conversation-queue.test.ts +6 -0
  64. package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
  65. package/src/__tests__/conversation-slash-queue.test.ts +6 -0
  66. package/src/__tests__/conversation-slash-unknown.test.ts +6 -0
  67. package/src/__tests__/conversation-speed-override.test.ts +6 -0
  68. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
  69. package/src/__tests__/conversation-title-service.test.ts +62 -0
  70. package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -0
  71. package/src/__tests__/conversation-workspace-injection.test.ts +6 -0
  72. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -0
  73. package/src/__tests__/credential-broker.test.ts +449 -1
  74. package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
  75. package/src/__tests__/credential-execution-tools.test.ts +0 -1
  76. package/src/__tests__/credential-prompt-route.test.ts +4 -4
  77. package/src/__tests__/credential-routes.test.ts +360 -0
  78. package/src/__tests__/credential-security-invariants.test.ts +4 -13
  79. package/src/__tests__/disk-pressure-policy.test.ts +12 -0
  80. package/src/__tests__/disk-pressure-tools.test.ts +41 -1
  81. package/src/__tests__/disk-usage.test.ts +65 -0
  82. package/src/__tests__/document-tool-security.test.ts +9 -6
  83. package/src/__tests__/document-update-default-surface.test.ts +202 -0
  84. package/src/__tests__/dynamic-page-surface.test.ts +152 -1
  85. package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
  86. package/src/__tests__/gateway-flag-listener.test.ts +110 -1
  87. package/src/__tests__/gateway-only-guard.test.ts +3 -7
  88. package/src/__tests__/gemini-count-tokens.test.ts +70 -0
  89. package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
  90. package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
  91. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
  92. package/src/__tests__/guardian-grant-minting.test.ts +3 -35
  93. package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
  94. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  95. package/src/__tests__/headless-browser-mode.test.ts +10 -0
  96. package/src/__tests__/headless-browser-navigate.test.ts +8 -3
  97. package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
  98. package/src/__tests__/host-browser-proxy.test.ts +87 -0
  99. package/src/__tests__/identity-routes.test.ts +0 -189
  100. package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
  101. package/src/__tests__/injector-disk-pressure.test.ts +10 -5
  102. package/src/__tests__/injector-v3-suppression.test.ts +27 -20
  103. package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
  104. package/src/__tests__/invite-redemption-service.test.ts +4 -7
  105. package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
  106. package/src/__tests__/llm-catalog-parity.test.ts +30 -23
  107. package/src/__tests__/llm-resolver.test.ts +70 -24
  108. package/src/__tests__/llm-schema.test.ts +1 -0
  109. package/src/__tests__/managed-profile-guard.test.ts +163 -4
  110. package/src/__tests__/mcp-health-check.test.ts +6 -7
  111. package/src/__tests__/media-stream-server-integration.test.ts +317 -13
  112. package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
  113. package/src/__tests__/onboarding-persona-write.test.ts +1 -1
  114. package/src/__tests__/path-policy.test.ts +34 -0
  115. package/src/__tests__/persona-resolver.test.ts +49 -14
  116. package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
  117. package/src/__tests__/plugin-api-provider.test.ts +24 -0
  118. package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
  119. package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
  120. package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
  121. package/src/__tests__/reaction-persistence.test.ts +150 -29
  122. package/src/__tests__/registry.test.ts +2 -7
  123. package/src/__tests__/relay-server.test.ts +285 -0
  124. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  125. package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
  126. package/src/__tests__/schedule-routes.test.ts +0 -30
  127. package/src/__tests__/schedule-tools.test.ts +2 -18
  128. package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
  129. package/src/__tests__/secret-response-routing.test.ts +35 -0
  130. package/src/__tests__/secret-routes-platform-proxy.test.ts +16 -2
  131. package/src/__tests__/skill-execute-input.test.ts +177 -1
  132. package/src/__tests__/skill-load-tool.test.ts +72 -0
  133. package/src/__tests__/skill-runtime-path.test.ts +2 -3
  134. package/src/__tests__/skills.test.ts +51 -0
  135. package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
  136. package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
  137. package/src/__tests__/subagent-tools.test.ts +266 -0
  138. package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
  139. package/src/__tests__/system-storage-cleanup-skill.test.ts +56 -0
  140. package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
  141. package/src/__tests__/title-generate-hook.test.ts +100 -3
  142. package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
  143. package/src/__tests__/token-manager.test.ts +519 -0
  144. package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
  145. package/src/__tests__/tool-audit-listener.test.ts +7 -7
  146. package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
  147. package/src/__tests__/tool-executor.test.ts +0 -79
  148. package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
  149. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
  150. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
  151. package/src/__tests__/trusted-contact-verification.test.ts +8 -10
  152. package/src/__tests__/twilio-routes.test.ts +81 -1
  153. package/src/__tests__/voice-invite-redemption.test.ts +2 -3
  154. package/src/__tests__/weak-open-model.test.ts +30 -0
  155. package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
  156. package/src/__tests__/workspace-greetings.test.ts +152 -0
  157. package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
  158. package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
  159. package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
  160. package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
  161. package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
  162. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
  163. package/src/agent/loop.ts +75 -29
  164. package/src/api/README.md +6 -6
  165. package/src/api/events/tool-result.ts +6 -0
  166. package/src/api/events/workflow-completed.ts +53 -0
  167. package/src/api/events/workflow-leaf-finished.ts +38 -0
  168. package/src/api/events/workflow-leaf-started.ts +35 -0
  169. package/src/api/events/workflow-progress.ts +32 -0
  170. package/src/api/events/workflow-started.ts +31 -0
  171. package/src/api/index.ts +40 -0
  172. package/src/api/responses/conversation-message.ts +28 -4
  173. package/src/api/responses/home.ts +26 -4
  174. package/src/api/responses/workflow-journal.ts +53 -0
  175. package/src/approvals/guardian-card-withdrawal.ts +145 -0
  176. package/src/approvals/guardian-decision-primitive.ts +26 -3
  177. package/src/approvals/guardian-request-resolvers.ts +183 -80
  178. package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
  179. package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
  180. package/src/calls/call-pointer-messages.ts +10 -4
  181. package/src/calls/channel-admission-reader.ts +104 -0
  182. package/src/calls/guardian-dispatch.ts +17 -45
  183. package/src/calls/media-stream-server.ts +84 -2
  184. package/src/calls/relay-access-wait.ts +1 -1
  185. package/src/calls/relay-server.ts +66 -0
  186. package/src/calls/relay-setup-router.ts +82 -1
  187. package/src/calls/twilio-routes.ts +17 -8
  188. package/src/calls/voice-session-bridge.ts +2 -2
  189. package/src/cli/commands/clients.ts +3 -0
  190. package/src/cli/commands/db/status.ts +37 -3
  191. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
  192. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
  193. package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
  194. package/src/cli/commands/memory/index.ts +30 -0
  195. package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
  196. package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
  197. package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
  198. package/src/cli/commands/oauth/status.test.ts +36 -0
  199. package/src/cli/commands/oauth/status.ts +23 -3
  200. package/src/cli/commands/plugins.ts +400 -14
  201. package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
  202. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  203. package/src/cli/lib/__tests__/install-from-github.test.ts +31 -0
  204. package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
  205. package/src/cli/lib/__tests__/plugin-pin-history.test.ts +162 -0
  206. package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
  207. package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
  208. package/src/cli/lib/diff-plugin.ts +346 -0
  209. package/src/cli/lib/inspect-plugin.ts +12 -1
  210. package/src/cli/lib/install-from-github.ts +128 -19
  211. package/src/cli/lib/merge-plugin-tree.ts +328 -0
  212. package/src/cli/lib/plugin-fingerprint.ts +14 -0
  213. package/src/cli/lib/plugin-marketplace.ts +11 -0
  214. package/src/cli/lib/plugin-pin-history.ts +257 -0
  215. package/src/cli/lib/plugin-surfaces.ts +104 -0
  216. package/src/cli/lib/upgrade-plugin.ts +298 -10
  217. package/src/cli/program.ts +2 -6
  218. package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
  219. package/src/config/assistant-feature-flags.ts +22 -7
  220. package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
  221. package/src/config/bundled-skills/document-editor/SKILL.md +3 -3
  222. package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
  223. package/src/config/bundled-skills/messaging/SKILL.md +6 -4
  224. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
  225. package/src/config/bundled-skills/subagent/SKILL.md +4 -0
  226. package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
  227. package/src/config/bundled-skills/system-storage-cleanup/SKILL.md +74 -0
  228. package/src/config/bundled-skills/workflows/SKILL.md +14 -8
  229. package/src/config/bundled-tool-registry.ts +2 -7
  230. package/src/config/call-site-defaults.ts +15 -2
  231. package/src/config/feature-flag-registry.json +46 -31
  232. package/src/config/inference-profile-validation.ts +26 -0
  233. package/src/config/llm-resolver.ts +3 -0
  234. package/src/config/loader.ts +4 -0
  235. package/src/config/memory-v3-gate.ts +11 -0
  236. package/src/config/profile-order.ts +28 -0
  237. package/src/config/schema.ts +8 -6
  238. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  239. package/src/config/schemas/call-site-catalog.ts +7 -0
  240. package/src/config/schemas/channels.ts +11 -0
  241. package/src/config/schemas/elevenlabs.ts +0 -1
  242. package/src/config/schemas/llm.ts +31 -0
  243. package/src/config/schemas/memory-lifecycle.ts +3 -7
  244. package/src/config/schemas/memory-v3.ts +6 -0
  245. package/src/config/schemas/platform.ts +0 -8
  246. package/src/config/schemas/services.ts +18 -0
  247. package/src/config/seed-inference-profiles.ts +109 -44
  248. package/src/config/skills.ts +21 -0
  249. package/src/config/sync-gated-profiles.ts +220 -0
  250. package/src/contacts/contact-store.ts +89 -106
  251. package/src/contacts/contacts-write.ts +5 -22
  252. package/src/contacts/types.ts +0 -1
  253. package/src/context/compactor.ts +88 -54
  254. package/src/context/strip-injections.ts +58 -10
  255. package/src/context/token-estimator.ts +1 -1
  256. package/src/credential-execution/process-manager.ts +55 -14
  257. package/src/credential-execution/prompted-credential.ts +2 -3
  258. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
  259. package/src/daemon/__tests__/conversation-tool-setup.test.ts +44 -0
  260. package/src/daemon/config-watcher.ts +0 -4
  261. package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
  262. package/src/daemon/conversation-agent-loop.ts +114 -22
  263. package/src/daemon/conversation-history.ts +1 -1
  264. package/src/daemon/conversation-lifecycle.ts +3 -5
  265. package/src/daemon/conversation-process.ts +13 -5
  266. package/src/daemon/conversation-runtime-assembly.ts +13 -15
  267. package/src/daemon/conversation-slash.ts +2 -23
  268. package/src/daemon/conversation-surfaces.ts +26 -0
  269. package/src/daemon/conversation-tool-setup.ts +53 -19
  270. package/src/daemon/conversation.ts +131 -20
  271. package/src/daemon/disk-pressure-policy.ts +5 -3
  272. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
  273. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
  274. package/src/daemon/handlers/config-a2a.ts +0 -2
  275. package/src/daemon/handlers/config-channels.ts +15 -16
  276. package/src/daemon/handlers/config-slack-channel.ts +22 -3
  277. package/src/daemon/handlers/conversations.ts +107 -0
  278. package/src/daemon/host-browser-proxy.ts +41 -0
  279. package/src/daemon/lifecycle.ts +55 -27
  280. package/src/daemon/memory-v2-startup.test.ts +131 -0
  281. package/src/daemon/memory-v2-startup.ts +100 -1
  282. package/src/daemon/message-provenance.ts +2 -0
  283. package/src/daemon/message-types/contacts.ts +0 -1
  284. package/src/daemon/message-types/conversations.ts +3 -3
  285. package/src/daemon/message-types/sync.ts +0 -1
  286. package/src/daemon/message-types/web-activity.ts +7 -1
  287. package/src/daemon/message-types/workflows.ts +83 -1
  288. package/src/daemon/orphan-reaper.test.ts +0 -19
  289. package/src/daemon/orphan-reaper.ts +2 -24
  290. package/src/daemon/server.ts +0 -10
  291. package/src/daemon/tool-setup-types.ts +4 -0
  292. package/src/daemon/trust-context.ts +1 -1
  293. package/src/daemon/wake-conversation-ops.ts +1 -0
  294. package/src/events/tool-audit-listener.ts +2 -2
  295. package/src/home/feed-source-enrichment.test.ts +151 -0
  296. package/src/home/feed-source-enrichment.ts +176 -0
  297. package/src/home/relationship-state.ts +2 -4
  298. package/src/instrument.ts +18 -6
  299. package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
  300. package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
  301. package/src/ipc/assistant-server.ts +37 -4
  302. package/src/ipc/gateway-flag-listener.ts +18 -2
  303. package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
  304. package/src/memory/__tests__/db-logs-attach.test.ts +122 -0
  305. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
  306. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
  307. package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
  308. package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
  309. package/src/memory/auth-fallback-events-store.ts +2 -2
  310. package/src/memory/auto-analysis-enqueue.ts +3 -5
  311. package/src/memory/bookmark-crud.ts +1 -2
  312. package/src/memory/canonical-guardian-store.ts +39 -1
  313. package/src/memory/conversation-crud.ts +9 -4
  314. package/src/memory/conversation-key-store.ts +17 -2
  315. package/src/memory/conversation-title-service.ts +64 -7
  316. package/src/memory/db-async-query.ts +20 -2
  317. package/src/memory/db-connection.ts +49 -5
  318. package/src/memory/db-init.ts +17 -17
  319. package/src/memory/embedding-backend.ts +38 -1
  320. package/src/memory/embedding-billing-breaker.ts +96 -0
  321. package/src/memory/jobs-store.ts +25 -13
  322. package/src/memory/jobs-worker.ts +54 -1
  323. package/src/memory/lifecycle-events-store.ts +2 -2
  324. package/src/memory/memory-retrospective-constants.ts +4 -4
  325. package/src/memory/memory-retrospective-enqueue.ts +31 -6
  326. package/src/memory/memory-retrospective-job.ts +28 -227
  327. package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
  328. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
  329. package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
  330. package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
  331. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
  332. package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
  333. package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
  334. package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
  335. package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
  336. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
  337. package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
  338. package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
  339. package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
  340. package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
  341. package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
  342. package/src/memory/migrations/index.ts +6 -0
  343. package/src/memory/migrations/run-migrations.ts +41 -0
  344. package/src/memory/migrations/validate-migration-state.ts +1 -1
  345. package/src/memory/onboarding-events-store.ts +3 -3
  346. package/src/memory/schema/contacts.ts +0 -5
  347. package/src/memory/skill-loaded-events-store.test.ts +7 -15
  348. package/src/memory/skill-loaded-events-store.ts +2 -2
  349. package/src/memory/tool-executed-events-store.test.ts +7 -7
  350. package/src/memory/turn-trace-store.test.ts +736 -0
  351. package/src/memory/turn-trace-store.ts +364 -0
  352. package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
  353. package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
  354. package/src/memory/v2/consolidation-job.ts +2 -2
  355. package/src/memory/v2/skill-content.ts +25 -7
  356. package/src/memory/v2/skill-store.ts +7 -1
  357. package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
  358. package/src/memory/v3-eval/eval-packets.ts +546 -0
  359. package/src/messaging/providers/slack/adapter.ts +1 -1
  360. package/src/messaging/providers/slack/api.ts +31 -0
  361. package/src/messaging/providers/slack/send.test.ts +114 -2
  362. package/src/messaging/providers/slack/send.ts +30 -7
  363. package/src/messaging/providers/slack/withdraw.test.ts +200 -0
  364. package/src/messaging/providers/slack/withdraw.ts +161 -0
  365. package/src/notifications/AGENTS.md +2 -0
  366. package/src/notifications/access-request-copy.ts +72 -59
  367. package/src/notifications/adapters/shared.ts +29 -0
  368. package/src/notifications/adapters/slack.ts +58 -103
  369. package/src/notifications/adapters/telegram.ts +2 -20
  370. package/src/notifications/approval-card-data.ts +333 -0
  371. package/src/notifications/broadcaster.ts +16 -3
  372. package/src/notifications/canonical-delivery-recorder.ts +139 -0
  373. package/src/notifications/copy-composer.ts +3 -3
  374. package/src/notifications/decision-engine.ts +4 -2
  375. package/src/notifications/destination-resolver.ts +4 -6
  376. package/src/notifications/guardian-question-mode.ts +10 -0
  377. package/src/notifications/home-feed-side-effect.ts +7 -16
  378. package/src/notifications/notification-utils.ts +19 -20
  379. package/src/notifications/signal.ts +79 -43
  380. package/src/notifications/types.ts +98 -121
  381. package/src/oauth/AGENTS.md +5 -24
  382. package/src/permissions/checker.test.ts +51 -0
  383. package/src/permissions/checker.ts +185 -26
  384. package/src/permissions/ipc-risk-types.ts +24 -0
  385. package/src/permissions/question-prompter.test.ts +27 -0
  386. package/src/permissions/question-prompter.ts +4 -0
  387. package/src/permissions/secret-prompter.ts +15 -1
  388. package/src/platform/client.test.ts +119 -0
  389. package/src/platform/client.ts +66 -0
  390. package/src/platform/consent-cache.test.ts +267 -0
  391. package/src/platform/consent-cache.ts +174 -0
  392. package/src/plugin-api/constants.ts +1 -1
  393. package/src/plugin-api/index.ts +33 -1
  394. package/src/plugin-api/model-profiles.ts +33 -0
  395. package/src/plugin-api/types.ts +50 -2
  396. package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
  397. package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
  398. package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
  399. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
  400. package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
  401. package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
  402. package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
  403. package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
  404. package/src/plugins/defaults/advisor/config.ts +21 -0
  405. package/src/plugins/defaults/advisor/consult.ts +93 -0
  406. package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
  407. package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
  408. package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
  409. package/src/plugins/defaults/advisor/package.json +14 -0
  410. package/src/plugins/defaults/advisor/steering.ts +67 -0
  411. package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
  412. package/src/plugins/defaults/advisor/transcript.ts +76 -0
  413. package/src/plugins/defaults/compaction/window-manager.ts +18 -0
  414. package/src/plugins/defaults/index.ts +60 -0
  415. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
  416. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
  417. package/src/plugins/defaults/memory-retrieval/injectors.ts +4 -4
  418. package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
  419. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
  420. package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
  421. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
  422. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
  423. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
  424. package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
  425. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
  426. package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
  427. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
  428. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
  429. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
  430. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
  431. package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
  432. package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
  433. package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
  434. package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
  435. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
  436. package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
  437. package/src/prompts/persona-resolver.ts +14 -4
  438. package/src/prompts/templates/system-sections.ts +7 -2
  439. package/src/providers/__tests__/count-tokens-forwarding.test.ts +98 -0
  440. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  441. package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
  442. package/src/providers/__tests__/retry-callsite.test.ts +176 -0
  443. package/src/providers/anthropic/client.ts +230 -175
  444. package/src/providers/atlascloud/client.ts +85 -0
  445. package/src/providers/call-site-routing.ts +10 -0
  446. package/src/providers/fetch-provider-catalog.ts +85 -0
  447. package/src/providers/gemini/client.ts +43 -0
  448. package/src/providers/inference/adapter-factory.ts +3 -0
  449. package/src/providers/model-catalog.ts +58 -0
  450. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
  451. package/src/providers/openai/chat-completions-provider.ts +7 -0
  452. package/src/providers/openai/responses-provider.ts +10 -0
  453. package/src/providers/provider-send-message.ts +11 -3
  454. package/src/providers/ratelimit.ts +9 -0
  455. package/src/providers/retry.ts +62 -12
  456. package/src/providers/search-provider-catalog.ts +10 -0
  457. package/src/providers/types.ts +16 -0
  458. package/src/providers/usage-tracking.ts +7 -0
  459. package/src/providers/weak-open-model.ts +22 -0
  460. package/src/runtime/AGENTS.md +0 -1
  461. package/src/runtime/__tests__/agent-wake.test.ts +227 -0
  462. package/src/runtime/__tests__/client-health.test.ts +44 -0
  463. package/src/runtime/access-request-helper.ts +21 -53
  464. package/src/runtime/actor-trust-resolver.ts +59 -63
  465. package/src/runtime/agent-wake.ts +71 -0
  466. package/src/runtime/assistant-event-hub.ts +18 -4
  467. package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
  468. package/src/runtime/auth/require-bound-guardian.ts +1 -4
  469. package/src/runtime/btw-sidechain.ts +3 -6
  470. package/src/runtime/capabilities.test.ts +120 -0
  471. package/src/runtime/capabilities.ts +197 -0
  472. package/src/runtime/channel-approval-types.ts +22 -45
  473. package/src/runtime/channel-invite-transports/telegram.ts +4 -4
  474. package/src/runtime/channel-retry-sweep.ts +1 -0
  475. package/src/runtime/channel-verification-service.ts +3 -3
  476. package/src/runtime/client-health.ts +26 -0
  477. package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
  478. package/src/runtime/effective-capabilities.test.ts +128 -0
  479. package/src/runtime/effective-capabilities.ts +84 -0
  480. package/src/runtime/guardian-reply-router.ts +106 -21
  481. package/src/runtime/invite-redemption-service.ts +9 -25
  482. package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +126 -0
  483. package/src/runtime/migrations/vbundle-builder.ts +49 -20
  484. package/src/runtime/pending-interactions.ts +35 -0
  485. package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
  486. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
  487. package/src/runtime/routes/__tests__/plugins-routes.test.ts +383 -1
  488. package/src/runtime/routes/app-routes.ts +1 -1
  489. package/src/runtime/routes/approval-routes.ts +40 -9
  490. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
  491. package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
  492. package/src/runtime/routes/browser-tabs-routes.ts +9 -0
  493. package/src/runtime/routes/btw-routes.ts +1 -27
  494. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
  495. package/src/runtime/routes/client-routes.ts +10 -0
  496. package/src/runtime/routes/contact-routes.ts +31 -8
  497. package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
  498. package/src/runtime/routes/conversation-management-routes.ts +80 -1
  499. package/src/runtime/routes/conversation-query-routes.ts +68 -22
  500. package/src/runtime/routes/conversation-routes.ts +39 -14
  501. package/src/runtime/routes/credential-routes.ts +40 -16
  502. package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
  503. package/src/runtime/routes/events-routes.ts +1 -3
  504. package/src/runtime/routes/guardian-approval-interception.ts +14 -73
  505. package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
  506. package/src/runtime/routes/home-feed-routes.ts +8 -3
  507. package/src/runtime/routes/identity-routes.ts +1 -296
  508. package/src/runtime/routes/inbound-message-handler.ts +214 -228
  509. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
  510. package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
  511. package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
  512. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
  513. package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
  514. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
  515. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
  516. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
  517. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
  518. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
  519. package/src/runtime/routes/index.ts +2 -0
  520. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
  521. package/src/runtime/routes/integrations/slack/channel.ts +36 -0
  522. package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
  523. package/src/runtime/routes/mcp-auth-routes.ts +233 -41
  524. package/src/runtime/routes/memory-eval-routes.ts +87 -0
  525. package/src/runtime/routes/notification-routes.ts +122 -133
  526. package/src/runtime/routes/platform-routes.ts +2 -2
  527. package/src/runtime/routes/plugins-routes.ts +366 -11
  528. package/src/runtime/routes/schedule-routes.ts +0 -22
  529. package/src/runtime/routes/secret-routes.ts +15 -0
  530. package/src/runtime/routes/surface-action-routes.ts +2 -1
  531. package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
  532. package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
  533. package/src/runtime/routes/workflow-routes.test.ts +229 -44
  534. package/src/runtime/routes/workflow-routes.ts +131 -29
  535. package/src/runtime/routes/workspace-greetings.ts +55 -0
  536. package/src/runtime/sync/resource-sync-events.ts +1 -11
  537. package/src/runtime/tool-grant-request-helper.ts +18 -16
  538. package/src/runtime/trust-context-resolver.ts +8 -5
  539. package/src/schedule/inference-profile.ts +2 -14
  540. package/src/schedule/schedule-store.ts +1 -1
  541. package/src/schedule/scheduler-types.ts +5 -1
  542. package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
  543. package/src/security/secret-patterns.ts +3 -0
  544. package/src/subagent/manager.ts +17 -4
  545. package/src/subagent/types.ts +6 -0
  546. package/src/telemetry/trace-collection-policy.test.ts +28 -0
  547. package/src/telemetry/trace-collection-policy.ts +30 -0
  548. package/src/telemetry/types.ts +89 -0
  549. package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
  550. package/src/telemetry/usage-telemetry-reporter.ts +148 -41
  551. package/src/tools/AGENTS.md +3 -3
  552. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
  553. package/src/tools/browser/browser-execution.ts +30 -19
  554. package/src/tools/document/document-tool.ts +30 -6
  555. package/src/tools/executor.ts +5 -3
  556. package/src/tools/host-terminal/host-shell.ts +5 -4
  557. package/src/tools/memory/register.ts +2 -2
  558. package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
  559. package/src/tools/network/__tests__/web-search.test.ts +143 -0
  560. package/src/tools/network/web-fetch.ts +372 -1
  561. package/src/tools/network/web-search-error.ts +1 -1
  562. package/src/tools/network/web-search.ts +213 -10
  563. package/src/tools/permission-checker.ts +4 -3
  564. package/src/tools/registry.ts +20 -0
  565. package/src/tools/schedule/create.ts +7 -12
  566. package/src/tools/schedule/update.ts +4 -11
  567. package/src/tools/shared/filesystem/path-policy.ts +39 -13
  568. package/src/tools/side-effects.ts +2 -17
  569. package/src/tools/skills/execute.ts +99 -2
  570. package/src/tools/skills/load.ts +43 -2
  571. package/src/tools/subagent/spawn.ts +64 -15
  572. package/src/tools/terminal/shell.ts +10 -4
  573. package/src/tools/tool-approval-handler.ts +18 -13
  574. package/src/tools/tool-manifest.ts +0 -2
  575. package/src/tools/types.ts +10 -0
  576. package/src/tools/ui-surface/definitions.ts +64 -3
  577. package/src/tools/verification-control-plane-policy.ts +3 -1
  578. package/src/tools/workflows/run-workflow.test.ts +8 -18
  579. package/src/tools/workflows/run-workflow.ts +1 -0
  580. package/src/util/disk-usage.ts +78 -23
  581. package/src/util/logs-db-path.ts +22 -0
  582. package/src/util/platform.ts +10 -3
  583. package/src/watcher/telemetry.ts +2 -2
  584. package/src/workflows/capabilities.ts +2 -3
  585. package/src/workflows/engine.test.ts +175 -1
  586. package/src/workflows/engine.ts +82 -0
  587. package/src/workflows/journal-store.test.ts +70 -0
  588. package/src/workflows/journal-store.ts +18 -3
  589. package/src/workflows/run-manager.test.ts +171 -28
  590. package/src/workflows/run-manager.ts +66 -24
  591. package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
  592. package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
  593. package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
  594. package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
  595. package/src/workspace/migrations/registry.ts +8 -0
  596. package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
  597. package/src/__tests__/credential-security-e2e.test.ts +0 -362
  598. package/src/__tests__/credential-vault-unit.test.ts +0 -1528
  599. package/src/__tests__/credential-vault.test.ts +0 -1706
  600. package/src/__tests__/identity-intro-cache.test.ts +0 -315
  601. package/src/__tests__/secret-onetime-send.test.ts +0 -182
  602. package/src/cli/commands/__tests__/task.test.ts +0 -914
  603. package/src/cli/commands/task.ts +0 -771
  604. package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
  605. package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
  606. package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
  607. package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
  608. package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
  609. package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
  610. package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
  611. package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
  612. package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
  613. package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
  614. package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
  615. package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
  616. package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
  617. package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
  618. package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
  619. package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
  620. package/src/memory/preloaded-apps.ts +0 -116
  621. package/src/notifications/tool-approval-copy.ts +0 -142
  622. package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
  623. package/src/runtime/routes/identity-intro-cache.ts +0 -172
  624. package/src/tools/credentials/vault.ts +0 -712
@@ -0,0 +1,154 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import { getSqliteFrom } from "../../db-connection.js";
7
+ import * as schema from "../../schema.js";
8
+ import { migrateDropLegacyMemberGuardianTables } from "../131-drop-legacy-member-guardian-tables.js";
9
+
10
+ function createTestDb() {
11
+ const sqlite = new Database(":memory:");
12
+ sqlite.exec("PRAGMA journal_mode=WAL");
13
+ return drizzle(sqlite, { schema });
14
+ }
15
+
16
+ function bootstrap(db: ReturnType<typeof createTestDb>): void {
17
+ const raw = getSqliteFrom(db);
18
+ raw.exec(/*sql*/ `
19
+ CREATE TABLE contacts (
20
+ id TEXT PRIMARY KEY,
21
+ display_name TEXT NOT NULL,
22
+ role TEXT NOT NULL DEFAULT 'contact',
23
+ principal_id TEXT,
24
+ created_at INTEGER NOT NULL,
25
+ updated_at INTEGER NOT NULL
26
+ )
27
+ `);
28
+ raw.exec(/*sql*/ `
29
+ CREATE TABLE contact_channels (
30
+ id TEXT PRIMARY KEY,
31
+ contact_id TEXT NOT NULL,
32
+ type TEXT NOT NULL,
33
+ address TEXT NOT NULL,
34
+ external_user_id TEXT,
35
+ external_chat_id TEXT,
36
+ status TEXT NOT NULL DEFAULT 'unverified',
37
+ policy TEXT NOT NULL DEFAULT 'allow',
38
+ invite_id TEXT,
39
+ revoked_reason TEXT,
40
+ blocked_reason TEXT,
41
+ last_seen_at INTEGER,
42
+ verified_at INTEGER,
43
+ verified_via TEXT,
44
+ created_at INTEGER NOT NULL,
45
+ updated_at INTEGER
46
+ )
47
+ `);
48
+ raw.exec(/*sql*/ `
49
+ CREATE INDEX idx_contact_channels_type_ext_user
50
+ ON contact_channels(type, external_user_id)
51
+ `);
52
+ }
53
+
54
+ function createLegacyTables(raw: Database): void {
55
+ raw.exec(/*sql*/ `
56
+ CREATE TABLE channel_guardian_bindings (
57
+ id TEXT PRIMARY KEY,
58
+ channel TEXT NOT NULL,
59
+ status TEXT NOT NULL,
60
+ guardian_external_user_id TEXT,
61
+ guardian_principal_id TEXT,
62
+ guardian_delivery_chat_id TEXT,
63
+ metadata_json TEXT,
64
+ verified_at INTEGER,
65
+ verified_via TEXT,
66
+ created_at INTEGER NOT NULL
67
+ )
68
+ `);
69
+ raw.exec(/*sql*/ `
70
+ CREATE TABLE assistant_ingress_members (
71
+ id TEXT PRIMARY KEY,
72
+ source_channel TEXT NOT NULL,
73
+ external_user_id TEXT,
74
+ external_chat_id TEXT,
75
+ display_name TEXT,
76
+ username TEXT,
77
+ status TEXT NOT NULL,
78
+ policy TEXT,
79
+ invite_id TEXT,
80
+ revoked_reason TEXT,
81
+ blocked_reason TEXT,
82
+ last_seen_at INTEGER,
83
+ created_at INTEGER NOT NULL,
84
+ updated_at INTEGER
85
+ )
86
+ `);
87
+ }
88
+
89
+ function tableExists(raw: Database, name: string): boolean {
90
+ return !!raw
91
+ .prepare(`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?`)
92
+ .get(name);
93
+ }
94
+
95
+ function seedLegacyRows(raw: Database): void {
96
+ raw.run(
97
+ `INSERT INTO channel_guardian_bindings
98
+ (id, channel, status, guardian_external_user_id, guardian_principal_id,
99
+ guardian_delivery_chat_id, metadata_json, verified_at, verified_via, created_at)
100
+ VALUES ('g1','telegram','active','U-guardian','prin-1','chat-1',NULL,1000,'telegram',1000)`,
101
+ );
102
+ raw.run(
103
+ `INSERT INTO assistant_ingress_members
104
+ (id, source_channel, external_user_id, external_chat_id, display_name,
105
+ username, status, policy, invite_id, revoked_reason, blocked_reason,
106
+ last_seen_at, created_at, updated_at)
107
+ VALUES ('m1','slack','U-member',NULL,'Member One','member1','active','allow',
108
+ NULL,NULL,NULL,2000,2000,2000)`,
109
+ );
110
+ }
111
+
112
+ describe("migration 131 — drop legacy member/guardian tables", () => {
113
+ test("syncs stragglers then drops the legacy tables when the column is present", () => {
114
+ const db = createTestDb();
115
+ const raw = getSqliteFrom(db);
116
+ bootstrap(db);
117
+ createLegacyTables(raw);
118
+ seedLegacyRows(raw);
119
+
120
+ migrateDropLegacyMemberGuardianTables(db);
121
+
122
+ // The straggler rows were synced into contact_channels.
123
+ const synced = raw
124
+ .prepare(`SELECT external_user_id FROM contact_channels ORDER BY id`)
125
+ .all() as { external_user_id: string | null }[];
126
+ expect(synced.map((r) => r.external_user_id).sort()).toEqual([
127
+ "U-guardian",
128
+ "U-member",
129
+ ]);
130
+
131
+ // The legacy tables were removed.
132
+ expect(tableExists(raw, "channel_guardian_bindings")).toBe(false);
133
+ expect(tableExists(raw, "assistant_ingress_members")).toBe(false);
134
+ });
135
+
136
+ test("drops the legacy tables without throwing when external_user_id is absent (re-run after migration 294)", () => {
137
+ const db = createTestDb();
138
+ const raw = getSqliteFrom(db);
139
+ bootstrap(db);
140
+ createLegacyTables(raw);
141
+ seedLegacyRows(raw);
142
+
143
+ // Simulate a later startup where migration 294 has already dropped the
144
+ // index + column. The sync references external_user_id, so 131 must skip it
145
+ // and still drop the tables rather than failing on every boot.
146
+ raw.run("DROP INDEX IF EXISTS idx_contact_channels_type_ext_user");
147
+ raw.run("ALTER TABLE contact_channels DROP COLUMN external_user_id");
148
+
149
+ expect(() => migrateDropLegacyMemberGuardianTables(db)).not.toThrow();
150
+
151
+ expect(tableExists(raw, "channel_guardian_bindings")).toBe(false);
152
+ expect(tableExists(raw, "assistant_ingress_members")).toBe(false);
153
+ });
154
+ });
@@ -568,4 +568,35 @@ describe("migration 287 — dedup case collisions + drop ext_user indexes", () =
568
568
  // Original casing preserved
569
569
  expect(channels[0]!.address).toBe("U999");
570
570
  });
571
+
572
+ test("no-op when external_user_id column is absent (re-run after migration 294)", () => {
573
+ const db = createTestDb();
574
+ const raw = getSqliteFrom(db);
575
+ bootstrap(db);
576
+
577
+ insertContact(raw, "c1");
578
+ insertChannel(raw, {
579
+ id: "ch1",
580
+ contactId: "c1",
581
+ type: "slack",
582
+ address: "U999",
583
+ externalUserId: "U999",
584
+ status: "active",
585
+ updatedAt: 1000,
586
+ });
587
+
588
+ // Simulate a later startup where migration 294 has already dropped the
589
+ // index and column. Migration steps re-run on every startup, so this must
590
+ // tolerate the dropped column rather than throwing "no such column".
591
+ raw.run("DROP INDEX IF EXISTS idx_contact_channels_type_ext_user");
592
+ raw.run("ALTER TABLE contact_channels DROP COLUMN external_user_id");
593
+
594
+ expect(() => migrateContactChannelsUniqueExtUser(db)).not.toThrow();
595
+
596
+ const rows = raw
597
+ .prepare("SELECT id, address FROM contact_channels")
598
+ .all() as { id: string; address: string }[];
599
+ expect(rows).toHaveLength(1);
600
+ expect(rows[0]!.address).toBe("U999");
601
+ });
571
602
  });
@@ -0,0 +1,341 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import { getSqliteFrom } from "../../db-connection.js";
7
+ import * as schema from "../../schema.js";
8
+ import { migrateContactChannelsRenormalizeAddresses } from "../291-contact-channels-renormalize-addresses.js";
9
+
10
+ interface ChannelRow {
11
+ id: string;
12
+ contact_id: string;
13
+ type: string;
14
+ address: string;
15
+ external_user_id: string | null;
16
+ status: string;
17
+ }
18
+
19
+ function createTestDb() {
20
+ const sqlite = new Database(":memory:");
21
+ sqlite.exec("PRAGMA journal_mode=WAL");
22
+ sqlite.exec("PRAGMA foreign_keys = ON");
23
+ return drizzle(sqlite, { schema });
24
+ }
25
+
26
+ function bootstrap(db: ReturnType<typeof createTestDb>): void {
27
+ const raw = getSqliteFrom(db);
28
+ raw.exec(/*sql*/ `
29
+ CREATE TABLE contacts (
30
+ id TEXT PRIMARY KEY,
31
+ display_name TEXT NOT NULL,
32
+ created_at INTEGER NOT NULL,
33
+ updated_at INTEGER NOT NULL,
34
+ role TEXT NOT NULL DEFAULT 'contact',
35
+ contact_type TEXT NOT NULL DEFAULT 'human'
36
+ )
37
+ `);
38
+ raw.exec(/*sql*/ `
39
+ CREATE TABLE contact_channels (
40
+ id TEXT PRIMARY KEY,
41
+ contact_id TEXT NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
42
+ type TEXT NOT NULL,
43
+ address TEXT NOT NULL,
44
+ is_primary INTEGER NOT NULL DEFAULT 0,
45
+ external_user_id TEXT,
46
+ external_chat_id TEXT,
47
+ status TEXT NOT NULL DEFAULT 'unverified',
48
+ policy TEXT NOT NULL DEFAULT 'allow',
49
+ interaction_count INTEGER NOT NULL DEFAULT 0,
50
+ updated_at INTEGER,
51
+ created_at INTEGER NOT NULL
52
+ )
53
+ `);
54
+ raw.exec(/*sql*/ `
55
+ CREATE UNIQUE INDEX idx_contact_channels_type_address
56
+ ON contact_channels(type, address)
57
+ `);
58
+ }
59
+
60
+ function insertContact(raw: Database, id: string): void {
61
+ const now = Date.now();
62
+ raw
63
+ .query(
64
+ `INSERT INTO contacts (id, display_name, created_at, updated_at) VALUES (?, ?, ?, ?)`,
65
+ )
66
+ .run(id, `Contact ${id}`, now, now);
67
+ }
68
+
69
+ function insertChannel(
70
+ raw: Database,
71
+ opts: {
72
+ id: string;
73
+ contactId: string;
74
+ type: string;
75
+ address: string;
76
+ externalUserId: string | null;
77
+ status: string;
78
+ },
79
+ ): void {
80
+ const now = Date.now();
81
+ raw
82
+ .query(
83
+ `INSERT INTO contact_channels (id, contact_id, type, address, external_user_id, status, updated_at, created_at)
84
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
85
+ )
86
+ .run(
87
+ opts.id,
88
+ opts.contactId,
89
+ opts.type,
90
+ opts.address,
91
+ opts.externalUserId,
92
+ opts.status,
93
+ now,
94
+ now,
95
+ );
96
+ }
97
+
98
+ describe("migration 291 — renormalize addresses", () => {
99
+ test("restores Slack address casing from external_user_id", () => {
100
+ const db = createTestDb();
101
+ bootstrap(db);
102
+ const raw = getSqliteFrom(db);
103
+
104
+ insertContact(raw, "c1");
105
+ insertChannel(raw, {
106
+ id: "ch1",
107
+ contactId: "c1",
108
+ type: "slack",
109
+ address: "u12345abc",
110
+ externalUserId: "U12345ABC",
111
+ status: "active",
112
+ });
113
+
114
+ migrateContactChannelsRenormalizeAddresses(db);
115
+
116
+ const rows = raw
117
+ .prepare("SELECT * FROM contact_channels")
118
+ .all() as ChannelRow[];
119
+ expect(rows).toHaveLength(1);
120
+ expect(rows[0].address).toBe("U12345ABC");
121
+ });
122
+
123
+ test("preserves lowercase email addresses (does not overwrite with mixed-case external_user_id)", () => {
124
+ const db = createTestDb();
125
+ bootstrap(db);
126
+ const raw = getSqliteFrom(db);
127
+
128
+ insertContact(raw, "c1");
129
+ insertChannel(raw, {
130
+ id: "ch1",
131
+ contactId: "c1",
132
+ type: "email",
133
+ address: "user@example.com",
134
+ // generic-examples:ignore-next-line — reason: testing mixed-case email normalization
135
+ externalUserId: "User@Example.com",
136
+ status: "active",
137
+ });
138
+
139
+ migrateContactChannelsRenormalizeAddresses(db);
140
+
141
+ const rows = raw
142
+ .prepare("SELECT * FROM contact_channels")
143
+ .all() as ChannelRow[];
144
+ expect(rows).toHaveLength(1);
145
+ expect(rows[0].address).toBe("user@example.com");
146
+ });
147
+
148
+ test("lowercases email address if it was stored incorrectly", () => {
149
+ const db = createTestDb();
150
+ bootstrap(db);
151
+ const raw = getSqliteFrom(db);
152
+
153
+ insertContact(raw, "c1");
154
+ insertChannel(raw, {
155
+ id: "ch1",
156
+ contactId: "c1",
157
+ type: "email",
158
+ // generic-examples:ignore-next-line — reason: testing mixed-case email stored incorrectly
159
+ address: "User@Example.com",
160
+ // generic-examples:ignore-next-line — reason: testing mixed-case email stored incorrectly
161
+ externalUserId: "User@Example.com",
162
+ status: "active",
163
+ });
164
+
165
+ migrateContactChannelsRenormalizeAddresses(db);
166
+
167
+ const rows = raw
168
+ .prepare("SELECT * FROM contact_channels")
169
+ .all() as ChannelRow[];
170
+ expect(rows).toHaveLength(1);
171
+ expect(rows[0].address).toBe("user@example.com");
172
+ });
173
+
174
+ test("removes cross-column blocker before normalization", () => {
175
+ const db = createTestDb();
176
+ bootstrap(db);
177
+ const raw = getSqliteFrom(db);
178
+
179
+ insertContact(raw, "c1");
180
+ insertContact(raw, "c2");
181
+ // Blocker: NULL external_user_id, address matches normalizer's external_user_id
182
+ insertChannel(raw, {
183
+ id: "blocker",
184
+ contactId: "c1",
185
+ type: "slack",
186
+ address: "u12345abc",
187
+ externalUserId: null,
188
+ status: "unverified",
189
+ });
190
+ // Normalizer: has external_user_id that will become its address
191
+ insertChannel(raw, {
192
+ id: "normalizer",
193
+ contactId: "c2",
194
+ type: "slack",
195
+ address: "old-address",
196
+ externalUserId: "U12345ABC",
197
+ status: "active",
198
+ });
199
+
200
+ migrateContactChannelsRenormalizeAddresses(db);
201
+
202
+ const rows = raw
203
+ .prepare("SELECT * FROM contact_channels ORDER BY id")
204
+ .all() as ChannelRow[];
205
+ expect(rows).toHaveLength(1);
206
+ expect(rows[0].id).toBe("normalizer");
207
+ expect(rows[0].address).toBe("U12345ABC");
208
+ });
209
+
210
+ test("idempotent — safe to run twice", () => {
211
+ const db = createTestDb();
212
+ bootstrap(db);
213
+ const raw = getSqliteFrom(db);
214
+
215
+ insertContact(raw, "c1");
216
+ insertChannel(raw, {
217
+ id: "ch1",
218
+ contactId: "c1",
219
+ type: "slack",
220
+ address: "u12345abc",
221
+ externalUserId: "U12345ABC",
222
+ status: "active",
223
+ });
224
+
225
+ migrateContactChannelsRenormalizeAddresses(db);
226
+ migrateContactChannelsRenormalizeAddresses(db);
227
+
228
+ const rows = raw
229
+ .prepare("SELECT * FROM contact_channels")
230
+ .all() as ChannelRow[];
231
+ expect(rows).toHaveLength(1);
232
+ expect(rows[0].address).toBe("U12345ABC");
233
+ });
234
+
235
+ test("does not overwrite canonical E.164 phone address with raw external_user_id", () => {
236
+ const db = createTestDb();
237
+ bootstrap(db);
238
+ const raw = getSqliteFrom(db);
239
+
240
+ insertContact(raw, "c1");
241
+ // Phone channel whose address was canonicalized to E.164 (+1 prefix)
242
+ // but external_user_id still holds the raw 10-digit number.
243
+ insertChannel(raw, {
244
+ id: "ch1",
245
+ contactId: "c1",
246
+ type: "phone",
247
+ // generic-examples:ignore-next-line — reason: testing E.164 canonicalization preservation
248
+ address: "+15550101234",
249
+ // generic-examples:ignore-next-line — reason: testing raw 10-digit phone before E.164 normalization
250
+ externalUserId: "5550101234",
251
+ status: "active",
252
+ });
253
+
254
+ migrateContactChannelsRenormalizeAddresses(db);
255
+
256
+ const rows = raw
257
+ .prepare("SELECT * FROM contact_channels")
258
+ .all() as ChannelRow[];
259
+ expect(rows).toHaveLength(1);
260
+ // generic-examples:ignore-next-line — reason: verifying E.164 address preserved
261
+ expect(rows[0].address).toBe("+15550101234");
262
+ });
263
+
264
+ test("does not overwrite canonical WhatsApp address with raw external_user_id", () => {
265
+ const db = createTestDb();
266
+ bootstrap(db);
267
+ const raw = getSqliteFrom(db);
268
+
269
+ insertContact(raw, "c1");
270
+ insertChannel(raw, {
271
+ id: "ch1",
272
+ contactId: "c1",
273
+ type: "whatsapp",
274
+ address: "+447911123456",
275
+ externalUserId: "447911123456",
276
+ status: "active",
277
+ });
278
+
279
+ migrateContactChannelsRenormalizeAddresses(db);
280
+
281
+ const rows = raw
282
+ .prepare("SELECT * FROM contact_channels")
283
+ .all() as ChannelRow[];
284
+ expect(rows).toHaveLength(1);
285
+ expect(rows[0].address).toBe("+447911123456");
286
+ });
287
+
288
+ test("no-op when address already matches external_user_id", () => {
289
+ const db = createTestDb();
290
+ bootstrap(db);
291
+ const raw = getSqliteFrom(db);
292
+
293
+ insertContact(raw, "c1");
294
+ insertChannel(raw, {
295
+ id: "ch1",
296
+ contactId: "c1",
297
+ type: "slack",
298
+ address: "U12345ABC",
299
+ externalUserId: "U12345ABC",
300
+ status: "active",
301
+ });
302
+
303
+ migrateContactChannelsRenormalizeAddresses(db);
304
+
305
+ const rows = raw
306
+ .prepare("SELECT * FROM contact_channels")
307
+ .all() as ChannelRow[];
308
+ expect(rows).toHaveLength(1);
309
+ expect(rows[0].address).toBe("U12345ABC");
310
+ });
311
+
312
+ test("no-op when external_user_id column is absent (re-run after migration 294)", () => {
313
+ const db = createTestDb();
314
+ bootstrap(db);
315
+ const raw = getSqliteFrom(db);
316
+
317
+ insertContact(raw, "c1");
318
+ insertChannel(raw, {
319
+ id: "ch1",
320
+ contactId: "c1",
321
+ type: "slack",
322
+ address: "u12345abc",
323
+ externalUserId: "U12345ABC",
324
+ status: "active",
325
+ });
326
+
327
+ // Simulate a later startup where migration 294 has already dropped the
328
+ // index and column. Migration steps re-run on every startup, so this must
329
+ // tolerate the dropped column rather than throwing "no such column".
330
+ raw.run("DROP INDEX IF EXISTS idx_contact_channels_type_ext_user");
331
+ raw.run("ALTER TABLE contact_channels DROP COLUMN external_user_id");
332
+
333
+ expect(() => migrateContactChannelsRenormalizeAddresses(db)).not.toThrow();
334
+
335
+ const rows = raw
336
+ .prepare("SELECT id, address FROM contact_channels")
337
+ .all() as { id: string; address: string }[];
338
+ expect(rows).toHaveLength(1);
339
+ expect(rows[0].address).toBe("u12345abc");
340
+ });
341
+ });
@@ -0,0 +1,52 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { describe, expect, test } from "bun:test";
3
+
4
+ import { drizzle } from "drizzle-orm/bun-sqlite";
5
+
6
+ import * as schema from "../../schema.js";
7
+ import { type MigrationStep, runMigrationSteps } from "../run-migrations.js";
8
+
9
+ function createTestDb() {
10
+ const sqlite = new Database(":memory:");
11
+ sqlite.exec("PRAGMA journal_mode=WAL");
12
+ sqlite.exec("PRAGMA foreign_keys = ON");
13
+ return drizzle(sqlite, { schema });
14
+ }
15
+
16
+ describe("runMigrationSteps — checkpointing", () => {
17
+ // Skipped: documents the post-checkpointing contract and fails against the
18
+ // current behavior, which re-runs every forward step on every boot. Promote
19
+ // to `test` when true checkpointing of initial migrations lands.
20
+ test.skip("does not re-execute a step that was already applied on a prior run", () => {
21
+ /**
22
+ * Booting an already-migrated database must not re-run forward migration
23
+ * steps. With true checkpointing each step's body executes at most once
24
+ * across boots; without it every step re-runs on every startup — the
25
+ * ~200-step re-probe that floors daemon startup at ~30s.
26
+ */
27
+
28
+ // GIVEN three dummy migration steps that count how often their body runs
29
+ const calls = { a: 0, b: 0, c: 0 };
30
+ const steps: MigrationStep[] = [
31
+ function dummyMigrationA() {
32
+ calls.a++;
33
+ },
34
+ function dummyMigrationB() {
35
+ calls.b++;
36
+ },
37
+ function dummyMigrationC() {
38
+ calls.c++;
39
+ },
40
+ ];
41
+
42
+ // AND a database that has already been migrated once
43
+ const db = createTestDb();
44
+ runMigrationSteps(db, steps);
45
+
46
+ // WHEN the same steps run again against the already-migrated database
47
+ runMigrationSteps(db, steps);
48
+
49
+ // THEN no step body executes a second time
50
+ expect(calls).toEqual({ a: 1, b: 1, c: 1 });
51
+ });
52
+ });
@@ -282,6 +282,12 @@ export { migrateConversationOriginChannelIndex } from "./287-conversation-origin
282
282
  export { migrateBackfillOriginChannelFromBindings } from "./288-backfill-origin-channel-from-bindings.js";
283
283
  export { migrateContactChannelsUniqueExtUser } from "./289-contact-channels-unique-ext-user.js";
284
284
  export { migrateScheduleCapabilities } from "./290-schedule-capabilities.js";
285
+ export { migrateContactChannelsRenormalizeAddresses } from "./291-contact-channels-renormalize-addresses.js";
286
+ export { migrateScheduleDefaultNoReuseConversation } from "./292-schedule-default-no-reuse-conversation.js";
287
+ export { migrateWorkflowJournalLeafTokens } from "./293-workflow-journal-leaf-tokens.js";
288
+ export { migrateDropExternalUserId } from "./294-drop-external-user-id.js";
289
+ export { dropApprovalPromptTsTrackerTable } from "./295-drop-approval-prompt-ts-tracker.js";
290
+ export { migrateRewriteBalancedEconomyProfilePins } from "./296-rewrite-balanced-economy-profile-pins.js";
285
291
  export {
286
292
  MIGRATION_REGISTRY,
287
293
  type MigrationRegistryEntry,
@@ -0,0 +1,41 @@
1
+ import { getLogger } from "../../util/logger.js";
2
+ import type { DrizzleDb } from "../db-connection.js";
3
+
4
+ const log = getLogger("db-init");
5
+
6
+ /** A single forward migration step, identified for logging by its `.name`. */
7
+ export type MigrationStep = (database: DrizzleDb) => void;
8
+
9
+ export interface MigrationRunResult {
10
+ /** Steps whose body threw. */
11
+ failed: string[];
12
+ }
13
+
14
+ /**
15
+ * Run the ordered list of forward migration steps against the database.
16
+ *
17
+ * Individual step failures are caught and logged so one broken migration does
18
+ * not prevent independent later ones from succeeding.
19
+ */
20
+ export function runMigrationSteps(
21
+ database: DrizzleDb,
22
+ steps: MigrationStep[],
23
+ ): MigrationRunResult {
24
+ const failed: string[] = [];
25
+
26
+ for (const step of steps) {
27
+ try {
28
+ log.debug({ migration: step.name }, `Starting migration: ${step.name}`);
29
+ step(database);
30
+ log.debug({ migration: step.name }, `Migration succeeded: ${step.name}`);
31
+ } catch (err) {
32
+ failed.push(step.name);
33
+ log.error(
34
+ { err, migration: step.name },
35
+ `Migration failed: ${step.name}`,
36
+ );
37
+ }
38
+ }
39
+
40
+ return { failed };
41
+ }
@@ -220,7 +220,7 @@ export function validateMigrationState(
220
220
  // registry entry — these are from a newer version of the daemon.
221
221
  //
222
222
  // The memory_checkpoints table is a general-purpose key-value store also
223
- // used by non-migration subsystems (e.g., "identity:intro:text",
223
+ // used by non-migration subsystems (e.g., "empty_state:greeting:text",
224
224
  // "conversation_starters:item_count_at_last_gen"). Filter to only keys
225
225
  // that follow migration naming conventions before comparing against the
226
226
  // registry to avoid false-positive warnings.
@@ -1,7 +1,7 @@
1
1
  import { and, asc, eq, gt, or } from "drizzle-orm";
2
2
  import { v4 as uuid } from "uuid";
3
3
 
4
- import { getConfig } from "../config/loader.js";
4
+ import { getCachedShareAnalytics } from "../platform/consent-cache.js";
5
5
  import {
6
6
  ACTIVATION_AB_VARIANT,
7
7
  ACTIVATION_FUNNEL_VERSION,
@@ -58,7 +58,7 @@ function insertOnboardingEvent(event: OnboardingEvent): OnboardingEvent {
58
58
  export function recordOnboardingEvent(
59
59
  params: RecordOnboardingEventParams,
60
60
  ): OnboardingEvent | null {
61
- if (!getConfig().collectUsageData) return null;
61
+ if (!getCachedShareAnalytics()) return null;
62
62
  return insertOnboardingEvent({
63
63
  id: uuid(),
64
64
  createdAt: Date.now(),
@@ -93,7 +93,7 @@ export function recordActivationEvent(params: {
93
93
  userId?: string | null;
94
94
  abVariant?: string;
95
95
  }): OnboardingEvent | null {
96
- if (!getConfig().collectUsageData) return null;
96
+ if (!getCachedShareAnalytics()) return null;
97
97
  const createdAt = Date.now();
98
98
  return insertOnboardingEvent({
99
99
  id: uuid(),
@@ -26,7 +26,6 @@ export const contactChannels = sqliteTable(
26
26
  isPrimary: integer("is_primary", { mode: "boolean" })
27
27
  .notNull()
28
28
  .default(false),
29
- externalUserId: text("external_user_id"), // channel-native user ID (e.g., Telegram numeric ID, E.164 phone)
30
29
  externalChatId: text("external_chat_id"), // delivery/notification routing address (e.g., Telegram chat ID)
31
30
  status: text("status").notNull().default("unverified"), // 'active' | 'pending' | 'revoked' | 'blocked' | 'unverified'
32
31
  policy: text("policy").notNull().default("allow"), // 'allow' | 'deny' | 'escalate'
@@ -42,10 +41,6 @@ export const contactChannels = sqliteTable(
42
41
  createdAt: integer("created_at").notNull(),
43
42
  },
44
43
  (table) => [
45
- index("idx_contact_channels_type_ext_user").on(
46
- table.type,
47
- table.externalUserId,
48
- ),
49
44
  index("idx_contact_channels_type_ext_chat").on(
50
45
  table.type,
51
46
  table.externalChatId,