@vellumai/assistant 0.4.16 → 0.4.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (536) hide show
  1. package/Dockerfile +6 -6
  2. package/README.md +1 -2
  3. package/eslint.config.mjs +2 -2
  4. package/package.json +1 -1
  5. package/src/__tests__/access-request-decision.test.ts +128 -120
  6. package/src/__tests__/account-registry.test.ts +121 -110
  7. package/src/__tests__/active-skill-tools.test.ts +200 -172
  8. package/src/__tests__/actor-token-service.test.ts +341 -274
  9. package/src/__tests__/agent-loop-thinking.test.ts +28 -19
  10. package/src/__tests__/agent-loop.test.ts +798 -378
  11. package/src/__tests__/anthropic-provider.test.ts +405 -247
  12. package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
  13. package/src/__tests__/app-bundler.test.ts +112 -79
  14. package/src/__tests__/app-executors.test.ts +205 -178
  15. package/src/__tests__/app-git-history.test.ts +90 -73
  16. package/src/__tests__/app-git-service.test.ts +67 -53
  17. package/src/__tests__/app-open-proxy.test.ts +29 -25
  18. package/src/__tests__/approval-conversation-turn.test.ts +100 -81
  19. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
  20. package/src/__tests__/approval-message-composer.test.ts +119 -119
  21. package/src/__tests__/approval-primitive.test.ts +264 -233
  22. package/src/__tests__/approval-routes-http.test.ts +4 -3
  23. package/src/__tests__/asset-materialize-tool.test.ts +250 -178
  24. package/src/__tests__/asset-search-tool.test.ts +251 -191
  25. package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
  26. package/src/__tests__/assistant-attachments.test.ts +254 -186
  27. package/src/__tests__/assistant-event-hub.test.ts +105 -63
  28. package/src/__tests__/assistant-event.test.ts +66 -58
  29. package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
  30. package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
  31. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
  32. package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
  33. package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
  34. package/src/__tests__/attachments-store.test.ts +240 -183
  35. package/src/__tests__/attachments.test.ts +70 -62
  36. package/src/__tests__/audit-log-rotation.test.ts +50 -35
  37. package/src/__tests__/browser-fill-credential.test.ts +169 -101
  38. package/src/__tests__/browser-manager.test.ts +97 -75
  39. package/src/__tests__/browser-runtime-check.test.ts +16 -15
  40. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
  41. package/src/__tests__/browser-skill-endstate.test.ts +97 -72
  42. package/src/__tests__/bundle-scanner.test.ts +47 -22
  43. package/src/__tests__/bundled-asset.test.ts +74 -47
  44. package/src/__tests__/call-constants.test.ts +19 -19
  45. package/src/__tests__/call-controller.test.ts +1073 -751
  46. package/src/__tests__/call-conversation-messages.test.ts +90 -65
  47. package/src/__tests__/call-domain.test.ts +149 -121
  48. package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
  49. package/src/__tests__/call-pointer-messages.test.ts +213 -154
  50. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
  51. package/src/__tests__/call-recovery.test.ts +232 -212
  52. package/src/__tests__/call-routes-http.test.ts +328 -279
  53. package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
  54. package/src/__tests__/call-state-machine.test.ts +62 -51
  55. package/src/__tests__/call-state.test.ts +89 -75
  56. package/src/__tests__/call-store.test.ts +387 -316
  57. package/src/__tests__/callback-handoff-copy.test.ts +84 -82
  58. package/src/__tests__/canonical-guardian-store.test.ts +331 -280
  59. package/src/__tests__/channel-approval-routes.test.ts +1643 -1126
  60. package/src/__tests__/channel-approval.test.ts +139 -137
  61. package/src/__tests__/channel-approvals.test.ts +226 -182
  62. package/src/__tests__/channel-delivery-store.test.ts +232 -194
  63. package/src/__tests__/channel-guardian.test.ts +6 -3
  64. package/src/__tests__/channel-invite-transport.test.ts +107 -92
  65. package/src/__tests__/channel-policy.test.ts +42 -38
  66. package/src/__tests__/channel-readiness-service.test.ts +119 -102
  67. package/src/__tests__/channel-reply-delivery.test.ts +147 -118
  68. package/src/__tests__/channel-retry-sweep.test.ts +153 -110
  69. package/src/__tests__/checker.test.ts +3309 -1850
  70. package/src/__tests__/clarification-resolver.test.ts +91 -79
  71. package/src/__tests__/classifier.test.ts +64 -54
  72. package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
  73. package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
  74. package/src/__tests__/clawhub.test.ts +92 -82
  75. package/src/__tests__/cli.test.ts +30 -30
  76. package/src/__tests__/clipboard.test.ts +53 -46
  77. package/src/__tests__/commit-guarantee.test.ts +59 -52
  78. package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
  79. package/src/__tests__/compaction.benchmark.test.ts +33 -31
  80. package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
  81. package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
  82. package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
  83. package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
  84. package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
  85. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
  86. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
  87. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
  88. package/src/__tests__/computer-use-tools.test.ts +121 -98
  89. package/src/__tests__/config-schema.test.ts +443 -347
  90. package/src/__tests__/config-watcher.test.ts +96 -81
  91. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
  92. package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
  93. package/src/__tests__/conflict-policy.test.ts +151 -80
  94. package/src/__tests__/conflict-store.test.ts +203 -157
  95. package/src/__tests__/connection-policy.test.ts +89 -59
  96. package/src/__tests__/contacts-tools.test.ts +247 -178
  97. package/src/__tests__/context-memory-e2e.test.ts +306 -214
  98. package/src/__tests__/context-token-estimator.test.ts +114 -74
  99. package/src/__tests__/context-window-manager.test.ts +269 -167
  100. package/src/__tests__/contradiction-checker.test.ts +161 -135
  101. package/src/__tests__/conversation-attention-store.test.ts +350 -290
  102. package/src/__tests__/conversation-attention-telegram.test.ts +156 -114
  103. package/src/__tests__/conversation-pairing.test.ts +220 -113
  104. package/src/__tests__/conversation-routes-guardian-reply.test.ts +164 -104
  105. package/src/__tests__/conversation-routes.test.ts +71 -41
  106. package/src/__tests__/conversation-store.test.ts +390 -235
  107. package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
  108. package/src/__tests__/credential-broker-server-use.test.ts +283 -243
  109. package/src/__tests__/credential-broker.test.ts +128 -74
  110. package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
  111. package/src/__tests__/credential-metadata-store.test.ts +360 -311
  112. package/src/__tests__/credential-policy-validate.test.ts +81 -65
  113. package/src/__tests__/credential-resolve.test.ts +212 -145
  114. package/src/__tests__/credential-security-e2e.test.ts +144 -103
  115. package/src/__tests__/credential-security-invariants.test.ts +253 -208
  116. package/src/__tests__/credential-selection.test.ts +254 -146
  117. package/src/__tests__/credential-vault-unit.test.ts +531 -341
  118. package/src/__tests__/credential-vault.test.ts +761 -484
  119. package/src/__tests__/daemon-assistant-events.test.ts +91 -66
  120. package/src/__tests__/daemon-lifecycle.test.ts +258 -190
  121. package/src/__tests__/daemon-server-session-init.test.ts +257 -191
  122. package/src/__tests__/date-context.test.ts +314 -249
  123. package/src/__tests__/db-migration-rollback.test.ts +259 -130
  124. package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
  125. package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
  126. package/src/__tests__/deterministic-verification-control-plane.test.ts +183 -135
  127. package/src/__tests__/dictation-mode-detection.test.ts +77 -55
  128. package/src/__tests__/dictation-profile-store.test.ts +70 -56
  129. package/src/__tests__/dictation-text-processing.test.ts +53 -35
  130. package/src/__tests__/diff.test.ts +102 -98
  131. package/src/__tests__/domain-normalize.test.ts +54 -54
  132. package/src/__tests__/domain-policy.test.ts +71 -55
  133. package/src/__tests__/dynamic-page-surface.test.ts +31 -33
  134. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
  135. package/src/__tests__/edit-engine.test.ts +56 -56
  136. package/src/__tests__/elevenlabs-client.test.ts +117 -91
  137. package/src/__tests__/elevenlabs-config.test.ts +32 -31
  138. package/src/__tests__/email-classifier.test.ts +15 -12
  139. package/src/__tests__/email-cli.test.ts +121 -108
  140. package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
  141. package/src/__tests__/encrypted-store.test.ts +180 -154
  142. package/src/__tests__/entity-extractor.test.ts +108 -87
  143. package/src/__tests__/entity-search.test.ts +664 -258
  144. package/src/__tests__/ephemeral-permissions.test.ts +224 -188
  145. package/src/__tests__/event-bus.test.ts +81 -77
  146. package/src/__tests__/extract-email.test.ts +51 -0
  147. package/src/__tests__/file-edit-tool.test.ts +62 -44
  148. package/src/__tests__/file-ops-service.test.ts +131 -114
  149. package/src/__tests__/file-read-tool.test.ts +48 -31
  150. package/src/__tests__/file-write-tool.test.ts +43 -37
  151. package/src/__tests__/filesystem-tools.test.ts +238 -209
  152. package/src/__tests__/followup-tools.test.ts +237 -162
  153. package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
  154. package/src/__tests__/frontmatter.test.ts +96 -81
  155. package/src/__tests__/fuzzy-match-property.test.ts +75 -81
  156. package/src/__tests__/fuzzy-match.test.ts +71 -65
  157. package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
  158. package/src/__tests__/gateway-only-enforcement.test.ts +467 -369
  159. package/src/__tests__/gateway-only-guard.test.ts +54 -56
  160. package/src/__tests__/gemini-image-service.test.ts +113 -100
  161. package/src/__tests__/gemini-provider.test.ts +297 -220
  162. package/src/__tests__/get-weather.test.ts +188 -114
  163. package/src/__tests__/gmail-integration.test.ts +47 -46
  164. package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
  165. package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
  166. package/src/__tests__/guardian-action-followup-executor.test.ts +215 -151
  167. package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
  168. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
  169. package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
  170. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
  171. package/src/__tests__/guardian-action-store.test.ts +158 -109
  172. package/src/__tests__/guardian-action-sweep.test.ts +114 -100
  173. package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
  174. package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
  175. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
  176. package/src/__tests__/guardian-dispatch.test.ts +316 -256
  177. package/src/__tests__/guardian-grant-minting.test.ts +247 -178
  178. package/src/__tests__/guardian-outbound-http.test.ts +337 -209
  179. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
  180. package/src/__tests__/guardian-question-copy.test.ts +17 -17
  181. package/src/__tests__/guardian-question-mode.test.ts +134 -100
  182. package/src/__tests__/guardian-routing-invariants.test.ts +679 -613
  183. package/src/__tests__/guardian-routing-state.test.ts +256 -209
  184. package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
  185. package/src/__tests__/guardian-verification-voice-binding.test.ts +47 -41
  186. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
  187. package/src/__tests__/handle-user-message-secret-resume.test.ts +43 -21
  188. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
  189. package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
  190. package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
  191. package/src/__tests__/handlers-slack-config.test.ts +63 -54
  192. package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
  193. package/src/__tests__/handlers-telegram-config.test.ts +662 -329
  194. package/src/__tests__/handlers-twitter-config.test.ts +525 -298
  195. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +270 -195
  196. package/src/__tests__/headless-browser-interactions.test.ts +444 -280
  197. package/src/__tests__/headless-browser-navigate.test.ts +116 -79
  198. package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
  199. package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
  200. package/src/__tests__/heartbeat-service.test.ts +76 -58
  201. package/src/__tests__/history-repair-observability.test.ts +14 -14
  202. package/src/__tests__/history-repair.test.ts +171 -167
  203. package/src/__tests__/home-base-bootstrap.test.ts +30 -27
  204. package/src/__tests__/hooks-blocking.test.ts +86 -37
  205. package/src/__tests__/hooks-cli.test.ts +104 -68
  206. package/src/__tests__/hooks-config.test.ts +81 -43
  207. package/src/__tests__/hooks-discovery.test.ts +106 -96
  208. package/src/__tests__/hooks-integration.test.ts +78 -72
  209. package/src/__tests__/hooks-manager.test.ts +99 -61
  210. package/src/__tests__/hooks-runner.test.ts +94 -71
  211. package/src/__tests__/hooks-settings.test.ts +69 -64
  212. package/src/__tests__/hooks-templates.test.ts +85 -54
  213. package/src/__tests__/hooks-ts-runner.test.ts +82 -45
  214. package/src/__tests__/hooks-watch.test.ts +32 -22
  215. package/src/__tests__/host-file-edit-tool.test.ts +190 -148
  216. package/src/__tests__/host-file-read-tool.test.ts +86 -63
  217. package/src/__tests__/host-file-write-tool.test.ts +98 -64
  218. package/src/__tests__/host-shell-tool.test.ts +342 -233
  219. package/src/__tests__/inbound-invite-redemption.test.ts +194 -152
  220. package/src/__tests__/ingress-member-store.test.ts +163 -159
  221. package/src/__tests__/ingress-reconcile.test.ts +183 -142
  222. package/src/__tests__/ingress-routes-http.test.ts +441 -356
  223. package/src/__tests__/ingress-url-consistency.test.ts +125 -64
  224. package/src/__tests__/integration-status.test.ts +93 -73
  225. package/src/__tests__/intent-routing.test.ts +148 -118
  226. package/src/__tests__/invite-redemption-service.test.ts +163 -121
  227. package/src/__tests__/ipc-blob-store.test.ts +104 -91
  228. package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
  229. package/src/__tests__/ipc-contract.test.ts +24 -23
  230. package/src/__tests__/ipc-protocol.test.ts +52 -46
  231. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
  232. package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
  233. package/src/__tests__/ipc-validate.test.ts +240 -179
  234. package/src/__tests__/key-migration.test.ts +123 -90
  235. package/src/__tests__/keychain.test.ts +150 -123
  236. package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
  237. package/src/__tests__/llm-usage-store.test.ts +112 -87
  238. package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
  239. package/src/__tests__/managed-store.test.ts +411 -360
  240. package/src/__tests__/mcp-cli.test.ts +189 -123
  241. package/src/__tests__/mcp-health-check.test.ts +26 -21
  242. package/src/__tests__/media-generate-image.test.ts +122 -99
  243. package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
  244. package/src/__tests__/media-visibility-policy.test.ts +86 -38
  245. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
  246. package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
  247. package/src/__tests__/memory-query-builder.test.ts +32 -33
  248. package/src/__tests__/memory-recall-quality.test.ts +761 -407
  249. package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
  250. package/src/__tests__/memory-regressions.test.ts +3725 -2642
  251. package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
  252. package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
  253. package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
  254. package/src/__tests__/messaging-send-tool.test.ts +36 -29
  255. package/src/__tests__/migration-cli-flows.test.ts +69 -53
  256. package/src/__tests__/migration-ordering.test.ts +103 -86
  257. package/src/__tests__/mime-builder.test.ts +55 -32
  258. package/src/__tests__/mock-signup-server.test.ts +384 -246
  259. package/src/__tests__/model-intents.test.ts +61 -37
  260. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
  261. package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
  262. package/src/__tests__/non-member-access-request.test.ts +294 -249
  263. package/src/__tests__/notification-broadcaster.test.ts +99 -81
  264. package/src/__tests__/notification-decision-fallback.test.ts +223 -178
  265. package/src/__tests__/notification-decision-strategy.test.ts +375 -337
  266. package/src/__tests__/notification-deep-link.test.ts +67 -61
  267. package/src/__tests__/notification-guardian-path.test.ts +248 -206
  268. package/src/__tests__/notification-routing-intent.test.ts +166 -93
  269. package/src/__tests__/notification-telegram-adapter.test.ts +60 -46
  270. package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
  271. package/src/__tests__/notification-thread-candidates.test.ts +64 -61
  272. package/src/__tests__/oauth-callback-registry.test.ts +40 -30
  273. package/src/__tests__/oauth-connect-handler.test.ts +109 -89
  274. package/src/__tests__/oauth-scope-policy.test.ts +63 -55
  275. package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
  276. package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
  277. package/src/__tests__/onboarding-template-contract.test.ts +93 -94
  278. package/src/__tests__/openai-provider.test.ts +366 -274
  279. package/src/__tests__/pairing-concurrent.test.ts +18 -12
  280. package/src/__tests__/pairing-routes.test.ts +45 -41
  281. package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
  282. package/src/__tests__/parser.test.ts +316 -226
  283. package/src/__tests__/path-classifier.test.ts +24 -25
  284. package/src/__tests__/path-policy.test.ts +187 -147
  285. package/src/__tests__/phone.test.ts +36 -36
  286. package/src/__tests__/platform-move-helper.test.ts +48 -40
  287. package/src/__tests__/platform-socket-path.test.ts +23 -24
  288. package/src/__tests__/platform-workspace-migration.test.ts +464 -414
  289. package/src/__tests__/platform.test.ts +61 -53
  290. package/src/__tests__/playbook-execution.test.ts +397 -265
  291. package/src/__tests__/playbook-tools.test.ts +267 -196
  292. package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
  293. package/src/__tests__/pricing.test.ts +316 -136
  294. package/src/__tests__/profile-compiler.test.ts +206 -188
  295. package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
  296. package/src/__tests__/provider-error-scenarios.test.ts +212 -158
  297. package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
  298. package/src/__tests__/provider-registry-ollama.test.ts +13 -9
  299. package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
  300. package/src/__tests__/proxy-approval-callback.test.ts +180 -119
  301. package/src/__tests__/public-ingress-urls.test.ts +112 -94
  302. package/src/__tests__/qdrant-manager.test.ts +147 -98
  303. package/src/__tests__/ratelimit.test.ts +152 -82
  304. package/src/__tests__/recording-handler.test.ts +273 -151
  305. package/src/__tests__/recording-intent-fallback.test.ts +94 -75
  306. package/src/__tests__/recording-intent-handler.test.ts +422 -292
  307. package/src/__tests__/recording-intent.test.ts +578 -379
  308. package/src/__tests__/recording-state-machine.test.ts +530 -316
  309. package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
  310. package/src/__tests__/recurrence-engine.test.ts +81 -41
  311. package/src/__tests__/recurrence-types.test.ts +63 -44
  312. package/src/__tests__/relay-server.test.ts +2131 -1602
  313. package/src/__tests__/reminder-store.test.ts +158 -80
  314. package/src/__tests__/reminder.test.ts +113 -109
  315. package/src/__tests__/remote-skill-policy.test.ts +96 -72
  316. package/src/__tests__/request-file-tool.test.ts +74 -67
  317. package/src/__tests__/response-tier.test.ts +131 -74
  318. package/src/__tests__/runtime-attachment-metadata.test.ts +107 -70
  319. package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
  320. package/src/__tests__/runtime-events-sse.test.ts +67 -51
  321. package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
  322. package/src/__tests__/sandbox-host-parity.test.ts +377 -301
  323. package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
  324. package/src/__tests__/schedule-store.test.ts +268 -205
  325. package/src/__tests__/schedule-tools.test.ts +702 -524
  326. package/src/__tests__/scheduler-recurrence.test.ts +240 -130
  327. package/src/__tests__/scoped-approval-grants.test.ts +258 -168
  328. package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
  329. package/src/__tests__/script-proxy-certs.test.ts +38 -35
  330. package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
  331. package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
  332. package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
  333. package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
  334. package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
  335. package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
  336. package/src/__tests__/script-proxy-policy.test.ts +308 -153
  337. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
  338. package/src/__tests__/script-proxy-router.test.ts +111 -77
  339. package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
  340. package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
  341. package/src/__tests__/secret-allowlist.test.ts +105 -90
  342. package/src/__tests__/secret-ingress-handler.test.ts +41 -30
  343. package/src/__tests__/secret-onetime-send.test.ts +67 -50
  344. package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
  345. package/src/__tests__/secret-response-routing.test.ts +50 -41
  346. package/src/__tests__/secret-scanner-executor.test.ts +152 -111
  347. package/src/__tests__/secret-scanner.test.ts +495 -413
  348. package/src/__tests__/secure-keys.test.ts +132 -121
  349. package/src/__tests__/send-endpoint-busy.test.ts +313 -232
  350. package/src/__tests__/send-notification-tool.test.ts +43 -42
  351. package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
  352. package/src/__tests__/sequence-store.test.ts +335 -167
  353. package/src/__tests__/server-history-render.test.ts +341 -202
  354. package/src/__tests__/session-abort-tool-results.test.ts +133 -70
  355. package/src/__tests__/session-approval-overrides.test.ts +93 -91
  356. package/src/__tests__/session-confirmation-signals.test.ts +252 -160
  357. package/src/__tests__/session-conflict-gate.test.ts +775 -585
  358. package/src/__tests__/session-error.test.ts +222 -191
  359. package/src/__tests__/session-evictor.test.ts +79 -62
  360. package/src/__tests__/session-init.benchmark.test.ts +170 -108
  361. package/src/__tests__/session-load-history-repair.test.ts +273 -139
  362. package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
  363. package/src/__tests__/session-pre-run-repair.test.ts +106 -59
  364. package/src/__tests__/session-profile-injection.test.ts +198 -130
  365. package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
  366. package/src/__tests__/session-queue.test.ts +624 -321
  367. package/src/__tests__/session-runtime-assembly.test.ts +425 -329
  368. package/src/__tests__/session-runtime-workspace.test.ts +69 -61
  369. package/src/__tests__/session-skill-tools.test.ts +973 -678
  370. package/src/__tests__/session-slash-known.test.ts +185 -133
  371. package/src/__tests__/session-slash-queue.test.ts +147 -81
  372. package/src/__tests__/session-slash-unknown.test.ts +135 -90
  373. package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
  374. package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
  375. package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
  376. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
  377. package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
  378. package/src/__tests__/session-undo.test.ts +43 -30
  379. package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
  380. package/src/__tests__/session-workspace-injection.test.ts +245 -117
  381. package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
  382. package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
  383. package/src/__tests__/shell-credential-ref.test.ts +126 -90
  384. package/src/__tests__/shell-identity.test.ts +134 -111
  385. package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
  386. package/src/__tests__/shell-parser-property.test.ts +435 -288
  387. package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
  388. package/src/__tests__/size-guard.test.ts +42 -44
  389. package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
  390. package/src/__tests__/skill-feature-flags.test.ts +75 -47
  391. package/src/__tests__/skill-include-graph.test.ts +143 -148
  392. package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
  393. package/src/__tests__/skill-load-tool.test.ts +371 -199
  394. package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
  395. package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
  396. package/src/__tests__/skill-script-runner-host.test.ts +460 -250
  397. package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
  398. package/src/__tests__/skill-script-runner.test.ts +115 -74
  399. package/src/__tests__/skill-tool-factory.test.ts +140 -96
  400. package/src/__tests__/skill-tool-manifest.test.ts +306 -210
  401. package/src/__tests__/skill-version-hash.test.ts +70 -56
  402. package/src/__tests__/skills.test.ts +0 -1
  403. package/src/__tests__/slack-channel-config.test.ts +127 -84
  404. package/src/__tests__/slack-skill.test.ts +60 -47
  405. package/src/__tests__/slash-commands-catalog.test.ts +37 -31
  406. package/src/__tests__/slash-commands-parser.test.ts +71 -64
  407. package/src/__tests__/slash-commands-resolver.test.ts +143 -107
  408. package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
  409. package/src/__tests__/sms-messaging-provider.test.ts +74 -47
  410. package/src/__tests__/speaker-identification.test.ts +28 -25
  411. package/src/__tests__/starter-bundle.test.ts +27 -23
  412. package/src/__tests__/starter-task-flow.test.ts +67 -52
  413. package/src/__tests__/subagent-manager-notify.test.ts +154 -108
  414. package/src/__tests__/subagent-tools.test.ts +311 -270
  415. package/src/__tests__/subagent-types.test.ts +40 -40
  416. package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
  417. package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
  418. package/src/__tests__/swarm-orchestrator.test.ts +135 -101
  419. package/src/__tests__/swarm-plan-validator.test.ts +125 -73
  420. package/src/__tests__/swarm-recursion.test.ts +58 -46
  421. package/src/__tests__/swarm-router-planner.test.ts +99 -74
  422. package/src/__tests__/swarm-session-integration.test.ts +148 -91
  423. package/src/__tests__/swarm-tool.test.ts +65 -45
  424. package/src/__tests__/swarm-worker-backend.test.ts +59 -45
  425. package/src/__tests__/swarm-worker-runner.test.ts +133 -118
  426. package/src/__tests__/system-prompt.test.ts +290 -256
  427. package/src/__tests__/task-compiler.test.ts +176 -120
  428. package/src/__tests__/task-management-tools.test.ts +561 -456
  429. package/src/__tests__/task-memory-cleanup.test.ts +627 -362
  430. package/src/__tests__/task-runner.test.ts +117 -94
  431. package/src/__tests__/task-scheduler.test.ts +113 -84
  432. package/src/__tests__/task-tools.test.ts +349 -264
  433. package/src/__tests__/terminal-sandbox.test.ts +138 -108
  434. package/src/__tests__/terminal-tools.test.ts +350 -305
  435. package/src/__tests__/thread-seed-composer.test.ts +307 -180
  436. package/src/__tests__/tool-approval-handler.test.ts +238 -137
  437. package/src/__tests__/tool-audit-listener.test.ts +69 -69
  438. package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
  439. package/src/__tests__/tool-execution-abort-cleanup.test.ts +153 -146
  440. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
  441. package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
  442. package/src/__tests__/tool-executor-redaction.test.ts +112 -109
  443. package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
  444. package/src/__tests__/tool-executor.test.ts +1274 -674
  445. package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
  446. package/src/__tests__/tool-metrics-listener.test.ts +97 -85
  447. package/src/__tests__/tool-notification-listener.test.ts +42 -25
  448. package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
  449. package/src/__tests__/tool-policy.test.ts +44 -25
  450. package/src/__tests__/tool-profiling-listener.test.ts +99 -93
  451. package/src/__tests__/tool-result-truncation.test.ts +5 -4
  452. package/src/__tests__/tool-trace-listener.test.ts +131 -111
  453. package/src/__tests__/top-level-renderer.test.ts +62 -58
  454. package/src/__tests__/top-level-scanner.test.ts +68 -64
  455. package/src/__tests__/trace-emitter.test.ts +56 -56
  456. package/src/__tests__/trust-context-guards.test.ts +65 -65
  457. package/src/__tests__/trust-store.test.ts +1239 -806
  458. package/src/__tests__/trusted-contact-approval-notifier.test.ts +339 -275
  459. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +484 -373
  460. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +264 -241
  461. package/src/__tests__/trusted-contact-multichannel.test.ts +182 -142
  462. package/src/__tests__/trusted-contact-verification.test.ts +251 -231
  463. package/src/__tests__/turn-commit.test.ts +259 -200
  464. package/src/__tests__/twilio-config.test.ts +49 -41
  465. package/src/__tests__/twilio-provider.test.ts +140 -126
  466. package/src/__tests__/twilio-rest.test.ts +22 -18
  467. package/src/__tests__/twilio-routes-elevenlabs.test.ts +188 -162
  468. package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
  469. package/src/__tests__/twilio-routes.test.ts +389 -281
  470. package/src/__tests__/twitter-auth-handler.test.ts +184 -139
  471. package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
  472. package/src/__tests__/twitter-cli-routing.test.ts +146 -99
  473. package/src/__tests__/twitter-oauth-client.test.ts +82 -65
  474. package/src/__tests__/update-bulletin-format.test.ts +69 -66
  475. package/src/__tests__/update-bulletin-state.test.ts +66 -60
  476. package/src/__tests__/update-bulletin.test.ts +150 -114
  477. package/src/__tests__/update-template-contract.test.ts +15 -10
  478. package/src/__tests__/url-safety.test.ts +288 -265
  479. package/src/__tests__/user-reference.test.ts +32 -32
  480. package/src/__tests__/view-image-tool.test.ts +118 -96
  481. package/src/__tests__/voice-invite-redemption.test.ts +111 -106
  482. package/src/__tests__/voice-quality.test.ts +117 -102
  483. package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
  484. package/src/__tests__/voice-session-bridge.test.ts +351 -216
  485. package/src/__tests__/weather-skill-regression.test.ts +170 -120
  486. package/src/__tests__/web-fetch.test.ts +664 -526
  487. package/src/__tests__/web-search.test.ts +379 -213
  488. package/src/__tests__/work-item-output.test.ts +90 -53
  489. package/src/__tests__/workspace-git-service.test.ts +437 -356
  490. package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
  491. package/src/__tests__/workspace-lifecycle.test.ts +98 -64
  492. package/src/__tests__/workspace-policy.test.ts +139 -71
  493. package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
  494. package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
  495. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +44 -4
  496. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
  497. package/src/config/bundled-skills/messaging/SKILL.md +9 -7
  498. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
  499. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
  500. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +11 -7
  501. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
  502. package/src/config/bundled-tool-registry.ts +2 -0
  503. package/src/config/env.ts +38 -29
  504. package/src/daemon/handlers/skills.ts +18 -10
  505. package/src/daemon/ipc-contract/messages.ts +1 -0
  506. package/src/daemon/ipc-contract/surfaces.ts +7 -1
  507. package/src/daemon/session-agent-loop-handlers.ts +5 -0
  508. package/src/daemon/session-agent-loop.ts +1 -1
  509. package/src/daemon/session-process.ts +1 -1
  510. package/src/daemon/session-surfaces.ts +42 -2
  511. package/src/memory/db-connection.ts +16 -10
  512. package/src/messaging/providers/gmail/adapter.ts +10 -3
  513. package/src/messaging/providers/gmail/client.ts +280 -72
  514. package/src/runtime/auth/__tests__/context.test.ts +75 -65
  515. package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
  516. package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
  517. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
  518. package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
  519. package/src/runtime/auth/__tests__/policy.test.ts +9 -9
  520. package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
  521. package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
  522. package/src/runtime/auth/__tests__/subject.test.ts +54 -54
  523. package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
  524. package/src/runtime/auth/scopes.ts +3 -0
  525. package/src/runtime/auth/token-service.ts +78 -48
  526. package/src/runtime/auth/types.ts +2 -1
  527. package/src/runtime/http-server.ts +2 -1
  528. package/src/security/secure-keys.ts +103 -53
  529. package/src/sequence/reply-matcher.ts +10 -6
  530. package/src/skills/frontmatter.ts +9 -6
  531. package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
  532. package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
  533. package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
  534. package/src/tools/ui-surface/definitions.ts +2 -1
  535. package/src/util/platform.ts +0 -12
  536. package/docs/architecture/http-token-refresh.md +0 -274
@@ -11,135 +11,146 @@
11
11
  * 4. activated — when the trusted contact successfully verifies
12
12
  * 5. denied — when the guardian denies the request
13
13
  */
14
- import { mkdtempSync, rmSync } from 'node:fs';
15
- import { tmpdir } from 'node:os';
16
- import { join } from 'node:path';
17
-
18
- import { afterAll, beforeEach, describe, expect, mock, test } from 'bun:test';
14
+ import { mkdtempSync, rmSync } from "node:fs";
15
+ import { tmpdir } from "node:os";
16
+ import { join } from "node:path";
17
+ import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
19
18
 
20
19
  // ---------------------------------------------------------------------------
21
20
  // Test isolation: in-memory SQLite via temp directory
22
21
  // ---------------------------------------------------------------------------
23
22
 
24
- const testDir = mkdtempSync(join(tmpdir(), 'trusted-contact-lifecycle-notif-'));
23
+ const testDir = mkdtempSync(join(tmpdir(), "trusted-contact-lifecycle-notif-"));
25
24
 
26
- mock.module('../util/platform.js', () => ({
25
+ mock.module("../util/platform.js", () => ({
27
26
  getRootDir: () => testDir,
28
27
  getDataDir: () => testDir,
29
- isMacOS: () => process.platform === 'darwin',
30
- isLinux: () => process.platform === 'linux',
31
- isWindows: () => process.platform === 'win32',
32
- getSocketPath: () => join(testDir, 'test.sock'),
33
- getPidPath: () => join(testDir, 'test.pid'),
34
- getDbPath: () => join(testDir, 'test.db'),
35
- getLogPath: () => join(testDir, 'test.log'),
28
+ isMacOS: () => process.platform === "darwin",
29
+ isLinux: () => process.platform === "linux",
30
+ isWindows: () => process.platform === "win32",
31
+ getSocketPath: () => join(testDir, "test.sock"),
32
+ getPidPath: () => join(testDir, "test.pid"),
33
+ getDbPath: () => join(testDir, "test.db"),
34
+ getLogPath: () => join(testDir, "test.log"),
36
35
  ensureDataDir: () => {},
37
- readHttpToken: () => 'test-bearer-token',
36
+ readHttpToken: () => "test-bearer-token",
38
37
  }));
39
38
 
40
- mock.module('../util/logger.js', () => ({
41
- getLogger: () => new Proxy({} as Record<string, unknown>, {
42
- get: () => () => {},
43
- }),
39
+ mock.module("../util/logger.js", () => ({
40
+ getLogger: () =>
41
+ new Proxy({} as Record<string, unknown>, {
42
+ get: () => () => {},
43
+ }),
44
44
  }));
45
45
 
46
46
  // Mock security check to always pass
47
- mock.module('../security/secret-ingress.js', () => ({
47
+ mock.module("../security/secret-ingress.js", () => ({
48
48
  checkIngressForSecrets: () => ({ blocked: false }),
49
49
  }));
50
50
 
51
- mock.module('../config/env.js', () => ({
52
- getGatewayInternalBaseUrl: () => 'http://127.0.0.1:7830',
51
+ mock.module("../config/env.js", () => ({
52
+ isHttpAuthDisabled: () => true,
53
+ getGatewayInternalBaseUrl: () => "http://127.0.0.1:7830",
53
54
  }));
54
55
 
55
56
  // Track emitNotificationSignal calls
56
57
  const emitSignalCalls: Array<Record<string, unknown>> = [];
57
- mock.module('../notifications/emit-signal.js', () => ({
58
+ mock.module("../notifications/emit-signal.js", () => ({
58
59
  emitNotificationSignal: async (params: Record<string, unknown>) => {
59
60
  emitSignalCalls.push(params);
60
61
  return {
61
- signalId: 'mock-signal-id',
62
+ signalId: "mock-signal-id",
62
63
  deduplicated: false,
63
64
  dispatched: true,
64
- reason: 'mock',
65
+ reason: "mock",
65
66
  deliveryResults: [],
66
67
  };
67
68
  },
68
69
  }));
69
70
 
70
71
  // Track deliverChannelReply calls
71
- const deliverReplyCalls: Array<{ url: string; payload: Record<string, unknown> }> = [];
72
- mock.module('../runtime/gateway-client.js', () => ({
73
- deliverChannelReply: async (url: string, payload: Record<string, unknown>) => {
72
+ const deliverReplyCalls: Array<{
73
+ url: string;
74
+ payload: Record<string, unknown>;
75
+ }> = [];
76
+ mock.module("../runtime/gateway-client.js", () => ({
77
+ deliverChannelReply: async (
78
+ url: string,
79
+ payload: Record<string, unknown>,
80
+ ) => {
74
81
  deliverReplyCalls.push({ url, payload });
75
82
  },
76
83
  }));
77
84
 
78
85
  // Mock the approval conversation / copy generators so they return canned text.
79
- mock.module('../runtime/approval-message-composer.js', () => ({
80
- composeApprovalMessage: () => 'mock approval message',
81
- composeApprovalMessageGenerative: async () => 'mock generative message',
86
+ mock.module("../runtime/approval-message-composer.js", () => ({
87
+ composeApprovalMessage: () => "mock approval message",
88
+ composeApprovalMessageGenerative: async () => "mock generative message",
82
89
  }));
83
90
 
84
- import { getResolver } from '../approvals/guardian-request-resolvers.js';
91
+ import { getResolver } from "../approvals/guardian-request-resolvers.js";
85
92
  import {
86
93
  createApprovalRequest,
87
94
  createBinding,
88
- } from '../memory/channel-guardian-store.js';
89
- import { getDb, initializeDb, resetDb } from '../memory/db.js';
90
- import { findMember, upsertMember } from '../memory/ingress-member-store.js';
91
- import {
92
- createOutboundSession,
93
- } from '../runtime/channel-guardian-service.js';
94
- import { handleChannelInbound } from '../runtime/routes/channel-routes.js';
95
+ } from "../memory/channel-guardian-store.js";
96
+ import { getDb, initializeDb, resetDb } from "../memory/db.js";
97
+ import { findMember, upsertMember } from "../memory/ingress-member-store.js";
98
+ import { createOutboundSession } from "../runtime/channel-guardian-service.js";
99
+ import { handleChannelInbound } from "../runtime/routes/channel-routes.js";
95
100
 
96
101
  initializeDb();
97
102
 
98
103
  afterAll(() => {
99
104
  resetDb();
100
- try { rmSync(testDir, { recursive: true }); } catch { /* best effort */ }
105
+ try {
106
+ rmSync(testDir, { recursive: true });
107
+ } catch {
108
+ /* best effort */
109
+ }
101
110
  });
102
111
 
103
112
  // ---------------------------------------------------------------------------
104
113
  // Helpers
105
114
  // ---------------------------------------------------------------------------
106
115
 
107
- const TEST_BEARER_TOKEN = 'test-token';
116
+ const TEST_BEARER_TOKEN = "test-token";
108
117
  const GUARDIAN_APPROVAL_TTL_MS = 5 * 60 * 1000;
109
118
 
110
119
  function resetState(): void {
111
120
  const db = getDb();
112
- db.run('DELETE FROM channel_guardian_approval_requests');
113
- db.run('DELETE FROM channel_guardian_bindings');
114
- db.run('DELETE FROM channel_guardian_verification_challenges');
115
- db.run('DELETE FROM channel_guardian_rate_limits');
116
- db.run('DELETE FROM channel_inbound_events');
117
- db.run('DELETE FROM conversations');
118
- db.run('DELETE FROM notification_events');
119
- db.run('DELETE FROM assistant_ingress_members');
121
+ db.run("DELETE FROM channel_guardian_approval_requests");
122
+ db.run("DELETE FROM channel_guardian_bindings");
123
+ db.run("DELETE FROM channel_guardian_verification_challenges");
124
+ db.run("DELETE FROM channel_guardian_rate_limits");
125
+ db.run("DELETE FROM channel_inbound_events");
126
+ db.run("DELETE FROM conversations");
127
+ db.run("DELETE FROM notification_events");
128
+ db.run("DELETE FROM assistant_ingress_members");
120
129
  emitSignalCalls.length = 0;
121
130
  deliverReplyCalls.length = 0;
122
131
  }
123
132
 
124
133
  function buildInboundRequest(overrides: Record<string, unknown> = {}): Request {
125
134
  const body: Record<string, unknown> = {
126
- sourceChannel: 'telegram',
127
- interface: 'telegram',
128
- conversationExternalId: 'chat-123',
129
- externalMessageId: `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
130
- content: 'Hello',
131
- actorExternalId: 'requester-user-456',
132
- actorDisplayName: 'Alice Requester',
133
- actorUsername: 'alice_req',
134
- replyCallbackUrl: 'http://localhost:7830/deliver/telegram',
135
+ sourceChannel: "telegram",
136
+ interface: "telegram",
137
+ conversationExternalId: "chat-123",
138
+ externalMessageId: `msg-${Date.now()}-${Math.random()
139
+ .toString(36)
140
+ .slice(2, 8)}`,
141
+ content: "Hello",
142
+ actorExternalId: "requester-user-456",
143
+ actorDisplayName: "Alice Requester",
144
+ actorUsername: "alice_req",
145
+ replyCallbackUrl: "http://localhost:7830/deliver/telegram",
135
146
  ...overrides,
136
147
  };
137
148
 
138
- return new Request('http://localhost:8080/channels/inbound', {
139
- method: 'POST',
149
+ return new Request("http://localhost:8080/channels/inbound", {
150
+ method: "POST",
140
151
  headers: {
141
- 'Content-Type': 'application/json',
142
- 'X-Gateway-Origin': TEST_BEARER_TOKEN,
152
+ "Content-Type": "application/json",
153
+ "X-Gateway-Origin": TEST_BEARER_TOKEN,
143
154
  },
144
155
  body: JSON.stringify(body),
145
156
  });
@@ -149,27 +160,27 @@ function buildInboundRequest(overrides: Record<string, unknown> = {}): Request {
149
160
  // Tests: Guardian decision signals (approve/deny)
150
161
  // ---------------------------------------------------------------------------
151
162
 
152
- describe('trusted contact lifecycle notification signals', () => {
163
+ describe("trusted contact lifecycle notification signals", () => {
153
164
  beforeEach(() => {
154
165
  resetState();
155
166
  });
156
167
 
157
- test('guardian deny emits guardian_decision and denied signals', async () => {
168
+ test("guardian deny emits guardian_decision and denied signals", async () => {
158
169
  // Set up guardian binding and member record (guardians must pass ACL)
159
170
  createBinding({
160
- assistantId: 'self',
161
- channel: 'telegram',
162
- guardianExternalUserId: 'guardian-user-789',
163
- guardianDeliveryChatId: 'guardian-chat-789',
164
- guardianPrincipalId: 'guardian-user-789',
171
+ assistantId: "self",
172
+ channel: "telegram",
173
+ guardianExternalUserId: "guardian-user-789",
174
+ guardianDeliveryChatId: "guardian-chat-789",
175
+ guardianPrincipalId: "guardian-user-789",
165
176
  });
166
177
  upsertMember({
167
- assistantId: 'self',
168
- sourceChannel: 'telegram',
169
- externalUserId: 'guardian-user-789',
170
- externalChatId: 'guardian-chat-789',
171
- status: 'active',
172
- policy: 'allow',
178
+ assistantId: "self",
179
+ sourceChannel: "telegram",
180
+ externalUserId: "guardian-user-789",
181
+ externalChatId: "guardian-chat-789",
182
+ status: "active",
183
+ policy: "allow",
173
184
  });
174
185
 
175
186
  const testRequestId = `req-deny-${Date.now()}`;
@@ -178,25 +189,25 @@ describe('trusted contact lifecycle notification signals', () => {
178
189
  const _approval = createApprovalRequest({
179
190
  runId: `ingress-access-request-${Date.now()}`,
180
191
  requestId: testRequestId,
181
- conversationId: 'access-req-telegram-requester-user-456',
182
- assistantId: 'self',
183
- channel: 'telegram',
184
- requesterExternalUserId: 'requester-user-456',
185
- requesterChatId: 'requester-chat-456',
186
- guardianExternalUserId: 'guardian-user-789',
187
- guardianChatId: 'guardian-chat-789',
188
- toolName: 'ingress_access_request',
189
- riskLevel: 'access_request',
190
- reason: 'Alice is requesting access',
192
+ conversationId: "access-req-telegram-requester-user-456",
193
+ assistantId: "self",
194
+ channel: "telegram",
195
+ requesterExternalUserId: "requester-user-456",
196
+ requesterChatId: "requester-chat-456",
197
+ guardianExternalUserId: "guardian-user-789",
198
+ guardianChatId: "guardian-chat-789",
199
+ toolName: "ingress_access_request",
200
+ riskLevel: "access_request",
201
+ reason: "Alice is requesting access",
191
202
  expiresAt: Date.now() + GUARDIAN_APPROVAL_TTL_MS,
192
203
  });
193
204
 
194
205
  // Guardian denies via callback button
195
206
  const guardianReq = buildInboundRequest({
196
- conversationExternalId: 'guardian-chat-789',
197
- actorExternalId: 'guardian-user-789',
198
- actorDisplayName: 'Guardian',
199
- content: '',
207
+ conversationExternalId: "guardian-chat-789",
208
+ actorExternalId: "guardian-user-789",
209
+ actorDisplayName: "Guardian",
210
+ content: "",
200
211
  callbackData: `apr:${testRequestId}:reject`,
201
212
  });
202
213
 
@@ -205,47 +216,52 @@ describe('trusted contact lifecycle notification signals', () => {
205
216
  // Should emit guardian_decision and denied signals
206
217
 
207
218
  const guardianDecisionSignals = emitSignalCalls.filter(
208
- (c) => c.sourceEventName === 'ingress.trusted_contact.guardian_decision',
219
+ (c) => c.sourceEventName === "ingress.trusted_contact.guardian_decision",
209
220
  );
210
221
  const deniedSignals = emitSignalCalls.filter(
211
- (c) => c.sourceEventName === 'ingress.trusted_contact.denied',
222
+ (c) => c.sourceEventName === "ingress.trusted_contact.denied",
212
223
  );
213
224
 
214
225
  expect(guardianDecisionSignals.length).toBe(1);
215
226
  expect(deniedSignals.length).toBe(1);
216
227
 
217
228
  // Verify guardian_decision payload
218
- const gdPayload = guardianDecisionSignals[0].contextPayload as Record<string, unknown>;
219
- expect(gdPayload.decision).toBe('denied');
220
- expect(gdPayload.requesterExternalUserId).toBe('requester-user-456');
221
- expect(gdPayload.decidedByExternalUserId).toBe('guardian-user-789');
229
+ const gdPayload = guardianDecisionSignals[0].contextPayload as Record<
230
+ string,
231
+ unknown
232
+ >;
233
+ expect(gdPayload.decision).toBe("denied");
234
+ expect(gdPayload.requesterExternalUserId).toBe("requester-user-456");
235
+ expect(gdPayload.decidedByExternalUserId).toBe("guardian-user-789");
222
236
 
223
237
  // Verify denied payload
224
238
  const dPayload = deniedSignals[0].contextPayload as Record<string, unknown>;
225
- expect(dPayload.decision).toBe('denied');
226
- expect(dPayload.requesterExternalUserId).toBe('requester-user-456');
239
+ expect(dPayload.decision).toBe("denied");
240
+ expect(dPayload.requesterExternalUserId).toBe("requester-user-456");
227
241
 
228
242
  // Verify deduplication keys are distinct
229
- expect(guardianDecisionSignals[0].dedupeKey).toContain('trusted-contact:guardian-decision:');
230
- expect(deniedSignals[0].dedupeKey).toContain('trusted-contact:denied:');
243
+ expect(guardianDecisionSignals[0].dedupeKey).toContain(
244
+ "trusted-contact:guardian-decision:",
245
+ );
246
+ expect(deniedSignals[0].dedupeKey).toContain("trusted-contact:denied:");
231
247
  });
232
248
 
233
- test('guardian approve emits guardian_decision and verification_sent signals', async () => {
249
+ test("guardian approve emits guardian_decision and verification_sent signals", async () => {
234
250
  // Set up guardian binding and member record (guardians must pass ACL)
235
251
  createBinding({
236
- assistantId: 'self',
237
- channel: 'telegram',
238
- guardianExternalUserId: 'guardian-user-789',
239
- guardianDeliveryChatId: 'guardian-chat-789',
240
- guardianPrincipalId: 'guardian-user-789',
252
+ assistantId: "self",
253
+ channel: "telegram",
254
+ guardianExternalUserId: "guardian-user-789",
255
+ guardianDeliveryChatId: "guardian-chat-789",
256
+ guardianPrincipalId: "guardian-user-789",
241
257
  });
242
258
  upsertMember({
243
- assistantId: 'self',
244
- sourceChannel: 'telegram',
245
- externalUserId: 'guardian-user-789',
246
- externalChatId: 'guardian-chat-789',
247
- status: 'active',
248
- policy: 'allow',
259
+ assistantId: "self",
260
+ sourceChannel: "telegram",
261
+ externalUserId: "guardian-user-789",
262
+ externalChatId: "guardian-chat-789",
263
+ status: "active",
264
+ policy: "allow",
249
265
  });
250
266
 
251
267
  const testRequestId = `req-approve-${Date.now()}`;
@@ -254,25 +270,25 @@ describe('trusted contact lifecycle notification signals', () => {
254
270
  const _approval = createApprovalRequest({
255
271
  runId: `ingress-access-request-${Date.now()}`,
256
272
  requestId: testRequestId,
257
- conversationId: 'access-req-telegram-requester-user-456',
258
- assistantId: 'self',
259
- channel: 'telegram',
260
- requesterExternalUserId: 'requester-user-456',
261
- requesterChatId: 'requester-chat-456',
262
- guardianExternalUserId: 'guardian-user-789',
263
- guardianChatId: 'guardian-chat-789',
264
- toolName: 'ingress_access_request',
265
- riskLevel: 'access_request',
266
- reason: 'Alice is requesting access',
273
+ conversationId: "access-req-telegram-requester-user-456",
274
+ assistantId: "self",
275
+ channel: "telegram",
276
+ requesterExternalUserId: "requester-user-456",
277
+ requesterChatId: "requester-chat-456",
278
+ guardianExternalUserId: "guardian-user-789",
279
+ guardianChatId: "guardian-chat-789",
280
+ toolName: "ingress_access_request",
281
+ riskLevel: "access_request",
282
+ reason: "Alice is requesting access",
267
283
  expiresAt: Date.now() + GUARDIAN_APPROVAL_TTL_MS,
268
284
  });
269
285
 
270
286
  // Guardian approves via callback button
271
287
  const guardianReq = buildInboundRequest({
272
- conversationExternalId: 'guardian-chat-789',
273
- actorExternalId: 'guardian-user-789',
274
- actorDisplayName: 'Guardian',
275
- content: '',
288
+ conversationExternalId: "guardian-chat-789",
289
+ actorExternalId: "guardian-user-789",
290
+ actorDisplayName: "Guardian",
291
+ content: "",
276
292
  callbackData: `apr:${testRequestId}:approve_once`,
277
293
  });
278
294
 
@@ -282,10 +298,10 @@ describe('trusted contact lifecycle notification signals', () => {
282
298
  // is still pending — it would cause the notification pipeline to send a
283
299
  // premature "approved" message to the guardian's chat.
284
300
  const guardianDecisionSignals = emitSignalCalls.filter(
285
- (c) => c.sourceEventName === 'ingress.trusted_contact.guardian_decision',
301
+ (c) => c.sourceEventName === "ingress.trusted_contact.guardian_decision",
286
302
  );
287
303
  const verificationSentSignals = emitSignalCalls.filter(
288
- (c) => c.sourceEventName === 'ingress.trusted_contact.verification_sent',
304
+ (c) => c.sourceEventName === "ingress.trusted_contact.verification_sent",
289
305
  );
290
306
 
291
307
  expect(guardianDecisionSignals.length).toBe(0);
@@ -294,33 +310,35 @@ describe('trusted contact lifecycle notification signals', () => {
294
310
  // Verify verification_sent payload and that it's suppressed from delivery
295
311
  const vsSignal = verificationSentSignals[0];
296
312
  const vsPayload = vsSignal.contextPayload as Record<string, unknown>;
297
- expect(vsPayload.requesterExternalUserId).toBe('requester-user-456');
313
+ expect(vsPayload.requesterExternalUserId).toBe("requester-user-456");
298
314
  expect(vsPayload.verificationSessionId).toBeDefined();
299
- expect((vsSignal.attentionHints as Record<string, unknown>).visibleInSourceNow).toBe(true);
315
+ expect(
316
+ (vsSignal.attentionHints as Record<string, unknown>).visibleInSourceNow,
317
+ ).toBe(true);
300
318
 
301
319
  // Should NOT emit denied signal
302
320
  const deniedSignals = emitSignalCalls.filter(
303
- (c) => c.sourceEventName === 'ingress.trusted_contact.denied',
321
+ (c) => c.sourceEventName === "ingress.trusted_contact.denied",
304
322
  );
305
323
  expect(deniedSignals.length).toBe(0);
306
324
  });
307
325
 
308
- test('deduplication keys prevent duplicate signals', async () => {
326
+ test("deduplication keys prevent duplicate signals", async () => {
309
327
  // Set up guardian binding and member record (guardians must pass ACL)
310
328
  createBinding({
311
- assistantId: 'self',
312
- channel: 'telegram',
313
- guardianExternalUserId: 'guardian-user-789',
314
- guardianDeliveryChatId: 'guardian-chat-789',
315
- guardianPrincipalId: 'guardian-user-789',
329
+ assistantId: "self",
330
+ channel: "telegram",
331
+ guardianExternalUserId: "guardian-user-789",
332
+ guardianDeliveryChatId: "guardian-chat-789",
333
+ guardianPrincipalId: "guardian-user-789",
316
334
  });
317
335
  upsertMember({
318
- assistantId: 'self',
319
- sourceChannel: 'telegram',
320
- externalUserId: 'guardian-user-789',
321
- externalChatId: 'guardian-chat-789',
322
- status: 'active',
323
- policy: 'allow',
336
+ assistantId: "self",
337
+ sourceChannel: "telegram",
338
+ externalUserId: "guardian-user-789",
339
+ externalChatId: "guardian-chat-789",
340
+ status: "active",
341
+ policy: "allow",
324
342
  });
325
343
 
326
344
  const testRequestId = `req-dedup-${Date.now()}`;
@@ -328,32 +346,34 @@ describe('trusted contact lifecycle notification signals', () => {
328
346
  const approval = createApprovalRequest({
329
347
  runId: `ingress-access-request-${Date.now()}`,
330
348
  requestId: testRequestId,
331
- conversationId: 'access-req-telegram-requester-user-456',
332
- assistantId: 'self',
333
- channel: 'telegram',
334
- requesterExternalUserId: 'requester-user-456',
335
- requesterChatId: 'requester-chat-456',
336
- guardianExternalUserId: 'guardian-user-789',
337
- guardianChatId: 'guardian-chat-789',
338
- toolName: 'ingress_access_request',
339
- riskLevel: 'access_request',
340
- reason: 'Alice is requesting access',
349
+ conversationId: "access-req-telegram-requester-user-456",
350
+ assistantId: "self",
351
+ channel: "telegram",
352
+ requesterExternalUserId: "requester-user-456",
353
+ requesterChatId: "requester-chat-456",
354
+ guardianExternalUserId: "guardian-user-789",
355
+ guardianChatId: "guardian-chat-789",
356
+ toolName: "ingress_access_request",
357
+ riskLevel: "access_request",
358
+ reason: "Alice is requesting access",
341
359
  expiresAt: Date.now() + GUARDIAN_APPROVAL_TTL_MS,
342
360
  });
343
361
 
344
362
  // All guardian_decision signals include the approval ID in the dedupe key
345
363
  const guardianReq = buildInboundRequest({
346
- conversationExternalId: 'guardian-chat-789',
347
- actorExternalId: 'guardian-user-789',
348
- actorDisplayName: 'Guardian',
349
- content: '',
364
+ conversationExternalId: "guardian-chat-789",
365
+ actorExternalId: "guardian-user-789",
366
+ actorDisplayName: "Guardian",
367
+ content: "",
350
368
  callbackData: `apr:${testRequestId}:reject`,
351
369
  });
352
370
 
353
371
  await handleChannelInbound(guardianReq, undefined, TEST_BEARER_TOKEN);
354
372
 
355
373
  const signals = emitSignalCalls.filter(
356
- (c) => typeof c.dedupeKey === 'string' && (c.dedupeKey as string).includes(approval.id),
374
+ (c) =>
375
+ typeof c.dedupeKey === "string" &&
376
+ (c.dedupeKey as string).includes(approval.id),
357
377
  );
358
378
  // guardian_decision and denied — both keyed on approval.id
359
379
  expect(signals.length).toBe(2);
@@ -364,188 +384,191 @@ describe('trusted contact lifecycle notification signals', () => {
364
384
  // Tests: Activated signal (trusted contact verification success)
365
385
  // ---------------------------------------------------------------------------
366
386
 
367
- describe('trusted contact activated notification signal', () => {
387
+ describe("trusted contact activated notification signal", () => {
368
388
  beforeEach(() => {
369
389
  resetState();
370
390
  });
371
391
 
372
- test('successful trusted contact verification emits activated signal', async () => {
392
+ test("successful trusted contact verification emits activated signal", async () => {
373
393
  // Set up a guardian binding so the verification path allows bypass
374
394
  createBinding({
375
- assistantId: 'self',
376
- channel: 'telegram',
377
- guardianExternalUserId: 'guardian-user-789',
378
- guardianDeliveryChatId: 'guardian-chat-789',
379
- guardianPrincipalId: 'guardian-user-789',
395
+ assistantId: "self",
396
+ channel: "telegram",
397
+ guardianExternalUserId: "guardian-user-789",
398
+ guardianDeliveryChatId: "guardian-chat-789",
399
+ guardianPrincipalId: "guardian-user-789",
380
400
  });
381
401
 
382
402
  // Create an identity-bound outbound session (simulates M3 approval flow)
383
403
  const session = createOutboundSession({
384
- assistantId: 'self',
385
- channel: 'telegram',
386
- expectedExternalUserId: 'requester-user-456',
387
- expectedChatId: 'chat-123',
388
- identityBindingStatus: 'bound',
389
- destinationAddress: 'chat-123',
390
- verificationPurpose: 'trusted_contact',
404
+ assistantId: "self",
405
+ channel: "telegram",
406
+ expectedExternalUserId: "requester-user-456",
407
+ expectedChatId: "chat-123",
408
+ identityBindingStatus: "bound",
409
+ destinationAddress: "chat-123",
410
+ verificationPurpose: "trusted_contact",
391
411
  });
392
412
 
393
413
  // Requester enters the verification code
394
414
  const verifyReq = buildInboundRequest({
395
415
  content: session.secret,
396
- conversationExternalId: 'chat-123',
397
- actorExternalId: 'requester-user-456',
416
+ conversationExternalId: "chat-123",
417
+ actorExternalId: "requester-user-456",
398
418
  });
399
419
 
400
420
  await handleChannelInbound(verifyReq, undefined, TEST_BEARER_TOKEN);
401
421
 
402
422
  // Should emit the activated signal
403
423
  const activatedSignals = emitSignalCalls.filter(
404
- (c) => c.sourceEventName === 'ingress.trusted_contact.activated',
424
+ (c) => c.sourceEventName === "ingress.trusted_contact.activated",
405
425
  );
406
426
 
407
427
  expect(activatedSignals.length).toBe(1);
408
428
 
409
429
  // Verify payload
410
- const payload = activatedSignals[0].contextPayload as Record<string, unknown>;
411
- expect(payload.sourceChannel).toBe('telegram');
412
- expect(payload.actorExternalId).toBe('requester-user-456');
413
- expect(payload.conversationExternalId).toBe('chat-123');
430
+ const payload = activatedSignals[0].contextPayload as Record<
431
+ string,
432
+ unknown
433
+ >;
434
+ expect(payload.sourceChannel).toBe("telegram");
435
+ expect(payload.actorExternalId).toBe("requester-user-456");
436
+ expect(payload.conversationExternalId).toBe("chat-123");
414
437
 
415
438
  // Verify deduplication key includes the user identity
416
439
  const dedupeKey = activatedSignals[0].dedupeKey as string;
417
- expect(dedupeKey).toContain('trusted-contact:activated:');
418
- expect(dedupeKey).toContain('requester-user-456');
440
+ expect(dedupeKey).toContain("trusted-contact:activated:");
441
+ expect(dedupeKey).toContain("requester-user-456");
419
442
 
420
443
  // Verify attention hints indicate informational (no action required)
421
444
  const hints = activatedSignals[0].attentionHints as Record<string, unknown>;
422
445
  expect(hints.requiresAction).toBe(false);
423
- expect(hints.urgency).toBe('low');
446
+ expect(hints.urgency).toBe("low");
424
447
  });
425
448
 
426
- test('re-verification preserves an existing guardian-managed member display name', async () => {
449
+ test("re-verification preserves an existing guardian-managed member display name", async () => {
427
450
  createBinding({
428
- assistantId: 'self',
429
- channel: 'telegram',
430
- guardianExternalUserId: 'guardian-user-789',
431
- guardianDeliveryChatId: 'guardian-chat-789',
432
- guardianPrincipalId: 'guardian-user-789',
451
+ assistantId: "self",
452
+ channel: "telegram",
453
+ guardianExternalUserId: "guardian-user-789",
454
+ guardianDeliveryChatId: "guardian-chat-789",
455
+ guardianPrincipalId: "guardian-user-789",
433
456
  });
434
457
 
435
458
  upsertMember({
436
- assistantId: 'self',
437
- sourceChannel: 'telegram',
438
- externalUserId: 'requester-user-456',
439
- externalChatId: 'chat-123',
440
- status: 'revoked',
441
- policy: 'allow',
442
- displayName: 'Jeff',
459
+ assistantId: "self",
460
+ sourceChannel: "telegram",
461
+ externalUserId: "requester-user-456",
462
+ externalChatId: "chat-123",
463
+ status: "revoked",
464
+ policy: "allow",
465
+ displayName: "Jeff",
443
466
  });
444
467
 
445
468
  const session = createOutboundSession({
446
- assistantId: 'self',
447
- channel: 'telegram',
448
- expectedExternalUserId: 'requester-user-456',
449
- expectedChatId: 'chat-123',
450
- identityBindingStatus: 'bound',
451
- destinationAddress: 'chat-123',
452
- verificationPurpose: 'trusted_contact',
469
+ assistantId: "self",
470
+ channel: "telegram",
471
+ expectedExternalUserId: "requester-user-456",
472
+ expectedChatId: "chat-123",
473
+ identityBindingStatus: "bound",
474
+ destinationAddress: "chat-123",
475
+ verificationPurpose: "trusted_contact",
453
476
  });
454
477
 
455
478
  const verifyReq = buildInboundRequest({
456
479
  content: session.secret,
457
- conversationExternalId: 'chat-123',
458
- actorExternalId: 'requester-user-456',
459
- actorDisplayName: 'Noa Flaherty',
480
+ conversationExternalId: "chat-123",
481
+ actorExternalId: "requester-user-456",
482
+ actorDisplayName: "Noa Flaherty",
460
483
  });
461
484
 
462
485
  await handleChannelInbound(verifyReq, undefined, TEST_BEARER_TOKEN);
463
486
 
464
487
  const member = findMember({
465
- assistantId: 'self',
466
- sourceChannel: 'telegram',
467
- externalUserId: 'requester-user-456',
468
- externalChatId: 'chat-123',
488
+ assistantId: "self",
489
+ sourceChannel: "telegram",
490
+ externalUserId: "requester-user-456",
491
+ externalChatId: "chat-123",
469
492
  });
470
493
  expect(member).not.toBeNull();
471
- expect(member!.status).toBe('active');
472
- expect(member!.displayName).toBe('Jeff');
494
+ expect(member!.status).toBe("active");
495
+ expect(member!.displayName).toBe("Jeff");
473
496
  });
474
497
 
475
- test('guardian verification does NOT emit activated signal', async () => {
498
+ test("guardian verification does NOT emit activated signal", async () => {
476
499
  // Create an inbound challenge (guardian flow, not trusted contact)
477
- // eslint-disable-next-line @typescript-eslint/no-require-imports
478
- const { createVerificationChallenge } = require('../runtime/channel-guardian-service.js');
479
- const { secret } = createVerificationChallenge('self', 'telegram');
500
+ const { createVerificationChallenge } =
501
+ await import("../runtime/channel-guardian-service.js");
502
+ const { secret } = createVerificationChallenge("self", "telegram");
480
503
 
481
504
  // "Guardian" enters the verification code
482
505
  const verifyReq = buildInboundRequest({
483
506
  content: secret,
484
- conversationExternalId: 'guardian-chat-new',
485
- actorExternalId: 'guardian-user-new',
507
+ conversationExternalId: "guardian-chat-new",
508
+ actorExternalId: "guardian-user-new",
486
509
  });
487
510
 
488
511
  await handleChannelInbound(verifyReq, undefined, TEST_BEARER_TOKEN);
489
512
 
490
513
  // Should NOT emit the trusted_contact.activated signal
491
514
  const activatedSignals = emitSignalCalls.filter(
492
- (c) => c.sourceEventName === 'ingress.trusted_contact.activated',
515
+ (c) => c.sourceEventName === "ingress.trusted_contact.activated",
493
516
  );
494
517
  expect(activatedSignals.length).toBe(0);
495
518
  });
496
519
 
497
- test('voice access_request resolver has registered handler for access_request kind', () => {
520
+ test("voice access_request resolver has registered handler for access_request kind", () => {
498
521
  // The access_request resolver is registered during module load. When the
499
522
  // source channel is 'voice', it should directly activate the member via
500
523
  // upsertMember (no verification session). This test validates the resolver
501
524
  // is registered and accessible.
502
- const resolver = getResolver('access_request');
525
+ const resolver = getResolver("access_request");
503
526
  expect(resolver).toBeDefined();
504
- expect(resolver!.kind).toBe('access_request');
527
+ expect(resolver!.kind).toBe("access_request");
505
528
  });
506
529
 
507
- test('member is persisted BEFORE activated signal is emitted', async () => {
530
+ test("member is persisted BEFORE activated signal is emitted", async () => {
508
531
  // Set up a guardian binding
509
532
  createBinding({
510
- assistantId: 'self',
511
- channel: 'telegram',
512
- guardianExternalUserId: 'guardian-user-789',
513
- guardianDeliveryChatId: 'guardian-chat-789',
514
- guardianPrincipalId: 'guardian-user-789',
533
+ assistantId: "self",
534
+ channel: "telegram",
535
+ guardianExternalUserId: "guardian-user-789",
536
+ guardianDeliveryChatId: "guardian-chat-789",
537
+ guardianPrincipalId: "guardian-user-789",
515
538
  });
516
539
 
517
540
  const session = createOutboundSession({
518
- assistantId: 'self',
519
- channel: 'telegram',
520
- expectedExternalUserId: 'requester-user-456',
521
- expectedChatId: 'chat-123',
522
- identityBindingStatus: 'bound',
523
- destinationAddress: 'chat-123',
524
- verificationPurpose: 'trusted_contact',
541
+ assistantId: "self",
542
+ channel: "telegram",
543
+ expectedExternalUserId: "requester-user-456",
544
+ expectedChatId: "chat-123",
545
+ identityBindingStatus: "bound",
546
+ destinationAddress: "chat-123",
547
+ verificationPurpose: "trusted_contact",
525
548
  });
526
549
 
527
550
  const verifyReq = buildInboundRequest({
528
551
  content: session.secret,
529
- conversationExternalId: 'chat-123',
530
- actorExternalId: 'requester-user-456',
552
+ conversationExternalId: "chat-123",
553
+ actorExternalId: "requester-user-456",
531
554
  });
532
555
 
533
556
  await handleChannelInbound(verifyReq, undefined, TEST_BEARER_TOKEN);
534
557
 
535
558
  // The activated signal was emitted
536
559
  const activatedSignals = emitSignalCalls.filter(
537
- (c) => c.sourceEventName === 'ingress.trusted_contact.activated',
560
+ (c) => c.sourceEventName === "ingress.trusted_contact.activated",
538
561
  );
539
562
  expect(activatedSignals.length).toBe(1);
540
563
 
541
564
  // Verify the member was already persisted (the signal fires after upsertMember)
542
565
  const member = findMember({
543
- assistantId: 'self',
544
- sourceChannel: 'telegram',
545
- externalUserId: 'requester-user-456',
566
+ assistantId: "self",
567
+ sourceChannel: "telegram",
568
+ externalUserId: "requester-user-456",
546
569
  });
547
570
  expect(member).not.toBeNull();
548
- expect(member!.status).toBe('active');
549
- expect(member!.policy).toBe('allow');
571
+ expect(member!.status).toBe("active");
572
+ expect(member!.policy).toBe("allow");
550
573
  });
551
574
  });