@useatlas/create 0.0.6 → 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
@@ -2,18 +2,19 @@
2
2
  * Scheduled tasks REST routes — CRUD + trigger + run history.
3
3
  *
4
4
  * Gated behind ATLAS_SCHEDULER_ENABLED=true (conditional mount in index.ts).
5
- * Follows the same auth rate limit → withRequestContext pattern as conversations.ts.
5
+ * CRUD routes use `adminAuth` + `requireOrgContext` middleware (admin/owner
6
+ * role required, org-scoped). The `/tick` endpoint uses its own cron-secret
7
+ * auth and is registered on the outer app so it bypasses user-auth middleware.
6
8
  */
7
9
 
8
- import { Hono } from "hono";
10
+ import { OpenAPIHono, createRoute } from "@hono/zod-openapi";
11
+ import { Effect } from "effect";
12
+ import { runEffect } from "@atlas/api/lib/effect/hono";
13
+ import { RequestContext, AuthContext } from "@atlas/api/lib/effect/services";
14
+ import { validationHook } from "./validation-hook";
15
+ import { HTTPException } from "hono/http-exception";
9
16
  import { z } from "zod";
10
- import { createLogger, withRequestContext } from "@atlas/api/lib/logger";
11
- import type { AuthResult } from "@atlas/api/lib/auth/types";
12
- import {
13
- authenticateRequest,
14
- checkRateLimit,
15
- getClientIP,
16
- } from "@atlas/api/lib/auth/middleware";
17
+ import { createLogger } from "@atlas/api/lib/logger";
17
18
  import { hasInternalDB } from "@atlas/api/lib/db/internal";
18
19
  import {
19
20
  createScheduledTask,
@@ -22,11 +23,15 @@ import {
22
23
  updateScheduledTask,
23
24
  deleteScheduledTask,
24
25
  listTaskRuns,
26
+ listAllRuns,
25
27
  validateCronExpression,
26
28
  type CrudFailReason,
27
29
  } from "@atlas/api/lib/scheduled-tasks";
28
- import { DELIVERY_CHANNELS } from "@atlas/api/lib/scheduled-task-types";
30
+ import { DELIVERY_CHANNELS, RUN_STATUSES, type RunStatus } from "@atlas/api/lib/scheduled-task-types";
29
31
  import { ACTION_APPROVAL_MODES } from "@atlas/api/lib/action-types";
32
+ import { type AuthEnv } from "./middleware";
33
+ import { ErrorSchema, parsePagination } from "./shared-schemas";
34
+ import { createAdminRouter, requireOrgContext } from "./admin-router";
30
35
 
31
36
  const log = createLogger("scheduled-tasks-routes");
32
37
 
@@ -40,7 +45,7 @@ const RecipientSchema = z.discriminatedUnion("type", [
40
45
  z.object({ type: z.literal("webhook"), url: z.string().url(), headers: z.record(z.string(), z.string()).optional() }),
41
46
  ]);
42
47
 
43
- export const CreateScheduledTaskSchema = z.object({
48
+ const CreateScheduledTaskSchema = z.object({
44
49
  name: z.string().min(1).max(200),
45
50
  question: z.string().min(1).max(2000),
46
51
  cronExpression: z.string().min(1),
@@ -50,7 +55,7 @@ export const CreateScheduledTaskSchema = z.object({
50
55
  approvalMode: z.enum(ACTION_APPROVAL_MODES).default("auto"),
51
56
  });
52
57
 
53
- export const UpdateScheduledTaskSchema = z.object({
58
+ const UpdateScheduledTaskSchema = z.object({
54
59
  name: z.string().min(1).max(200).optional(),
55
60
  question: z.string().min(1).max(2000).optional(),
56
61
  cronExpression: z.string().min(1).optional(),
@@ -63,405 +68,496 @@ export const UpdateScheduledTaskSchema = z.object({
63
68
 
64
69
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
65
70
 
66
- function crudFailResponse(reason: CrudFailReason) {
71
+
72
+ function crudFailResponse(reason: CrudFailReason, requestId?: string) {
67
73
  switch (reason) {
68
74
  case "no_db":
69
75
  return { body: { error: "not_available", message: "Scheduled tasks require an internal database." }, status: 404 as const };
70
76
  case "not_found":
71
77
  return { body: { error: "not_found", message: "Scheduled task not found." }, status: 404 as const };
72
78
  case "error":
73
- return { body: { error: "internal_error", message: "A database error occurred. Please try again." }, status: 500 as const };
79
+ return { body: { error: "internal_error", message: "A database error occurred. Please try again.", ...(requestId && { requestId }) }, status: 500 as const };
74
80
  default: {
75
81
  const _exhaustive: never = reason;
76
- return { body: { error: "internal_error", message: `Unexpected failure: ${_exhaustive}` }, status: 500 as const };
82
+ return { body: { error: "internal_error", message: `Unexpected failure: ${_exhaustive}`, ...(requestId && { requestId }) }, status: 500 as const };
77
83
  }
78
84
  }
79
85
  }
80
86
 
81
- const scheduledTasks = new Hono();
82
-
83
87
  // ---------------------------------------------------------------------------
84
- // Shared auth preamble
88
+ // Route definitions
85
89
  // ---------------------------------------------------------------------------
86
90
 
87
- async function authPreamble(req: Request, requestId: string) {
88
- let authResult: AuthResult;
89
- try {
90
- authResult = await authenticateRequest(req);
91
- } catch (err) {
92
- log.error(
93
- { err: err instanceof Error ? err : new Error(String(err)), requestId },
94
- "Auth dispatch failed",
95
- );
96
- return { error: { error: "auth_error", message: "Authentication system error" }, status: 500 as const };
97
- }
98
- if (!authResult.authenticated) {
99
- log.warn({ requestId, status: authResult.status }, "Authentication failed");
100
- return { error: { error: "auth_error", message: authResult.error }, status: authResult.status as 401 | 403 | 500 };
101
- }
91
+ const listTasksRoute = createRoute({
92
+ method: "get",
93
+ path: "/",
94
+ tags: ["Scheduled Tasks"],
95
+ summary: "List scheduled tasks",
96
+ description:
97
+ "Returns scheduled tasks for the active organization. Requires admin role, ATLAS_SCHEDULER_ENABLED=true, and an internal database.",
98
+ request: {
99
+ query: z.object({
100
+ limit: z.string().optional().openapi({
101
+ param: { name: "limit", in: "query" },
102
+ description: "Maximum number of items to return (1-100, default 20).",
103
+ }),
104
+ offset: z.string().optional().openapi({
105
+ param: { name: "offset", in: "query" },
106
+ description: "Number of items to skip (default 0).",
107
+ }),
108
+ enabled: z.string().optional().openapi({
109
+ param: { name: "enabled", in: "query" },
110
+ description: "Filter by enabled status.",
111
+ }),
112
+ }),
113
+ },
114
+ responses: {
115
+ 200: {
116
+ description: "Paginated list of scheduled tasks",
117
+ content: { "application/json": { schema: z.record(z.string(), z.unknown()) } },
118
+ },
119
+ 401: { description: "Authentication required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
120
+ 403: { description: "Forbidden — admin role required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
121
+ 404: { description: "Scheduled tasks not available", content: { "application/json": { schema: ErrorSchema } } },
122
+ 429: { description: "Rate limit exceeded", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
123
+ 500: { description: "Internal server error", content: { "application/json": { schema: ErrorSchema } } },
124
+ },
125
+ });
102
126
 
103
- const ip = getClientIP(req);
104
- const rateLimitKey = authResult.user?.id ?? (ip ? `ip:${ip}` : "anon");
105
- const rateCheck = checkRateLimit(rateLimitKey);
106
- if (!rateCheck.allowed) {
107
- const retryAfterSeconds = Math.ceil((rateCheck.retryAfterMs ?? 60000) / 1000);
108
- return {
109
- error: { error: "rate_limited", message: "Too many requests. Please wait before trying again.", retryAfterSeconds },
110
- status: 429 as const,
111
- headers: { "Retry-After": String(retryAfterSeconds) },
112
- };
113
- }
127
+ const createTaskRoute = createRoute({
128
+ method: "post",
129
+ path: "/",
130
+ tags: ["Scheduled Tasks"],
131
+ summary: "Create a scheduled task",
132
+ description: "Creates a recurring query task with a cron schedule and delivery channel. Requires admin role.",
133
+ request: {
134
+ body: {
135
+ content: { "application/json": { schema: CreateScheduledTaskSchema } },
136
+ required: true,
137
+ },
138
+ },
139
+ responses: {
140
+ 201: { description: "Scheduled task created", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
141
+ 400: { description: "Invalid request body or cron expression", content: { "application/json": { schema: ErrorSchema } } },
142
+ 401: { description: "Authentication required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
143
+ 403: { description: "Forbidden — admin role required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
144
+ 404: { description: "Feature not available", content: { "application/json": { schema: ErrorSchema } } },
145
+ 422: { description: "Validation error", content: { "application/json": { schema: ErrorSchema.extend({ details: z.array(z.unknown()).optional() }) } } },
146
+ 429: { description: "Rate limit exceeded", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
147
+ 500: { description: "Internal server error", content: { "application/json": { schema: ErrorSchema } } },
148
+ },
149
+ });
114
150
 
115
- return { authResult };
116
- }
151
+ const tickRoute = createRoute({
152
+ method: "post",
153
+ path: "/tick",
154
+ tags: ["Scheduled Tasks"],
155
+ summary: "Trigger scheduler tick",
156
+ description:
157
+ "Serverless scheduler tick endpoint for Vercel Cron or external cron services. " +
158
+ "Checks for due tasks and executes them. Requires CRON_SECRET or ATLAS_SCHEDULER_SECRET.",
159
+ responses: {
160
+ 200: { description: "Tick completed", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
161
+ 401: { description: "Invalid or missing cron secret", content: { "application/json": { schema: ErrorSchema } } },
162
+ 404: { description: "Feature not available (no internal database configured)", content: { "application/json": { schema: ErrorSchema } } },
163
+ 500: { description: "Tick execution failed", content: { "application/json": { schema: ErrorSchema } } },
164
+ },
165
+ });
166
+
167
+ const listAllRunsRoute = createRoute({
168
+ method: "get",
169
+ path: "/runs",
170
+ tags: ["Scheduled Tasks"],
171
+ summary: "List all task runs",
172
+ description: "Returns cross-task run history with filtering by task, status, and date range. Requires admin role.",
173
+ request: {
174
+ query: z.object({
175
+ limit: z.string().optional().openapi({ param: { name: "limit", in: "query" }, description: "Maximum number of runs (1-100, default 20)." }),
176
+ offset: z.string().optional().openapi({ param: { name: "offset", in: "query" }, description: "Number of items to skip (default 0)." }),
177
+ task_id: z.string().optional().openapi({ param: { name: "task_id", in: "query" }, description: "Filter by task ID." }),
178
+ status: z.string().optional().openapi({ param: { name: "status", in: "query" }, description: "Filter by run status." }),
179
+ date_from: z.string().optional().openapi({ param: { name: "date_from", in: "query" }, description: "Filter from date (YYYY-MM-DD)." }),
180
+ date_to: z.string().optional().openapi({ param: { name: "date_to", in: "query" }, description: "Filter to date (YYYY-MM-DD)." }),
181
+ }),
182
+ },
183
+ responses: {
184
+ 200: { description: "List of task runs", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
185
+ 401: { description: "Authentication required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
186
+ 403: { description: "Forbidden — admin role required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
187
+ 404: { description: "Not available", content: { "application/json": { schema: ErrorSchema } } },
188
+ 429: { description: "Rate limit exceeded", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } },
189
+ 500: { description: "Internal server error", content: { "application/json": { schema: ErrorSchema } } },
190
+ },
191
+ });
192
+
193
+ const getTaskRoute = createRoute({ method: "get", path: "/{id}", tags: ["Scheduled Tasks"], summary: "Get scheduled task", description: "Returns a scheduled task with its 10 most recent runs. Requires admin role.", request: { params: z.object({ id: z.string().openapi({ param: { name: "id", in: "path" }, example: "00000000-0000-0000-0000-000000000000" }) }) }, responses: { 200: { description: "Scheduled task with recent runs", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 400: { description: "Invalid task ID format", content: { "application/json": { schema: ErrorSchema } } }, 401: { description: "Authentication required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 403: { description: "Forbidden — admin role required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 404: { description: "Task not found", content: { "application/json": { schema: ErrorSchema } } }, 429: { description: "Rate limit exceeded", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 500: { description: "Internal server error", content: { "application/json": { schema: ErrorSchema } } } } });
194
+
195
+ const updateTaskRoute = createRoute({ method: "put", path: "/{id}", tags: ["Scheduled Tasks"], summary: "Update a scheduled task", description: "Updates a scheduled task. All fields are optional. Requires admin role.", request: { params: z.object({ id: z.string().openapi({ param: { name: "id", in: "path" }, example: "00000000-0000-0000-0000-000000000000" }) }), body: { content: { "application/json": { schema: UpdateScheduledTaskSchema } }, required: true } }, responses: { 200: { description: "Updated scheduled task", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 400: { description: "Invalid request body or cron expression", content: { "application/json": { schema: ErrorSchema } } }, 401: { description: "Authentication required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 403: { description: "Forbidden — admin role required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 404: { description: "Task not found", content: { "application/json": { schema: ErrorSchema } } }, 422: { description: "Validation error", content: { "application/json": { schema: ErrorSchema.extend({ details: z.array(z.unknown()).optional() }) } } }, 429: { description: "Rate limit exceeded", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 500: { description: "Internal server error", content: { "application/json": { schema: ErrorSchema } } } } });
196
+
197
+ const deleteTaskRoute = createRoute({ method: "delete", path: "/{id}", tags: ["Scheduled Tasks"], summary: "Delete a scheduled task", description: "Soft-deletes (disables) a scheduled task. Requires admin role.", request: { params: z.object({ id: z.string().openapi({ param: { name: "id", in: "path" }, example: "00000000-0000-0000-0000-000000000000" }) }) }, responses: { 204: { description: "Task deleted successfully" }, 400: { description: "Invalid task ID format", content: { "application/json": { schema: ErrorSchema } } }, 401: { description: "Authentication required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 403: { description: "Forbidden — admin role required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 404: { description: "Task not found", content: { "application/json": { schema: ErrorSchema } } }, 429: { description: "Rate limit exceeded", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 500: { description: "Internal server error", content: { "application/json": { schema: ErrorSchema } } } } });
198
+
199
+ const triggerTaskRoute = createRoute({ method: "post", path: "/{id}/run", tags: ["Scheduled Tasks"], summary: "Trigger immediate execution", description: "Triggers an immediate execution of a scheduled task. Requires admin role.", request: { params: z.object({ id: z.string().openapi({ param: { name: "id", in: "path" }, example: "00000000-0000-0000-0000-000000000000" }) }) }, responses: { 200: { description: "Task triggered", content: { "application/json": { schema: z.object({ message: z.string(), taskId: z.string() }) } } }, 400: { description: "Invalid task ID format", content: { "application/json": { schema: ErrorSchema } } }, 401: { description: "Authentication required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 403: { description: "Forbidden — admin role required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 404: { description: "Task not found", content: { "application/json": { schema: ErrorSchema } } }, 429: { description: "Rate limit exceeded", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 500: { description: "Internal server error", content: { "application/json": { schema: ErrorSchema } } } } });
200
+
201
+ const previewTaskRoute = createRoute({ method: "post", path: "/{id}/preview", tags: ["Scheduled Tasks"], summary: "Preview delivery format", description: "Dry-run delivery format with mock data. Requires admin role.", request: { params: z.object({ id: z.string().openapi({ param: { name: "id", in: "path" }, example: "00000000-0000-0000-0000-000000000000" }) }) }, responses: { 200: { description: "Delivery preview", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 400: { description: "Invalid task ID format", content: { "application/json": { schema: ErrorSchema } } }, 401: { description: "Authentication required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 403: { description: "Forbidden — admin role required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 404: { description: "Task not found", content: { "application/json": { schema: ErrorSchema } } }, 429: { description: "Rate limit exceeded", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 500: { description: "Internal server error", content: { "application/json": { schema: ErrorSchema } } } } });
202
+
203
+ const listTaskRunsRoute = createRoute({ method: "get", path: "/{id}/runs", tags: ["Scheduled Tasks"], summary: "List task runs", description: "Returns past execution runs for a scheduled task. Requires admin role.", request: { params: z.object({ id: z.string().openapi({ param: { name: "id", in: "path" }, example: "00000000-0000-0000-0000-000000000000" }) }), query: z.object({ limit: z.string().optional().openapi({ param: { name: "limit", in: "query" }, description: "Maximum number of runs to return (1-100, default 20)." }) }) }, responses: { 200: { description: "List of task runs", content: { "application/json": { schema: z.object({ runs: z.array(z.record(z.string(), z.unknown())) }) } } }, 400: { description: "Invalid task ID format", content: { "application/json": { schema: ErrorSchema } } }, 401: { description: "Authentication required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 403: { description: "Forbidden — admin role required", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 404: { description: "Task not found", content: { "application/json": { schema: ErrorSchema } } }, 429: { description: "Rate limit exceeded", content: { "application/json": { schema: z.record(z.string(), z.unknown()) } } }, 500: { description: "Internal server error", content: { "application/json": { schema: ErrorSchema } } } } });
117
204
 
118
205
  // ---------------------------------------------------------------------------
119
- // GET / — list scheduled tasks
206
+ // Router
120
207
  // ---------------------------------------------------------------------------
121
208
 
122
- scheduledTasks.get("/", async (c) => {
123
- const req = c.req.raw;
124
- const requestId = crypto.randomUUID();
209
+ // Outer app: tick route (cron-secret auth, no user-auth middleware)
210
+ const scheduledTasks = new OpenAPIHono<AuthEnv>({ defaultHook: validationHook });
125
211
 
126
- if (!hasInternalDB()) {
127
- return c.json({ error: "not_available", message: "Scheduled tasks require an internal database." }, 404);
128
- }
212
+ // Inner app: admin-authenticated, org-scoped routes (adminAuth + requireOrgContext)
213
+ const authed = createAdminRouter();
214
+ authed.use(requireOrgContext());
129
215
 
130
- const preamble = await authPreamble(req, requestId);
131
- if ("error" in preamble) {
132
- return c.json(preamble.error, { status: preamble.status, headers: preamble.headers });
216
+ // Tick also needs a JSON-parse error handler (outer app only — authed uses eeOnError via createAdminRouter)
217
+ scheduledTasks.onError((err, c) => {
218
+ if (err instanceof HTTPException) {
219
+ if (err.res) return err.res;
220
+ if (err.status === 400) {
221
+ return c.json({ error: "invalid_request", message: "Invalid JSON body." }, 400);
222
+ }
133
223
  }
134
- const { authResult } = preamble;
224
+ throw err;
225
+ });
226
+
227
+ // ---------------------------------------------------------------------------
228
+ // GET / — list scheduled tasks
229
+ // ---------------------------------------------------------------------------
230
+
231
+ authed.openapi(listTasksRoute, async (c) => {
232
+ return runEffect(c, Effect.gen(function* () {
233
+ const { orgId } = yield* AuthContext;
135
234
 
136
- return withRequestContext({ requestId, user: authResult.user }, async () => {
137
- const rawLimit = parseInt(c.req.query("limit") ?? "20", 10);
138
- const rawOffset = parseInt(c.req.query("offset") ?? "0", 10);
139
- const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit, 100) : 20;
140
- const offset = Number.isFinite(rawOffset) && rawOffset >= 0 ? rawOffset : 0;
235
+ const { limit, offset } = parsePagination(c, { limit: 20, maxLimit: 100 });
141
236
  const enabledParam = c.req.query("enabled");
142
237
  const enabled = enabledParam === "true" ? true : enabledParam === "false" ? false : undefined;
143
238
 
144
- const result = await listScheduledTasks({
145
- ownerId: authResult.user?.id,
239
+ const items = yield* Effect.promise(() => listScheduledTasks({
240
+ orgId,
146
241
  enabled,
147
242
  limit,
148
243
  offset,
149
- });
150
- return c.json(result);
151
- });
244
+ }));
245
+ return c.json(items, 200);
246
+ }), { label: "list scheduled tasks" });
152
247
  });
153
248
 
154
249
  // ---------------------------------------------------------------------------
155
250
  // POST / — create scheduled task
156
251
  // ---------------------------------------------------------------------------
157
252
 
158
- scheduledTasks.post("/", async (c) => {
159
- const req = c.req.raw;
160
- const requestId = crypto.randomUUID();
253
+ authed.openapi(
254
+ createTaskRoute,
255
+ async (c) => {
256
+ return runEffect(c, Effect.gen(function* () {
257
+ const { requestId } = yield* RequestContext;
258
+ const { orgId, user } = yield* AuthContext;
161
259
 
162
- if (!hasInternalDB()) {
163
- return c.json({ error: "not_available", message: "Scheduled tasks require an internal database." }, 404);
164
- }
260
+ const parsed = c.req.valid("json");
165
261
 
166
- const preamble = await authPreamble(req, requestId);
167
- if ("error" in preamble) {
168
- return c.json(preamble.error, { status: preamble.status, headers: preamble.headers });
169
- }
170
- const { authResult } = preamble;
171
-
172
- return withRequestContext({ requestId, user: authResult.user }, async () => {
173
- let body: unknown;
174
- try {
175
- body = await req.json();
176
- } catch {
177
- return c.json({ error: "invalid_request", message: "Invalid JSON body." }, 400);
178
- }
179
-
180
- const parsed = CreateScheduledTaskSchema.safeParse(body);
181
- if (!parsed.success) {
182
- const issues = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
183
- return c.json({ error: "invalid_request", message: issues }, 400);
184
- }
262
+ // Validate cron expression
263
+ const cronCheck = validateCronExpression(parsed.cronExpression);
264
+ if (!cronCheck.valid) {
265
+ return c.json({ error: "invalid_request", message: `Invalid cron expression: ${cronCheck.error}` }, 400);
266
+ }
185
267
 
186
- // Validate cron expression
187
- const cronCheck = validateCronExpression(parsed.data.cronExpression);
188
- if (!cronCheck.valid) {
189
- return c.json({ error: "invalid_request", message: `Invalid cron expression: ${cronCheck.error}` }, 400);
190
- }
268
+ const createResult = yield* Effect.promise(() => createScheduledTask({
269
+ ownerId: user?.id ?? "anonymous",
270
+ orgId,
271
+ name: parsed.name,
272
+ question: parsed.question,
273
+ cronExpression: parsed.cronExpression,
274
+ deliveryChannel: parsed.deliveryChannel,
275
+ recipients: parsed.recipients,
276
+ connectionId: parsed.connectionId ?? null,
277
+ approvalMode: parsed.approvalMode,
278
+ }));
279
+
280
+ if (!createResult.ok) {
281
+ const fail = crudFailResponse(createResult.reason, requestId);
282
+ return c.json(fail.body, fail.status);
283
+ }
191
284
 
192
- const result = await createScheduledTask({
193
- ownerId: authResult.user?.id ?? "anonymous",
194
- name: parsed.data.name,
195
- question: parsed.data.question,
196
- cronExpression: parsed.data.cronExpression,
197
- deliveryChannel: parsed.data.deliveryChannel,
198
- recipients: parsed.data.recipients,
199
- connectionId: parsed.data.connectionId ?? null,
200
- approvalMode: parsed.data.approvalMode,
201
- });
202
-
203
- if (!result.ok) {
204
- const fail = crudFailResponse(result.reason);
205
- return c.json(fail.body, fail.status);
285
+ return c.json(createResult.data, 201);
286
+ }), { label: "create scheduled task" });
287
+ },
288
+ (result, c) => {
289
+ if (!result.success) {
290
+ return c.json(
291
+ { error: "validation_error", message: "Invalid request body.", details: result.error.issues },
292
+ 422,
293
+ );
206
294
  }
207
-
208
- return c.json(result.data, 201);
209
- });
210
- });
295
+ },
296
+ );
211
297
 
212
298
  // ---------------------------------------------------------------------------
213
299
  // POST /tick — serverless scheduler tick (Vercel Cron)
214
300
  // ---------------------------------------------------------------------------
215
301
 
216
- scheduledTasks.post("/tick", async (c) => {
217
- const req = c.req.raw;
302
+ scheduledTasks.openapi(tickRoute, async (c) => {
303
+ return runEffect(c, Effect.gen(function* () {
304
+ const req = c.req.raw;
305
+ const requestId = crypto.randomUUID();
218
306
 
219
- if (!hasInternalDB()) {
220
- return c.json({ error: "not_available", message: "Scheduled tasks require an internal database." }, 404);
221
- }
307
+ if (!hasInternalDB()) {
308
+ return c.json({ error: "not_available", message: "Scheduled tasks require an internal database.", requestId }, 404);
309
+ }
222
310
 
223
- // Auth: check CRON_SECRET (Vercel-native) or ATLAS_SCHEDULER_SECRET (generic)
224
- const secret = process.env.CRON_SECRET ?? process.env.ATLAS_SCHEDULER_SECRET;
225
- const { getConfig } = await import("@atlas/api/lib/config");
226
- const config = getConfig();
311
+ // Auth: check CRON_SECRET (Vercel-native) or ATLAS_SCHEDULER_SECRET (generic)
312
+ const secret = process.env.CRON_SECRET ?? process.env.ATLAS_SCHEDULER_SECRET;
313
+ const { getConfig } = yield* Effect.promise(() => import("@atlas/api/lib/config"));
314
+ const config = getConfig();
227
315
 
228
- if (secret) {
229
- const authHeader = req.headers.get("authorization");
230
- if (authHeader !== `Bearer ${secret}`) {
231
- return c.json({ error: "unauthorized", message: "Invalid or missing cron secret." }, 401);
316
+ if (secret) {
317
+ const authHeader = req.headers.get("authorization");
318
+ if (authHeader !== `Bearer ${secret}`) {
319
+ return c.json({ error: "unauthorized", message: "Invalid or missing cron secret.", requestId }, 401);
320
+ }
321
+ } else if (config?.scheduler?.backend === "vercel") {
322
+ return c.json(
323
+ { error: "misconfigured", message: "Vercel backend requires CRON_SECRET or ATLAS_SCHEDULER_SECRET to be set.", requestId },
324
+ 500,
325
+ );
326
+ } else if (process.env.NODE_ENV === "production") {
327
+ return c.json(
328
+ { error: "misconfigured", message: "CRON_SECRET or ATLAS_SCHEDULER_SECRET must be set in production.", requestId },
329
+ 500,
330
+ );
331
+ } else {
332
+ log.warn("POST /tick called without secret — allowing because NODE_ENV is not 'production'");
232
333
  }
233
- } else if (config?.scheduler?.backend === "vercel") {
234
- return c.json(
235
- { error: "misconfigured", message: "Vercel backend requires CRON_SECRET or ATLAS_SCHEDULER_SECRET to be set." },
236
- 500,
237
- );
238
- } else if (process.env.NODE_ENV === "production") {
239
- return c.json(
240
- { error: "misconfigured", message: "CRON_SECRET or ATLAS_SCHEDULER_SECRET must be set in production." },
241
- 500,
242
- );
243
- } else {
244
- log.warn("POST /tick called without secret — allowing because NODE_ENV is not 'production'");
245
- }
246
334
 
247
- try {
248
- const { runTick } = await import("@atlas/api/lib/scheduler/engine");
249
- const result = await runTick();
250
- if (result.error) {
251
- return c.json(result, 500);
335
+ const tickOutcome = yield* Effect.tryPromise({
336
+ try: async () => {
337
+ const { runTick } = await import("@atlas/api/lib/scheduler/engine");
338
+ return runTick();
339
+ },
340
+ catch: (err) => err instanceof Error ? err : new Error(String(err)),
341
+ }).pipe(Effect.catchAll((err) => {
342
+ log.error({ err, requestId }, "Tick execution failed");
343
+ return Effect.succeed({ error: "internal_error" as const, requestId });
344
+ }));
345
+
346
+ if ("error" in tickOutcome && tickOutcome.error === "internal_error") {
347
+ return c.json({ error: "internal_error", message: "Tick execution failed.", requestId }, 500);
252
348
  }
253
- return c.json(result);
254
- } catch (err) {
255
- log.error({ err: err instanceof Error ? err : new Error(String(err)) }, "Tick execution failed");
256
- return c.json({ error: "internal_error", message: "Tick execution failed." }, 500);
257
- }
349
+ if (tickOutcome.error) {
350
+ return c.json({ error: "tick_failed", message: tickOutcome.error, requestId }, 500);
351
+ }
352
+ return c.json(tickOutcome, 200);
353
+ }), { label: "scheduler tick" });
258
354
  });
259
355
 
260
356
  // ---------------------------------------------------------------------------
261
- // GET /:idget scheduled task with recent runs
357
+ // GET /runscross-task run history
262
358
  // ---------------------------------------------------------------------------
263
359
 
264
- scheduledTasks.get("/:id", async (c) => {
265
- const req = c.req.raw;
266
- const requestId = crypto.randomUUID();
360
+ authed.openapi(listAllRunsRoute, async (c) => {
361
+ return runEffect(c, Effect.gen(function* () {
362
+ const { orgId } = yield* AuthContext;
363
+
364
+ const { limit, offset } = parsePagination(c, { limit: 20, maxLimit: 100 });
365
+
366
+ const taskIdParam = c.req.query("task_id") || undefined;
367
+ const taskId = taskIdParam && UUID_RE.test(taskIdParam) ? taskIdParam : undefined;
368
+ const statusParam = c.req.query("status");
369
+ const status = statusParam && (RUN_STATUSES as readonly string[]).includes(statusParam)
370
+ ? (statusParam as RunStatus)
371
+ : undefined;
372
+ const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
373
+ const dateFromParam = c.req.query("date_from") || undefined;
374
+ const dateToParam = c.req.query("date_to") || undefined;
375
+ const dateFrom = dateFromParam && ISO_DATE_RE.test(dateFromParam) ? dateFromParam : undefined;
376
+ const dateTo = dateToParam && ISO_DATE_RE.test(dateToParam) ? dateToParam : undefined;
377
+
378
+ const runs = yield* Effect.promise(() => listAllRuns({ orgId, taskId, status, dateFrom, dateTo, limit, offset }));
379
+ return c.json(runs, 200);
380
+ }), { label: "list all runs" });
381
+ });
267
382
 
268
- if (!hasInternalDB()) {
269
- return c.json({ error: "not_available", message: "Scheduled tasks require an internal database." }, 404);
270
- }
383
+ // ---------------------------------------------------------------------------
384
+ // GET /:id get scheduled task with recent runs
385
+ // ---------------------------------------------------------------------------
271
386
 
272
- const preamble = await authPreamble(req, requestId);
273
- if ("error" in preamble) {
274
- return c.json(preamble.error, { status: preamble.status, headers: preamble.headers });
275
- }
276
- const { authResult } = preamble;
387
+ authed.openapi(getTaskRoute, async (c) => {
388
+ return runEffect(c, Effect.gen(function* () {
389
+ const { requestId } = yield* RequestContext;
390
+ const { orgId } = yield* AuthContext;
277
391
 
278
- const id = c.req.param("id");
279
- if (!UUID_RE.test(id)) {
280
- return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
281
- }
392
+ const { id } = c.req.valid("param");
393
+ if (!UUID_RE.test(id)) {
394
+ return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
395
+ }
282
396
 
283
- return withRequestContext({ requestId, user: authResult.user }, async () => {
284
- const result = await getScheduledTask(id, authResult.user?.id);
285
- if (!result.ok) {
286
- const fail = crudFailResponse(result.reason);
397
+ const taskResult = yield* Effect.promise(() => getScheduledTask(id, { orgId }));
398
+ if (!taskResult.ok) {
399
+ const fail = crudFailResponse(taskResult.reason, requestId);
287
400
  return c.json(fail.body, fail.status);
288
401
  }
289
402
 
290
- const runs = await listTaskRuns(id, { limit: 10 });
291
- return c.json({ ...result.data, recentRuns: runs });
292
- });
403
+ const runs = yield* Effect.promise(() => listTaskRuns(id, { limit: 10 }));
404
+ return c.json({ ...taskResult.data, recentRuns: runs }, 200);
405
+ }), { label: "get scheduled task" });
293
406
  });
294
407
 
295
408
  // ---------------------------------------------------------------------------
296
409
  // PUT /:id — update scheduled task
297
410
  // ---------------------------------------------------------------------------
298
411
 
299
- scheduledTasks.put("/:id", async (c) => {
300
- const req = c.req.raw;
301
- const requestId = crypto.randomUUID();
412
+ authed.openapi(
413
+ updateTaskRoute,
414
+ async (c) => {
415
+ return runEffect(c, Effect.gen(function* () {
416
+ const { requestId } = yield* RequestContext;
417
+ const { orgId } = yield* AuthContext;
302
418
 
303
- if (!hasInternalDB()) {
304
- return c.json({ error: "not_available", message: "Scheduled tasks require an internal database." }, 404);
305
- }
306
-
307
- const preamble = await authPreamble(req, requestId);
308
- if ("error" in preamble) {
309
- return c.json(preamble.error, { status: preamble.status, headers: preamble.headers });
310
- }
311
- const { authResult } = preamble;
312
-
313
- const id = c.req.param("id");
314
- if (!UUID_RE.test(id)) {
315
- return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
316
- }
317
-
318
- return withRequestContext({ requestId, user: authResult.user }, async () => {
319
- let body: unknown;
320
- try {
321
- body = await req.json();
322
- } catch {
323
- return c.json({ error: "invalid_request", message: "Invalid JSON body." }, 400);
324
- }
419
+ const { id } = c.req.valid("param");
420
+ if (!UUID_RE.test(id)) {
421
+ return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
422
+ }
325
423
 
326
- const parsed = UpdateScheduledTaskSchema.safeParse(body);
327
- if (!parsed.success) {
328
- const issues = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
329
- return c.json({ error: "invalid_request", message: issues }, 400);
330
- }
424
+ const parsed = c.req.valid("json");
331
425
 
332
- // Validate cron if provided
333
- if (parsed.data.cronExpression) {
334
- const cronCheck = validateCronExpression(parsed.data.cronExpression);
335
- if (!cronCheck.valid) {
336
- return c.json({ error: "invalid_request", message: `Invalid cron expression: ${cronCheck.error}` }, 400);
426
+ // Validate cron if provided
427
+ if (parsed.cronExpression) {
428
+ const cronCheck = validateCronExpression(parsed.cronExpression);
429
+ if (!cronCheck.valid) {
430
+ return c.json({ error: "invalid_request", message: `Invalid cron expression: ${cronCheck.error}` }, 400);
431
+ }
337
432
  }
338
- }
339
433
 
340
- const result = await updateScheduledTask(id, authResult.user?.id ?? "anonymous", parsed.data);
341
- if (!result.ok) {
342
- const fail = crudFailResponse(result.reason);
343
- return c.json(fail.body, fail.status);
344
- }
434
+ const updateResult = yield* Effect.promise(() => updateScheduledTask(id, { orgId }, parsed));
435
+ if (!updateResult.ok) {
436
+ const fail = crudFailResponse(updateResult.reason, requestId);
437
+ return c.json(fail.body, fail.status);
438
+ }
345
439
 
346
- // Fetch updated task to return
347
- const updated = await getScheduledTask(id, authResult.user?.id);
348
- if (!updated.ok) {
349
- return c.json({ ok: true });
440
+ // Fetch updated task to return
441
+ const updated = yield* Effect.promise(() => getScheduledTask(id, { orgId }));
442
+ if (!updated.ok) {
443
+ return c.json({ ok: true }, 200);
444
+ }
445
+ return c.json(updated.data, 200);
446
+ }), { label: "update scheduled task" });
447
+ },
448
+ (result, c) => {
449
+ if (!result.success) {
450
+ return c.json(
451
+ { error: "validation_error", message: "Invalid request body.", details: result.error.issues },
452
+ 422,
453
+ );
350
454
  }
351
- return c.json(updated.data);
352
- });
353
- });
455
+ },
456
+ );
354
457
 
355
458
  // ---------------------------------------------------------------------------
356
459
  // DELETE /:id — soft delete (disable)
357
460
  // ---------------------------------------------------------------------------
358
461
 
359
- scheduledTasks.delete("/:id", async (c) => {
360
- const req = c.req.raw;
361
- const requestId = crypto.randomUUID();
362
-
363
- if (!hasInternalDB()) {
364
- return c.json({ error: "not_available", message: "Scheduled tasks require an internal database." }, 404);
365
- }
366
-
367
- const preamble = await authPreamble(req, requestId);
368
- if ("error" in preamble) {
369
- return c.json(preamble.error, { status: preamble.status, headers: preamble.headers });
370
- }
371
- const { authResult } = preamble;
462
+ authed.openapi(deleteTaskRoute, async (c) => {
463
+ return runEffect(c, Effect.gen(function* () {
464
+ const { requestId } = yield* RequestContext;
465
+ const { orgId } = yield* AuthContext;
372
466
 
373
- const id = c.req.param("id");
374
- if (!UUID_RE.test(id)) {
375
- return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
376
- }
467
+ const { id } = c.req.valid("param");
468
+ if (!UUID_RE.test(id)) {
469
+ return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
470
+ }
377
471
 
378
- return withRequestContext({ requestId, user: authResult.user }, async () => {
379
- const result = await deleteScheduledTask(id, authResult.user?.id);
380
- if (!result.ok) {
381
- const fail = crudFailResponse(result.reason);
472
+ const delResult = yield* Effect.promise(() => deleteScheduledTask(id, { orgId }));
473
+ if (!delResult.ok) {
474
+ const fail = crudFailResponse(delResult.reason, requestId);
382
475
  return c.json(fail.body, fail.status);
383
476
  }
384
477
  return c.body(null, 204);
385
- });
478
+ }), { label: "delete scheduled task" });
386
479
  });
387
480
 
388
481
  // ---------------------------------------------------------------------------
389
482
  // POST /:id/run — trigger immediate execution
390
483
  // ---------------------------------------------------------------------------
391
484
 
392
- scheduledTasks.post("/:id/run", async (c) => {
393
- const req = c.req.raw;
394
- const requestId = crypto.randomUUID();
485
+ authed.openapi(triggerTaskRoute, async (c) => {
486
+ return runEffect(c, Effect.gen(function* () {
487
+ const { requestId } = yield* RequestContext;
488
+ const { orgId } = yield* AuthContext;
395
489
 
396
- if (!hasInternalDB()) {
397
- return c.json({ error: "not_available", message: "Scheduled tasks require an internal database." }, 404);
398
- }
490
+ const { id } = c.req.valid("param");
491
+ if (!UUID_RE.test(id)) {
492
+ return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
493
+ }
399
494
 
400
- const preamble = await authPreamble(req, requestId);
401
- if ("error" in preamble) {
402
- return c.json(preamble.error, { status: preamble.status, headers: preamble.headers });
403
- }
404
- const { authResult } = preamble;
495
+ const task = yield* Effect.promise(() => getScheduledTask(id, { orgId }));
496
+ if (!task.ok) {
497
+ const fail = crudFailResponse(task.reason, requestId);
498
+ return c.json(fail.body, fail.status);
499
+ }
405
500
 
406
- const id = c.req.param("id");
407
- if (!UUID_RE.test(id)) {
408
- return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
409
- }
501
+ const { triggerTask } = yield* Effect.promise(() => import("@atlas/api/lib/scheduler/engine"));
502
+ yield* Effect.promise(() => triggerTask(id));
503
+ return c.json({ message: "Task triggered successfully.", taskId: id }, 200);
504
+ }), { label: "trigger task execution" });
505
+ });
506
+
507
+ // ---------------------------------------------------------------------------
508
+ // POST /:id/preview — dry-run delivery format with mock data
509
+ // ---------------------------------------------------------------------------
410
510
 
411
- return withRequestContext({ requestId, user: authResult.user }, async () => {
412
- const task = await getScheduledTask(id, authResult.user?.id);
511
+ authed.openapi(previewTaskRoute, async (c) => {
512
+ return runEffect(c, Effect.gen(function* () {
513
+ const { requestId } = yield* RequestContext;
514
+ const { orgId } = yield* AuthContext;
515
+
516
+ const { id } = c.req.valid("param");
517
+ if (!UUID_RE.test(id)) {
518
+ return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
519
+ }
520
+
521
+ const task = yield* Effect.promise(() => getScheduledTask(id, { orgId }));
413
522
  if (!task.ok) {
414
- const fail = crudFailResponse(task.reason);
523
+ const fail = crudFailResponse(task.reason, requestId);
415
524
  return c.json(fail.body, fail.status);
416
525
  }
417
526
 
418
- try {
419
- const { triggerTask } = await import("@atlas/api/lib/scheduler/engine");
420
- await triggerTask(id);
421
- return c.json({ message: "Task triggered successfully.", taskId: id });
422
- } catch (err) {
423
- log.error({ err: err instanceof Error ? err.message : String(err), taskId: id }, "Trigger failed");
424
- return c.json({ error: "internal_error", message: "Failed to trigger task execution." }, 500);
425
- }
426
- });
527
+ const { generateDeliveryPreview } = yield* Effect.promise(() => import("@atlas/api/lib/scheduler/preview"));
528
+ const preview = generateDeliveryPreview(task.data);
529
+ return c.json(preview, 200);
530
+ }), { label: "generate delivery preview" });
427
531
  });
428
532
 
429
533
  // ---------------------------------------------------------------------------
430
534
  // GET /:id/runs — list past runs
431
535
  // ---------------------------------------------------------------------------
432
536
 
433
- scheduledTasks.get("/:id/runs", async (c) => {
434
- const req = c.req.raw;
435
- const requestId = crypto.randomUUID();
537
+ authed.openapi(listTaskRunsRoute, async (c) => {
538
+ return runEffect(c, Effect.gen(function* () {
539
+ const { requestId } = yield* RequestContext;
540
+ const { orgId } = yield* AuthContext;
436
541
 
437
- if (!hasInternalDB()) {
438
- return c.json({ error: "not_available", message: "Scheduled tasks require an internal database." }, 404);
439
- }
440
-
441
- const preamble = await authPreamble(req, requestId);
442
- if ("error" in preamble) {
443
- return c.json(preamble.error, { status: preamble.status, headers: preamble.headers });
444
- }
445
- const { authResult } = preamble;
446
-
447
- const id = c.req.param("id");
448
- if (!UUID_RE.test(id)) {
449
- return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
450
- }
542
+ const { id } = c.req.valid("param");
543
+ if (!UUID_RE.test(id)) {
544
+ return c.json({ error: "invalid_request", message: "Invalid task ID format." }, 400);
545
+ }
451
546
 
452
- return withRequestContext({ requestId, user: authResult.user }, async () => {
453
- // Verify task ownership
454
- const task = await getScheduledTask(id, authResult.user?.id);
547
+ // Verify task belongs to this org
548
+ const task = yield* Effect.promise(() => getScheduledTask(id, { orgId }));
455
549
  if (!task.ok) {
456
- const fail = crudFailResponse(task.reason);
550
+ const fail = crudFailResponse(task.reason, requestId);
457
551
  return c.json(fail.body, fail.status);
458
552
  }
459
553
 
460
- const rawLimit = parseInt(c.req.query("limit") ?? "20", 10);
461
- const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit, 100) : 20;
462
- const runs = await listTaskRuns(id, { limit });
463
- return c.json({ runs });
464
- });
554
+ const { limit } = parsePagination(c, { limit: 20, maxLimit: 100 });
555
+ const runs = yield* Effect.promise(() => listTaskRuns(id, { limit }));
556
+ return c.json({ runs }, 200);
557
+ }), { label: "list task runs" });
465
558
  });
466
559
 
560
+ // Mount authenticated routes on the outer app
561
+ scheduledTasks.route("/", authed);
562
+
467
563
  export { scheduledTasks };