@useatlas/create 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (952) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -1
  3. package/index.ts +253 -36
  4. package/package.json +4 -4
  5. package/templates/docker/Dockerfile +1 -1
  6. package/templates/docker/Dockerfile.sidecar +1 -1
  7. package/templates/docker/bin/__tests__/duckdb-ingest.test.ts +17 -14
  8. package/templates/docker/bin/__tests__/failure-threshold.test.ts +148 -0
  9. package/templates/docker/bin/__tests__/fatal-error-propagation.test.ts +267 -0
  10. package/templates/docker/bin/__tests__/profiler-heuristics.test.ts +5 -5
  11. package/templates/docker/bin/__tests__/schema-drift.test.ts +39 -0
  12. package/templates/docker/bin/atlas.ts +981 -1819
  13. package/templates/docker/bin/benchmark.ts +14 -16
  14. package/templates/docker/bin/enrich.ts +7 -2
  15. package/templates/docker/brand.css +13 -0
  16. package/templates/docker/data/cybersec-semantic/catalog.yml +222 -0
  17. package/templates/docker/data/cybersec-semantic/entities/alerts.yml +195 -0
  18. package/templates/docker/data/cybersec-semantic/entities/assets.yml +191 -0
  19. package/templates/docker/data/cybersec-semantic/entities/compliance_assessments.yml +170 -0
  20. package/templates/docker/data/cybersec-semantic/entities/incidents.yml +219 -0
  21. package/templates/docker/data/cybersec-semantic/entities/organizations.yml +136 -0
  22. package/templates/docker/data/cybersec-semantic/entities/plans.yml +114 -0
  23. package/templates/docker/data/cybersec-semantic/entities/remediation_actions.yml +212 -0
  24. package/templates/docker/data/cybersec-semantic/entities/scan_results.yml +215 -0
  25. package/templates/docker/data/cybersec-semantic/entities/scans.yml +180 -0
  26. package/templates/docker/data/cybersec-semantic/entities/subscriptions.yml +184 -0
  27. package/templates/docker/data/cybersec-semantic/entities/users.yml +140 -0
  28. package/templates/docker/data/cybersec-semantic/entities/vulnerabilities.yml +154 -0
  29. package/templates/docker/data/cybersec-semantic/glossary.yml +207 -0
  30. package/templates/docker/data/cybersec-semantic/metrics/business.yml +148 -0
  31. package/templates/docker/data/cybersec-semantic/metrics/compliance.yml +138 -0
  32. package/templates/docker/data/cybersec-semantic/metrics/security.yml +181 -0
  33. package/templates/docker/data/cybersec.sql +8 -8
  34. package/templates/docker/data/demo.sql +3 -0
  35. package/templates/docker/data/ecommerce-semantic/catalog.yml +221 -0
  36. package/templates/docker/data/ecommerce-semantic/entities/categories.yml +91 -0
  37. package/templates/docker/data/ecommerce-semantic/entities/customers.yml +133 -0
  38. package/templates/docker/data/ecommerce-semantic/entities/email_campaigns.yml +119 -0
  39. package/templates/docker/data/ecommerce-semantic/entities/inventory_levels.yml +153 -0
  40. package/templates/docker/data/ecommerce-semantic/entities/order_items.yml +159 -0
  41. package/templates/docker/data/ecommerce-semantic/entities/orders.yml +199 -0
  42. package/templates/docker/data/ecommerce-semantic/entities/payments.yml +140 -0
  43. package/templates/docker/data/ecommerce-semantic/entities/product_reviews.yml +155 -0
  44. package/templates/docker/data/ecommerce-semantic/entities/products.yml +178 -0
  45. package/templates/docker/data/ecommerce-semantic/entities/promotions.yml +171 -0
  46. package/templates/docker/data/ecommerce-semantic/entities/returns.yml +144 -0
  47. package/templates/docker/data/ecommerce-semantic/entities/sellers.yml +124 -0
  48. package/templates/docker/data/ecommerce-semantic/entities/shipments.yml +159 -0
  49. package/templates/docker/data/ecommerce-semantic/glossary.yml +193 -0
  50. package/templates/docker/data/ecommerce-semantic/metrics/customers.yml +116 -0
  51. package/templates/docker/data/ecommerce-semantic/metrics/operations.yml +131 -0
  52. package/templates/docker/data/ecommerce-semantic/metrics/revenue.yml +120 -0
  53. package/templates/docker/docs/deploy.md +2 -1
  54. package/templates/docker/ee/src/__mocks__/internal.ts +170 -0
  55. package/templates/docker/ee/src/audit/purge-scheduler.ts +113 -0
  56. package/templates/docker/ee/src/audit/retention.ts +467 -0
  57. package/templates/docker/ee/src/auth/ip-allowlist.ts +367 -0
  58. package/templates/docker/ee/src/auth/roles.ts +562 -0
  59. package/templates/docker/ee/src/auth/scim.ts +343 -0
  60. package/templates/docker/ee/src/auth/sso.ts +538 -0
  61. package/templates/docker/ee/src/backups/engine.ts +355 -0
  62. package/templates/docker/ee/src/backups/index.ts +26 -0
  63. package/templates/docker/ee/src/backups/restore.ts +169 -0
  64. package/templates/docker/ee/src/backups/scheduler.ts +153 -0
  65. package/templates/docker/ee/src/backups/verify.ts +124 -0
  66. package/templates/docker/ee/src/branding/white-label.ts +228 -0
  67. package/templates/docker/ee/src/compliance/masking.ts +477 -0
  68. package/templates/docker/ee/src/compliance/patterns.ts +16 -0
  69. package/templates/docker/ee/src/compliance/pii-detection.ts +217 -0
  70. package/templates/docker/ee/src/compliance/reports.ts +402 -0
  71. package/templates/docker/ee/src/deploy-mode.ts +37 -0
  72. package/templates/docker/ee/src/governance/approval.ts +699 -0
  73. package/templates/docker/ee/src/index.ts +74 -0
  74. package/templates/docker/ee/src/platform/domains.ts +562 -0
  75. package/templates/docker/ee/src/platform/model-routing.ts +382 -0
  76. package/templates/docker/ee/src/platform/residency.ts +265 -0
  77. package/templates/docker/ee/src/sla/alerting.ts +382 -0
  78. package/templates/docker/ee/src/sla/index.ts +12 -0
  79. package/templates/docker/ee/src/sla/metrics.ts +275 -0
  80. package/templates/docker/ee/src/test-setup.ts +1 -0
  81. package/templates/docker/next.config.ts +4 -1
  82. package/templates/docker/package.json +49 -29
  83. package/templates/docker/sidecar/Dockerfile +1 -1
  84. package/templates/docker/src/api/index.ts +336 -24
  85. package/templates/docker/src/api/routes/actions.ts +443 -176
  86. package/templates/docker/src/api/routes/admin-abuse.ts +219 -0
  87. package/templates/docker/src/api/routes/admin-approval.ts +418 -0
  88. package/templates/docker/src/api/routes/admin-audit-retention.ts +405 -0
  89. package/templates/docker/src/api/routes/admin-auth.ts +122 -0
  90. package/templates/docker/src/api/routes/admin-branding.ts +252 -0
  91. package/templates/docker/src/api/routes/admin-compliance.ts +352 -0
  92. package/templates/docker/src/api/routes/admin-domains.ts +334 -0
  93. package/templates/docker/src/api/routes/admin-integrations.ts +2667 -0
  94. package/templates/docker/src/api/routes/admin-ip-allowlist.ts +261 -0
  95. package/templates/docker/src/api/routes/admin-learned-patterns.ts +525 -0
  96. package/templates/docker/src/api/routes/admin-model-config.ts +252 -0
  97. package/templates/docker/src/api/routes/admin-onboarding-emails.ts +145 -0
  98. package/templates/docker/src/api/routes/admin-orgs.ts +710 -0
  99. package/templates/docker/src/api/routes/admin-prompts.ts +694 -0
  100. package/templates/docker/src/api/routes/admin-residency.ts +570 -0
  101. package/templates/docker/src/api/routes/admin-roles.ts +296 -0
  102. package/templates/docker/src/api/routes/admin-router.ts +120 -0
  103. package/templates/docker/src/api/routes/admin-sandbox.ts +417 -0
  104. package/templates/docker/src/api/routes/admin-scim.ts +262 -0
  105. package/templates/docker/src/api/routes/admin-sso.ts +545 -0
  106. package/templates/docker/src/api/routes/admin-suggestions.ts +176 -0
  107. package/templates/docker/src/api/routes/admin-usage.ts +310 -0
  108. package/templates/docker/src/api/routes/admin.ts +4156 -898
  109. package/templates/docker/src/api/routes/auth-preamble.ts +105 -0
  110. package/templates/docker/src/api/routes/billing.ts +397 -0
  111. package/templates/docker/src/api/routes/chat.ts +597 -334
  112. package/templates/docker/src/api/routes/conversations.ts +987 -132
  113. package/templates/docker/src/api/routes/demo.ts +673 -0
  114. package/templates/docker/src/api/routes/discord.ts +274 -0
  115. package/templates/docker/src/api/routes/ee-error-handler.ts +32 -0
  116. package/templates/docker/src/api/routes/health.ts +129 -14
  117. package/templates/docker/src/api/routes/middleware.ts +244 -0
  118. package/templates/docker/src/api/routes/onboarding-emails.ts +134 -0
  119. package/templates/docker/src/api/routes/onboarding.ts +1109 -0
  120. package/templates/docker/src/api/routes/openapi.ts +184 -1597
  121. package/templates/docker/src/api/routes/platform-admin.ts +760 -0
  122. package/templates/docker/src/api/routes/platform-backups.ts +436 -0
  123. package/templates/docker/src/api/routes/platform-domains.ts +235 -0
  124. package/templates/docker/src/api/routes/platform-residency.ts +257 -0
  125. package/templates/docker/src/api/routes/platform-sla.ts +379 -0
  126. package/templates/docker/src/api/routes/prompts.ts +221 -0
  127. package/templates/docker/src/api/routes/public-branding.ts +106 -0
  128. package/templates/docker/src/api/routes/query.ts +330 -219
  129. package/templates/docker/src/api/routes/scheduled-tasks.ts +393 -297
  130. package/templates/docker/src/api/routes/semantic.ts +179 -0
  131. package/templates/docker/src/api/routes/sessions.ts +210 -0
  132. package/templates/docker/src/api/routes/shared-domains.ts +98 -0
  133. package/templates/docker/src/api/routes/shared-schemas.ts +139 -0
  134. package/templates/docker/src/api/routes/slack.ts +209 -52
  135. package/templates/docker/src/api/routes/suggestions.ts +233 -0
  136. package/templates/docker/src/api/routes/tables.ts +67 -0
  137. package/templates/docker/src/api/routes/teams.ts +222 -0
  138. package/templates/docker/src/api/routes/validate-sql.ts +188 -0
  139. package/templates/docker/src/api/routes/validation-hook.ts +62 -0
  140. package/templates/docker/src/api/routes/widget-loader.ts +356 -0
  141. package/templates/docker/src/api/routes/widget.ts +428 -0
  142. package/templates/docker/src/api/routes/wizard.ts +852 -0
  143. package/templates/docker/src/api/server.ts +187 -69
  144. package/templates/docker/src/app/error.tsx +5 -2
  145. package/templates/docker/src/app/globals.css +1 -1
  146. package/templates/docker/src/app/layout.tsx +7 -2
  147. package/templates/docker/src/app/page.tsx +39 -5
  148. package/templates/docker/src/components/data-table/data-table-column-header.tsx +99 -0
  149. package/templates/docker/src/components/data-table/data-table-date-filter.tsx +225 -0
  150. package/templates/docker/src/components/data-table/data-table-expandable.tsx +125 -0
  151. package/templates/docker/src/components/data-table/data-table-faceted-filter.tsx +189 -0
  152. package/templates/docker/src/components/data-table/data-table-pagination.tsx +112 -0
  153. package/templates/docker/src/components/data-table/data-table-range-filter.tsx +122 -0
  154. package/templates/docker/src/components/data-table/data-table-slider-filter.tsx +256 -0
  155. package/templates/docker/src/components/data-table/data-table-sort-list.tsx +407 -0
  156. package/templates/docker/src/components/data-table/data-table-toolbar.tsx +149 -0
  157. package/templates/docker/src/components/data-table/data-table-view-options.tsx +89 -0
  158. package/templates/docker/src/components/data-table/data-table.tsx +105 -0
  159. package/templates/docker/src/components/form-dialog.tsx +135 -0
  160. package/templates/docker/src/components/ui/accordion.tsx +66 -0
  161. package/templates/docker/src/components/ui/calendar.tsx +220 -0
  162. package/templates/docker/src/components/ui/checkbox.tsx +32 -0
  163. package/templates/docker/src/components/ui/faceted.tsx +283 -0
  164. package/templates/docker/src/components/ui/form.tsx +167 -0
  165. package/templates/docker/src/components/ui/label.tsx +24 -0
  166. package/templates/docker/src/components/ui/popover.tsx +89 -0
  167. package/templates/docker/src/components/ui/progress.tsx +31 -0
  168. package/templates/docker/src/components/ui/scroll-area.tsx +6 -2
  169. package/templates/docker/src/components/ui/slider.tsx +63 -0
  170. package/templates/docker/src/components/ui/sortable.tsx +581 -0
  171. package/templates/docker/src/components/ui/switch.tsx +35 -0
  172. package/templates/docker/src/components/ui/textarea.tsx +18 -0
  173. package/templates/docker/src/config/data-table.ts +82 -0
  174. package/templates/docker/src/env-check.ts +74 -0
  175. package/templates/docker/src/hooks/use-callback-ref.ts +27 -0
  176. package/templates/docker/src/hooks/use-data-table.ts +316 -0
  177. package/templates/docker/src/hooks/use-debounced-callback.ts +28 -0
  178. package/templates/docker/src/lib/action-types.ts +7 -41
  179. package/templates/docker/src/lib/agent-query.ts +4 -2
  180. package/templates/docker/src/lib/agent.ts +363 -31
  181. package/templates/docker/src/lib/auth/admin-permissions.ts +38 -0
  182. package/templates/docker/src/lib/auth/audit.ts +19 -4
  183. package/templates/docker/src/lib/auth/byot.ts +3 -3
  184. package/templates/docker/src/lib/auth/client.ts +33 -3
  185. package/templates/docker/src/lib/auth/detect.ts +29 -8
  186. package/templates/docker/src/lib/auth/managed.ts +104 -14
  187. package/templates/docker/src/lib/auth/middleware.ts +53 -6
  188. package/templates/docker/src/lib/auth/migrate.ts +140 -15
  189. package/templates/docker/src/lib/auth/oauth-state.ts +123 -0
  190. package/templates/docker/src/lib/auth/org-permissions.ts +55 -0
  191. package/templates/docker/src/lib/auth/permissions.ts +26 -19
  192. package/templates/docker/src/lib/auth/server.ts +355 -9
  193. package/templates/docker/src/lib/auth/simple-key.ts +3 -3
  194. package/templates/docker/src/lib/auth/types.ts +15 -21
  195. package/templates/docker/src/lib/billing/enforcement.ts +368 -0
  196. package/templates/docker/src/lib/billing/plans.ts +155 -0
  197. package/templates/docker/src/lib/cache/index.ts +92 -0
  198. package/templates/docker/src/lib/cache/keys.ts +30 -0
  199. package/templates/docker/src/lib/cache/lru.ts +79 -0
  200. package/templates/docker/src/lib/cache/types.ts +31 -0
  201. package/templates/docker/src/lib/compose-refs.ts +62 -0
  202. package/templates/docker/src/lib/config.ts +563 -11
  203. package/templates/docker/src/lib/connection-types.ts +9 -0
  204. package/templates/docker/src/lib/conversation-types.ts +1 -25
  205. package/templates/docker/src/lib/conversations.ts +345 -14
  206. package/templates/docker/src/lib/data-table.ts +61 -0
  207. package/templates/docker/src/lib/db/connection.ts +793 -39
  208. package/templates/docker/src/lib/db/internal.ts +985 -139
  209. package/templates/docker/src/lib/db/migrate.ts +295 -0
  210. package/templates/docker/src/lib/db/migrations/0000_baseline.sql +703 -0
  211. package/templates/docker/src/lib/db/migrations/0001_teams_installations.sql +14 -0
  212. package/templates/docker/src/lib/db/migrations/0002_discord_installations.sql +14 -0
  213. package/templates/docker/src/lib/db/migrations/0003_telegram_installations.sql +15 -0
  214. package/templates/docker/src/lib/db/migrations/0004_sandbox_credentials.sql +18 -0
  215. package/templates/docker/src/lib/db/migrations/0005_oauth_state.sql +16 -0
  216. package/templates/docker/src/lib/db/migrations/0006_byot_credentials.sql +14 -0
  217. package/templates/docker/src/lib/db/migrations/0007_gchat_installations.sql +15 -0
  218. package/templates/docker/src/lib/db/migrations/0008_github_installations.sql +14 -0
  219. package/templates/docker/src/lib/db/migrations/0009_linear_installations.sql +15 -0
  220. package/templates/docker/src/lib/db/migrations/0010_whatsapp_installations.sql +14 -0
  221. package/templates/docker/src/lib/db/migrations/0011_email_installations.sql +16 -0
  222. package/templates/docker/src/lib/db/migrations/0012_region_migrations.sql +25 -0
  223. package/templates/docker/src/lib/db/schema.ts +1120 -0
  224. package/templates/docker/src/lib/db/source-rate-limit.ts +89 -139
  225. package/templates/docker/src/lib/demo.ts +308 -0
  226. package/templates/docker/src/lib/discord/store.ts +225 -0
  227. package/templates/docker/src/lib/effect/ai.ts +243 -0
  228. package/templates/docker/src/lib/effect/errors.ts +234 -0
  229. package/templates/docker/src/lib/effect/hono.ts +454 -0
  230. package/templates/docker/src/lib/effect/index.ts +137 -0
  231. package/templates/docker/src/lib/effect/layers.ts +496 -0
  232. package/templates/docker/src/lib/effect/services.ts +776 -0
  233. package/templates/docker/src/lib/effect/sql.ts +178 -0
  234. package/templates/docker/src/lib/effect/toolkit.ts +123 -0
  235. package/templates/docker/src/lib/email/delivery.ts +232 -0
  236. package/templates/docker/src/lib/email/engine.ts +349 -0
  237. package/templates/docker/src/lib/email/hooks.ts +107 -0
  238. package/templates/docker/src/lib/email/index.ts +16 -0
  239. package/templates/docker/src/lib/email/scheduler.ts +72 -0
  240. package/templates/docker/src/lib/email/sequence.ts +73 -0
  241. package/templates/docker/src/lib/email/store.ts +163 -0
  242. package/templates/docker/src/lib/email/templates.ts +215 -0
  243. package/templates/docker/src/lib/format.ts +67 -0
  244. package/templates/docker/src/lib/gchat/store.ts +202 -0
  245. package/templates/docker/src/lib/github/store.ts +197 -0
  246. package/templates/docker/src/lib/id.ts +29 -0
  247. package/templates/docker/src/lib/integrations/types.ts +166 -0
  248. package/templates/docker/src/lib/learn/pattern-analyzer.ts +224 -0
  249. package/templates/docker/src/lib/learn/pattern-cache.ts +229 -0
  250. package/templates/docker/src/lib/learn/pattern-proposer.ts +87 -0
  251. package/templates/docker/src/lib/learn/suggestion-helpers.ts +34 -0
  252. package/templates/docker/src/lib/learn/suggestions.ts +139 -0
  253. package/templates/docker/src/lib/linear/store.ts +200 -0
  254. package/templates/docker/src/lib/logger.ts +35 -3
  255. package/templates/docker/src/lib/metering.ts +272 -0
  256. package/templates/docker/src/lib/parsers.ts +99 -0
  257. package/templates/docker/src/lib/plugins/hooks.ts +13 -11
  258. package/templates/docker/src/lib/plugins/index.ts +3 -1
  259. package/templates/docker/src/lib/plugins/registry.ts +58 -6
  260. package/templates/docker/src/lib/plugins/settings.ts +147 -0
  261. package/templates/docker/src/lib/plugins/wiring.ts +6 -9
  262. package/templates/docker/src/lib/profiler.ts +1665 -0
  263. package/templates/docker/src/lib/providers.ts +188 -13
  264. package/templates/docker/src/lib/rls.ts +172 -60
  265. package/templates/docker/src/lib/sandbox/credentials.ts +206 -0
  266. package/templates/docker/src/lib/sandbox/validate.ts +179 -0
  267. package/templates/docker/src/lib/scheduled-task-types.ts +26 -94
  268. package/templates/docker/src/lib/scheduled-tasks.ts +174 -34
  269. package/templates/docker/src/lib/scheduler/delivery.ts +248 -150
  270. package/templates/docker/src/lib/scheduler/engine.ts +190 -154
  271. package/templates/docker/src/lib/scheduler/executor.ts +74 -23
  272. package/templates/docker/src/lib/scheduler/preview.ts +72 -0
  273. package/templates/docker/src/lib/security/abuse.ts +463 -0
  274. package/templates/docker/src/lib/semantic/diff.ts +267 -0
  275. package/templates/docker/src/lib/semantic/entities.ts +167 -0
  276. package/templates/docker/src/lib/semantic/files.ts +283 -0
  277. package/templates/docker/src/lib/semantic/index.ts +27 -0
  278. package/templates/docker/src/lib/{semantic-index.ts → semantic/search.ts} +80 -9
  279. package/templates/docker/src/lib/semantic/sync.ts +581 -0
  280. package/templates/docker/src/lib/{semantic.ts → semantic/whitelist.ts} +189 -3
  281. package/templates/docker/src/lib/settings.ts +817 -0
  282. package/templates/docker/src/lib/sidecar-types.ts +13 -0
  283. package/templates/docker/src/lib/slack/store.ts +134 -25
  284. package/templates/docker/src/lib/startup.ts +528 -362
  285. package/templates/docker/src/lib/teams/store.ts +216 -0
  286. package/templates/docker/src/lib/telegram/store.ts +202 -0
  287. package/templates/docker/src/lib/telemetry.ts +40 -0
  288. package/templates/docker/src/lib/tools/actions/audit.ts +8 -5
  289. package/templates/docker/src/lib/tools/actions/email.ts +3 -1
  290. package/templates/docker/src/lib/tools/actions/handler.ts +276 -93
  291. package/templates/docker/src/lib/tools/actions/jira.ts +2 -2
  292. package/templates/docker/src/lib/tools/backends/detect.ts +16 -0
  293. package/templates/docker/src/lib/tools/backends/index.ts +11 -0
  294. package/templates/docker/src/lib/tools/backends/nsjail.ts +213 -0
  295. package/templates/docker/src/lib/tools/backends/shared.ts +103 -0
  296. package/templates/docker/src/lib/tools/backends/types.ts +26 -0
  297. package/templates/docker/src/lib/tools/explore-nsjail.ts +7 -228
  298. package/templates/docker/src/lib/tools/explore-sandbox.ts +4 -29
  299. package/templates/docker/src/lib/tools/explore-sidecar.ts +18 -2
  300. package/templates/docker/src/lib/tools/explore.ts +246 -54
  301. package/templates/docker/src/lib/tools/index.ts +17 -0
  302. package/templates/docker/src/lib/tools/python-nsjail.ts +11 -139
  303. package/templates/docker/src/lib/tools/python-sandbox.ts +9 -132
  304. package/templates/docker/src/lib/tools/python-sidecar.ts +184 -3
  305. package/templates/docker/src/lib/tools/python-stream.ts +33 -0
  306. package/templates/docker/src/lib/tools/python-wrapper.ts +129 -0
  307. package/templates/docker/src/lib/tools/python.ts +115 -15
  308. package/templates/docker/src/lib/tools/registry.ts +14 -2
  309. package/templates/docker/src/lib/tools/sql.ts +778 -362
  310. package/templates/docker/src/lib/tracing.ts +16 -0
  311. package/templates/docker/src/lib/whatsapp/store.ts +198 -0
  312. package/templates/docker/src/lib/workspace.ts +89 -0
  313. package/templates/docker/src/progress.ts +121 -0
  314. package/templates/docker/src/types/data-table.ts +48 -0
  315. package/templates/docker/src/ui/atlas-chat-reexport.ts +3 -0
  316. package/templates/docker/src/ui/components/actions/action-approval-card.tsx +26 -19
  317. package/templates/docker/src/ui/components/actions/action-status-badge.tsx +3 -3
  318. package/templates/docker/src/ui/components/admin/admin-layout.tsx +57 -39
  319. package/templates/docker/src/ui/components/admin/admin-sidebar.tsx +213 -35
  320. package/templates/docker/src/ui/components/admin/delivery-status-badge.tsx +53 -0
  321. package/templates/docker/src/ui/components/admin/empty-state.tsx +27 -6
  322. package/templates/docker/src/ui/components/admin/entity-detail.tsx +3 -52
  323. package/templates/docker/src/ui/components/admin/error-banner.tsx +2 -2
  324. package/templates/docker/src/ui/components/admin/feature-disabled.tsx +28 -5
  325. package/templates/docker/src/ui/components/admin-content-wrapper.tsx +87 -0
  326. package/templates/docker/src/ui/components/atlas-chat.tsx +449 -166
  327. package/templates/docker/src/ui/components/branding-head.tsx +41 -0
  328. package/templates/docker/src/ui/components/chart/chart-detection.ts +62 -5
  329. package/templates/docker/src/ui/components/chart/result-chart.tsx +316 -125
  330. package/templates/docker/src/ui/components/chat/api-key-bar.tsx +4 -4
  331. package/templates/docker/src/ui/components/chat/data-table.tsx +45 -4
  332. package/templates/docker/src/ui/components/chat/error-banner.tsx +86 -5
  333. package/templates/docker/src/ui/components/chat/follow-up-chips.tsx +29 -0
  334. package/templates/docker/src/ui/components/chat/markdown.tsx +24 -0
  335. package/templates/docker/src/ui/components/chat/prompt-library.tsx +206 -0
  336. package/templates/docker/src/ui/components/chat/python-result-card.tsx +106 -78
  337. package/templates/docker/src/ui/components/chat/result-card-base.tsx +101 -0
  338. package/templates/docker/src/ui/components/chat/share-dialog.tsx +377 -0
  339. package/templates/docker/src/ui/components/chat/sql-result-card.tsx +94 -73
  340. package/templates/docker/src/ui/components/chat/suggestion-chips.tsx +46 -0
  341. package/templates/docker/src/ui/components/chat/tool-part.tsx +16 -4
  342. package/templates/docker/src/ui/components/conversations/conversation-item.tsx +48 -17
  343. package/templates/docker/src/ui/components/conversations/conversation-list.tsx +38 -24
  344. package/templates/docker/src/ui/components/conversations/conversation-sidebar.tsx +66 -7
  345. package/templates/docker/src/ui/components/conversations/delete-confirmation.tsx +9 -2
  346. package/templates/docker/src/ui/components/error-boundary.tsx +66 -0
  347. package/templates/docker/src/ui/components/notebook/delete-cell-dialog.tsx +48 -0
  348. package/templates/docker/src/ui/components/notebook/fork-branch-selector.tsx +68 -0
  349. package/templates/docker/src/ui/components/notebook/notebook-cell-input.tsx +76 -0
  350. package/templates/docker/src/ui/components/notebook/notebook-cell-output.tsx +58 -0
  351. package/templates/docker/src/ui/components/notebook/notebook-cell-toolbar.tsx +91 -0
  352. package/templates/docker/src/ui/components/notebook/notebook-cell.tsx +119 -0
  353. package/templates/docker/src/ui/components/notebook/notebook-empty-state.tsx +19 -0
  354. package/templates/docker/src/ui/components/notebook/notebook-export.ts +287 -0
  355. package/templates/docker/src/ui/components/notebook/notebook-input-bar.tsx +49 -0
  356. package/templates/docker/src/ui/components/notebook/notebook-shell.tsx +266 -0
  357. package/templates/docker/src/ui/components/notebook/notebook-text-cell.tsx +152 -0
  358. package/templates/docker/src/ui/components/notebook/types.ts +39 -0
  359. package/templates/docker/src/ui/components/notebook/use-keyboard-nav.ts +109 -0
  360. package/templates/docker/src/ui/components/notebook/use-notebook.ts +684 -0
  361. package/templates/docker/src/ui/components/org-switcher.tsx +111 -0
  362. package/templates/docker/src/ui/components/region-picker.tsx +103 -0
  363. package/templates/docker/src/ui/components/schema-explorer/schema-explorer.tsx +522 -0
  364. package/templates/docker/src/ui/components/social-icons.tsx +26 -0
  365. package/templates/docker/src/ui/components/tour/guided-tour.tsx +81 -0
  366. package/templates/docker/src/ui/components/tour/index.ts +5 -0
  367. package/templates/docker/src/ui/components/tour/nav-bar.tsx +100 -0
  368. package/templates/docker/src/ui/components/tour/tour-overlay.tsx +298 -0
  369. package/templates/docker/src/ui/components/tour/tour-steps.ts +43 -0
  370. package/templates/docker/src/ui/components/tour/types.ts +21 -0
  371. package/templates/docker/src/ui/components/tour/use-tour.ts +193 -0
  372. package/templates/docker/src/ui/context-reexport.ts +3 -0
  373. package/templates/docker/src/ui/hooks/theme-init-script.ts +17 -0
  374. package/templates/docker/src/ui/hooks/use-admin-fetch.ts +38 -30
  375. package/templates/docker/src/ui/hooks/use-admin-mutation.ts +188 -0
  376. package/templates/docker/src/ui/hooks/use-atlas-transport.ts +225 -0
  377. package/templates/docker/src/ui/hooks/use-branding.ts +68 -0
  378. package/templates/docker/src/ui/hooks/use-conversations.ts +106 -83
  379. package/templates/docker/src/ui/hooks/use-dark-mode.ts +134 -10
  380. package/templates/docker/src/ui/hooks/use-deploy-mode.ts +36 -0
  381. package/templates/docker/src/ui/hooks/use-platform-admin-guard.ts +49 -0
  382. package/templates/docker/src/ui/lib/action-types.ts +11 -63
  383. package/templates/docker/src/ui/lib/admin-schemas.ts +744 -0
  384. package/templates/docker/src/ui/lib/fetch-client.ts +84 -0
  385. package/templates/docker/src/ui/lib/fetch-error.ts +54 -0
  386. package/templates/docker/src/ui/lib/helpers.ts +94 -1
  387. package/templates/docker/src/ui/lib/types.ts +149 -140
  388. package/templates/docker/tsconfig.json +4 -2
  389. package/templates/nextjs-standalone/bin/__tests__/duckdb-ingest.test.ts +17 -14
  390. package/templates/nextjs-standalone/bin/__tests__/failure-threshold.test.ts +148 -0
  391. package/templates/nextjs-standalone/bin/__tests__/fatal-error-propagation.test.ts +267 -0
  392. package/templates/nextjs-standalone/bin/__tests__/profiler-heuristics.test.ts +5 -5
  393. package/templates/nextjs-standalone/bin/__tests__/schema-drift.test.ts +39 -0
  394. package/templates/nextjs-standalone/bin/atlas.ts +981 -1819
  395. package/templates/nextjs-standalone/bin/benchmark.ts +14 -16
  396. package/templates/nextjs-standalone/bin/enrich.ts +7 -2
  397. package/templates/nextjs-standalone/brand.css +13 -0
  398. package/templates/nextjs-standalone/data/cybersec-semantic/catalog.yml +222 -0
  399. package/templates/nextjs-standalone/data/cybersec-semantic/entities/alerts.yml +195 -0
  400. package/templates/nextjs-standalone/data/cybersec-semantic/entities/assets.yml +191 -0
  401. package/templates/nextjs-standalone/data/cybersec-semantic/entities/compliance_assessments.yml +170 -0
  402. package/templates/nextjs-standalone/data/cybersec-semantic/entities/incidents.yml +219 -0
  403. package/templates/nextjs-standalone/data/cybersec-semantic/entities/organizations.yml +136 -0
  404. package/templates/nextjs-standalone/data/cybersec-semantic/entities/plans.yml +114 -0
  405. package/templates/nextjs-standalone/data/cybersec-semantic/entities/remediation_actions.yml +212 -0
  406. package/templates/nextjs-standalone/data/cybersec-semantic/entities/scan_results.yml +215 -0
  407. package/templates/nextjs-standalone/data/cybersec-semantic/entities/scans.yml +180 -0
  408. package/templates/nextjs-standalone/data/cybersec-semantic/entities/subscriptions.yml +184 -0
  409. package/templates/nextjs-standalone/data/cybersec-semantic/entities/users.yml +140 -0
  410. package/templates/nextjs-standalone/data/cybersec-semantic/entities/vulnerabilities.yml +154 -0
  411. package/templates/nextjs-standalone/data/cybersec-semantic/glossary.yml +207 -0
  412. package/templates/nextjs-standalone/data/cybersec-semantic/metrics/business.yml +148 -0
  413. package/templates/nextjs-standalone/data/cybersec-semantic/metrics/compliance.yml +138 -0
  414. package/templates/nextjs-standalone/data/cybersec-semantic/metrics/security.yml +181 -0
  415. package/templates/nextjs-standalone/data/cybersec.sql +8 -8
  416. package/templates/nextjs-standalone/data/demo.sql +3 -0
  417. package/templates/nextjs-standalone/data/ecommerce-semantic/catalog.yml +221 -0
  418. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/categories.yml +91 -0
  419. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/customers.yml +133 -0
  420. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/email_campaigns.yml +119 -0
  421. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/inventory_levels.yml +153 -0
  422. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/order_items.yml +159 -0
  423. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/orders.yml +199 -0
  424. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/payments.yml +140 -0
  425. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/product_reviews.yml +155 -0
  426. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/products.yml +178 -0
  427. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/promotions.yml +171 -0
  428. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/returns.yml +144 -0
  429. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/sellers.yml +124 -0
  430. package/templates/nextjs-standalone/data/ecommerce-semantic/entities/shipments.yml +159 -0
  431. package/templates/nextjs-standalone/data/ecommerce-semantic/glossary.yml +193 -0
  432. package/templates/nextjs-standalone/data/ecommerce-semantic/metrics/customers.yml +116 -0
  433. package/templates/nextjs-standalone/data/ecommerce-semantic/metrics/operations.yml +131 -0
  434. package/templates/nextjs-standalone/data/ecommerce-semantic/metrics/revenue.yml +120 -0
  435. package/templates/nextjs-standalone/docs/deploy.md +2 -1
  436. package/templates/nextjs-standalone/ee/src/__mocks__/internal.ts +170 -0
  437. package/templates/nextjs-standalone/ee/src/audit/purge-scheduler.ts +113 -0
  438. package/templates/nextjs-standalone/ee/src/audit/retention.ts +467 -0
  439. package/templates/nextjs-standalone/ee/src/auth/ip-allowlist.ts +367 -0
  440. package/templates/nextjs-standalone/ee/src/auth/roles.ts +562 -0
  441. package/templates/nextjs-standalone/ee/src/auth/scim.ts +343 -0
  442. package/templates/nextjs-standalone/ee/src/auth/sso.ts +538 -0
  443. package/templates/nextjs-standalone/ee/src/backups/engine.ts +355 -0
  444. package/templates/nextjs-standalone/ee/src/backups/index.ts +26 -0
  445. package/templates/nextjs-standalone/ee/src/backups/restore.ts +169 -0
  446. package/templates/nextjs-standalone/ee/src/backups/scheduler.ts +153 -0
  447. package/templates/nextjs-standalone/ee/src/backups/verify.ts +124 -0
  448. package/templates/nextjs-standalone/ee/src/branding/white-label.ts +228 -0
  449. package/templates/nextjs-standalone/ee/src/compliance/masking.ts +477 -0
  450. package/templates/nextjs-standalone/ee/src/compliance/patterns.ts +16 -0
  451. package/templates/nextjs-standalone/ee/src/compliance/pii-detection.ts +217 -0
  452. package/templates/nextjs-standalone/ee/src/compliance/reports.ts +402 -0
  453. package/templates/nextjs-standalone/ee/src/deploy-mode.ts +37 -0
  454. package/templates/nextjs-standalone/ee/src/governance/approval.ts +699 -0
  455. package/templates/nextjs-standalone/ee/src/index.ts +74 -0
  456. package/templates/nextjs-standalone/ee/src/platform/domains.ts +562 -0
  457. package/templates/nextjs-standalone/ee/src/platform/model-routing.ts +382 -0
  458. package/templates/nextjs-standalone/ee/src/platform/residency.ts +265 -0
  459. package/templates/nextjs-standalone/ee/src/sla/alerting.ts +382 -0
  460. package/templates/nextjs-standalone/ee/src/sla/index.ts +12 -0
  461. package/templates/nextjs-standalone/ee/src/sla/metrics.ts +275 -0
  462. package/templates/nextjs-standalone/ee/src/test-setup.ts +1 -0
  463. package/templates/nextjs-standalone/next.config.ts +1 -1
  464. package/templates/nextjs-standalone/package.json +50 -30
  465. package/templates/nextjs-standalone/src/api/index.ts +336 -24
  466. package/templates/nextjs-standalone/src/api/routes/actions.ts +443 -176
  467. package/templates/nextjs-standalone/src/api/routes/admin-abuse.ts +219 -0
  468. package/templates/nextjs-standalone/src/api/routes/admin-approval.ts +418 -0
  469. package/templates/nextjs-standalone/src/api/routes/admin-audit-retention.ts +405 -0
  470. package/templates/nextjs-standalone/src/api/routes/admin-auth.ts +122 -0
  471. package/templates/nextjs-standalone/src/api/routes/admin-branding.ts +252 -0
  472. package/templates/nextjs-standalone/src/api/routes/admin-compliance.ts +352 -0
  473. package/templates/nextjs-standalone/src/api/routes/admin-domains.ts +334 -0
  474. package/templates/nextjs-standalone/src/api/routes/admin-integrations.ts +2667 -0
  475. package/templates/nextjs-standalone/src/api/routes/admin-ip-allowlist.ts +261 -0
  476. package/templates/nextjs-standalone/src/api/routes/admin-learned-patterns.ts +525 -0
  477. package/templates/nextjs-standalone/src/api/routes/admin-model-config.ts +252 -0
  478. package/templates/nextjs-standalone/src/api/routes/admin-onboarding-emails.ts +145 -0
  479. package/templates/nextjs-standalone/src/api/routes/admin-orgs.ts +710 -0
  480. package/templates/nextjs-standalone/src/api/routes/admin-prompts.ts +694 -0
  481. package/templates/nextjs-standalone/src/api/routes/admin-residency.ts +570 -0
  482. package/templates/nextjs-standalone/src/api/routes/admin-roles.ts +296 -0
  483. package/templates/nextjs-standalone/src/api/routes/admin-router.ts +120 -0
  484. package/templates/nextjs-standalone/src/api/routes/admin-sandbox.ts +417 -0
  485. package/templates/nextjs-standalone/src/api/routes/admin-scim.ts +262 -0
  486. package/templates/nextjs-standalone/src/api/routes/admin-sso.ts +545 -0
  487. package/templates/nextjs-standalone/src/api/routes/admin-suggestions.ts +176 -0
  488. package/templates/nextjs-standalone/src/api/routes/admin-usage.ts +310 -0
  489. package/templates/nextjs-standalone/src/api/routes/admin.ts +4156 -898
  490. package/templates/nextjs-standalone/src/api/routes/auth-preamble.ts +105 -0
  491. package/templates/nextjs-standalone/src/api/routes/billing.ts +397 -0
  492. package/templates/nextjs-standalone/src/api/routes/chat.ts +597 -334
  493. package/templates/nextjs-standalone/src/api/routes/conversations.ts +987 -132
  494. package/templates/nextjs-standalone/src/api/routes/demo.ts +673 -0
  495. package/templates/nextjs-standalone/src/api/routes/discord.ts +274 -0
  496. package/templates/nextjs-standalone/src/api/routes/ee-error-handler.ts +32 -0
  497. package/templates/nextjs-standalone/src/api/routes/health.ts +129 -14
  498. package/templates/nextjs-standalone/src/api/routes/middleware.ts +244 -0
  499. package/templates/nextjs-standalone/src/api/routes/onboarding-emails.ts +134 -0
  500. package/templates/nextjs-standalone/src/api/routes/onboarding.ts +1109 -0
  501. package/templates/nextjs-standalone/src/api/routes/openapi.ts +184 -1597
  502. package/templates/nextjs-standalone/src/api/routes/platform-admin.ts +760 -0
  503. package/templates/nextjs-standalone/src/api/routes/platform-backups.ts +436 -0
  504. package/templates/nextjs-standalone/src/api/routes/platform-domains.ts +235 -0
  505. package/templates/nextjs-standalone/src/api/routes/platform-residency.ts +257 -0
  506. package/templates/nextjs-standalone/src/api/routes/platform-sla.ts +379 -0
  507. package/templates/nextjs-standalone/src/api/routes/prompts.ts +221 -0
  508. package/templates/nextjs-standalone/src/api/routes/public-branding.ts +106 -0
  509. package/templates/nextjs-standalone/src/api/routes/query.ts +330 -219
  510. package/templates/nextjs-standalone/src/api/routes/scheduled-tasks.ts +393 -297
  511. package/templates/nextjs-standalone/src/api/routes/semantic.ts +179 -0
  512. package/templates/nextjs-standalone/src/api/routes/sessions.ts +210 -0
  513. package/templates/nextjs-standalone/src/api/routes/shared-domains.ts +98 -0
  514. package/templates/nextjs-standalone/src/api/routes/shared-schemas.ts +139 -0
  515. package/templates/nextjs-standalone/src/api/routes/slack.ts +209 -52
  516. package/templates/nextjs-standalone/src/api/routes/suggestions.ts +233 -0
  517. package/templates/nextjs-standalone/src/api/routes/tables.ts +67 -0
  518. package/templates/nextjs-standalone/src/api/routes/teams.ts +222 -0
  519. package/templates/nextjs-standalone/src/api/routes/validate-sql.ts +188 -0
  520. package/templates/nextjs-standalone/src/api/routes/validation-hook.ts +62 -0
  521. package/templates/nextjs-standalone/src/api/routes/widget-loader.ts +356 -0
  522. package/templates/nextjs-standalone/src/api/routes/widget.ts +428 -0
  523. package/templates/nextjs-standalone/src/api/routes/wizard.ts +852 -0
  524. package/templates/nextjs-standalone/src/api/server.ts +187 -69
  525. package/templates/nextjs-standalone/src/app/error.tsx +5 -2
  526. package/templates/nextjs-standalone/src/app/globals.css +1 -1
  527. package/templates/nextjs-standalone/src/app/layout.tsx +7 -2
  528. package/templates/nextjs-standalone/src/app/page.tsx +39 -5
  529. package/templates/nextjs-standalone/src/components/data-table/data-table-column-header.tsx +99 -0
  530. package/templates/nextjs-standalone/src/components/data-table/data-table-date-filter.tsx +225 -0
  531. package/templates/nextjs-standalone/src/components/data-table/data-table-expandable.tsx +125 -0
  532. package/templates/nextjs-standalone/src/components/data-table/data-table-faceted-filter.tsx +189 -0
  533. package/templates/nextjs-standalone/src/components/data-table/data-table-pagination.tsx +112 -0
  534. package/templates/nextjs-standalone/src/components/data-table/data-table-range-filter.tsx +122 -0
  535. package/templates/nextjs-standalone/src/components/data-table/data-table-slider-filter.tsx +256 -0
  536. package/templates/nextjs-standalone/src/components/data-table/data-table-sort-list.tsx +407 -0
  537. package/templates/nextjs-standalone/src/components/data-table/data-table-toolbar.tsx +149 -0
  538. package/templates/nextjs-standalone/src/components/data-table/data-table-view-options.tsx +89 -0
  539. package/templates/nextjs-standalone/src/components/data-table/data-table.tsx +105 -0
  540. package/templates/nextjs-standalone/src/components/form-dialog.tsx +135 -0
  541. package/templates/nextjs-standalone/src/components/ui/accordion.tsx +66 -0
  542. package/templates/nextjs-standalone/src/components/ui/calendar.tsx +220 -0
  543. package/templates/nextjs-standalone/src/components/ui/checkbox.tsx +32 -0
  544. package/templates/nextjs-standalone/src/components/ui/faceted.tsx +283 -0
  545. package/templates/nextjs-standalone/src/components/ui/form.tsx +167 -0
  546. package/templates/nextjs-standalone/src/components/ui/label.tsx +24 -0
  547. package/templates/nextjs-standalone/src/components/ui/popover.tsx +89 -0
  548. package/templates/nextjs-standalone/src/components/ui/progress.tsx +31 -0
  549. package/templates/nextjs-standalone/src/components/ui/scroll-area.tsx +6 -2
  550. package/templates/nextjs-standalone/src/components/ui/slider.tsx +63 -0
  551. package/templates/nextjs-standalone/src/components/ui/sortable.tsx +581 -0
  552. package/templates/nextjs-standalone/src/components/ui/switch.tsx +35 -0
  553. package/templates/nextjs-standalone/src/components/ui/textarea.tsx +18 -0
  554. package/templates/nextjs-standalone/src/config/data-table.ts +82 -0
  555. package/templates/nextjs-standalone/src/env-check.ts +74 -0
  556. package/templates/nextjs-standalone/src/hooks/use-callback-ref.ts +27 -0
  557. package/templates/nextjs-standalone/src/hooks/use-data-table.ts +316 -0
  558. package/templates/nextjs-standalone/src/hooks/use-debounced-callback.ts +28 -0
  559. package/templates/nextjs-standalone/src/lib/action-types.ts +7 -41
  560. package/templates/nextjs-standalone/src/lib/agent-query.ts +4 -2
  561. package/templates/nextjs-standalone/src/lib/agent.ts +363 -31
  562. package/templates/nextjs-standalone/src/lib/api-url.ts +2 -3
  563. package/templates/nextjs-standalone/src/lib/auth/admin-permissions.ts +38 -0
  564. package/templates/nextjs-standalone/src/lib/auth/audit.ts +19 -4
  565. package/templates/nextjs-standalone/src/lib/auth/byot.ts +3 -3
  566. package/templates/nextjs-standalone/src/lib/auth/detect.ts +29 -8
  567. package/templates/nextjs-standalone/src/lib/auth/managed.ts +104 -14
  568. package/templates/nextjs-standalone/src/lib/auth/middleware.ts +53 -6
  569. package/templates/nextjs-standalone/src/lib/auth/migrate.ts +140 -15
  570. package/templates/nextjs-standalone/src/lib/auth/oauth-state.ts +123 -0
  571. package/templates/nextjs-standalone/src/lib/auth/org-permissions.ts +55 -0
  572. package/templates/nextjs-standalone/src/lib/auth/permissions.ts +26 -19
  573. package/templates/nextjs-standalone/src/lib/auth/server.ts +355 -9
  574. package/templates/nextjs-standalone/src/lib/auth/simple-key.ts +3 -3
  575. package/templates/nextjs-standalone/src/lib/auth/types.ts +15 -21
  576. package/templates/nextjs-standalone/src/lib/billing/enforcement.ts +368 -0
  577. package/templates/nextjs-standalone/src/lib/billing/plans.ts +155 -0
  578. package/templates/nextjs-standalone/src/lib/cache/index.ts +92 -0
  579. package/templates/nextjs-standalone/src/lib/cache/keys.ts +30 -0
  580. package/templates/nextjs-standalone/src/lib/cache/lru.ts +79 -0
  581. package/templates/nextjs-standalone/src/lib/cache/types.ts +31 -0
  582. package/templates/nextjs-standalone/src/lib/compose-refs.ts +62 -0
  583. package/templates/nextjs-standalone/src/lib/config.ts +563 -11
  584. package/templates/nextjs-standalone/src/lib/connection-types.ts +9 -0
  585. package/templates/nextjs-standalone/src/lib/conversation-types.ts +1 -25
  586. package/templates/nextjs-standalone/src/lib/conversations.ts +345 -14
  587. package/templates/nextjs-standalone/src/lib/data-table.ts +61 -0
  588. package/templates/nextjs-standalone/src/lib/db/connection.ts +793 -39
  589. package/templates/nextjs-standalone/src/lib/db/internal.ts +985 -139
  590. package/templates/nextjs-standalone/src/lib/db/migrate.ts +295 -0
  591. package/templates/nextjs-standalone/src/lib/db/migrations/0000_baseline.sql +703 -0
  592. package/templates/nextjs-standalone/src/lib/db/migrations/0001_teams_installations.sql +14 -0
  593. package/templates/nextjs-standalone/src/lib/db/migrations/0002_discord_installations.sql +14 -0
  594. package/templates/nextjs-standalone/src/lib/db/migrations/0003_telegram_installations.sql +15 -0
  595. package/templates/nextjs-standalone/src/lib/db/migrations/0004_sandbox_credentials.sql +18 -0
  596. package/templates/nextjs-standalone/src/lib/db/migrations/0005_oauth_state.sql +16 -0
  597. package/templates/nextjs-standalone/src/lib/db/migrations/0006_byot_credentials.sql +14 -0
  598. package/templates/nextjs-standalone/src/lib/db/migrations/0007_gchat_installations.sql +15 -0
  599. package/templates/nextjs-standalone/src/lib/db/migrations/0008_github_installations.sql +14 -0
  600. package/templates/nextjs-standalone/src/lib/db/migrations/0009_linear_installations.sql +15 -0
  601. package/templates/nextjs-standalone/src/lib/db/migrations/0010_whatsapp_installations.sql +14 -0
  602. package/templates/nextjs-standalone/src/lib/db/migrations/0011_email_installations.sql +16 -0
  603. package/templates/nextjs-standalone/src/lib/db/migrations/0012_region_migrations.sql +25 -0
  604. package/templates/nextjs-standalone/src/lib/db/schema.ts +1120 -0
  605. package/templates/nextjs-standalone/src/lib/db/source-rate-limit.ts +89 -139
  606. package/templates/nextjs-standalone/src/lib/demo.ts +308 -0
  607. package/templates/nextjs-standalone/src/lib/discord/store.ts +225 -0
  608. package/templates/nextjs-standalone/src/lib/effect/ai.ts +243 -0
  609. package/templates/nextjs-standalone/src/lib/effect/errors.ts +234 -0
  610. package/templates/nextjs-standalone/src/lib/effect/hono.ts +454 -0
  611. package/templates/nextjs-standalone/src/lib/effect/index.ts +137 -0
  612. package/templates/nextjs-standalone/src/lib/effect/layers.ts +496 -0
  613. package/templates/nextjs-standalone/src/lib/effect/services.ts +776 -0
  614. package/templates/nextjs-standalone/src/lib/effect/sql.ts +178 -0
  615. package/templates/nextjs-standalone/src/lib/effect/toolkit.ts +123 -0
  616. package/templates/nextjs-standalone/src/lib/email/delivery.ts +232 -0
  617. package/templates/nextjs-standalone/src/lib/email/engine.ts +349 -0
  618. package/templates/nextjs-standalone/src/lib/email/hooks.ts +107 -0
  619. package/templates/nextjs-standalone/src/lib/email/index.ts +16 -0
  620. package/templates/nextjs-standalone/src/lib/email/scheduler.ts +72 -0
  621. package/templates/nextjs-standalone/src/lib/email/sequence.ts +73 -0
  622. package/templates/nextjs-standalone/src/lib/email/store.ts +163 -0
  623. package/templates/nextjs-standalone/src/lib/email/templates.ts +215 -0
  624. package/templates/nextjs-standalone/src/lib/format.test.ts +117 -0
  625. package/templates/nextjs-standalone/src/lib/format.ts +67 -0
  626. package/templates/nextjs-standalone/src/lib/gchat/store.ts +202 -0
  627. package/templates/nextjs-standalone/src/lib/github/store.ts +197 -0
  628. package/templates/nextjs-standalone/src/lib/id.ts +29 -0
  629. package/templates/nextjs-standalone/src/lib/integrations/types.ts +166 -0
  630. package/templates/nextjs-standalone/src/lib/learn/pattern-analyzer.ts +224 -0
  631. package/templates/nextjs-standalone/src/lib/learn/pattern-cache.ts +229 -0
  632. package/templates/nextjs-standalone/src/lib/learn/pattern-proposer.ts +87 -0
  633. package/templates/nextjs-standalone/src/lib/learn/suggestion-helpers.ts +34 -0
  634. package/templates/nextjs-standalone/src/lib/learn/suggestions.ts +139 -0
  635. package/templates/nextjs-standalone/src/lib/linear/store.ts +200 -0
  636. package/templates/nextjs-standalone/src/lib/logger.ts +35 -3
  637. package/templates/nextjs-standalone/src/lib/metering.ts +272 -0
  638. package/templates/nextjs-standalone/src/lib/parsers.ts +99 -0
  639. package/templates/nextjs-standalone/src/lib/plugins/hooks.ts +13 -11
  640. package/templates/nextjs-standalone/src/lib/plugins/index.ts +3 -1
  641. package/templates/nextjs-standalone/src/lib/plugins/registry.ts +58 -6
  642. package/templates/nextjs-standalone/src/lib/plugins/settings.ts +147 -0
  643. package/templates/nextjs-standalone/src/lib/plugins/wiring.ts +6 -9
  644. package/templates/nextjs-standalone/src/lib/profiler.ts +1665 -0
  645. package/templates/nextjs-standalone/src/lib/providers.ts +188 -13
  646. package/templates/nextjs-standalone/src/lib/rls.ts +172 -60
  647. package/templates/nextjs-standalone/src/lib/sandbox/credentials.ts +206 -0
  648. package/templates/nextjs-standalone/src/lib/sandbox/validate.ts +179 -0
  649. package/templates/nextjs-standalone/src/lib/scheduled-task-types.ts +26 -94
  650. package/templates/nextjs-standalone/src/lib/scheduled-tasks.ts +174 -34
  651. package/templates/nextjs-standalone/src/lib/scheduler/delivery.ts +248 -150
  652. package/templates/nextjs-standalone/src/lib/scheduler/engine.ts +190 -154
  653. package/templates/nextjs-standalone/src/lib/scheduler/executor.ts +74 -23
  654. package/templates/nextjs-standalone/src/lib/scheduler/preview.ts +72 -0
  655. package/templates/nextjs-standalone/src/lib/security/abuse.ts +463 -0
  656. package/templates/nextjs-standalone/src/lib/semantic/diff.ts +267 -0
  657. package/templates/nextjs-standalone/src/lib/semantic/entities.ts +167 -0
  658. package/templates/nextjs-standalone/src/lib/semantic/files.ts +283 -0
  659. package/templates/nextjs-standalone/src/lib/semantic/index.ts +27 -0
  660. package/templates/nextjs-standalone/src/lib/{semantic-index.ts → semantic/search.ts} +80 -9
  661. package/templates/nextjs-standalone/src/lib/semantic/sync.ts +581 -0
  662. package/templates/nextjs-standalone/src/lib/{semantic.ts → semantic/whitelist.ts} +189 -3
  663. package/templates/nextjs-standalone/src/lib/settings.ts +817 -0
  664. package/templates/nextjs-standalone/src/lib/sidecar-types.ts +13 -0
  665. package/templates/nextjs-standalone/src/lib/slack/store.ts +134 -25
  666. package/templates/nextjs-standalone/src/lib/startup.ts +528 -362
  667. package/templates/nextjs-standalone/src/lib/teams/store.ts +216 -0
  668. package/templates/nextjs-standalone/src/lib/telegram/store.ts +202 -0
  669. package/templates/nextjs-standalone/src/lib/telemetry.ts +40 -0
  670. package/templates/nextjs-standalone/src/lib/tools/actions/audit.ts +8 -5
  671. package/templates/nextjs-standalone/src/lib/tools/actions/email.ts +3 -1
  672. package/templates/nextjs-standalone/src/lib/tools/actions/handler.ts +276 -93
  673. package/templates/nextjs-standalone/src/lib/tools/actions/jira.ts +2 -2
  674. package/templates/nextjs-standalone/src/lib/tools/backends/detect.ts +16 -0
  675. package/templates/nextjs-standalone/src/lib/tools/backends/index.ts +11 -0
  676. package/templates/nextjs-standalone/src/lib/tools/backends/nsjail.ts +213 -0
  677. package/templates/nextjs-standalone/src/lib/tools/backends/shared.ts +103 -0
  678. package/templates/nextjs-standalone/src/lib/tools/backends/types.ts +26 -0
  679. package/templates/nextjs-standalone/src/lib/tools/explore-nsjail.ts +7 -228
  680. package/templates/nextjs-standalone/src/lib/tools/explore-sandbox.ts +4 -29
  681. package/templates/nextjs-standalone/src/lib/tools/explore-sidecar.ts +18 -2
  682. package/templates/nextjs-standalone/src/lib/tools/explore.ts +246 -54
  683. package/templates/nextjs-standalone/src/lib/tools/index.ts +17 -0
  684. package/templates/nextjs-standalone/src/lib/tools/python-nsjail.ts +11 -139
  685. package/templates/nextjs-standalone/src/lib/tools/python-sandbox.ts +9 -132
  686. package/templates/nextjs-standalone/src/lib/tools/python-sidecar.ts +184 -3
  687. package/templates/nextjs-standalone/src/lib/tools/python-stream.ts +33 -0
  688. package/templates/nextjs-standalone/src/lib/tools/python-wrapper.ts +129 -0
  689. package/templates/nextjs-standalone/src/lib/tools/python.ts +115 -15
  690. package/templates/nextjs-standalone/src/lib/tools/registry.ts +14 -2
  691. package/templates/nextjs-standalone/src/lib/tools/sql.ts +778 -362
  692. package/templates/nextjs-standalone/src/lib/tracing.ts +16 -0
  693. package/templates/nextjs-standalone/src/lib/whatsapp/store.ts +198 -0
  694. package/templates/nextjs-standalone/src/lib/workspace.ts +89 -0
  695. package/templates/nextjs-standalone/src/progress.ts +121 -0
  696. package/templates/nextjs-standalone/src/types/data-table.ts +48 -0
  697. package/templates/nextjs-standalone/src/ui/atlas-chat-reexport.ts +3 -0
  698. package/templates/nextjs-standalone/src/ui/components/actions/action-approval-card.tsx +26 -19
  699. package/templates/nextjs-standalone/src/ui/components/actions/action-status-badge.tsx +3 -3
  700. package/templates/nextjs-standalone/src/ui/components/admin/admin-layout.tsx +57 -39
  701. package/templates/nextjs-standalone/src/ui/components/admin/admin-sidebar.tsx +213 -35
  702. package/templates/nextjs-standalone/src/ui/components/admin/delivery-status-badge.tsx +53 -0
  703. package/templates/nextjs-standalone/src/ui/components/admin/empty-state.tsx +27 -6
  704. package/templates/nextjs-standalone/src/ui/components/admin/entity-detail.tsx +3 -52
  705. package/templates/nextjs-standalone/src/ui/components/admin/error-banner.tsx +2 -2
  706. package/templates/nextjs-standalone/src/ui/components/admin/feature-disabled.tsx +28 -5
  707. package/templates/nextjs-standalone/src/ui/components/admin-content-wrapper.tsx +87 -0
  708. package/templates/nextjs-standalone/src/ui/components/atlas-chat.tsx +449 -166
  709. package/templates/nextjs-standalone/src/ui/components/branding-head.tsx +41 -0
  710. package/templates/nextjs-standalone/src/ui/components/chart/chart-detection.ts +62 -5
  711. package/templates/nextjs-standalone/src/ui/components/chart/result-chart.tsx +316 -125
  712. package/templates/nextjs-standalone/src/ui/components/chat/api-key-bar.tsx +4 -4
  713. package/templates/nextjs-standalone/src/ui/components/chat/data-table.tsx +45 -4
  714. package/templates/nextjs-standalone/src/ui/components/chat/error-banner.tsx +86 -5
  715. package/templates/nextjs-standalone/src/ui/components/chat/follow-up-chips.tsx +29 -0
  716. package/templates/nextjs-standalone/src/ui/components/chat/markdown.tsx +24 -0
  717. package/templates/nextjs-standalone/src/ui/components/chat/prompt-library.tsx +206 -0
  718. package/templates/nextjs-standalone/src/ui/components/chat/python-result-card.tsx +106 -78
  719. package/templates/nextjs-standalone/src/ui/components/chat/result-card-base.tsx +101 -0
  720. package/templates/nextjs-standalone/src/ui/components/chat/share-dialog.tsx +377 -0
  721. package/templates/nextjs-standalone/src/ui/components/chat/sql-result-card.tsx +94 -73
  722. package/templates/nextjs-standalone/src/ui/components/chat/suggestion-chips.tsx +46 -0
  723. package/templates/nextjs-standalone/src/ui/components/chat/tool-part.tsx +16 -4
  724. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-item.tsx +48 -17
  725. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-list.tsx +38 -24
  726. package/templates/nextjs-standalone/src/ui/components/conversations/conversation-sidebar.tsx +66 -7
  727. package/templates/nextjs-standalone/src/ui/components/conversations/delete-confirmation.tsx +9 -2
  728. package/templates/nextjs-standalone/src/ui/components/error-boundary.tsx +66 -0
  729. package/templates/nextjs-standalone/src/ui/components/notebook/delete-cell-dialog.tsx +48 -0
  730. package/templates/nextjs-standalone/src/ui/components/notebook/fork-branch-selector.tsx +68 -0
  731. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-cell-input.tsx +76 -0
  732. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-cell-output.tsx +58 -0
  733. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-cell-toolbar.tsx +91 -0
  734. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-cell.tsx +119 -0
  735. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-empty-state.tsx +19 -0
  736. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-export.ts +287 -0
  737. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-input-bar.tsx +49 -0
  738. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-shell.tsx +266 -0
  739. package/templates/nextjs-standalone/src/ui/components/notebook/notebook-text-cell.tsx +152 -0
  740. package/templates/nextjs-standalone/src/ui/components/notebook/types.ts +39 -0
  741. package/templates/nextjs-standalone/src/ui/components/notebook/use-keyboard-nav.ts +109 -0
  742. package/templates/nextjs-standalone/src/ui/components/notebook/use-notebook.ts +684 -0
  743. package/templates/nextjs-standalone/src/ui/components/org-switcher.tsx +111 -0
  744. package/templates/nextjs-standalone/src/ui/components/region-picker.tsx +103 -0
  745. package/templates/nextjs-standalone/src/ui/components/schema-explorer/schema-explorer.tsx +522 -0
  746. package/templates/nextjs-standalone/src/ui/components/social-icons.tsx +26 -0
  747. package/templates/nextjs-standalone/src/ui/components/tour/guided-tour.tsx +81 -0
  748. package/templates/nextjs-standalone/src/ui/components/tour/index.ts +5 -0
  749. package/templates/nextjs-standalone/src/ui/components/tour/nav-bar.tsx +100 -0
  750. package/templates/nextjs-standalone/src/ui/components/tour/tour-overlay.tsx +298 -0
  751. package/templates/nextjs-standalone/src/ui/components/tour/tour-steps.ts +43 -0
  752. package/templates/nextjs-standalone/src/ui/components/tour/types.ts +21 -0
  753. package/templates/nextjs-standalone/src/ui/components/tour/use-tour.ts +193 -0
  754. package/templates/nextjs-standalone/src/ui/context-reexport.ts +3 -0
  755. package/templates/nextjs-standalone/src/ui/hooks/theme-init-script.ts +17 -0
  756. package/templates/nextjs-standalone/src/ui/hooks/use-admin-fetch.ts +38 -30
  757. package/templates/nextjs-standalone/src/ui/hooks/use-admin-mutation.ts +188 -0
  758. package/templates/nextjs-standalone/src/ui/hooks/use-atlas-transport.ts +225 -0
  759. package/templates/nextjs-standalone/src/ui/hooks/use-branding.ts +68 -0
  760. package/templates/nextjs-standalone/src/ui/hooks/use-conversations.ts +106 -83
  761. package/templates/nextjs-standalone/src/ui/hooks/use-dark-mode.ts +134 -10
  762. package/templates/nextjs-standalone/src/ui/hooks/use-deploy-mode.ts +36 -0
  763. package/templates/nextjs-standalone/src/ui/hooks/use-platform-admin-guard.ts +49 -0
  764. package/templates/nextjs-standalone/src/ui/lib/action-types.ts +11 -63
  765. package/templates/nextjs-standalone/src/ui/lib/admin-schemas.ts +744 -0
  766. package/templates/nextjs-standalone/src/ui/lib/fetch-client.ts +84 -0
  767. package/templates/nextjs-standalone/src/ui/lib/fetch-error.ts +54 -0
  768. package/templates/nextjs-standalone/src/ui/lib/helpers.ts +94 -1
  769. package/templates/nextjs-standalone/src/ui/lib/types.ts +149 -140
  770. package/templates/nextjs-standalone/tsconfig.json +3 -2
  771. package/templates/docker/src/api/__tests__/actions.test.ts +0 -683
  772. package/templates/docker/src/api/__tests__/admin.test.ts +0 -820
  773. package/templates/docker/src/api/__tests__/auth.test.ts +0 -165
  774. package/templates/docker/src/api/__tests__/chat.test.ts +0 -376
  775. package/templates/docker/src/api/__tests__/conversations.test.ts +0 -555
  776. package/templates/docker/src/api/__tests__/cors.test.ts +0 -135
  777. package/templates/docker/src/api/__tests__/health-plugin.test.ts +0 -176
  778. package/templates/docker/src/api/__tests__/health.test.ts +0 -283
  779. package/templates/docker/src/api/__tests__/query.test.ts +0 -891
  780. package/templates/docker/src/api/__tests__/scheduled-tasks.test.ts +0 -601
  781. package/templates/docker/src/api/__tests__/slack.test.ts +0 -847
  782. package/templates/docker/src/lib/__tests__/agent-cache.test.ts +0 -439
  783. package/templates/docker/src/lib/__tests__/agent-dialect.test.ts +0 -131
  784. package/templates/docker/src/lib/__tests__/agent-health-annotations.test.ts +0 -166
  785. package/templates/docker/src/lib/__tests__/agent-integration.test.ts +0 -516
  786. package/templates/docker/src/lib/__tests__/config-actions.test.ts +0 -166
  787. package/templates/docker/src/lib/__tests__/config.test.ts +0 -1113
  788. package/templates/docker/src/lib/__tests__/conversations.test.ts +0 -589
  789. package/templates/docker/src/lib/__tests__/errors.test.ts +0 -256
  790. package/templates/docker/src/lib/__tests__/logger.test.ts +0 -200
  791. package/templates/docker/src/lib/__tests__/plugin-aware-validation.test.ts +0 -321
  792. package/templates/docker/src/lib/__tests__/providers.test.ts +0 -130
  793. package/templates/docker/src/lib/__tests__/rls.test.ts +0 -435
  794. package/templates/docker/src/lib/__tests__/scheduled-task-types.test.ts +0 -124
  795. package/templates/docker/src/lib/__tests__/scheduled-tasks.test.ts +0 -550
  796. package/templates/docker/src/lib/__tests__/semantic-index.test.ts +0 -547
  797. package/templates/docker/src/lib/__tests__/semantic-multisource.test.ts +0 -544
  798. package/templates/docker/src/lib/__tests__/semantic.test.ts +0 -363
  799. package/templates/docker/src/lib/__tests__/startup-actions.test.ts +0 -461
  800. package/templates/docker/src/lib/__tests__/startup-first-run.test.ts +0 -429
  801. package/templates/docker/src/lib/__tests__/startup.test.ts +0 -470
  802. package/templates/docker/src/lib/__tests__/tracing.test.ts +0 -28
  803. package/templates/docker/src/lib/auth/__tests__/audit.test.ts +0 -418
  804. package/templates/docker/src/lib/auth/__tests__/byot-integration.test.ts +0 -222
  805. package/templates/docker/src/lib/auth/__tests__/byot.test.ts +0 -366
  806. package/templates/docker/src/lib/auth/__tests__/detect.test.ts +0 -190
  807. package/templates/docker/src/lib/auth/__tests__/managed.test.ts +0 -173
  808. package/templates/docker/src/lib/auth/__tests__/middleware.test.ts +0 -456
  809. package/templates/docker/src/lib/auth/__tests__/migrate.test.ts +0 -203
  810. package/templates/docker/src/lib/auth/__tests__/permissions.test.ts +0 -225
  811. package/templates/docker/src/lib/auth/__tests__/server.test.ts +0 -34
  812. package/templates/docker/src/lib/auth/__tests__/simple-key.test.ts +0 -176
  813. package/templates/docker/src/lib/auth/__tests__/types.test.ts +0 -44
  814. package/templates/docker/src/lib/db/__tests__/connection.test.ts +0 -144
  815. package/templates/docker/src/lib/db/__tests__/internal.test.ts +0 -387
  816. package/templates/docker/src/lib/db/__tests__/registry-health.test.ts +0 -190
  817. package/templates/docker/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -137
  818. package/templates/docker/src/lib/db/__tests__/registry.test.ts +0 -398
  819. package/templates/docker/src/lib/db/__tests__/source-rate-limit.test.ts +0 -130
  820. package/templates/docker/src/lib/errors.ts +0 -154
  821. package/templates/docker/src/lib/plugins/__tests__/hooks-integration.test.ts +0 -204
  822. package/templates/docker/src/lib/plugins/__tests__/hooks.test.ts +0 -529
  823. package/templates/docker/src/lib/plugins/__tests__/migrate.test.ts +0 -875
  824. package/templates/docker/src/lib/plugins/__tests__/registry.test.ts +0 -373
  825. package/templates/docker/src/lib/plugins/__tests__/tools.test.ts +0 -49
  826. package/templates/docker/src/lib/plugins/__tests__/wiring.test.ts +0 -799
  827. package/templates/docker/src/lib/scheduler/__tests__/delivery.test.ts +0 -192
  828. package/templates/docker/src/lib/scheduler/__tests__/engine.test.ts +0 -248
  829. package/templates/docker/src/lib/scheduler/__tests__/format-email.test.ts +0 -96
  830. package/templates/docker/src/lib/scheduler/__tests__/format-slack.test.ts +0 -78
  831. package/templates/docker/src/lib/scheduler/__tests__/format-webhook.test.ts +0 -78
  832. package/templates/docker/src/lib/scheduler/index.ts +0 -7
  833. package/templates/docker/src/lib/slack/__tests__/api.test.ts +0 -160
  834. package/templates/docker/src/lib/slack/__tests__/format.test.ts +0 -237
  835. package/templates/docker/src/lib/slack/__tests__/store.test.ts +0 -188
  836. package/templates/docker/src/lib/slack/__tests__/threads.test.ts +0 -112
  837. package/templates/docker/src/lib/slack/__tests__/verify.test.ts +0 -111
  838. package/templates/docker/src/lib/tools/__tests__/action-permissions.test.ts +0 -594
  839. package/templates/docker/src/lib/tools/__tests__/custom-validation.test.ts +0 -240
  840. package/templates/docker/src/lib/tools/__tests__/explore-backend.test.ts +0 -267
  841. package/templates/docker/src/lib/tools/__tests__/explore-nsjail.test.ts +0 -506
  842. package/templates/docker/src/lib/tools/__tests__/explore-plugin.test.ts +0 -374
  843. package/templates/docker/src/lib/tools/__tests__/explore-sdk-compat.test.ts +0 -82
  844. package/templates/docker/src/lib/tools/__tests__/explore-sidecar.test.ts +0 -210
  845. package/templates/docker/src/lib/tools/__tests__/python-nsjail.test.ts +0 -515
  846. package/templates/docker/src/lib/tools/__tests__/python-sandbox.test.ts +0 -397
  847. package/templates/docker/src/lib/tools/__tests__/python-sidecar.test.ts +0 -365
  848. package/templates/docker/src/lib/tools/__tests__/python.test.ts +0 -331
  849. package/templates/docker/src/lib/tools/__tests__/registry-actions.test.ts +0 -132
  850. package/templates/docker/src/lib/tools/__tests__/registry.test.ts +0 -242
  851. package/templates/docker/src/lib/tools/__tests__/sql-audit.test.ts +0 -227
  852. package/templates/docker/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +0 -100
  853. package/templates/docker/src/lib/tools/__tests__/sql-ratelimit.test.ts +0 -227
  854. package/templates/docker/src/lib/tools/__tests__/sql.test.ts +0 -709
  855. package/templates/docker/src/lib/tools/actions/__tests__/audit.test.ts +0 -211
  856. package/templates/docker/src/lib/tools/actions/__tests__/email.test.ts +0 -378
  857. package/templates/docker/src/lib/tools/actions/__tests__/handler.test.ts +0 -681
  858. package/templates/docker/src/lib/tools/actions/__tests__/jira.test.ts +0 -427
  859. package/templates/docker/src/test-setup.ts +0 -38
  860. package/templates/docker/src/types/vercel-sandbox.d.ts +0 -61
  861. package/templates/docker/src/ui/components/chat/managed-auth-card.tsx +0 -116
  862. package/templates/nextjs-standalone/src/api/__tests__/actions.test.ts +0 -683
  863. package/templates/nextjs-standalone/src/api/__tests__/admin.test.ts +0 -820
  864. package/templates/nextjs-standalone/src/api/__tests__/auth.test.ts +0 -165
  865. package/templates/nextjs-standalone/src/api/__tests__/chat.test.ts +0 -376
  866. package/templates/nextjs-standalone/src/api/__tests__/conversations.test.ts +0 -555
  867. package/templates/nextjs-standalone/src/api/__tests__/cors.test.ts +0 -135
  868. package/templates/nextjs-standalone/src/api/__tests__/health-plugin.test.ts +0 -176
  869. package/templates/nextjs-standalone/src/api/__tests__/health.test.ts +0 -283
  870. package/templates/nextjs-standalone/src/api/__tests__/query.test.ts +0 -891
  871. package/templates/nextjs-standalone/src/api/__tests__/scheduled-tasks.test.ts +0 -601
  872. package/templates/nextjs-standalone/src/api/__tests__/slack.test.ts +0 -847
  873. package/templates/nextjs-standalone/src/app/global-error.tsx +0 -68
  874. package/templates/nextjs-standalone/src/lib/__tests__/agent-cache.test.ts +0 -439
  875. package/templates/nextjs-standalone/src/lib/__tests__/agent-dialect.test.ts +0 -131
  876. package/templates/nextjs-standalone/src/lib/__tests__/agent-health-annotations.test.ts +0 -166
  877. package/templates/nextjs-standalone/src/lib/__tests__/agent-integration.test.ts +0 -516
  878. package/templates/nextjs-standalone/src/lib/__tests__/config-actions.test.ts +0 -166
  879. package/templates/nextjs-standalone/src/lib/__tests__/config.test.ts +0 -1113
  880. package/templates/nextjs-standalone/src/lib/__tests__/conversations.test.ts +0 -589
  881. package/templates/nextjs-standalone/src/lib/__tests__/errors.test.ts +0 -256
  882. package/templates/nextjs-standalone/src/lib/__tests__/logger.test.ts +0 -200
  883. package/templates/nextjs-standalone/src/lib/__tests__/plugin-aware-validation.test.ts +0 -321
  884. package/templates/nextjs-standalone/src/lib/__tests__/providers.test.ts +0 -130
  885. package/templates/nextjs-standalone/src/lib/__tests__/rls.test.ts +0 -435
  886. package/templates/nextjs-standalone/src/lib/__tests__/scheduled-task-types.test.ts +0 -124
  887. package/templates/nextjs-standalone/src/lib/__tests__/scheduled-tasks.test.ts +0 -550
  888. package/templates/nextjs-standalone/src/lib/__tests__/semantic-index.test.ts +0 -547
  889. package/templates/nextjs-standalone/src/lib/__tests__/semantic-multisource.test.ts +0 -544
  890. package/templates/nextjs-standalone/src/lib/__tests__/semantic.test.ts +0 -363
  891. package/templates/nextjs-standalone/src/lib/__tests__/startup-actions.test.ts +0 -461
  892. package/templates/nextjs-standalone/src/lib/__tests__/startup-first-run.test.ts +0 -429
  893. package/templates/nextjs-standalone/src/lib/__tests__/startup.test.ts +0 -470
  894. package/templates/nextjs-standalone/src/lib/__tests__/tracing.test.ts +0 -28
  895. package/templates/nextjs-standalone/src/lib/auth/__tests__/audit.test.ts +0 -418
  896. package/templates/nextjs-standalone/src/lib/auth/__tests__/byot-integration.test.ts +0 -222
  897. package/templates/nextjs-standalone/src/lib/auth/__tests__/byot.test.ts +0 -366
  898. package/templates/nextjs-standalone/src/lib/auth/__tests__/detect.test.ts +0 -190
  899. package/templates/nextjs-standalone/src/lib/auth/__tests__/managed.test.ts +0 -173
  900. package/templates/nextjs-standalone/src/lib/auth/__tests__/middleware.test.ts +0 -456
  901. package/templates/nextjs-standalone/src/lib/auth/__tests__/migrate.test.ts +0 -203
  902. package/templates/nextjs-standalone/src/lib/auth/__tests__/permissions.test.ts +0 -225
  903. package/templates/nextjs-standalone/src/lib/auth/__tests__/server.test.ts +0 -34
  904. package/templates/nextjs-standalone/src/lib/auth/__tests__/simple-key.test.ts +0 -176
  905. package/templates/nextjs-standalone/src/lib/auth/__tests__/types.test.ts +0 -44
  906. package/templates/nextjs-standalone/src/lib/db/__tests__/connection.test.ts +0 -144
  907. package/templates/nextjs-standalone/src/lib/db/__tests__/internal.test.ts +0 -387
  908. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-health.test.ts +0 -190
  909. package/templates/nextjs-standalone/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -137
  910. package/templates/nextjs-standalone/src/lib/db/__tests__/registry.test.ts +0 -398
  911. package/templates/nextjs-standalone/src/lib/db/__tests__/source-rate-limit.test.ts +0 -130
  912. package/templates/nextjs-standalone/src/lib/errors.ts +0 -154
  913. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks-integration.test.ts +0 -204
  914. package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks.test.ts +0 -529
  915. package/templates/nextjs-standalone/src/lib/plugins/__tests__/migrate.test.ts +0 -875
  916. package/templates/nextjs-standalone/src/lib/plugins/__tests__/registry.test.ts +0 -373
  917. package/templates/nextjs-standalone/src/lib/plugins/__tests__/tools.test.ts +0 -49
  918. package/templates/nextjs-standalone/src/lib/plugins/__tests__/wiring.test.ts +0 -799
  919. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/delivery.test.ts +0 -192
  920. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/engine.test.ts +0 -248
  921. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-email.test.ts +0 -96
  922. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-slack.test.ts +0 -78
  923. package/templates/nextjs-standalone/src/lib/scheduler/__tests__/format-webhook.test.ts +0 -78
  924. package/templates/nextjs-standalone/src/lib/scheduler/index.ts +0 -7
  925. package/templates/nextjs-standalone/src/lib/slack/__tests__/api.test.ts +0 -160
  926. package/templates/nextjs-standalone/src/lib/slack/__tests__/format.test.ts +0 -237
  927. package/templates/nextjs-standalone/src/lib/slack/__tests__/store.test.ts +0 -188
  928. package/templates/nextjs-standalone/src/lib/slack/__tests__/threads.test.ts +0 -112
  929. package/templates/nextjs-standalone/src/lib/slack/__tests__/verify.test.ts +0 -111
  930. package/templates/nextjs-standalone/src/lib/tools/__tests__/action-permissions.test.ts +0 -594
  931. package/templates/nextjs-standalone/src/lib/tools/__tests__/custom-validation.test.ts +0 -240
  932. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-backend.test.ts +0 -267
  933. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-nsjail.test.ts +0 -506
  934. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-plugin.test.ts +0 -374
  935. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sdk-compat.test.ts +0 -82
  936. package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sidecar.test.ts +0 -210
  937. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-nsjail.test.ts +0 -515
  938. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sandbox.test.ts +0 -397
  939. package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sidecar.test.ts +0 -365
  940. package/templates/nextjs-standalone/src/lib/tools/__tests__/python.test.ts +0 -331
  941. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry-actions.test.ts +0 -132
  942. package/templates/nextjs-standalone/src/lib/tools/__tests__/registry.test.ts +0 -242
  943. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-audit.test.ts +0 -227
  944. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +0 -100
  945. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-ratelimit.test.ts +0 -227
  946. package/templates/nextjs-standalone/src/lib/tools/__tests__/sql.test.ts +0 -709
  947. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/audit.test.ts +0 -211
  948. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/email.test.ts +0 -378
  949. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/handler.test.ts +0 -681
  950. package/templates/nextjs-standalone/src/lib/tools/actions/__tests__/jira.test.ts +0 -427
  951. package/templates/nextjs-standalone/src/test-setup.ts +0 -38
  952. package/templates/nextjs-standalone/src/ui/components/chat/managed-auth-card.tsx +0 -116
@@ -0,0 +1,1109 @@
1
+ /**
2
+ * Onboarding API routes for self-serve signup flow.
3
+ *
4
+ * Mounted at /api/v1/onboarding. Requires managed auth (session-based).
5
+ * These routes power the post-signup wizard: test a database connection
6
+ * and finalize workspace setup (persist connection scoped to the user's org).
7
+ */
8
+
9
+ import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
10
+ import { Effect } from "effect";
11
+ import { runEffect } from "@atlas/api/lib/effect/hono";
12
+ import {
13
+ RequestContext,
14
+ AuthContext,
15
+ } from "@atlas/api/lib/effect/services";
16
+ import { validationHook } from "./validation-hook";
17
+ import { HTTPException } from "hono/http-exception";
18
+ import { z } from "zod";
19
+ import { createLogger } from "@atlas/api/lib/logger";
20
+ import { detectAuthMode } from "@atlas/api/lib/auth/detect";
21
+ import { connections, detectDBType, resolveDatasourceUrl } from "@atlas/api/lib/db/connection";
22
+ import { hasInternalDB, internalQuery, encryptUrl } from "@atlas/api/lib/db/internal";
23
+ import { maskConnectionUrl } from "@atlas/api/lib/security";
24
+ import { _resetWhitelists } from "@atlas/api/lib/semantic";
25
+ import { importFromDisk } from "@atlas/api/lib/semantic/sync";
26
+ import { getSemanticRoot } from "@atlas/api/lib/semantic/files";
27
+ import { ErrorSchema } from "./shared-schemas";
28
+ import { standardAuth, requestContext, type AuthEnv } from "./middleware";
29
+ import path from "path";
30
+ import { existsSync } from "fs";
31
+
32
+ const log = createLogger("onboarding");
33
+
34
+ // ---------------------------------------------------------------------------
35
+ // Demo dataset types — each maps to a semantic layer directory on disk
36
+ // ---------------------------------------------------------------------------
37
+
38
+ type DemoType = "demo" | "cybersec" | "ecommerce";
39
+
40
+ const DEMO_LABELS: Record<DemoType, string> = {
41
+ demo: "SaaS CRM",
42
+ cybersec: "Sentinel Security (Cybersecurity SaaS)",
43
+ ecommerce: "NovaMart (E-commerce)",
44
+ };
45
+
46
+ /**
47
+ * Resolve the semantic layer source directory for a demo type.
48
+ *
49
+ * In Docker: demo → /app/semantic, cybersec → /app/data/cybersec-semantic, ecommerce → /app/data/ecommerce-semantic
50
+ * In dev: demo → {cwd}/semantic, cybersec → {cwd}/packages/cli/data/cybersec-semantic, etc.
51
+ */
52
+ function getDemoSemanticDir(demoType: DemoType): string {
53
+ if (demoType === "demo") return getSemanticRoot();
54
+
55
+ // Docker image has these at /app/data/{type}-semantic
56
+ const dockerPath = path.resolve(process.cwd(), "data", `${demoType}-semantic`);
57
+ // Dev fallback: packages/cli/data/{type}-semantic
58
+ const devPath = path.resolve(process.cwd(), "packages", "cli", "data", `${demoType}-semantic`);
59
+
60
+ // Check Docker path first (production), then dev path
61
+ if (existsSync(path.join(dockerPath, "entities"))) return dockerPath;
62
+ if (existsSync(path.join(devPath, "entities"))) return devPath;
63
+
64
+ throw new Error(
65
+ `Semantic layer not found for demo type "${demoType}". ` +
66
+ `Checked: ${dockerPath}/entities, ${devPath}/entities`,
67
+ );
68
+ }
69
+
70
+ /** Valid connection ID: lowercase alphanumeric, hyphens, underscores, 1-64 chars. Must not start with underscore (reserved for internal IDs). */
71
+ const CONNECTION_ID_PATTERN = /^[a-z][a-z0-9_-]{0,62}[a-z0-9]$/;
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Schemas
75
+ // ---------------------------------------------------------------------------
76
+
77
+
78
+ const TestConnectionRequestSchema = z.object({
79
+ url: z.string().min(1, "Database URL is required."),
80
+ });
81
+
82
+ const TestConnectionResponseSchema = z.object({
83
+ status: z.string(),
84
+ latencyMs: z.number(),
85
+ dbType: z.string(),
86
+ maskedUrl: z.string(),
87
+ });
88
+
89
+ const CompleteOnboardingRequestSchema = z.object({
90
+ url: z.string().min(1, "Database URL is required."),
91
+ connectionId: z.string().optional(),
92
+ });
93
+
94
+ const CompleteOnboardingResponseSchema = z.object({
95
+ connectionId: z.string(),
96
+ dbType: z.string(),
97
+ maskedUrl: z.string(),
98
+ });
99
+
100
+ const SocialProvidersResponseSchema = z.object({
101
+ providers: z.array(z.string()),
102
+ });
103
+
104
+ // ---------------------------------------------------------------------------
105
+ // Route definitions
106
+ // ---------------------------------------------------------------------------
107
+
108
+ const socialProvidersRoute = createRoute({
109
+ method: "get",
110
+ path: "/social-providers",
111
+ tags: ["Onboarding"],
112
+ summary: "List enabled social login providers",
113
+ description:
114
+ "Returns which OAuth providers (Google, GitHub, Microsoft) are configured so the signup page can render the correct buttons. Public endpoint — no authentication required.",
115
+ responses: {
116
+ 200: {
117
+ description: "List of enabled social providers",
118
+ content: { "application/json": { schema: SocialProvidersResponseSchema } },
119
+ },
120
+ },
121
+ });
122
+
123
+ const testConnectionRoute = createRoute({
124
+ method: "post",
125
+ path: "/test-connection",
126
+ tags: ["Onboarding"],
127
+ summary: "Test a database connection",
128
+ description:
129
+ "Validates the URL scheme, creates a temporary connection, runs a health check, and returns the result. " +
130
+ "The connection is not persisted. Requires managed auth mode and an authenticated session.",
131
+ request: {
132
+ body: {
133
+ content: { "application/json": { schema: TestConnectionRequestSchema } },
134
+ required: true,
135
+ },
136
+ },
137
+ responses: {
138
+ 200: {
139
+ description: "Connection test result",
140
+ content: { "application/json": { schema: TestConnectionResponseSchema } },
141
+ },
142
+ 400: {
143
+ description: "Invalid URL scheme or connection test failed",
144
+ content: { "application/json": { schema: ErrorSchema } },
145
+ },
146
+ 401: {
147
+ description: "Authentication required",
148
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
149
+ },
150
+ 404: {
151
+ description: "Onboarding requires managed auth mode",
152
+ content: { "application/json": { schema: ErrorSchema } },
153
+ },
154
+ 422: {
155
+ description: "Validation error (invalid request body)",
156
+ content: {
157
+ "application/json": {
158
+ schema: ErrorSchema.extend({ details: z.array(z.unknown()).optional() }),
159
+ },
160
+ },
161
+ },
162
+ 429: {
163
+ description: "Rate limit exceeded",
164
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
165
+ },
166
+ 500: {
167
+ description: "Internal server error",
168
+ content: { "application/json": { schema: ErrorSchema } },
169
+ },
170
+ },
171
+ });
172
+
173
+ const completeOnboardingRoute = createRoute({
174
+ method: "post",
175
+ path: "/complete",
176
+ tags: ["Onboarding"],
177
+ summary: "Complete workspace setup",
178
+ description:
179
+ "Finalizes onboarding by testing the connection, encrypting the URL, and persisting it to the internal database " +
180
+ "scoped to the user's active organization. Resets the semantic layer whitelist cache so new tables become queryable immediately.",
181
+ request: {
182
+ body: {
183
+ content: { "application/json": { schema: CompleteOnboardingRequestSchema } },
184
+ required: true,
185
+ },
186
+ },
187
+ responses: {
188
+ 201: {
189
+ description: "Connection saved and workspace setup complete",
190
+ content: { "application/json": { schema: CompleteOnboardingResponseSchema } },
191
+ },
192
+ 400: {
193
+ description: "Invalid URL, connection test failed, or no active organization",
194
+ content: { "application/json": { schema: ErrorSchema } },
195
+ },
196
+ 401: {
197
+ description: "Authentication required",
198
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
199
+ },
200
+ 404: {
201
+ description: "Onboarding requires managed auth mode and DATABASE_URL",
202
+ content: { "application/json": { schema: ErrorSchema } },
203
+ },
204
+ 409: {
205
+ description: "Connection ID already in use by another organization",
206
+ content: { "application/json": { schema: ErrorSchema } },
207
+ },
208
+ 422: {
209
+ description: "Validation error (invalid request body)",
210
+ content: {
211
+ "application/json": {
212
+ schema: ErrorSchema.extend({ details: z.array(z.unknown()).optional() }),
213
+ },
214
+ },
215
+ },
216
+ 429: {
217
+ description: "Rate limit exceeded",
218
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
219
+ },
220
+ 500: {
221
+ description: "Failed to encrypt or save connection",
222
+ content: { "application/json": { schema: ErrorSchema } },
223
+ },
224
+ },
225
+ });
226
+
227
+ const UseDemoResponseSchema = z.object({
228
+ connectionId: z.string(),
229
+ dbType: z.string(),
230
+ maskedUrl: z.string(),
231
+ entitiesImported: z.number(),
232
+ });
233
+
234
+ const UseDemoBodySchema = z.object({
235
+ demoType: z.enum(["demo", "cybersec", "ecommerce"]).optional().default("demo"),
236
+ });
237
+
238
+ const useDemoRoute = createRoute({
239
+ method: "post",
240
+ path: "/use-demo",
241
+ tags: ["Onboarding"],
242
+ summary: "Set up workspace with demo data",
243
+ description:
244
+ "Connects the workspace to the platform's default datasource (ATLAS_DATASOURCE_URL) and imports " +
245
+ "the semantic layer for the chosen demo dataset. Three datasets are available: " +
246
+ "'demo' (SaaS CRM, 3 tables), 'cybersec' (Sentinel Security, 62 tables), " +
247
+ "'ecommerce' (NovaMart, 52 tables). Defaults to 'demo' if not specified.",
248
+ request: {
249
+ body: {
250
+ required: false,
251
+ content: { "application/json": { schema: UseDemoBodySchema } },
252
+ },
253
+ },
254
+ responses: {
255
+ 201: {
256
+ description: "Demo connection saved, semantic layer imported",
257
+ content: { "application/json": { schema: UseDemoResponseSchema } },
258
+ },
259
+ 400: {
260
+ description: "No active organization or demo datasource not available",
261
+ content: { "application/json": { schema: ErrorSchema } },
262
+ },
263
+ 404: {
264
+ description: "Onboarding requires managed auth mode and DATABASE_URL",
265
+ content: { "application/json": { schema: ErrorSchema } },
266
+ },
267
+ 409: {
268
+ description: "Connection ID already in use by another organization",
269
+ content: { "application/json": { schema: ErrorSchema } },
270
+ },
271
+ 422: {
272
+ description: "Invalid request body",
273
+ content: { "application/json": { schema: ErrorSchema } },
274
+ },
275
+ 500: {
276
+ description: "Failed to set up demo connection",
277
+ content: { "application/json": { schema: ErrorSchema } },
278
+ },
279
+ },
280
+ });
281
+
282
+ // ---------------------------------------------------------------------------
283
+ // Router
284
+ // ---------------------------------------------------------------------------
285
+
286
+ const onboarding = new OpenAPIHono<AuthEnv>({ defaultHook: validationHook });
287
+
288
+ // Normalize JSON parse errors. Only catch SyntaxError (malformed JSON); let
289
+ // other 400s (e.g. Zod query/path param validation) propagate with their message.
290
+ onboarding.onError((err, c) => {
291
+ if (err instanceof HTTPException) {
292
+ if (err.res) return err.res;
293
+ if (err.status === 400) {
294
+ if (err.cause instanceof SyntaxError) {
295
+ log.warn("Malformed JSON body in request");
296
+ return c.json({ error: "invalid_request", message: "Invalid JSON body." }, 400);
297
+ }
298
+ return c.json({ error: "invalid_request", message: err.message || "Bad request." }, 400);
299
+ }
300
+ }
301
+ throw err;
302
+ });
303
+
304
+ // ---------------------------------------------------------------------------
305
+ // GET /social-providers — returns which social login providers are enabled
306
+ // (public — no auth middleware)
307
+ // ---------------------------------------------------------------------------
308
+
309
+ onboarding.openapi(socialProvidersRoute, (c) => {
310
+ const providers: string[] = [];
311
+ if (process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET) providers.push("google");
312
+ if (process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET) providers.push("github");
313
+ if (process.env.MICROSOFT_CLIENT_ID && process.env.MICROSOFT_CLIENT_SECRET) providers.push("microsoft");
314
+ return c.json({ providers }, 200);
315
+ });
316
+
317
+ // ---------------------------------------------------------------------------
318
+ // Apply auth middleware to all routes registered after this point
319
+ // ---------------------------------------------------------------------------
320
+
321
+ onboarding.use("/test-connection", standardAuth);
322
+ onboarding.use("/test-connection", requestContext);
323
+ onboarding.use("/complete", standardAuth);
324
+ onboarding.use("/complete", requestContext);
325
+ onboarding.use("/use-demo", standardAuth);
326
+ onboarding.use("/use-demo", requestContext);
327
+ onboarding.use("/tour-status", standardAuth);
328
+ onboarding.use("/tour-status", requestContext);
329
+ onboarding.use("/tour-complete", standardAuth);
330
+ onboarding.use("/tour-complete", requestContext);
331
+ onboarding.use("/tour-reset", standardAuth);
332
+ onboarding.use("/tour-reset", requestContext);
333
+
334
+ // ---------------------------------------------------------------------------
335
+ // POST /test-connection — test a datasource URL without persisting
336
+ // ---------------------------------------------------------------------------
337
+
338
+ onboarding.openapi(
339
+ testConnectionRoute,
340
+ async (c) => {
341
+ return runEffect(c, Effect.gen(function* () {
342
+ const { requestId } = yield* RequestContext;
343
+
344
+ if (detectAuthMode() !== "managed") {
345
+ return c.json({ error: "not_available", message: "Onboarding requires managed auth mode.", requestId }, 404);
346
+ }
347
+
348
+ const { url } = c.req.valid("json");
349
+
350
+ // Validate URL scheme
351
+ let dbType: string;
352
+ try {
353
+ dbType = detectDBType(url);
354
+ } catch (err) {
355
+ log.warn({ err: err instanceof Error ? err.message : String(err), requestId }, "Invalid database URL scheme");
356
+ return c.json({
357
+ error: "invalid_url",
358
+ message: "Unsupported database URL scheme. Use postgresql:// or mysql://.",
359
+ }, 400);
360
+ }
361
+
362
+ // Register a temporary connection, test it, then always clean up
363
+ const tempId = `_onboard_${Date.now()}`;
364
+ return yield* Effect.tryPromise({
365
+ try: async () => {
366
+ connections.register(tempId, { url });
367
+ const result = await connections.healthCheck(tempId);
368
+ return c.json({
369
+ status: result.status,
370
+ latencyMs: result.latencyMs,
371
+ dbType,
372
+ maskedUrl: maskConnectionUrl(url),
373
+ }, 200);
374
+ },
375
+ catch: (err) => err instanceof Error ? err : new Error(String(err)),
376
+ }).pipe(
377
+ Effect.catchAll((err) => {
378
+ log.warn({ err: err.message, requestId }, "Connection test failed");
379
+ return Effect.succeed(c.json({
380
+ error: "connection_failed",
381
+ message: "Connection test failed. Check the URL, credentials, and that the database is reachable.",
382
+ }, 400));
383
+ }),
384
+ Effect.ensuring(Effect.sync(() => {
385
+ if (connections.has(tempId)) {
386
+ connections.unregister(tempId);
387
+ }
388
+ })),
389
+ );
390
+ }), { label: "test connection" });
391
+ },
392
+ (result, c) => {
393
+ if (!result.success) {
394
+ return c.json(
395
+ { error: "validation_error", message: "Invalid request body.", details: result.error.issues },
396
+ 422,
397
+ );
398
+ }
399
+ },
400
+ );
401
+
402
+ // ---------------------------------------------------------------------------
403
+ // POST /complete — finalize workspace setup
404
+ // ---------------------------------------------------------------------------
405
+
406
+ onboarding.openapi(
407
+ completeOnboardingRoute,
408
+ async (c) => {
409
+ return runEffect(c, Effect.gen(function* () {
410
+ const { requestId } = yield* RequestContext;
411
+ const { user, orgId } = yield* AuthContext;
412
+
413
+ if (detectAuthMode() !== "managed") {
414
+ return c.json({ error: "not_available", message: "Onboarding requires managed auth mode.", requestId }, 404);
415
+ }
416
+
417
+ if (!hasInternalDB()) {
418
+ return c.json({ error: "not_available", message: "Onboarding requires an internal database (DATABASE_URL).", requestId }, 404);
419
+ }
420
+
421
+ if (!orgId) {
422
+ return c.json({ error: "no_organization", message: "No active organization. Create a workspace first." }, 400);
423
+ }
424
+
425
+ const { url, connectionId: rawConnectionId } = c.req.valid("json");
426
+
427
+ const id = typeof rawConnectionId === "string" && rawConnectionId.trim()
428
+ ? rawConnectionId.trim()
429
+ : "default";
430
+
431
+ // Validate connectionId format (skip for default)
432
+ if (id !== "default" && !CONNECTION_ID_PATTERN.test(id)) {
433
+ return c.json({
434
+ error: "invalid_request",
435
+ message: "Connection ID must be 2-64 lowercase alphanumeric characters, hyphens, or underscores.",
436
+ }, 400);
437
+ }
438
+
439
+ // Validate URL scheme
440
+ let dbType: string;
441
+ try {
442
+ dbType = detectDBType(url);
443
+ } catch (err) {
444
+ log.warn({ err: err instanceof Error ? err.message : String(err), requestId }, "Invalid database URL scheme");
445
+ return c.json({
446
+ error: "invalid_url",
447
+ message: "Unsupported database URL scheme. Use postgresql:// or mysql://.",
448
+ }, 400);
449
+ }
450
+
451
+ // Test the connection before persisting
452
+ const tempId = `_onboard_complete_${Date.now()}`;
453
+ const testResult = yield* Effect.tryPromise({
454
+ try: async () => {
455
+ connections.register(tempId, { url });
456
+ await connections.healthCheck(tempId);
457
+ return { ok: true as const };
458
+ },
459
+ catch: (err) => err instanceof Error ? err : new Error(String(err)),
460
+ }).pipe(
461
+ Effect.catchAll((err) => {
462
+ log.warn({ err: err.message, requestId }, "Connection test failed during onboarding");
463
+ return Effect.succeed({ ok: false as const, response: c.json({
464
+ error: "connection_failed",
465
+ message: "Connection test failed. Check the URL, credentials, and that the database is reachable.",
466
+ }, 400) });
467
+ }),
468
+ Effect.ensuring(Effect.sync(() => {
469
+ if (connections.has(tempId)) connections.unregister(tempId);
470
+ })),
471
+ );
472
+ if (!testResult.ok) {
473
+ return testResult.response;
474
+ }
475
+
476
+ // Encrypt and persist to internal DB
477
+ let encryptedUrl: string;
478
+ try {
479
+ encryptedUrl = encryptUrl(url);
480
+ } catch (err) {
481
+ log.error({ err: err instanceof Error ? err.message : String(err), requestId }, "Failed to encrypt connection URL during onboarding");
482
+ return c.json({ error: "encryption_failed", message: "Failed to encrypt connection URL.", requestId }, 500);
483
+ }
484
+
485
+ // Org-scoped upsert: only update if the existing row belongs to the same org
486
+ const upsertResult = yield* Effect.tryPromise({
487
+ try: () => internalQuery<{ id: string }>(
488
+ `INSERT INTO connections (id, url, type, description, org_id)
489
+ VALUES ($1, $2, $3, $4, $5)
490
+ ON CONFLICT (id) DO UPDATE SET url = $2, type = $3, org_id = $5, updated_at = NOW()
491
+ WHERE connections.org_id = $5 OR connections.org_id IS NULL
492
+ RETURNING id`,
493
+ [id, encryptedUrl, dbType, `${dbType} datasource`, orgId],
494
+ ),
495
+ catch: (err) => err instanceof Error ? err : new Error(String(err)),
496
+ }).pipe(Effect.catchAll((err) => {
497
+ log.error({ err, requestId }, "Failed to persist onboarding connection");
498
+ return Effect.succeed(null);
499
+ }));
500
+
501
+ if (upsertResult === null) {
502
+ return c.json({ error: "internal_error", message: "Failed to save connection.", requestId }, 500);
503
+ }
504
+ if (upsertResult.length === 0) {
505
+ return c.json({
506
+ error: "conflict",
507
+ message: `Connection ID "${id}" is already in use by another organization.`,
508
+ }, 409);
509
+ }
510
+
511
+ // Register the connection in the runtime registry
512
+ try {
513
+ if (connections.has(id)) connections.unregister(id);
514
+ connections.register(id, { url, description: `${dbType} datasource` });
515
+ } catch (err) {
516
+ log.warn({ err: err instanceof Error ? err.message : String(err), requestId }, "Connection saved but runtime registration failed — will load on next restart");
517
+ }
518
+
519
+ _resetWhitelists();
520
+
521
+ log.info({ requestId, connectionId: id, orgId, dbType, userId: user?.id }, "Onboarding complete — connection saved");
522
+
523
+ // Trigger onboarding milestone: database connected (fire-and-forget)
524
+ // AtlasUser.label is the user's email in managed auth mode.
525
+ if (user?.id && user.label?.includes("@")) {
526
+ yield* Effect.tryPromise({
527
+ try: async () => {
528
+ const { onDatabaseConnected } = await import("@atlas/api/lib/email/hooks");
529
+ onDatabaseConnected({
530
+ userId: user.id,
531
+ email: user.label!,
532
+ orgId,
533
+ });
534
+ },
535
+ catch: (err) => err instanceof Error ? err : new Error(String(err)),
536
+ }).pipe(Effect.catchAll((err) => {
537
+ log.debug({ err: err.message }, "Onboarding email hook not available");
538
+ return Effect.void;
539
+ }));
540
+ }
541
+
542
+ return c.json({
543
+ connectionId: id,
544
+ dbType,
545
+ maskedUrl: maskConnectionUrl(url),
546
+ }, 201);
547
+ }), { label: "complete onboarding" });
548
+ },
549
+ (result, c) => {
550
+ if (!result.success) {
551
+ return c.json(
552
+ { error: "validation_error", message: "Invalid request body.", details: result.error.issues },
553
+ 422,
554
+ );
555
+ }
556
+ },
557
+ );
558
+
559
+ // ---------------------------------------------------------------------------
560
+ // POST /use-demo — connect workspace to the default datasource + import semantic layer
561
+ // ---------------------------------------------------------------------------
562
+
563
+ onboarding.openapi(
564
+ useDemoRoute,
565
+ async (c) => {
566
+ return runEffect(c, Effect.gen(function* () {
567
+ const { requestId } = yield* RequestContext;
568
+ const { user, orgId } = yield* AuthContext;
569
+
570
+ if (detectAuthMode() !== "managed") {
571
+ return c.json({ error: "not_available", message: "Onboarding requires managed auth mode.", requestId }, 404);
572
+ }
573
+
574
+ if (!hasInternalDB()) {
575
+ return c.json({ error: "not_available", message: "Onboarding requires an internal database (DATABASE_URL).", requestId }, 404);
576
+ }
577
+
578
+ if (!orgId) {
579
+ return c.json({ error: "no_organization", message: "No active organization. Create a workspace first." }, 400);
580
+ }
581
+
582
+ const { demoType } = c.req.valid("json");
583
+
584
+ const url = resolveDatasourceUrl();
585
+ if (!url) {
586
+ return c.json({ error: "no_demo_datasource", message: "No demo datasource configured. Set ATLAS_DATASOURCE_URL." }, 400);
587
+ }
588
+
589
+ const id = "default";
590
+ let dbType: string;
591
+ try {
592
+ dbType = detectDBType(url);
593
+ } catch (err) {
594
+ log.error({ err: err instanceof Error ? err.message : String(err), requestId }, "Demo datasource URL has unsupported scheme");
595
+ return c.json({ error: "invalid_datasource", message: "Demo datasource URL has an unsupported scheme." }, 500);
596
+ }
597
+
598
+ // Encrypt and persist (same logic as /complete)
599
+ let encryptedUrl: string;
600
+ try {
601
+ encryptedUrl = encryptUrl(url);
602
+ } catch (err) {
603
+ log.error({ err: err instanceof Error ? err.message : String(err), requestId }, "Failed to encrypt demo connection URL");
604
+ return c.json({ error: "encryption_failed", message: "Failed to encrypt connection URL.", requestId }, 500);
605
+ }
606
+
607
+ const demoLabel = DEMO_LABELS[demoType];
608
+ const upsertResult = yield* Effect.tryPromise({
609
+ try: () => internalQuery<{ id: string }>(
610
+ `INSERT INTO connections (id, url, type, description, org_id)
611
+ VALUES ($1, $2, $3, $4, $5)
612
+ ON CONFLICT (id) DO UPDATE SET url = $2, type = $3, description = $4, org_id = $5, updated_at = NOW()
613
+ WHERE connections.org_id = $5 OR connections.org_id IS NULL
614
+ RETURNING id`,
615
+ [id, encryptedUrl, dbType, `${demoLabel} — demo ${dbType} datasource`, orgId],
616
+ ),
617
+ catch: (err) => err instanceof Error ? err : new Error(String(err)),
618
+ }).pipe(Effect.catchAll((err) => {
619
+ log.error({ err, requestId }, "Failed to persist demo connection");
620
+ return Effect.succeed(null);
621
+ }));
622
+
623
+ if (upsertResult === null) {
624
+ return c.json({ error: "internal_error", message: "Failed to save connection.", requestId }, 500);
625
+ }
626
+ if (upsertResult.length === 0) {
627
+ return c.json({ error: "conflict", message: "Connection ID 'default' is already in use by another organization." }, 409);
628
+ }
629
+
630
+ // Register in runtime
631
+ try {
632
+ if (connections.has(id)) connections.unregister(id);
633
+ connections.register(id, { url, description: `${demoLabel} — demo ${dbType} datasource` });
634
+ } catch (err) {
635
+ log.warn({ err: err instanceof Error ? err.message : String(err), requestId }, "Demo connection saved but runtime registration failed");
636
+ }
637
+
638
+ // Resolve and import the semantic layer for the chosen demo dataset
639
+ let semanticDir: string;
640
+ try {
641
+ semanticDir = getDemoSemanticDir(demoType);
642
+ } catch (err) {
643
+ log.error({ err: err instanceof Error ? err.message : String(err), requestId, demoType }, "Semantic layer not found for demo type");
644
+ return c.json({
645
+ error: "demo_not_available",
646
+ message: `Demo dataset "${demoType}" is not installed on this server. Contact the platform administrator.`,
647
+ requestId,
648
+ }, 500);
649
+ }
650
+
651
+ const importResult = yield* Effect.tryPromise({
652
+ try: () => importFromDisk(orgId, { sourceDir: semanticDir, connectionId: "default" }),
653
+ catch: (err) => err instanceof Error ? err : new Error(String(err)),
654
+ }).pipe(Effect.catchAll((err) => {
655
+ log.error({ err: err.message, requestId, demoType, semanticDir }, "Semantic layer import failed");
656
+ return Effect.succeed(null);
657
+ }));
658
+
659
+ if (importResult === null) {
660
+ return c.json({
661
+ error: "import_failed",
662
+ message: `Failed to import semantic layer for "${demoType}" dataset. The connection was saved but the workspace needs manual setup.`,
663
+ requestId,
664
+ }, 500);
665
+ }
666
+
667
+ const entitiesImported = importResult.imported;
668
+ if (entitiesImported > 0) {
669
+ log.info({ orgId, demoType, imported: importResult.imported, skipped: importResult.skipped, requestId }, "Imported semantic layer for demo workspace");
670
+ }
671
+
672
+ _resetWhitelists();
673
+
674
+ log.info({ requestId, orgId, demoType, dbType, userId: user?.id, entitiesImported }, "Demo onboarding complete");
675
+
676
+ return c.json({
677
+ connectionId: id,
678
+ dbType,
679
+ maskedUrl: maskConnectionUrl(url),
680
+ entitiesImported,
681
+ }, 201);
682
+ }), { label: "use demo data" });
683
+ },
684
+ (result, c) => {
685
+ if (!result.success) {
686
+ return c.json(
687
+ { error: "validation_error", message: "Invalid request body.", details: result.error.issues },
688
+ 422,
689
+ );
690
+ }
691
+ },
692
+ );
693
+
694
+ // ---------------------------------------------------------------------------
695
+ // Region selection during signup
696
+ // ---------------------------------------------------------------------------
697
+
698
+ type ResidencyModule = typeof import("@atlas/ee/platform/residency");
699
+
700
+ async function loadResidency(): Promise<ResidencyModule | null> {
701
+ try {
702
+ return await import("@atlas/ee/platform/residency");
703
+ } catch (err) {
704
+ if (
705
+ err != null &&
706
+ typeof err === "object" &&
707
+ "code" in err &&
708
+ (err as NodeJS.ErrnoException).code === "MODULE_NOT_FOUND"
709
+ ) {
710
+ return null;
711
+ }
712
+ throw err;
713
+ }
714
+ }
715
+
716
+ const OnboardingRegionSchema = z.object({
717
+ id: z.string(),
718
+ label: z.string(),
719
+ isDefault: z.boolean(),
720
+ });
721
+
722
+ const OnboardingRegionsResponseSchema = z.object({
723
+ configured: z.boolean(),
724
+ defaultRegion: z.string(),
725
+ availableRegions: z.array(OnboardingRegionSchema),
726
+ });
727
+
728
+ const AssignRegionBodySchema = z.object({
729
+ region: z.string().min(1),
730
+ });
731
+
732
+ const AssignRegionResponseSchema = z.object({
733
+ workspaceId: z.string(),
734
+ region: z.string(),
735
+ assignedAt: z.string(),
736
+ });
737
+
738
+ const getRegionsRoute = createRoute({
739
+ method: "get",
740
+ path: "/regions",
741
+ tags: ["Onboarding"],
742
+ summary: "List available data residency regions",
743
+ description:
744
+ "Returns available data residency regions for the signup flow. " +
745
+ "If residency is not configured (self-hosted or EE not available), " +
746
+ "returns configured=false so the frontend can skip the region step.",
747
+ responses: {
748
+ 200: {
749
+ description: "Available regions",
750
+ content: { "application/json": { schema: OnboardingRegionsResponseSchema } },
751
+ },
752
+ 401: {
753
+ description: "Authentication required",
754
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
755
+ },
756
+ 404: {
757
+ description: "Onboarding requires managed auth mode",
758
+ content: { "application/json": { schema: ErrorSchema } },
759
+ },
760
+ 500: {
761
+ description: "Internal server error",
762
+ content: { "application/json": { schema: ErrorSchema } },
763
+ },
764
+ },
765
+ });
766
+
767
+ const assignRegionRoute = createRoute({
768
+ method: "post",
769
+ path: "/assign-region",
770
+ tags: ["Onboarding"],
771
+ summary: "Assign data residency region during signup",
772
+ description:
773
+ "Assigns a data residency region to the user's workspace during the signup flow. " +
774
+ "This must be called before connecting a database. The region cannot be changed " +
775
+ "after assignment.",
776
+ request: {
777
+ body: {
778
+ content: { "application/json": { schema: AssignRegionBodySchema } },
779
+ required: true,
780
+ },
781
+ },
782
+ responses: {
783
+ 200: {
784
+ description: "Region assigned",
785
+ content: { "application/json": { schema: AssignRegionResponseSchema } },
786
+ },
787
+ 400: {
788
+ description: "Invalid region or no active organization",
789
+ content: { "application/json": { schema: ErrorSchema } },
790
+ },
791
+ 401: {
792
+ description: "Authentication required",
793
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
794
+ },
795
+ 404: {
796
+ description: "Onboarding requires managed auth mode or residency not configured",
797
+ content: { "application/json": { schema: ErrorSchema } },
798
+ },
799
+ 409: {
800
+ description: "Region already assigned (immutable)",
801
+ content: { "application/json": { schema: ErrorSchema } },
802
+ },
803
+ 422: {
804
+ description: "Validation error",
805
+ content: {
806
+ "application/json": {
807
+ schema: ErrorSchema.extend({ details: z.array(z.unknown()).optional() }),
808
+ },
809
+ },
810
+ },
811
+ 503: {
812
+ description: "Service unavailable (no internal database)",
813
+ content: { "application/json": { schema: ErrorSchema } },
814
+ },
815
+ 500: {
816
+ description: "Internal server error",
817
+ content: { "application/json": { schema: ErrorSchema } },
818
+ },
819
+ },
820
+ });
821
+
822
+ onboarding.use("/regions", standardAuth);
823
+ onboarding.use("/regions", requestContext);
824
+ onboarding.use("/assign-region", standardAuth);
825
+ onboarding.use("/assign-region", requestContext);
826
+
827
+ // GET /regions — available data residency regions for signup
828
+
829
+ onboarding.openapi(getRegionsRoute, async (c) => {
830
+ return runEffect(c, Effect.gen(function* () {
831
+ const { requestId } = yield* RequestContext;
832
+
833
+ if (detectAuthMode() !== "managed") {
834
+ return c.json({ error: "not_available", message: "Onboarding requires managed auth mode.", requestId }, 404);
835
+ }
836
+
837
+ const mod = yield* Effect.promise(() => loadResidency());
838
+ if (!mod) {
839
+ return c.json({ configured: false, defaultRegion: "none", availableRegions: [] }, 200);
840
+ }
841
+
842
+ try {
843
+ const defaultRegion = mod.getDefaultRegion();
844
+ const regions = mod.getConfiguredRegions();
845
+ const availableRegions = Object.entries(regions).map(([id, cfg]) => ({
846
+ id,
847
+ label: cfg.label,
848
+ isDefault: id === defaultRegion,
849
+ }));
850
+ return c.json({ configured: true, defaultRegion, availableRegions }, 200);
851
+ } catch (err) {
852
+ if (err instanceof mod.ResidencyError && err.code === "not_configured") {
853
+ return c.json({ configured: false, defaultRegion: "none", availableRegions: [] }, 200);
854
+ }
855
+ throw err;
856
+ }
857
+ }), { label: "get onboarding regions" });
858
+ });
859
+
860
+ // POST /assign-region — assign region during signup
861
+
862
+ onboarding.openapi(
863
+ assignRegionRoute,
864
+ async (c) => {
865
+ return runEffect(c, Effect.gen(function* () {
866
+ const { requestId } = yield* RequestContext;
867
+ const { orgId } = yield* AuthContext;
868
+
869
+ if (detectAuthMode() !== "managed") {
870
+ return c.json({ error: "not_available", message: "Onboarding requires managed auth mode.", requestId }, 404);
871
+ }
872
+
873
+ if (!orgId) {
874
+ return c.json({ error: "no_organization", message: "No active organization. Create a workspace first.", requestId }, 400);
875
+ }
876
+
877
+ const { region } = c.req.valid("json");
878
+
879
+ const mod = yield* Effect.promise(() => loadResidency());
880
+ if (!mod) {
881
+ return c.json({ error: "not_available", message: "Data residency is not available in this deployment.", requestId }, 404);
882
+ }
883
+
884
+ try {
885
+ const result = yield* Effect.promise(() => mod.assignWorkspaceRegion(orgId, region));
886
+ log.info({ orgId, region, requestId }, "Workspace region assigned during signup");
887
+ return c.json(result, 200);
888
+ } catch (err) {
889
+ if (err instanceof mod.ResidencyError) {
890
+ switch (err.code) {
891
+ case "invalid_region":
892
+ return c.json({ error: "invalid_region", message: err.message, requestId }, 400);
893
+ case "already_assigned":
894
+ return c.json({ error: "already_assigned", message: err.message, requestId }, 409);
895
+ case "workspace_not_found":
896
+ return c.json({ error: "workspace_not_found", message: err.message, requestId }, 404);
897
+ case "no_internal_db":
898
+ return c.json({ error: "no_internal_db", message: err.message, requestId }, 503);
899
+ case "not_configured":
900
+ return c.json({ error: "not_configured", message: err.message, requestId }, 404);
901
+ default:
902
+ log.warn({ code: err.code, requestId }, "Unhandled ResidencyError code");
903
+ throw err;
904
+ }
905
+ }
906
+ throw err;
907
+ }
908
+ }), { label: "assign region during signup" });
909
+ },
910
+ (result, c) => {
911
+ if (!result.success) {
912
+ return c.json(
913
+ { error: "validation_error", message: "Invalid request body.", details: result.error.issues },
914
+ 422,
915
+ );
916
+ }
917
+ },
918
+ );
919
+
920
+ // ---------------------------------------------------------------------------
921
+ // Tour status & completion
922
+ // ---------------------------------------------------------------------------
923
+
924
+ const TourStatusResponseSchema = z.object({
925
+ tourCompleted: z.boolean(),
926
+ tourCompletedAt: z.string().nullable(),
927
+ });
928
+
929
+ const tourStatusRoute = createRoute({
930
+ method: "get",
931
+ path: "/tour-status",
932
+ tags: ["Onboarding"],
933
+ summary: "Get guided tour completion status",
934
+ description:
935
+ "Returns whether the authenticated user has completed the guided tour. " +
936
+ "Used on app load to decide whether to auto-start the tour.",
937
+ responses: {
938
+ 200: {
939
+ description: "Tour completion status",
940
+ content: { "application/json": { schema: TourStatusResponseSchema } },
941
+ },
942
+ 401: {
943
+ description: "Authentication required",
944
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
945
+ },
946
+ 404: {
947
+ description: "Requires managed auth mode and internal database",
948
+ content: { "application/json": { schema: ErrorSchema } },
949
+ },
950
+ 500: {
951
+ description: "Internal server error",
952
+ content: { "application/json": { schema: ErrorSchema } },
953
+ },
954
+ },
955
+ });
956
+
957
+ const tourCompleteRoute = createRoute({
958
+ method: "post",
959
+ path: "/tour-complete",
960
+ tags: ["Onboarding"],
961
+ summary: "Mark guided tour as completed",
962
+ description:
963
+ "Records that the authenticated user has completed (or dismissed) the guided tour. " +
964
+ "Idempotent — calling multiple times is safe.",
965
+ responses: {
966
+ 200: {
967
+ description: "Tour marked as completed",
968
+ content: { "application/json": { schema: TourStatusResponseSchema } },
969
+ },
970
+ 401: {
971
+ description: "Authentication required",
972
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
973
+ },
974
+ 404: {
975
+ description: "Requires managed auth mode and internal database",
976
+ content: { "application/json": { schema: ErrorSchema } },
977
+ },
978
+ 500: {
979
+ description: "Internal server error",
980
+ content: { "application/json": { schema: ErrorSchema } },
981
+ },
982
+ },
983
+ });
984
+
985
+ const tourResetRoute = createRoute({
986
+ method: "post",
987
+ path: "/tour-reset",
988
+ tags: ["Onboarding"],
989
+ summary: "Reset guided tour so it can be replayed",
990
+ description:
991
+ "Clears the tour completion timestamp for the authenticated user, allowing " +
992
+ "the guided tour to be triggered again.",
993
+ responses: {
994
+ 200: {
995
+ description: "Tour reset successfully",
996
+ content: { "application/json": { schema: TourStatusResponseSchema } },
997
+ },
998
+ 401: {
999
+ description: "Authentication required",
1000
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
1001
+ },
1002
+ 404: {
1003
+ description: "Requires managed auth mode and internal database",
1004
+ content: { "application/json": { schema: ErrorSchema } },
1005
+ },
1006
+ 500: {
1007
+ description: "Internal server error",
1008
+ content: { "application/json": { schema: ErrorSchema } },
1009
+ },
1010
+ },
1011
+ });
1012
+
1013
+ // ---------------------------------------------------------------------------
1014
+ // GET /tour-status
1015
+ // ---------------------------------------------------------------------------
1016
+
1017
+ onboarding.openapi(tourStatusRoute, async (c) => {
1018
+ return runEffect(c, Effect.gen(function* () {
1019
+ const { requestId } = yield* RequestContext;
1020
+ const { user } = yield* AuthContext;
1021
+
1022
+ if (detectAuthMode() !== "managed") {
1023
+ return c.json({ error: "not_available", message: "Tour tracking requires managed auth mode.", requestId }, 404);
1024
+ }
1025
+ if (!hasInternalDB()) {
1026
+ return c.json({ error: "not_available", message: "Tour tracking requires an internal database (DATABASE_URL).", requestId }, 404);
1027
+ }
1028
+
1029
+ const userId = user?.id;
1030
+ if (!userId) {
1031
+ return c.json({ error: "auth_error", message: "No user ID in session.", requestId }, 401);
1032
+ }
1033
+
1034
+ const rows = yield* Effect.promise(() => internalQuery<{ tour_completed_at: string | null }>(
1035
+ `SELECT tour_completed_at FROM user_onboarding WHERE user_id = $1`,
1036
+ [userId],
1037
+ ));
1038
+ const row = rows[0];
1039
+ return c.json({
1040
+ tourCompleted: !!row?.tour_completed_at,
1041
+ tourCompletedAt: row?.tour_completed_at ?? null,
1042
+ }, 200);
1043
+ }), { label: "fetch tour status" });
1044
+ });
1045
+
1046
+ // ---------------------------------------------------------------------------
1047
+ // POST /tour-complete
1048
+ // ---------------------------------------------------------------------------
1049
+
1050
+ onboarding.openapi(tourCompleteRoute, async (c) => {
1051
+ return runEffect(c, Effect.gen(function* () {
1052
+ const { requestId } = yield* RequestContext;
1053
+ const { user } = yield* AuthContext;
1054
+
1055
+ if (detectAuthMode() !== "managed") {
1056
+ return c.json({ error: "not_available", message: "Tour tracking requires managed auth mode.", requestId }, 404);
1057
+ }
1058
+ if (!hasInternalDB()) {
1059
+ return c.json({ error: "not_available", message: "Tour tracking requires an internal database (DATABASE_URL).", requestId }, 404);
1060
+ }
1061
+
1062
+ const userId = user?.id;
1063
+ if (!userId) {
1064
+ return c.json({ error: "auth_error", message: "No user ID in session.", requestId }, 401);
1065
+ }
1066
+
1067
+ const now = new Date().toISOString();
1068
+ yield* Effect.promise(() => internalQuery(
1069
+ `INSERT INTO user_onboarding (user_id, tour_completed_at)
1070
+ VALUES ($1, $2)
1071
+ ON CONFLICT (user_id) DO UPDATE SET tour_completed_at = $2`,
1072
+ [userId, now],
1073
+ ));
1074
+ log.info({ requestId, userId }, "Tour marked as completed");
1075
+ return c.json({ tourCompleted: true, tourCompletedAt: now }, 200);
1076
+ }), { label: "save tour completion" });
1077
+ });
1078
+
1079
+ // ---------------------------------------------------------------------------
1080
+ // POST /tour-reset
1081
+ // ---------------------------------------------------------------------------
1082
+
1083
+ onboarding.openapi(tourResetRoute, async (c) => {
1084
+ return runEffect(c, Effect.gen(function* () {
1085
+ const { requestId } = yield* RequestContext;
1086
+ const { user } = yield* AuthContext;
1087
+
1088
+ if (detectAuthMode() !== "managed") {
1089
+ return c.json({ error: "not_available", message: "Tour tracking requires managed auth mode.", requestId }, 404);
1090
+ }
1091
+ if (!hasInternalDB()) {
1092
+ return c.json({ error: "not_available", message: "Tour tracking requires an internal database (DATABASE_URL).", requestId }, 404);
1093
+ }
1094
+
1095
+ const userId = user?.id;
1096
+ if (!userId) {
1097
+ return c.json({ error: "auth_error", message: "No user ID in session.", requestId }, 401);
1098
+ }
1099
+
1100
+ yield* Effect.promise(() => internalQuery(
1101
+ `UPDATE user_onboarding SET tour_completed_at = NULL WHERE user_id = $1`,
1102
+ [userId],
1103
+ ));
1104
+ log.info({ requestId, userId }, "Tour reset for replay");
1105
+ return c.json({ tourCompleted: false, tourCompletedAt: null }, 200);
1106
+ }), { label: "reset tour" });
1107
+ });
1108
+
1109
+ export { onboarding };