@libredb/studio 0.9.7 → 0.9.13

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 (688) hide show
  1. package/dist/chunk-34YQUUCM.mjs +319 -0
  2. package/dist/chunk-34YQUUCM.mjs.map +1 -0
  3. package/dist/chunk-4LVB3K53.mjs +37 -0
  4. package/dist/chunk-4LVB3K53.mjs.map +1 -0
  5. package/dist/chunk-6DRZXXNT.mjs +100 -0
  6. package/dist/chunk-6DRZXXNT.mjs.map +1 -0
  7. package/dist/chunk-CPF7XWV5.mjs +1289 -0
  8. package/dist/chunk-CPF7XWV5.mjs.map +1 -0
  9. package/dist/chunk-CZVV3JJB.mjs +160 -0
  10. package/dist/chunk-CZVV3JJB.mjs.map +1 -0
  11. package/dist/chunk-D4WVWWWF.js +332 -0
  12. package/dist/chunk-D4WVWWWF.js.map +1 -0
  13. package/dist/chunk-DY3KXE44.mjs +3 -0
  14. package/dist/chunk-DY3KXE44.mjs.map +1 -0
  15. package/dist/chunk-FYSE52VB.js +242 -0
  16. package/dist/chunk-FYSE52VB.js.map +1 -0
  17. package/dist/chunk-G3S66G64.mjs +6673 -0
  18. package/dist/chunk-G3S66G64.mjs.map +1 -0
  19. package/dist/chunk-G4WYE6TI.js +4 -0
  20. package/dist/chunk-G4WYE6TI.js.map +1 -0
  21. package/dist/chunk-HGPD6PWV.js +1310 -0
  22. package/dist/chunk-HGPD6PWV.js.map +1 -0
  23. package/dist/chunk-JZO5KRZN.js +165 -0
  24. package/dist/chunk-JZO5KRZN.js.map +1 -0
  25. package/dist/chunk-KV356UXJ.js +253 -0
  26. package/dist/chunk-KV356UXJ.js.map +1 -0
  27. package/dist/chunk-PPODO6HX.mjs +237 -0
  28. package/dist/chunk-PPODO6HX.mjs.map +1 -0
  29. package/dist/chunk-PTIRB2JO.js +258 -0
  30. package/dist/chunk-PTIRB2JO.js.map +1 -0
  31. package/dist/chunk-Q6LRDBK7.js +42 -0
  32. package/dist/chunk-Q6LRDBK7.js.map +1 -0
  33. package/dist/chunk-QJP5FZRY.mjs +255 -0
  34. package/dist/chunk-QJP5FZRY.mjs.map +1 -0
  35. package/dist/chunk-R3POCJK6.mjs +248 -0
  36. package/dist/chunk-R3POCJK6.mjs.map +1 -0
  37. package/dist/chunk-RCQB4FCE.js +186 -0
  38. package/dist/chunk-RCQB4FCE.js.map +1 -0
  39. package/dist/chunk-SR5DRGBX.mjs +174 -0
  40. package/dist/chunk-SR5DRGBX.mjs.map +1 -0
  41. package/dist/chunk-VLCRUZX7.js +102 -0
  42. package/dist/chunk-VLCRUZX7.js.map +1 -0
  43. package/dist/chunk-Y52UIFEX.js +6741 -0
  44. package/dist/chunk-Y52UIFEX.js.map +1 -0
  45. package/dist/components.d.mts +273 -0
  46. package/dist/components.d.ts +273 -0
  47. package/dist/components.js +59 -0
  48. package/dist/components.js.map +1 -0
  49. package/dist/components.mjs +6 -0
  50. package/dist/components.mjs.map +1 -0
  51. package/dist/custom-BNDOYC5P.js +134 -0
  52. package/dist/custom-BNDOYC5P.js.map +1 -0
  53. package/dist/custom-S2EKFMP3.mjs +132 -0
  54. package/dist/custom-S2EKFMP3.mjs.map +1 -0
  55. package/dist/gemini-4ASHNK4H.js +81 -0
  56. package/dist/gemini-4ASHNK4H.js.map +1 -0
  57. package/dist/gemini-C5RBLQEJ.mjs +79 -0
  58. package/dist/gemini-C5RBLQEJ.mjs.map +1 -0
  59. package/dist/index.d.mts +6 -0
  60. package/dist/index.d.ts +6 -0
  61. package/dist/index.js +95 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/index.mjs +10 -0
  64. package/dist/index.mjs.map +1 -0
  65. package/dist/mongodb-XMZEZA4A.mjs +748 -0
  66. package/dist/mongodb-XMZEZA4A.mjs.map +1 -0
  67. package/dist/mongodb-YQJJTLX3.js +750 -0
  68. package/dist/mongodb-YQJJTLX3.js.map +1 -0
  69. package/dist/mssql-PMOU4D36.js +916 -0
  70. package/dist/mssql-PMOU4D36.js.map +1 -0
  71. package/{src/lib/db/providers/sql/mssql.ts → dist/mssql-ZH5VP2C5.mjs} +268 -423
  72. package/dist/mssql-ZH5VP2C5.mjs.map +1 -0
  73. package/{src/lib/db/providers/sql/mysql.ts → dist/mysql-I3WJQXN2.mjs} +277 -428
  74. package/dist/mysql-I3WJQXN2.mjs.map +1 -0
  75. package/dist/mysql-Y3MSA5QY.js +833 -0
  76. package/dist/mysql-Y3MSA5QY.js.map +1 -0
  77. package/dist/ollama-26BYLVEV.mjs +115 -0
  78. package/dist/ollama-26BYLVEV.mjs.map +1 -0
  79. package/dist/ollama-HVWAGKQC.js +117 -0
  80. package/dist/ollama-HVWAGKQC.js.map +1 -0
  81. package/dist/openai-4U56KPG7.mjs +111 -0
  82. package/dist/openai-4U56KPG7.mjs.map +1 -0
  83. package/dist/openai-AK3R37BS.js +113 -0
  84. package/dist/openai-AK3R37BS.js.map +1 -0
  85. package/dist/oracle-L6VEAVXO.js +917 -0
  86. package/dist/oracle-L6VEAVXO.js.map +1 -0
  87. package/{src/lib/db/providers/sql/oracle.ts → dist/oracle-P2G7T4P4.mjs} +321 -454
  88. package/dist/oracle-P2G7T4P4.mjs.map +1 -0
  89. package/{src/lib/db/providers/sql/postgres.ts → dist/postgres-O5KOQUVP.mjs} +261 -471
  90. package/dist/postgres-O5KOQUVP.mjs.map +1 -0
  91. package/dist/postgres-RLCWNFFX.js +971 -0
  92. package/dist/postgres-RLCWNFFX.js.map +1 -0
  93. package/dist/providers.d.mts +149 -0
  94. package/dist/providers.d.ts +149 -0
  95. package/dist/providers.js +44 -0
  96. package/dist/providers.js.map +1 -0
  97. package/dist/providers.mjs +7 -0
  98. package/dist/providers.mjs.map +1 -0
  99. package/dist/redis-4WMQOVLX.mjs +435 -0
  100. package/dist/redis-4WMQOVLX.mjs.map +1 -0
  101. package/dist/redis-QVQ6YU62.js +441 -0
  102. package/dist/redis-QVQ6YU62.js.map +1 -0
  103. package/dist/sqlite-4I2P2OGQ.js +554 -0
  104. package/dist/sqlite-4I2P2OGQ.js.map +1 -0
  105. package/dist/sqlite-OA4YJX5S.mjs +531 -0
  106. package/dist/sqlite-OA4YJX5S.mjs.map +1 -0
  107. package/dist/types-BJvJfxSY.d.mts +141 -0
  108. package/dist/types-BJvJfxSY.d.ts +141 -0
  109. package/dist/types-ClAg_v5k.d.mts +343 -0
  110. package/dist/types-Der_X8E8.d.ts +343 -0
  111. package/dist/types.d.mts +2 -0
  112. package/dist/types.d.ts +2 -0
  113. package/dist/types.js +6 -0
  114. package/dist/types.js.map +1 -0
  115. package/dist/types.mjs +3 -0
  116. package/dist/types.mjs.map +1 -0
  117. package/dist/workspace.d.mts +80 -0
  118. package/dist/workspace.d.ts +80 -0
  119. package/dist/workspace.js +4174 -0
  120. package/dist/workspace.js.map +1 -0
  121. package/dist/workspace.mjs +4147 -0
  122. package/dist/workspace.mjs.map +1 -0
  123. package/package.json +60 -5
  124. package/.claude/settings.local.json +0 -127
  125. package/.cursorrules +0 -426
  126. package/.devin/wiki.json +0 -143
  127. package/.dockerignore +0 -80
  128. package/.env.example +0 -159
  129. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -49
  130. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -29
  131. package/.github/PULL_REQUEST_TEMPLATE.md +0 -57
  132. package/.github/workflows/ci.yml +0 -185
  133. package/.github/workflows/codeql.yml +0 -57
  134. package/.github/workflows/docker-build-push.yml +0 -118
  135. package/.github/workflows/helm-release.yml +0 -113
  136. package/CLAUDE.md +0 -265
  137. package/CODE_OF_CONDUCT.md +0 -124
  138. package/CONTRIBUTING.md +0 -154
  139. package/Dockerfile +0 -73
  140. package/SECURITY.md +0 -107
  141. package/artifacthub-repo.yml +0 -4
  142. package/bun.lock +0 -1714
  143. package/bunfig.toml +0 -3
  144. package/charts/libredb-studio/.helmignore +0 -11
  145. package/charts/libredb-studio/Chart.lock +0 -6
  146. package/charts/libredb-studio/Chart.yaml +0 -50
  147. package/charts/libredb-studio/README.md +0 -206
  148. package/charts/libredb-studio/templates/NOTES.txt +0 -59
  149. package/charts/libredb-studio/templates/_helpers.tpl +0 -135
  150. package/charts/libredb-studio/templates/configmap.yaml +0 -37
  151. package/charts/libredb-studio/templates/deployment.yaml +0 -184
  152. package/charts/libredb-studio/templates/hpa.yaml +0 -32
  153. package/charts/libredb-studio/templates/ingress.yaml +0 -41
  154. package/charts/libredb-studio/templates/networkpolicy.yaml +0 -50
  155. package/charts/libredb-studio/templates/pdb.yaml +0 -18
  156. package/charts/libredb-studio/templates/pvc.yaml +0 -23
  157. package/charts/libredb-studio/templates/secret.yaml +0 -30
  158. package/charts/libredb-studio/templates/seed-configmap.yaml +0 -11
  159. package/charts/libredb-studio/templates/service.yaml +0 -22
  160. package/charts/libredb-studio/templates/serviceaccount.yaml +0 -13
  161. package/charts/libredb-studio/values.schema.json +0 -246
  162. package/charts/libredb-studio/values.yaml +0 -286
  163. package/components.json +0 -22
  164. package/conductor/code_styleguides/typescript.md +0 -43
  165. package/conductor/product-guidelines.md +0 -43
  166. package/conductor/product.md +0 -3
  167. package/conductor/setup_state.json +0 -1
  168. package/conductor/tech-stack.md +0 -39
  169. package/conductor/tracks/enhance_postgres_monitoring_20251227/metadata.json +0 -8
  170. package/conductor/tracks/enhance_postgres_monitoring_20251227/plan.md +0 -44
  171. package/conductor/tracks/enhance_postgres_monitoring_20251227/spec.md +0 -31
  172. package/conductor/tracks.md +0 -8
  173. package/conductor/workflow.md +0 -333
  174. package/database-compose.yml +0 -55
  175. package/docker/postgres-init/01-extensions.sql +0 -10
  176. package/docker/postgres-init/02-sample-data.sql +0 -585
  177. package/docker/postgres.yml +0 -68
  178. package/docker-compose.yml +0 -38
  179. package/docs/AI_PLAN.md +0 -74
  180. package/docs/API_DOCS.md +0 -875
  181. package/docs/ARCHITECTURE.md +0 -218
  182. package/docs/DATABASE_PROVIDERS.md +0 -358
  183. package/docs/FEATURES.md +0 -116
  184. package/docs/HELM_CHART.md +0 -252
  185. package/docs/LOGIN_PAGE.md +0 -178
  186. package/docs/MONACO_EDITOR_PERFORMANCE.md +0 -315
  187. package/docs/OIDC_ARCH.md +0 -681
  188. package/docs/OIDC_SETUP.md +0 -322
  189. package/docs/POSTGRES_METRICS.md +0 -516
  190. package/docs/QUERY_OPTIMIZATION.md +0 -370
  191. package/docs/SEED_CONNECTIONS.md +0 -468
  192. package/docs/SQL_ALIAS_COMPLETION.md +0 -190
  193. package/docs/STORAGE_ARCHITECTURE.md +0 -565
  194. package/docs/STORAGE_QUICK_SETUP.md +0 -419
  195. package/docs/TECHNICAL_PLAN.md +0 -36
  196. package/docs/THEMING.md +0 -345
  197. package/docs/adding-a-new-database-provider.md +0 -642
  198. package/docs/backlogs/000-PLATFORM_DATA_SYNC_DATABASE.md +0 -360
  199. package/docs/backlogs/001-INLINE_DATA_EDITING.md +0 -118
  200. package/docs/backlogs/002-DATA_IMPORT.md +0 -215
  201. package/docs/backlogs/003-QUERY_TIME_MACHINE.md +0 -183
  202. package/docs/backlogs/004-AI_DATA_STORYTELLER.md +0 -292
  203. package/docs/backlogs/005-QUERY_PLAYGROUND.md +0 -352
  204. package/docs/backlogs/006-DATA_MASKING.md +0 -418
  205. package/docs/enterprise-features.md +0 -718
  206. package/docs/kubernetes-helm-chart-artifacthub-plan.md +0 -803
  207. package/docs/medium-koyeb-article-en.md +0 -215
  208. package/docs/plans/test-plans.md +0 -445
  209. package/docs/releases/RELEASE.V0.3.0.md +0 -22
  210. package/docs/releases/RELEASE.V0.4.0.md +0 -154
  211. package/docs/releases/RELEASE.V0.5.0.md +0 -252
  212. package/docs/releases/RELEASE_v0.5.6.md +0 -145
  213. package/docs/releases/RELEASE_v0.6.1.md +0 -303
  214. package/docs/releases/RELEASE_v0.6.7.md +0 -292
  215. package/docs/releases/RELEASE_v0.7.0.md +0 -332
  216. package/docs/releases/RELEASE_v0.8.0.md +0 -521
  217. package/docs/sampledb/titanic.sql +0 -1379
  218. package/docs/superpowers/plans/2026-03-25-seed-connections.md +0 -1362
  219. package/docs/superpowers/specs/2026-03-25-seed-connections-design.md +0 -590
  220. package/e2e/admin-dashboard.spec.ts +0 -64
  221. package/e2e/connection-management.spec.ts +0 -58
  222. package/e2e/export.spec.ts +0 -34
  223. package/e2e/login.spec.ts +0 -85
  224. package/e2e/query-execution.spec.ts +0 -35
  225. package/e2e/tab-management.spec.ts +0 -64
  226. package/eslint.config.mjs +0 -28
  227. package/fly.toml +0 -43
  228. package/next.config.ts +0 -32
  229. package/playwright.config.ts +0 -34
  230. package/postcss.config.mjs +0 -7
  231. package/public/favicon-32x32.png +0 -0
  232. package/public/favicon.ico +0 -0
  233. package/public/file.svg +0 -1
  234. package/public/globe.svg +0 -1
  235. package/public/logo.svg +0 -32
  236. package/public/next.svg +0 -1
  237. package/public/screenshots/code-generator.png +0 -0
  238. package/public/screenshots/connection-modal.png +0 -0
  239. package/public/screenshots/data-profiler.png +0 -0
  240. package/public/screenshots/erd-diagram.png +0 -0
  241. package/public/screenshots/hero-editor.png +0 -0
  242. package/public/screenshots/nl2sql.png +0 -0
  243. package/public/vercel.svg +0 -1
  244. package/public/window.svg +0 -1
  245. package/render.yaml +0 -58
  246. package/scripts/merge-lcov.mjs +0 -239
  247. package/sonar-project.properties +0 -16
  248. package/src/app/admin/error.tsx +0 -46
  249. package/src/app/admin/page.tsx +0 -10
  250. package/src/app/api/admin/audit/route.ts +0 -52
  251. package/src/app/api/admin/fleet-health/route.ts +0 -81
  252. package/src/app/api/ai/autopilot/route.ts +0 -105
  253. package/src/app/api/ai/chat/route.ts +0 -132
  254. package/src/app/api/ai/describe-schema/route.ts +0 -52
  255. package/src/app/api/ai/explain/route.ts +0 -86
  256. package/src/app/api/ai/impact/route.ts +0 -97
  257. package/src/app/api/ai/index-advisor/route.ts +0 -98
  258. package/src/app/api/ai/nl2sql/route.ts +0 -87
  259. package/src/app/api/ai/query-safety/route.ts +0 -87
  260. package/src/app/api/auth/login/route.ts +0 -62
  261. package/src/app/api/auth/logout/route.ts +0 -25
  262. package/src/app/api/auth/me/route.ts +0 -10
  263. package/src/app/api/auth/oidc/callback/route.ts +0 -82
  264. package/src/app/api/auth/oidc/login/route.ts +0 -43
  265. package/src/app/api/connections/managed/route.ts +0 -35
  266. package/src/app/api/db/cancel/route.ts +0 -42
  267. package/src/app/api/db/disconnect/route.ts +0 -28
  268. package/src/app/api/db/health/route.ts +0 -49
  269. package/src/app/api/db/maintenance/route.ts +0 -72
  270. package/src/app/api/db/monitoring/route.ts +0 -62
  271. package/src/app/api/db/multi-query/route.ts +0 -116
  272. package/src/app/api/db/pool-stats/route.ts +0 -37
  273. package/src/app/api/db/profile/route.ts +0 -144
  274. package/src/app/api/db/provider-meta/route.ts +0 -49
  275. package/src/app/api/db/query/route.ts +0 -50
  276. package/src/app/api/db/schema/route.ts +0 -47
  277. package/src/app/api/db/schema-snapshot/route.ts +0 -42
  278. package/src/app/api/db/test-connection/route.ts +0 -55
  279. package/src/app/api/db/transaction/route.ts +0 -111
  280. package/src/app/api/storage/[collection]/route.ts +0 -67
  281. package/src/app/api/storage/config/route.ts +0 -17
  282. package/src/app/api/storage/migrate/route.ts +0 -45
  283. package/src/app/api/storage/route.ts +0 -32
  284. package/src/app/error.tsx +0 -49
  285. package/src/app/global-error.tsx +0 -55
  286. package/src/app/globals.css +0 -146
  287. package/src/app/icon.svg +0 -42
  288. package/src/app/layout.tsx +0 -34
  289. package/src/app/login/login-form.tsx +0 -301
  290. package/src/app/login/page.tsx +0 -11
  291. package/src/app/monitoring/page.tsx +0 -8
  292. package/src/app/not-found.tsx +0 -29
  293. package/src/app/page.tsx +0 -5
  294. package/src/components/AIAutopilotPanel.tsx +0 -238
  295. package/src/components/CodeGenerator.tsx +0 -271
  296. package/src/components/CommandPalette.tsx +0 -227
  297. package/src/components/ConnectionModal.tsx +0 -759
  298. package/src/components/CreateTableModal.tsx +0 -281
  299. package/src/components/DataCharts.tsx +0 -962
  300. package/src/components/DataImportModal.tsx +0 -582
  301. package/src/components/DataProfiler.tsx +0 -335
  302. package/src/components/DatabaseDocs.tsx +0 -251
  303. package/src/components/MaskingSettings.tsx +0 -414
  304. package/src/components/MobileNav.tsx +0 -50
  305. package/src/components/NL2SQLPanel.tsx +0 -281
  306. package/src/components/PivotTable.tsx +0 -257
  307. package/src/components/QueryEditor.tsx +0 -760
  308. package/src/components/QueryHistory.tsx +0 -344
  309. package/src/components/QuerySafetyDialog.tsx +0 -290
  310. package/src/components/ResultsGrid.tsx +0 -644
  311. package/src/components/SaveQueryModal.tsx +0 -104
  312. package/src/components/SavedQueries.tsx +0 -128
  313. package/src/components/SchemaDiagram.tsx +0 -473
  314. package/src/components/SchemaDiff.tsx +0 -473
  315. package/src/components/SnapshotTimeline.tsx +0 -116
  316. package/src/components/Studio.tsx +0 -639
  317. package/src/components/TestDataGenerator.tsx +0 -261
  318. package/src/components/VisualExplain.tsx +0 -820
  319. package/src/components/admin/AdminDashboard.tsx +0 -163
  320. package/src/components/admin/tabs/AuditTab.tsx +0 -531
  321. package/src/components/admin/tabs/MonitoringEmbed.tsx +0 -11
  322. package/src/components/admin/tabs/OperationsTab.tsx +0 -646
  323. package/src/components/admin/tabs/OverviewTab.tsx +0 -1328
  324. package/src/components/admin/tabs/SecurityTab.tsx +0 -284
  325. package/src/components/community-section.tsx +0 -92
  326. package/src/components/icons/db-icons.tsx +0 -84
  327. package/src/components/libredb-logo.tsx +0 -61
  328. package/src/components/monitoring/MonitoringDashboard.tsx +0 -345
  329. package/src/components/monitoring/tabs/MetricChart.tsx +0 -82
  330. package/src/components/monitoring/tabs/OverviewTab.tsx +0 -263
  331. package/src/components/monitoring/tabs/PerformanceTab.tsx +0 -254
  332. package/src/components/monitoring/tabs/PoolTab.tsx +0 -174
  333. package/src/components/monitoring/tabs/QueriesTab.tsx +0 -287
  334. package/src/components/monitoring/tabs/SessionsTab.tsx +0 -316
  335. package/src/components/monitoring/tabs/StorageTab.tsx +0 -335
  336. package/src/components/monitoring/tabs/TablesTab.tsx +0 -300
  337. package/src/components/results-grid/ResultCard.tsx +0 -111
  338. package/src/components/results-grid/RowDetailSheet.tsx +0 -178
  339. package/src/components/results-grid/StatsBar.tsx +0 -201
  340. package/src/components/results-grid/index.ts +0 -1
  341. package/src/components/results-grid/utils.ts +0 -23
  342. package/src/components/schema-explorer/ColumnList.tsx +0 -53
  343. package/src/components/schema-explorer/SchemaExplorer.tsx +0 -182
  344. package/src/components/schema-explorer/TableItem.tsx +0 -210
  345. package/src/components/schema-explorer/index.ts +0 -1
  346. package/src/components/sidebar/ConnectionItem.tsx +0 -105
  347. package/src/components/sidebar/ConnectionsList.tsx +0 -62
  348. package/src/components/sidebar/Sidebar.tsx +0 -130
  349. package/src/components/sidebar/index.ts +0 -2
  350. package/src/components/studio/BottomPanel.tsx +0 -286
  351. package/src/components/studio/QueryToolbar.tsx +0 -180
  352. package/src/components/studio/StudioDesktopHeader.tsx +0 -114
  353. package/src/components/studio/StudioMobileHeader.tsx +0 -340
  354. package/src/components/studio/StudioTabBar.tsx +0 -82
  355. package/src/components/studio/index.ts +0 -5
  356. package/src/components/ui/accordion.tsx +0 -66
  357. package/src/components/ui/alert-dialog.tsx +0 -157
  358. package/src/components/ui/alert.tsx +0 -66
  359. package/src/components/ui/aspect-ratio.tsx +0 -11
  360. package/src/components/ui/avatar.tsx +0 -53
  361. package/src/components/ui/badge.tsx +0 -46
  362. package/src/components/ui/breadcrumb.tsx +0 -109
  363. package/src/components/ui/button-group.tsx +0 -83
  364. package/src/components/ui/button.tsx +0 -60
  365. package/src/components/ui/calendar.tsx +0 -216
  366. package/src/components/ui/card.tsx +0 -92
  367. package/src/components/ui/carousel.tsx +0 -241
  368. package/src/components/ui/chart.tsx +0 -357
  369. package/src/components/ui/checkbox.tsx +0 -32
  370. package/src/components/ui/collapsible.tsx +0 -33
  371. package/src/components/ui/command.tsx +0 -184
  372. package/src/components/ui/context-menu.tsx +0 -252
  373. package/src/components/ui/dialog.tsx +0 -143
  374. package/src/components/ui/drawer.tsx +0 -135
  375. package/src/components/ui/dropdown-menu.tsx +0 -257
  376. package/src/components/ui/empty.tsx +0 -104
  377. package/src/components/ui/field.tsx +0 -248
  378. package/src/components/ui/form.tsx +0 -167
  379. package/src/components/ui/hover-card.tsx +0 -44
  380. package/src/components/ui/input-group.tsx +0 -170
  381. package/src/components/ui/input-otp.tsx +0 -77
  382. package/src/components/ui/input.tsx +0 -21
  383. package/src/components/ui/item.tsx +0 -193
  384. package/src/components/ui/kbd.tsx +0 -28
  385. package/src/components/ui/label.tsx +0 -24
  386. package/src/components/ui/menubar.tsx +0 -276
  387. package/src/components/ui/navigation-menu.tsx +0 -168
  388. package/src/components/ui/pagination.tsx +0 -127
  389. package/src/components/ui/popover.tsx +0 -48
  390. package/src/components/ui/progress.tsx +0 -31
  391. package/src/components/ui/radio-group.tsx +0 -45
  392. package/src/components/ui/resizable.tsx +0 -56
  393. package/src/components/ui/scroll-area.tsx +0 -58
  394. package/src/components/ui/select.tsx +0 -187
  395. package/src/components/ui/separator.tsx +0 -28
  396. package/src/components/ui/sheet.tsx +0 -139
  397. package/src/components/ui/sidebar.tsx +0 -726
  398. package/src/components/ui/skeleton.tsx +0 -13
  399. package/src/components/ui/slider.tsx +0 -63
  400. package/src/components/ui/sonner.tsx +0 -40
  401. package/src/components/ui/spinner.tsx +0 -16
  402. package/src/components/ui/switch.tsx +0 -31
  403. package/src/components/ui/table.tsx +0 -116
  404. package/src/components/ui/tabs.tsx +0 -66
  405. package/src/components/ui/textarea.tsx +0 -18
  406. package/src/components/ui/toggle-group.tsx +0 -83
  407. package/src/components/ui/toggle.tsx +0 -47
  408. package/src/components/ui/tooltip.tsx +0 -61
  409. package/src/exports/components.ts +0 -15
  410. package/src/exports/index.ts +0 -4
  411. package/src/exports/providers.ts +0 -4
  412. package/src/exports/types.ts +0 -26
  413. package/src/hooks/use-ai-chat.ts +0 -182
  414. package/src/hooks/use-all-connections.ts +0 -66
  415. package/src/hooks/use-api-call.ts +0 -71
  416. package/src/hooks/use-auth.ts +0 -51
  417. package/src/hooks/use-connection-form.ts +0 -349
  418. package/src/hooks/use-connection-manager.ts +0 -169
  419. package/src/hooks/use-connection-payload.ts +0 -15
  420. package/src/hooks/use-inline-editing.ts +0 -109
  421. package/src/hooks/use-mobile.ts +0 -20
  422. package/src/hooks/use-monitoring-data.ts +0 -270
  423. package/src/hooks/use-provider-metadata.ts +0 -62
  424. package/src/hooks/use-query-execution.ts +0 -478
  425. package/src/hooks/use-storage-sync.ts +0 -259
  426. package/src/hooks/use-tab-manager.ts +0 -231
  427. package/src/hooks/use-toast.ts +0 -20
  428. package/src/hooks/use-transaction-control.ts +0 -64
  429. package/src/lib/api/error-codes.ts +0 -30
  430. package/src/lib/api/errors.ts +0 -236
  431. package/src/lib/api/with-error-handler.ts +0 -41
  432. package/src/lib/audit.ts +0 -105
  433. package/src/lib/auth.ts +0 -87
  434. package/src/lib/connection-string-parser.ts +0 -172
  435. package/src/lib/data-masking.ts +0 -385
  436. package/src/lib/db/base-provider.ts +0 -325
  437. package/src/lib/db/errors.ts +0 -317
  438. package/src/lib/db/factory.ts +0 -324
  439. package/src/lib/db/index.ts +0 -123
  440. package/src/lib/db/providers/document/index.ts +0 -6
  441. package/src/lib/db/providers/document/mongodb.ts +0 -992
  442. package/src/lib/db/providers/keyvalue/redis.ts +0 -554
  443. package/src/lib/db/providers/sql/index.ts +0 -11
  444. package/src/lib/db/providers/sql/sql-base.ts +0 -174
  445. package/src/lib/db/providers/sql/sqlite.ts +0 -721
  446. package/src/lib/db/types.ts +0 -437
  447. package/src/lib/db/utils/pool-manager.ts +0 -287
  448. package/src/lib/db/utils/query-limiter.ts +0 -239
  449. package/src/lib/db-ui-config.ts +0 -86
  450. package/src/lib/editor/mongodb-completions.ts +0 -172
  451. package/src/lib/editor/sql-completions.ts +0 -280
  452. package/src/lib/llm/base-provider.ts +0 -117
  453. package/src/lib/llm/factory.ts +0 -102
  454. package/src/lib/llm/index.ts +0 -90
  455. package/src/lib/llm/providers/custom.ts +0 -181
  456. package/src/lib/llm/providers/gemini.ts +0 -126
  457. package/src/lib/llm/providers/ollama.ts +0 -154
  458. package/src/lib/llm/providers/openai.ts +0 -146
  459. package/src/lib/llm/types.ts +0 -173
  460. package/src/lib/llm/utils/config.ts +0 -187
  461. package/src/lib/llm/utils/retry.ts +0 -119
  462. package/src/lib/llm/utils/streaming.ts +0 -202
  463. package/src/lib/logger.ts +0 -127
  464. package/src/lib/monitoring-thresholds.ts +0 -44
  465. package/src/lib/oidc.ts +0 -262
  466. package/src/lib/query-generators.ts +0 -61
  467. package/src/lib/schema-diff/diff-engine.ts +0 -273
  468. package/src/lib/schema-diff/migration-generator.ts +0 -208
  469. package/src/lib/schema-diff/types.ts +0 -55
  470. package/src/lib/seed/config-loader.ts +0 -79
  471. package/src/lib/seed/connection-filter.ts +0 -49
  472. package/src/lib/seed/credential-resolver.ts +0 -62
  473. package/src/lib/seed/index.ts +0 -40
  474. package/src/lib/seed/resolve-connection.ts +0 -57
  475. package/src/lib/seed/types.ts +0 -69
  476. package/src/lib/sql/alias-extractor.ts +0 -267
  477. package/src/lib/sql/index.ts +0 -8
  478. package/src/lib/sql/statement-splitter.ts +0 -167
  479. package/src/lib/sql/types.ts +0 -40
  480. package/src/lib/ssh/tunnel.ts +0 -142
  481. package/src/lib/storage/factory.ts +0 -84
  482. package/src/lib/storage/index.ts +0 -14
  483. package/src/lib/storage/local-storage.ts +0 -99
  484. package/src/lib/storage/providers/postgres.ts +0 -225
  485. package/src/lib/storage/providers/sqlite.ts +0 -153
  486. package/src/lib/storage/storage-facade.ts +0 -272
  487. package/src/lib/storage/types.ts +0 -75
  488. package/src/lib/time-series-buffer.ts +0 -58
  489. package/src/lib/types.ts +0 -173
  490. package/src/lib/utils.ts +0 -6
  491. package/src/proxy.ts +0 -104
  492. package/src/types/db-drivers.d.ts +0 -23
  493. package/src/types/html2canvas.d.ts +0 -9
  494. package/tests/api/admin/audit.test.ts +0 -178
  495. package/tests/api/admin/fleet-health.test.ts +0 -183
  496. package/tests/api/ai/autopilot.test.ts +0 -174
  497. package/tests/api/ai/chat.test.ts +0 -250
  498. package/tests/api/ai/describe-schema.test.ts +0 -266
  499. package/tests/api/ai/explain.test.ts +0 -199
  500. package/tests/api/ai/impact.test.ts +0 -168
  501. package/tests/api/ai/index-advisor.test.ts +0 -171
  502. package/tests/api/ai/nl2sql.test.ts +0 -202
  503. package/tests/api/ai/query-safety.test.ts +0 -196
  504. package/tests/api/auth/login.test.ts +0 -170
  505. package/tests/api/auth/logout.test.ts +0 -140
  506. package/tests/api/auth/me.test.ts +0 -73
  507. package/tests/api/auth/oidc-callback.test.ts +0 -215
  508. package/tests/api/auth/oidc-login.test.ts +0 -127
  509. package/tests/api/db/cancel.test.ts +0 -198
  510. package/tests/api/db/disconnect.test.ts +0 -124
  511. package/tests/api/db/health.test.ts +0 -222
  512. package/tests/api/db/maintenance.test.ts +0 -263
  513. package/tests/api/db/monitoring.test.ts +0 -221
  514. package/tests/api/db/multi-query.test.ts +0 -316
  515. package/tests/api/db/pool-stats.test.ts +0 -135
  516. package/tests/api/db/profile.test.ts +0 -330
  517. package/tests/api/db/provider-meta.test.ts +0 -193
  518. package/tests/api/db/query.test.ts +0 -314
  519. package/tests/api/db/schema-snapshot.test.ts +0 -170
  520. package/tests/api/db/schema.test.ts +0 -191
  521. package/tests/api/db/test-connection.test.ts +0 -185
  522. package/tests/api/db/transaction.test.ts +0 -314
  523. package/tests/api/proxy.test.ts +0 -191
  524. package/tests/api/seed/managed-route.test.ts +0 -113
  525. package/tests/api/storage/config.test.ts +0 -42
  526. package/tests/api/storage/storage-routes.test.ts +0 -309
  527. package/tests/components/AIAutopilotPanel.test.tsx +0 -756
  528. package/tests/components/AdminPage.test.tsx +0 -33
  529. package/tests/components/CodeGenerator.test.tsx +0 -182
  530. package/tests/components/CommandPalette.test.tsx +0 -428
  531. package/tests/components/CommunitySection.test.tsx +0 -91
  532. package/tests/components/ConnectionModal.mobile.test.tsx +0 -284
  533. package/tests/components/ConnectionModal.test.tsx +0 -570
  534. package/tests/components/CreateTableModal.test.tsx +0 -383
  535. package/tests/components/DataCharts.test.tsx +0 -739
  536. package/tests/components/DataImportModal.test.tsx +0 -751
  537. package/tests/components/DataProfiler.test.tsx +0 -589
  538. package/tests/components/DatabaseDocs.test.tsx +0 -353
  539. package/tests/components/LoginPage.test.tsx +0 -163
  540. package/tests/components/LoginPageOIDC.test.tsx +0 -92
  541. package/tests/components/MaskingSettings.test.tsx +0 -498
  542. package/tests/components/MobileNav.test.tsx +0 -30
  543. package/tests/components/MonitoringPage.test.tsx +0 -32
  544. package/tests/components/NL2SQLPanel.test.tsx +0 -621
  545. package/tests/components/Page.test.tsx +0 -33
  546. package/tests/components/PivotTable.test.tsx +0 -350
  547. package/tests/components/QueryEditor.test.tsx +0 -1730
  548. package/tests/components/QueryHistory.test.tsx +0 -572
  549. package/tests/components/QuerySafetyDialog.test.tsx +0 -586
  550. package/tests/components/ResultsGrid.test.tsx +0 -804
  551. package/tests/components/RootLayout.test.tsx +0 -83
  552. package/tests/components/SaveQueryModal.test.tsx +0 -25
  553. package/tests/components/SavedQueries.test.tsx +0 -43
  554. package/tests/components/SchemaDiagram.test.tsx +0 -1034
  555. package/tests/components/SchemaDiff.test.tsx +0 -906
  556. package/tests/components/SnapshotTimeline.test.tsx +0 -174
  557. package/tests/components/Studio.test.tsx +0 -1030
  558. package/tests/components/TestDataGenerator.test.tsx +0 -291
  559. package/tests/components/VisualExplain.test.tsx +0 -704
  560. package/tests/components/admin/AdminDashboard.test.tsx +0 -205
  561. package/tests/components/admin/AuditTab.test.tsx +0 -220
  562. package/tests/components/admin/MonitoringEmbed.test.tsx +0 -58
  563. package/tests/components/admin/OperationsTab.test.tsx +0 -975
  564. package/tests/components/admin/OverviewTab.test.tsx +0 -254
  565. package/tests/components/admin/SecurityTab.test.tsx +0 -467
  566. package/tests/components/monitoring/MetricChart.test.tsx +0 -111
  567. package/tests/components/monitoring/MonitoringDashboard.test.tsx +0 -259
  568. package/tests/components/monitoring/OverviewTab.test.tsx +0 -78
  569. package/tests/components/monitoring/PerformanceTab.test.tsx +0 -87
  570. package/tests/components/monitoring/PoolTab.test.tsx +0 -42
  571. package/tests/components/monitoring/QueriesTab.test.tsx +0 -80
  572. package/tests/components/monitoring/SessionsTab.test.tsx +0 -154
  573. package/tests/components/monitoring/StorageTab.test.tsx +0 -127
  574. package/tests/components/monitoring/TablesTab.test.tsx +0 -153
  575. package/tests/components/results-grid/ResultCard.test.tsx +0 -105
  576. package/tests/components/results-grid/RowDetailSheet.test.tsx +0 -308
  577. package/tests/components/results-grid/StatsBar.test.tsx +0 -162
  578. package/tests/components/schema-explorer/ColumnList.test.tsx +0 -151
  579. package/tests/components/schema-explorer/SchemaExplorer.test.tsx +0 -461
  580. package/tests/components/schema-explorer/TableItem.test.tsx +0 -415
  581. package/tests/components/sidebar/ConnectionItem.test.tsx +0 -201
  582. package/tests/components/sidebar/ConnectionsList.test.tsx +0 -176
  583. package/tests/components/sidebar/Sidebar.test.tsx +0 -187
  584. package/tests/components/studio/BottomPanel.test.tsx +0 -383
  585. package/tests/components/studio/QueryToolbar.test.tsx +0 -321
  586. package/tests/components/studio/StudioDesktopHeader.test.tsx +0 -377
  587. package/tests/components/studio/StudioMobileHeader.test.tsx +0 -198
  588. package/tests/components/studio/StudioTabBar.test.tsx +0 -331
  589. package/tests/fixtures/connections.ts +0 -96
  590. package/tests/fixtures/masking-configs.ts +0 -86
  591. package/tests/fixtures/query-results.ts +0 -71
  592. package/tests/fixtures/schemas.ts +0 -64
  593. package/tests/fixtures/seed-connections/invalid-config.yaml +0 -7
  594. package/tests/fixtures/seed-connections/minimal-config.yaml +0 -8
  595. package/tests/fixtures/seed-connections/mixed-credentials.yaml +0 -23
  596. package/tests/fixtures/seed-connections/multi-role-config.yaml +0 -30
  597. package/tests/fixtures/seed-connections/valid-config.json +0 -15
  598. package/tests/fixtures/seed-connections/valid-config.yaml +0 -51
  599. package/tests/helpers/mock-fetch.ts +0 -59
  600. package/tests/helpers/mock-monaco.ts +0 -112
  601. package/tests/helpers/mock-navigation.ts +0 -28
  602. package/tests/helpers/mock-next.ts +0 -80
  603. package/tests/helpers/mock-provider.ts +0 -133
  604. package/tests/helpers/mock-sonner.ts +0 -29
  605. package/tests/helpers/render-with-providers.tsx +0 -19
  606. package/tests/hooks/use-ai-chat.test.ts +0 -600
  607. package/tests/hooks/use-auth.test.ts +0 -371
  608. package/tests/hooks/use-connection-form.test.ts +0 -743
  609. package/tests/hooks/use-connection-manager.test.ts +0 -466
  610. package/tests/hooks/use-inline-editing.test.ts +0 -321
  611. package/tests/hooks/use-mobile.test.ts +0 -177
  612. package/tests/hooks/use-monitoring-data.test.ts +0 -819
  613. package/tests/hooks/use-provider-metadata.test.ts +0 -228
  614. package/tests/hooks/use-query-execution.test.ts +0 -1212
  615. package/tests/hooks/use-tab-manager.test.ts +0 -756
  616. package/tests/hooks/use-toast.test.ts +0 -74
  617. package/tests/hooks/use-transaction-control.test.ts +0 -211
  618. package/tests/integration/db/mongodb-provider.test.ts +0 -698
  619. package/tests/integration/db/mssql-provider.test.ts +0 -840
  620. package/tests/integration/db/mysql-provider.test.ts +0 -872
  621. package/tests/integration/db/oracle-provider.test.ts +0 -843
  622. package/tests/integration/db/postgres-provider.test.ts +0 -1382
  623. package/tests/integration/db/redis-provider.test.ts +0 -526
  624. package/tests/integration/db/sqlite-provider.test.ts +0 -480
  625. package/tests/integration/seed/seed-pipeline.test.ts +0 -102
  626. package/tests/isolated/factory-singleton.test.ts +0 -150
  627. package/tests/isolated/use-storage-sync.test.ts +0 -389
  628. package/tests/run-components.sh +0 -196
  629. package/tests/setup-dom.ts +0 -58
  630. package/tests/setup.ts +0 -40
  631. package/tests/unit/api-errors.test.ts +0 -210
  632. package/tests/unit/code-generator-functions.test.ts +0 -271
  633. package/tests/unit/components/column-list.test.tsx +0 -190
  634. package/tests/unit/components/data-import-modal.test.tsx +0 -441
  635. package/tests/unit/components/studio-mobile-header.test.tsx +0 -327
  636. package/tests/unit/data-charts-functions.test.ts +0 -496
  637. package/tests/unit/data-import-functions.test.ts +0 -320
  638. package/tests/unit/data-import-utils.test.ts +0 -125
  639. package/tests/unit/db/base-provider.test.ts +0 -517
  640. package/tests/unit/db/errors.test.ts +0 -403
  641. package/tests/unit/db/factory.test.ts +0 -436
  642. package/tests/unit/db/pool-manager.test.ts +0 -440
  643. package/tests/unit/db/query-limiter.test.ts +0 -387
  644. package/tests/unit/db/sql-base.test.ts +0 -438
  645. package/tests/unit/lib/api/error-codes.test.ts +0 -39
  646. package/tests/unit/lib/audit.test.ts +0 -326
  647. package/tests/unit/lib/auth.test.ts +0 -146
  648. package/tests/unit/lib/connection-string-parser.test.ts +0 -424
  649. package/tests/unit/lib/data-masking.test.ts +0 -583
  650. package/tests/unit/lib/db-icons.test.tsx +0 -41
  651. package/tests/unit/lib/monitoring-thresholds.test.ts +0 -133
  652. package/tests/unit/lib/oidc.test.ts +0 -509
  653. package/tests/unit/lib/query-generators.test.ts +0 -127
  654. package/tests/unit/lib/storage/factory.test.ts +0 -71
  655. package/tests/unit/lib/storage/local-storage.test.ts +0 -114
  656. package/tests/unit/lib/storage/providers/postgres.test.ts +0 -312
  657. package/tests/unit/lib/storage/providers/sqlite.test.ts +0 -232
  658. package/tests/unit/lib/storage/storage-facade-extended.test.ts +0 -331
  659. package/tests/unit/lib/storage/storage-facade.test.ts +0 -184
  660. package/tests/unit/lib/storage.test.ts +0 -317
  661. package/tests/unit/lib/time-series-buffer.test.ts +0 -212
  662. package/tests/unit/lib/utils.test.ts +0 -24
  663. package/tests/unit/llm/base-provider.test.ts +0 -238
  664. package/tests/unit/llm/config.test.ts +0 -262
  665. package/tests/unit/llm/custom-provider.test.ts +0 -281
  666. package/tests/unit/llm/gemini-provider.test.ts +0 -248
  667. package/tests/unit/llm/llm-factory.test.ts +0 -155
  668. package/tests/unit/llm/ollama-provider.test.ts +0 -288
  669. package/tests/unit/llm/openai-provider.test.ts +0 -324
  670. package/tests/unit/llm/retry.test.ts +0 -180
  671. package/tests/unit/llm/streaming.test.ts +0 -355
  672. package/tests/unit/logger.test.ts +0 -198
  673. package/tests/unit/mongodb-completions.test.ts +0 -516
  674. package/tests/unit/pivot-table-functions.test.ts +0 -76
  675. package/tests/unit/query-cancelled-error.test.ts +0 -81
  676. package/tests/unit/schema-diff/diff-engine.test.ts +0 -367
  677. package/tests/unit/schema-diff/migration-generator.test.ts +0 -513
  678. package/tests/unit/seed/config-loader.test.ts +0 -73
  679. package/tests/unit/seed/connection-filter.test.ts +0 -91
  680. package/tests/unit/seed/credential-resolver.test.ts +0 -85
  681. package/tests/unit/seed/index.test.ts +0 -72
  682. package/tests/unit/seed/resolve-connection.test.ts +0 -74
  683. package/tests/unit/seed/types.test.ts +0 -129
  684. package/tests/unit/sql/alias-extractor.test.ts +0 -444
  685. package/tests/unit/sql/statement-splitter.test.ts +0 -348
  686. package/tests/unit/sql-completions.test.ts +0 -463
  687. package/tests/unit/ssh-tunnel.test.ts +0 -465
  688. package/tsconfig.json +0 -42
@@ -1,1362 +0,0 @@
1
- # Seed Connections Implementation Plan
2
-
3
- > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
-
5
- **Goal:** Enable pre-configured database connections via YAML/JSON config file with role-based access control and hybrid managed/unmanaged model.
6
-
7
- **Architecture:** Dedicated `src/lib/seed/` module reads a volume-mounted config file at runtime (TTL-cached), resolves `${ENV_VAR}` credentials from `process.env`, filters by user role, and serves managed connections via a new API endpoint. A shared `resolveConnection()` utility is injected into 13 existing DB API routes to handle `seed:` prefixed connection IDs server-side. Client hooks merge managed connections with user connections, sending `connectionId` instead of full credentials for managed connections.
8
-
9
- **Tech Stack:** TypeScript, Zod v4 (validation — project uses `^4.1.12`), `yaml` npm package (YAML parsing), Next.js API routes, existing JWT auth (`jose`)
10
-
11
- **Spec:** `docs/superpowers/specs/2026-03-25-seed-connections-design.md`
12
-
13
- **Important notes:**
14
- - Project uses **Zod v4** (`^4.1.12`). All schema code uses v4 API (`.check()` instead of `.refine()` for some patterns, `z.object()` still supports `.strict()`). Verify Zod v4 compatibility at each step.
15
- - **`disconnect/route.ts` is EXCLUDED** from `resolveConnection()` injection — it already accepts `connectionId` as a cache key for provider teardown, not connection establishment. The `seed:X` prefixed IDs flow naturally because `resolveConnection()` sets `id = "seed:X"` which becomes the cache key.
16
- - **`POST /api/db/health`** (connection-level health check) IS included as an affected route.
17
- - `pool-stats/route.ts` and `provider-meta/route.ts` are both **POST** routes, not GET.
18
-
19
- ---
20
-
21
- ## File Map
22
-
23
- ### New Files
24
-
25
- | File | Responsibility |
26
- |------|---------------|
27
- | `src/lib/seed/types.ts` | Zod v4 schemas + TS types: `SeedConfig`, `SeedConnection`, `SeedDefaults`, `ManagedConnection` |
28
- | `src/lib/seed/config-loader.ts` | Read YAML/JSON from disk, validate with Zod, TTL cache |
29
- | `src/lib/seed/credential-resolver.ts` | Resolve `${VAR}` patterns from `process.env`, per-connection error isolation |
30
- | `src/lib/seed/connection-filter.ts` | Merge defaults, filter by role, map to `ManagedConnection` |
31
- | `src/lib/seed/resolve-connection.ts` | Shared utility for all API routes: detect `seed:` prefix, resolve full credentials, verify role |
32
- | `src/lib/seed/index.ts` | Barrel export: `getManagedConnections(roles)` + `getSeedConnectionById()` + `getSeedConnectionByIdUnfiltered()` |
33
- | `src/hooks/use-connection-payload.ts` | Shared helper: `buildConnectionPayload(conn)` — returns `{ connectionId }` or `{ connection }` based on `managed` flag |
34
- | `src/app/api/connections/managed/route.ts` | `GET /api/connections/managed` — auth + role filter + credential stripping |
35
- | `charts/libredb-studio/templates/seed-configmap.yaml` | Helm ConfigMap for seed config |
36
- | `tests/fixtures/seed-connections/valid-config.yaml` | Full valid config fixture |
37
- | `tests/fixtures/seed-connections/valid-config.json` | Same config in JSON format (for format detection test) |
38
- | `tests/fixtures/seed-connections/minimal-config.yaml` | Minimum required fields only |
39
- | `tests/fixtures/seed-connections/invalid-config.yaml` | Validation failure cases |
40
- | `tests/fixtures/seed-connections/mixed-credentials.yaml` | Some `${VAR}`, some plaintext |
41
- | `tests/fixtures/seed-connections/multi-role-config.yaml` | Different roles per connection |
42
- | `tests/unit/seed/types.test.ts` | Zod schema validation tests |
43
- | `tests/unit/seed/config-loader.test.ts` | File read, parse, cache, error handling |
44
- | `tests/unit/seed/credential-resolver.test.ts` | Env var resolution, skip, warn |
45
- | `tests/unit/seed/connection-filter.test.ts` | Role filter, defaults merge, mapping |
46
- | `tests/unit/seed/index.test.ts` | Orchestrator + getSeedConnectionById tests |
47
- | `tests/unit/seed/resolve-connection.test.ts` | Seed prefix detection, role check, fallback |
48
- | `tests/api/seed/managed-route.test.ts` | API endpoint auth, filter, strip, errors |
49
- | `tests/integration/seed/seed-pipeline.test.ts` | Full pipeline + multi-route resolution |
50
-
51
- **Not in this plan (future task):** `e2e/seed-connections.spec.ts` — Playwright E2E test for managed connections in sidebar. Requires running app with seed config, best handled as a separate task after core implementation is stable.
52
-
53
- ### Modified Files
54
-
55
- | File | Change |
56
- |------|--------|
57
- | `src/lib/types.ts:42-61` | Add `managed?: boolean`, `seedId?: string` to `DatabaseConnection` |
58
- | `src/lib/audit.ts` | Add `'managed_connection'` to `AuditEventType` |
59
- | `src/app/api/db/query/route.ts` | Import `resolveConnection`, use before `getOrCreateProvider` |
60
- | `src/app/api/db/schema/route.ts` | Same pattern (also change body parsing to `req.json()`) |
61
- | `src/app/api/db/multi-query/route.ts` | Same pattern |
62
- | `src/app/api/db/transaction/route.ts` | Same pattern |
63
- | `src/app/api/db/cancel/route.ts` | Same pattern |
64
- | `src/app/api/db/maintenance/route.ts` | Same pattern |
65
- | `src/app/api/db/monitoring/route.ts` | Same pattern |
66
- | `src/app/api/db/pool-stats/route.ts` | Same pattern (POST route) |
67
- | `src/app/api/db/profile/route.ts` | Same pattern |
68
- | `src/app/api/db/provider-meta/route.ts` | Same pattern (POST route) |
69
- | `src/app/api/db/test-connection/route.ts` | Same pattern |
70
- | `src/app/api/db/schema-snapshot/route.ts` | Same pattern |
71
- | `src/app/api/db/health/route.ts` | Same pattern (POST connection health check) |
72
- | `src/hooks/use-connection-manager.ts` | Fetch managed connections, merge with user connections, update `fetchSchema` |
73
- | `src/hooks/use-query-execution.ts` | Use `buildConnectionPayload()` at all 5 fetch sites |
74
- | `src/hooks/use-transaction-control.ts` | Use `buildConnectionPayload()` |
75
- | `src/components/sidebar/ConnectionItem.tsx:82-106` | Lock icon for managed, hide edit/delete |
76
- | `charts/libredb-studio/values.yaml` | Add `seedConnections` section |
77
- | `charts/libredb-studio/values.schema.json` | Add `seedConnections` schema |
78
- | `charts/libredb-studio/templates/deployment.yaml` | Volume mount + env vars |
79
- | `docker-compose.yml` | Add seed config volume mount example |
80
- | `.env.example` | Document new env vars |
81
-
82
- **NOT modified:** `src/app/api/db/disconnect/route.ts` — already accepts `connectionId` as cache key, `seed:X` IDs work naturally.
83
-
84
- ---
85
-
86
- ## Task 1: Install `yaml` dependency + add test fixtures
87
-
88
- **Files:**
89
- - Modify: `package.json`
90
- - Create: `tests/fixtures/seed-connections/valid-config.yaml`
91
- - Create: `tests/fixtures/seed-connections/valid-config.json`
92
- - Create: `tests/fixtures/seed-connections/minimal-config.yaml`
93
- - Create: `tests/fixtures/seed-connections/invalid-config.yaml`
94
- - Create: `tests/fixtures/seed-connections/mixed-credentials.yaml`
95
- - Create: `tests/fixtures/seed-connections/multi-role-config.yaml`
96
-
97
- - [ ] **Step 1: Install yaml package**
98
-
99
- ```bash
100
- bun add yaml
101
- ```
102
-
103
- - [ ] **Step 2: Create valid-config.yaml fixture**
104
-
105
- ```yaml
106
- # tests/fixtures/seed-connections/valid-config.yaml
107
- version: "1"
108
-
109
- defaults:
110
- managed: true
111
- environment: production
112
-
113
- connections:
114
- - id: "test-postgres"
115
- name: "Test PostgreSQL"
116
- type: postgres
117
- host: pg.internal
118
- port: 5432
119
- database: testdb
120
- user: "testuser"
121
- password: "${TEST_PG_PASSWORD}"
122
- environment: production
123
- group: "Backend"
124
- roles: ["admin"]
125
- managed: true
126
- color: "#10B981"
127
-
128
- - id: "test-mysql"
129
- name: "Test MySQL"
130
- type: mysql
131
- host: mysql.internal
132
- port: 3306
133
- database: appdb
134
- user: "devuser"
135
- password: "${TEST_MYSQL_PASSWORD}"
136
- environment: staging
137
- group: "Backend"
138
- roles: ["*"]
139
- managed: false
140
-
141
- - id: "test-mongo"
142
- name: "Test MongoDB"
143
- type: mongodb
144
- connectionString: "${TEST_MONGO_URI}"
145
- group: "Platform"
146
- roles: ["admin"]
147
- managed: true
148
-
149
- - id: "test-redis"
150
- name: "Test Redis"
151
- type: redis
152
- host: redis.internal
153
- port: 6379
154
- database: "0"
155
- password: "${TEST_REDIS_PASSWORD}"
156
- roles: ["*"]
157
- managed: true
158
- ```
159
-
160
- - [ ] **Step 3: Create valid-config.json fixture** (same data, JSON format)
161
-
162
- ```json
163
- {
164
- "version": "1",
165
- "defaults": { "managed": true, "environment": "production" },
166
- "connections": [
167
- {
168
- "id": "test-postgres",
169
- "name": "Test PostgreSQL",
170
- "type": "postgres",
171
- "host": "pg.internal",
172
- "port": 5432,
173
- "password": "${TEST_PG_PASSWORD}",
174
- "roles": ["admin"]
175
- }
176
- ]
177
- }
178
- ```
179
-
180
- - [ ] **Step 4: Create minimal-config.yaml, invalid-config.yaml, mixed-credentials.yaml, multi-role-config.yaml**
181
-
182
- (Same content as previous plan version — these fixtures are unchanged)
183
-
184
- - [ ] **Step 5: Commit**
185
-
186
- ```bash
187
- git add package.json bun.lockb tests/fixtures/seed-connections/
188
- git commit -m "feat(seed): add yaml dependency and test fixtures for seed connections"
189
- ```
190
-
191
- ---
192
-
193
- ## Task 2: Types + Zod v4 Schemas (`src/lib/seed/types.ts`)
194
-
195
- **Files:**
196
- - Modify: `src/lib/types.ts:42-61`
197
- - Create: `src/lib/seed/types.ts`
198
- - Create: `tests/unit/seed/types.test.ts`
199
-
200
- **Important:** Project uses Zod v4 (`^4.1.12`). Key v4 changes: `z.object()` still works, `.strict()` still works, `.safeParse()` returns `{ success, data, error }`, `.refine()` still works. Verify with `bun test` at each step.
201
-
202
- - [ ] **Step 1: Add `managed` and `seedId` to DatabaseConnection**
203
-
204
- In `src/lib/types.ts`, add two optional fields after `instanceName?` (line 60):
205
-
206
- ```typescript
207
- managed?: boolean; // true = admin-controlled, read-only in UI
208
- seedId?: string; // stable reference to seed config ID
209
- ```
210
-
211
- - [ ] **Step 2: Write failing tests for Zod schemas**
212
-
213
- Create `tests/unit/seed/types.test.ts` — same tests as previous plan, but **without `'prefer'` in SSLMode** and with Zod v4 API compatibility confirmed:
214
-
215
- ```typescript
216
- import { describe, it, expect } from 'bun:test';
217
- import {
218
- SeedConnectionSchema,
219
- SeedConfigSchema,
220
- SeedDefaultsSchema,
221
- } from '@/lib/seed/types';
222
-
223
- describe('SeedConnectionSchema', () => {
224
- const validConn = {
225
- id: 'test-pg',
226
- name: 'Test PG',
227
- type: 'postgres',
228
- host: 'localhost',
229
- port: 5432,
230
- roles: ['admin'],
231
- };
232
-
233
- it('accepts a valid connection', () => {
234
- const result = SeedConnectionSchema.safeParse(validConn);
235
- expect(result.success).toBe(true);
236
- });
237
-
238
- it('rejects invalid id format (uppercase)', () => {
239
- const result = SeedConnectionSchema.safeParse({ ...validConn, id: 'INVALID' });
240
- expect(result.success).toBe(false);
241
- });
242
-
243
- it('rejects empty name', () => {
244
- const result = SeedConnectionSchema.safeParse({ ...validConn, name: '' });
245
- expect(result.success).toBe(false);
246
- });
247
-
248
- it('rejects demo type', () => {
249
- const result = SeedConnectionSchema.safeParse({ ...validConn, type: 'demo' });
250
- expect(result.success).toBe(false);
251
- });
252
-
253
- it('rejects empty roles array', () => {
254
- const result = SeedConnectionSchema.safeParse({ ...validConn, roles: [] });
255
- expect(result.success).toBe(false);
256
- });
257
-
258
- it('accepts wildcard role', () => {
259
- const result = SeedConnectionSchema.safeParse({ ...validConn, roles: ['*'] });
260
- expect(result.success).toBe(true);
261
- });
262
-
263
- it('rejects unknown roles like data-team', () => {
264
- const result = SeedConnectionSchema.safeParse({ ...validConn, roles: ['data-team'] });
265
- expect(result.success).toBe(false);
266
- });
267
-
268
- it('accepts combined admin and user roles', () => {
269
- const result = SeedConnectionSchema.safeParse({ ...validConn, roles: ['admin', 'user'] });
270
- expect(result.success).toBe(true);
271
- });
272
-
273
- it('rejects invalid port range', () => {
274
- const result = SeedConnectionSchema.safeParse({ ...validConn, port: 99999 });
275
- expect(result.success).toBe(false);
276
- });
277
-
278
- it('accepts valid color hex', () => {
279
- const result = SeedConnectionSchema.safeParse({ ...validConn, color: '#10B981' });
280
- expect(result.success).toBe(true);
281
- });
282
-
283
- it('rejects invalid color format', () => {
284
- const result = SeedConnectionSchema.safeParse({ ...validConn, color: 'red' });
285
- expect(result.success).toBe(false);
286
- });
287
-
288
- it('accepts all 7 valid database types', () => {
289
- for (const type of ['postgres', 'mysql', 'sqlite', 'mongodb', 'redis', 'oracle', 'mssql']) {
290
- const result = SeedConnectionSchema.safeParse({ ...validConn, type });
291
- expect(result.success).toBe(true);
292
- }
293
- });
294
- });
295
-
296
- describe('SeedConfigSchema', () => {
297
- it('accepts valid config with version 1', () => {
298
- const result = SeedConfigSchema.safeParse({
299
- version: '1',
300
- connections: [{ id: 'a', name: 'A', type: 'postgres', host: 'h', roles: ['*'] }],
301
- });
302
- expect(result.success).toBe(true);
303
- });
304
-
305
- it('rejects version 2', () => {
306
- const result = SeedConfigSchema.safeParse({
307
- version: '2',
308
- connections: [{ id: 'a', name: 'A', type: 'postgres', host: 'h', roles: ['*'] }],
309
- });
310
- expect(result.success).toBe(false);
311
- });
312
-
313
- it('rejects duplicate connection IDs', () => {
314
- const result = SeedConfigSchema.safeParse({
315
- version: '1',
316
- connections: [
317
- { id: 'dup', name: 'A', type: 'postgres', host: 'h', roles: ['*'] },
318
- { id: 'dup', name: 'B', type: 'mysql', host: 'h', roles: ['*'] },
319
- ],
320
- });
321
- expect(result.success).toBe(false);
322
- });
323
-
324
- it('rejects empty connections array', () => {
325
- const result = SeedConfigSchema.safeParse({ version: '1', connections: [] });
326
- expect(result.success).toBe(false);
327
- });
328
- });
329
-
330
- describe('SeedDefaultsSchema', () => {
331
- it('accepts valid ssl config with mode require', () => {
332
- const result = SeedDefaultsSchema.safeParse({
333
- ssl: { mode: 'require', rejectUnauthorized: true },
334
- });
335
- expect(result.success).toBe(true);
336
- });
337
-
338
- it('rejects ssl mode prefer (not in SSLMode type)', () => {
339
- const result = SeedDefaultsSchema.safeParse({
340
- ssl: { mode: 'prefer' },
341
- });
342
- expect(result.success).toBe(false);
343
- });
344
-
345
- it('rejects invalid environment', () => {
346
- const result = SeedDefaultsSchema.safeParse({ environment: 'unknown' });
347
- expect(result.success).toBe(false);
348
- });
349
- });
350
- ```
351
-
352
- - [ ] **Step 3: Run tests to verify they fail**
353
-
354
- ```bash
355
- bun test tests/unit/seed/types.test.ts
356
- ```
357
-
358
- Expected: FAIL — `@/lib/seed/types` does not exist yet
359
-
360
- - [ ] **Step 4: Implement types.ts**
361
-
362
- Create `src/lib/seed/types.ts`:
363
-
364
- ```typescript
365
- import { z } from 'zod';
366
- import type { DatabaseConnection } from '@/lib/types';
367
-
368
- // SSLMode matches src/lib/types.ts line 21 — NO 'prefer'
369
- const SSLModeSchema = z.enum(['disable', 'require', 'verify-ca', 'verify-full']);
370
-
371
- const SSLConfigSchema = z.object({
372
- mode: SSLModeSchema.optional(),
373
- rejectUnauthorized: z.boolean().optional(),
374
- caCert: z.string().optional(),
375
- clientCert: z.string().optional(),
376
- clientKey: z.string().optional(),
377
- }).optional();
378
-
379
- const ConnectionEnvironmentSchema = z.enum([
380
- 'production', 'staging', 'development', 'local', 'other',
381
- ]);
382
-
383
- // Allowed roles in current iteration (matches JWT role: 'admin' | 'user' + wildcard)
384
- const AllowedRoleSchema = z.enum(['*', 'admin', 'user']);
385
-
386
- const SeedDatabaseType = z.enum([
387
- 'postgres', 'mysql', 'sqlite', 'mongodb', 'redis', 'oracle', 'mssql',
388
- ]);
389
-
390
- export const SeedDefaultsSchema = z.object({
391
- managed: z.boolean().optional(),
392
- environment: ConnectionEnvironmentSchema.optional(),
393
- ssl: SSLConfigSchema,
394
- });
395
-
396
- export const SeedConnectionSchema = z.object({
397
- id: z.string().min(1).max(64).regex(/^[a-z0-9-]+$/, 'ID must be lowercase alphanumeric with hyphens'),
398
- name: z.string().min(1).max(128),
399
- type: SeedDatabaseType,
400
- host: z.string().optional(),
401
- port: z.number().int().min(1).max(65535).optional(),
402
- database: z.string().optional(),
403
- user: z.string().optional(),
404
- password: z.string().optional(),
405
- connectionString: z.string().optional(),
406
- environment: ConnectionEnvironmentSchema.optional(),
407
- group: z.string().max(64).optional(),
408
- color: z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
409
- roles: z.array(AllowedRoleSchema).min(1, 'At least one role is required'),
410
- managed: z.boolean().optional(),
411
- ssl: SSLConfigSchema,
412
- serviceName: z.string().optional(),
413
- instanceName: z.string().optional(),
414
- });
415
-
416
- export const SeedConfigSchema = z.object({
417
- version: z.literal('1'),
418
- defaults: SeedDefaultsSchema.optional(),
419
- connections: z.array(SeedConnectionSchema).min(1, 'At least one connection is required'),
420
- }).refine(
421
- (cfg) => new Set(cfg.connections.map((c) => c.id)).size === cfg.connections.length,
422
- { message: 'Connection IDs must be unique' },
423
- );
424
-
425
- export type SeedConnection = z.infer<typeof SeedConnectionSchema>;
426
- export type SeedDefaults = z.infer<typeof SeedDefaultsSchema>;
427
- export type SeedConfig = z.infer<typeof SeedConfigSchema>;
428
-
429
- export interface ManagedConnection extends DatabaseConnection {
430
- managed: boolean;
431
- roles: string[];
432
- seedId: string;
433
- }
434
- ```
435
-
436
- - [ ] **Step 5: Run tests to verify they pass**
437
-
438
- ```bash
439
- bun test tests/unit/seed/types.test.ts
440
- ```
441
-
442
- Expected: All PASS. If Zod v4 API differs, adjust accordingly.
443
-
444
- - [ ] **Step 6: Commit**
445
-
446
- ```bash
447
- git add src/lib/types.ts src/lib/seed/types.ts tests/unit/seed/types.test.ts
448
- git commit -m "feat(seed): add Zod v4 schemas and types for seed connections"
449
- ```
450
-
451
- ---
452
-
453
- ## Task 3: Config Loader (`src/lib/seed/config-loader.ts`)
454
-
455
- **Files:**
456
- - Create: `src/lib/seed/config-loader.ts`
457
- - Create: `tests/unit/seed/config-loader.test.ts`
458
-
459
- - [ ] **Step 1: Write failing tests**
460
-
461
- Create `tests/unit/seed/config-loader.test.ts`:
462
-
463
- ```typescript
464
- import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
465
- import path from 'path';
466
- import { loadConfig, resetCache } from '@/lib/seed/config-loader';
467
-
468
- const FIXTURES = path.resolve(__dirname, '../../../fixtures/seed-connections');
469
-
470
- describe('config-loader', () => {
471
- beforeEach(() => {
472
- resetCache();
473
- });
474
-
475
- afterEach(() => {
476
- delete process.env.SEED_CONFIG_PATH;
477
- delete process.env.SEED_CACHE_TTL_MS;
478
- });
479
-
480
- it('loads and parses valid YAML config', async () => {
481
- process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'valid-config.yaml');
482
- const config = await loadConfig();
483
- expect(config).not.toBeNull();
484
- expect(config!.version).toBe('1');
485
- expect(config!.connections).toHaveLength(4);
486
- expect(config!.connections[0].id).toBe('test-postgres');
487
- });
488
-
489
- it('loads and parses valid JSON config', async () => {
490
- process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'valid-config.json');
491
- const config = await loadConfig();
492
- expect(config).not.toBeNull();
493
- expect(config!.version).toBe('1');
494
- expect(config!.connections).toHaveLength(1);
495
- });
496
-
497
- it('returns null when config file does not exist', async () => {
498
- process.env.SEED_CONFIG_PATH = '/nonexistent/path/config.yaml';
499
- const config = await loadConfig();
500
- expect(config).toBeNull();
501
- });
502
-
503
- it('throws on invalid YAML (validation fails)', async () => {
504
- process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'invalid-config.yaml');
505
- await expect(loadConfig()).rejects.toThrow();
506
- });
507
-
508
- it('uses default path when SEED_CONFIG_PATH not set', async () => {
509
- const config = await loadConfig();
510
- expect(config).toBeNull();
511
- });
512
-
513
- it('caches result within TTL', async () => {
514
- process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'valid-config.yaml');
515
- process.env.SEED_CACHE_TTL_MS = '60000';
516
- const config1 = await loadConfig();
517
- const config2 = await loadConfig();
518
- expect(config1).toBe(config2); // same reference
519
- });
520
-
521
- it('reloads after cache reset', async () => {
522
- process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'valid-config.yaml');
523
- const config1 = await loadConfig();
524
- resetCache();
525
- const config2 = await loadConfig();
526
- expect(config1).not.toBe(config2); // different reference
527
- expect(config1!.connections).toHaveLength(config2!.connections.length);
528
- });
529
-
530
- it('loads minimal config with only required fields', async () => {
531
- process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'minimal-config.yaml');
532
- const config = await loadConfig();
533
- expect(config).not.toBeNull();
534
- expect(config!.connections).toHaveLength(1);
535
- });
536
- });
537
- ```
538
-
539
- - [ ] **Step 2: Run tests to verify they fail**
540
-
541
- ```bash
542
- bun test tests/unit/seed/config-loader.test.ts
543
- ```
544
-
545
- - [ ] **Step 3: Implement config-loader.ts**
546
-
547
- Create `src/lib/seed/config-loader.ts` — same implementation as before (readFile → parse YAML/JSON → Zod validate → TTL cache).
548
-
549
- - [ ] **Step 4: Run tests to verify they pass**
550
-
551
- ```bash
552
- bun test tests/unit/seed/config-loader.test.ts
553
- ```
554
-
555
- - [ ] **Step 5: Commit**
556
-
557
- ```bash
558
- git add src/lib/seed/config-loader.ts tests/unit/seed/config-loader.test.ts
559
- git commit -m "feat(seed): implement config loader with YAML/JSON parsing and TTL cache"
560
- ```
561
-
562
- ---
563
-
564
- ## Task 4: Credential Resolver (`src/lib/seed/credential-resolver.ts`)
565
-
566
- **Files:**
567
- - Create: `src/lib/seed/credential-resolver.ts`
568
- - Create: `tests/unit/seed/credential-resolver.test.ts`
569
-
570
- - [ ] **Step 1: Write failing tests** (same as before)
571
- - [ ] **Step 2: Run tests to verify they fail**
572
- - [ ] **Step 3: Implement credential-resolver.ts** (same as before)
573
- - [ ] **Step 4: Run tests to verify they pass**
574
- - [ ] **Step 5: Commit**
575
-
576
- ```bash
577
- git add src/lib/seed/credential-resolver.ts tests/unit/seed/credential-resolver.test.ts
578
- git commit -m "feat(seed): implement credential resolver with env var injection"
579
- ```
580
-
581
- ---
582
-
583
- ## Task 5: Connection Filter (`src/lib/seed/connection-filter.ts`)
584
-
585
- **Files:**
586
- - Create: `src/lib/seed/connection-filter.ts`
587
- - Create: `tests/unit/seed/connection-filter.test.ts`
588
-
589
- - [ ] **Step 1: Write failing tests** (same as before)
590
- - [ ] **Step 2: Run tests to verify they fail**
591
- - [ ] **Step 3: Implement connection-filter.ts** (same as before)
592
- - [ ] **Step 4: Run tests to verify they pass**
593
- - [ ] **Step 5: Commit**
594
-
595
- ```bash
596
- git add src/lib/seed/connection-filter.ts tests/unit/seed/connection-filter.test.ts
597
- git commit -m "feat(seed): implement connection filter with role matching and defaults merge"
598
- ```
599
-
600
- ---
601
-
602
- ## Task 6: Barrel Export + Orchestrator (`src/lib/seed/index.ts`) + Tests
603
-
604
- **Files:**
605
- - Create: `src/lib/seed/index.ts`
606
- - Create: `tests/unit/seed/index.test.ts`
607
-
608
- - [ ] **Step 1: Write failing tests**
609
-
610
- Create `tests/unit/seed/index.test.ts`:
611
-
612
- ```typescript
613
- import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
614
- import path from 'path';
615
- import {
616
- getManagedConnections,
617
- getSeedConnectionById,
618
- getSeedConnectionByIdUnfiltered,
619
- resetCache,
620
- } from '@/lib/seed';
621
- import { resetPlaintextWarnings } from '@/lib/seed/credential-resolver';
622
-
623
- const FIXTURES = path.resolve(__dirname, '../../../fixtures/seed-connections');
624
-
625
- describe('seed/index orchestrator', () => {
626
- beforeEach(() => {
627
- resetCache();
628
- resetPlaintextWarnings();
629
- process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'multi-role-config.yaml');
630
- process.env.ADMIN_PG_PASS = 'admin-secret';
631
- process.env.USER_MYSQL_PASS = 'user-secret';
632
- process.env.SHARED_PG_PASS = 'shared-secret';
633
- process.env.BOTH_PG_PASS = 'both-secret';
634
- });
635
-
636
- afterEach(() => {
637
- delete process.env.SEED_CONFIG_PATH;
638
- delete process.env.ADMIN_PG_PASS;
639
- delete process.env.USER_MYSQL_PASS;
640
- delete process.env.SHARED_PG_PASS;
641
- delete process.env.BOTH_PG_PASS;
642
- });
643
-
644
- it('getManagedConnections returns role-filtered connections', async () => {
645
- const adminConns = await getManagedConnections(['admin']);
646
- expect(adminConns.length).toBeGreaterThanOrEqual(3); // admin-only, everyone, admin-and-user
647
-
648
- const userConns = await getManagedConnections(['user']);
649
- const userIds = userConns.map((c) => c.seedId);
650
- expect(userIds).toContain('everyone');
651
- expect(userIds).toContain('user-only');
652
- expect(userIds).not.toContain('admin-only');
653
- });
654
-
655
- it('getSeedConnectionById returns connection with role check', async () => {
656
- const conn = await getSeedConnectionById('everyone', ['user']);
657
- expect(conn).not.toBeNull();
658
- expect(conn!.seedId).toBe('everyone');
659
- expect(conn!.password).toBe('shared-secret');
660
- });
661
-
662
- it('getSeedConnectionById returns null when role mismatches', async () => {
663
- const conn = await getSeedConnectionById('admin-only', ['user']);
664
- expect(conn).toBeNull();
665
- });
666
-
667
- it('getSeedConnectionByIdUnfiltered returns connection regardless of role', async () => {
668
- const conn = await getSeedConnectionByIdUnfiltered('admin-only');
669
- expect(conn).not.toBeNull();
670
- expect(conn!.seedId).toBe('admin-only');
671
- });
672
-
673
- it('getSeedConnectionByIdUnfiltered returns null for nonexistent ID', async () => {
674
- const conn = await getSeedConnectionByIdUnfiltered('nonexistent');
675
- expect(conn).toBeNull();
676
- });
677
-
678
- it('returns empty array when config file missing', async () => {
679
- process.env.SEED_CONFIG_PATH = '/nonexistent.yaml';
680
- resetCache();
681
- const conns = await getManagedConnections(['admin']);
682
- expect(conns).toHaveLength(0);
683
- });
684
- });
685
- ```
686
-
687
- - [ ] **Step 2: Run tests to verify they fail**
688
-
689
- ```bash
690
- bun test tests/unit/seed/index.test.ts
691
- ```
692
-
693
- - [ ] **Step 3: Implement index.ts**
694
-
695
- Create `src/lib/seed/index.ts`:
696
-
697
- ```typescript
698
- import { loadConfig, resetCache } from './config-loader';
699
- import { resolveAllCredentials } from './credential-resolver';
700
- import { filterByRoles, mergeDefaults } from './connection-filter';
701
- import type { ManagedConnection } from './types';
702
-
703
- export type { ManagedConnection, SeedConfig, SeedConnection, SeedDefaults } from './types';
704
- export { SeedConfigSchema, SeedConnectionSchema, SeedDefaultsSchema } from './types';
705
- export { resetCache } from './config-loader';
706
- export { resetPlaintextWarnings } from './credential-resolver';
707
-
708
- async function loadAndResolve(): Promise<ManagedConnection[]> {
709
- const config = await loadConfig();
710
- if (!config) return [];
711
-
712
- const withDefaults = config.connections.map((conn) =>
713
- mergeDefaults(conn, config.defaults),
714
- );
715
-
716
- const resolved = resolveAllCredentials(withDefaults);
717
- // Return all resolved connections (unfiltered) for internal use
718
- return filterByRoles(resolved, ['*', 'admin', 'user']);
719
- }
720
-
721
- export async function getManagedConnections(roles: string[]): Promise<ManagedConnection[]> {
722
- const config = await loadConfig();
723
- if (!config) return [];
724
-
725
- const withDefaults = config.connections.map((conn) =>
726
- mergeDefaults(conn, config.defaults),
727
- );
728
-
729
- const resolved = resolveAllCredentials(withDefaults);
730
- return filterByRoles(resolved, roles);
731
- }
732
-
733
- export async function getSeedConnectionById(
734
- seedId: string,
735
- roles: string[],
736
- ): Promise<ManagedConnection | null> {
737
- const all = await getManagedConnections(roles);
738
- return all.find((c) => c.seedId === seedId) ?? null;
739
- }
740
-
741
- /**
742
- * Get seed connection by ID WITHOUT role filtering.
743
- * Used only for 403-vs-404 differentiation in resolveConnection().
744
- */
745
- export async function getSeedConnectionByIdUnfiltered(
746
- seedId: string,
747
- ): Promise<ManagedConnection | null> {
748
- const all = await loadAndResolve();
749
- return all.find((c) => c.seedId === seedId) ?? null;
750
- }
751
- ```
752
-
753
- - [ ] **Step 4: Run tests to verify they pass**
754
-
755
- ```bash
756
- bun test tests/unit/seed/index.test.ts
757
- ```
758
-
759
- - [ ] **Step 5: Run all seed unit tests**
760
-
761
- ```bash
762
- bun test tests/unit/seed/
763
- ```
764
-
765
- Expected: All PASS
766
-
767
- - [ ] **Step 6: Commit**
768
-
769
- ```bash
770
- git add src/lib/seed/index.ts tests/unit/seed/index.test.ts
771
- git commit -m "feat(seed): add barrel export with orchestrator and unfiltered lookup"
772
- ```
773
-
774
- ---
775
-
776
- ## Task 7: Resolve Connection Utility (`src/lib/seed/resolve-connection.ts`)
777
-
778
- **Files:**
779
- - Modify: `src/lib/audit.ts` (add `'managed_connection'` event type)
780
- - Create: `src/lib/seed/resolve-connection.ts`
781
- - Create: `tests/unit/seed/resolve-connection.test.ts`
782
-
783
- - [ ] **Step 1: Add managed_connection to AuditEventType**
784
-
785
- In `src/lib/audit.ts`, add to the `AuditEventType` union:
786
-
787
- ```typescript
788
- export type AuditEventType =
789
- | 'maintenance'
790
- | 'kill_session'
791
- | 'masking_config'
792
- | 'threshold_config'
793
- | 'connection_test'
794
- | 'query_execution'
795
- | 'managed_connection'; // NEW
796
- ```
797
-
798
- - [ ] **Step 2: Write failing tests**
799
-
800
- Create `tests/unit/seed/resolve-connection.test.ts`:
801
-
802
- ```typescript
803
- import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
804
- import path from 'path';
805
- import type { DatabaseConnection } from '@/lib/types';
806
-
807
- const FIXTURES = path.resolve(__dirname, '../../../fixtures/seed-connections');
808
- process.env.SEED_CONFIG_PATH = path.join(FIXTURES, 'multi-role-config.yaml');
809
- process.env.ADMIN_PG_PASS = 'admin-secret';
810
- process.env.USER_MYSQL_PASS = 'user-secret';
811
- process.env.SHARED_PG_PASS = 'shared-secret';
812
- process.env.BOTH_PG_PASS = 'both-secret';
813
-
814
- import { resolveConnection, SeedConnectionError } from '@/lib/seed/resolve-connection';
815
- import { resetCache } from '@/lib/seed/config-loader';
816
-
817
- describe('resolve-connection', () => {
818
- beforeEach(() => {
819
- resetCache();
820
- });
821
-
822
- it('returns connection object as-is when no connectionId', async () => {
823
- const conn: DatabaseConnection = {
824
- id: 'user-conn', name: 'User DB', type: 'postgres', host: 'localhost', createdAt: new Date(),
825
- };
826
- const result = await resolveConnection({ connection: conn }, { role: 'user', username: 'test' });
827
- expect(result.id).toBe('user-conn');
828
- });
829
-
830
- it('resolves seed connection by connectionId', async () => {
831
- const result = await resolveConnection(
832
- { connectionId: 'seed:everyone' },
833
- { role: 'user', username: 'test' },
834
- );
835
- expect(result.id).toBe('seed:everyone');
836
- expect(result.password).toBe('shared-secret');
837
- });
838
-
839
- it('throws 403 when role does not have access', async () => {
840
- try {
841
- await resolveConnection({ connectionId: 'seed:admin-only' }, { role: 'user', username: 'test' });
842
- expect(true).toBe(false); // should not reach
843
- } catch (err) {
844
- expect(err).toBeInstanceOf(SeedConnectionError);
845
- expect((err as SeedConnectionError).statusCode).toBe(403);
846
- }
847
- });
848
-
849
- it('throws 404 when seed connection does not exist', async () => {
850
- try {
851
- await resolveConnection({ connectionId: 'seed:nonexistent' }, { role: 'admin', username: 'test' });
852
- expect(true).toBe(false);
853
- } catch (err) {
854
- expect(err).toBeInstanceOf(SeedConnectionError);
855
- expect((err as SeedConnectionError).statusCode).toBe(404);
856
- }
857
- });
858
-
859
- it('admin can access admin-only connections', async () => {
860
- const result = await resolveConnection(
861
- { connectionId: 'seed:admin-only' },
862
- { role: 'admin', username: 'test' },
863
- );
864
- expect(result.password).toBe('admin-secret');
865
- });
866
-
867
- it('throws 400 when neither connection nor connectionId', async () => {
868
- try {
869
- await resolveConnection({}, { role: 'admin', username: 'test' });
870
- expect(true).toBe(false);
871
- } catch (err) {
872
- expect(err).toBeInstanceOf(SeedConnectionError);
873
- expect((err as SeedConnectionError).statusCode).toBe(400);
874
- }
875
- });
876
- });
877
- ```
878
-
879
- - [ ] **Step 3: Run tests to verify they fail**
880
- - [ ] **Step 4: Implement resolve-connection.ts**
881
-
882
- Create `src/lib/seed/resolve-connection.ts`:
883
-
884
- ```typescript
885
- import type { DatabaseConnection } from '@/lib/types';
886
- import { getSeedConnectionById, getSeedConnectionByIdUnfiltered } from './index';
887
- import { logger } from '@/lib/logger';
888
-
889
- export class SeedConnectionError extends Error {
890
- constructor(message: string, public statusCode: number) {
891
- super(message);
892
- this.name = 'SeedConnectionError';
893
- }
894
- }
895
-
896
- export async function resolveConnection(
897
- body: { connection?: DatabaseConnection; connectionId?: string },
898
- session: { role: string; username: string },
899
- ): Promise<DatabaseConnection> {
900
- const { connection, connectionId } = body;
901
-
902
- if (connection && !connectionId) {
903
- return connection;
904
- }
905
-
906
- if (connectionId) {
907
- if (!connectionId.startsWith('seed:')) {
908
- throw new SeedConnectionError('Invalid connection ID format', 400);
909
- }
910
-
911
- const seedId = connectionId.slice(5);
912
- const seedConn = await getSeedConnectionById(seedId, [session.role]);
913
-
914
- if (!seedConn) {
915
- // Differentiate 403 vs 404 using unfiltered lookup
916
- const exists = await getSeedConnectionByIdUnfiltered(seedId);
917
- if (exists) {
918
- logger.warn('Seed connection access denied', {
919
- route: 'seed/resolve-connection',
920
- connectionId: seedId,
921
- user: session.username,
922
- role: session.role,
923
- });
924
- throw new SeedConnectionError(
925
- `Access denied: connection "${seedId}" not available for role "${session.role}"`,
926
- 403,
927
- );
928
- }
929
- throw new SeedConnectionError(`Seed connection "${seedId}" not found`, 404);
930
- }
931
-
932
- logger.debug('Resolved seed connection', {
933
- route: 'seed/resolve-connection',
934
- connectionId: seedId,
935
- user: session.username,
936
- });
937
-
938
- return seedConn;
939
- }
940
-
941
- throw new SeedConnectionError('Either connection or connectionId is required', 400);
942
- }
943
- ```
944
-
945
- - [ ] **Step 5: Run tests to verify they pass**
946
- - [ ] **Step 6: Commit**
947
-
948
- ```bash
949
- git add src/lib/audit.ts src/lib/seed/resolve-connection.ts tests/unit/seed/resolve-connection.test.ts
950
- git commit -m "feat(seed): implement resolveConnection with 403/404 differentiation and audit"
951
- ```
952
-
953
- ---
954
-
955
- ## Task 8: API Endpoint (`GET /api/connections/managed`)
956
-
957
- **Files:**
958
- - Create: `src/app/api/connections/managed/route.ts`
959
- - Create: `tests/api/seed/managed-route.test.ts`
960
-
961
- - [ ] **Step 1: Write failing tests** (same as before, with auth mock)
962
- - [ ] **Step 2: Run tests to verify they fail**
963
- - [ ] **Step 3: Implement the API route**
964
-
965
- Create `src/app/api/connections/managed/route.ts`:
966
-
967
- ```typescript
968
- import { NextResponse } from 'next/server';
969
- import { getSession } from '@/lib/auth';
970
- import { getManagedConnections } from '@/lib/seed';
971
- import { logger } from '@/lib/logger';
972
-
973
- export const dynamic = 'force-dynamic';
974
-
975
- export async function GET() {
976
- try {
977
- const session = await getSession();
978
- if (!session) {
979
- return NextResponse.json({ error: 'Authentication required' }, { status: 401 });
980
- }
981
-
982
- const connections = await getManagedConnections([session.role]);
983
-
984
- const sanitized = connections.map((conn) => {
985
- if (conn.managed) {
986
- const { password, connectionString, ...rest } = conn;
987
- return rest;
988
- }
989
- return conn;
990
- });
991
-
992
- const cacheTTL = Number(process.env.SEED_CACHE_TTL_MS) || 60_000;
993
-
994
- return NextResponse.json({ connections: sanitized, cacheHint: cacheTTL });
995
- } catch (error) {
996
- logger.error('Failed to load managed connections', {
997
- route: 'GET /api/connections/managed',
998
- error: (error as Error).message,
999
- });
1000
- return NextResponse.json({ error: 'Failed to load managed connections' }, { status: 500 });
1001
- }
1002
- }
1003
- ```
1004
-
1005
- - [ ] **Step 4: Run tests to verify they pass**
1006
- - [ ] **Step 5: Commit**
1007
-
1008
- ```bash
1009
- git add src/app/api/connections/managed/route.ts tests/api/seed/managed-route.test.ts
1010
- git commit -m "feat(seed): add GET /api/connections/managed endpoint"
1011
- ```
1012
-
1013
- ---
1014
-
1015
- ## Task 9: Integrate `resolveConnection` into all DB API routes
1016
-
1017
- **Files:**
1018
- - Modify: 13 routes in `src/app/api/db/` (all POST, **excluding** `disconnect/route.ts`)
1019
-
1020
- **Note:** `disconnect/route.ts` is excluded — it already accepts `connectionId` as a cache key. The `seed:X` IDs flow naturally through the provider cache.
1021
-
1022
- - [ ] **Step 1: Read each route to identify body extraction pattern**
1023
-
1024
- All affected routes use one of:
1025
- - Pattern A: `const { connection, ... } = await request.json()`
1026
- - Pattern B: `const connection = JSON.parse(await request.text())` (schema route only)
1027
-
1028
- - [ ] **Step 2: Modify each route with resolveConnection**
1029
-
1030
- For each route, add at the top:
1031
-
1032
- ```typescript
1033
- import { resolveConnection, SeedConnectionError } from '@/lib/seed/resolve-connection';
1034
- import { getSession } from '@/lib/auth';
1035
- ```
1036
-
1037
- Change body extraction:
1038
-
1039
- ```typescript
1040
- const body = await request.json();
1041
- const session = await getSession();
1042
- if (!session) {
1043
- return NextResponse.json({ error: 'Authentication required' }, { status: 401 });
1044
- }
1045
- const connection = await resolveConnection(body, session);
1046
- ```
1047
-
1048
- Add to catch block:
1049
-
1050
- ```typescript
1051
- if (error instanceof SeedConnectionError) {
1052
- return NextResponse.json({ error: error.message }, { status: error.statusCode });
1053
- }
1054
- ```
1055
-
1056
- **Special case — `schema/route.ts`:** Currently uses `req.text()` + `JSON.parse()`. Change to `req.json()` for consistency. Client will send `{ connection: conn }` or `{ connectionId: "seed:X" }`.
1057
-
1058
- **Special case — `maintenance/route.ts`:** Already has session check. Reuse existing session.
1059
-
1060
- Apply to all 13 routes:
1061
- 1. `query/route.ts`
1062
- 2. `multi-query/route.ts`
1063
- 3. `schema/route.ts`
1064
- 4. `transaction/route.ts`
1065
- 5. `cancel/route.ts`
1066
- 6. `maintenance/route.ts`
1067
- 7. `monitoring/route.ts`
1068
- 8. `pool-stats/route.ts` (POST)
1069
- 9. `profile/route.ts`
1070
- 10. `provider-meta/route.ts` (POST)
1071
- 11. `test-connection/route.ts`
1072
- 12. `schema-snapshot/route.ts`
1073
- 13. `health/route.ts` (POST connection health check — needs auth added)
1074
-
1075
- - [ ] **Step 3: Run all existing tests**
1076
-
1077
- ```bash
1078
- bun run test
1079
- ```
1080
-
1081
- Expected: All PASS
1082
-
1083
- - [ ] **Step 4: Commit**
1084
-
1085
- ```bash
1086
- git add src/app/api/db/
1087
- git commit -m "feat(seed): integrate resolveConnection into all DB API routes"
1088
- ```
1089
-
1090
- ---
1091
-
1092
- ## Task 10: Shared client helper + useConnectionManager merge
1093
-
1094
- **Files:**
1095
- - Create: `src/hooks/use-connection-payload.ts`
1096
- - Modify: `src/hooks/use-connection-manager.ts`
1097
-
1098
- - [ ] **Step 1: Create shared helper**
1099
-
1100
- Create `src/hooks/use-connection-payload.ts`:
1101
-
1102
- ```typescript
1103
- import type { DatabaseConnection } from '@/lib/types';
1104
-
1105
- /**
1106
- * Builds the connection portion of an API request body.
1107
- * For managed connections: sends { connectionId: "seed:X" } (no credentials).
1108
- * For user connections: sends { connection: conn } (full object).
1109
- */
1110
- export function buildConnectionPayload(
1111
- conn: DatabaseConnection,
1112
- ): { connectionId: string } | { connection: DatabaseConnection } {
1113
- if (conn.managed && conn.seedId) {
1114
- return { connectionId: `seed:${conn.seedId}` };
1115
- }
1116
- return { connection: conn };
1117
- }
1118
- ```
1119
-
1120
- - [ ] **Step 2: Update useConnectionManager — add managed connection fetch + merge**
1121
-
1122
- In `src/hooks/use-connection-manager.ts`, after the demo connection fetch block and before the `return` statement of the initialization effect:
1123
-
1124
- ```typescript
1125
- // Fetch managed (seed) connections
1126
- try {
1127
- const managedRes = await fetch('/api/connections/managed');
1128
- if (managedRes.ok) {
1129
- const { connections: managedConns } = await managedRes.json();
1130
- if (managedConns?.length > 0) {
1131
- // ... merge logic as described in spec Section 4
1132
- }
1133
- }
1134
- } catch {
1135
- // Managed connections are optional
1136
- }
1137
- ```
1138
-
1139
- - [ ] **Step 3: Update fetchSchema to use buildConnectionPayload**
1140
-
1141
- In `use-connection-manager.ts`, `fetchSchema` callback (line 27-30):
1142
-
1143
- ```typescript
1144
- // Before:
1145
- body: JSON.stringify(conn),
1146
-
1147
- // After:
1148
- import { buildConnectionPayload } from './use-connection-payload';
1149
- body: JSON.stringify(buildConnectionPayload(conn)),
1150
- ```
1151
-
1152
- **Important:** The schema route was updated in Task 9 to use `req.json()` + `resolveConnection()`. The client must now send `{ connection: conn }` (wrapped) or `{ connectionId: "seed:X" }`, NOT the bare `conn` object. `buildConnectionPayload()` handles both cases correctly.
1153
-
1154
- - [ ] **Step 4: Update health pulse fetch** (line ~171):
1155
-
1156
- ```typescript
1157
- body: JSON.stringify(buildConnectionPayload(conn)),
1158
- ```
1159
-
1160
- - [ ] **Step 5: Run tests**
1161
-
1162
- ```bash
1163
- bun run test:hooks
1164
- ```
1165
-
1166
- - [ ] **Step 6: Commit**
1167
-
1168
- ```bash
1169
- git add src/hooks/use-connection-payload.ts src/hooks/use-connection-manager.ts
1170
- git commit -m "feat(seed): add managed connection merge to useConnectionManager"
1171
- ```
1172
-
1173
- ---
1174
-
1175
- ## Task 11: Client hooks — useQueryExecution + useTransactionControl
1176
-
1177
- **Files:**
1178
- - Modify: `src/hooks/use-query-execution.ts`
1179
- - Modify: `src/hooks/use-transaction-control.ts`
1180
-
1181
- - [ ] **Step 1: Update ALL 6 fetch calls in useQueryExecution**
1182
-
1183
- Import helper and update each fetch site:
1184
-
1185
- ```typescript
1186
- import { buildConnectionPayload } from './use-connection-payload';
1187
- ```
1188
-
1189
- **Site 1 — Playground BEGIN** (line 150):
1190
- ```typescript
1191
- body: JSON.stringify({ ...buildConnectionPayload(activeConnection), action: 'begin' }),
1192
- ```
1193
-
1194
- **Site 2 — Main query** (line ~179):
1195
- ```typescript
1196
- body: JSON.stringify({
1197
- ...buildConnectionPayload(activeConnection),
1198
- ...(useTransaction ? { action: 'query', sql, options } : { sql, options, ...(!useMultiQuery && { queryId }) }),
1199
- }),
1200
- ```
1201
-
1202
- **Site 3 — Background EXPLAIN query** (line ~198-202):
1203
- ```typescript
1204
- body: JSON.stringify({
1205
- ...buildConnectionPayload(activeConnection),
1206
- sql: explainSql,
1207
- options: {},
1208
- }),
1209
- ```
1210
-
1211
- **Site 4 — Playground rollback success** (line ~357):
1212
- ```typescript
1213
- body: JSON.stringify({ ...buildConnectionPayload(activeConnection), action: 'rollback' }),
1214
- ```
1215
-
1216
- **Site 5 — Playground rollback error** (line ~382):
1217
- ```typescript
1218
- body: JSON.stringify({ ...buildConnectionPayload(activeConnection), action: 'rollback' }),
1219
- ```
1220
-
1221
- **Site 6 — Cancel query** (line ~433):
1222
- ```typescript
1223
- body: JSON.stringify({
1224
- ...buildConnectionPayload(activeConnection),
1225
- queryId: activeQueryIdRef.current,
1226
- }),
1227
- ```
1228
-
1229
- - [ ] **Step 2: Update useTransactionControl** (line 20-24):
1230
-
1231
- ```typescript
1232
- import { buildConnectionPayload } from './use-connection-payload';
1233
-
1234
- body: JSON.stringify({
1235
- ...buildConnectionPayload(activeConnection),
1236
- action,
1237
- }),
1238
- ```
1239
-
1240
- - [ ] **Step 3: Run tests**
1241
-
1242
- ```bash
1243
- bun run test:hooks
1244
- ```
1245
-
1246
- - [ ] **Step 4: Commit**
1247
-
1248
- ```bash
1249
- git add src/hooks/use-query-execution.ts src/hooks/use-transaction-control.ts
1250
- git commit -m "feat(seed): send connectionId for managed connections in all hook fetch calls"
1251
- ```
1252
-
1253
- ---
1254
-
1255
- ## Task 12: UI — Lock icon + hide edit/delete for managed connections
1256
-
1257
- **Files:**
1258
- - Modify: `src/components/sidebar/ConnectionItem.tsx`
1259
-
1260
- - [ ] **Step 1: Add lock icon and conditional buttons**
1261
-
1262
- Import Lock icon, add managed lock indicator, wrap edit/delete with `!conn.managed` check.
1263
-
1264
- - [ ] **Step 2: Run component tests**
1265
-
1266
- ```bash
1267
- bun run test:components
1268
- ```
1269
-
1270
- - [ ] **Step 3: Commit**
1271
-
1272
- ```bash
1273
- git add src/components/sidebar/ConnectionItem.tsx
1274
- git commit -m "feat(seed): add lock icon and hide edit/delete for managed connections"
1275
- ```
1276
-
1277
- ---
1278
-
1279
- ## Task 13: Integration Tests
1280
-
1281
- **Files:**
1282
- - Create: `tests/integration/seed/seed-pipeline.test.ts`
1283
-
1284
- - [ ] **Step 1: Write integration tests** — full pipeline, partial failure, hot-reload, defaults merge, audit trail
1285
- - [ ] **Step 2: Run integration tests**
1286
-
1287
- ```bash
1288
- bun test tests/integration/seed/
1289
- ```
1290
-
1291
- - [ ] **Step 3: Commit**
1292
-
1293
- ```bash
1294
- git add tests/integration/seed/
1295
- git commit -m "test(seed): add integration tests for full seed pipeline"
1296
- ```
1297
-
1298
- ---
1299
-
1300
- ## Task 14: Helm chart + Docker + env documentation
1301
-
1302
- **Files:**
1303
- - Create: `charts/libredb-studio/templates/seed-configmap.yaml`
1304
- - Modify: `charts/libredb-studio/values.yaml`
1305
- - Modify: `charts/libredb-studio/values.schema.json`
1306
- - Modify: `charts/libredb-studio/templates/deployment.yaml`
1307
- - Modify: `docker-compose.yml`
1308
- - Modify: `.env.example`
1309
-
1310
- - [ ] **Step 1: Create seed-configmap.yaml**
1311
- - [ ] **Step 2: Add seedConnections to values.yaml**
1312
- - [ ] **Step 3: Update values.schema.json**
1313
- - [ ] **Step 4: Update deployment.yaml** (volume mount + env vars)
1314
- - [ ] **Step 5: Update docker-compose.yml** (commented example)
1315
- - [ ] **Step 6: Update .env.example** (new env vars)
1316
- - [ ] **Step 7: Lint Helm chart**
1317
-
1318
- ```bash
1319
- helm lint charts/libredb-studio --strict
1320
- helm template test charts/libredb-studio --set secrets.jwtSecret=test-secret-32-chars-minimum-here --set secrets.adminPassword=test123 --set secrets.userPassword=test123 --set seedConnections.enabled=true
1321
- ```
1322
-
1323
- - [ ] **Step 8: Commit**
1324
-
1325
- ```bash
1326
- git add charts/ docker-compose.yml .env.example
1327
- git commit -m "feat(seed): add Helm chart, Docker, and env documentation for seed connections"
1328
- ```
1329
-
1330
- ---
1331
-
1332
- ## Task 15: CI Verification
1333
-
1334
- - [ ] **Step 1: Lint**
1335
-
1336
- ```bash
1337
- bun run lint
1338
- ```
1339
-
1340
- - [ ] **Step 2: Type check**
1341
-
1342
- ```bash
1343
- bun run typecheck
1344
- ```
1345
-
1346
- - [ ] **Step 3: Run all tests**
1347
-
1348
- ```bash
1349
- bun run test
1350
- ```
1351
-
1352
- - [ ] **Step 4: Build**
1353
-
1354
- ```bash
1355
- bun run build
1356
- ```
1357
-
1358
- - [ ] **Step 5: Fix any failures and commit**
1359
-
1360
- ```bash
1361
- git log --oneline -15 # verify all seed commits
1362
- ```