@useatlas/create 0.0.2 → 0.0.4
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.
- package/README.md +4 -18
- package/index.ts +191 -31
- package/package.json +1 -1
- package/templates/docker/.env.example +3 -3
- package/templates/docker/Dockerfile.sidecar +28 -0
- package/templates/docker/bin/__tests__/plugin-cli.test.ts +9 -9
- package/templates/docker/bin/atlas.ts +108 -44
- package/templates/docker/data/demo-semantic/catalog.yml +51 -27
- package/templates/docker/data/demo-semantic/entities/accounts.yml +95 -103
- package/templates/docker/data/demo-semantic/entities/companies.yml +88 -152
- package/templates/docker/data/demo-semantic/entities/people.yml +82 -95
- package/templates/docker/data/demo-semantic/glossary.yml +104 -8
- package/templates/docker/data/demo-semantic/metrics/accounts.yml +62 -23
- package/templates/docker/data/demo-semantic/metrics/companies.yml +52 -78
- package/templates/docker/docker-compose.yml +1 -1
- package/templates/docker/docs/deploy.md +2 -39
- package/templates/docker/package.json +17 -1
- package/templates/docker/semantic/catalog.yml +62 -3
- package/templates/docker/semantic/entities/accounts.yml +162 -0
- package/templates/docker/semantic/entities/companies.yml +143 -0
- package/templates/docker/semantic/entities/people.yml +132 -0
- package/templates/docker/semantic/glossary.yml +116 -4
- package/templates/docker/semantic/metrics/accounts.yml +77 -0
- package/templates/docker/semantic/metrics/companies.yml +63 -0
- package/templates/docker/sidecar/Dockerfile +5 -6
- package/templates/docker/sidecar/railway.json +1 -2
- package/templates/docker/src/api/__tests__/admin.test.ts +7 -7
- package/templates/docker/src/api/__tests__/health-plugin.test.ts +7 -0
- package/templates/docker/src/api/__tests__/health.test.ts +30 -8
- package/templates/docker/src/api/routes/admin.ts +549 -8
- package/templates/docker/src/api/routes/chat.ts +5 -20
- package/templates/docker/src/api/routes/health.ts +39 -27
- package/templates/docker/src/api/routes/openapi.ts +1329 -74
- package/templates/docker/src/api/routes/query.ts +2 -1
- package/templates/docker/src/api/server.ts +27 -0
- package/templates/docker/src/app/api/[...route]/route.ts +2 -2
- package/templates/docker/src/app/globals.css +13 -12
- package/templates/docker/src/app/layout.tsx +9 -2
- package/templates/docker/src/components/ui/alert-dialog.tsx +196 -0
- package/templates/docker/src/components/ui/badge.tsx +48 -0
- package/templates/docker/src/components/ui/button.tsx +64 -0
- package/templates/docker/src/components/ui/card.tsx +92 -0
- package/templates/docker/src/components/ui/collapsible.tsx +33 -0
- package/templates/docker/src/components/ui/command.tsx +184 -0
- package/templates/docker/src/components/ui/dialog.tsx +158 -0
- package/templates/docker/src/components/ui/dropdown-menu.tsx +257 -0
- package/templates/docker/src/components/ui/input.tsx +21 -0
- package/templates/docker/src/components/ui/scroll-area.tsx +58 -0
- package/templates/docker/src/components/ui/select.tsx +190 -0
- package/templates/docker/src/components/ui/separator.tsx +28 -0
- package/templates/docker/src/components/ui/sheet.tsx +143 -0
- package/templates/docker/src/components/ui/sidebar.tsx +726 -0
- package/templates/docker/src/components/ui/skeleton.tsx +13 -0
- package/templates/docker/src/components/ui/table.tsx +116 -0
- package/templates/docker/src/components/ui/tabs.tsx +91 -0
- package/templates/docker/src/components/ui/toggle-group.tsx +83 -0
- package/templates/docker/src/components/ui/toggle.tsx +47 -0
- package/templates/docker/src/components/ui/tooltip.tsx +57 -0
- package/templates/docker/src/hooks/use-mobile.ts +19 -0
- package/templates/docker/src/lib/__tests__/agent-cache.test.ts +2 -0
- package/templates/docker/src/lib/__tests__/agent-dialect.test.ts +17 -0
- package/templates/docker/src/lib/__tests__/agent-health-annotations.test.ts +2 -0
- package/templates/docker/src/lib/__tests__/agent-integration.test.ts +2 -0
- package/templates/docker/src/lib/__tests__/config.test.ts +69 -19
- package/templates/docker/src/lib/__tests__/plugin-aware-validation.test.ts +321 -0
- package/templates/docker/src/lib/__tests__/providers.test.ts +32 -1
- package/templates/docker/src/lib/__tests__/startup-actions.test.ts +9 -0
- package/templates/docker/src/lib/__tests__/startup-first-run.test.ts +429 -0
- package/templates/docker/src/lib/__tests__/startup.test.ts +5 -0
- package/templates/docker/src/lib/agent-query.ts +5 -23
- package/templates/docker/src/lib/agent.ts +32 -112
- package/templates/docker/src/lib/auth/__tests__/migrate.test.ts +5 -3
- package/templates/docker/src/lib/auth/middleware.ts +30 -4
- package/templates/docker/src/lib/auth/migrate.ts +97 -0
- package/templates/docker/src/lib/auth/server.ts +12 -1
- package/templates/docker/src/lib/config.ts +37 -39
- package/templates/docker/src/lib/db/__tests__/connection.test.ts +89 -14
- package/templates/docker/src/lib/db/__tests__/registry-health.test.ts +1 -18
- package/templates/docker/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -19
- package/templates/docker/src/lib/db/__tests__/registry.test.ts +11 -208
- package/templates/docker/src/lib/db/connection.ts +87 -265
- package/templates/docker/src/lib/db/internal.ts +6 -1
- package/templates/docker/src/lib/plugins/__tests__/hooks-integration.test.ts +3 -1
- package/templates/docker/src/lib/plugins/__tests__/hooks.test.ts +2 -2
- package/templates/docker/src/lib/plugins/__tests__/migrate.test.ts +355 -1
- package/templates/docker/src/lib/plugins/__tests__/registry.test.ts +32 -5
- package/templates/docker/src/lib/plugins/__tests__/wiring.test.ts +228 -14
- package/templates/docker/src/lib/plugins/index.ts +4 -1
- package/templates/docker/src/lib/plugins/migrate.ts +103 -0
- package/templates/docker/src/lib/plugins/registry.ts +12 -6
- package/templates/docker/src/lib/plugins/wiring.ts +113 -4
- package/templates/docker/src/lib/providers.ts +6 -1
- package/templates/docker/src/lib/security.ts +24 -0
- package/templates/docker/src/lib/semantic.ts +2 -0
- package/templates/docker/src/lib/sidecar-types.ts +12 -1
- package/templates/docker/src/lib/startup.ts +71 -101
- package/templates/docker/src/lib/tools/__tests__/custom-validation.test.ts +2 -0
- package/templates/docker/src/lib/tools/__tests__/explore-nsjail.test.ts +32 -18
- package/templates/docker/src/lib/tools/__tests__/explore-plugin.test.ts +14 -14
- package/templates/docker/src/lib/tools/__tests__/explore-sidecar.test.ts +5 -3
- package/templates/docker/src/lib/tools/__tests__/python-nsjail.test.ts +515 -0
- package/templates/docker/src/lib/tools/__tests__/python-sandbox.test.ts +397 -0
- package/templates/docker/src/lib/tools/__tests__/python-sidecar.test.ts +365 -0
- package/templates/docker/src/lib/tools/__tests__/python.test.ts +331 -0
- package/templates/docker/src/lib/tools/__tests__/registry-actions.test.ts +1 -13
- package/templates/docker/src/lib/tools/__tests__/registry.test.ts +38 -31
- package/templates/docker/src/lib/tools/__tests__/sql-audit.test.ts +2 -0
- package/templates/docker/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +2 -0
- package/templates/docker/src/lib/tools/__tests__/sql-ratelimit.test.ts +2 -0
- package/templates/docker/src/lib/tools/__tests__/sql.test.ts +5 -308
- package/templates/docker/src/lib/tools/explore-nsjail.ts +17 -12
- package/templates/docker/src/lib/tools/explore-sidecar.ts +25 -0
- package/templates/docker/src/lib/tools/explore.ts +28 -32
- package/templates/docker/src/lib/tools/python-nsjail.ts +396 -0
- package/templates/docker/src/lib/tools/python-sandbox.ts +476 -0
- package/templates/docker/src/lib/tools/python-sidecar.ts +150 -0
- package/templates/docker/src/lib/tools/python.ts +367 -0
- package/templates/docker/src/lib/tools/registry.ts +49 -22
- package/templates/docker/src/lib/tools/sql.ts +88 -88
- package/templates/docker/src/types/vercel-sandbox.d.ts +7 -0
- package/templates/docker/src/ui/components/admin/admin-layout.tsx +77 -8
- package/templates/docker/src/ui/components/admin/admin-sidebar.tsx +25 -17
- package/templates/docker/src/ui/components/admin/change-password-dialog.tsx +128 -0
- package/templates/docker/src/ui/components/admin/entity-detail.tsx +3 -3
- package/templates/docker/src/ui/components/admin/semantic-file-tree.tsx +159 -0
- package/templates/docker/src/ui/components/atlas-chat.tsx +64 -12
- package/templates/docker/src/ui/components/chart/result-chart.tsx +25 -15
- package/templates/docker/src/ui/components/chat/markdown.tsx +88 -42
- package/templates/docker/src/ui/components/chat/python-result-card.tsx +244 -0
- package/templates/docker/src/ui/components/chat/sql-block.tsx +39 -15
- package/templates/docker/src/ui/components/chat/sql-result-card.tsx +6 -1
- package/templates/docker/src/ui/components/chat/tool-part.tsx +12 -3
- package/templates/docker/src/ui/components/chat/typing-indicator.tsx +5 -2
- package/templates/docker/src/ui/components/conversations/conversation-item.tsx +25 -20
- package/templates/docker/src/ui/context.tsx +1 -1
- package/templates/docker/src/ui/hooks/use-conversations.ts +3 -3
- package/templates/docker/src/ui/hooks/use-dark-mode.ts +17 -10
- package/templates/docker/tsconfig.json +2 -2
- package/templates/nextjs-standalone/.env.example +1 -1
- package/templates/nextjs-standalone/bin/__tests__/plugin-cli.test.ts +9 -9
- package/templates/nextjs-standalone/bin/atlas.ts +108 -44
- package/templates/nextjs-standalone/data/demo-semantic/catalog.yml +51 -27
- package/templates/nextjs-standalone/data/demo-semantic/entities/accounts.yml +95 -103
- package/templates/nextjs-standalone/data/demo-semantic/entities/companies.yml +88 -152
- package/templates/nextjs-standalone/data/demo-semantic/entities/people.yml +82 -95
- package/templates/nextjs-standalone/data/demo-semantic/glossary.yml +104 -8
- package/templates/nextjs-standalone/data/demo-semantic/metrics/accounts.yml +62 -23
- package/templates/nextjs-standalone/data/demo-semantic/metrics/companies.yml +52 -78
- package/templates/nextjs-standalone/docs/deploy.md +2 -39
- package/templates/nextjs-standalone/package.json +11 -2
- package/templates/nextjs-standalone/scripts/migrate-auth.ts +25 -0
- package/templates/nextjs-standalone/scripts/seed-demo.ts +94 -0
- package/templates/nextjs-standalone/semantic/catalog.yml +62 -3
- package/templates/nextjs-standalone/semantic/entities/accounts.yml +162 -0
- package/templates/nextjs-standalone/semantic/entities/companies.yml +143 -0
- package/templates/nextjs-standalone/semantic/entities/people.yml +132 -0
- package/templates/nextjs-standalone/semantic/glossary.yml +116 -4
- package/templates/nextjs-standalone/semantic/metrics/accounts.yml +77 -0
- package/templates/nextjs-standalone/semantic/metrics/companies.yml +63 -0
- package/templates/nextjs-standalone/src/api/__tests__/admin.test.ts +7 -7
- package/templates/nextjs-standalone/src/api/__tests__/health-plugin.test.ts +7 -0
- package/templates/nextjs-standalone/src/api/__tests__/health.test.ts +30 -8
- package/templates/nextjs-standalone/src/api/routes/admin.ts +549 -8
- package/templates/nextjs-standalone/src/api/routes/chat.ts +5 -20
- package/templates/nextjs-standalone/src/api/routes/health.ts +39 -27
- package/templates/nextjs-standalone/src/api/routes/openapi.ts +1329 -74
- package/templates/nextjs-standalone/src/api/routes/query.ts +2 -1
- package/templates/nextjs-standalone/src/api/server.ts +27 -0
- package/templates/nextjs-standalone/src/app/api/[...route]/route.ts +2 -2
- package/templates/nextjs-standalone/src/app/globals.css +13 -12
- package/templates/nextjs-standalone/src/app/layout.tsx +9 -2
- package/templates/nextjs-standalone/src/components/ui/alert-dialog.tsx +196 -0
- package/templates/nextjs-standalone/src/components/ui/badge.tsx +48 -0
- package/templates/nextjs-standalone/src/components/ui/button.tsx +64 -0
- package/templates/nextjs-standalone/src/components/ui/card.tsx +92 -0
- package/templates/nextjs-standalone/src/components/ui/collapsible.tsx +33 -0
- package/templates/nextjs-standalone/src/components/ui/command.tsx +184 -0
- package/templates/nextjs-standalone/src/components/ui/dialog.tsx +158 -0
- package/templates/nextjs-standalone/src/components/ui/dropdown-menu.tsx +257 -0
- package/templates/nextjs-standalone/src/components/ui/input.tsx +21 -0
- package/templates/nextjs-standalone/src/components/ui/scroll-area.tsx +58 -0
- package/templates/nextjs-standalone/src/components/ui/select.tsx +190 -0
- package/templates/nextjs-standalone/src/components/ui/separator.tsx +28 -0
- package/templates/nextjs-standalone/src/components/ui/sheet.tsx +143 -0
- package/templates/nextjs-standalone/src/components/ui/sidebar.tsx +726 -0
- package/templates/nextjs-standalone/src/components/ui/skeleton.tsx +13 -0
- package/templates/nextjs-standalone/src/components/ui/table.tsx +116 -0
- package/templates/nextjs-standalone/src/components/ui/tabs.tsx +91 -0
- package/templates/nextjs-standalone/src/components/ui/toggle-group.tsx +83 -0
- package/templates/nextjs-standalone/src/components/ui/toggle.tsx +47 -0
- package/templates/nextjs-standalone/src/components/ui/tooltip.tsx +57 -0
- package/templates/nextjs-standalone/src/hooks/use-mobile.ts +19 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-cache.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-dialect.test.ts +17 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-health-annotations.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/__tests__/agent-integration.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/__tests__/config.test.ts +69 -19
- package/templates/nextjs-standalone/src/lib/__tests__/plugin-aware-validation.test.ts +321 -0
- package/templates/nextjs-standalone/src/lib/__tests__/providers.test.ts +32 -1
- package/templates/nextjs-standalone/src/lib/__tests__/startup-actions.test.ts +9 -0
- package/templates/nextjs-standalone/src/lib/__tests__/startup-first-run.test.ts +429 -0
- package/templates/nextjs-standalone/src/lib/__tests__/startup.test.ts +5 -0
- package/templates/nextjs-standalone/src/lib/agent-query.ts +5 -23
- package/templates/nextjs-standalone/src/lib/agent.ts +32 -112
- package/templates/nextjs-standalone/src/lib/auth/__tests__/migrate.test.ts +5 -3
- package/templates/nextjs-standalone/src/lib/auth/middleware.ts +30 -4
- package/templates/nextjs-standalone/src/lib/auth/migrate.ts +97 -0
- package/templates/nextjs-standalone/src/lib/auth/server.ts +12 -1
- package/templates/nextjs-standalone/src/lib/config.ts +37 -39
- package/templates/nextjs-standalone/src/lib/db/__tests__/connection.test.ts +89 -14
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry-health.test.ts +1 -18
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry-pool-limits.test.ts +0 -19
- package/templates/nextjs-standalone/src/lib/db/__tests__/registry.test.ts +11 -208
- package/templates/nextjs-standalone/src/lib/db/connection.ts +87 -265
- package/templates/nextjs-standalone/src/lib/db/internal.ts +6 -1
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks-integration.test.ts +3 -1
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/hooks.test.ts +2 -2
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/migrate.test.ts +355 -1
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/registry.test.ts +32 -5
- package/templates/nextjs-standalone/src/lib/plugins/__tests__/wiring.test.ts +228 -14
- package/templates/nextjs-standalone/src/lib/plugins/index.ts +4 -1
- package/templates/nextjs-standalone/src/lib/plugins/migrate.ts +103 -0
- package/templates/nextjs-standalone/src/lib/plugins/registry.ts +12 -6
- package/templates/nextjs-standalone/src/lib/plugins/wiring.ts +113 -4
- package/templates/nextjs-standalone/src/lib/providers.ts +6 -1
- package/templates/nextjs-standalone/src/lib/security.ts +24 -0
- package/templates/nextjs-standalone/src/lib/semantic.ts +2 -0
- package/templates/nextjs-standalone/src/lib/sidecar-types.ts +12 -1
- package/templates/nextjs-standalone/src/lib/startup.ts +71 -101
- package/templates/nextjs-standalone/src/lib/tools/__tests__/custom-validation.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-nsjail.test.ts +32 -18
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-plugin.test.ts +14 -14
- package/templates/nextjs-standalone/src/lib/tools/__tests__/explore-sidecar.test.ts +5 -3
- package/templates/nextjs-standalone/src/lib/tools/__tests__/python-nsjail.test.ts +515 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sandbox.test.ts +397 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/python-sidecar.test.ts +365 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/python.test.ts +331 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/registry-actions.test.ts +1 -13
- package/templates/nextjs-standalone/src/lib/tools/__tests__/registry.test.ts +38 -31
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-audit.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-connection-whitelist.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-ratelimit.test.ts +2 -0
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql.test.ts +5 -308
- package/templates/nextjs-standalone/src/lib/tools/explore-nsjail.ts +17 -12
- package/templates/nextjs-standalone/src/lib/tools/explore-sidecar.ts +25 -0
- package/templates/nextjs-standalone/src/lib/tools/explore.ts +28 -32
- package/templates/nextjs-standalone/src/lib/tools/python-nsjail.ts +396 -0
- package/templates/nextjs-standalone/src/lib/tools/python-sandbox.ts +476 -0
- package/templates/nextjs-standalone/src/lib/tools/python-sidecar.ts +150 -0
- package/templates/nextjs-standalone/src/lib/tools/python.ts +367 -0
- package/templates/nextjs-standalone/src/lib/tools/registry.ts +49 -22
- package/templates/nextjs-standalone/src/lib/tools/sql.ts +88 -88
- package/templates/nextjs-standalone/src/ui/components/admin/admin-layout.tsx +77 -8
- package/templates/nextjs-standalone/src/ui/components/admin/admin-sidebar.tsx +25 -17
- package/templates/nextjs-standalone/src/ui/components/admin/change-password-dialog.tsx +128 -0
- package/templates/nextjs-standalone/src/ui/components/admin/entity-detail.tsx +3 -3
- package/templates/nextjs-standalone/src/ui/components/admin/semantic-file-tree.tsx +159 -0
- package/templates/nextjs-standalone/src/ui/components/atlas-chat.tsx +64 -12
- package/templates/nextjs-standalone/src/ui/components/chart/result-chart.tsx +25 -15
- package/templates/nextjs-standalone/src/ui/components/chat/markdown.tsx +88 -42
- package/templates/nextjs-standalone/src/ui/components/chat/python-result-card.tsx +244 -0
- package/templates/nextjs-standalone/src/ui/components/chat/sql-block.tsx +39 -15
- package/templates/nextjs-standalone/src/ui/components/chat/sql-result-card.tsx +6 -1
- package/templates/nextjs-standalone/src/ui/components/chat/tool-part.tsx +12 -3
- package/templates/nextjs-standalone/src/ui/components/chat/typing-indicator.tsx +5 -2
- package/templates/nextjs-standalone/src/ui/components/conversations/conversation-item.tsx +25 -20
- package/templates/nextjs-standalone/src/ui/context.tsx +1 -1
- package/templates/nextjs-standalone/src/ui/hooks/use-conversations.ts +3 -3
- package/templates/nextjs-standalone/src/ui/hooks/use-dark-mode.ts +17 -10
- package/templates/nextjs-standalone/tsconfig.json +0 -1
- package/templates/nextjs-standalone/vercel.json +4 -1
- package/templates/docker/render.yaml +0 -34
- package/templates/docker/semantic/entities/.gitkeep +0 -0
- package/templates/docker/semantic/metrics/.gitkeep +0 -0
- package/templates/docker/src/lib/db/__tests__/duckdb.test.ts +0 -141
- package/templates/docker/src/lib/db/__tests__/salesforce.test.ts +0 -339
- package/templates/docker/src/lib/db/__tests__/snowflake.test.ts +0 -217
- package/templates/docker/src/lib/db/duckdb.ts +0 -122
- package/templates/docker/src/lib/db/salesforce.ts +0 -342
- package/templates/docker/src/lib/tools/__tests__/salesforce-tool.test.ts +0 -154
- package/templates/docker/src/lib/tools/__tests__/soql-validation.test.ts +0 -303
- package/templates/docker/src/lib/tools/__tests__/sql-duckdb.test.ts +0 -233
- package/templates/docker/src/lib/tools/salesforce.ts +0 -138
- package/templates/docker/src/lib/tools/soql-validation.ts +0 -172
- package/templates/nextjs-standalone/semantic/entities/.gitkeep +0 -0
- package/templates/nextjs-standalone/semantic/metrics/.gitkeep +0 -0
- package/templates/nextjs-standalone/src/lib/db/__tests__/duckdb.test.ts +0 -141
- package/templates/nextjs-standalone/src/lib/db/__tests__/salesforce.test.ts +0 -339
- package/templates/nextjs-standalone/src/lib/db/__tests__/snowflake.test.ts +0 -217
- package/templates/nextjs-standalone/src/lib/db/duckdb.ts +0 -122
- package/templates/nextjs-standalone/src/lib/db/salesforce.ts +0 -342
- package/templates/nextjs-standalone/src/lib/tools/__tests__/salesforce-tool.test.ts +0 -154
- package/templates/nextjs-standalone/src/lib/tools/__tests__/soql-validation.test.ts +0 -303
- package/templates/nextjs-standalone/src/lib/tools/__tests__/sql-duckdb.test.ts +0 -233
- package/templates/nextjs-standalone/src/lib/tools/salesforce.ts +0 -138
- package/templates/nextjs-standalone/src/lib/tools/soql-validation.ts +0 -172
|
@@ -12,6 +12,7 @@ import { ChatRequestSchema } from "./chat";
|
|
|
12
12
|
import {
|
|
13
13
|
ConversationWithMessagesSchema,
|
|
14
14
|
ListConversationsResponseSchema,
|
|
15
|
+
StarConversationBodySchema,
|
|
15
16
|
} from "./conversations";
|
|
16
17
|
import { HealthResponseSchema } from "./health";
|
|
17
18
|
|
|
@@ -21,6 +22,40 @@ function toJsonSchema(schema: z.ZodType): Record<string, unknown> {
|
|
|
21
22
|
return z.toJSONSchema(schema) as Record<string, unknown>;
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Reusable parameter definitions
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
const uuidPathParam = (name: string, description: string) => ({
|
|
30
|
+
name,
|
|
31
|
+
in: "path" as const,
|
|
32
|
+
description,
|
|
33
|
+
required: true,
|
|
34
|
+
schema: { type: "string", format: "uuid" },
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const paginationParams = (defaults?: { limit?: number; maxLimit?: number }) => [
|
|
38
|
+
{
|
|
39
|
+
name: "limit",
|
|
40
|
+
in: "query" as const,
|
|
41
|
+
description: `Maximum number of items to return (1-${defaults?.maxLimit ?? 100}, default ${defaults?.limit ?? 20}).`,
|
|
42
|
+
required: false,
|
|
43
|
+
schema: {
|
|
44
|
+
type: "integer",
|
|
45
|
+
minimum: 1,
|
|
46
|
+
maximum: defaults?.maxLimit ?? 100,
|
|
47
|
+
default: defaults?.limit ?? 20,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "offset",
|
|
52
|
+
in: "query" as const,
|
|
53
|
+
description: "Number of items to skip (default 0).",
|
|
54
|
+
required: false,
|
|
55
|
+
schema: { type: "integer", minimum: 0, default: 0 },
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
|
|
24
59
|
function buildSpec(): Record<string, unknown> {
|
|
25
60
|
const ErrorSchema = z.object({
|
|
26
61
|
error: z.string(),
|
|
@@ -45,14 +80,32 @@ function buildSpec(): Record<string, unknown> {
|
|
|
45
80
|
content: { "application/json": { schema: toJsonSchema(schema) } },
|
|
46
81
|
});
|
|
47
82
|
|
|
83
|
+
// Common error responses shared across most routes
|
|
84
|
+
const authErrors = {
|
|
85
|
+
"401": errorResponse("Authentication required"),
|
|
86
|
+
"403": errorResponse("Forbidden — insufficient permissions"),
|
|
87
|
+
"429": errorResponse("Rate limit exceeded", RateLimitErrorSchema),
|
|
88
|
+
"500": errorResponse("Internal server error"),
|
|
89
|
+
};
|
|
90
|
+
|
|
48
91
|
return {
|
|
49
92
|
openapi: "3.1.0",
|
|
50
93
|
info: {
|
|
51
94
|
title: "Atlas API",
|
|
52
|
-
version: "1.0
|
|
95
|
+
version: "0.1.0",
|
|
53
96
|
description:
|
|
54
97
|
"Text-to-SQL data analyst agent. Ask natural-language questions about your data and receive structured answers.",
|
|
55
98
|
},
|
|
99
|
+
servers: [
|
|
100
|
+
{
|
|
101
|
+
url: "http://localhost:3001",
|
|
102
|
+
description: "Standalone API (development)",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
url: "http://localhost:3000",
|
|
106
|
+
description: "Same-origin via Next.js rewrites",
|
|
107
|
+
},
|
|
108
|
+
],
|
|
56
109
|
paths: {
|
|
57
110
|
// -----------------------------------------------------------------
|
|
58
111
|
// POST /api/chat — Streaming chat (SSE)
|
|
@@ -106,6 +159,10 @@ function buildSpec(): Record<string, unknown> {
|
|
|
106
159
|
"404": errorResponse(
|
|
107
160
|
"Conversation not found (invalid conversationId)",
|
|
108
161
|
),
|
|
162
|
+
"422": errorResponse(
|
|
163
|
+
"Validation error (invalid request body)",
|
|
164
|
+
ValidationErrorSchema,
|
|
165
|
+
),
|
|
109
166
|
"429": errorResponse(
|
|
110
167
|
"Rate limit exceeded",
|
|
111
168
|
RateLimitErrorSchema,
|
|
@@ -183,30 +240,13 @@ function buildSpec(): Record<string, unknown> {
|
|
|
183
240
|
tags: ["Conversations"],
|
|
184
241
|
security: [{ bearerAuth: [] }, {}],
|
|
185
242
|
parameters: [
|
|
243
|
+
...paginationParams(),
|
|
186
244
|
{
|
|
187
|
-
name: "
|
|
188
|
-
in: "query",
|
|
189
|
-
description:
|
|
190
|
-
"Maximum number of conversations to return (1-100, default 20).",
|
|
191
|
-
required: false,
|
|
192
|
-
schema: {
|
|
193
|
-
type: "integer",
|
|
194
|
-
minimum: 1,
|
|
195
|
-
maximum: 100,
|
|
196
|
-
default: 20,
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
name: "offset",
|
|
245
|
+
name: "starred",
|
|
201
246
|
in: "query",
|
|
202
|
-
description:
|
|
203
|
-
"Number of conversations to skip (default 0).",
|
|
247
|
+
description: "Filter by starred status.",
|
|
204
248
|
required: false,
|
|
205
|
-
schema: {
|
|
206
|
-
type: "integer",
|
|
207
|
-
minimum: 0,
|
|
208
|
-
default: 0,
|
|
209
|
-
},
|
|
249
|
+
schema: { type: "boolean" },
|
|
210
250
|
},
|
|
211
251
|
],
|
|
212
252
|
responses: {
|
|
@@ -218,22 +258,16 @@ function buildSpec(): Record<string, unknown> {
|
|
|
218
258
|
},
|
|
219
259
|
},
|
|
220
260
|
},
|
|
221
|
-
|
|
222
|
-
"403": errorResponse("Forbidden — insufficient permissions"),
|
|
261
|
+
...authErrors,
|
|
223
262
|
"404": errorResponse(
|
|
224
263
|
"Not available (no internal database configured)",
|
|
225
264
|
),
|
|
226
|
-
"429": errorResponse(
|
|
227
|
-
"Rate limit exceeded",
|
|
228
|
-
RateLimitErrorSchema,
|
|
229
|
-
),
|
|
230
|
-
"500": errorResponse("Internal server error"),
|
|
231
265
|
},
|
|
232
266
|
},
|
|
233
267
|
},
|
|
234
268
|
|
|
235
269
|
// -----------------------------------------------------------------
|
|
236
|
-
// GET /api/v1/conversations/{id}
|
|
270
|
+
// GET/DELETE /api/v1/conversations/{id}
|
|
237
271
|
// -----------------------------------------------------------------
|
|
238
272
|
"/api/v1/conversations/{id}": {
|
|
239
273
|
get: {
|
|
@@ -244,13 +278,7 @@ function buildSpec(): Record<string, unknown> {
|
|
|
244
278
|
tags: ["Conversations"],
|
|
245
279
|
security: [{ bearerAuth: [] }, {}],
|
|
246
280
|
parameters: [
|
|
247
|
-
|
|
248
|
-
name: "id",
|
|
249
|
-
in: "path",
|
|
250
|
-
description: "Conversation UUID.",
|
|
251
|
-
required: true,
|
|
252
|
-
schema: { type: "string", format: "uuid" },
|
|
253
|
-
},
|
|
281
|
+
uuidPathParam("id", "Conversation UUID."),
|
|
254
282
|
],
|
|
255
283
|
responses: {
|
|
256
284
|
"200": {
|
|
@@ -262,16 +290,10 @@ function buildSpec(): Record<string, unknown> {
|
|
|
262
290
|
},
|
|
263
291
|
},
|
|
264
292
|
"400": errorResponse("Invalid conversation ID format"),
|
|
265
|
-
|
|
266
|
-
"403": errorResponse("Forbidden — insufficient permissions"),
|
|
293
|
+
...authErrors,
|
|
267
294
|
"404": errorResponse(
|
|
268
295
|
"Conversation not found or not available",
|
|
269
296
|
),
|
|
270
|
-
"429": errorResponse(
|
|
271
|
-
"Rate limit exceeded",
|
|
272
|
-
RateLimitErrorSchema,
|
|
273
|
-
),
|
|
274
|
-
"500": errorResponse("Internal server error"),
|
|
275
297
|
},
|
|
276
298
|
},
|
|
277
299
|
delete: {
|
|
@@ -282,29 +304,60 @@ function buildSpec(): Record<string, unknown> {
|
|
|
282
304
|
tags: ["Conversations"],
|
|
283
305
|
security: [{ bearerAuth: [] }, {}],
|
|
284
306
|
parameters: [
|
|
285
|
-
|
|
286
|
-
name: "id",
|
|
287
|
-
in: "path",
|
|
288
|
-
description: "Conversation UUID.",
|
|
289
|
-
required: true,
|
|
290
|
-
schema: { type: "string", format: "uuid" },
|
|
291
|
-
},
|
|
307
|
+
uuidPathParam("id", "Conversation UUID."),
|
|
292
308
|
],
|
|
293
309
|
responses: {
|
|
294
310
|
"204": {
|
|
295
311
|
description: "Conversation deleted successfully",
|
|
296
312
|
},
|
|
297
313
|
"400": errorResponse("Invalid conversation ID format"),
|
|
298
|
-
|
|
299
|
-
"403": errorResponse("Forbidden — insufficient permissions"),
|
|
314
|
+
...authErrors,
|
|
300
315
|
"404": errorResponse(
|
|
301
316
|
"Conversation not found or not available",
|
|
302
317
|
),
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
|
|
322
|
+
// -----------------------------------------------------------------
|
|
323
|
+
// PATCH /api/v1/conversations/{id}/star
|
|
324
|
+
// -----------------------------------------------------------------
|
|
325
|
+
"/api/v1/conversations/{id}/star": {
|
|
326
|
+
patch: {
|
|
327
|
+
operationId: "starConversation",
|
|
328
|
+
summary: "Star or unstar a conversation",
|
|
329
|
+
description: "Sets the starred status of a conversation.",
|
|
330
|
+
tags: ["Conversations"],
|
|
331
|
+
security: [{ bearerAuth: [] }, {}],
|
|
332
|
+
parameters: [
|
|
333
|
+
uuidPathParam("id", "Conversation UUID."),
|
|
334
|
+
],
|
|
335
|
+
requestBody: {
|
|
336
|
+
required: true,
|
|
337
|
+
content: {
|
|
338
|
+
"application/json": {
|
|
339
|
+
schema: toJsonSchema(StarConversationBodySchema),
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
responses: {
|
|
344
|
+
"200": {
|
|
345
|
+
description: "Star status updated",
|
|
346
|
+
content: {
|
|
347
|
+
"application/json": {
|
|
348
|
+
schema: {
|
|
349
|
+
type: "object",
|
|
350
|
+
properties: {
|
|
351
|
+
id: { type: "string", format: "uuid" },
|
|
352
|
+
starred: { type: "boolean" },
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
"400": errorResponse("Invalid conversation ID or request body"),
|
|
359
|
+
...authErrors,
|
|
360
|
+
"404": errorResponse("Conversation not found or not available"),
|
|
308
361
|
},
|
|
309
362
|
},
|
|
310
363
|
},
|
|
@@ -352,28 +405,1230 @@ function buildSpec(): Record<string, unknown> {
|
|
|
352
405
|
},
|
|
353
406
|
},
|
|
354
407
|
},
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
408
|
+
|
|
409
|
+
// -----------------------------------------------------------------
|
|
410
|
+
// Actions — approval-gated write operations
|
|
411
|
+
// -----------------------------------------------------------------
|
|
412
|
+
"/api/v1/actions": {
|
|
413
|
+
get: {
|
|
414
|
+
operationId: "listActions",
|
|
415
|
+
summary: "List actions",
|
|
361
416
|
description:
|
|
362
|
-
"
|
|
417
|
+
"Returns actions filtered by status. Requires ATLAS_ACTIONS_ENABLED=true and an internal database.",
|
|
418
|
+
tags: ["Actions"],
|
|
419
|
+
security: [{ bearerAuth: [] }, {}],
|
|
420
|
+
parameters: [
|
|
421
|
+
{
|
|
422
|
+
name: "status",
|
|
423
|
+
in: "query",
|
|
424
|
+
description: "Filter by action status (default: pending).",
|
|
425
|
+
required: false,
|
|
426
|
+
schema: {
|
|
427
|
+
type: "string",
|
|
428
|
+
enum: ["pending", "approved", "denied", "executed", "failed", "timed_out", "auto_approved"],
|
|
429
|
+
default: "pending",
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
name: "limit",
|
|
434
|
+
in: "query",
|
|
435
|
+
description: "Maximum number of actions to return (1-100, default 50).",
|
|
436
|
+
required: false,
|
|
437
|
+
schema: { type: "integer", minimum: 1, maximum: 100, default: 50 },
|
|
438
|
+
},
|
|
439
|
+
],
|
|
440
|
+
responses: {
|
|
441
|
+
"200": {
|
|
442
|
+
description: "List of actions",
|
|
443
|
+
content: {
|
|
444
|
+
"application/json": {
|
|
445
|
+
schema: {
|
|
446
|
+
type: "object",
|
|
447
|
+
properties: {
|
|
448
|
+
actions: {
|
|
449
|
+
type: "array",
|
|
450
|
+
items: {
|
|
451
|
+
type: "object",
|
|
452
|
+
properties: {
|
|
453
|
+
id: { type: "string", format: "uuid" },
|
|
454
|
+
action_type: { type: "string" },
|
|
455
|
+
target: { type: "string" },
|
|
456
|
+
summary: { type: "string" },
|
|
457
|
+
status: { type: "string", enum: ["pending", "approved", "denied", "executed", "failed", "timed_out", "auto_approved"] },
|
|
458
|
+
requested_by: { type: "string" },
|
|
459
|
+
created_at: { type: "string", format: "date-time" },
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
...authErrors,
|
|
469
|
+
"404": errorResponse("Actions not available (no internal database or feature disabled)"),
|
|
470
|
+
},
|
|
363
471
|
},
|
|
364
472
|
},
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
473
|
+
|
|
474
|
+
"/api/v1/actions/{id}": {
|
|
475
|
+
get: {
|
|
476
|
+
operationId: "getAction",
|
|
477
|
+
summary: "Get action by ID",
|
|
478
|
+
description: "Returns a single action. Only returns actions requested by the authenticated user.",
|
|
479
|
+
tags: ["Actions"],
|
|
480
|
+
security: [{ bearerAuth: [] }, {}],
|
|
481
|
+
parameters: [uuidPathParam("id", "Action UUID.")],
|
|
482
|
+
responses: {
|
|
483
|
+
"200": {
|
|
484
|
+
description: "Action details",
|
|
485
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
486
|
+
},
|
|
487
|
+
"400": errorResponse("Invalid action ID format"),
|
|
488
|
+
...authErrors,
|
|
489
|
+
"404": errorResponse("Action not found"),
|
|
490
|
+
},
|
|
491
|
+
},
|
|
371
492
|
},
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
493
|
+
|
|
494
|
+
"/api/v1/actions/{id}/approve": {
|
|
495
|
+
post: {
|
|
496
|
+
operationId: "approveAction",
|
|
497
|
+
summary: "Approve a pending action",
|
|
498
|
+
description:
|
|
499
|
+
"Approves a pending action and triggers execution. Returns the updated action with results. " +
|
|
500
|
+
"For admin-only approval mode, the requester cannot approve their own action (separation of duties).",
|
|
501
|
+
tags: ["Actions"],
|
|
502
|
+
security: [{ bearerAuth: [] }],
|
|
503
|
+
parameters: [uuidPathParam("id", "Action UUID.")],
|
|
504
|
+
responses: {
|
|
505
|
+
"200": {
|
|
506
|
+
description: "Action approved and execution result",
|
|
507
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
508
|
+
},
|
|
509
|
+
"400": errorResponse("Invalid action ID format"),
|
|
510
|
+
...authErrors,
|
|
511
|
+
"404": errorResponse("Action not found"),
|
|
512
|
+
"409": errorResponse("Action has already been resolved"),
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
|
|
517
|
+
"/api/v1/actions/{id}/deny": {
|
|
518
|
+
post: {
|
|
519
|
+
operationId: "denyAction",
|
|
520
|
+
summary: "Deny a pending action",
|
|
521
|
+
description:
|
|
522
|
+
"Denies a pending action. Optionally provide a reason in the request body. " +
|
|
523
|
+
"For admin-only approval mode, the requester cannot deny their own action.",
|
|
524
|
+
tags: ["Actions"],
|
|
525
|
+
security: [{ bearerAuth: [] }],
|
|
526
|
+
parameters: [uuidPathParam("id", "Action UUID.")],
|
|
527
|
+
requestBody: {
|
|
528
|
+
required: false,
|
|
529
|
+
content: {
|
|
530
|
+
"application/json": {
|
|
531
|
+
schema: {
|
|
532
|
+
type: "object",
|
|
533
|
+
properties: {
|
|
534
|
+
reason: { type: "string", description: "Optional denial reason." },
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
responses: {
|
|
541
|
+
"200": {
|
|
542
|
+
description: "Action denied",
|
|
543
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
544
|
+
},
|
|
545
|
+
"400": errorResponse("Invalid action ID or request body"),
|
|
546
|
+
...authErrors,
|
|
547
|
+
"404": errorResponse("Action not found"),
|
|
548
|
+
"409": errorResponse("Action has already been resolved"),
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
},
|
|
552
|
+
|
|
553
|
+
// -----------------------------------------------------------------
|
|
554
|
+
// Scheduled Tasks
|
|
555
|
+
// -----------------------------------------------------------------
|
|
556
|
+
"/api/v1/scheduled-tasks": {
|
|
557
|
+
get: {
|
|
558
|
+
operationId: "listScheduledTasks",
|
|
559
|
+
summary: "List scheduled tasks",
|
|
560
|
+
description:
|
|
561
|
+
"Returns scheduled tasks owned by the authenticated user. Requires ATLAS_SCHEDULER_ENABLED=true and an internal database.",
|
|
562
|
+
tags: ["Scheduled Tasks"],
|
|
563
|
+
security: [{ bearerAuth: [] }, {}],
|
|
564
|
+
parameters: [
|
|
565
|
+
...paginationParams(),
|
|
566
|
+
{
|
|
567
|
+
name: "enabled",
|
|
568
|
+
in: "query",
|
|
569
|
+
description: "Filter by enabled status.",
|
|
570
|
+
required: false,
|
|
571
|
+
schema: { type: "boolean" },
|
|
572
|
+
},
|
|
573
|
+
],
|
|
574
|
+
responses: {
|
|
575
|
+
"200": {
|
|
576
|
+
description: "Paginated list of scheduled tasks",
|
|
577
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
578
|
+
},
|
|
579
|
+
...authErrors,
|
|
580
|
+
"404": errorResponse("Scheduled tasks not available (no internal database or feature disabled)"),
|
|
581
|
+
},
|
|
582
|
+
},
|
|
583
|
+
post: {
|
|
584
|
+
operationId: "createScheduledTask",
|
|
585
|
+
summary: "Create a scheduled task",
|
|
586
|
+
description:
|
|
587
|
+
"Creates a recurring query task with a cron schedule and delivery channel.",
|
|
588
|
+
tags: ["Scheduled Tasks"],
|
|
589
|
+
security: [{ bearerAuth: [] }],
|
|
590
|
+
requestBody: {
|
|
591
|
+
required: true,
|
|
592
|
+
content: {
|
|
593
|
+
"application/json": {
|
|
594
|
+
schema: {
|
|
595
|
+
type: "object",
|
|
596
|
+
required: ["name", "question", "cronExpression"],
|
|
597
|
+
properties: {
|
|
598
|
+
name: { type: "string", minLength: 1, maxLength: 200, description: "Task name." },
|
|
599
|
+
question: { type: "string", minLength: 1, maxLength: 2000, description: "Natural language question." },
|
|
600
|
+
cronExpression: { type: "string", description: "Cron schedule (e.g. '0 9 * * *')." },
|
|
601
|
+
deliveryChannel: { type: "string", enum: ["email", "slack", "webhook"], default: "webhook", description: "Delivery channel." },
|
|
602
|
+
recipients: {
|
|
603
|
+
type: "array",
|
|
604
|
+
description: "Delivery targets.",
|
|
605
|
+
items: {
|
|
606
|
+
type: "object",
|
|
607
|
+
properties: {
|
|
608
|
+
type: { type: "string", enum: ["email", "slack", "webhook"] },
|
|
609
|
+
address: { type: "string", description: "Email address (for email type)." },
|
|
610
|
+
channel: { type: "string", description: "Slack channel (for slack type)." },
|
|
611
|
+
teamId: { type: "string", description: "Slack team ID (for slack type)." },
|
|
612
|
+
url: { type: "string", description: "Webhook URL (for webhook type)." },
|
|
613
|
+
headers: { type: "object", additionalProperties: { type: "string" }, description: "Custom headers (for webhook type)." },
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
connectionId: { type: "string", nullable: true, description: "Target datasource connection." },
|
|
618
|
+
approvalMode: { type: "string", enum: ["auto", "manual", "admin-only"], default: "auto", description: "Action approval mode." },
|
|
619
|
+
},
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
},
|
|
623
|
+
},
|
|
624
|
+
responses: {
|
|
625
|
+
"201": {
|
|
626
|
+
description: "Scheduled task created",
|
|
627
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
628
|
+
},
|
|
629
|
+
"400": errorResponse("Invalid request body or cron expression"),
|
|
630
|
+
...authErrors,
|
|
631
|
+
"404": errorResponse("Feature not available"),
|
|
632
|
+
},
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
|
|
636
|
+
"/api/v1/scheduled-tasks/tick": {
|
|
637
|
+
post: {
|
|
638
|
+
operationId: "schedulerTick",
|
|
639
|
+
summary: "Trigger scheduler tick",
|
|
640
|
+
description:
|
|
641
|
+
"Serverless scheduler tick endpoint for Vercel Cron or external cron services. " +
|
|
642
|
+
"Checks for due tasks and executes them. Requires CRON_SECRET or ATLAS_SCHEDULER_SECRET.",
|
|
643
|
+
tags: ["Scheduled Tasks"],
|
|
644
|
+
security: [{ bearerAuth: [] }],
|
|
645
|
+
responses: {
|
|
646
|
+
"200": {
|
|
647
|
+
description: "Tick completed",
|
|
648
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
649
|
+
},
|
|
650
|
+
"401": errorResponse("Invalid or missing cron secret"),
|
|
651
|
+
"500": errorResponse("Tick execution failed"),
|
|
652
|
+
},
|
|
653
|
+
},
|
|
654
|
+
},
|
|
655
|
+
|
|
656
|
+
"/api/v1/scheduled-tasks/{id}": {
|
|
657
|
+
get: {
|
|
658
|
+
operationId: "getScheduledTask",
|
|
659
|
+
summary: "Get scheduled task",
|
|
660
|
+
description: "Returns a scheduled task with its 10 most recent runs.",
|
|
661
|
+
tags: ["Scheduled Tasks"],
|
|
662
|
+
security: [{ bearerAuth: [] }, {}],
|
|
663
|
+
parameters: [uuidPathParam("id", "Task UUID.")],
|
|
664
|
+
responses: {
|
|
665
|
+
"200": {
|
|
666
|
+
description: "Scheduled task with recent runs",
|
|
667
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
668
|
+
},
|
|
669
|
+
"400": errorResponse("Invalid task ID format"),
|
|
670
|
+
...authErrors,
|
|
671
|
+
"404": errorResponse("Task not found"),
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
put: {
|
|
675
|
+
operationId: "updateScheduledTask",
|
|
676
|
+
summary: "Update a scheduled task",
|
|
677
|
+
description: "Updates a scheduled task. All fields are optional.",
|
|
678
|
+
tags: ["Scheduled Tasks"],
|
|
679
|
+
security: [{ bearerAuth: [] }],
|
|
680
|
+
parameters: [uuidPathParam("id", "Task UUID.")],
|
|
681
|
+
requestBody: {
|
|
682
|
+
required: true,
|
|
683
|
+
content: {
|
|
684
|
+
"application/json": {
|
|
685
|
+
schema: {
|
|
686
|
+
type: "object",
|
|
687
|
+
properties: {
|
|
688
|
+
name: { type: "string", minLength: 1, maxLength: 200 },
|
|
689
|
+
question: { type: "string", minLength: 1, maxLength: 2000 },
|
|
690
|
+
cronExpression: { type: "string" },
|
|
691
|
+
deliveryChannel: { type: "string", enum: ["email", "slack", "webhook"] },
|
|
692
|
+
recipients: { type: "array", items: { type: "object" } },
|
|
693
|
+
connectionId: { type: "string", nullable: true },
|
|
694
|
+
approvalMode: { type: "string", enum: ["auto", "manual", "admin-only"] },
|
|
695
|
+
enabled: { type: "boolean" },
|
|
696
|
+
},
|
|
697
|
+
},
|
|
698
|
+
},
|
|
699
|
+
},
|
|
700
|
+
},
|
|
701
|
+
responses: {
|
|
702
|
+
"200": {
|
|
703
|
+
description: "Updated scheduled task",
|
|
704
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
705
|
+
},
|
|
706
|
+
"400": errorResponse("Invalid request body or cron expression"),
|
|
707
|
+
...authErrors,
|
|
708
|
+
"404": errorResponse("Task not found"),
|
|
709
|
+
},
|
|
710
|
+
},
|
|
711
|
+
delete: {
|
|
712
|
+
operationId: "deleteScheduledTask",
|
|
713
|
+
summary: "Delete a scheduled task",
|
|
714
|
+
description: "Soft-deletes (disables) a scheduled task.",
|
|
715
|
+
tags: ["Scheduled Tasks"],
|
|
716
|
+
security: [{ bearerAuth: [] }],
|
|
717
|
+
parameters: [uuidPathParam("id", "Task UUID.")],
|
|
718
|
+
responses: {
|
|
719
|
+
"204": { description: "Task deleted successfully" },
|
|
720
|
+
"400": errorResponse("Invalid task ID format"),
|
|
721
|
+
...authErrors,
|
|
722
|
+
"404": errorResponse("Task not found"),
|
|
723
|
+
},
|
|
724
|
+
},
|
|
375
725
|
},
|
|
726
|
+
|
|
727
|
+
"/api/v1/scheduled-tasks/{id}/run": {
|
|
728
|
+
post: {
|
|
729
|
+
operationId: "triggerScheduledTask",
|
|
730
|
+
summary: "Trigger immediate execution",
|
|
731
|
+
description: "Triggers an immediate execution of a scheduled task.",
|
|
732
|
+
tags: ["Scheduled Tasks"],
|
|
733
|
+
security: [{ bearerAuth: [] }],
|
|
734
|
+
parameters: [uuidPathParam("id", "Task UUID.")],
|
|
735
|
+
responses: {
|
|
736
|
+
"200": {
|
|
737
|
+
description: "Task triggered",
|
|
738
|
+
content: {
|
|
739
|
+
"application/json": {
|
|
740
|
+
schema: {
|
|
741
|
+
type: "object",
|
|
742
|
+
properties: {
|
|
743
|
+
message: { type: "string" },
|
|
744
|
+
taskId: { type: "string", format: "uuid" },
|
|
745
|
+
},
|
|
746
|
+
},
|
|
747
|
+
},
|
|
748
|
+
},
|
|
749
|
+
},
|
|
750
|
+
"400": errorResponse("Invalid task ID format"),
|
|
751
|
+
...authErrors,
|
|
752
|
+
"404": errorResponse("Task not found"),
|
|
753
|
+
},
|
|
754
|
+
},
|
|
755
|
+
},
|
|
756
|
+
|
|
757
|
+
"/api/v1/scheduled-tasks/{id}/runs": {
|
|
758
|
+
get: {
|
|
759
|
+
operationId: "listTaskRuns",
|
|
760
|
+
summary: "List task runs",
|
|
761
|
+
description: "Returns past execution runs for a scheduled task.",
|
|
762
|
+
tags: ["Scheduled Tasks"],
|
|
763
|
+
security: [{ bearerAuth: [] }, {}],
|
|
764
|
+
parameters: [
|
|
765
|
+
uuidPathParam("id", "Task UUID."),
|
|
766
|
+
{
|
|
767
|
+
name: "limit",
|
|
768
|
+
in: "query",
|
|
769
|
+
description: "Maximum number of runs to return (1-100, default 20).",
|
|
770
|
+
required: false,
|
|
771
|
+
schema: { type: "integer", minimum: 1, maximum: 100, default: 20 },
|
|
772
|
+
},
|
|
773
|
+
],
|
|
774
|
+
responses: {
|
|
775
|
+
"200": {
|
|
776
|
+
description: "List of task runs",
|
|
777
|
+
content: {
|
|
778
|
+
"application/json": {
|
|
779
|
+
schema: {
|
|
780
|
+
type: "object",
|
|
781
|
+
properties: {
|
|
782
|
+
runs: { type: "array", items: { type: "object" } },
|
|
783
|
+
},
|
|
784
|
+
},
|
|
785
|
+
},
|
|
786
|
+
},
|
|
787
|
+
},
|
|
788
|
+
"400": errorResponse("Invalid task ID format"),
|
|
789
|
+
...authErrors,
|
|
790
|
+
"404": errorResponse("Task not found"),
|
|
791
|
+
},
|
|
792
|
+
},
|
|
793
|
+
},
|
|
794
|
+
|
|
795
|
+
// -----------------------------------------------------------------
|
|
796
|
+
// Auth — Better Auth routes (key endpoints)
|
|
797
|
+
// -----------------------------------------------------------------
|
|
798
|
+
"/api/auth/sign-up/email": {
|
|
799
|
+
post: {
|
|
800
|
+
operationId: "signUpEmail",
|
|
801
|
+
summary: "Sign up with email",
|
|
802
|
+
description:
|
|
803
|
+
"Creates a new user account with email and password. Only available when auth mode is 'managed' (Better Auth).",
|
|
804
|
+
tags: ["Auth"],
|
|
805
|
+
requestBody: {
|
|
806
|
+
required: true,
|
|
807
|
+
content: {
|
|
808
|
+
"application/json": {
|
|
809
|
+
schema: {
|
|
810
|
+
type: "object",
|
|
811
|
+
required: ["email", "password", "name"],
|
|
812
|
+
properties: {
|
|
813
|
+
email: { type: "string", format: "email" },
|
|
814
|
+
password: { type: "string", minLength: 8 },
|
|
815
|
+
name: { type: "string" },
|
|
816
|
+
},
|
|
817
|
+
},
|
|
818
|
+
},
|
|
819
|
+
},
|
|
820
|
+
},
|
|
821
|
+
responses: {
|
|
822
|
+
"200": {
|
|
823
|
+
description: "User created successfully",
|
|
824
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
825
|
+
},
|
|
826
|
+
"400": errorResponse("Invalid request"),
|
|
827
|
+
"404": errorResponse("Auth routes not enabled (not in managed mode)"),
|
|
828
|
+
},
|
|
829
|
+
},
|
|
830
|
+
},
|
|
831
|
+
|
|
832
|
+
"/api/auth/sign-in/email": {
|
|
833
|
+
post: {
|
|
834
|
+
operationId: "signInEmail",
|
|
835
|
+
summary: "Sign in with email",
|
|
836
|
+
description:
|
|
837
|
+
"Authenticates a user with email and password. Returns a session token. Only available when auth mode is 'managed'.",
|
|
838
|
+
tags: ["Auth"],
|
|
839
|
+
requestBody: {
|
|
840
|
+
required: true,
|
|
841
|
+
content: {
|
|
842
|
+
"application/json": {
|
|
843
|
+
schema: {
|
|
844
|
+
type: "object",
|
|
845
|
+
required: ["email", "password"],
|
|
846
|
+
properties: {
|
|
847
|
+
email: { type: "string", format: "email" },
|
|
848
|
+
password: { type: "string" },
|
|
849
|
+
},
|
|
850
|
+
},
|
|
851
|
+
},
|
|
852
|
+
},
|
|
853
|
+
},
|
|
854
|
+
responses: {
|
|
855
|
+
"200": {
|
|
856
|
+
description: "Session created",
|
|
857
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
858
|
+
},
|
|
859
|
+
"401": errorResponse("Invalid credentials"),
|
|
860
|
+
"404": errorResponse("Auth routes not enabled"),
|
|
861
|
+
},
|
|
862
|
+
},
|
|
863
|
+
},
|
|
864
|
+
|
|
865
|
+
"/api/auth/get-session": {
|
|
866
|
+
get: {
|
|
867
|
+
operationId: "getSession",
|
|
868
|
+
summary: "Get current session",
|
|
869
|
+
description:
|
|
870
|
+
"Returns the current session and user info. Requires a valid session cookie or Authorization header.",
|
|
871
|
+
tags: ["Auth"],
|
|
872
|
+
security: [{ bearerAuth: [] }],
|
|
873
|
+
responses: {
|
|
874
|
+
"200": {
|
|
875
|
+
description: "Current session",
|
|
876
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
877
|
+
},
|
|
878
|
+
"401": errorResponse("Not authenticated"),
|
|
879
|
+
"404": errorResponse("Auth routes not enabled"),
|
|
880
|
+
},
|
|
881
|
+
},
|
|
882
|
+
},
|
|
883
|
+
|
|
884
|
+
"/api/auth/sign-out": {
|
|
885
|
+
post: {
|
|
886
|
+
operationId: "signOut",
|
|
887
|
+
summary: "Sign out",
|
|
888
|
+
description: "Destroys the current session.",
|
|
889
|
+
tags: ["Auth"],
|
|
890
|
+
security: [{ bearerAuth: [] }],
|
|
891
|
+
responses: {
|
|
892
|
+
"200": { description: "Session destroyed" },
|
|
893
|
+
"404": errorResponse("Auth routes not enabled"),
|
|
894
|
+
},
|
|
895
|
+
},
|
|
896
|
+
},
|
|
897
|
+
|
|
898
|
+
// -----------------------------------------------------------------
|
|
899
|
+
// Slack integration
|
|
900
|
+
// -----------------------------------------------------------------
|
|
901
|
+
"/api/slack/commands": {
|
|
902
|
+
post: {
|
|
903
|
+
operationId: "slackCommand",
|
|
904
|
+
summary: "Slack slash command",
|
|
905
|
+
description:
|
|
906
|
+
"Handles Slack slash commands (/atlas). Acks within 3 seconds and processes the query asynchronously. " +
|
|
907
|
+
"Requires SLACK_SIGNING_SECRET. Request signature is verified.",
|
|
908
|
+
tags: ["Slack"],
|
|
909
|
+
requestBody: {
|
|
910
|
+
required: true,
|
|
911
|
+
content: {
|
|
912
|
+
"application/x-www-form-urlencoded": {
|
|
913
|
+
schema: {
|
|
914
|
+
type: "object",
|
|
915
|
+
properties: {
|
|
916
|
+
text: { type: "string", description: "The question text." },
|
|
917
|
+
channel_id: { type: "string" },
|
|
918
|
+
user_id: { type: "string" },
|
|
919
|
+
team_id: { type: "string" },
|
|
920
|
+
response_url: { type: "string" },
|
|
921
|
+
},
|
|
922
|
+
},
|
|
923
|
+
},
|
|
924
|
+
},
|
|
925
|
+
},
|
|
926
|
+
responses: {
|
|
927
|
+
"200": {
|
|
928
|
+
description: "Immediate acknowledgment (processing continues asynchronously)",
|
|
929
|
+
content: {
|
|
930
|
+
"application/json": {
|
|
931
|
+
schema: {
|
|
932
|
+
type: "object",
|
|
933
|
+
properties: {
|
|
934
|
+
response_type: { type: "string" },
|
|
935
|
+
text: { type: "string" },
|
|
936
|
+
},
|
|
937
|
+
},
|
|
938
|
+
},
|
|
939
|
+
},
|
|
940
|
+
},
|
|
941
|
+
"401": errorResponse("Invalid Slack signature"),
|
|
942
|
+
},
|
|
943
|
+
},
|
|
944
|
+
},
|
|
945
|
+
|
|
946
|
+
"/api/slack/events": {
|
|
947
|
+
post: {
|
|
948
|
+
operationId: "slackEvents",
|
|
949
|
+
summary: "Slack Events API",
|
|
950
|
+
description:
|
|
951
|
+
"Handles Slack Events API callbacks including url_verification challenges and thread follow-up messages. " +
|
|
952
|
+
"Bot messages are ignored to prevent loops.",
|
|
953
|
+
tags: ["Slack"],
|
|
954
|
+
requestBody: {
|
|
955
|
+
required: true,
|
|
956
|
+
content: {
|
|
957
|
+
"application/json": {
|
|
958
|
+
schema: {
|
|
959
|
+
type: "object",
|
|
960
|
+
properties: {
|
|
961
|
+
type: { type: "string", enum: ["url_verification", "event_callback"] },
|
|
962
|
+
challenge: { type: "string", description: "Verification challenge (url_verification only)." },
|
|
963
|
+
event: { type: "object", description: "The Slack event payload." },
|
|
964
|
+
},
|
|
965
|
+
},
|
|
966
|
+
},
|
|
967
|
+
},
|
|
968
|
+
},
|
|
969
|
+
responses: {
|
|
970
|
+
"200": {
|
|
971
|
+
description: "Event acknowledged",
|
|
972
|
+
content: {
|
|
973
|
+
"application/json": {
|
|
974
|
+
schema: {
|
|
975
|
+
type: "object",
|
|
976
|
+
properties: {
|
|
977
|
+
ok: { type: "boolean" },
|
|
978
|
+
challenge: { type: "string", description: "Echoed challenge (url_verification only)." },
|
|
979
|
+
},
|
|
980
|
+
},
|
|
981
|
+
},
|
|
982
|
+
},
|
|
983
|
+
},
|
|
984
|
+
"401": errorResponse("Invalid Slack signature"),
|
|
985
|
+
},
|
|
986
|
+
},
|
|
987
|
+
},
|
|
988
|
+
|
|
989
|
+
"/api/slack/install": {
|
|
990
|
+
get: {
|
|
991
|
+
operationId: "slackInstall",
|
|
992
|
+
summary: "Slack OAuth install",
|
|
993
|
+
description:
|
|
994
|
+
"Redirects to the Slack OAuth authorization page. Requires SLACK_CLIENT_ID to be configured.",
|
|
995
|
+
tags: ["Slack"],
|
|
996
|
+
responses: {
|
|
997
|
+
"302": { description: "Redirect to Slack OAuth authorization page" },
|
|
998
|
+
"501": errorResponse("OAuth not configured"),
|
|
999
|
+
},
|
|
1000
|
+
},
|
|
1001
|
+
},
|
|
1002
|
+
|
|
1003
|
+
"/api/slack/callback": {
|
|
1004
|
+
get: {
|
|
1005
|
+
operationId: "slackCallback",
|
|
1006
|
+
summary: "Slack OAuth callback",
|
|
1007
|
+
description:
|
|
1008
|
+
"Handles the OAuth callback from Slack, exchanges the code for a bot token, and saves the installation.",
|
|
1009
|
+
tags: ["Slack"],
|
|
1010
|
+
parameters: [
|
|
1011
|
+
{ name: "code", in: "query", required: true, schema: { type: "string" }, description: "OAuth authorization code." },
|
|
1012
|
+
{ name: "state", in: "query", required: true, schema: { type: "string" }, description: "CSRF state parameter." },
|
|
1013
|
+
],
|
|
1014
|
+
responses: {
|
|
1015
|
+
"200": {
|
|
1016
|
+
description: "Installation successful (HTML response)",
|
|
1017
|
+
content: { "text/html": { schema: { type: "string" } } },
|
|
1018
|
+
},
|
|
1019
|
+
"400": errorResponse("Invalid or expired state, or missing code"),
|
|
1020
|
+
"500": { description: "Installation failed (HTML response)", content: { "text/html": { schema: { type: "string" } } } },
|
|
1021
|
+
"501": errorResponse("OAuth not configured"),
|
|
1022
|
+
},
|
|
1023
|
+
},
|
|
1024
|
+
},
|
|
1025
|
+
|
|
1026
|
+
// -----------------------------------------------------------------
|
|
1027
|
+
// Admin — admin console routes
|
|
1028
|
+
// -----------------------------------------------------------------
|
|
1029
|
+
"/api/v1/admin/overview": {
|
|
1030
|
+
get: {
|
|
1031
|
+
operationId: "adminOverview",
|
|
1032
|
+
summary: "Dashboard overview",
|
|
1033
|
+
description:
|
|
1034
|
+
"Returns counts of connections, entities, metrics, glossary terms, and plugins. Requires admin role.",
|
|
1035
|
+
tags: ["Admin"],
|
|
1036
|
+
security: [{ bearerAuth: [] }],
|
|
1037
|
+
responses: {
|
|
1038
|
+
"200": {
|
|
1039
|
+
description: "Dashboard summary",
|
|
1040
|
+
content: {
|
|
1041
|
+
"application/json": {
|
|
1042
|
+
schema: {
|
|
1043
|
+
type: "object",
|
|
1044
|
+
properties: {
|
|
1045
|
+
connections: { type: "integer" },
|
|
1046
|
+
entities: { type: "integer" },
|
|
1047
|
+
metrics: { type: "integer" },
|
|
1048
|
+
glossaryTerms: { type: "integer" },
|
|
1049
|
+
plugins: { type: "integer" },
|
|
1050
|
+
pluginHealth: {
|
|
1051
|
+
type: "array",
|
|
1052
|
+
items: {
|
|
1053
|
+
type: "object",
|
|
1054
|
+
properties: {
|
|
1055
|
+
id: { type: "string" },
|
|
1056
|
+
name: { type: "string" },
|
|
1057
|
+
type: { type: "string" },
|
|
1058
|
+
status: { type: "string" },
|
|
1059
|
+
},
|
|
1060
|
+
},
|
|
1061
|
+
},
|
|
1062
|
+
},
|
|
1063
|
+
},
|
|
1064
|
+
},
|
|
1065
|
+
},
|
|
1066
|
+
},
|
|
1067
|
+
...authErrors,
|
|
1068
|
+
},
|
|
1069
|
+
},
|
|
1070
|
+
},
|
|
1071
|
+
|
|
1072
|
+
"/api/v1/admin/semantic/entities": {
|
|
1073
|
+
get: {
|
|
1074
|
+
operationId: "adminListEntities",
|
|
1075
|
+
summary: "List semantic entities",
|
|
1076
|
+
description: "Lists all entity YAML files with summary info. Requires admin role.",
|
|
1077
|
+
tags: ["Admin"],
|
|
1078
|
+
security: [{ bearerAuth: [] }],
|
|
1079
|
+
responses: {
|
|
1080
|
+
"200": {
|
|
1081
|
+
description: "List of entities",
|
|
1082
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1083
|
+
},
|
|
1084
|
+
...authErrors,
|
|
1085
|
+
},
|
|
1086
|
+
},
|
|
1087
|
+
},
|
|
1088
|
+
|
|
1089
|
+
"/api/v1/admin/semantic/entities/{name}": {
|
|
1090
|
+
get: {
|
|
1091
|
+
operationId: "adminGetEntity",
|
|
1092
|
+
summary: "Get entity details",
|
|
1093
|
+
description: "Returns the full parsed YAML for a specific entity. Requires admin role.",
|
|
1094
|
+
tags: ["Admin"],
|
|
1095
|
+
security: [{ bearerAuth: [] }],
|
|
1096
|
+
parameters: [
|
|
1097
|
+
{ name: "name", in: "path", required: true, schema: { type: "string" }, description: "Entity name (e.g. 'orders')." },
|
|
1098
|
+
],
|
|
1099
|
+
responses: {
|
|
1100
|
+
"200": {
|
|
1101
|
+
description: "Entity YAML content",
|
|
1102
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1103
|
+
},
|
|
1104
|
+
"400": errorResponse("Invalid entity name"),
|
|
1105
|
+
...authErrors,
|
|
1106
|
+
"404": errorResponse("Entity not found"),
|
|
1107
|
+
},
|
|
1108
|
+
},
|
|
1109
|
+
},
|
|
1110
|
+
|
|
1111
|
+
"/api/v1/admin/semantic/metrics": {
|
|
1112
|
+
get: {
|
|
1113
|
+
operationId: "adminListMetrics",
|
|
1114
|
+
summary: "List metrics",
|
|
1115
|
+
description: "Lists all metric YAML files grouped by source. Requires admin role.",
|
|
1116
|
+
tags: ["Admin"],
|
|
1117
|
+
security: [{ bearerAuth: [] }],
|
|
1118
|
+
responses: {
|
|
1119
|
+
"200": {
|
|
1120
|
+
description: "List of metrics",
|
|
1121
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1122
|
+
},
|
|
1123
|
+
...authErrors,
|
|
1124
|
+
},
|
|
1125
|
+
},
|
|
1126
|
+
},
|
|
1127
|
+
|
|
1128
|
+
"/api/v1/admin/semantic/glossary": {
|
|
1129
|
+
get: {
|
|
1130
|
+
operationId: "adminGetGlossary",
|
|
1131
|
+
summary: "Get glossary",
|
|
1132
|
+
description: "Returns all glossary files (default and per-source). Requires admin role.",
|
|
1133
|
+
tags: ["Admin"],
|
|
1134
|
+
security: [{ bearerAuth: [] }],
|
|
1135
|
+
responses: {
|
|
1136
|
+
"200": {
|
|
1137
|
+
description: "Glossary content",
|
|
1138
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1139
|
+
},
|
|
1140
|
+
...authErrors,
|
|
1141
|
+
},
|
|
1142
|
+
},
|
|
1143
|
+
},
|
|
1144
|
+
|
|
1145
|
+
"/api/v1/admin/semantic/catalog": {
|
|
1146
|
+
get: {
|
|
1147
|
+
operationId: "adminGetCatalog",
|
|
1148
|
+
summary: "Get catalog",
|
|
1149
|
+
description: "Returns the parsed catalog.yml. Returns an object with a null catalog field if no catalog exists. Requires admin role.",
|
|
1150
|
+
tags: ["Admin"],
|
|
1151
|
+
security: [{ bearerAuth: [] }],
|
|
1152
|
+
responses: {
|
|
1153
|
+
"200": {
|
|
1154
|
+
description: "Catalog content",
|
|
1155
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1156
|
+
},
|
|
1157
|
+
...authErrors,
|
|
1158
|
+
},
|
|
1159
|
+
},
|
|
1160
|
+
},
|
|
1161
|
+
|
|
1162
|
+
"/api/v1/admin/semantic/raw/{file}": {
|
|
1163
|
+
get: {
|
|
1164
|
+
operationId: "adminGetRawFile",
|
|
1165
|
+
summary: "Get raw YAML file",
|
|
1166
|
+
description:
|
|
1167
|
+
"Serves a raw top-level YAML file from the semantic layer (e.g. catalog.yml, glossary.yml). " +
|
|
1168
|
+
"Only .yml files matching the allowed pattern are served. Requires admin role.",
|
|
1169
|
+
tags: ["Admin"],
|
|
1170
|
+
security: [{ bearerAuth: [] }],
|
|
1171
|
+
parameters: [
|
|
1172
|
+
{
|
|
1173
|
+
name: "file",
|
|
1174
|
+
in: "path",
|
|
1175
|
+
required: true,
|
|
1176
|
+
schema: { type: "string", pattern: "^(catalog|glossary)\\.yml$" },
|
|
1177
|
+
description: "Top-level YAML filename (e.g. 'catalog.yml').",
|
|
1178
|
+
},
|
|
1179
|
+
],
|
|
1180
|
+
responses: {
|
|
1181
|
+
"200": {
|
|
1182
|
+
description: "Raw YAML content",
|
|
1183
|
+
content: { "text/plain": { schema: { type: "string" } } },
|
|
1184
|
+
},
|
|
1185
|
+
"400": errorResponse("Invalid file path"),
|
|
1186
|
+
...authErrors,
|
|
1187
|
+
"404": errorResponse("File not found"),
|
|
1188
|
+
},
|
|
1189
|
+
},
|
|
1190
|
+
},
|
|
1191
|
+
|
|
1192
|
+
"/api/v1/admin/semantic/raw/{dir}/{file}": {
|
|
1193
|
+
get: {
|
|
1194
|
+
operationId: "adminGetRawDirFile",
|
|
1195
|
+
summary: "Get raw YAML file from subdirectory",
|
|
1196
|
+
description:
|
|
1197
|
+
"Serves a raw YAML file from a semantic layer subdirectory (e.g. entities/orders.yml, metrics/revenue.yml). " +
|
|
1198
|
+
"Only .yml files in entities/ or metrics/ are allowed. Requires admin role.",
|
|
1199
|
+
tags: ["Admin"],
|
|
1200
|
+
security: [{ bearerAuth: [] }],
|
|
1201
|
+
parameters: [
|
|
1202
|
+
{
|
|
1203
|
+
name: "dir",
|
|
1204
|
+
in: "path",
|
|
1205
|
+
required: true,
|
|
1206
|
+
schema: { type: "string", enum: ["entities", "metrics"] },
|
|
1207
|
+
description: "Subdirectory name.",
|
|
1208
|
+
},
|
|
1209
|
+
{
|
|
1210
|
+
name: "file",
|
|
1211
|
+
in: "path",
|
|
1212
|
+
required: true,
|
|
1213
|
+
schema: { type: "string", pattern: "^[a-zA-Z0-9_-]+\\.yml$" },
|
|
1214
|
+
description: "YAML filename (e.g. 'orders.yml').",
|
|
1215
|
+
},
|
|
1216
|
+
],
|
|
1217
|
+
responses: {
|
|
1218
|
+
"200": {
|
|
1219
|
+
description: "Raw YAML content",
|
|
1220
|
+
content: { "text/plain": { schema: { type: "string" } } },
|
|
1221
|
+
},
|
|
1222
|
+
"400": errorResponse("Invalid file path"),
|
|
1223
|
+
...authErrors,
|
|
1224
|
+
"404": errorResponse("File not found"),
|
|
1225
|
+
},
|
|
1226
|
+
},
|
|
1227
|
+
},
|
|
1228
|
+
|
|
1229
|
+
"/api/v1/admin/semantic/stats": {
|
|
1230
|
+
get: {
|
|
1231
|
+
operationId: "adminSemanticStats",
|
|
1232
|
+
summary: "Semantic layer statistics",
|
|
1233
|
+
description: "Aggregate statistics across the semantic layer. Requires admin role.",
|
|
1234
|
+
tags: ["Admin"],
|
|
1235
|
+
security: [{ bearerAuth: [] }],
|
|
1236
|
+
responses: {
|
|
1237
|
+
"200": {
|
|
1238
|
+
description: "Semantic layer stats",
|
|
1239
|
+
content: {
|
|
1240
|
+
"application/json": {
|
|
1241
|
+
schema: {
|
|
1242
|
+
type: "object",
|
|
1243
|
+
properties: {
|
|
1244
|
+
totalEntities: { type: "integer" },
|
|
1245
|
+
totalColumns: { type: "integer" },
|
|
1246
|
+
totalJoins: { type: "integer" },
|
|
1247
|
+
totalMeasures: { type: "integer" },
|
|
1248
|
+
coverageGaps: {
|
|
1249
|
+
type: "object",
|
|
1250
|
+
properties: {
|
|
1251
|
+
noDescription: { type: "integer" },
|
|
1252
|
+
noColumns: { type: "integer" },
|
|
1253
|
+
noJoins: { type: "integer" },
|
|
1254
|
+
},
|
|
1255
|
+
},
|
|
1256
|
+
},
|
|
1257
|
+
},
|
|
1258
|
+
},
|
|
1259
|
+
},
|
|
1260
|
+
},
|
|
1261
|
+
...authErrors,
|
|
1262
|
+
},
|
|
1263
|
+
},
|
|
1264
|
+
},
|
|
1265
|
+
|
|
1266
|
+
"/api/v1/admin/connections": {
|
|
1267
|
+
get: {
|
|
1268
|
+
operationId: "adminListConnections",
|
|
1269
|
+
summary: "List connections",
|
|
1270
|
+
description: "Lists all registered database connections with type and cached health status. Requires admin role.",
|
|
1271
|
+
tags: ["Admin"],
|
|
1272
|
+
security: [{ bearerAuth: [] }],
|
|
1273
|
+
responses: {
|
|
1274
|
+
"200": {
|
|
1275
|
+
description: "List of connections",
|
|
1276
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1277
|
+
},
|
|
1278
|
+
...authErrors,
|
|
1279
|
+
},
|
|
1280
|
+
},
|
|
1281
|
+
},
|
|
1282
|
+
|
|
1283
|
+
"/api/v1/admin/connections/{id}/test": {
|
|
1284
|
+
post: {
|
|
1285
|
+
operationId: "adminTestConnection",
|
|
1286
|
+
summary: "Test a connection",
|
|
1287
|
+
description: "Triggers a live health check for a specific connection. Requires admin role.",
|
|
1288
|
+
tags: ["Admin"],
|
|
1289
|
+
security: [{ bearerAuth: [] }],
|
|
1290
|
+
parameters: [
|
|
1291
|
+
{ name: "id", in: "path", required: true, schema: { type: "string" }, description: "Connection ID (e.g. 'default')." },
|
|
1292
|
+
],
|
|
1293
|
+
responses: {
|
|
1294
|
+
"200": {
|
|
1295
|
+
description: "Connection health check result",
|
|
1296
|
+
content: {
|
|
1297
|
+
"application/json": {
|
|
1298
|
+
schema: {
|
|
1299
|
+
type: "object",
|
|
1300
|
+
properties: {
|
|
1301
|
+
status: { type: "string", enum: ["healthy", "unhealthy"] },
|
|
1302
|
+
latencyMs: { type: "integer" },
|
|
1303
|
+
checkedAt: { type: "string", format: "date-time" },
|
|
1304
|
+
},
|
|
1305
|
+
},
|
|
1306
|
+
},
|
|
1307
|
+
},
|
|
1308
|
+
},
|
|
1309
|
+
...authErrors,
|
|
1310
|
+
"404": errorResponse("Connection not found"),
|
|
1311
|
+
},
|
|
1312
|
+
},
|
|
1313
|
+
},
|
|
1314
|
+
|
|
1315
|
+
"/api/v1/admin/users": {
|
|
1316
|
+
get: {
|
|
1317
|
+
operationId: "adminListUsers",
|
|
1318
|
+
summary: "List users",
|
|
1319
|
+
description: "Lists users with pagination, search, and role filtering. Requires admin role and managed auth.",
|
|
1320
|
+
tags: ["Admin"],
|
|
1321
|
+
security: [{ bearerAuth: [] }],
|
|
1322
|
+
parameters: [
|
|
1323
|
+
...paginationParams({ limit: 50, maxLimit: 200 }),
|
|
1324
|
+
{ name: "search", in: "query", required: false, schema: { type: "string" }, description: "Search by email (contains match)." },
|
|
1325
|
+
{ name: "role", in: "query", required: false, schema: { type: "string", enum: ["viewer", "analyst", "admin"] }, description: "Filter by role." },
|
|
1326
|
+
],
|
|
1327
|
+
responses: {
|
|
1328
|
+
"200": {
|
|
1329
|
+
description: "Paginated list of users",
|
|
1330
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1331
|
+
},
|
|
1332
|
+
...authErrors,
|
|
1333
|
+
},
|
|
1334
|
+
},
|
|
1335
|
+
},
|
|
1336
|
+
|
|
1337
|
+
"/api/v1/admin/users/stats": {
|
|
1338
|
+
get: {
|
|
1339
|
+
operationId: "adminUserStats",
|
|
1340
|
+
summary: "User statistics",
|
|
1341
|
+
description: "Aggregate user statistics: total count, banned count, and breakdown by role. Requires admin role.",
|
|
1342
|
+
tags: ["Admin"],
|
|
1343
|
+
security: [{ bearerAuth: [] }],
|
|
1344
|
+
responses: {
|
|
1345
|
+
"200": {
|
|
1346
|
+
description: "User stats",
|
|
1347
|
+
content: {
|
|
1348
|
+
"application/json": {
|
|
1349
|
+
schema: {
|
|
1350
|
+
type: "object",
|
|
1351
|
+
properties: {
|
|
1352
|
+
total: { type: "integer" },
|
|
1353
|
+
banned: { type: "integer" },
|
|
1354
|
+
byRole: {
|
|
1355
|
+
type: "object",
|
|
1356
|
+
properties: {
|
|
1357
|
+
admin: { type: "integer" },
|
|
1358
|
+
analyst: { type: "integer" },
|
|
1359
|
+
viewer: { type: "integer" },
|
|
1360
|
+
},
|
|
1361
|
+
},
|
|
1362
|
+
},
|
|
1363
|
+
},
|
|
1364
|
+
},
|
|
1365
|
+
},
|
|
1366
|
+
},
|
|
1367
|
+
...authErrors,
|
|
1368
|
+
},
|
|
1369
|
+
},
|
|
1370
|
+
},
|
|
1371
|
+
|
|
1372
|
+
"/api/v1/admin/users/{id}/role": {
|
|
1373
|
+
patch: {
|
|
1374
|
+
operationId: "adminChangeUserRole",
|
|
1375
|
+
summary: "Change user role",
|
|
1376
|
+
description: "Updates a user's role. Cannot change your own role or demote the last admin. Requires admin role.",
|
|
1377
|
+
tags: ["Admin"],
|
|
1378
|
+
security: [{ bearerAuth: [] }],
|
|
1379
|
+
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" }, description: "User ID." }],
|
|
1380
|
+
requestBody: {
|
|
1381
|
+
required: true,
|
|
1382
|
+
content: {
|
|
1383
|
+
"application/json": {
|
|
1384
|
+
schema: {
|
|
1385
|
+
type: "object",
|
|
1386
|
+
required: ["role"],
|
|
1387
|
+
properties: {
|
|
1388
|
+
role: { type: "string", enum: ["viewer", "analyst", "admin"] },
|
|
1389
|
+
},
|
|
1390
|
+
},
|
|
1391
|
+
},
|
|
1392
|
+
},
|
|
1393
|
+
},
|
|
1394
|
+
responses: {
|
|
1395
|
+
"200": { description: "Role updated", content: { "application/json": { schema: { type: "object" } } } },
|
|
1396
|
+
"400": errorResponse("Invalid role or cannot change own role"),
|
|
1397
|
+
...authErrors,
|
|
1398
|
+
},
|
|
1399
|
+
},
|
|
1400
|
+
},
|
|
1401
|
+
|
|
1402
|
+
"/api/v1/admin/users/{id}/ban": {
|
|
1403
|
+
post: {
|
|
1404
|
+
operationId: "adminBanUser",
|
|
1405
|
+
summary: "Ban a user",
|
|
1406
|
+
description: "Bans a user with optional reason and expiration. Requires admin role.",
|
|
1407
|
+
tags: ["Admin"],
|
|
1408
|
+
security: [{ bearerAuth: [] }],
|
|
1409
|
+
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" }, description: "User ID." }],
|
|
1410
|
+
requestBody: {
|
|
1411
|
+
required: false,
|
|
1412
|
+
content: {
|
|
1413
|
+
"application/json": {
|
|
1414
|
+
schema: {
|
|
1415
|
+
type: "object",
|
|
1416
|
+
properties: {
|
|
1417
|
+
reason: { type: "string" },
|
|
1418
|
+
expiresIn: { type: "integer", description: "Ban duration in seconds." },
|
|
1419
|
+
},
|
|
1420
|
+
},
|
|
1421
|
+
},
|
|
1422
|
+
},
|
|
1423
|
+
},
|
|
1424
|
+
responses: {
|
|
1425
|
+
"200": { description: "User banned", content: { "application/json": { schema: { type: "object" } } } },
|
|
1426
|
+
...authErrors,
|
|
1427
|
+
},
|
|
1428
|
+
},
|
|
1429
|
+
},
|
|
1430
|
+
|
|
1431
|
+
"/api/v1/admin/users/{id}/unban": {
|
|
1432
|
+
post: {
|
|
1433
|
+
operationId: "adminUnbanUser",
|
|
1434
|
+
summary: "Unban a user",
|
|
1435
|
+
description: "Removes a ban from a user. Requires admin role.",
|
|
1436
|
+
tags: ["Admin"],
|
|
1437
|
+
security: [{ bearerAuth: [] }],
|
|
1438
|
+
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" }, description: "User ID." }],
|
|
1439
|
+
responses: {
|
|
1440
|
+
"200": { description: "User unbanned", content: { "application/json": { schema: { type: "object" } } } },
|
|
1441
|
+
...authErrors,
|
|
1442
|
+
},
|
|
1443
|
+
},
|
|
1444
|
+
},
|
|
1445
|
+
|
|
1446
|
+
"/api/v1/admin/users/{id}": {
|
|
1447
|
+
delete: {
|
|
1448
|
+
operationId: "adminDeleteUser",
|
|
1449
|
+
summary: "Delete a user",
|
|
1450
|
+
description: "Permanently deletes a user. Cannot delete yourself or the last admin. Requires admin role.",
|
|
1451
|
+
tags: ["Admin"],
|
|
1452
|
+
security: [{ bearerAuth: [] }],
|
|
1453
|
+
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" }, description: "User ID." }],
|
|
1454
|
+
responses: {
|
|
1455
|
+
"204": { description: "User deleted" },
|
|
1456
|
+
"400": errorResponse("Cannot delete yourself or last admin"),
|
|
1457
|
+
...authErrors,
|
|
1458
|
+
},
|
|
1459
|
+
},
|
|
1460
|
+
},
|
|
1461
|
+
|
|
1462
|
+
"/api/v1/admin/users/{id}/revoke": {
|
|
1463
|
+
post: {
|
|
1464
|
+
operationId: "adminRevokeUserSessions",
|
|
1465
|
+
summary: "Revoke user sessions",
|
|
1466
|
+
description: "Revokes all sessions for a user (force logout). Requires admin role.",
|
|
1467
|
+
tags: ["Admin"],
|
|
1468
|
+
security: [{ bearerAuth: [] }],
|
|
1469
|
+
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" }, description: "User ID." }],
|
|
1470
|
+
responses: {
|
|
1471
|
+
"200": { description: "Sessions revoked", content: { "application/json": { schema: { type: "object" } } } },
|
|
1472
|
+
...authErrors,
|
|
1473
|
+
},
|
|
1474
|
+
},
|
|
1475
|
+
},
|
|
1476
|
+
|
|
1477
|
+
"/api/v1/admin/audit": {
|
|
1478
|
+
get: {
|
|
1479
|
+
operationId: "adminListAuditLog",
|
|
1480
|
+
summary: "Query audit log",
|
|
1481
|
+
description: "Returns paginated audit log entries with optional filters. Requires admin role and internal database.",
|
|
1482
|
+
tags: ["Admin"],
|
|
1483
|
+
security: [{ bearerAuth: [] }],
|
|
1484
|
+
parameters: [
|
|
1485
|
+
...paginationParams({ limit: 50, maxLimit: 200 }),
|
|
1486
|
+
{ name: "user", in: "query", required: false, schema: { type: "string" }, description: "Filter by user ID." },
|
|
1487
|
+
{ name: "success", in: "query", required: false, schema: { type: "boolean" }, description: "Filter by success/failure." },
|
|
1488
|
+
{ name: "from", in: "query", required: false, schema: { type: "string", format: "date-time" }, description: "ISO 8601 start date." },
|
|
1489
|
+
{ name: "to", in: "query", required: false, schema: { type: "string", format: "date-time" }, description: "ISO 8601 end date." },
|
|
1490
|
+
],
|
|
1491
|
+
responses: {
|
|
1492
|
+
"200": {
|
|
1493
|
+
description: "Paginated audit log",
|
|
1494
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1495
|
+
},
|
|
1496
|
+
...authErrors,
|
|
1497
|
+
},
|
|
1498
|
+
},
|
|
1499
|
+
},
|
|
1500
|
+
|
|
1501
|
+
"/api/v1/admin/audit/stats": {
|
|
1502
|
+
get: {
|
|
1503
|
+
operationId: "adminAuditStats",
|
|
1504
|
+
summary: "Audit statistics",
|
|
1505
|
+
description: "Aggregate audit statistics: total queries, error count, error rate, and queries per day. Requires admin role.",
|
|
1506
|
+
tags: ["Admin"],
|
|
1507
|
+
security: [{ bearerAuth: [] }],
|
|
1508
|
+
responses: {
|
|
1509
|
+
"200": {
|
|
1510
|
+
description: "Audit stats",
|
|
1511
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1512
|
+
},
|
|
1513
|
+
...authErrors,
|
|
1514
|
+
},
|
|
1515
|
+
},
|
|
1516
|
+
},
|
|
1517
|
+
|
|
1518
|
+
"/api/v1/admin/plugins": {
|
|
1519
|
+
get: {
|
|
1520
|
+
operationId: "adminListPlugins",
|
|
1521
|
+
summary: "List plugins",
|
|
1522
|
+
description: "Lists all installed plugins with type, version, and status. Requires admin role.",
|
|
1523
|
+
tags: ["Admin"],
|
|
1524
|
+
security: [{ bearerAuth: [] }],
|
|
1525
|
+
responses: {
|
|
1526
|
+
"200": {
|
|
1527
|
+
description: "List of plugins",
|
|
1528
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1529
|
+
},
|
|
1530
|
+
...authErrors,
|
|
1531
|
+
},
|
|
1532
|
+
},
|
|
1533
|
+
},
|
|
1534
|
+
|
|
1535
|
+
"/api/v1/admin/plugins/{id}/health": {
|
|
1536
|
+
post: {
|
|
1537
|
+
operationId: "adminPluginHealth",
|
|
1538
|
+
summary: "Check plugin health",
|
|
1539
|
+
description: "Triggers a health check for a specific plugin. Requires admin role.",
|
|
1540
|
+
tags: ["Admin"],
|
|
1541
|
+
security: [{ bearerAuth: [] }],
|
|
1542
|
+
parameters: [
|
|
1543
|
+
{ name: "id", in: "path", required: true, schema: { type: "string" }, description: "Plugin ID." },
|
|
1544
|
+
],
|
|
1545
|
+
responses: {
|
|
1546
|
+
"200": {
|
|
1547
|
+
description: "Plugin health check result",
|
|
1548
|
+
content: { "application/json": { schema: { type: "object" } } },
|
|
1549
|
+
},
|
|
1550
|
+
...authErrors,
|
|
1551
|
+
"404": errorResponse("Plugin not found"),
|
|
1552
|
+
},
|
|
1553
|
+
},
|
|
1554
|
+
},
|
|
1555
|
+
|
|
1556
|
+
"/api/v1/admin/me/password-status": {
|
|
1557
|
+
get: {
|
|
1558
|
+
operationId: "adminPasswordStatus",
|
|
1559
|
+
summary: "Check password change requirement",
|
|
1560
|
+
description: "Checks if the current user must change their password. Available to any authenticated managed-auth user.",
|
|
1561
|
+
tags: ["Admin"],
|
|
1562
|
+
security: [{ bearerAuth: [] }],
|
|
1563
|
+
responses: {
|
|
1564
|
+
"200": {
|
|
1565
|
+
description: "Password status",
|
|
1566
|
+
content: {
|
|
1567
|
+
"application/json": {
|
|
1568
|
+
schema: {
|
|
1569
|
+
type: "object",
|
|
1570
|
+
properties: {
|
|
1571
|
+
mustChange: { type: "boolean" },
|
|
1572
|
+
},
|
|
1573
|
+
},
|
|
1574
|
+
},
|
|
1575
|
+
},
|
|
1576
|
+
},
|
|
1577
|
+
...authErrors,
|
|
1578
|
+
},
|
|
1579
|
+
},
|
|
1580
|
+
},
|
|
1581
|
+
|
|
1582
|
+
"/api/v1/admin/me/password": {
|
|
1583
|
+
post: {
|
|
1584
|
+
operationId: "adminChangePassword",
|
|
1585
|
+
summary: "Change password",
|
|
1586
|
+
description: "Changes the current user's password. Available to any authenticated managed-auth user.",
|
|
1587
|
+
tags: ["Admin"],
|
|
1588
|
+
security: [{ bearerAuth: [] }],
|
|
1589
|
+
requestBody: {
|
|
1590
|
+
required: true,
|
|
1591
|
+
content: {
|
|
1592
|
+
"application/json": {
|
|
1593
|
+
schema: {
|
|
1594
|
+
type: "object",
|
|
1595
|
+
required: ["currentPassword", "newPassword"],
|
|
1596
|
+
properties: {
|
|
1597
|
+
currentPassword: { type: "string" },
|
|
1598
|
+
newPassword: { type: "string", minLength: 8 },
|
|
1599
|
+
},
|
|
1600
|
+
},
|
|
1601
|
+
},
|
|
1602
|
+
},
|
|
1603
|
+
},
|
|
1604
|
+
responses: {
|
|
1605
|
+
"200": { description: "Password changed", content: { "application/json": { schema: { type: "object" } } } },
|
|
1606
|
+
"400": errorResponse("Invalid current password or weak new password"),
|
|
1607
|
+
...authErrors,
|
|
1608
|
+
},
|
|
1609
|
+
},
|
|
1610
|
+
},
|
|
1611
|
+
},
|
|
1612
|
+
components: {
|
|
1613
|
+
securitySchemes: {
|
|
1614
|
+
bearerAuth: {
|
|
1615
|
+
type: "http",
|
|
1616
|
+
scheme: "bearer",
|
|
1617
|
+
description:
|
|
1618
|
+
"API key or JWT token. Pass via Authorization: Bearer <token>.",
|
|
1619
|
+
},
|
|
1620
|
+
},
|
|
1621
|
+
},
|
|
1622
|
+
tags: [
|
|
1623
|
+
{ name: "Chat", description: "Streaming chat with the Atlas agent" },
|
|
1624
|
+
{ name: "Query", description: "Synchronous JSON query endpoint" },
|
|
1625
|
+
{ name: "Conversations", description: "Conversation history CRUD operations" },
|
|
376
1626
|
{ name: "Health", description: "Service health checks" },
|
|
1627
|
+
{ name: "Actions", description: "Approval-gated write operations (requires ATLAS_ACTIONS_ENABLED=true)" },
|
|
1628
|
+
{ name: "Scheduled Tasks", description: "Recurring query tasks with cron scheduling (requires ATLAS_SCHEDULER_ENABLED=true)" },
|
|
1629
|
+
{ name: "Auth", description: "Authentication routes (managed auth via Better Auth)" },
|
|
1630
|
+
{ name: "Slack", description: "Slack integration (requires SLACK_SIGNING_SECRET)" },
|
|
1631
|
+
{ name: "Admin", description: "Admin console API (requires admin role)" },
|
|
377
1632
|
],
|
|
378
1633
|
};
|
|
379
1634
|
}
|