@pellux/goodvibes-tui 0.18.4 → 0.18.9

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 (571) hide show
  1. package/CHANGELOG.md +190 -0
  2. package/README.md +2 -2
  3. package/bin/goodvibes +1 -1
  4. package/bin/goodvibes-daemon +66 -0
  5. package/docs/foundation-artifacts/operator-contract.json +1 -1
  6. package/package.json +14 -7
  7. package/scripts/postinstall.js +220 -0
  8. package/src/acp/connection.ts +5 -5
  9. package/src/acp/index.ts +1 -1
  10. package/src/acp/manager.ts +1 -133
  11. package/src/adapters/bluebubbles/index.ts +1 -1
  12. package/src/adapters/discord/index.ts +2 -2
  13. package/src/adapters/github/index.ts +1 -1
  14. package/src/adapters/google-chat/index.ts +1 -1
  15. package/src/adapters/imessage/index.ts +1 -1
  16. package/src/adapters/index.ts +15 -15
  17. package/src/adapters/matrix/index.ts +1 -1
  18. package/src/adapters/mattermost/index.ts +1 -1
  19. package/src/adapters/msteams/index.ts +2 -2
  20. package/src/adapters/ntfy/index.ts +1 -1
  21. package/src/adapters/signal/index.ts +1 -1
  22. package/src/adapters/slack/index.ts +2 -2
  23. package/src/adapters/telegram/index.ts +1 -1
  24. package/src/adapters/types.ts +4 -4
  25. package/src/adapters/webhook/index.ts +1 -1
  26. package/src/adapters/whatsapp/index.ts +1 -1
  27. package/src/agents/message-bus-core.ts +2 -2
  28. package/src/agents/message-bus.ts +2 -2
  29. package/src/agents/orchestrator-prompts.ts +4 -4
  30. package/src/agents/orchestrator-runner.ts +11 -11
  31. package/src/agents/orchestrator.ts +15 -14
  32. package/src/agents/session.ts +1 -1
  33. package/src/agents/worktree.ts +1 -1
  34. package/src/agents/wrfc-config.ts +2 -2
  35. package/src/agents/wrfc-controller.ts +12 -12
  36. package/src/agents/wrfc-gate-runtime.ts +5 -5
  37. package/src/agents/wrfc-reporting.ts +1 -1
  38. package/src/agents/wrfc-runtime-events.ts +3 -3
  39. package/src/agents/wrfc-types.ts +1 -1
  40. package/src/automation/delivery-manager.ts +4 -4
  41. package/src/automation/index.ts +4 -4
  42. package/src/automation/manager-runtime-delivery.ts +1 -1
  43. package/src/automation/manager-runtime-events.ts +3 -3
  44. package/src/automation/manager-runtime-execution.ts +5 -5
  45. package/src/automation/manager-runtime-helpers.ts +2 -2
  46. package/src/automation/manager-runtime-job-mutations.ts +3 -3
  47. package/src/automation/manager-runtime-reconcile.ts +4 -4
  48. package/src/automation/manager-runtime-scheduling.ts +2 -2
  49. package/src/automation/manager-runtime.ts +18 -18
  50. package/src/automation/manager.ts +2 -2
  51. package/src/automation/service.ts +2 -2
  52. package/src/channels/builtin/account-actions.ts +5 -5
  53. package/src/channels/builtin/accounts.ts +2 -2
  54. package/src/channels/builtin/contracts.ts +3 -3
  55. package/src/channels/builtin/plugins.ts +5 -5
  56. package/src/channels/builtin/rendering.ts +4 -4
  57. package/src/channels/builtin/setup-schema.ts +1 -1
  58. package/src/channels/builtin/shared.ts +7 -7
  59. package/src/channels/builtin/surfaces.ts +2 -2
  60. package/src/channels/builtin/targets.ts +3 -3
  61. package/src/channels/builtin-runtime.ts +11 -11
  62. package/src/channels/delivery/shared.ts +2 -2
  63. package/src/channels/delivery/strategies-bridge.ts +3 -3
  64. package/src/channels/delivery/strategies-core.ts +5 -5
  65. package/src/channels/delivery/strategies-enterprise.ts +3 -3
  66. package/src/channels/delivery/types.ts +2 -2
  67. package/src/channels/delivery-router.ts +9 -9
  68. package/src/channels/index.ts +12 -12
  69. package/src/channels/plugin-registry.ts +1 -1
  70. package/src/channels/provider-runtime.ts +3 -3
  71. package/src/channels/reply-pipeline.ts +3 -3
  72. package/src/channels/route-manager.ts +2 -2
  73. package/src/channels/surface-registry.ts +2 -2
  74. package/src/config/helper-model.ts +1 -233
  75. package/src/config/index.ts +3 -3
  76. package/src/config/manager.ts +8 -404
  77. package/src/config/secrets.ts +21 -542
  78. package/src/config/service-registry.ts +1 -329
  79. package/src/config/tool-llm.ts +3 -3
  80. package/src/control-plane/approval-broker.ts +1 -1
  81. package/src/control-plane/gateway.ts +1 -713
  82. package/src/control-plane/index.ts +7 -7
  83. package/src/control-plane/media-contract-schemas.ts +1 -208
  84. package/src/control-plane/method-catalog-admin.ts +1 -136
  85. package/src/control-plane/method-catalog-channels.ts +1 -591
  86. package/src/control-plane/method-catalog-control-automation.ts +1 -475
  87. package/src/control-plane/method-catalog-control-core.ts +1 -594
  88. package/src/control-plane/method-catalog-control.ts +1 -8
  89. package/src/control-plane/method-catalog-events.ts +1 -74
  90. package/src/control-plane/method-catalog-knowledge.ts +1 -531
  91. package/src/control-plane/method-catalog-media.ts +1 -279
  92. package/src/control-plane/method-catalog-runtime.ts +1 -304
  93. package/src/control-plane/method-catalog-shared.ts +1 -223
  94. package/src/control-plane/method-catalog.ts +1 -242
  95. package/src/control-plane/operator-contract-schemas-admin.ts +1 -639
  96. package/src/control-plane/operator-contract-schemas-channels.ts +1 -375
  97. package/src/control-plane/operator-contract-schemas-control.ts +1 -226
  98. package/src/control-plane/operator-contract-schemas-domains.ts +1 -4
  99. package/src/control-plane/operator-contract-schemas-knowledge.ts +1 -582
  100. package/src/control-plane/operator-contract-schemas-media.ts +1 -297
  101. package/src/control-plane/operator-contract-schemas-permissions.ts +1 -100
  102. package/src/control-plane/operator-contract-schemas-remote.ts +1 -38
  103. package/src/control-plane/operator-contract-schemas-runtime.ts +1 -563
  104. package/src/control-plane/operator-contract-schemas-shared.ts +1 -85
  105. package/src/control-plane/operator-contract-schemas-telemetry.ts +1 -349
  106. package/src/control-plane/operator-contract-schemas.ts +1 -6
  107. package/src/control-plane/operator-contract.ts +5 -3
  108. package/src/control-plane/session-broker.ts +1 -1
  109. package/src/core/compaction-sections.ts +5 -5
  110. package/src/core/compaction-types.ts +3 -3
  111. package/src/core/composer-state.ts +1 -1
  112. package/src/core/context-compaction.ts +7 -7
  113. package/src/core/conversation-compaction.ts +4 -4
  114. package/src/core/conversation-diff.ts +1 -1
  115. package/src/core/conversation-rendering.ts +5 -5
  116. package/src/core/conversation-utils.ts +2 -2
  117. package/src/core/conversation.ts +10 -10
  118. package/src/core/event-replay.ts +1 -1
  119. package/src/core/orchestrator-context-runtime.ts +8 -8
  120. package/src/core/orchestrator-follow-up-runtime.ts +2 -2
  121. package/src/core/orchestrator-runtime.ts +4 -4
  122. package/src/core/orchestrator-tool-runtime.ts +7 -7
  123. package/src/core/orchestrator-turn-helpers.ts +7 -7
  124. package/src/core/orchestrator-turn-loop.ts +10 -10
  125. package/src/core/orchestrator.ts +17 -17
  126. package/src/core/plan-command-handler.ts +2 -2
  127. package/src/core/system-message-router.ts +2 -2
  128. package/src/core/transcript-events/classify.ts +1 -1
  129. package/src/core/transcript-events/index.ts +3 -3
  130. package/src/daemon/cli.ts +6 -6
  131. package/src/daemon/control-plane.ts +7 -7
  132. package/src/daemon/facade-composition.ts +16 -15
  133. package/src/daemon/facade.ts +17 -17
  134. package/src/daemon/helpers.ts +2 -2
  135. package/src/daemon/http/router-route-contexts.ts +11 -11
  136. package/src/daemon/http/router.ts +25 -25
  137. package/src/daemon/http-listener.ts +3 -3
  138. package/src/daemon/index.ts +1 -3
  139. package/src/daemon/service-manager.ts +1 -1
  140. package/src/daemon/surface-actions.ts +8 -8
  141. package/src/daemon/surface-delivery.ts +7 -7
  142. package/src/daemon/surface-policy.ts +1 -1
  143. package/src/daemon/transport-events.ts +4 -4
  144. package/src/daemon/types.ts +24 -24
  145. package/src/export/markdown.ts +1 -1
  146. package/src/export/session-export.ts +1 -633
  147. package/src/git/index.ts +1 -1
  148. package/src/git/service.ts +1 -1
  149. package/src/hooks/chain-engine.ts +1 -1
  150. package/src/hooks/dispatcher.ts +4 -4
  151. package/src/hooks/hook-api.ts +1 -1
  152. package/src/hooks/index.ts +8 -8
  153. package/src/hooks/runners/agent.ts +1 -1
  154. package/src/hooks/runners/prompt.ts +1 -1
  155. package/src/hooks/workbench.ts +2 -2
  156. package/src/input/command-registry.ts +24 -17
  157. package/src/input/commands/config.ts +1 -1
  158. package/src/input/commands/control-room-runtime.ts +2 -2
  159. package/src/input/commands/conversation-runtime.ts +1 -1
  160. package/src/input/commands/discovery-runtime.ts +7 -1
  161. package/src/input/commands/eval.ts +2 -2
  162. package/src/input/commands/git-runtime.ts +1 -1
  163. package/src/input/commands/guidance-runtime.ts +3 -3
  164. package/src/input/commands/health-runtime.ts +7 -7
  165. package/src/input/commands/incident-runtime.ts +1 -1
  166. package/src/input/commands/integration-runtime.ts +3 -3
  167. package/src/input/commands/local-provider-runtime.ts +1 -1
  168. package/src/input/commands/local-runtime.ts +1 -1
  169. package/src/input/commands/local-setup-review.ts +2 -2
  170. package/src/input/commands/local-setup.ts +2 -2
  171. package/src/input/commands/managed-runtime.ts +2 -2
  172. package/src/input/commands/marketplace-runtime.ts +1 -1
  173. package/src/input/commands/platform-access-runtime.ts +1 -1
  174. package/src/input/commands/platform-sandbox-qemu.ts +3 -3
  175. package/src/input/commands/platform-sandbox-runtime.ts +5 -5
  176. package/src/input/commands/platform-sandbox-session.ts +1 -1
  177. package/src/input/commands/policy-dispatch.ts +2 -2
  178. package/src/input/commands/product-runtime.ts +2 -2
  179. package/src/input/commands/profile-sync-runtime.ts +1 -1
  180. package/src/input/commands/provider-accounts-runtime.ts +1 -1
  181. package/src/input/commands/provider.ts +3 -3
  182. package/src/input/commands/quit-shared.ts +1 -1
  183. package/src/input/commands/recall-bundle.ts +1 -1
  184. package/src/input/commands/recall-capture.ts +2 -2
  185. package/src/input/commands/recall-query.ts +2 -2
  186. package/src/input/commands/recall-shared.ts +1 -1
  187. package/src/input/commands/remote-runtime-setup.ts +1 -1
  188. package/src/input/commands/remote-runtime.ts +1 -1
  189. package/src/input/commands/runtime-services.ts +13 -11
  190. package/src/input/commands/schedule-runtime.ts +2 -2
  191. package/src/input/commands/session-content.ts +1 -1
  192. package/src/input/commands/session-workflow.ts +4 -4
  193. package/src/input/commands/settings-sync-runtime.ts +1 -1
  194. package/src/input/commands/share-runtime.ts +9 -4
  195. package/src/input/commands/shell-core.ts +1 -1
  196. package/src/input/commands/skills-runtime.ts +1 -1
  197. package/src/input/commands/subscription-runtime.ts +1 -1
  198. package/src/input/commands/tasks-runtime.ts +1 -1
  199. package/src/input/commands/teamwork-runtime.ts +1 -1
  200. package/src/input/commands/worktree-runtime.ts +1 -1
  201. package/src/input/handler-command-route.ts +1 -1
  202. package/src/input/handler-content-actions.ts +3 -3
  203. package/src/input/handler-feed-routes.ts +2 -2
  204. package/src/input/handler-feed.ts +1 -1
  205. package/src/input/handler-shortcuts.ts +1 -1
  206. package/src/input/handler.ts +1 -1
  207. package/src/input/keybindings.ts +5 -0
  208. package/src/input/model-picker.ts +2 -2
  209. package/src/input/profile-picker-modal.ts +1 -1
  210. package/src/input/session-picker-modal.ts +1 -1
  211. package/src/input/settings-modal.ts +4 -4
  212. package/src/integrations/index.ts +1 -1
  213. package/src/integrations/notifier.ts +1 -1
  214. package/src/integrations/webhooks.ts +1 -177
  215. package/src/knowledge/consolidation.ts +2 -2
  216. package/src/knowledge/graphql.ts +1 -1
  217. package/src/knowledge/index.ts +5 -5
  218. package/src/knowledge/ingest-compile.ts +3 -3
  219. package/src/knowledge/ingest-context.ts +1 -1
  220. package/src/knowledge/ingest-inputs.ts +4 -4
  221. package/src/knowledge/ingest.ts +1 -20
  222. package/src/knowledge/internal.ts +1 -1
  223. package/src/knowledge/knowledge-api.ts +7 -7
  224. package/src/knowledge/lint.ts +3 -3
  225. package/src/knowledge/memory-sync.ts +2 -2
  226. package/src/knowledge/packet.ts +3 -3
  227. package/src/knowledge/scheduling.ts +2 -2
  228. package/src/knowledge/service.ts +10 -10
  229. package/src/main.ts +11 -10
  230. package/src/mcp/index.ts +4 -4
  231. package/src/mcp/mcp-api.ts +1 -1
  232. package/src/mcp/registry.ts +1 -508
  233. package/src/media/builtin-image-understanding.ts +2 -2
  234. package/src/media/builtin-providers.ts +2 -2
  235. package/src/media/index.ts +1 -1
  236. package/src/multimodal/index.ts +1 -1
  237. package/src/multimodal/service.ts +2 -2
  238. package/src/panels/agent-inspector-panel.ts +2 -2
  239. package/src/panels/agent-logs-panel.ts +3 -3
  240. package/src/panels/approval-panel.ts +2 -2
  241. package/src/panels/builtin/operations.ts +3 -1
  242. package/src/panels/builtin/shared.ts +14 -14
  243. package/src/panels/context-visualizer-panel.ts +2 -2
  244. package/src/panels/cost-tracker-panel.ts +2 -2
  245. package/src/panels/debug-panel.ts +3 -3
  246. package/src/panels/git-panel.ts +1 -1
  247. package/src/panels/hooks-panel.ts +4 -4
  248. package/src/panels/knowledge-panel.ts +1 -1
  249. package/src/panels/marketplace-panel.ts +1 -1
  250. package/src/panels/mcp-panel.ts +1 -1
  251. package/src/panels/memory-panel.ts +2 -2
  252. package/src/panels/ops-control-panel.ts +2 -2
  253. package/src/panels/ops-strategy-panel.ts +2 -2
  254. package/src/panels/plugins-panel.ts +1 -1
  255. package/src/panels/policy-panel.ts +1 -1
  256. package/src/panels/provider-health-panel.ts +3 -3
  257. package/src/panels/provider-stats-panel.ts +2 -2
  258. package/src/panels/sandbox-panel.ts +3 -3
  259. package/src/panels/schedule-panel.ts +1 -1
  260. package/src/panels/settings-sync-panel.ts +1 -1
  261. package/src/panels/skills-panel.ts +28 -1
  262. package/src/panels/system-messages-panel.ts +1 -1
  263. package/src/panels/tasks-panel.ts +1 -1
  264. package/src/panels/thinking-panel.ts +2 -2
  265. package/src/panels/token-budget-panel.ts +1 -1
  266. package/src/panels/tool-inspector-panel.ts +2 -2
  267. package/src/panels/worktree-panel.ts +1 -1
  268. package/src/panels/wrfc-panel.ts +4 -4
  269. package/src/permissions/briefs/build.ts +1 -1
  270. package/src/permissions/manager.ts +1 -356
  271. package/src/permissions/prompt.ts +1 -1
  272. package/src/plugins/api.ts +9 -9
  273. package/src/plugins/loader.ts +8 -8
  274. package/src/plugins/manager.ts +5 -5
  275. package/src/providers/amazon-bedrock-mantle.ts +1 -1
  276. package/src/providers/amazon-bedrock.ts +1 -1
  277. package/src/providers/anthropic-compat.ts +4 -4
  278. package/src/providers/anthropic-sdk-provider.ts +5 -5
  279. package/src/providers/anthropic-vertex.ts +1 -1
  280. package/src/providers/anthropic.ts +4 -4
  281. package/src/providers/auto-register.ts +6 -6
  282. package/src/providers/builtin-catalog.ts +2 -2
  283. package/src/providers/builtin-registry.ts +15 -15
  284. package/src/providers/cache-planner.ts +2 -2
  285. package/src/providers/capabilities.ts +1 -601
  286. package/src/providers/custom-loader.ts +6 -6
  287. package/src/providers/discovered-compat.ts +7 -18
  288. package/src/providers/discovered-factory.ts +7 -7
  289. package/src/providers/discovered-traits.ts +1 -1
  290. package/src/providers/gemini.ts +4 -4
  291. package/src/providers/github-copilot.ts +4 -4
  292. package/src/providers/index.ts +1 -47
  293. package/src/providers/interface.ts +1 -1
  294. package/src/providers/llama-cpp.ts +4 -4
  295. package/src/providers/lm-studio-helpers.ts +1 -1
  296. package/src/providers/lm-studio.ts +4 -4
  297. package/src/providers/model-catalog-cache.ts +1 -1
  298. package/src/providers/model-catalog-notifications.ts +1 -1
  299. package/src/providers/model-catalog-synthetic.ts +2 -2
  300. package/src/providers/model-catalog.ts +7 -7
  301. package/src/providers/model-limits.ts +1 -280
  302. package/src/providers/ollama.ts +4 -4
  303. package/src/providers/openai-codex.ts +2 -2
  304. package/src/providers/openai-compat.ts +4 -4
  305. package/src/providers/openai.ts +3 -3
  306. package/src/providers/optimizer.ts +1 -381
  307. package/src/providers/provider-api.ts +1 -553
  308. package/src/providers/registry-helpers.ts +1 -1
  309. package/src/providers/registry-models.ts +2 -2
  310. package/src/providers/registry-types.ts +5 -5
  311. package/src/providers/registry.ts +1 -729
  312. package/src/providers/runtime-metadata.ts +1 -1
  313. package/src/providers/runtime-snapshot.ts +3 -3
  314. package/src/providers/synthetic.ts +3 -3
  315. package/src/providers/tier-prompts.ts +1 -1
  316. package/src/providers/tool-formats.ts +1 -1
  317. package/src/renderer/agent-detail-modal.ts +2 -2
  318. package/src/renderer/block-actions.ts +1 -1
  319. package/src/renderer/context-inspector.ts +1 -1
  320. package/src/renderer/conversation-layout.ts +1 -1
  321. package/src/renderer/conversation-overlays.ts +1 -1
  322. package/src/renderer/git-status.ts +1 -1
  323. package/src/renderer/live-tail-modal.ts +1 -1
  324. package/src/renderer/process-modal.ts +2 -2
  325. package/src/runtime/bootstrap-background.ts +18 -8
  326. package/src/runtime/bootstrap-command-context.ts +24 -24
  327. package/src/runtime/bootstrap-command-parts.ts +24 -24
  328. package/src/runtime/bootstrap-core.ts +12 -10
  329. package/src/runtime/bootstrap-helpers.ts +2 -2
  330. package/src/runtime/bootstrap-hook-bridge.ts +9 -9
  331. package/src/runtime/bootstrap-runtime-events.ts +4 -4
  332. package/src/runtime/bootstrap-services.ts +4 -4
  333. package/src/runtime/bootstrap-shell.ts +11 -11
  334. package/src/runtime/bootstrap.ts +28 -10
  335. package/src/runtime/compaction/index.ts +1 -90
  336. package/src/runtime/compaction/lifecycle.ts +1 -167
  337. package/src/runtime/compaction/manager.ts +11 -11
  338. package/src/runtime/compaction/quality-score.ts +1 -279
  339. package/src/runtime/compaction/resume-repair.ts +1 -183
  340. package/src/runtime/compaction/strategies/autocompact.ts +1 -65
  341. package/src/runtime/compaction/strategies/boundary-commit.ts +1 -106
  342. package/src/runtime/compaction/strategies/collapse.ts +1 -90
  343. package/src/runtime/compaction/strategies/index.ts +1 -23
  344. package/src/runtime/compaction/strategies/microcompact.ts +1 -74
  345. package/src/runtime/compaction/strategies/reactive.ts +1 -89
  346. package/src/runtime/compaction/types.ts +1 -221
  347. package/src/runtime/context.ts +10 -10
  348. package/src/runtime/diagnostics/actions.ts +1 -1
  349. package/src/runtime/diagnostics/index.ts +5 -5
  350. package/src/runtime/diagnostics/panels/agents.ts +2 -2
  351. package/src/runtime/diagnostics/panels/events.ts +2 -2
  352. package/src/runtime/diagnostics/panels/health.ts +2 -2
  353. package/src/runtime/diagnostics/panels/ops.ts +2 -2
  354. package/src/runtime/diagnostics/panels/policy.ts +2 -2
  355. package/src/runtime/diagnostics/panels/tasks.ts +2 -2
  356. package/src/runtime/diagnostics/panels/tool-calls.ts +2 -2
  357. package/src/runtime/diagnostics/provider.ts +1 -1
  358. package/src/runtime/ecosystem/recommendations.ts +1 -1
  359. package/src/runtime/emitters/agents.ts +2 -2
  360. package/src/runtime/emitters/automation.ts +2 -2
  361. package/src/runtime/emitters/communication.ts +2 -2
  362. package/src/runtime/emitters/compaction.ts +2 -2
  363. package/src/runtime/emitters/control-plane.ts +2 -2
  364. package/src/runtime/emitters/deliveries.ts +2 -2
  365. package/src/runtime/emitters/forensics.ts +2 -2
  366. package/src/runtime/emitters/index.ts +27 -27
  367. package/src/runtime/emitters/knowledge.ts +2 -2
  368. package/src/runtime/emitters/mcp.ts +2 -2
  369. package/src/runtime/emitters/ops.ts +2 -2
  370. package/src/runtime/emitters/orchestration.ts +2 -2
  371. package/src/runtime/emitters/permissions.ts +2 -2
  372. package/src/runtime/emitters/planner.ts +2 -2
  373. package/src/runtime/emitters/plugins.ts +2 -2
  374. package/src/runtime/emitters/providers.ts +2 -2
  375. package/src/runtime/emitters/routes.ts +2 -2
  376. package/src/runtime/emitters/security.ts +2 -2
  377. package/src/runtime/emitters/session.ts +2 -2
  378. package/src/runtime/emitters/surfaces.ts +2 -2
  379. package/src/runtime/emitters/tasks.ts +2 -2
  380. package/src/runtime/emitters/tools.ts +2 -2
  381. package/src/runtime/emitters/transport.ts +2 -2
  382. package/src/runtime/emitters/turn.ts +3 -3
  383. package/src/runtime/emitters/ui.ts +2 -2
  384. package/src/runtime/emitters/watchers.ts +2 -2
  385. package/src/runtime/emitters/workflows.ts +3 -3
  386. package/src/runtime/eval/index.ts +3 -3
  387. package/src/runtime/eval/runner.ts +1 -1
  388. package/src/runtime/eval/suites.ts +1 -1
  389. package/src/runtime/events/domain-map.ts +2 -2
  390. package/src/runtime/events/index.ts +1 -194
  391. package/src/runtime/events/turn.ts +1 -60
  392. package/src/runtime/events/workflows.ts +1 -17
  393. package/src/runtime/forensics/collector.ts +4 -4
  394. package/src/runtime/forensics/index.ts +1 -1
  395. package/src/runtime/foundation-clients.ts +14 -14
  396. package/src/runtime/foundation-services.ts +8 -8
  397. package/src/runtime/guidance.ts +3 -3
  398. package/src/runtime/health/effect-handlers.ts +3 -3
  399. package/src/runtime/health/index.ts +4 -4
  400. package/src/runtime/health/wiring.ts +2 -2
  401. package/src/runtime/index.ts +29 -29
  402. package/src/runtime/integration/helpers.ts +12 -12
  403. package/src/runtime/lifecycle.ts +4 -4
  404. package/src/runtime/mcp/index.ts +3 -3
  405. package/src/runtime/mcp/manager.ts +1 -1
  406. package/src/runtime/network/inbound.ts +2 -2
  407. package/src/runtime/network/index.ts +5 -5
  408. package/src/runtime/network/outbound.ts +2 -2
  409. package/src/runtime/network/shared.ts +1 -1
  410. package/src/runtime/operator-client.ts +9 -9
  411. package/src/runtime/ops/control-plane.ts +2 -2
  412. package/src/runtime/ops/index.ts +3 -3
  413. package/src/runtime/ops/playbooks/index.ts +2 -2
  414. package/src/runtime/ops/playbooks/session-unrecoverable.ts +2 -2
  415. package/src/runtime/ops/playbooks/stuck-turn.ts +1 -1
  416. package/src/runtime/ops/runtime-context.ts +1 -1
  417. package/src/runtime/orchestration/spawn-policy.ts +1 -1
  418. package/src/runtime/peer-client.ts +3 -3
  419. package/src/runtime/perf/index.ts +1 -1
  420. package/src/runtime/perf/slo-collector.ts +1 -1
  421. package/src/runtime/permissions/index.ts +5 -5
  422. package/src/runtime/permissions/policy-runtime.ts +1 -175
  423. package/src/runtime/permissions/rule-suggestions.ts +1 -1
  424. package/src/runtime/plugins/hot-reload.ts +4 -4
  425. package/src/runtime/plugins/index.ts +13 -13
  426. package/src/runtime/plugins/lifecycle.ts +1 -1
  427. package/src/runtime/plugins/manager.ts +10 -10
  428. package/src/runtime/plugins/manifest.ts +2 -2
  429. package/src/runtime/plugins/quarantine.ts +2 -2
  430. package/src/runtime/plugins/trust.ts +2 -2
  431. package/src/runtime/plugins/types.ts +1 -1
  432. package/src/runtime/provider-accounts/registry.ts +2 -2
  433. package/src/runtime/remote/distributed-runtime-contract-schemas.ts +3 -3
  434. package/src/runtime/remote/index.ts +3 -3
  435. package/src/runtime/remote/runner-registry.ts +2 -2
  436. package/src/runtime/remote/supervisor.ts +1 -1
  437. package/src/runtime/runtime-hook-api.ts +1 -1
  438. package/src/runtime/runtime-knowledge-api.ts +1 -1
  439. package/src/runtime/runtime-mcp-api.ts +1 -1
  440. package/src/runtime/runtime-ops-api.ts +2 -2
  441. package/src/runtime/runtime-provider-api.ts +1 -1
  442. package/src/runtime/services.ts +42 -35
  443. package/src/runtime/session-maintenance.ts +1 -1
  444. package/src/runtime/session-persistence.ts +2 -2
  445. package/src/runtime/session-return-context.ts +3 -3
  446. package/src/runtime/settings/control-plane-store.ts +1 -1
  447. package/src/runtime/settings/control-plane.ts +2 -2
  448. package/src/runtime/shell-command-extensions.ts +7 -7
  449. package/src/runtime/shell-command-ops.ts +6 -6
  450. package/src/runtime/shell-command-platform.ts +1 -1
  451. package/src/runtime/shell-command-services.ts +18 -18
  452. package/src/runtime/shell-command-workspace.ts +2 -2
  453. package/src/runtime/store/domains/conversation.ts +1 -1
  454. package/src/runtime/store/domains/index.ts +4 -4
  455. package/src/runtime/store/domains/permissions.ts +1 -1
  456. package/src/runtime/store/helpers/reducers/conversation.ts +3 -3
  457. package/src/runtime/store/helpers/reducers/lifecycle.ts +3 -3
  458. package/src/runtime/store/helpers/reducers/shared.ts +2 -2
  459. package/src/runtime/store/helpers/reducers/sync.ts +1 -1
  460. package/src/runtime/store/helpers/reducers.ts +4 -4
  461. package/src/runtime/store/index.ts +4 -4
  462. package/src/runtime/store/selectors/index.ts +2 -2
  463. package/src/runtime/store/state.ts +4 -4
  464. package/src/runtime/tasks/adapters/acp-adapter.ts +1 -1
  465. package/src/runtime/tasks/adapters/index.ts +6 -6
  466. package/src/runtime/tasks/index.ts +3 -3
  467. package/src/runtime/tasks/manager.ts +3 -3
  468. package/src/runtime/telemetry/api-helpers.ts +2 -2
  469. package/src/runtime/telemetry/api.ts +2 -2
  470. package/src/runtime/telemetry/index.ts +5 -5
  471. package/src/runtime/telemetry/instrumentation/domain-bridge-agent-session.ts +1 -1
  472. package/src/runtime/telemetry/instrumentation/domain-bridge-plugin-mcp.ts +1 -1
  473. package/src/runtime/telemetry/instrumentation/domain-bridge-shared.ts +1 -1
  474. package/src/runtime/telemetry/instrumentation/domain-bridge-transport-task.ts +1 -1
  475. package/src/runtime/telemetry/instrumentation/domain-bridge.ts +5 -5
  476. package/src/runtime/telemetry/instrumentation/index.ts +3 -3
  477. package/src/runtime/tools/context.ts +3 -3
  478. package/src/runtime/tools/index.ts +4 -4
  479. package/src/runtime/tools/phased-executor.ts +3 -3
  480. package/src/runtime/tools/phases/budget.ts +1 -1
  481. package/src/runtime/tools/phases/execute.ts +1 -1
  482. package/src/runtime/tools/phases/index.ts +7 -7
  483. package/src/runtime/tools/phases/map-output.ts +1 -1
  484. package/src/runtime/tools/phases/permission.ts +2 -2
  485. package/src/runtime/tools/phases/posthook.ts +1 -1
  486. package/src/runtime/tools/phases/prehook.ts +1 -1
  487. package/src/runtime/tools/phases/validate.ts +1 -1
  488. package/src/runtime/transports/direct.ts +4 -4
  489. package/src/runtime/transports/http-helpers.ts +3 -3
  490. package/src/runtime/transports/http-types.ts +6 -6
  491. package/src/runtime/transports/http.ts +8 -8
  492. package/src/runtime/transports/realtime.ts +4 -4
  493. package/src/runtime/transports/remote-events.ts +1 -1
  494. package/src/runtime/transports/shared.ts +2 -2
  495. package/src/runtime/transports/ui-runtime-events.ts +2 -2
  496. package/src/runtime/ui/index.ts +7 -7
  497. package/src/runtime/ui/model-picker/data-provider.ts +4 -4
  498. package/src/runtime/ui/model-picker/health-enrichment.ts +3 -3
  499. package/src/runtime/ui/model-picker/index.ts +8 -8
  500. package/src/runtime/ui/provider-health/data-provider.ts +2 -2
  501. package/src/runtime/ui/provider-health/fallback-visualizer.ts +1 -1
  502. package/src/runtime/ui/provider-health/index.ts +5 -5
  503. package/src/runtime/ui-events.ts +1 -1
  504. package/src/runtime/ui-read-models-core.ts +2 -2
  505. package/src/runtime/ui-read-models-observability-maintenance.ts +4 -4
  506. package/src/runtime/ui-read-models-observability-options.ts +1 -1
  507. package/src/runtime/ui-read-models-observability-remote.ts +2 -2
  508. package/src/runtime/ui-read-models-observability-security.ts +3 -3
  509. package/src/runtime/ui-read-models-observability-system.ts +6 -6
  510. package/src/runtime/ui-read-models-observability.ts +10 -10
  511. package/src/runtime/ui-read-models-operations.ts +2 -2
  512. package/src/runtime/ui-read-models.ts +7 -7
  513. package/src/runtime/ui-service-queries.ts +2 -2
  514. package/src/runtime/ui-services.ts +7 -7
  515. package/src/runtime/worktree/registry.ts +1 -1
  516. package/src/scripts/process-messages.ts +1 -1
  517. package/src/sessions/manager.ts +9 -383
  518. package/src/shell/blocking-input.ts +3 -3
  519. package/src/shell/ui-openers.ts +3 -3
  520. package/src/state/file-watcher.ts +1 -1
  521. package/src/state/index.ts +10 -10
  522. package/src/state/knowledge-injection.ts +2 -2
  523. package/src/state/memory-embedding-http.ts +2 -2
  524. package/src/state/memory-embeddings.ts +1 -1
  525. package/src/state/memory-ingest.ts +3 -3
  526. package/src/state/memory-registry.ts +3 -3
  527. package/src/state/memory-store-helpers.ts +1 -1
  528. package/src/state/memory-store.ts +4 -4
  529. package/src/state/memory-vector-store.ts +3 -3
  530. package/src/tools/agent/index.ts +7 -7
  531. package/src/tools/agent/manager.ts +8 -8
  532. package/src/tools/analyze/git-modes.ts +2 -2
  533. package/src/tools/analyze/index.ts +2 -2
  534. package/src/tools/channel/agent-tools.ts +1 -1
  535. package/src/tools/channel/index.ts +2 -2
  536. package/src/tools/control/index.ts +1 -1
  537. package/src/tools/edit/core.ts +3 -3
  538. package/src/tools/edit/index.ts +2 -2
  539. package/src/tools/edit/phased.ts +2 -2
  540. package/src/tools/fetch/index.ts +2 -2
  541. package/src/tools/fetch/phased.ts +1 -1
  542. package/src/tools/index.ts +28 -28
  543. package/src/tools/mcp/index.ts +1 -1
  544. package/src/tools/remote-trigger/index.ts +1 -1
  545. package/src/tools/shared/auto-heal.ts +2 -2
  546. package/src/tools/state/index.ts +1 -1
  547. package/src/tools/web-search/index.ts +1 -1
  548. package/src/tools/write/index.ts +3 -3
  549. package/src/tools/write/phased.ts +1 -1
  550. package/src/version.ts +1 -1
  551. package/src/watchers/index.ts +2 -2
  552. package/src/watchers/registry.ts +2 -2
  553. package/src/web-search/index.ts +10 -10
  554. package/src/web-search/provider-registry.ts +8 -8
  555. package/src/web-search/providers/brave.ts +1 -1
  556. package/src/web-search/providers/duckduckgo.ts +1 -1
  557. package/src/web-search/providers/exa.ts +1 -1
  558. package/src/web-search/providers/firecrawl.ts +1 -1
  559. package/src/web-search/providers/perplexity.ts +1 -1
  560. package/src/web-search/providers/searxng.ts +1 -1
  561. package/src/web-search/providers/shared.ts +1 -1
  562. package/src/web-search/providers/tavily.ts +1 -1
  563. package/src/web-search/service.ts +2 -2
  564. package/docs/README.md +0 -32
  565. package/scripts/postinstall.mjs +0 -203
  566. package/src/runtime/ecosystem/catalog.ts +0 -606
  567. package/src/runtime/sandbox/backend.ts +0 -291
  568. package/src/runtime/sandbox/manager.ts +0 -364
  569. package/src/runtime/sandbox/provisioning.ts +0 -422
  570. package/src/runtime/sandbox/session-registry.ts +0 -289
  571. package/src/tools/repl/index.ts +0 -318
@@ -1,547 +1,26 @@
1
- /**
2
- * SecretsManager — hierarchy-aware secret resolution and persistence.
3
- *
4
- * Resolution order:
5
- * 1. Environment variable (process.env[key])
6
- * 2. Project/ancestor secure stores (.goodvibes/tui/secrets.enc), nearest first
7
- * 3. Project/ancestor plaintext stores (.goodvibes/goodvibes.secrets.json), nearest first
8
- * 4. User secure store (~/.goodvibes/tui/secrets.enc)
9
- * 5. User plaintext store (~/.goodvibes/goodvibes.secrets.json)
10
- * 6. If a resolved value is a SecretRef, resolve through the referenced provider
11
- *
12
- * The active policy decides whether plaintext stores are eligible:
13
- * - plaintext_allowed read/write plaintext or secure
14
- * - preferred_secure → prefer secure, allow plaintext fallback with warning
15
- * - require_secure → never read/write plaintext
16
- *
17
- * Secret values are never logged.
18
- */
19
-
20
- import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'crypto';
21
- import { dirname, isAbsolute, join, resolve } from 'path';
22
- import { hostname, userInfo } from 'os';
23
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
24
- import type { ConfigManager } from './manager.ts';
25
- import { getSecretRefSource, isSecretRefInput, resolveSecretRef } from '@pellux/goodvibes-sdk/platform/config/secret-refs';
26
- import { logger } from '@pellux/goodvibes-sdk/platform/utils/logger';
27
- import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils/error-display';
28
-
29
- export type SecretStorageMode = 'plaintext_allowed' | 'preferred_secure' | 'require_secure';
30
- export type SecretScope = 'project' | 'user';
31
- export type SecretStorageMedium = 'secure' | 'plaintext';
32
- export type SecretSource =
33
- | 'env'
34
- | 'project-secure'
35
- | 'project-plaintext'
36
- | 'user-secure'
37
- | 'user-plaintext';
38
-
39
- export interface SecretRecord {
40
- readonly key: string;
41
- readonly source: SecretSource;
42
- readonly scope: SecretScope | 'env';
43
- readonly secure: boolean;
44
- readonly path?: string;
45
- readonly overriddenByEnv: boolean;
46
- readonly refSource?: string;
47
- }
48
-
49
- export interface SecretWriteOptions {
50
- readonly scope?: SecretScope;
51
- readonly medium?: SecretStorageMedium;
52
- }
53
-
54
- export interface SecretDeleteOptions {
55
- readonly scope?: SecretScope;
56
- readonly medium?: SecretStorageMedium;
57
- }
58
-
59
- export interface SecretStorageReview {
60
- readonly policy: SecretStorageMode;
61
- readonly secureAvailable: boolean;
62
- readonly storedKeys: number;
63
- readonly envBackedKeys: number;
64
- readonly secureKeys: number;
65
- readonly plaintextKeys: number;
66
- readonly warnings: readonly string[];
67
- readonly locations: readonly {
68
- readonly source: Exclude<SecretSource, 'env'>;
69
- readonly path: string;
70
- readonly exists: boolean;
71
- readonly readable: boolean;
72
- }[];
73
- }
74
-
75
- interface EncryptedStore {
76
- iv: string;
77
- tag: string;
78
- data: string;
79
- }
80
-
81
- interface PlaintextStore {
82
- readonly version: 1;
83
- readonly secrets: Record<string, string>;
84
- }
85
-
86
- interface SecretStorePath {
87
- readonly source: Exclude<SecretSource, 'env'>;
88
- readonly path: string;
89
- readonly secure: boolean;
90
- readonly scope: SecretScope;
91
- }
92
-
93
- export interface SecretsManagerOptions {
94
- readonly projectRoot: string;
95
- readonly globalHome: string;
96
- readonly configManager?: Pick<ConfigManager, 'get'>;
97
- readonly policy?: SecretStorageMode;
98
- readonly secureProjectFilePath?: string;
99
- readonly secureUserFilePath?: string;
100
- readonly plaintextProjectFilePath?: string;
101
- readonly plaintextUserFilePath?: string;
102
- }
103
-
104
- function requireAbsoluteOwnedPath(path: string, name: string): string {
105
- const trimmed = path.trim();
106
- if (!trimmed) {
107
- throw new Error(`SecretsManager ${name} must be a non-empty absolute path.`);
108
- }
109
- if (!isAbsolute(trimmed)) {
110
- throw new Error(`SecretsManager ${name} must be an absolute path.`);
111
- }
112
- return resolve(trimmed);
113
- }
114
-
115
- function normalizeOptionalOwnedPath(path: string | undefined, name: string): string | undefined {
116
- return path === undefined ? undefined : requireAbsoluteOwnedPath(path, name);
117
- }
118
-
119
- function deriveEncryptionKey(): Buffer {
120
- const seed = hostname() + userInfo().username + 'goodvibes-secrets';
121
- return createHash('sha256').update(seed, 'utf8').digest();
122
- }
123
-
124
- function encrypt(plaintext: string, key: Buffer): EncryptedStore {
125
- const iv = randomBytes(12);
126
- const cipher = createCipheriv('aes-256-gcm', key, iv);
127
- const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
128
- const tag = cipher.getAuthTag();
129
- return { iv: iv.toString('hex'), tag: tag.toString('hex'), data: encrypted.toString('hex') };
130
- }
131
-
132
- function decrypt(store: EncryptedStore, key: Buffer): string {
133
- const iv = Buffer.from(store.iv, 'hex');
134
- const tag = Buffer.from(store.tag, 'hex');
135
- const data = Buffer.from(store.data, 'hex');
136
- const decipher = createDecipheriv('aes-256-gcm', key, iv);
137
- decipher.setAuthTag(tag);
138
- const decrypted = Buffer.concat([decipher.update(data), decipher.final()]);
139
- return decrypted.toString('utf8');
140
- }
141
-
142
- function loadConfiguredSecretPolicy(configManager?: Pick<ConfigManager, 'get'>): SecretStorageMode {
143
- try {
144
- return (configManager?.get('storage.secretPolicy') as SecretStorageMode | undefined) ?? 'preferred_secure';
145
- } catch {
146
- return 'preferred_secure';
147
- }
148
- }
149
-
150
- function uniquePaths(paths: readonly SecretStorePath[]): SecretStorePath[] {
151
- const seen = new Set<string>();
152
- const ordered: SecretStorePath[] = [];
153
- for (const path of paths) {
154
- const key = `${path.source}:${path.path}`;
155
- if (seen.has(key)) continue;
156
- seen.add(key);
157
- ordered.push(path);
158
- }
159
- return ordered;
160
- }
161
-
162
- function collectAncestorRoots(start: string): string[] {
163
- const roots: string[] = [];
164
- let current = resolve(start);
165
- while (true) {
166
- roots.push(current);
167
- const parent = dirname(current);
168
- if (parent === current) break;
169
- current = parent;
170
- }
171
- return roots;
172
- }
173
-
174
- export class SecretsManager {
175
- private readonly encKey: Buffer;
176
- private readonly options: SecretsManagerOptions;
177
-
1
+ export type {
2
+ SecretDeleteOptions,
3
+ SecretRecord,
4
+ SecretScope,
5
+ SecretSource,
6
+ SecretStorageMedium,
7
+ SecretStorageMode,
8
+ SecretStorageReview,
9
+ SecretWriteOptions,
10
+ } from '@pellux/goodvibes-sdk/platform/config/secrets';
11
+
12
+ import {
13
+ SecretsManager as SdkSecretsManager,
14
+ type SecretsManagerOptions as SdkSecretsManagerOptions,
15
+ } from '@pellux/goodvibes-sdk/platform/config/secrets';
16
+
17
+ export type SecretsManagerOptions = Omit<SdkSecretsManagerOptions, 'surfaceRoot'>;
18
+
19
+ export class SecretsManager extends SdkSecretsManager {
178
20
  constructor(options: SecretsManagerOptions) {
179
- this.encKey = deriveEncryptionKey();
180
- this.options = {
21
+ super({
181
22
  ...options,
182
- projectRoot: requireAbsoluteOwnedPath(options.projectRoot, 'projectRoot'),
183
- globalHome: requireAbsoluteOwnedPath(options.globalHome, 'globalHome'),
184
- secureProjectFilePath: normalizeOptionalOwnedPath(options.secureProjectFilePath, 'secureProjectFilePath'),
185
- secureUserFilePath: normalizeOptionalOwnedPath(options.secureUserFilePath, 'secureUserFilePath'),
186
- plaintextProjectFilePath: normalizeOptionalOwnedPath(options.plaintextProjectFilePath, 'plaintextProjectFilePath'),
187
- plaintextUserFilePath: normalizeOptionalOwnedPath(options.plaintextUserFilePath, 'plaintextUserFilePath'),
188
- };
189
- }
190
-
191
- getGlobalHome(): string {
192
- return this.options.globalHome;
193
- }
194
-
195
- async get(key: string): Promise<string | null> {
196
- return this.getInternal(key, new Set([key]));
197
- }
198
-
199
- private async getInternal(key: string, seen: Set<string>): Promise<string | null> {
200
- const envValue = process.env[key];
201
- if (envValue !== undefined) {
202
- logger.debug('SecretsManager: resolved from env', { key });
203
- return this.resolveMaybeReferencedValue(key, envValue, seen);
204
- }
205
-
206
- for (const path of this.getReadOrder()) {
207
- const secrets = path.secure
208
- ? this.readEncryptedFile(path.path)
209
- : this.readPlaintextFile(path.path);
210
- if (secrets !== null && key in secrets) {
211
- logger.debug('SecretsManager: resolved from store', { key, source: path.source });
212
- const value = secrets[key];
213
- return value === undefined ? null : this.resolveMaybeReferencedValue(key, value, seen);
214
- }
215
- }
216
-
217
- return null;
218
- }
219
-
220
- private async resolveMaybeReferencedValue(key: string, value: string, seen: Set<string>): Promise<string | null> {
221
- if (!isSecretRefInput(value)) return value;
222
-
223
- try {
224
- const resolved = await resolveSecretRef(value, {
225
- resolveLocalSecret: async (nextKey) => {
226
- if (seen.has(nextKey)) {
227
- throw new Error(`Recursive GoodVibes secret reference for ${nextKey}`);
228
- }
229
- const nextSeen = new Set(seen);
230
- nextSeen.add(nextKey);
231
- return this.getInternal(nextKey, nextSeen);
232
- },
233
- homeDirectory: this.options.globalHome,
234
- });
235
- logger.debug('SecretsManager: resolved secret reference', { key, refSource: resolved.source });
236
- return resolved.value;
237
- } catch (error) {
238
- logger.warn('SecretsManager: failed to resolve secret reference', {
239
- key,
240
- refSource: getSecretRefSource(value) ?? 'unknown',
241
- error: summarizeError(error),
242
- });
243
- return null;
244
- }
245
- }
246
-
247
- async set(key: string, value: string, options: SecretWriteOptions = {}): Promise<void> {
248
- const policy = this.getPolicy();
249
- const medium = options.medium ?? this.getDefaultWriteMedium(policy);
250
- const scope = options.scope ?? 'project';
251
-
252
- if (policy === 'require_secure' && medium === 'plaintext') {
253
- throw new Error('Secret policy require_secure forbids plaintext persistence');
254
- }
255
-
256
- const target = this.resolveWriteTarget(scope, medium);
257
- const existing = target.secure
258
- ? this.readEncryptedFile(target.path) ?? {}
259
- : this.readPlaintextFile(target.path) ?? {};
260
- existing[key] = value;
261
-
262
- try {
263
- if (target.secure) {
264
- this.writeEncryptedFile(target.path, existing);
265
- } else {
266
- this.writePlaintextFile(target.path, existing);
267
- }
268
- logger.debug('SecretsManager: stored secret', { key, source: target.source });
269
- return;
270
- } catch (error) {
271
- if (policy === 'preferred_secure' && target.secure) {
272
- const fallback = this.resolveWriteTarget(scope, 'plaintext');
273
- const fallbackExisting = this.readPlaintextFile(fallback.path) ?? {};
274
- fallbackExisting[key] = value;
275
- this.writePlaintextFile(fallback.path, fallbackExisting);
276
- logger.warn('SecretsManager: secure write failed, fell back to plaintext', {
277
- key,
278
- path: fallback.path,
279
- error: summarizeError(error),
280
- });
281
- return;
282
- }
283
- throw error;
284
- }
285
- }
286
-
287
- async list(): Promise<string[]> {
288
- const keys = new Set<string>();
289
- for (const path of this.getReadOrder()) {
290
- const values = path.secure
291
- ? this.readEncryptedFile(path.path)
292
- : this.readPlaintextFile(path.path);
293
- if (!values) continue;
294
- for (const key of Object.keys(values)) keys.add(key);
295
- }
296
- return [...keys].sort((a, b) => a.localeCompare(b));
297
- }
298
-
299
- async listDetailed(): Promise<SecretRecord[]> {
300
- const envKeys = new Set(Object.keys(process.env));
301
- const records: SecretRecord[] = [];
302
-
303
- for (const path of this.getReadOrder()) {
304
- const values = path.secure
305
- ? this.readEncryptedFile(path.path)
306
- : this.readPlaintextFile(path.path);
307
- if (!values) continue;
308
- for (const key of Object.keys(values)) {
309
- const refSource = getSecretRefSource(values[key]);
310
- records.push({
311
- key,
312
- source: path.source,
313
- scope: path.scope,
314
- secure: path.secure,
315
- path: path.path,
316
- overriddenByEnv: envKeys.has(key),
317
- ...(refSource ? { refSource } : {}),
318
- });
319
- }
320
- }
321
-
322
- for (const key of envKeys) {
323
- records.push({
324
- key,
325
- source: 'env',
326
- scope: 'env',
327
- secure: false,
328
- overriddenByEnv: false,
329
- });
330
- }
331
-
332
- return records.sort((a, b) => a.key.localeCompare(b.key) || a.source.localeCompare(b.source));
333
- }
334
-
335
- async inspect(): Promise<SecretStorageReview> {
336
- const policy = this.getPolicy();
337
- const records = await this.listDetailed();
338
- const storedRecords = records.filter((record) => record.source !== 'env');
339
- const locations = uniquePaths(this.getAllCandidateStores()).map((path) => ({
340
- source: path.source,
341
- path: path.path,
342
- exists: existsSync(path.path),
343
- readable: (path.secure ? this.readEncryptedFile(path.path) : this.readPlaintextFile(path.path)) !== null,
344
- }));
345
- const warnings: string[] = [];
346
- if (policy === 'preferred_secure' && storedRecords.some((record) => !record.secure)) {
347
- warnings.push('plaintext fallback secrets are present');
348
- }
349
- if (policy === 'require_secure' && storedRecords.some((record) => !record.secure)) {
350
- warnings.push('plaintext secrets exist but are ignored by current policy');
351
- }
352
-
353
- return {
354
- policy,
355
- secureAvailable: true,
356
- storedKeys: new Set(storedRecords.map((record) => record.key)).size,
357
- envBackedKeys: new Set(records.filter((record) => record.source === 'env').map((record) => record.key)).size,
358
- secureKeys: new Set(storedRecords.filter((record) => record.secure).map((record) => record.key)).size,
359
- plaintextKeys: new Set(storedRecords.filter((record) => !record.secure).map((record) => record.key)).size,
360
- warnings,
361
- locations,
362
- };
363
- }
364
-
365
- async delete(key: string, options: SecretDeleteOptions = {}): Promise<void> {
366
- const stores = this.getAllCandidateStores().filter((store) => {
367
- if (options.scope && store.scope !== options.scope) return false;
368
- if (options.medium && (options.medium === 'secure') !== store.secure) return false;
369
- return true;
370
- });
371
-
372
- for (const store of stores) {
373
- const values = store.secure
374
- ? this.readEncryptedFile(store.path)
375
- : this.readPlaintextFile(store.path);
376
- if (!values || !(key in values)) continue;
377
- delete values[key];
378
- if (store.secure) this.writeEncryptedFile(store.path, values);
379
- else this.writePlaintextFile(store.path, values);
380
- logger.debug('SecretsManager: deleted secret', { key, source: store.source });
381
- }
382
- }
383
-
384
- private getPolicy(): SecretStorageMode {
385
- return this.options.policy ?? loadConfiguredSecretPolicy(this.options.configManager);
386
- }
387
-
388
- private getReadOrder(): SecretStorePath[] {
389
- const policy = this.getPolicy();
390
- const includePlaintext = policy !== 'require_secure';
391
- const ordered: SecretStorePath[] = [];
392
- const projectRoot = this.options.projectRoot;
393
- const userHome = this.options.globalHome;
394
-
395
- for (const root of collectAncestorRoots(projectRoot)) {
396
- ordered.push({
397
- source: 'project-secure',
398
- path: this.options.secureProjectFilePath ?? join(root, '.goodvibes', 'tui', 'secrets.enc'),
399
- secure: true,
400
- scope: 'project',
401
- });
402
- if (includePlaintext) {
403
- ordered.push({
404
- source: 'project-plaintext',
405
- path: this.options.plaintextProjectFilePath ?? join(root, '.goodvibes', 'goodvibes.secrets.json'),
406
- secure: false,
407
- scope: 'project',
408
- });
409
- }
410
- }
411
-
412
- ordered.push({
413
- source: 'user-secure',
414
- path: this.options.secureUserFilePath ?? join(userHome, '.goodvibes', 'tui', 'secrets.enc'),
415
- secure: true,
416
- scope: 'user',
417
- });
418
-
419
- if (includePlaintext) {
420
- ordered.push({
421
- source: 'user-plaintext',
422
- path: this.options.plaintextUserFilePath ?? join(userHome, '.goodvibes', 'goodvibes.secrets.json'),
423
- secure: false,
424
- scope: 'user',
425
- });
426
- }
427
-
428
- return uniquePaths(ordered);
429
- }
430
-
431
- private getAllCandidateStores(): SecretStorePath[] {
432
- const projectRoot = this.options.projectRoot;
433
- const userHome = this.options.globalHome;
434
- const ordered: SecretStorePath[] = [];
435
- for (const root of collectAncestorRoots(projectRoot)) {
436
- ordered.push({
437
- source: 'project-secure',
438
- path: this.options.secureProjectFilePath ?? join(root, '.goodvibes', 'tui', 'secrets.enc'),
439
- secure: true,
440
- scope: 'project',
441
- });
442
- ordered.push({
443
- source: 'project-plaintext',
444
- path: this.options.plaintextProjectFilePath ?? join(root, '.goodvibes', 'goodvibes.secrets.json'),
445
- secure: false,
446
- scope: 'project',
447
- });
448
- }
449
- ordered.push({
450
- source: 'user-secure',
451
- path: this.options.secureUserFilePath ?? join(userHome, '.goodvibes', 'tui', 'secrets.enc'),
452
- secure: true,
453
- scope: 'user',
454
- });
455
- ordered.push({
456
- source: 'user-plaintext',
457
- path: this.options.plaintextUserFilePath ?? join(userHome, '.goodvibes', 'goodvibes.secrets.json'),
458
- secure: false,
459
- scope: 'user',
23
+ surfaceRoot: 'tui',
460
24
  });
461
- return uniquePaths(ordered);
462
- }
463
-
464
- private resolveWriteTarget(scope: SecretScope, medium: SecretStorageMedium): SecretStorePath {
465
- if (scope === 'project') {
466
- const root = this.options.projectRoot;
467
- return medium === 'secure'
468
- ? {
469
- source: 'project-secure',
470
- path: this.options.secureProjectFilePath ?? join(root, '.goodvibes', 'tui', 'secrets.enc'),
471
- secure: true,
472
- scope,
473
- }
474
- : {
475
- source: 'project-plaintext',
476
- path: this.options.plaintextProjectFilePath ?? join(root, '.goodvibes', 'goodvibes.secrets.json'),
477
- secure: false,
478
- scope,
479
- };
480
- }
481
-
482
- const userHome = this.options.globalHome;
483
- return medium === 'secure'
484
- ? {
485
- source: 'user-secure',
486
- path: this.options.secureUserFilePath ?? join(userHome, '.goodvibes', 'tui', 'secrets.enc'),
487
- secure: true,
488
- scope,
489
- }
490
- : {
491
- source: 'user-plaintext',
492
- path: this.options.plaintextUserFilePath ?? join(userHome, '.goodvibes', 'goodvibes.secrets.json'),
493
- secure: false,
494
- scope,
495
- };
496
- }
497
-
498
- private getDefaultWriteMedium(policy: SecretStorageMode): SecretStorageMedium {
499
- return policy === 'plaintext_allowed' ? 'plaintext' : 'secure';
500
- }
501
-
502
- private readEncryptedFile(filePath: string): Record<string, string> | null {
503
- try {
504
- const raw = readFileSync(filePath, 'utf-8');
505
- const store: EncryptedStore = JSON.parse(raw);
506
- return JSON.parse(decrypt(store, this.encKey)) as Record<string, string>;
507
- } catch (err) {
508
- const code = (err as NodeJS.ErrnoException).code;
509
- if (code !== 'ENOENT') {
510
- logger.error('SecretsManager: failed to read encrypted store', { path: filePath });
511
- }
512
- return null;
513
- }
514
- }
515
-
516
- private writeEncryptedFile(filePath: string, secrets: Record<string, string>): void {
517
- mkdirSync(dirname(filePath), { recursive: true });
518
- const plaintext = JSON.stringify(secrets);
519
- const store = encrypt(plaintext, this.encKey);
520
- writeFileSync(filePath, `${JSON.stringify(store, null, 2)}\n`, 'utf-8');
521
- }
522
-
523
- private readPlaintextFile(filePath: string): Record<string, string> | null {
524
- try {
525
- const raw = readFileSync(filePath, 'utf-8');
526
- const parsed = JSON.parse(raw) as unknown;
527
- if (!parsed || typeof parsed !== 'object') return null;
528
- if ('version' in parsed && 'secrets' in parsed) {
529
- const secrets = (parsed as PlaintextStore).secrets;
530
- return secrets && typeof secrets === 'object' ? secrets : null;
531
- }
532
- return parsed as Record<string, string>;
533
- } catch (err) {
534
- const code = (err as NodeJS.ErrnoException).code;
535
- if (code !== 'ENOENT') {
536
- logger.error('SecretsManager: failed to read plaintext store', { path: filePath });
537
- }
538
- return null;
539
- }
540
- }
541
-
542
- private writePlaintextFile(filePath: string, secrets: Record<string, string>): void {
543
- mkdirSync(dirname(filePath), { recursive: true });
544
- const payload: PlaintextStore = { version: 1, secrets };
545
- writeFileSync(filePath, `${JSON.stringify(payload, null, 2)}\n`, 'utf-8');
546
25
  }
547
26
  }