@vellumai/assistant 0.5.6 → 0.5.7

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 (305) hide show
  1. package/.env.example +16 -2
  2. package/ARCHITECTURE.md +6 -75
  3. package/Dockerfile +1 -1
  4. package/README.md +0 -2
  5. package/bun.lock +0 -414
  6. package/docs/architecture/keychain-broker.md +45 -240
  7. package/docs/architecture/security.md +0 -17
  8. package/docs/credential-execution-service.md +2 -2
  9. package/node_modules/@vellumai/ces-contracts/package.json +1 -0
  10. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +119 -0
  11. package/node_modules/@vellumai/credential-storage/package.json +1 -0
  12. package/node_modules/@vellumai/egress-proxy/package.json +1 -0
  13. package/package.json +2 -3
  14. package/src/__tests__/actor-token-service.test.ts +0 -114
  15. package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
  16. package/src/__tests__/browser-skill-endstate.test.ts +6 -5
  17. package/src/__tests__/btw-routes.test.ts +0 -39
  18. package/src/__tests__/call-domain.test.ts +0 -128
  19. package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
  20. package/src/__tests__/channel-approval-routes.test.ts +0 -5
  21. package/src/__tests__/channel-readiness-service.test.ts +1 -60
  22. package/src/__tests__/checker.test.ts +4 -2
  23. package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
  24. package/src/__tests__/config-schema-cmd.test.ts +0 -1
  25. package/src/__tests__/config-schema.test.ts +1 -1
  26. package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
  27. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  28. package/src/__tests__/conversation-skill-tools.test.ts +0 -54
  29. package/src/__tests__/conversation-title-service.test.ts +87 -0
  30. package/src/__tests__/credential-execution-feature-gates.test.ts +28 -14
  31. package/src/__tests__/credential-execution-managed-contract.test.ts +33 -18
  32. package/src/__tests__/credential-security-e2e.test.ts +0 -66
  33. package/src/__tests__/credential-security-invariants.test.ts +4 -45
  34. package/src/__tests__/credentials-cli.test.ts +78 -0
  35. package/src/__tests__/db-migration-rollback.test.ts +2015 -1
  36. package/src/__tests__/docker-signing-key-bootstrap.test.ts +34 -143
  37. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
  38. package/src/__tests__/guardian-routing-state.test.ts +0 -5
  39. package/src/__tests__/host-shell-tool.test.ts +6 -7
  40. package/src/__tests__/http-user-message-parity.test.ts +3 -103
  41. package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
  42. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
  43. package/src/__tests__/intent-routing.test.ts +0 -13
  44. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
  45. package/src/__tests__/keychain-broker-client.test.ts +161 -22
  46. package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
  47. package/src/__tests__/migration-export-http.test.ts +2 -2
  48. package/src/__tests__/migration-import-commit-http.test.ts +2 -2
  49. package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
  50. package/src/__tests__/migration-validate-http.test.ts +2 -2
  51. package/src/__tests__/non-member-access-request.test.ts +0 -5
  52. package/src/__tests__/notification-decision-fallback.test.ts +4 -0
  53. package/src/__tests__/notification-decision-identity.test.ts +4 -0
  54. package/src/__tests__/permission-types.test.ts +1 -0
  55. package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
  56. package/src/__tests__/qdrant-manager.test.ts +28 -2
  57. package/src/__tests__/registry.test.ts +0 -6
  58. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
  59. package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
  60. package/src/__tests__/secure-keys.test.ts +83 -263
  61. package/src/__tests__/shell-identity.test.ts +96 -6
  62. package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
  63. package/src/__tests__/skill-feature-flags.test.ts +46 -45
  64. package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
  65. package/src/__tests__/skill-load-inline-command.test.ts +8 -12
  66. package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
  67. package/src/__tests__/skill-load-tool.test.ts +0 -2
  68. package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
  69. package/src/__tests__/skills.test.ts +0 -2
  70. package/src/__tests__/slack-inbound-verification.test.ts +0 -4
  71. package/src/__tests__/suggestion-routes.test.ts +1 -32
  72. package/src/__tests__/system-prompt.test.ts +0 -1
  73. package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
  74. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
  75. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
  76. package/src/__tests__/update-bulletin.test.ts +0 -2
  77. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
  78. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -6
  79. package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
  80. package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +218 -0
  81. package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
  82. package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
  83. package/src/calls/audio-store.test.ts +97 -0
  84. package/src/calls/audio-store.ts +205 -0
  85. package/src/calls/call-controller.ts +85 -7
  86. package/src/calls/call-domain.ts +3 -0
  87. package/src/calls/call-store.ts +10 -3
  88. package/src/calls/fish-audio-client.ts +117 -0
  89. package/src/calls/relay-server.ts +27 -0
  90. package/src/calls/twilio-routes.ts +2 -1
  91. package/src/calls/types.ts +1 -0
  92. package/src/calls/voice-ingress-preflight.ts +0 -42
  93. package/src/calls/voice-quality.ts +26 -5
  94. package/src/calls/voice-session-bridge.ts +6 -12
  95. package/src/cli/commands/config.ts +1 -4
  96. package/src/cli/commands/credentials.ts +34 -4
  97. package/src/cli/commands/oauth/index.ts +7 -0
  98. package/src/cli/commands/oauth/platform.ts +179 -0
  99. package/src/cli/commands/platform.ts +3 -3
  100. package/src/config/assistant-feature-flags.ts +186 -5
  101. package/src/config/bundled-skills/messaging/SKILL.md +5 -5
  102. package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
  103. package/src/config/bundled-skills/settings/TOOLS.json +2 -2
  104. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
  105. package/src/config/bundled-tool-registry.ts +1 -11
  106. package/src/config/env-registry.ts +1 -1
  107. package/src/config/env.ts +8 -14
  108. package/src/config/feature-flag-registry.json +48 -8
  109. package/src/config/loader.ts +98 -31
  110. package/src/config/schema.ts +4 -13
  111. package/src/config/schemas/calls.ts +13 -0
  112. package/src/config/schemas/fish-audio.ts +39 -0
  113. package/src/config/schemas/security.ts +0 -4
  114. package/src/config/types.ts +0 -1
  115. package/src/contacts/contact-store.ts +39 -0
  116. package/src/contacts/types.ts +2 -0
  117. package/src/credential-execution/approval-bridge.ts +1 -0
  118. package/src/credential-execution/executable-discovery.ts +28 -4
  119. package/src/credential-execution/feature-gates.ts +16 -0
  120. package/src/credential-execution/process-manager.ts +38 -0
  121. package/src/daemon/assistant-attachments.ts +9 -0
  122. package/src/daemon/config-watcher.ts +5 -0
  123. package/src/daemon/conversation-tool-setup.ts +0 -105
  124. package/src/daemon/conversation.ts +10 -1
  125. package/src/daemon/handlers/config-vercel.ts +92 -0
  126. package/src/daemon/handlers/skills.ts +2 -15
  127. package/src/daemon/install-symlink.ts +195 -0
  128. package/src/daemon/lifecycle.ts +227 -51
  129. package/src/daemon/message-types/conversations.ts +3 -4
  130. package/src/daemon/message-types/diagnostics.ts +3 -22
  131. package/src/daemon/message-types/messages.ts +0 -2
  132. package/src/daemon/message-types/upgrades.ts +8 -0
  133. package/src/daemon/server.ts +30 -92
  134. package/src/events/domain-events.ts +2 -1
  135. package/src/inbound/platform-callback-registration.ts +3 -3
  136. package/src/instrument.ts +8 -5
  137. package/src/memory/conversation-title-service.ts +50 -1
  138. package/src/memory/db-init.ts +12 -0
  139. package/src/memory/items-extractor.ts +15 -1
  140. package/src/memory/job-handlers/conversation-starters.ts +4 -1
  141. package/src/memory/jobs-store.ts +30 -5
  142. package/src/memory/jobs-worker.ts +31 -7
  143. package/src/memory/migrations/001-job-deferrals.ts +19 -0
  144. package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
  145. package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
  146. package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
  147. package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
  148. package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
  149. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
  150. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
  151. package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
  152. package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
  153. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
  154. package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
  155. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
  156. package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
  157. package/src/memory/migrations/116-messages-fts.ts +106 -1
  158. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
  159. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
  160. package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
  161. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
  162. package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
  163. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
  164. package/src/memory/migrations/141-rename-verification-table.ts +54 -0
  165. package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
  166. package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
  167. package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
  168. package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
  169. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
  170. package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
  171. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
  172. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
  173. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
  174. package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
  175. package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
  176. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
  177. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
  178. package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
  179. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
  180. package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
  181. package/src/memory/migrations/index.ts +4 -0
  182. package/src/memory/migrations/registry.ts +90 -0
  183. package/src/memory/migrations/validate-migration-state.ts +137 -11
  184. package/src/memory/qdrant-circuit-breaker.ts +9 -0
  185. package/src/memory/qdrant-manager.ts +64 -7
  186. package/src/memory/schema/calls.ts +1 -0
  187. package/src/memory/schema/contacts.ts +1 -0
  188. package/src/notifications/decision-engine.ts +4 -1
  189. package/src/oauth/connection-resolver.ts +6 -4
  190. package/src/permissions/checker.ts +0 -38
  191. package/src/permissions/shell-identity.ts +76 -22
  192. package/src/permissions/types.ts +4 -2
  193. package/src/platform/client.ts +35 -7
  194. package/src/prompts/persona-resolver.ts +138 -0
  195. package/src/prompts/system-prompt.ts +36 -4
  196. package/src/prompts/templates/users/default.md +1 -0
  197. package/src/providers/registry.ts +27 -40
  198. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  199. package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
  200. package/src/runtime/auth/external-assistant-id.ts +13 -59
  201. package/src/runtime/auth/route-policy.ts +15 -1
  202. package/src/runtime/auth/token-service.ts +43 -138
  203. package/src/runtime/channel-readiness-service.ts +1 -16
  204. package/src/runtime/http-server.ts +27 -2
  205. package/src/runtime/middleware/error-handler.ts +1 -9
  206. package/src/runtime/routes/audio-routes.ts +40 -0
  207. package/src/runtime/routes/btw-routes.ts +0 -17
  208. package/src/runtime/routes/conversation-query-routes.ts +63 -1
  209. package/src/runtime/routes/conversation-routes.ts +4 -44
  210. package/src/runtime/routes/diagnostics-routes.ts +1 -477
  211. package/src/runtime/routes/identity-routes.ts +18 -29
  212. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
  213. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
  214. package/src/runtime/routes/integrations/vercel.ts +89 -0
  215. package/src/runtime/routes/log-export-routes.ts +5 -0
  216. package/src/runtime/routes/memory-item-routes.ts +24 -6
  217. package/src/runtime/routes/migration-rollback-routes.ts +209 -0
  218. package/src/runtime/routes/migration-routes.ts +17 -1
  219. package/src/runtime/routes/notification-routes.ts +58 -0
  220. package/src/runtime/routes/schedule-routes.ts +65 -0
  221. package/src/runtime/routes/settings-routes.ts +41 -1
  222. package/src/runtime/routes/tts-routes.ts +86 -0
  223. package/src/runtime/routes/upgrade-broadcast-routes.ts +26 -2
  224. package/src/runtime/routes/workspace-commit-routes.ts +62 -0
  225. package/src/runtime/routes/workspace-routes.test.ts +22 -1
  226. package/src/runtime/routes/workspace-routes.ts +1 -1
  227. package/src/runtime/routes/workspace-utils.ts +86 -2
  228. package/src/security/ces-credential-client.ts +59 -22
  229. package/src/security/ces-rpc-credential-backend.ts +85 -0
  230. package/src/security/credential-backend.ts +12 -88
  231. package/src/security/keychain-broker-client.ts +10 -2
  232. package/src/security/secure-keys.ts +94 -113
  233. package/src/skills/catalog-install.ts +13 -7
  234. package/src/telemetry/usage-telemetry-reporter.ts +4 -2
  235. package/src/tools/calls/call-start.ts +1 -0
  236. package/src/tools/executor.ts +0 -4
  237. package/src/tools/network/script-proxy/session-manager.ts +19 -4
  238. package/src/tools/network/web-fetch.ts +3 -1
  239. package/src/tools/skills/execute.ts +1 -1
  240. package/src/tools/types.ts +0 -8
  241. package/src/util/errors.ts +0 -12
  242. package/src/util/platform.ts +3 -50
  243. package/src/workspace/git-service.ts +5 -2
  244. package/src/workspace/migrations/001-avatar-rename.ts +15 -0
  245. package/src/workspace/migrations/003-seed-device-id.ts +17 -1
  246. package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
  247. package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
  248. package/src/workspace/migrations/006-services-config.ts +49 -0
  249. package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
  250. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
  251. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
  252. package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
  253. package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
  254. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
  255. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
  256. package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
  257. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
  258. package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
  259. package/src/workspace/migrations/017-seed-persona-dirs.ts +95 -0
  260. package/src/workspace/migrations/migrate-to-workspace-volume.ts +23 -1
  261. package/src/workspace/migrations/registry.ts +8 -0
  262. package/src/workspace/migrations/runner.ts +106 -2
  263. package/src/workspace/migrations/types.ts +4 -0
  264. package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
  265. package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
  266. package/src/__tests__/diagnostics-export.test.ts +0 -288
  267. package/src/__tests__/local-gateway-health.test.ts +0 -209
  268. package/src/__tests__/secret-ingress-handler.test.ts +0 -120
  269. package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
  270. package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
  271. package/src/__tests__/swarm-orchestrator.test.ts +0 -463
  272. package/src/__tests__/swarm-plan-validator.test.ts +0 -384
  273. package/src/__tests__/swarm-recursion.test.ts +0 -197
  274. package/src/__tests__/swarm-router-planner.test.ts +0 -234
  275. package/src/__tests__/swarm-tool.test.ts +0 -185
  276. package/src/__tests__/swarm-worker-backend.test.ts +0 -144
  277. package/src/__tests__/swarm-worker-runner.test.ts +0 -288
  278. package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
  279. package/src/commands/cc-command-registry.ts +0 -248
  280. package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
  281. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
  282. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
  283. package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
  284. package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
  285. package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
  286. package/src/config/schemas/swarm.ts +0 -82
  287. package/src/logfire.ts +0 -135
  288. package/src/runtime/local-gateway-health.ts +0 -275
  289. package/src/security/secret-ingress.ts +0 -68
  290. package/src/swarm/backend-claude-code.ts +0 -225
  291. package/src/swarm/checkpoint.ts +0 -137
  292. package/src/swarm/graph-utils.ts +0 -53
  293. package/src/swarm/index.ts +0 -55
  294. package/src/swarm/limits.ts +0 -66
  295. package/src/swarm/orchestrator.ts +0 -424
  296. package/src/swarm/plan-validator.ts +0 -117
  297. package/src/swarm/router-planner.ts +0 -162
  298. package/src/swarm/router-prompts.ts +0 -39
  299. package/src/swarm/synthesizer.ts +0 -81
  300. package/src/swarm/types.ts +0 -72
  301. package/src/swarm/worker-backend.ts +0 -131
  302. package/src/swarm/worker-prompts.ts +0 -80
  303. package/src/swarm/worker-runner.ts +0 -170
  304. package/src/tools/claude-code/claude-code.ts +0 -610
  305. package/src/tools/swarm/delegate.ts +0 -205
@@ -1,264 +1,69 @@
1
- # macOS Keychain Broker Architecture
1
+ # macOS Keychain Broker Architecture (Legacy)
2
2
 
3
- **Status:** Accepted
4
- **Last Updated:** 2026-03-14
3
+ **Status:** Superseded by CES credential routing
4
+ **Last Updated:** 2026-03-22
5
5
  **Owners:** macOS client + assistant runtime
6
6
 
7
- ## Decision
7
+ ## Current State
8
8
 
9
- Embed the keychain broker in the macOS app process rather than running a standalone daemon. The app exposes SecItem keychain operations over a Unix domain socket to the assistant runtime and gateway. Debug builds skip the broker entirely (`#if !DEBUG` guard) so developers never see keychain authorization prompts during rebuilds.
9
+ The daemon no longer uses the keychain broker for credential operations. Credential storage is routed through the Credential Execution Service (CES):
10
10
 
11
- Credential storage is abstracted behind a `CredentialBackend` interface with two implementations: a keychain backend (backed by the broker) and an encrypted file store backend. Each process resolves a single primary backend at startup and uses single-writer semantics -- all writes go to the resolved backend only, with no dual-writing.
11
+ 1. **CES RPC** (primary) -- stdio RPC to the CES process. Default path for all local modes (desktop app, dev, CLI).
12
+ 2. **CES HTTP** -- containerized/Docker/managed mode via `CES_CREDENTIAL_URL`.
13
+ 3. **Encrypted file store** (fallback) -- used when CES is unavailable.
12
14
 
13
- ## Problem Statement
15
+ See [`assistant/docs/credential-execution-service.md`](../credential-execution-service.md) for the current credential architecture.
14
16
 
15
- We want macOS to use Keychain as the primary secret store, but direct keychain access from the daemon process causes repeated authorization prompts. The prompts are especially problematic during development with ad-hoc signed builds, where every rebuild changes the signing identity and triggers a new keychain prompt.
17
+ ### What remains
16
18
 
17
- Prior state:
19
+ The keychain broker is not fully deleted. These components still exist:
18
20
 
19
- - macOS defaulted to encrypted file storage to avoid prompt fatigue: `assistant/src/security/secure-keys.ts`.
20
- - Historical comments documented prompt issues with ad-hoc signing: `clients/shared/App/SigningIdentityManager.swift`.
21
- - The `keychain.ts` module (now deleted) called `/usr/bin/security` CLI, which was unreliable and prompt-heavy.
21
+ | Component | Location | Why it exists |
22
+ |---|---|---|
23
+ | Keychain broker client | `assistant/src/security/keychain-broker-client.ts` | Used only by workspace migrations 015 and 016 |
24
+ | Migration 015 | `assistant/src/workspace/migrations/015-migrate-credentials-to-keychain.ts` | Historical migration that copied encrypted store credentials into keychain |
25
+ | Migration 016 | `assistant/src/workspace/migrations/016-migrate-credentials-from-keychain.ts` | Reverse migration that copies keychain credentials back to the encrypted store for CES unification |
26
+ | Swift broker server | `clients/macos/vellum-assistant/Security/KeychainBrokerServer.swift` | UDS server in the macOS app; still compiled for release builds (`#if !DEBUG`) |
27
+ | Swift broker service | `clients/macos/vellum-assistant/Security/KeychainBrokerService.swift` | `SecItem*` wrapper used by the broker server |
28
+ | Gateway credential reader | `gateway/src/credential-reader.ts` | Still tries the keychain broker as a secondary fallback after CES, before the encrypted store |
22
29
 
23
- ## Architecture
30
+ The broker client and Swift server remain because migrations 015/016 must be able to read/write the keychain for users who previously stored credentials there. These migrations are append-only and cannot be removed. The gateway's broker fallback provides a read path for credentials that may still be in the keychain during the migration window.
24
31
 
25
- ### CredentialBackend interface
32
+ ### What was removed
26
33
 
27
- All credential storage operations are routed through the `CredentialBackend` interface, which provides a uniform API for get, set, delete, and list operations. This abstraction decouples `secure-keys.ts` from any specific storage mechanism.
34
+ - **`KeychainBackend`** class and `createKeychainBackend()` factory -- the daemon's `CredentialBackend` implementation that wrapped the broker client. Removed from `credential-backend.ts`.
35
+ - **`resolveBackendAsync()` keychain resolution path** -- the daemon no longer considers `VELLUM_DESKTOP_APP` or `VELLUM_DEV` for backend selection. Backend resolution in `secure-keys.ts` now follows the CES RPC > CES HTTP > encrypted store priority.
36
+ - **Dual-writing and broker-unavailable commit behavior** -- the daemon previously committed to the keychain backend even when the broker socket was unreachable, causing operations to fail visibly. This behavior is gone; CES RPC is the primary backend with encrypted store as a graceful fallback.
28
37
 
29
- Two implementations exist:
38
+ ## Original Design (Historical)
30
39
 
31
- | Backend | Backing store | When used |
32
- | ---------------- | -------------------------------------------- | ----------------------------------------------------------------------- |
33
- | Keychain backend | macOS Keychain via the broker UDS connection | Production app context (`VELLUM_DEV` is NOT `"1"`) and broker available |
34
- | Encrypted store | `~/.vellum/protected/keys.enc` (AES-256-GCM) | `VELLUM_DEV=1`, broker unavailable, CLI-only, headless, CI |
40
+ The sections below document the original broker architecture for historical reference. They describe behavior that is no longer active in the daemon's credential resolution path.
35
41
 
36
- The interface is intentionally minimal to make adding future backends trivial -- e.g., Linux secret service (libsecret/D-Bus), 1Password CLI, or cloud KMS. A new backend only needs to implement the `CredentialBackend` interface and be wired into the backend resolution logic.
42
+ ### Original problem
37
43
 
38
- ### Broker topology
44
+ Direct keychain access from the daemon process caused repeated macOS authorization prompts, especially during development with ad-hoc signed builds where every rebuild changed the signing identity.
39
45
 
40
- ```mermaid
41
- graph LR
42
- subgraph "macOS App Process"
43
- SERVER["KeychainBrokerServer<br/>(NWListener on UDS)"]
44
- SERVICE["KeychainBrokerService<br/>(SecItem* wrapper)"]
45
- SERVER --> SERVICE
46
- SERVICE --> KC["macOS Keychain"]
47
- end
46
+ ### Original topology
48
47
 
49
- subgraph "Backend Resolution"
50
- RESOLVE{"resolveBackend()"}
51
- KB["Keychain Backend"]
52
- EB["Encrypted Store Backend"]
53
- RESOLVE -->|"VELLUM_DEV!=1<br/>+ broker available"| KB
54
- RESOLVE -->|"VELLUM_DEV=1<br/>OR broker unavailable"| EB
55
- end
48
+ The macOS app embedded a `KeychainBrokerServer` (NWListener on a Unix domain socket) that accepted JSON requests from the daemon and gateway, validated an auth token, and dispatched to `KeychainBrokerService` (a thin `SecItem*` wrapper). The daemon resolved either the keychain backend or encrypted store at startup based on `VELLUM_DESKTOP_APP` and `VELLUM_DEV` environment variables.
56
49
 
57
- KB -->|"UDS JSON"| SERVER
58
- RUNTIME["Assistant Runtime (Bun)"] --> RESOLVE
59
- GATEWAY["Gateway (Bun)"] -->|"read-only"| RESOLVE
50
+ ### Message contract
60
51
 
61
- EB --> ENC["Encrypted Store<br/>(~/.vellum/protected/keys.enc)"]
62
- ```
52
+ Transport: Unix domain socket at `~/.vellum/keychain-broker.sock`, newline-delimited JSON.
63
53
 
64
- ### Key properties
54
+ | Method | Params | Result |
55
+ |---|---|---|
56
+ | `broker.ping` | none | `{ pong: true }` |
57
+ | `key.get` | `{ account }` | `{ found, value? }` |
58
+ | `key.set` | `{ account, value }` | `{ stored: true }` |
59
+ | `key.delete` | `{ account }` | `{ deleted: true }` |
60
+ | `key.list` | none | `{ accounts: string[] }` |
65
61
 
66
- - **No separate process lifecycle.** The broker starts when the app starts and stops when the app stops. No launchd plist, no health checks, no orphan cleanup.
67
- - **No auth bootstrap problem.** The app writes the broker auth token to disk before launching the daemon, so the daemon always has a valid token at startup.
68
- - **No keychain prompts on signed builds.** Items are stored with `kSecAttrAccessibleAfterFirstUnlock` under the `vellum-assistant` service name. A stable code-signing identity means macOS grants access without prompting after the first unlock.
69
- - **No keychain interaction on debug builds.** The entire `KeychainBrokerServer` is compiled out with `#if !DEBUG`, so development builds use the encrypted file store exclusively.
70
- - **Single-writer to resolved backend.** Each process resolves exactly one primary backend at startup. Writes go only to that backend. There is no dual-writing.
71
- - **Encrypted file store as permanent fallback.** CLI-only, headless, and development environments always have the encrypted store (`~/.vellum/protected/keys.enc`) available.
62
+ This protocol is still used by migrations 015/016 via the broker client.
72
63
 
73
- ## Components
64
+ ### Security model
74
65
 
75
- ### Swift side (macOS app)
76
-
77
- | File | Role |
78
- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
79
- | `clients/macos/vellum-assistant/Security/KeychainBrokerServer.swift` | UDS server using `NWListener`. Accepts newline-delimited JSON requests, validates auth token, dispatches to `KeychainBrokerService`. Compiled only for `!DEBUG` builds. |
80
- | `clients/macos/vellum-assistant/Security/KeychainBrokerService.swift` | Thin `SecItem*` wrapper scoped to the `vellum-assistant` service. Provides `get`, `set`, `delete`, `list`. Uses `kSecAttrAccessibleAfterFirstUnlock`. Compiled only for `macOS`. |
81
-
82
- ### TypeScript side (runtime + gateway)
83
-
84
- | File | Role |
85
- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
86
- | `assistant/src/security/credential-backend.ts` | `CredentialBackend` interface definition (`get`, `set`, `delete`, `list`) plus both adapter implementations: `KeychainBackend` (backed by the broker UDS client) and `EncryptedStoreBackend` (backed by `encrypted-store.ts` / `~/.vellum/protected/keys.enc`). Also exports factory functions `createKeychainBackend()` and `createEncryptedStoreBackend()`. |
87
- | `assistant/src/security/keychain-broker-client.ts` | Async UDS client for the runtime. Persistent socket connection, request/response correlation, auth token caching with auto-refresh on `UNAUTHORIZED`. Falls back gracefully (returns safe defaults, never throws). |
88
- | `assistant/src/security/secure-keys.ts` | Unified API surface. Resolves a single primary `CredentialBackend` at startup based on environment and broker availability. All writes go to the resolved backend only (single-writer). Reads check the primary backend first, with legacy fallback to the encrypted store for migration. Deletes clean up both stores to prevent stale keys. |
89
- | `gateway/src/credential-reader.ts` | Read-only credential reader. Tries broker via native async UDS connection (`node:net`), falls back to encrypted store. All public credential read functions are async. |
90
-
91
- ## Message Contract
92
-
93
- ### Transport
94
-
95
- - Unix domain socket: `~/.vellum/keychain-broker.sock`
96
- - Socket path is derived from the data directory (e.g., `join(getRootDir(), "keychain-broker.sock")`)
97
- - Newline-delimited JSON (`\n` as message boundary)
98
-
99
- ### Request envelope
100
-
101
- ```json
102
- {
103
- "v": 1,
104
- "id": "uuid",
105
- "token": "hex-auth-token",
106
- "method": "key.get",
107
- "params": { "account": "anthropic" }
108
- }
109
- ```
110
-
111
- The `v` field is a protocol version number (currently `1`). The server rejects requests with unsupported versions.
112
-
113
- ### Response envelope
114
-
115
- Success:
116
-
117
- ```json
118
- {
119
- "id": "uuid",
120
- "ok": true,
121
- "result": { "found": true, "value": "sk-..." }
122
- }
123
- ```
124
-
125
- Error:
126
-
127
- ```json
128
- {
129
- "id": "uuid",
130
- "ok": false,
131
- "error": { "code": "UNAUTHORIZED", "message": "Invalid auth token" }
132
- }
133
- ```
134
-
135
- ### Methods
136
-
137
- | Method | Params | Result |
138
- | ------------- | -------------------- | ------------------------ |
139
- | `broker.ping` | none | `{ pong: true }` |
140
- | `key.get` | `{ account }` | `{ found, value? }` |
141
- | `key.set` | `{ account, value }` | `{ stored: true }` |
142
- | `key.delete` | `{ account }` | `{ deleted: true }` |
143
- | `key.list` | none | `{ accounts: string[] }` |
144
-
145
- ### Error codes
146
-
147
- - `UNAUTHORIZED` — invalid or missing auth token
148
- - `INVALID_REQUEST` — malformed request, missing params, or unsupported protocol version
149
- - `KEYCHAIN_ERROR` — SecItem operation failed
150
-
151
- ## Security Model
152
-
153
- ### Authentication
154
-
155
- 1. On app launch, the broker generates 32 random bytes via `SecRandomCopyBytes` and hex-encodes them as the auth token.
156
- 2. The token is written to `~/.vellum/protected/keychain-broker.token` with `0600` permissions. The parent directory is `0700`.
157
- 3. Every request must include the token. Requests with missing or invalid tokens are rejected before method dispatch.
158
- 4. If the app restarts (new token), the TS client detects `UNAUTHORIZED`, re-reads the token from disk, and retries once.
159
-
160
- ### Process boundary
161
-
162
- - The UDS itself restricts access to local processes.
163
- - The token file's `0600` permissions restrict readers to the same user.
164
- - Together: only same-user local processes that can read the token file can authenticate.
165
-
166
- ### Keychain access control
167
-
168
- - All items use `kSecAttrAccessibleAfterFirstUnlock` — secrets survive screen lock without re-prompting.
169
- - All items are scoped to the `vellum-assistant` service name via `kSecAttrService`.
170
- - On signed release builds, the stable code-signing identity means macOS trusts the app to access its own keychain items without prompting.
171
-
172
- ### Threat model
173
-
174
- | Threat | Mitigation |
175
- | ------------------------------------------- | ------------------------------------------------------------------------------------------ |
176
- | Other-user process reads secrets | UDS + token file `0600` restrict to same user |
177
- | Malicious local process impersonates broker | Client reads token from a known file path; attacker would need same-user file write access |
178
- | Stale socket from unclean exit | Server calls `unlink()` on the socket path before binding |
179
- | App restart invalidates cached token | Client detects `UNAUTHORIZED`, re-reads token, retries once |
180
-
181
- ### Future: XPC transport
182
-
183
- XPC provides stronger caller identity guarantees via audit tokens and code requirement checks. This would replace the file-based auth token with kernel-enforced caller verification, preventing same-user impersonation. No timeline — the UDS + token model is sufficient for the current threat profile.
184
-
185
- ## Developer Experience
186
-
187
- - **Debug builds:** The `#if !DEBUG` guard compiles out the entire `KeychainBrokerServer`. The broker socket is not created, so clients see the broker as unavailable and use the encrypted store. Developers never encounter keychain prompts during the edit-build-run cycle.
188
- - **Release builds:** The broker starts automatically with the app. The daemon discovers the broker via the derived socket path (`join(getRootDir(), "keychain-broker.sock")`) and token file. No configuration needed.
189
- - **CLI-only / headless:** No macOS app means no broker socket. All storage uses the encrypted file store. This is the expected path for CI, servers, and non-macOS platforms.
190
-
191
- ## Store-Routing Policy
192
-
193
- ### Backend resolution
194
-
195
- At process startup, `secure-keys.ts` resolves a single primary `CredentialBackend` for the lifetime of the process:
196
-
197
- | Condition | Resolved backend |
198
- | ----------------------------------------------------- | ---------------- |
199
- | `VELLUM_DEV` is NOT `"1"` **and** broker is available | Keychain backend |
200
- | `VELLUM_DEV=1` **or** broker is unavailable | Encrypted store |
201
-
202
- Once resolved, the backend does not change during the process lifetime. There is no runtime switching between backends.
203
-
204
- ### Read strategy
205
-
206
- Reads go to the **primary backend first**. If the primary backend is the keychain backend and the key is not found, a legacy fallback read is attempted against the encrypted store. This fallback handles the migration period where keys written before the single-writer policy may still exist only in the encrypted store. When the primary backend is the encrypted store, there is no fallback -- the encrypted store is the sole source of truth.
207
-
208
- ### Write strategy
209
-
210
- Writes go **only to the resolved primary backend**. There is no dual-writing. This eliminates the consistency problems that dual-writing introduced (partial failures leaving stores out of sync, unclear source of truth).
211
-
212
- - Keychain backend resolved: writes go to the keychain via broker only.
213
- - Encrypted store resolved: writes go to the encrypted file store only.
214
-
215
- ### Delete strategy
216
-
217
- Deletes **always clean up both stores** regardless of the resolved backend. This ensures that stale keys do not linger in the non-primary store, which could cause unexpected reads through the legacy fallback path.
218
-
219
- ### `VELLUM_DEV` environment variable
220
-
221
- Setting `VELLUM_DEV=1` forces the encrypted store as the sole backend, bypassing the keychain broker entirely even when the broker socket is available. This serves two purposes:
222
-
223
- 1. **Development ergonomics.** Developers running the daemon outside the macOS app context (e.g., `bun run` directly) avoid broker connectivity issues and keychain prompt noise.
224
- 2. **Deterministic testing.** Tests and CI environments get predictable encrypted-store-only behavior without depending on macOS Keychain infrastructure.
225
-
226
- When `VELLUM_DEV` is not set or is set to any value other than `"1"`, backend resolution proceeds normally (broker availability check).
227
-
228
- ## Callsite Policy
229
-
230
- ### Async-only policy
231
-
232
- **All credential access uses the async functions** (`getSecureKeyAsync`, `setSecureKeyAsync`, `deleteSecureKeyAsync`). These route through the resolved `CredentialBackend`, with legacy fallback reads to the encrypted store when the keychain backend is primary. The migration from sync to async is complete: the sync variants (`getSecureKey`, `setSecureKey`, `deleteSecureKey`) have been deleted and no longer exist in the codebase.
233
-
234
- ### Runtime request handlers (secret-routes, etc.)
235
-
236
- All runtime HTTP handlers that write or delete secrets use the async APIs (`setSecureKeyAsync`, `deleteSecureKeyAsync`). These are the primary entry points for macOS app flows and route through the resolved backend.
237
-
238
- ### Gateway (credential-reader)
239
-
240
- The gateway reads credentials via async `readCredential()` which tries the broker first (native async UDS), falling back to the encrypted store. The gateway never writes credentials -- that responsibility belongs to the assistant runtime.
241
-
242
- ### Sync function removal
243
-
244
- The sync secure-key functions (`getSecureKey`, `setSecureKey`, `deleteSecureKey`) have been deleted. All code uses the async variants (`getSecureKeyAsync`, `setSecureKeyAsync`, `deleteSecureKeyAsync`).
245
-
246
- ## Migration
247
-
248
- Existing encrypted store keys remain accessible through the legacy read fallback. When the keychain backend is the resolved primary, reads that miss in the keychain fall back to the encrypted store, so keys written before the single-writer policy are still reachable without a one-time migration step.
249
-
250
- Over time, as keys are re-written through normal credential update flows, they will be written only to the resolved primary backend. The legacy fallback read path will eventually become a no-op as all keys migrate naturally to the keychain.
251
-
252
- Deletes always clean up both stores, so stale keys in the non-primary store are removed as part of normal credential lifecycle operations.
253
-
254
- The old `keychain.ts` module (which called `/usr/bin/security` CLI directly) has been deleted. The old keychain-to-encrypted migration code has been removed. All keychain access now flows exclusively through the broker.
255
-
256
- ## Extensibility
257
-
258
- The `CredentialBackend` interface is the extension point for adding new storage backends. To add a new backend (e.g., Linux secret service via libsecret/D-Bus, 1Password CLI, cloud KMS):
259
-
260
- 1. Implement the `CredentialBackend` interface in a new module.
261
- 2. Wire the new backend into the resolution logic in `secure-keys.ts`.
262
- 3. The rest of the codebase is unaffected -- all callers go through the existing async API surface.
263
-
264
- No changes to callsites, the gateway, or the broker protocol are needed when adding a backend.
66
+ - Auth token: 32 random bytes via `SecRandomCopyBytes`, written to `~/.vellum/protected/keychain-broker.token` (0600).
67
+ - UDS restricts to local processes; token file restricts to same user.
68
+ - Keychain items use `kSecAttrAccessibleAfterFirstUnlock` under the `vellum-assistant` service name.
69
+ - Debug builds compile out the entire broker server (`#if !DEBUG`).
@@ -249,22 +249,6 @@ sequenceDiagram
249
249
  end
250
250
  ```
251
251
 
252
- ### Secret Ingress Blocking
253
-
254
- ```mermaid
255
- graph TB
256
- MSG["Inbound user_message / task_submit"] --> CHECK{"secretDetection.enabled<br/>+ blockIngress == true?"}
257
- CHECK -->|no| PASS["Pass through to session"]
258
- CHECK -->|yes| SCAN["scanText(content)<br/>regex + entropy detection"]
259
- SCAN --> MATCH{"Matches found?"}
260
- MATCH -->|no| PASS
261
- MATCH -->|yes| BLOCK["Block message"]
262
- BLOCK --> NOTIFY["Send error to client:<br/>'Message contains sensitive info'"]
263
- BLOCK --> LOG["Log warning with<br/>detectedTypes + matchCount<br/>(never the secret itself)"]
264
- ```
265
-
266
- The secret scanner includes pattern-based detection for Telegram bot tokens (format: `<8-10 digit bot_id>:<35-char secret>`), API keys from major providers, Slack tokens, and other common secret formats. This prevents users from accidentally pasting a Telegram bot token in chat — the token must be entered through the secure credential prompt flow or the Settings UI instead.
267
-
268
252
  ### Brokered Credential Use
269
253
 
270
254
  ```mermaid
@@ -305,7 +289,6 @@ The `allowOneTimeSend` config gate (default: `false`) enables a secondary "Send
305
289
  | `assistant/src/tools/credentials/policy-validate.ts` | Policy input validation (allowedTools, allowedDomains) |
306
290
  | `assistant/src/permissions/secret-prompter.ts` | HTTP secret_request/secret_response flow |
307
291
  | `assistant/src/security/secret-scanner.ts` | Regex + entropy-based secret detection |
308
- | `assistant/src/security/secret-ingress.ts` | Inbound message secret blocking |
309
292
  | `clients/macos/.../SecretPromptManager.swift` | Floating panel UI for secure credential entry |
310
293
 
311
294
  ---
@@ -251,11 +251,11 @@ To dark-launch CES in managed deployments without user impact:
251
251
 
252
252
  1. **Deploy the CES container image** via the `credential_executor_image` field in `POST /v1/internal/assistant-image-releases/`. The warm-pool manager picks it up and includes it in pod templates. The CES container starts, binds its bootstrap socket and health port (8090), but does nothing until an assistant connects.
253
253
 
254
- 2. **Verify sidecar health** using kubelet probes: `/healthz` (liveness) and `/readyz` (readiness, always returns 200; includes `rpcConnected` field for observability). CES reports its protocol version in both probe responses.
254
+ 2. **Verify sidecar health** using kubelet probes: `/healthz` (liveness, returns `{"status": "ok"}`) and `/readyz` (readiness, always returns 200; includes `rpcConnected` field for observability).
255
255
 
256
256
  3. **Enable `ces-tools`** first on a test cohort. The assistant spawns a local CES child process and registers tools. Verify tool registration, grant creation, and audit logging work end-to-end without affecting existing workflows.
257
257
 
258
- 4. **Enable `ces-managed-sidecar`** on the same cohort. The assistant switches from child-process transport to the bootstrap Unix socket. CES `/readyz` always returns 200; check the `rpcConnected` field in the response body to verify the assistant has connected.
258
+ 4. **Enable `ces-managed-sidecar`** on the same cohort. The assistant switches from child-process transport to the bootstrap Unix socket. CES `/readyz` always returns 200 with `{"status": "ok", "rpcConnected": <boolean>}`; check the `rpcConnected` field to verify the assistant has connected.
259
259
 
260
260
  5. **Progressive rollout**: Widen the cohort by enabling flags on more assistants. Monitor for grant failures, materializer errors, and egress proxy issues.
261
261
 
@@ -2,6 +2,7 @@
2
2
  "name": "@vellumai/ces-contracts",
3
3
  "version": "0.0.1",
4
4
  "private": true,
5
+ "license": "MIT",
5
6
  "type": "module",
6
7
  "exports": {
7
8
  ".": "./src/index.ts",
@@ -25,6 +25,12 @@
25
25
  *
26
26
  * **Lifecycle**
27
27
  * - `update_managed_credential` — Push an updated API key to CES after hatch
28
+ *
29
+ * **Credential CRUD**
30
+ * - `get_credential` — Retrieve a credential by account name
31
+ * - `set_credential` — Store or update a credential
32
+ * - `delete_credential` — Delete a credential by account name
33
+ * - `list_credentials` — List all credential account names
28
34
  */
29
35
 
30
36
  import { z } from "zod/v4";
@@ -51,6 +57,14 @@ export const CesRpcMethod = {
51
57
  ListAuditRecords: "list_audit_records",
52
58
  /** Push an updated assistant credential to CES after post-hatch provisioning. */
53
59
  UpdateManagedCredential: "update_managed_credential",
60
+ /** Retrieve a single credential by account name. */
61
+ GetCredential: "get_credential",
62
+ /** Store or update a credential by account name. */
63
+ SetCredential: "set_credential",
64
+ /** Delete a credential by account name. */
65
+ DeleteCredential: "delete_credential",
66
+ /** List all credential account names. */
67
+ ListCredentials: "list_credentials",
54
68
  } as const;
55
69
 
56
70
  export type CesRpcMethod =
@@ -421,6 +435,79 @@ export type UpdateManagedCredentialResponse = z.infer<
421
435
  typeof UpdateManagedCredentialResponseSchema
422
436
  >;
423
437
 
438
+ // ---------------------------------------------------------------------------
439
+ // get_credential
440
+ // ---------------------------------------------------------------------------
441
+
442
+ export const GetCredentialSchema = z.object({
443
+ /** The account name to look up. */
444
+ account: z.string(),
445
+ });
446
+ export type GetCredential = z.infer<typeof GetCredentialSchema>;
447
+
448
+ export const GetCredentialResponseSchema = z.object({
449
+ /** Whether the credential was found. */
450
+ found: z.boolean(),
451
+ /** The credential value (present only when found). */
452
+ value: z.string().optional(),
453
+ });
454
+ export type GetCredentialResponse = z.infer<
455
+ typeof GetCredentialResponseSchema
456
+ >;
457
+
458
+ // ---------------------------------------------------------------------------
459
+ // set_credential
460
+ // ---------------------------------------------------------------------------
461
+
462
+ export const SetCredentialSchema = z.object({
463
+ /** The account name to store the credential under. */
464
+ account: z.string(),
465
+ /** The credential value to store. */
466
+ value: z.string(),
467
+ });
468
+ export type SetCredential = z.infer<typeof SetCredentialSchema>;
469
+
470
+ export const SetCredentialResponseSchema = z.object({
471
+ /** Whether the credential was successfully stored. */
472
+ ok: z.boolean(),
473
+ });
474
+ export type SetCredentialResponse = z.infer<
475
+ typeof SetCredentialResponseSchema
476
+ >;
477
+
478
+ // ---------------------------------------------------------------------------
479
+ // delete_credential
480
+ // ---------------------------------------------------------------------------
481
+
482
+ export const DeleteCredentialSchema = z.object({
483
+ /** The account name to delete. */
484
+ account: z.string(),
485
+ });
486
+ export type DeleteCredential = z.infer<typeof DeleteCredentialSchema>;
487
+
488
+ export const DeleteCredentialResponseSchema = z.object({
489
+ /** The result of the delete operation. */
490
+ result: z.enum(["deleted", "not-found", "error"]),
491
+ });
492
+ export type DeleteCredentialResponse = z.infer<
493
+ typeof DeleteCredentialResponseSchema
494
+ >;
495
+
496
+ // ---------------------------------------------------------------------------
497
+ // list_credentials
498
+ // ---------------------------------------------------------------------------
499
+
500
+ export const ListCredentialsSchema = z.object({});
501
+ export type ListCredentials = z.infer<typeof ListCredentialsSchema>;
502
+
503
+ export const ListCredentialsResponseSchema = z.object({
504
+ /** The account names of all stored credentials. */
505
+ accounts: z.array(z.string()),
506
+ });
507
+ export type ListCredentialsResponse = z.infer<
508
+ typeof ListCredentialsResponseSchema
509
+ >;
510
+
424
511
  // ---------------------------------------------------------------------------
425
512
  // Full RPC contract type map
426
513
  // ---------------------------------------------------------------------------
@@ -466,6 +553,22 @@ export interface CesRpcContract {
466
553
  request: UpdateManagedCredential;
467
554
  response: UpdateManagedCredentialResponse;
468
555
  };
556
+ [CesRpcMethod.GetCredential]: {
557
+ request: GetCredential;
558
+ response: GetCredentialResponse;
559
+ };
560
+ [CesRpcMethod.SetCredential]: {
561
+ request: SetCredential;
562
+ response: SetCredentialResponse;
563
+ };
564
+ [CesRpcMethod.DeleteCredential]: {
565
+ request: DeleteCredential;
566
+ response: DeleteCredentialResponse;
567
+ };
568
+ [CesRpcMethod.ListCredentials]: {
569
+ request: ListCredentials;
570
+ response: ListCredentialsResponse;
571
+ };
469
572
  }
470
573
 
471
574
  /**
@@ -508,4 +611,20 @@ export const CesRpcSchemas = {
508
611
  request: UpdateManagedCredentialSchema,
509
612
  response: UpdateManagedCredentialResponseSchema,
510
613
  },
614
+ [CesRpcMethod.GetCredential]: {
615
+ request: GetCredentialSchema,
616
+ response: GetCredentialResponseSchema,
617
+ },
618
+ [CesRpcMethod.SetCredential]: {
619
+ request: SetCredentialSchema,
620
+ response: SetCredentialResponseSchema,
621
+ },
622
+ [CesRpcMethod.DeleteCredential]: {
623
+ request: DeleteCredentialSchema,
624
+ response: DeleteCredentialResponseSchema,
625
+ },
626
+ [CesRpcMethod.ListCredentials]: {
627
+ request: ListCredentialsSchema,
628
+ response: ListCredentialsResponseSchema,
629
+ },
511
630
  } as const;
@@ -2,6 +2,7 @@
2
2
  "name": "@vellumai/credential-storage",
3
3
  "version": "0.0.1",
4
4
  "private": true,
5
+ "license": "MIT",
5
6
  "type": "module",
6
7
  "exports": {
7
8
  ".": "./src/index.ts"
@@ -2,6 +2,7 @@
2
2
  "name": "@vellumai/egress-proxy",
3
3
  "version": "0.0.1",
4
4
  "private": true,
5
+ "license": "MIT",
5
6
  "type": "module",
6
7
  "exports": {
7
8
  ".": "./src/index.ts"
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.5.6",
3
+ "version": "0.5.7",
4
+ "license": "MIT",
4
5
  "type": "module",
5
6
  "exports": {
6
7
  ".": "./src/index.ts"
@@ -28,7 +29,6 @@
28
29
  },
29
30
  "dependencies": {
30
31
  "@agentclientprotocol/sdk": "^0.16.1",
31
- "@anthropic-ai/claude-agent-sdk": "^0.2.42",
32
32
  "@anthropic-ai/sdk": "^0.78.0",
33
33
  "@google/genai": "^1.40.0",
34
34
  "@modelcontextprotocol/sdk": "^1.15.1",
@@ -70,7 +70,6 @@
70
70
  "@vellumai/egress-proxy"
71
71
  ],
72
72
  "devDependencies": {
73
- "@pydantic/logfire-node": "^0.13.0",
74
73
  "@types/archiver": "^7.0.0",
75
74
  "@types/bun": "^1.2.4",
76
75
  "@types/node": "^25.2.2",