@vellumai/assistant 0.4.17 → 0.4.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (528) hide show
  1. package/docs/runbook-trusted-contacts.md +5 -3
  2. package/eslint.config.mjs +2 -2
  3. package/package.json +1 -1
  4. package/src/__tests__/access-request-decision.test.ts +128 -120
  5. package/src/__tests__/account-registry.test.ts +121 -110
  6. package/src/__tests__/active-skill-tools.test.ts +200 -172
  7. package/src/__tests__/actor-token-service.test.ts +341 -274
  8. package/src/__tests__/agent-loop-thinking.test.ts +28 -19
  9. package/src/__tests__/agent-loop.test.ts +798 -378
  10. package/src/__tests__/anthropic-provider.test.ts +405 -247
  11. package/src/__tests__/app-builder-tool-scripts.test.ts +97 -97
  12. package/src/__tests__/app-bundler.test.ts +112 -79
  13. package/src/__tests__/app-executors.test.ts +205 -178
  14. package/src/__tests__/app-git-history.test.ts +90 -73
  15. package/src/__tests__/app-git-service.test.ts +67 -53
  16. package/src/__tests__/app-open-proxy.test.ts +29 -25
  17. package/src/__tests__/approval-conversation-turn.test.ts +100 -81
  18. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +45 -17
  19. package/src/__tests__/approval-message-composer.test.ts +119 -119
  20. package/src/__tests__/approval-primitive.test.ts +264 -233
  21. package/src/__tests__/approval-routes-http.test.ts +4 -3
  22. package/src/__tests__/asset-materialize-tool.test.ts +250 -178
  23. package/src/__tests__/asset-search-tool.test.ts +251 -191
  24. package/src/__tests__/assistant-attachment-directive.test.ts +187 -142
  25. package/src/__tests__/assistant-attachments.test.ts +254 -186
  26. package/src/__tests__/assistant-event-hub.test.ts +105 -63
  27. package/src/__tests__/assistant-event.test.ts +66 -58
  28. package/src/__tests__/assistant-events-sse-hardening.test.ts +113 -73
  29. package/src/__tests__/assistant-feature-flag-guard.test.ts +78 -52
  30. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +48 -45
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +118 -77
  32. package/src/__tests__/assistant-id-boundary-guard.test.ts +158 -104
  33. package/src/__tests__/attachments-store.test.ts +240 -183
  34. package/src/__tests__/attachments.test.ts +70 -62
  35. package/src/__tests__/audit-log-rotation.test.ts +50 -35
  36. package/src/__tests__/browser-fill-credential.test.ts +169 -101
  37. package/src/__tests__/browser-manager.test.ts +97 -75
  38. package/src/__tests__/browser-runtime-check.test.ts +16 -15
  39. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +12 -10
  40. package/src/__tests__/browser-skill-endstate.test.ts +97 -72
  41. package/src/__tests__/bundle-scanner.test.ts +47 -22
  42. package/src/__tests__/bundled-asset.test.ts +74 -47
  43. package/src/__tests__/call-constants.test.ts +19 -19
  44. package/src/__tests__/call-controller.test.ts +0 -1
  45. package/src/__tests__/call-conversation-messages.test.ts +90 -65
  46. package/src/__tests__/call-domain.test.ts +149 -121
  47. package/src/__tests__/call-pointer-message-composer.test.ts +113 -83
  48. package/src/__tests__/call-pointer-messages.test.ts +213 -154
  49. package/src/__tests__/call-pointer-no-hardcoded-copy.guard.test.ts +9 -10
  50. package/src/__tests__/call-recovery.test.ts +232 -212
  51. package/src/__tests__/call-routes-http.test.ts +0 -1
  52. package/src/__tests__/call-start-guardian-guard.test.ts +32 -30
  53. package/src/__tests__/call-state-machine.test.ts +62 -51
  54. package/src/__tests__/call-state.test.ts +89 -75
  55. package/src/__tests__/call-store.test.ts +387 -316
  56. package/src/__tests__/callback-handoff-copy.test.ts +84 -82
  57. package/src/__tests__/canonical-guardian-store.test.ts +331 -280
  58. package/src/__tests__/channel-approval-routes.test.ts +1643 -1115
  59. package/src/__tests__/channel-approval.test.ts +139 -137
  60. package/src/__tests__/channel-approvals.test.ts +7 -2
  61. package/src/__tests__/channel-delivery-store.test.ts +232 -194
  62. package/src/__tests__/channel-guardian.test.ts +5 -3
  63. package/src/__tests__/channel-invite-transport.test.ts +107 -92
  64. package/src/__tests__/channel-policy.test.ts +42 -38
  65. package/src/__tests__/channel-readiness-service.test.ts +119 -102
  66. package/src/__tests__/channel-reply-delivery.test.ts +147 -118
  67. package/src/__tests__/channel-retry-sweep.test.ts +153 -110
  68. package/src/__tests__/checker.test.ts +3309 -1850
  69. package/src/__tests__/clarification-resolver.test.ts +91 -79
  70. package/src/__tests__/classifier.test.ts +64 -54
  71. package/src/__tests__/claude-code-skill-regression.test.ts +42 -37
  72. package/src/__tests__/claude-code-tool-profiles.test.ts +31 -29
  73. package/src/__tests__/clawhub.test.ts +92 -82
  74. package/src/__tests__/cli.test.ts +30 -30
  75. package/src/__tests__/clipboard.test.ts +53 -46
  76. package/src/__tests__/commit-guarantee.test.ts +59 -52
  77. package/src/__tests__/commit-message-enrichment-service.test.ts +203 -75
  78. package/src/__tests__/compaction.benchmark.test.ts +33 -31
  79. package/src/__tests__/computer-use-session-compaction.test.ts +60 -50
  80. package/src/__tests__/computer-use-session-lifecycle.test.ts +145 -117
  81. package/src/__tests__/computer-use-session-working-dir.test.ts +62 -48
  82. package/src/__tests__/computer-use-skill-baseline.test.ts +22 -19
  83. package/src/__tests__/computer-use-skill-endstate.test.ts +45 -31
  84. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +121 -88
  85. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +65 -42
  86. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +33 -18
  87. package/src/__tests__/computer-use-tools.test.ts +121 -98
  88. package/src/__tests__/config-schema.test.ts +443 -347
  89. package/src/__tests__/config-watcher.test.ts +96 -81
  90. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +148 -133
  91. package/src/__tests__/conflict-intent-tokenization.test.ts +96 -78
  92. package/src/__tests__/conflict-policy.test.ts +151 -80
  93. package/src/__tests__/conflict-store.test.ts +203 -157
  94. package/src/__tests__/connection-policy.test.ts +89 -59
  95. package/src/__tests__/contacts-tools.test.ts +247 -178
  96. package/src/__tests__/context-memory-e2e.test.ts +306 -214
  97. package/src/__tests__/context-token-estimator.test.ts +114 -74
  98. package/src/__tests__/context-window-manager.test.ts +269 -167
  99. package/src/__tests__/contradiction-checker.test.ts +161 -135
  100. package/src/__tests__/conversation-attention-store.test.ts +350 -290
  101. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  102. package/src/__tests__/conversation-pairing.test.ts +220 -113
  103. package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
  104. package/src/__tests__/conversation-store.test.ts +390 -235
  105. package/src/__tests__/credential-broker-browser-fill.test.ts +325 -250
  106. package/src/__tests__/credential-broker-server-use.test.ts +283 -243
  107. package/src/__tests__/credential-broker.test.ts +128 -74
  108. package/src/__tests__/credential-host-pattern-match.test.ts +64 -44
  109. package/src/__tests__/credential-metadata-store.test.ts +360 -311
  110. package/src/__tests__/credential-policy-validate.test.ts +81 -65
  111. package/src/__tests__/credential-resolve.test.ts +212 -145
  112. package/src/__tests__/credential-security-e2e.test.ts +144 -103
  113. package/src/__tests__/credential-security-invariants.test.ts +253 -208
  114. package/src/__tests__/credential-selection.test.ts +254 -146
  115. package/src/__tests__/credential-vault-unit.test.ts +531 -341
  116. package/src/__tests__/credential-vault.test.ts +761 -484
  117. package/src/__tests__/daemon-assistant-events.test.ts +91 -66
  118. package/src/__tests__/daemon-lifecycle.test.ts +258 -190
  119. package/src/__tests__/daemon-server-session-init.test.ts +2 -1
  120. package/src/__tests__/date-context.test.ts +314 -249
  121. package/src/__tests__/db-migration-rollback.test.ts +259 -130
  122. package/src/__tests__/db-schedule-syntax-migration.test.ts +78 -41
  123. package/src/__tests__/delete-managed-skill-tool.test.ts +77 -53
  124. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  125. package/src/__tests__/dictation-mode-detection.test.ts +77 -55
  126. package/src/__tests__/dictation-profile-store.test.ts +70 -56
  127. package/src/__tests__/dictation-text-processing.test.ts +53 -35
  128. package/src/__tests__/diff.test.ts +102 -98
  129. package/src/__tests__/domain-normalize.test.ts +54 -54
  130. package/src/__tests__/domain-policy.test.ts +71 -55
  131. package/src/__tests__/dynamic-page-surface.test.ts +31 -33
  132. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +69 -69
  133. package/src/__tests__/edit-engine.test.ts +56 -56
  134. package/src/__tests__/elevenlabs-client.test.ts +117 -91
  135. package/src/__tests__/elevenlabs-config.test.ts +32 -31
  136. package/src/__tests__/email-classifier.test.ts +15 -12
  137. package/src/__tests__/email-cli.test.ts +121 -108
  138. package/src/__tests__/emit-signal-routing-intent.test.ts +76 -69
  139. package/src/__tests__/encrypted-store.test.ts +180 -154
  140. package/src/__tests__/entity-extractor.test.ts +108 -87
  141. package/src/__tests__/entity-search.test.ts +664 -258
  142. package/src/__tests__/ephemeral-permissions.test.ts +224 -188
  143. package/src/__tests__/event-bus.test.ts +81 -77
  144. package/src/__tests__/extract-email.test.ts +29 -20
  145. package/src/__tests__/file-edit-tool.test.ts +62 -44
  146. package/src/__tests__/file-ops-service.test.ts +131 -114
  147. package/src/__tests__/file-read-tool.test.ts +48 -31
  148. package/src/__tests__/file-write-tool.test.ts +43 -37
  149. package/src/__tests__/filesystem-tools.test.ts +238 -209
  150. package/src/__tests__/followup-tools.test.ts +237 -162
  151. package/src/__tests__/forbidden-legacy-symbols.test.ts +19 -20
  152. package/src/__tests__/frontmatter.test.ts +96 -81
  153. package/src/__tests__/fuzzy-match-property.test.ts +75 -81
  154. package/src/__tests__/fuzzy-match.test.ts +71 -65
  155. package/src/__tests__/gateway-client-managed-outbound.test.ts +76 -57
  156. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  157. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  158. package/src/__tests__/gemini-image-service.test.ts +113 -100
  159. package/src/__tests__/gemini-provider.test.ts +297 -220
  160. package/src/__tests__/get-weather.test.ts +188 -114
  161. package/src/__tests__/gmail-integration.test.ts +13 -5
  162. package/src/__tests__/guardian-action-conversation-turn.test.ts +226 -171
  163. package/src/__tests__/guardian-action-copy-generator.test.ts +111 -93
  164. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  165. package/src/__tests__/guardian-action-followup-store.test.ts +199 -167
  166. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +297 -250
  167. package/src/__tests__/guardian-action-late-reply.test.ts +462 -316
  168. package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +23 -18
  169. package/src/__tests__/guardian-action-store.test.ts +158 -109
  170. package/src/__tests__/guardian-action-sweep.test.ts +114 -100
  171. package/src/__tests__/guardian-actions-endpoint.test.ts +440 -256
  172. package/src/__tests__/guardian-control-plane-policy.test.ts +497 -331
  173. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +217 -215
  174. package/src/__tests__/guardian-dispatch.test.ts +316 -256
  175. package/src/__tests__/guardian-grant-minting.test.ts +247 -178
  176. package/src/__tests__/guardian-outbound-http.test.ts +5 -3
  177. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +99 -96
  178. package/src/__tests__/guardian-question-copy.test.ts +17 -17
  179. package/src/__tests__/guardian-question-mode.test.ts +134 -100
  180. package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
  181. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  182. package/src/__tests__/guardian-verification-intent-routing.test.ts +94 -88
  183. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  184. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +0 -1
  185. package/src/__tests__/handle-user-message-secret-resume.test.ts +7 -2
  186. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +92 -76
  187. package/src/__tests__/handlers-cu-observation-blob.test.ts +103 -70
  188. package/src/__tests__/handlers-ipc-blob-probe.test.ts +77 -51
  189. package/src/__tests__/handlers-slack-config.test.ts +63 -54
  190. package/src/__tests__/handlers-task-submit-slash.test.ts +18 -18
  191. package/src/__tests__/handlers-telegram-config.test.ts +662 -329
  192. package/src/__tests__/handlers-twitter-config.test.ts +525 -298
  193. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +5 -2
  194. package/src/__tests__/headless-browser-interactions.test.ts +444 -280
  195. package/src/__tests__/headless-browser-navigate.test.ts +116 -79
  196. package/src/__tests__/headless-browser-read-tools.test.ts +123 -86
  197. package/src/__tests__/headless-browser-snapshot.test.ts +71 -56
  198. package/src/__tests__/heartbeat-service.test.ts +76 -58
  199. package/src/__tests__/history-repair-observability.test.ts +14 -14
  200. package/src/__tests__/history-repair.test.ts +171 -167
  201. package/src/__tests__/home-base-bootstrap.test.ts +30 -27
  202. package/src/__tests__/hooks-blocking.test.ts +86 -37
  203. package/src/__tests__/hooks-cli.test.ts +104 -68
  204. package/src/__tests__/hooks-config.test.ts +81 -43
  205. package/src/__tests__/hooks-discovery.test.ts +106 -96
  206. package/src/__tests__/hooks-integration.test.ts +78 -72
  207. package/src/__tests__/hooks-manager.test.ts +99 -61
  208. package/src/__tests__/hooks-runner.test.ts +94 -71
  209. package/src/__tests__/hooks-settings.test.ts +69 -64
  210. package/src/__tests__/hooks-templates.test.ts +85 -54
  211. package/src/__tests__/hooks-ts-runner.test.ts +82 -45
  212. package/src/__tests__/hooks-watch.test.ts +32 -22
  213. package/src/__tests__/host-file-edit-tool.test.ts +190 -148
  214. package/src/__tests__/host-file-read-tool.test.ts +86 -63
  215. package/src/__tests__/host-file-write-tool.test.ts +98 -64
  216. package/src/__tests__/host-shell-tool.test.ts +342 -233
  217. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  218. package/src/__tests__/ingress-member-store.test.ts +163 -159
  219. package/src/__tests__/ingress-reconcile.test.ts +13 -6
  220. package/src/__tests__/ingress-routes-http.test.ts +441 -356
  221. package/src/__tests__/ingress-url-consistency.test.ts +125 -64
  222. package/src/__tests__/integration-status.test.ts +93 -73
  223. package/src/__tests__/intent-routing.test.ts +148 -118
  224. package/src/__tests__/invite-redemption-service.test.ts +163 -121
  225. package/src/__tests__/ipc-blob-store.test.ts +104 -91
  226. package/src/__tests__/ipc-contract-inventory.test.ts +27 -15
  227. package/src/__tests__/ipc-contract.test.ts +24 -23
  228. package/src/__tests__/ipc-protocol.test.ts +52 -46
  229. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +61 -50
  230. package/src/__tests__/ipc-snapshot.test.ts +1135 -1056
  231. package/src/__tests__/ipc-validate.test.ts +240 -179
  232. package/src/__tests__/key-migration.test.ts +123 -90
  233. package/src/__tests__/keychain.test.ts +150 -123
  234. package/src/__tests__/lifecycle-docs-guard.test.ts +65 -64
  235. package/src/__tests__/llm-usage-store.test.ts +112 -87
  236. package/src/__tests__/managed-skill-lifecycle.test.ts +147 -108
  237. package/src/__tests__/managed-store.test.ts +411 -360
  238. package/src/__tests__/mcp-cli.test.ts +190 -124
  239. package/src/__tests__/mcp-health-check.test.ts +26 -21
  240. package/src/__tests__/media-generate-image.test.ts +122 -99
  241. package/src/__tests__/media-reuse-story.e2e.test.ts +282 -214
  242. package/src/__tests__/media-visibility-policy.test.ts +86 -38
  243. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +146 -100
  244. package/src/__tests__/memory-lifecycle-e2e.test.ts +385 -297
  245. package/src/__tests__/memory-query-builder.test.ts +32 -33
  246. package/src/__tests__/memory-recall-quality.test.ts +761 -407
  247. package/src/__tests__/memory-regressions.experimental.test.ts +443 -380
  248. package/src/__tests__/memory-regressions.test.ts +3725 -2642
  249. package/src/__tests__/memory-retrieval-budget.test.ts +7 -8
  250. package/src/__tests__/memory-retrieval.benchmark.test.ts +144 -109
  251. package/src/__tests__/memory-upsert-concurrency.test.ts +292 -201
  252. package/src/__tests__/messaging-send-tool.test.ts +36 -29
  253. package/src/__tests__/migration-cli-flows.test.ts +69 -53
  254. package/src/__tests__/migration-ordering.test.ts +103 -86
  255. package/src/__tests__/mime-builder.test.ts +55 -32
  256. package/src/__tests__/mock-signup-server.test.ts +384 -246
  257. package/src/__tests__/model-intents.test.ts +61 -37
  258. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +9 -12
  259. package/src/__tests__/no-is-trusted-guard.test.ts +24 -21
  260. package/src/__tests__/non-member-access-request.test.ts +3 -2
  261. package/src/__tests__/notification-broadcaster.test.ts +99 -81
  262. package/src/__tests__/notification-decision-fallback.test.ts +223 -178
  263. package/src/__tests__/notification-decision-strategy.test.ts +375 -337
  264. package/src/__tests__/notification-deep-link.test.ts +67 -61
  265. package/src/__tests__/notification-guardian-path.test.ts +248 -206
  266. package/src/__tests__/notification-routing-intent.test.ts +166 -93
  267. package/src/__tests__/notification-thread-candidate-validation.test.ts +78 -75
  268. package/src/__tests__/notification-thread-candidates.test.ts +64 -61
  269. package/src/__tests__/oauth-callback-registry.test.ts +40 -30
  270. package/src/__tests__/oauth-connect-handler.test.ts +109 -89
  271. package/src/__tests__/oauth-scope-policy.test.ts +63 -55
  272. package/src/__tests__/oauth2-gateway-transport.test.ts +252 -174
  273. package/src/__tests__/onboarding-starter-tasks.test.ts +93 -89
  274. package/src/__tests__/onboarding-template-contract.test.ts +93 -94
  275. package/src/__tests__/openai-provider.test.ts +366 -274
  276. package/src/__tests__/pairing-concurrent.test.ts +18 -12
  277. package/src/__tests__/pairing-routes.test.ts +45 -41
  278. package/src/__tests__/parallel-tool.benchmark.test.ts +108 -58
  279. package/src/__tests__/parser.test.ts +316 -226
  280. package/src/__tests__/path-classifier.test.ts +24 -25
  281. package/src/__tests__/path-policy.test.ts +187 -147
  282. package/src/__tests__/phone.test.ts +36 -36
  283. package/src/__tests__/platform-move-helper.test.ts +48 -40
  284. package/src/__tests__/platform-socket-path.test.ts +23 -24
  285. package/src/__tests__/platform-workspace-migration.test.ts +464 -414
  286. package/src/__tests__/platform.test.ts +61 -53
  287. package/src/__tests__/playbook-execution.test.ts +397 -265
  288. package/src/__tests__/playbook-tools.test.ts +267 -196
  289. package/src/__tests__/prebuilt-home-base-seed.test.ts +30 -27
  290. package/src/__tests__/pricing.test.ts +316 -136
  291. package/src/__tests__/profile-compiler.test.ts +206 -188
  292. package/src/__tests__/provider-commit-message-generator.test.ts +114 -106
  293. package/src/__tests__/provider-error-scenarios.test.ts +212 -158
  294. package/src/__tests__/provider-fail-open-selection.test.ts +51 -44
  295. package/src/__tests__/provider-registry-ollama.test.ts +13 -9
  296. package/src/__tests__/provider-streaming.benchmark.test.ts +232 -183
  297. package/src/__tests__/proxy-approval-callback.test.ts +180 -119
  298. package/src/__tests__/public-ingress-urls.test.ts +112 -94
  299. package/src/__tests__/qdrant-manager.test.ts +147 -98
  300. package/src/__tests__/ratelimit.test.ts +152 -82
  301. package/src/__tests__/recording-handler.test.ts +273 -151
  302. package/src/__tests__/recording-intent-fallback.test.ts +94 -75
  303. package/src/__tests__/recording-intent-handler.test.ts +9 -2
  304. package/src/__tests__/recording-intent.test.ts +578 -379
  305. package/src/__tests__/recording-state-machine.test.ts +530 -316
  306. package/src/__tests__/recurrence-engine-rruleset.test.ts +150 -92
  307. package/src/__tests__/recurrence-engine.test.ts +81 -41
  308. package/src/__tests__/recurrence-types.test.ts +63 -44
  309. package/src/__tests__/relay-server.test.ts +2131 -1602
  310. package/src/__tests__/reminder-store.test.ts +158 -80
  311. package/src/__tests__/reminder.test.ts +113 -109
  312. package/src/__tests__/remote-skill-policy.test.ts +96 -72
  313. package/src/__tests__/request-file-tool.test.ts +74 -67
  314. package/src/__tests__/response-tier.test.ts +131 -74
  315. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  316. package/src/__tests__/runtime-events-sse-parity.test.ts +167 -145
  317. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  318. package/src/__tests__/sandbox-diagnostics.test.ts +66 -56
  319. package/src/__tests__/sandbox-host-parity.test.ts +377 -301
  320. package/src/__tests__/scaffold-managed-skill-tool.test.ts +213 -161
  321. package/src/__tests__/schedule-store.test.ts +268 -205
  322. package/src/__tests__/schedule-tools.test.ts +702 -524
  323. package/src/__tests__/scheduler-recurrence.test.ts +240 -130
  324. package/src/__tests__/scoped-approval-grants.test.ts +258 -168
  325. package/src/__tests__/scoped-grant-security-matrix.test.ts +160 -146
  326. package/src/__tests__/script-proxy-certs.test.ts +38 -35
  327. package/src/__tests__/script-proxy-connect-tunnel.test.ts +71 -46
  328. package/src/__tests__/script-proxy-decision-trace.test.ts +161 -84
  329. package/src/__tests__/script-proxy-http-forwarder.test.ts +146 -129
  330. package/src/__tests__/script-proxy-injection-runtime.test.ts +139 -113
  331. package/src/__tests__/script-proxy-mitm-handler.test.ts +226 -142
  332. package/src/__tests__/script-proxy-policy-runtime.test.ts +126 -86
  333. package/src/__tests__/script-proxy-policy.test.ts +308 -153
  334. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +74 -62
  335. package/src/__tests__/script-proxy-router.test.ts +111 -77
  336. package/src/__tests__/script-proxy-session-manager.test.ts +156 -113
  337. package/src/__tests__/script-proxy-session-runtime.test.ts +28 -24
  338. package/src/__tests__/secret-allowlist.test.ts +105 -90
  339. package/src/__tests__/secret-ingress-handler.test.ts +41 -30
  340. package/src/__tests__/secret-onetime-send.test.ts +67 -50
  341. package/src/__tests__/secret-prompt-log-hygiene.test.ts +35 -31
  342. package/src/__tests__/secret-response-routing.test.ts +50 -41
  343. package/src/__tests__/secret-scanner-executor.test.ts +152 -111
  344. package/src/__tests__/secret-scanner.test.ts +495 -413
  345. package/src/__tests__/secure-keys.test.ts +132 -121
  346. package/src/__tests__/send-endpoint-busy.test.ts +8 -3
  347. package/src/__tests__/send-notification-tool.test.ts +43 -42
  348. package/src/__tests__/sensitive-output-placeholders.test.ts +72 -64
  349. package/src/__tests__/sequence-store.test.ts +335 -167
  350. package/src/__tests__/server-history-render.test.ts +341 -202
  351. package/src/__tests__/session-abort-tool-results.test.ts +133 -70
  352. package/src/__tests__/session-confirmation-signals.test.ts +252 -160
  353. package/src/__tests__/session-conflict-gate.test.ts +775 -585
  354. package/src/__tests__/session-error.test.ts +222 -191
  355. package/src/__tests__/session-evictor.test.ts +79 -62
  356. package/src/__tests__/session-init.benchmark.test.ts +170 -108
  357. package/src/__tests__/session-load-history-repair.test.ts +273 -139
  358. package/src/__tests__/session-messaging-secret-redirect.test.ts +130 -90
  359. package/src/__tests__/session-pre-run-repair.test.ts +106 -59
  360. package/src/__tests__/session-profile-injection.test.ts +198 -130
  361. package/src/__tests__/session-provider-retry-repair.test.ts +223 -141
  362. package/src/__tests__/session-queue.test.ts +624 -321
  363. package/src/__tests__/session-runtime-assembly.test.ts +425 -329
  364. package/src/__tests__/session-runtime-workspace.test.ts +69 -61
  365. package/src/__tests__/session-skill-tools.test.ts +973 -678
  366. package/src/__tests__/session-slash-known.test.ts +185 -133
  367. package/src/__tests__/session-slash-queue.test.ts +147 -81
  368. package/src/__tests__/session-slash-unknown.test.ts +135 -90
  369. package/src/__tests__/session-surfaces-task-progress.test.ts +122 -87
  370. package/src/__tests__/session-tool-setup-app-refresh.test.ts +338 -177
  371. package/src/__tests__/session-tool-setup-memory-scope.test.ts +63 -40
  372. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +60 -37
  373. package/src/__tests__/session-tool-setup-tools-disabled.test.ts +28 -26
  374. package/src/__tests__/session-undo.test.ts +43 -30
  375. package/src/__tests__/session-workspace-cache-state.test.ts +108 -67
  376. package/src/__tests__/session-workspace-injection.test.ts +245 -117
  377. package/src/__tests__/session-workspace-tool-tracking.test.ts +260 -93
  378. package/src/__tests__/shared-filesystem-errors.test.ts +47 -47
  379. package/src/__tests__/shell-credential-ref.test.ts +126 -90
  380. package/src/__tests__/shell-identity.test.ts +134 -111
  381. package/src/__tests__/shell-parser-fuzz.test.ts +263 -179
  382. package/src/__tests__/shell-parser-property.test.ts +435 -288
  383. package/src/__tests__/shell-tool-proxy-mode.test.ts +142 -70
  384. package/src/__tests__/size-guard.test.ts +42 -44
  385. package/src/__tests__/skill-feature-flags-integration.test.ts +79 -52
  386. package/src/__tests__/skill-feature-flags.test.ts +75 -47
  387. package/src/__tests__/skill-include-graph.test.ts +143 -148
  388. package/src/__tests__/skill-load-feature-flag.test.ts +94 -59
  389. package/src/__tests__/skill-load-tool.test.ts +371 -199
  390. package/src/__tests__/skill-projection-feature-flag.test.ts +131 -88
  391. package/src/__tests__/skill-projection.benchmark.test.ts +93 -65
  392. package/src/__tests__/skill-script-runner-host.test.ts +460 -250
  393. package/src/__tests__/skill-script-runner-sandbox.test.ts +168 -108
  394. package/src/__tests__/skill-script-runner.test.ts +115 -74
  395. package/src/__tests__/skill-tool-factory.test.ts +140 -96
  396. package/src/__tests__/skill-tool-manifest.test.ts +306 -210
  397. package/src/__tests__/skill-version-hash.test.ts +70 -56
  398. package/src/__tests__/skills.test.ts +0 -1
  399. package/src/__tests__/slack-channel-config.test.ts +127 -84
  400. package/src/__tests__/slack-skill.test.ts +60 -47
  401. package/src/__tests__/slash-commands-catalog.test.ts +37 -31
  402. package/src/__tests__/slash-commands-parser.test.ts +71 -64
  403. package/src/__tests__/slash-commands-resolver.test.ts +143 -107
  404. package/src/__tests__/slash-commands-rewrite.test.ts +22 -22
  405. package/src/__tests__/sms-messaging-provider.test.ts +4 -0
  406. package/src/__tests__/speaker-identification.test.ts +28 -25
  407. package/src/__tests__/starter-bundle.test.ts +27 -23
  408. package/src/__tests__/starter-task-flow.test.ts +67 -52
  409. package/src/__tests__/subagent-manager-notify.test.ts +154 -108
  410. package/src/__tests__/subagent-tools.test.ts +311 -270
  411. package/src/__tests__/subagent-types.test.ts +40 -40
  412. package/src/__tests__/surface-mutex-cleanup.test.ts +42 -30
  413. package/src/__tests__/swarm-dag-pathological.test.ts +122 -111
  414. package/src/__tests__/swarm-orchestrator.test.ts +135 -101
  415. package/src/__tests__/swarm-plan-validator.test.ts +125 -73
  416. package/src/__tests__/swarm-recursion.test.ts +58 -46
  417. package/src/__tests__/swarm-router-planner.test.ts +99 -74
  418. package/src/__tests__/swarm-session-integration.test.ts +148 -91
  419. package/src/__tests__/swarm-tool.test.ts +65 -45
  420. package/src/__tests__/swarm-worker-backend.test.ts +59 -45
  421. package/src/__tests__/swarm-worker-runner.test.ts +133 -118
  422. package/src/__tests__/system-prompt.test.ts +311 -256
  423. package/src/__tests__/task-compiler.test.ts +176 -120
  424. package/src/__tests__/task-management-tools.test.ts +561 -456
  425. package/src/__tests__/task-memory-cleanup.test.ts +627 -362
  426. package/src/__tests__/task-runner.test.ts +117 -94
  427. package/src/__tests__/task-scheduler.test.ts +113 -84
  428. package/src/__tests__/task-tools.test.ts +349 -264
  429. package/src/__tests__/terminal-sandbox.test.ts +138 -108
  430. package/src/__tests__/terminal-tools.test.ts +350 -305
  431. package/src/__tests__/thread-seed-composer.test.ts +307 -180
  432. package/src/__tests__/tool-approval-handler.test.ts +238 -137
  433. package/src/__tests__/tool-audit-listener.test.ts +69 -69
  434. package/src/__tests__/tool-domain-event-publisher.test.ts +142 -132
  435. package/src/__tests__/tool-execution-abort-cleanup.test.ts +155 -146
  436. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +136 -105
  437. package/src/__tests__/tool-executor-lifecycle-events.test.ts +355 -239
  438. package/src/__tests__/tool-executor-redaction.test.ts +112 -109
  439. package/src/__tests__/tool-executor-shell-integration.test.ts +130 -79
  440. package/src/__tests__/tool-executor.test.ts +1274 -674
  441. package/src/__tests__/tool-grant-request-escalation.test.ts +401 -283
  442. package/src/__tests__/tool-metrics-listener.test.ts +97 -85
  443. package/src/__tests__/tool-notification-listener.test.ts +42 -25
  444. package/src/__tests__/tool-permission-simulate-handler.test.ts +137 -113
  445. package/src/__tests__/tool-policy.test.ts +44 -25
  446. package/src/__tests__/tool-profiling-listener.test.ts +99 -93
  447. package/src/__tests__/tool-result-truncation.test.ts +5 -4
  448. package/src/__tests__/tool-trace-listener.test.ts +131 -111
  449. package/src/__tests__/top-level-renderer.test.ts +62 -58
  450. package/src/__tests__/top-level-scanner.test.ts +68 -64
  451. package/src/__tests__/trace-emitter.test.ts +56 -56
  452. package/src/__tests__/trust-context-guards.test.ts +65 -65
  453. package/src/__tests__/trust-store.test.ts +1239 -806
  454. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  455. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  456. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +3 -2
  457. package/src/__tests__/trusted-contact-multichannel.test.ts +3 -2
  458. package/src/__tests__/trusted-contact-verification.test.ts +251 -231
  459. package/src/__tests__/turn-commit.test.ts +259 -200
  460. package/src/__tests__/twilio-provider.test.ts +140 -126
  461. package/src/__tests__/twilio-rest.test.ts +22 -18
  462. package/src/__tests__/twilio-routes-elevenlabs.test.ts +0 -1
  463. package/src/__tests__/twilio-routes-twiml.test.ts +55 -55
  464. package/src/__tests__/twilio-routes.test.ts +0 -1
  465. package/src/__tests__/twitter-auth-handler.test.ts +184 -139
  466. package/src/__tests__/twitter-cli-error-shaping.test.ts +88 -73
  467. package/src/__tests__/twitter-cli-routing.test.ts +146 -99
  468. package/src/__tests__/twitter-oauth-client.test.ts +82 -65
  469. package/src/__tests__/update-bulletin-format.test.ts +69 -66
  470. package/src/__tests__/update-bulletin-state.test.ts +66 -60
  471. package/src/__tests__/update-bulletin.test.ts +150 -114
  472. package/src/__tests__/update-template-contract.test.ts +15 -10
  473. package/src/__tests__/url-safety.test.ts +288 -265
  474. package/src/__tests__/user-reference.test.ts +32 -32
  475. package/src/__tests__/view-image-tool.test.ts +118 -96
  476. package/src/__tests__/voice-invite-redemption.test.ts +111 -106
  477. package/src/__tests__/voice-quality.test.ts +117 -102
  478. package/src/__tests__/voice-scoped-grant-consumer.test.ts +204 -146
  479. package/src/__tests__/voice-session-bridge.test.ts +351 -216
  480. package/src/__tests__/weather-skill-regression.test.ts +170 -120
  481. package/src/__tests__/web-fetch.test.ts +664 -526
  482. package/src/__tests__/web-search.test.ts +379 -213
  483. package/src/__tests__/work-item-output.test.ts +90 -53
  484. package/src/__tests__/workspace-git-service.test.ts +437 -356
  485. package/src/__tests__/workspace-heartbeat-service.test.ts +125 -91
  486. package/src/__tests__/workspace-lifecycle.test.ts +98 -64
  487. package/src/__tests__/workspace-policy.test.ts +139 -71
  488. package/src/cli/mcp.ts +81 -28
  489. package/src/commands/__tests__/cc-command-registry.test.ts +142 -134
  490. package/src/config/__tests__/feature-flag-registry-guard.test.ts +48 -39
  491. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +25 -10
  492. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -1
  493. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +6 -11
  494. package/src/config/bundled-skills/messaging/SKILL.md +4 -3
  495. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +15 -5
  496. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +16 -5
  497. package/src/config/bundled-skills/phone-calls/SKILL.md +1 -2
  498. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +34 -32
  499. package/src/config/bundled-skills/sms-setup/SKILL.md +8 -16
  500. package/src/config/bundled-skills/telegram-setup/SKILL.md +3 -3
  501. package/src/config/bundled-skills/trusted-contacts/SKILL.md +13 -25
  502. package/src/config/bundled-skills/twilio-setup/SKILL.md +13 -23
  503. package/src/config/bundled-tool-registry.ts +2 -0
  504. package/src/config/env.ts +3 -4
  505. package/src/config/system-prompt.ts +32 -0
  506. package/src/mcp/client.ts +2 -7
  507. package/src/memory/db-connection.ts +16 -10
  508. package/src/messaging/providers/gmail/adapter.ts +10 -3
  509. package/src/messaging/providers/gmail/client.ts +280 -72
  510. package/src/runtime/auth/__tests__/context.test.ts +75 -65
  511. package/src/runtime/auth/__tests__/credential-service.test.ts +137 -114
  512. package/src/runtime/auth/__tests__/guard-tests.test.ts +84 -90
  513. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +40 -40
  514. package/src/runtime/auth/__tests__/middleware.test.ts +80 -74
  515. package/src/runtime/auth/__tests__/policy.test.ts +9 -9
  516. package/src/runtime/auth/__tests__/route-policy.test.ts +76 -65
  517. package/src/runtime/auth/__tests__/scopes.test.ts +68 -60
  518. package/src/runtime/auth/__tests__/subject.test.ts +54 -54
  519. package/src/runtime/auth/__tests__/token-service.test.ts +115 -108
  520. package/src/runtime/auth/scopes.ts +3 -0
  521. package/src/runtime/auth/token-service.ts +4 -1
  522. package/src/runtime/auth/types.ts +2 -1
  523. package/src/runtime/http-server.ts +2 -1
  524. package/src/security/secure-keys.ts +120 -54
  525. package/src/tools/browser/__tests__/auth-cache.test.ts +69 -63
  526. package/src/tools/browser/__tests__/auth-detector.test.ts +218 -157
  527. package/src/tools/browser/__tests__/jit-auth.test.ts +83 -99
  528. package/src/tools/terminal/safe-env.ts +7 -0
@@ -1,4 +1,4 @@
1
- import { beforeEach, describe, expect, mock,test } from 'bun:test';
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  // ---------------------------------------------------------------------------
4
4
  // Mocks — declared before importing modules under test
@@ -7,7 +7,7 @@ import { beforeEach, describe, expect, mock,test } from 'bun:test';
7
7
  const mockConfig = {
8
8
  secretDetection: {
9
9
  enabled: true,
10
- action: 'block' as 'redact' | 'warn' | 'block',
10
+ action: "block" as "redact" | "warn" | "block",
11
11
  entropyThreshold: 4.0,
12
12
  allowOneTimeSend: false,
13
13
  blockIngress: true,
@@ -15,13 +15,13 @@ const mockConfig = {
15
15
  timeouts: { permissionTimeoutSec: 300 },
16
16
  };
17
17
 
18
- mock.module('../config/loader.js', () => ({
18
+ mock.module("../config/loader.js", () => ({
19
19
  getConfig: () => mockConfig,
20
20
  loadConfig: () => mockConfig,
21
21
  invalidateConfigCache: () => {},
22
22
  }));
23
23
 
24
- mock.module('../util/logger.js', () => ({
24
+ mock.module("../util/logger.js", () => ({
25
25
  getLogger: () =>
26
26
  new Proxy({} as Record<string, unknown>, {
27
27
  get: () => () => {},
@@ -30,7 +30,7 @@ mock.module('../util/logger.js', () => ({
30
30
 
31
31
  // Track keychain writes
32
32
  const storedKeys = new Map<string, string>();
33
- mock.module('../security/secure-keys.js', () => ({
33
+ mock.module("../security/secure-keys.js", () => ({
34
34
  getSecureKey: (key: string) => storedKeys.get(key) ?? null,
35
35
  setSecureKey: (key: string, value: string) => {
36
36
  storedKeys.set(key, value);
@@ -38,15 +38,22 @@ mock.module('../security/secure-keys.js', () => ({
38
38
  },
39
39
  deleteSecureKey: (key: string) => storedKeys.delete(key),
40
40
  listSecureKeys: () => [...storedKeys.keys()],
41
- getBackendType: () => 'encrypted',
41
+ getBackendType: () => "encrypted",
42
42
  isDowngradedFromKeychain: () => false,
43
43
  }));
44
44
 
45
45
  // In-memory metadata store that mirrors storedKeys for list/get operations
46
- const metadataStore = new Map<string, { credentialId: string; service: string; field: string }>();
47
-
48
- mock.module('../tools/credentials/metadata-store.js', () => ({
49
- upsertCredentialMetadata: (service: string, field: string, _policy?: Record<string, unknown>) => {
46
+ const metadataStore = new Map<
47
+ string,
48
+ { credentialId: string; service: string; field: string }
49
+ >();
50
+
51
+ mock.module("../tools/credentials/metadata-store.js", () => ({
52
+ upsertCredentialMetadata: (
53
+ service: string,
54
+ field: string,
55
+ _policy?: Record<string, unknown>,
56
+ ) => {
50
57
  const key = `${service}:${field}`;
51
58
  metadataStore.set(key, {
52
59
  credentialId: `cred-${service}-${field}`,
@@ -71,7 +78,7 @@ mock.module('../tools/credentials/metadata-store.js', () => ({
71
78
  _setMetadataPath: () => {},
72
79
  }));
73
80
 
74
- mock.module('../tools/credentials/policy-validate.js', () => ({
81
+ mock.module("../tools/credentials/policy-validate.js", () => ({
75
82
  validatePolicyInput: () => ({ valid: true, errors: [] }),
76
83
  toPolicyFromInput: (input: Record<string, unknown>) => ({
77
84
  allowedTools: input.allowed_tools ?? [],
@@ -81,10 +88,12 @@ mock.module('../tools/credentials/policy-validate.js', () => ({
81
88
  }));
82
89
 
83
90
  // Import modules under test
84
- const { credentialStoreTool } = await import('../tools/credentials/vault.js');
85
- const { checkIngressForSecrets } = await import('../security/secret-ingress.js');
86
- const { isToolAllowed } = await import('../tools/credentials/tool-policy.js');
87
- const { isDomainAllowed } = await import('../tools/credentials/domain-policy.js');
91
+ const { credentialStoreTool } = await import("../tools/credentials/vault.js");
92
+ const { checkIngressForSecrets } =
93
+ await import("../security/secret-ingress.js");
94
+ const { isToolAllowed } = await import("../tools/credentials/tool-policy.js");
95
+ const { isDomainAllowed } =
96
+ await import("../tools/credentials/domain-policy.js");
88
97
 
89
98
  // ---------------------------------------------------------------------------
90
99
  // Helpers
@@ -92,10 +101,10 @@ const { isDomainAllowed } = await import('../tools/credentials/domain-policy.js'
92
101
 
93
102
  function makeContext(overrides: Record<string, unknown> = {}) {
94
103
  return {
95
- workingDir: '/tmp',
96
- sessionId: 's1',
97
- conversationId: 'c1',
98
- guardianTrustClass: 'guardian' as const,
104
+ workingDir: "/tmp",
105
+ sessionId: "s1",
106
+ conversationId: "c1",
107
+ guardianTrustClass: "guardian" as const,
99
108
  ...overrides,
100
109
  };
101
110
  }
@@ -104,49 +113,65 @@ function makeContext(overrides: Record<string, unknown> = {}) {
104
113
  // E2E Scenario 1 — Normal secure store + list
105
114
  // ---------------------------------------------------------------------------
106
115
 
107
- describe('E2E: secure store and list lifecycle', () => {
108
- beforeEach(() => { storedKeys.clear(); metadataStore.clear(); });
116
+ describe("E2E: secure store and list lifecycle", () => {
117
+ beforeEach(() => {
118
+ storedKeys.clear();
119
+ metadataStore.clear();
120
+ });
109
121
 
110
- test('store persists credential and returns metadata-only confirmation', async () => {
122
+ test("store persists credential and returns metadata-only confirmation", async () => {
111
123
  const result = await credentialStoreTool.execute(
112
- { action: 'store', service: 'github', field: 'token', value: 'ghp_abc123' },
124
+ {
125
+ action: "store",
126
+ service: "github",
127
+ field: "token",
128
+ value: "ghp_abc123",
129
+ },
113
130
  makeContext(),
114
131
  );
115
132
  expect(result.isError).toBe(false);
116
- expect(result.content).toContain('github');
133
+ expect(result.content).toContain("github");
117
134
  // Value must NOT appear in tool output (invariant 1)
118
- expect(result.content).not.toContain('ghp_abc123');
135
+ expect(result.content).not.toContain("ghp_abc123");
119
136
  // Value must be in keychain
120
- expect(storedKeys.get('credential:github:token')).toBe('ghp_abc123');
137
+ expect(storedKeys.get("credential:github:token")).toBe("ghp_abc123");
121
138
  });
122
139
 
123
- test('list returns service/field pairs without secret values', async () => {
124
- storedKeys.set('credential:github:token', 'secret1');
125
- storedKeys.set('credential:aws:access_key', 'secret2');
126
- metadataStore.set('github:token', { credentialId: 'cred-github-token', service: 'github', field: 'token' });
127
- metadataStore.set('aws:access_key', { credentialId: 'cred-aws-access_key', service: 'aws', field: 'access_key' });
140
+ test("list returns service/field pairs without secret values", async () => {
141
+ storedKeys.set("credential:github:token", "secret1");
142
+ storedKeys.set("credential:aws:access_key", "secret2");
143
+ metadataStore.set("github:token", {
144
+ credentialId: "cred-github-token",
145
+ service: "github",
146
+ field: "token",
147
+ });
148
+ metadataStore.set("aws:access_key", {
149
+ credentialId: "cred-aws-access_key",
150
+ service: "aws",
151
+ field: "access_key",
152
+ });
128
153
 
129
154
  const result = await credentialStoreTool.execute(
130
- { action: 'list' },
155
+ { action: "list" },
131
156
  makeContext(),
132
157
  );
133
158
  expect(result.isError).toBe(false);
134
- expect(result.content).toContain('github');
135
- expect(result.content).toContain('token');
159
+ expect(result.content).toContain("github");
160
+ expect(result.content).toContain("token");
136
161
  // Secret values must NOT appear
137
- expect(result.content).not.toContain('secret1');
138
- expect(result.content).not.toContain('secret2');
162
+ expect(result.content).not.toContain("secret1");
163
+ expect(result.content).not.toContain("secret2");
139
164
  });
140
165
 
141
- test('delete removes credential from keychain', async () => {
142
- storedKeys.set('credential:github:token', 'secret1');
166
+ test("delete removes credential from keychain", async () => {
167
+ storedKeys.set("credential:github:token", "secret1");
143
168
 
144
169
  const result = await credentialStoreTool.execute(
145
- { action: 'delete', service: 'github', field: 'token' },
170
+ { action: "delete", service: "github", field: "token" },
146
171
  makeContext(),
147
172
  );
148
173
  expect(result.isError).toBe(false);
149
- expect(storedKeys.has('credential:github:token')).toBe(false);
174
+ expect(storedKeys.has("credential:github:token")).toBe(false);
150
175
  });
151
176
  });
152
177
 
@@ -154,14 +179,14 @@ describe('E2E: secure store and list lifecycle', () => {
154
179
  // E2E Scenario 2 — Secret-in-chat blocked and redirected
155
180
  // ---------------------------------------------------------------------------
156
181
 
157
- describe('E2E: secret ingress blocking', () => {
182
+ describe("E2E: secret ingress blocking", () => {
158
183
  beforeEach(() => {
159
184
  mockConfig.secretDetection.enabled = true;
160
- mockConfig.secretDetection.action = 'block';
185
+ mockConfig.secretDetection.action = "block";
161
186
  });
162
187
 
163
- test('blocks message containing AWS access key', () => {
164
- const awsKey = ['AKIA', 'IOSFODNN7', 'REALKEY'].join('');
188
+ test("blocks message containing AWS access key", () => {
189
+ const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
165
190
  const check = checkIngressForSecrets(`Here is my key: ${awsKey}`);
166
191
  expect(check.blocked).toBe(true);
167
192
  expect(check.detectedTypes.length).toBeGreaterThan(0);
@@ -170,36 +195,36 @@ describe('E2E: secret ingress blocking', () => {
170
195
  expect(check.userNotice).not.toContain(awsKey);
171
196
  });
172
197
 
173
- test('blocks message containing GitHub token', () => {
174
- const ghToken = ['ghp_', 'ABCDEFghijklMN01234567', '89abcdef'].join('');
198
+ test("blocks message containing GitHub token", () => {
199
+ const ghToken = ["ghp_", "ABCDEFghijklMN01234567", "89abcdef"].join("");
175
200
  const check = checkIngressForSecrets(`Use this token: ${ghToken}`);
176
201
  expect(check.blocked).toBe(true);
177
202
  });
178
203
 
179
- test('allows normal text through', () => {
180
- const check = checkIngressForSecrets('Please help me configure my project');
204
+ test("allows normal text through", () => {
205
+ const check = checkIngressForSecrets("Please help me configure my project");
181
206
  expect(check.blocked).toBe(false);
182
207
  expect(check.detectedTypes).toEqual([]);
183
208
  });
184
209
 
185
- test('bypasses when detection is disabled', () => {
210
+ test("bypasses when detection is disabled", () => {
186
211
  mockConfig.secretDetection.enabled = false;
187
- const awsKey = ['AKIA', 'IOSFODNN7', 'REALKEY'].join('');
212
+ const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
188
213
  const check = checkIngressForSecrets(awsKey);
189
214
  expect(check.blocked).toBe(false);
190
215
  });
191
216
 
192
- test('bypasses when blockIngress is false', () => {
217
+ test("bypasses when blockIngress is false", () => {
193
218
  mockConfig.secretDetection.blockIngress = false;
194
- const awsKey = ['AKIA', 'IOSFODNN7', 'REALKEY'].join('');
219
+ const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
195
220
  const check = checkIngressForSecrets(awsKey);
196
221
  expect(check.blocked).toBe(false);
197
222
  });
198
223
 
199
- test('still blocks when action is warn but blockIngress is true', () => {
200
- mockConfig.secretDetection.action = 'warn';
224
+ test("still blocks when action is warn but blockIngress is true", () => {
225
+ mockConfig.secretDetection.action = "warn";
201
226
  mockConfig.secretDetection.blockIngress = true;
202
- const awsKey = ['AKIA', 'IOSFODNN7', 'REALKEY'].join('');
227
+ const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
203
228
  const check = checkIngressForSecrets(awsKey);
204
229
  expect(check.blocked).toBe(true);
205
230
  });
@@ -209,54 +234,63 @@ describe('E2E: secret ingress blocking', () => {
209
234
  // E2E Scenario 3 — One-time send override path
210
235
  // ---------------------------------------------------------------------------
211
236
 
212
- describe('E2E: one-time send override', () => {
237
+ describe("E2E: one-time send override", () => {
213
238
  beforeEach(() => {
214
239
  storedKeys.clear();
215
240
  metadataStore.clear();
216
241
  mockConfig.secretDetection.allowOneTimeSend = false;
217
242
  });
218
243
 
219
- test('rejects transient_send when config gate is off', async () => {
244
+ test("rejects transient_send when config gate is off", async () => {
220
245
  const ctx = makeContext({
221
- requestSecret: async () => ({ value: 'tmp1', delivery: 'transient_send' as const }),
246
+ requestSecret: async () => ({
247
+ value: "tmp1",
248
+ delivery: "transient_send" as const,
249
+ }),
222
250
  });
223
251
  const result = await credentialStoreTool.execute(
224
- { action: 'prompt', service: 'svc', field: 'key', label: 'Key' },
252
+ { action: "prompt", service: "svc", field: "key", label: "Key" },
225
253
  ctx,
226
254
  );
227
255
  expect(result.isError).toBe(true);
228
- expect(result.content).toContain('not enabled');
229
- expect(storedKeys.has('credential:svc:key')).toBe(false);
256
+ expect(result.content).toContain("not enabled");
257
+ expect(storedKeys.has("credential:svc:key")).toBe(false);
230
258
  });
231
259
 
232
- test('accepts transient_send when config gate is on', async () => {
260
+ test("accepts transient_send when config gate is on", async () => {
233
261
  mockConfig.secretDetection.allowOneTimeSend = true;
234
262
  const ctx = makeContext({
235
- requestSecret: async () => ({ value: 'tmp1', delivery: 'transient_send' as const }),
263
+ requestSecret: async () => ({
264
+ value: "tmp1",
265
+ delivery: "transient_send" as const,
266
+ }),
236
267
  });
237
268
  const result = await credentialStoreTool.execute(
238
- { action: 'prompt', service: 'svc', field: 'key', label: 'Key' },
269
+ { action: "prompt", service: "svc", field: "key", label: "Key" },
239
270
  ctx,
240
271
  );
241
272
  expect(result.isError).toBe(false);
242
- expect(result.content).toContain('NOT saved');
273
+ expect(result.content).toContain("NOT saved");
243
274
  // Value must NOT be in keychain
244
- expect(storedKeys.has('credential:svc:key')).toBe(false);
275
+ expect(storedKeys.has("credential:svc:key")).toBe(false);
245
276
  // Value must NOT appear in output
246
- expect(result.content).not.toContain('tmp1');
277
+ expect(result.content).not.toContain("tmp1");
247
278
  });
248
279
 
249
- test('store delivery always persists regardless of config gate', async () => {
280
+ test("store delivery always persists regardless of config gate", async () => {
250
281
  mockConfig.secretDetection.allowOneTimeSend = true;
251
282
  const ctx = makeContext({
252
- requestSecret: async () => ({ value: 'perm1', delivery: 'store' as const }),
283
+ requestSecret: async () => ({
284
+ value: "perm1",
285
+ delivery: "store" as const,
286
+ }),
253
287
  });
254
288
  const result = await credentialStoreTool.execute(
255
- { action: 'prompt', service: 'svc', field: 'key', label: 'Key' },
289
+ { action: "prompt", service: "svc", field: "key", label: "Key" },
256
290
  ctx,
257
291
  );
258
292
  expect(result.isError).toBe(false);
259
- expect(storedKeys.has('credential:svc:key')).toBe(true);
293
+ expect(storedKeys.has("credential:svc:key")).toBe(true);
260
294
  });
261
295
  });
262
296
 
@@ -264,21 +298,25 @@ describe('E2E: one-time send override', () => {
264
298
  // E2E Scenario 4 — Tool policy enforcement
265
299
  // ---------------------------------------------------------------------------
266
300
 
267
- describe('E2E: tool policy enforcement', () => {
268
- test('allows tool when listed in allowedTools', () => {
269
- expect(isToolAllowed('browser_fill_credential', ['browser_fill_credential'])).toBe(true);
301
+ describe("E2E: tool policy enforcement", () => {
302
+ test("allows tool when listed in allowedTools", () => {
303
+ expect(
304
+ isToolAllowed("browser_fill_credential", ["browser_fill_credential"]),
305
+ ).toBe(true);
270
306
  });
271
307
 
272
- test('denies tool when not listed', () => {
273
- expect(isToolAllowed('browser_fill_credential', ['other_tool'])).toBe(false);
308
+ test("denies tool when not listed", () => {
309
+ expect(isToolAllowed("browser_fill_credential", ["other_tool"])).toBe(
310
+ false,
311
+ );
274
312
  });
275
313
 
276
- test('denies all tools when allowedTools is empty (fail-closed)', () => {
277
- expect(isToolAllowed('browser_fill_credential', [])).toBe(false);
314
+ test("denies all tools when allowedTools is empty (fail-closed)", () => {
315
+ expect(isToolAllowed("browser_fill_credential", [])).toBe(false);
278
316
  });
279
317
 
280
- test('denies when toolName is empty', () => {
281
- expect(isToolAllowed('', ['browser_fill_credential'])).toBe(false);
318
+ test("denies when toolName is empty", () => {
319
+ expect(isToolAllowed("", ["browser_fill_credential"])).toBe(false);
282
320
  });
283
321
  });
284
322
 
@@ -286,26 +324,26 @@ describe('E2E: tool policy enforcement', () => {
286
324
  // E2E Scenario 5 — Domain policy enforcement
287
325
  // ---------------------------------------------------------------------------
288
326
 
289
- describe('E2E: domain policy enforcement', () => {
290
- test('allows exact domain match', () => {
291
- expect(isDomainAllowed('github.com', ['github.com'])).toBe(true);
327
+ describe("E2E: domain policy enforcement", () => {
328
+ test("allows exact domain match", () => {
329
+ expect(isDomainAllowed("github.com", ["github.com"])).toBe(true);
292
330
  });
293
331
 
294
- test('allows subdomain of registrable domain', () => {
295
- expect(isDomainAllowed('login.github.com', ['github.com'])).toBe(true);
332
+ test("allows subdomain of registrable domain", () => {
333
+ expect(isDomainAllowed("login.github.com", ["github.com"])).toBe(true);
296
334
  });
297
335
 
298
- test('denies mismatched domain', () => {
299
- expect(isDomainAllowed('evil.com', ['github.com'])).toBe(false);
336
+ test("denies mismatched domain", () => {
337
+ expect(isDomainAllowed("evil.com", ["github.com"])).toBe(false);
300
338
  });
301
339
 
302
- test('denies when allowedDomains is empty (fail-closed)', () => {
303
- expect(isDomainAllowed('github.com', [])).toBe(false);
340
+ test("denies when allowedDomains is empty (fail-closed)", () => {
341
+ expect(isDomainAllowed("github.com", [])).toBe(false);
304
342
  });
305
343
 
306
- test('denies localhost and IP addresses', () => {
307
- expect(isDomainAllowed('localhost', ['localhost'])).toBe(false);
308
- expect(isDomainAllowed('127.0.0.1', ['127.0.0.1'])).toBe(false);
344
+ test("denies localhost and IP addresses", () => {
345
+ expect(isDomainAllowed("localhost", ["localhost"])).toBe(false);
346
+ expect(isDomainAllowed("127.0.0.1", ["127.0.0.1"])).toBe(false);
309
347
  });
310
348
  });
311
349
 
@@ -313,38 +351,41 @@ describe('E2E: domain policy enforcement', () => {
313
351
  // Cross-cutting — output never leaks secrets
314
352
  // ---------------------------------------------------------------------------
315
353
 
316
- describe('E2E: cross-cutting secret leak prevention', () => {
354
+ describe("E2E: cross-cutting secret leak prevention", () => {
317
355
  beforeEach(() => {
318
356
  storedKeys.clear();
319
357
  mockConfig.secretDetection.enabled = true;
320
- mockConfig.secretDetection.action = 'block';
358
+ mockConfig.secretDetection.action = "block";
321
359
  mockConfig.secretDetection.allowOneTimeSend = false;
322
360
  });
323
361
 
324
- test('store output never contains the stored value', async () => {
325
- const secret = ['sk', '-proj-', 'abc123xyz'].join('');
362
+ test("store output never contains the stored value", async () => {
363
+ const secret = ["sk", "-proj-", "abc123xyz"].join("");
326
364
  const result = await credentialStoreTool.execute(
327
- { action: 'store', service: 'openai', field: 'api_key', value: secret },
365
+ { action: "store", service: "openai", field: "api_key", value: secret },
328
366
  makeContext(),
329
367
  );
330
368
  expect(result.content).not.toContain(secret);
331
369
  });
332
370
 
333
- test('prompt output never contains the secret value', async () => {
371
+ test("prompt output never contains the secret value", async () => {
334
372
  mockConfig.secretDetection.allowOneTimeSend = true;
335
- const secret = ['tok', '_', 'sensitive99'].join('');
373
+ const secret = ["tok", "_", "sensitive99"].join("");
336
374
  const ctx = makeContext({
337
- requestSecret: async () => ({ value: secret, delivery: 'transient_send' as const }),
375
+ requestSecret: async () => ({
376
+ value: secret,
377
+ delivery: "transient_send" as const,
378
+ }),
338
379
  });
339
380
  const result = await credentialStoreTool.execute(
340
- { action: 'prompt', service: 'svc', field: 'key', label: 'Key' },
381
+ { action: "prompt", service: "svc", field: "key", label: "Key" },
341
382
  ctx,
342
383
  );
343
384
  expect(result.content).not.toContain(secret);
344
385
  });
345
386
 
346
- test('ingress notice never contains the detected secret', () => {
347
- const awsKey = ['AKIA', 'IOSFODNN7', 'REALKEY'].join('');
387
+ test("ingress notice never contains the detected secret", () => {
388
+ const awsKey = ["AKIA", "IOSFODNN7", "REALKEY"].join("");
348
389
  const check = checkIngressForSecrets(awsKey);
349
390
  expect(check.blocked).toBe(true);
350
391
  expect(check.userNotice).toBeDefined();