spine-framework 0.1.0
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/.framework/README.md +129 -0
- package/.framework/cli/bin.cjs +14 -0
- package/.framework/cli/commands/agents.ts +153 -0
- package/.framework/cli/commands/auth.ts +94 -0
- package/.framework/cli/commands/create-app.ts +185 -0
- package/.framework/cli/commands/dev.ts +295 -0
- package/.framework/cli/commands/doctor.ts +442 -0
- package/.framework/cli/commands/generate.ts +332 -0
- package/.framework/cli/commands/init.ts +272 -0
- package/.framework/cli/commands/install-app.ts +391 -0
- package/.framework/cli/commands/items.ts +253 -0
- package/.framework/cli/commands/migrations.ts +141 -0
- package/.framework/cli/commands/pipelines.ts +166 -0
- package/.framework/cli/commands/status.ts +197 -0
- package/.framework/cli/commands/system.ts +184 -0
- package/.framework/cli/commands/test.ts +227 -0
- package/.framework/cli/commands/uninstall-app.ts +166 -0
- package/.framework/cli/context.ts +268 -0
- package/.framework/cli/env-loader.ts +36 -0
- package/.framework/cli/index.ts +106 -0
- package/.framework/cli/welcome.cjs +45 -0
- package/.framework/docs/API.md +384 -0
- package/.framework/docs/STABILITY.md +52 -0
- package/.framework/docs/admin-routes.md +76 -0
- package/.framework/docs/api-docs-progress.md +38 -0
- package/.framework/docs/api-governance.md +146 -0
- package/.framework/docs/api-testing-results.md +212 -0
- package/.framework/docs/apis/admin-configs.md +567 -0
- package/.framework/docs/apis/admin-data.md +272 -0
- package/.framework/docs/apis/index.md +231 -0
- package/.framework/docs/apis/internal.md +295 -0
- package/.framework/docs/apis/runtime.md +537 -0
- package/.framework/docs/assembly-launch-guide.md +138 -0
- package/.framework/docs/audit-results.md +590 -0
- package/.framework/docs/authorization-model.md +170 -0
- package/.framework/docs/db-api-inventory.md +95 -0
- package/.framework/docs/examples/custom-app/README.md +77 -0
- package/.framework/docs/examples/custom-function/README.md +27 -0
- package/.framework/docs/examples/custom-function/handler.ts +48 -0
- package/.framework/docs/examples/custom-webhook/README.md +68 -0
- package/.framework/docs/gap-remediation-backlog.md +103 -0
- package/.framework/docs/guides/cli-guide.md +224 -0
- package/.framework/docs/guides/getting-started.md +103 -0
- package/.framework/docs/guides/import-guide.md +193 -0
- package/.framework/docs/guides/testing-guide.md +229 -0
- package/.framework/docs/permission-examples.md +326 -0
- package/.framework/docs/ui-adoption-verification.md +111 -0
- package/.framework/docs/ui-api-coverage.md +84 -0
- package/.framework/docs/v2-compatibility-audit.md +228 -0
- package/.framework/functions/.gitkeep +1 -0
- package/.framework/functions/_shared/agent-runner.ts +1097 -0
- package/.framework/functions/_shared/app-manifest.ts +184 -0
- package/.framework/functions/_shared/audit.ts +150 -0
- package/.framework/functions/_shared/db.ts +174 -0
- package/.framework/functions/_shared/index.ts +382 -0
- package/.framework/functions/_shared/middleware.ts +490 -0
- package/.framework/functions/_shared/permissions.ts +1325 -0
- package/.framework/functions/_shared/pipeline-runner.ts +731 -0
- package/.framework/functions/_shared/principal.ts +760 -0
- package/.framework/functions/_shared/schema-utils.ts +967 -0
- package/.framework/functions/_shared/testing.ts +258 -0
- package/.framework/functions/_shared/trigger-engine.ts +425 -0
- package/.framework/functions/_shared/webhook-registration.ts +168 -0
- package/.framework/functions/_shared/webhook-registry.ts +129 -0
- package/.framework/functions/account-nodes.ts +111 -0
- package/.framework/functions/admin-data.ts +606 -0
- package/.framework/functions/ai-agents.ts +323 -0
- package/.framework/functions/api-keys.ts +376 -0
- package/.framework/functions/apps.ts +483 -0
- package/.framework/functions/auth.ts +196 -0
- package/.framework/functions/debug-auth.ts +107 -0
- package/.framework/functions/embeddings.ts +556 -0
- package/.framework/functions/integration-routes.ts +523 -0
- package/.framework/functions/integrations.ts +319 -0
- package/.framework/functions/item-progress.ts +272 -0
- package/.framework/functions/logs.ts +438 -0
- package/.framework/functions/observability.ts +275 -0
- package/.framework/functions/pipeline-executions.ts +494 -0
- package/.framework/functions/pipelines.ts +485 -0
- package/.framework/functions/prompt-configs.ts +339 -0
- package/.framework/functions/roles.ts +387 -0
- package/.framework/functions/system-cron.ts +742 -0
- package/.framework/functions/system.ts +323 -0
- package/.framework/functions/tests.ts +119 -0
- package/.framework/functions/timers.ts +357 -0
- package/.framework/functions/triggers.ts +563 -0
- package/.framework/functions/types.ts +604 -0
- package/.framework/migrations/000_foundation.sql +1256 -0
- package/.framework/migrations/001_seed.sql +92 -0
- package/.framework/migrations/002_seed_constraints.sql +13 -0
- package/.framework/migrations/003_auth_user_trigger.sql +59 -0
- package/.framework/src/App.tsx +126 -0
- package/.framework/src/apps/admin/index.tsx +173 -0
- package/.framework/src/components/AppWrapper.tsx +56 -0
- package/.framework/src/components/CustomAppLoader.tsx +116 -0
- package/.framework/src/components/admin/AdminListPage.tsx +151 -0
- package/.framework/src/components/admin/AdminSidebar.tsx +166 -0
- package/.framework/src/components/admin/AdminStatsCard.tsx +62 -0
- package/.framework/src/components/admin/SortableTableHeader.tsx +42 -0
- package/.framework/src/components/app-shell/GenericAppShell.tsx +181 -0
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +200 -0
- package/.framework/src/components/app-shell/GenericListPage.tsx +116 -0
- package/.framework/src/components/app-sidebar.tsx +228 -0
- package/.framework/src/components/auth/ProtectedRoute.tsx +88 -0
- package/.framework/src/components/layout/AppShell.tsx +91 -0
- package/.framework/src/components/layout/Header.tsx +88 -0
- package/.framework/src/components/layout/Layout.tsx +95 -0
- package/.framework/src/components/layout/Sidebar.tsx +329 -0
- package/.framework/src/components/runtime/DataDetailHeader.tsx +77 -0
- package/.framework/src/components/runtime/DataDetailPage.tsx +171 -0
- package/.framework/src/components/runtime/DataFilters.tsx +91 -0
- package/.framework/src/components/runtime/DataHeader.tsx +68 -0
- package/.framework/src/components/runtime/DataListPage.tsx +124 -0
- package/.framework/src/components/runtime/DataStats.tsx +70 -0
- package/.framework/src/components/runtime/DataTable.tsx +174 -0
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +134 -0
- package/.framework/src/components/runtime/index.ts +18 -0
- package/.framework/src/components/search-form.tsx +29 -0
- package/.framework/src/components/shared/AgentView.tsx +213 -0
- package/.framework/src/components/shared/FieldRenderer.tsx +478 -0
- package/.framework/src/components/shared/SchemaFields.tsx +226 -0
- package/.framework/src/components/ui/DataTable.tsx +343 -0
- package/.framework/src/components/ui/Form.tsx +281 -0
- package/.framework/src/components/ui/ItemCard.tsx +296 -0
- package/.framework/src/components/ui/ItemListView.tsx +308 -0
- package/.framework/src/components/ui/LoadingSpinner.tsx +52 -0
- package/.framework/src/components/ui/Modal.tsx +61 -0
- package/.framework/src/components/ui/RichTextEditor.tsx +210 -0
- package/.framework/src/components/ui/accordion.tsx +82 -0
- package/.framework/src/components/ui/alert-dialog.tsx +197 -0
- package/.framework/src/components/ui/alert.tsx +76 -0
- package/.framework/src/components/ui/aspect-ratio.tsx +11 -0
- package/.framework/src/components/ui/avatar.tsx +110 -0
- package/.framework/src/components/ui/badge.tsx +49 -0
- package/.framework/src/components/ui/breadcrumb.tsx +122 -0
- package/.framework/src/components/ui/button-group.tsx +83 -0
- package/.framework/src/components/ui/button.tsx +65 -0
- package/.framework/src/components/ui/calendar.tsx +222 -0
- package/.framework/src/components/ui/card.tsx +100 -0
- package/.framework/src/components/ui/carousel.tsx +240 -0
- package/.framework/src/components/ui/chart.tsx +373 -0
- package/.framework/src/components/ui/checkbox.tsx +31 -0
- package/.framework/src/components/ui/collapsible.tsx +33 -0
- package/.framework/src/components/ui/combobox.tsx +299 -0
- package/.framework/src/components/ui/command.tsx +193 -0
- package/.framework/src/components/ui/context-menu.tsx +261 -0
- package/.framework/src/components/ui/dialog.tsx +165 -0
- package/.framework/src/components/ui/direction.tsx +22 -0
- package/.framework/src/components/ui/drawer.tsx +132 -0
- package/.framework/src/components/ui/dropdown-menu.tsx +269 -0
- package/.framework/src/components/ui/empty.tsx +104 -0
- package/.framework/src/components/ui/field.tsx +238 -0
- package/.framework/src/components/ui/hover-card.tsx +42 -0
- package/.framework/src/components/ui/input-group.tsx +153 -0
- package/.framework/src/components/ui/input-otp.tsx +87 -0
- package/.framework/src/components/ui/input.tsx +19 -0
- package/.framework/src/components/ui/item.tsx +196 -0
- package/.framework/src/components/ui/kbd.tsx +26 -0
- package/.framework/src/components/ui/label.tsx +22 -0
- package/.framework/src/components/ui/menubar.tsx +277 -0
- package/.framework/src/components/ui/native-select.tsx +61 -0
- package/.framework/src/components/ui/navigation-menu.tsx +164 -0
- package/.framework/src/components/ui/pagination.tsx +129 -0
- package/.framework/src/components/ui/popover.tsx +87 -0
- package/.framework/src/components/ui/progress.tsx +31 -0
- package/.framework/src/components/ui/radio-group.tsx +42 -0
- package/.framework/src/components/ui/resizable.tsx +50 -0
- package/.framework/src/components/ui/scroll-area.tsx +53 -0
- package/.framework/src/components/ui/select.tsx +195 -0
- package/.framework/src/components/ui/separator.tsx +26 -0
- package/.framework/src/components/ui/sheet.tsx +145 -0
- package/.framework/src/components/ui/sidebar.tsx +706 -0
- package/.framework/src/components/ui/skeleton.tsx +13 -0
- package/.framework/src/components/ui/slider.tsx +59 -0
- package/.framework/src/components/ui/sonner.tsx +47 -0
- package/.framework/src/components/ui/spinner.tsx +10 -0
- package/.framework/src/components/ui/switch.tsx +33 -0
- package/.framework/src/components/ui/table-primitives.tsx +141 -0
- package/.framework/src/components/ui/table.tsx +114 -0
- package/.framework/src/components/ui/tabs.tsx +90 -0
- package/.framework/src/components/ui/textarea.tsx +18 -0
- package/.framework/src/components/ui/toggle-group.tsx +89 -0
- package/.framework/src/components/ui/toggle.tsx +45 -0
- package/.framework/src/components/ui/tooltip.tsx +57 -0
- package/.framework/src/contexts/AppContext.tsx +133 -0
- package/.framework/src/contexts/AuthContext.tsx +371 -0
- package/.framework/src/hooks/use-mobile.ts +19 -0
- package/.framework/src/hooks/useApi.ts +526 -0
- package/.framework/src/hooks/useApps.ts +114 -0
- package/.framework/src/hooks/useEntityList.ts +190 -0
- package/.framework/src/hooks/useEntityRecord.ts +308 -0
- package/.framework/src/hooks/useForm.ts +307 -0
- package/.framework/src/hooks/useListSchema.ts +264 -0
- package/.framework/src/hooks/useSchemaRecord.ts +223 -0
- package/.framework/src/index.css +128 -0
- package/.framework/src/lib/api.ts +156 -0
- package/.framework/src/lib/supabase.ts +94 -0
- package/.framework/src/lib/utils.ts +317 -0
- package/.framework/src/main.tsx +27 -0
- package/.framework/src/pages/DashboardPage.tsx +181 -0
- package/.framework/src/pages/NotFoundPage.tsx +39 -0
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +161 -0
- package/.framework/src/pages/admin/AIAgentsPage.tsx +318 -0
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +199 -0
- package/.framework/src/pages/admin/APIKeysPage.tsx +303 -0
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +523 -0
- package/.framework/src/pages/admin/AppDetailPage.tsx +493 -0
- package/.framework/src/pages/admin/AppsPage.tsx +355 -0
- package/.framework/src/pages/admin/DesignedPage.tsx +491 -0
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +534 -0
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +424 -0
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +176 -0
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +109 -0
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +402 -0
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +187 -0
- package/.framework/src/pages/admin/IntegrationsPage.tsx +301 -0
- package/.framework/src/pages/admin/LogsPage.tsx +283 -0
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +85 -0
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +470 -0
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +183 -0
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +279 -0
- package/.framework/src/pages/admin/PipelinesPage.tsx +390 -0
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +299 -0
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +292 -0
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +434 -0
- package/.framework/src/pages/admin/RoleDetailPage.tsx +273 -0
- package/.framework/src/pages/admin/RolesPage.tsx +292 -0
- package/.framework/src/pages/admin/SelectTestPage.tsx +61 -0
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +588 -0
- package/.framework/src/pages/admin/SimpleDashboard.tsx +387 -0
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +172 -0
- package/.framework/src/pages/admin/TestingDashboard.tsx +257 -0
- package/.framework/src/pages/admin/TimerDetailPage.tsx +151 -0
- package/.framework/src/pages/admin/TimersPage.tsx +376 -0
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +149 -0
- package/.framework/src/pages/admin/TriggersPage.tsx +381 -0
- package/.framework/src/pages/admin/TypeDetailPage.tsx +694 -0
- package/.framework/src/pages/admin/TypesPage.tsx +295 -0
- package/.framework/src/pages/auth/LoginPage.tsx +188 -0
- package/.framework/src/pages/auth/RegisterPage.tsx +163 -0
- package/.framework/src/pages/spine-framework/APIPage.tsx +17 -0
- package/.framework/src/pages/spine-framework/CLIPage.tsx +25 -0
- package/.framework/src/types/auth.ts +125 -0
- package/.framework/src/types/types.ts +407 -0
- package/STRUCTURE.md +150 -0
- package/config/components.json +25 -0
- package/config/deno.lock +108 -0
- package/config/package-lock.json +17183 -0
- package/config/postcss.config.cjs +10 -0
- package/config/tailwind.config.cjs +78 -0
- package/config/tsconfig.build.json +32 -0
- package/config/tsconfig.cli.json +18 -0
- package/config/tsconfig.json +41 -0
- package/config/tsconfig.node.json +17 -0
- package/config/tsconfig.node.tsbuildinfo +1 -0
- package/config/tsconfig.tsbuildinfo +1 -0
- package/config/typedoc.json +16 -0
- package/config/vite.config.d.ts +2 -0
- package/config/vite.config.ts +72 -0
- package/dist/cli/commands/agents.d.ts +39 -0
- package/dist/cli/commands/agents.d.ts.map +1 -0
- package/dist/cli/commands/auth.d.ts +36 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/create-app.d.ts +23 -0
- package/dist/cli/commands/create-app.d.ts.map +1 -0
- package/dist/cli/commands/dev.d.ts +39 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/doctor.d.ts +42 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/generate.d.ts +36 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/init.d.ts +30 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/install-app.d.ts +30 -0
- package/dist/cli/commands/install-app.d.ts.map +1 -0
- package/dist/cli/commands/items.d.ts +45 -0
- package/dist/cli/commands/items.d.ts.map +1 -0
- package/dist/cli/commands/migrations.d.ts +41 -0
- package/dist/cli/commands/migrations.d.ts.map +1 -0
- package/dist/cli/commands/pipelines.d.ts +40 -0
- package/dist/cli/commands/pipelines.d.ts.map +1 -0
- package/dist/cli/commands/status.d.ts +23 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/system.d.ts +29 -0
- package/dist/cli/commands/system.d.ts.map +1 -0
- package/dist/cli/commands/test.d.ts +46 -0
- package/dist/cli/commands/test.d.ts.map +1 -0
- package/dist/cli/commands/uninstall-app.d.ts +23 -0
- package/dist/cli/commands/uninstall-app.d.ts.map +1 -0
- package/dist/cli/context.d.ts +88 -0
- package/dist/cli/context.d.ts.map +1 -0
- package/dist/cli/env-loader.d.ts +14 -0
- package/dist/cli/env-loader.d.ts.map +1 -0
- package/dist/cli/index.d.ts +41 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/functions/_shared/agent-runner.d.ts +156 -0
- package/dist/functions/_shared/agent-runner.d.ts.map +1 -0
- package/dist/functions/_shared/app-manifest.d.ts +68 -0
- package/dist/functions/_shared/app-manifest.d.ts.map +1 -0
- package/dist/functions/_shared/audit.d.ts +91 -0
- package/dist/functions/_shared/audit.d.ts.map +1 -0
- package/dist/functions/_shared/db.d.ts +125 -0
- package/dist/functions/_shared/db.d.ts.map +1 -0
- package/dist/functions/_shared/index.d.ts +298 -0
- package/dist/functions/_shared/index.d.ts.map +1 -0
- package/dist/functions/_shared/middleware.d.ts +315 -0
- package/dist/functions/_shared/middleware.d.ts.map +1 -0
- package/dist/functions/_shared/permissions.d.ts +626 -0
- package/dist/functions/_shared/permissions.d.ts.map +1 -0
- package/dist/functions/_shared/pipeline-runner.d.ts +124 -0
- package/dist/functions/_shared/pipeline-runner.d.ts.map +1 -0
- package/dist/functions/_shared/principal.d.ts +284 -0
- package/dist/functions/_shared/principal.d.ts.map +1 -0
- package/dist/functions/_shared/schema-utils.d.ts +181 -0
- package/dist/functions/_shared/schema-utils.d.ts.map +1 -0
- package/dist/functions/_shared/testing.d.ts +172 -0
- package/dist/functions/_shared/testing.d.ts.map +1 -0
- package/dist/functions/_shared/trigger-engine.d.ts +140 -0
- package/dist/functions/_shared/trigger-engine.d.ts.map +1 -0
- package/dist/functions/_shared/webhook-registration.d.ts +81 -0
- package/dist/functions/_shared/webhook-registration.d.ts.map +1 -0
- package/dist/functions/_shared/webhook-registry.d.ts +57 -0
- package/dist/functions/_shared/webhook-registry.d.ts.map +1 -0
- package/dist/functions/account-nodes.d.ts +48 -0
- package/dist/functions/account-nodes.d.ts.map +1 -0
- package/dist/functions/admin-data.d.ts +178 -0
- package/dist/functions/admin-data.d.ts.map +1 -0
- package/dist/functions/ai-agents.d.ts +125 -0
- package/dist/functions/ai-agents.d.ts.map +1 -0
- package/dist/functions/api-keys.d.ts +140 -0
- package/dist/functions/api-keys.d.ts.map +1 -0
- package/dist/functions/apps.d.ts +163 -0
- package/dist/functions/apps.d.ts.map +1 -0
- package/dist/functions/auth.d.ts +74 -0
- package/dist/functions/auth.d.ts.map +1 -0
- package/dist/functions/debug-auth.d.ts +33 -0
- package/dist/functions/debug-auth.d.ts.map +1 -0
- package/dist/functions/embeddings.d.ts +205 -0
- package/dist/functions/embeddings.d.ts.map +1 -0
- package/dist/functions/integration-routes.d.ts +45 -0
- package/dist/functions/integration-routes.d.ts.map +1 -0
- package/dist/functions/integrations.d.ts +124 -0
- package/dist/functions/integrations.d.ts.map +1 -0
- package/dist/functions/item-progress.d.ts +41 -0
- package/dist/functions/item-progress.d.ts.map +1 -0
- package/dist/functions/logs.d.ts +162 -0
- package/dist/functions/logs.d.ts.map +1 -0
- package/dist/functions/observability.d.ts +123 -0
- package/dist/functions/observability.d.ts.map +1 -0
- package/dist/functions/pipeline-executions.d.ts +190 -0
- package/dist/functions/pipeline-executions.d.ts.map +1 -0
- package/dist/functions/pipelines.d.ts +171 -0
- package/dist/functions/pipelines.d.ts.map +1 -0
- package/dist/functions/prompt-configs.d.ts +125 -0
- package/dist/functions/prompt-configs.d.ts.map +1 -0
- package/dist/functions/roles.d.ts +118 -0
- package/dist/functions/roles.d.ts.map +1 -0
- package/dist/functions/system-cron.d.ts +65 -0
- package/dist/functions/system-cron.d.ts.map +1 -0
- package/dist/functions/system.d.ts +29 -0
- package/dist/functions/system.d.ts.map +1 -0
- package/dist/functions/tests.d.ts +28 -0
- package/dist/functions/tests.d.ts.map +1 -0
- package/dist/functions/timers.d.ts +139 -0
- package/dist/functions/timers.d.ts.map +1 -0
- package/dist/functions/triggers.d.ts +203 -0
- package/dist/functions/triggers.d.ts.map +1 -0
- package/dist/functions/types.d.ts +151 -0
- package/dist/functions/types.d.ts.map +1 -0
- package/dist/src/types/types.d.ts +364 -0
- package/dist/src/types/types.d.ts.map +1 -0
- package/package.json +192 -0
- package/scripts/app-install-cli.ts +286 -0
- package/scripts/assemble-frontend.sh +79 -0
- package/scripts/assemble-functions.sh +62 -0
- package/scripts/assemble.sh +35 -0
- package/scripts/boundary-check.sh +106 -0
- package/scripts/build-manifest.sh +80 -0
- package/scripts/check-core-integrity.sh +82 -0
- package/scripts/ingest-chunks.cjs +202 -0
- package/scripts/kb-chunk-parser.cjs +312 -0
- package/scripts/kb-chunk-parser.ts +330 -0
- package/scripts/load-test-app-install.ts +484 -0
- package/scripts/netlify-dev-wrapper.sh +22 -0
- package/scripts/verify-integrity.sh +69 -0
|
@@ -0,0 +1,1256 @@
|
|
|
1
|
+
-- =============================================================================
|
|
2
|
+
-- 000_foundation.sql
|
|
3
|
+
-- Spine Framework — Complete schema for a fresh install
|
|
4
|
+
-- Generated from live production DB audit: May 28, 2026
|
|
5
|
+
-- =============================================================================
|
|
6
|
+
-- Run this on a blank Supabase project to create all core tables.
|
|
7
|
+
-- Follow with 001_seed.sql to insert bootstrap data.
|
|
8
|
+
-- =============================================================================
|
|
9
|
+
|
|
10
|
+
-- ---------------------------------------------------------------------------
|
|
11
|
+
-- Extensions
|
|
12
|
+
-- ---------------------------------------------------------------------------
|
|
13
|
+
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
14
|
+
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
15
|
+
CREATE EXTENSION IF NOT EXISTS "vector";
|
|
16
|
+
|
|
17
|
+
-- ---------------------------------------------------------------------------
|
|
18
|
+
-- Helper Functions (must exist before triggers)
|
|
19
|
+
-- ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
CREATE OR REPLACE FUNCTION public.set_updated_at()
|
|
22
|
+
RETURNS TRIGGER LANGUAGE plpgsql AS $$
|
|
23
|
+
BEGIN
|
|
24
|
+
NEW.updated_at = now();
|
|
25
|
+
RETURN NEW;
|
|
26
|
+
END;
|
|
27
|
+
$$;
|
|
28
|
+
|
|
29
|
+
CREATE OR REPLACE FUNCTION public.current_actor_id()
|
|
30
|
+
RETURNS uuid LANGUAGE plpgsql SECURITY DEFINER AS $$
|
|
31
|
+
DECLARE
|
|
32
|
+
v_auth_id UUID;
|
|
33
|
+
v_person_id UUID;
|
|
34
|
+
BEGIN
|
|
35
|
+
v_auth_id := auth.uid();
|
|
36
|
+
SELECT p.id INTO v_person_id
|
|
37
|
+
FROM public.people p
|
|
38
|
+
WHERE p.auth_uid = v_auth_id AND p.is_active = true
|
|
39
|
+
LIMIT 1;
|
|
40
|
+
RETURN v_person_id;
|
|
41
|
+
END;
|
|
42
|
+
$$;
|
|
43
|
+
|
|
44
|
+
CREATE OR REPLACE FUNCTION public.person_is_system_admin(person_uuid uuid)
|
|
45
|
+
RETURNS boolean LANGUAGE plpgsql SECURITY DEFINER AS $$
|
|
46
|
+
BEGIN
|
|
47
|
+
RETURN EXISTS (
|
|
48
|
+
SELECT 1 FROM public.people p
|
|
49
|
+
JOIN public.roles r ON p.role_id = r.id
|
|
50
|
+
WHERE p.id = person_uuid AND r.slug = 'system_admin'
|
|
51
|
+
);
|
|
52
|
+
END;
|
|
53
|
+
$$;
|
|
54
|
+
|
|
55
|
+
CREATE OR REPLACE FUNCTION public.get_accessible_accounts(actor_id uuid)
|
|
56
|
+
RETURNS SETOF uuid LANGUAGE plpgsql SECURITY DEFINER AS $$
|
|
57
|
+
DECLARE
|
|
58
|
+
actor_person_id uuid;
|
|
59
|
+
BEGIN
|
|
60
|
+
SELECT p.id INTO actor_person_id
|
|
61
|
+
FROM public.people p
|
|
62
|
+
WHERE p.id = actor_id AND p.is_active = true
|
|
63
|
+
LIMIT 1;
|
|
64
|
+
|
|
65
|
+
IF actor_person_id IS NULL THEN
|
|
66
|
+
SELECT p.id INTO actor_person_id
|
|
67
|
+
FROM public.people p
|
|
68
|
+
WHERE p.auth_uid = actor_id AND p.is_active = true
|
|
69
|
+
LIMIT 1;
|
|
70
|
+
END IF;
|
|
71
|
+
|
|
72
|
+
IF actor_person_id IS NULL THEN
|
|
73
|
+
RETURN;
|
|
74
|
+
END IF;
|
|
75
|
+
|
|
76
|
+
IF EXISTS (
|
|
77
|
+
SELECT 1 FROM public.people p
|
|
78
|
+
JOIN public.roles r ON p.role_id = r.id
|
|
79
|
+
WHERE p.id = actor_person_id AND r.slug = 'system_admin'
|
|
80
|
+
) THEN
|
|
81
|
+
RETURN QUERY SELECT a.id FROM public.accounts a;
|
|
82
|
+
RETURN;
|
|
83
|
+
END IF;
|
|
84
|
+
|
|
85
|
+
RETURN QUERY
|
|
86
|
+
WITH RECURSIVE account_tree AS (
|
|
87
|
+
SELECT p.account_id AS id FROM public.people p WHERE p.id = actor_person_id
|
|
88
|
+
UNION ALL
|
|
89
|
+
SELECT ap.descendant_id
|
|
90
|
+
FROM public.account_paths ap
|
|
91
|
+
JOIN account_tree at ON ap.ancestor_id = at.id
|
|
92
|
+
)
|
|
93
|
+
SELECT id FROM account_tree;
|
|
94
|
+
END;
|
|
95
|
+
$$;
|
|
96
|
+
|
|
97
|
+
CREATE OR REPLACE FUNCTION public.update_account_paths()
|
|
98
|
+
RETURNS TRIGGER LANGUAGE plpgsql AS $$
|
|
99
|
+
BEGIN
|
|
100
|
+
IF TG_OP = 'INSERT' THEN
|
|
101
|
+
IF NEW.parent_id IS NOT NULL THEN
|
|
102
|
+
INSERT INTO public.account_paths (ancestor_id, descendant_id, depth)
|
|
103
|
+
SELECT ancestor_id, NEW.id, depth + 1 FROM public.account_paths WHERE descendant_id = NEW.parent_id;
|
|
104
|
+
INSERT INTO public.account_paths (ancestor_id, descendant_id, depth) VALUES (NEW.parent_id, NEW.id, 1);
|
|
105
|
+
END IF;
|
|
106
|
+
RETURN NEW;
|
|
107
|
+
END IF;
|
|
108
|
+
IF TG_OP = 'UPDATE' AND OLD.parent_id IS DISTINCT FROM NEW.parent_id THEN
|
|
109
|
+
DELETE FROM public.account_paths WHERE descendant_id = NEW.id;
|
|
110
|
+
IF NEW.parent_id IS NOT NULL THEN
|
|
111
|
+
INSERT INTO public.account_paths (ancestor_id, descendant_id, depth)
|
|
112
|
+
SELECT ancestor_id, NEW.id, depth + 1 FROM public.account_paths WHERE descendant_id = NEW.parent_id;
|
|
113
|
+
INSERT INTO public.account_paths (ancestor_id, descendant_id, depth) VALUES (NEW.parent_id, NEW.id, 1);
|
|
114
|
+
END IF;
|
|
115
|
+
RETURN NEW;
|
|
116
|
+
END IF;
|
|
117
|
+
IF TG_OP = 'DELETE' THEN
|
|
118
|
+
DELETE FROM public.account_paths WHERE descendant_id = OLD.id;
|
|
119
|
+
RETURN OLD;
|
|
120
|
+
END IF;
|
|
121
|
+
RETURN NULL;
|
|
122
|
+
END;
|
|
123
|
+
$$;
|
|
124
|
+
|
|
125
|
+
-- ---------------------------------------------------------------------------
|
|
126
|
+
-- Core Tables (dependency order)
|
|
127
|
+
-- ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
-- roles (no dependencies)
|
|
130
|
+
CREATE TABLE IF NOT EXISTS public.roles (
|
|
131
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
132
|
+
slug text NOT NULL,
|
|
133
|
+
name text NOT NULL,
|
|
134
|
+
description text,
|
|
135
|
+
permissions jsonb DEFAULT '[]'::jsonb,
|
|
136
|
+
is_system boolean DEFAULT false,
|
|
137
|
+
is_active boolean DEFAULT true,
|
|
138
|
+
is_protected boolean DEFAULT false,
|
|
139
|
+
app_id uuid,
|
|
140
|
+
account_id uuid,
|
|
141
|
+
created_at timestamptz DEFAULT now(),
|
|
142
|
+
updated_at timestamptz DEFAULT now()
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
-- apps (no dependencies on other custom tables)
|
|
146
|
+
CREATE TABLE IF NOT EXISTS public.apps (
|
|
147
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
148
|
+
slug text NOT NULL UNIQUE,
|
|
149
|
+
name text NOT NULL,
|
|
150
|
+
description text,
|
|
151
|
+
icon text,
|
|
152
|
+
color text,
|
|
153
|
+
version text DEFAULT '0.1.0',
|
|
154
|
+
app_type text DEFAULT 'custom',
|
|
155
|
+
source text DEFAULT 'local',
|
|
156
|
+
account_id uuid,
|
|
157
|
+
owner_account_id uuid,
|
|
158
|
+
is_active boolean DEFAULT true,
|
|
159
|
+
is_system boolean DEFAULT false,
|
|
160
|
+
min_role text,
|
|
161
|
+
config jsonb DEFAULT '{}'::jsonb,
|
|
162
|
+
nav_items jsonb DEFAULT '[]'::jsonb,
|
|
163
|
+
route_prefix text,
|
|
164
|
+
renderer text DEFAULT 'react',
|
|
165
|
+
manifest_path text,
|
|
166
|
+
integration_deps jsonb DEFAULT '[]'::jsonb,
|
|
167
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
168
|
+
created_at timestamptz DEFAULT now(),
|
|
169
|
+
updated_at timestamptz DEFAULT now()
|
|
170
|
+
);
|
|
171
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_apps_route_prefix ON public.apps (route_prefix) WHERE (is_active = true AND route_prefix IS NOT NULL);
|
|
172
|
+
|
|
173
|
+
-- types (depends on apps)
|
|
174
|
+
CREATE TABLE IF NOT EXISTS public.types (
|
|
175
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
176
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE SET NULL,
|
|
177
|
+
kind text NOT NULL,
|
|
178
|
+
slug text NOT NULL,
|
|
179
|
+
name text NOT NULL,
|
|
180
|
+
description text,
|
|
181
|
+
icon text,
|
|
182
|
+
color text,
|
|
183
|
+
design_schema jsonb DEFAULT '{}'::jsonb,
|
|
184
|
+
validation_schema jsonb DEFAULT '{}'::jsonb,
|
|
185
|
+
ownership text DEFAULT 'tenant'::text,
|
|
186
|
+
is_active boolean DEFAULT true,
|
|
187
|
+
created_at timestamptz DEFAULT now(),
|
|
188
|
+
updated_at timestamptz DEFAULT now(),
|
|
189
|
+
UNIQUE (app_id, kind, slug)
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
-- accounts (depends on types, apps, people — people FK added after people table)
|
|
193
|
+
CREATE TABLE IF NOT EXISTS public.accounts (
|
|
194
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
195
|
+
parent_id uuid REFERENCES public.accounts(id) ON DELETE SET NULL,
|
|
196
|
+
type_id uuid NOT NULL REFERENCES public.types(id) ON DELETE RESTRICT,
|
|
197
|
+
slug text NOT NULL UNIQUE,
|
|
198
|
+
display_name text NOT NULL,
|
|
199
|
+
description text,
|
|
200
|
+
data jsonb DEFAULT '{}'::jsonb,
|
|
201
|
+
is_active boolean DEFAULT true,
|
|
202
|
+
created_at timestamptz DEFAULT now(),
|
|
203
|
+
updated_at timestamptz DEFAULT now(),
|
|
204
|
+
design_schema jsonb DEFAULT '{}'::jsonb,
|
|
205
|
+
validation_schema jsonb DEFAULT '{}'::jsonb,
|
|
206
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE SET NULL,
|
|
207
|
+
created_by uuid,
|
|
208
|
+
updated_by uuid
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
-- account_paths (depends on accounts, RLS disabled intentionally — internal trigger-managed)
|
|
212
|
+
CREATE TABLE IF NOT EXISTS public.account_paths (
|
|
213
|
+
ancestor_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
214
|
+
descendant_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
215
|
+
depth integer NOT NULL,
|
|
216
|
+
PRIMARY KEY (ancestor_id, descendant_id)
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
-- people (depends on accounts, types, roles, apps)
|
|
220
|
+
CREATE TABLE IF NOT EXISTS public.people (
|
|
221
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
222
|
+
auth_uid uuid UNIQUE,
|
|
223
|
+
email text NOT NULL,
|
|
224
|
+
full_name text NOT NULL,
|
|
225
|
+
avatar_url text,
|
|
226
|
+
phone text,
|
|
227
|
+
status text DEFAULT 'active',
|
|
228
|
+
data jsonb DEFAULT '{}'::jsonb,
|
|
229
|
+
is_active boolean DEFAULT true,
|
|
230
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
231
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE SET NULL,
|
|
232
|
+
role_id uuid REFERENCES public.roles(id) ON DELETE SET NULL,
|
|
233
|
+
type_id uuid NOT NULL REFERENCES public.types(id) ON DELETE RESTRICT,
|
|
234
|
+
created_at timestamptz DEFAULT now(),
|
|
235
|
+
updated_at timestamptz DEFAULT now(),
|
|
236
|
+
design_schema jsonb DEFAULT '{}'::jsonb,
|
|
237
|
+
validation_schema jsonb DEFAULT '{}'::jsonb,
|
|
238
|
+
created_by uuid
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
-- add deferred FKs now that people exists
|
|
242
|
+
ALTER TABLE public.accounts
|
|
243
|
+
ADD CONSTRAINT IF NOT EXISTS accounts_created_by_fkey FOREIGN KEY (created_by) REFERENCES public.people(id) ON DELETE SET NULL,
|
|
244
|
+
ADD CONSTRAINT IF NOT EXISTS accounts_updated_by_fkey FOREIGN KEY (updated_by) REFERENCES public.people(id) ON DELETE SET NULL;
|
|
245
|
+
|
|
246
|
+
ALTER TABLE public.people
|
|
247
|
+
ADD CONSTRAINT IF NOT EXISTS people_created_by_fkey FOREIGN KEY (created_by) REFERENCES public.people(id) ON DELETE SET NULL;
|
|
248
|
+
|
|
249
|
+
-- add FK on roles.account_id and roles.app_id
|
|
250
|
+
ALTER TABLE public.roles
|
|
251
|
+
ADD CONSTRAINT IF NOT EXISTS roles_account_id_fkey FOREIGN KEY (account_id) REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
252
|
+
ADD CONSTRAINT IF NOT EXISTS roles_app_id_fkey FOREIGN KEY (app_id) REFERENCES public.apps(id) ON DELETE CASCADE;
|
|
253
|
+
|
|
254
|
+
-- add FK on apps.account_id and apps.owner_account_id
|
|
255
|
+
ALTER TABLE public.apps
|
|
256
|
+
ADD CONSTRAINT IF NOT EXISTS apps_account_id_fkey FOREIGN KEY (account_id) REFERENCES public.accounts(id) ON DELETE SET NULL,
|
|
257
|
+
ADD CONSTRAINT IF NOT EXISTS apps_owner_account_id_fkey FOREIGN KEY (owner_account_id) REFERENCES public.accounts(id) ON DELETE SET NULL;
|
|
258
|
+
|
|
259
|
+
-- items (depends on accounts, types, apps)
|
|
260
|
+
CREATE TABLE IF NOT EXISTS public.items (
|
|
261
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
262
|
+
type_id uuid NOT NULL REFERENCES public.types(id) ON DELETE RESTRICT,
|
|
263
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
264
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE SET NULL,
|
|
265
|
+
title text,
|
|
266
|
+
description text,
|
|
267
|
+
status text DEFAULT 'active',
|
|
268
|
+
data jsonb DEFAULT '{}'::jsonb,
|
|
269
|
+
is_active boolean DEFAULT true,
|
|
270
|
+
design_schema jsonb DEFAULT '{}'::jsonb,
|
|
271
|
+
validation_schema jsonb DEFAULT '{}'::jsonb,
|
|
272
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
273
|
+
updated_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
274
|
+
created_at timestamptz DEFAULT now(),
|
|
275
|
+
updated_at timestamptz DEFAULT now()
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
-- link_types (depends on apps)
|
|
279
|
+
CREATE TABLE IF NOT EXISTS public.link_types (
|
|
280
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
281
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE CASCADE,
|
|
282
|
+
slug text NOT NULL,
|
|
283
|
+
name text NOT NULL,
|
|
284
|
+
description text,
|
|
285
|
+
icon text,
|
|
286
|
+
color text,
|
|
287
|
+
config jsonb DEFAULT '{}'::jsonb,
|
|
288
|
+
is_active boolean DEFAULT true,
|
|
289
|
+
created_at timestamptz DEFAULT now(),
|
|
290
|
+
updated_at timestamptz DEFAULT now()
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
-- links (depends on accounts, types, link_types)
|
|
294
|
+
CREATE TABLE IF NOT EXISTS public.links (
|
|
295
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
296
|
+
type_id uuid NOT NULL REFERENCES public.types(id) ON DELETE RESTRICT,
|
|
297
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
298
|
+
link_type_id uuid REFERENCES public.link_types(id) ON DELETE CASCADE,
|
|
299
|
+
source_type text NOT NULL,
|
|
300
|
+
source_id uuid NOT NULL,
|
|
301
|
+
target_type text NOT NULL,
|
|
302
|
+
target_id uuid NOT NULL,
|
|
303
|
+
link_type text,
|
|
304
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
305
|
+
data jsonb DEFAULT '{}'::jsonb,
|
|
306
|
+
design_schema jsonb DEFAULT '{}'::jsonb,
|
|
307
|
+
validation_schema jsonb DEFAULT '{}'::jsonb,
|
|
308
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
309
|
+
updated_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
310
|
+
created_at timestamptz DEFAULT now(),
|
|
311
|
+
updated_at timestamptz DEFAULT now()
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
-- threads (depends on accounts, types, apps, people)
|
|
315
|
+
CREATE TABLE IF NOT EXISTS public.threads (
|
|
316
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
317
|
+
type_id uuid NOT NULL REFERENCES public.types(id) ON DELETE RESTRICT,
|
|
318
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
319
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE SET NULL,
|
|
320
|
+
title text,
|
|
321
|
+
target_type text NOT NULL,
|
|
322
|
+
target_id uuid NOT NULL,
|
|
323
|
+
visibility text DEFAULT 'internal',
|
|
324
|
+
status text DEFAULT 'open',
|
|
325
|
+
data jsonb DEFAULT '{}'::jsonb,
|
|
326
|
+
is_active boolean DEFAULT true,
|
|
327
|
+
design_schema jsonb DEFAULT '{}'::jsonb,
|
|
328
|
+
validation_schema jsonb DEFAULT '{}'::jsonb,
|
|
329
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
330
|
+
updated_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
331
|
+
created_at timestamptz DEFAULT now(),
|
|
332
|
+
updated_at timestamptz DEFAULT now()
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
-- messages (depends on threads, types, accounts, people)
|
|
336
|
+
CREATE TABLE IF NOT EXISTS public.messages (
|
|
337
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
338
|
+
type_id uuid NOT NULL REFERENCES public.types(id) ON DELETE RESTRICT,
|
|
339
|
+
thread_id uuid NOT NULL REFERENCES public.threads(id) ON DELETE CASCADE,
|
|
340
|
+
content text NOT NULL,
|
|
341
|
+
direction text DEFAULT 'outbound',
|
|
342
|
+
sequence integer NOT NULL,
|
|
343
|
+
visibility text DEFAULT 'internal',
|
|
344
|
+
data jsonb DEFAULT '{}'::jsonb,
|
|
345
|
+
is_active boolean DEFAULT true,
|
|
346
|
+
design_schema jsonb DEFAULT '{}'::jsonb,
|
|
347
|
+
validation_schema jsonb DEFAULT '{}'::jsonb,
|
|
348
|
+
person_id uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
349
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
350
|
+
created_at timestamptz DEFAULT now(),
|
|
351
|
+
updated_at timestamptz DEFAULT now(),
|
|
352
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
-- attachments (depends on accounts, types, people)
|
|
356
|
+
CREATE TABLE IF NOT EXISTS public.attachments (
|
|
357
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
358
|
+
type_id uuid NOT NULL REFERENCES public.types(id) ON DELETE RESTRICT,
|
|
359
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
360
|
+
filename text NOT NULL,
|
|
361
|
+
file_size integer,
|
|
362
|
+
mime_type text,
|
|
363
|
+
storage_path text,
|
|
364
|
+
storage_provider text DEFAULT 'supabase',
|
|
365
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
366
|
+
data jsonb DEFAULT '{}'::jsonb,
|
|
367
|
+
design_schema jsonb DEFAULT '{}'::jsonb,
|
|
368
|
+
validation_schema jsonb DEFAULT '{}'::jsonb,
|
|
369
|
+
uploaded_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
370
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
371
|
+
created_at timestamptz DEFAULT now(),
|
|
372
|
+
updated_at timestamptz DEFAULT now()
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
-- watchers (depends on accounts, types, people)
|
|
376
|
+
CREATE TABLE IF NOT EXISTS public.watchers (
|
|
377
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
378
|
+
type_id uuid NOT NULL REFERENCES public.types(id) ON DELETE RESTRICT,
|
|
379
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
380
|
+
target_type text NOT NULL,
|
|
381
|
+
target_id uuid NOT NULL,
|
|
382
|
+
person_id uuid NOT NULL REFERENCES public.people(id) ON DELETE CASCADE,
|
|
383
|
+
watch_type text DEFAULT 'all',
|
|
384
|
+
notification_level text DEFAULT 'all',
|
|
385
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
386
|
+
data jsonb DEFAULT '{}'::jsonb,
|
|
387
|
+
design_schema jsonb DEFAULT '{}'::jsonb,
|
|
388
|
+
validation_schema jsonb DEFAULT '{}'::jsonb,
|
|
389
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
390
|
+
created_at timestamptz DEFAULT now(),
|
|
391
|
+
updated_at timestamptz DEFAULT now(),
|
|
392
|
+
UNIQUE (target_type, target_id, person_id)
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
-- pipelines (depends on accounts, apps, people)
|
|
396
|
+
CREATE TABLE IF NOT EXISTS public.pipelines (
|
|
397
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
398
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
399
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE CASCADE,
|
|
400
|
+
name text NOT NULL,
|
|
401
|
+
description text,
|
|
402
|
+
steps jsonb DEFAULT '[]'::jsonb,
|
|
403
|
+
config jsonb DEFAULT '{}'::jsonb,
|
|
404
|
+
ownership text DEFAULT 'tenant',
|
|
405
|
+
is_system boolean DEFAULT false,
|
|
406
|
+
is_active boolean DEFAULT true,
|
|
407
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
408
|
+
created_at timestamptz DEFAULT now(),
|
|
409
|
+
updated_at timestamptz DEFAULT now()
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
-- pipeline_executions (depends on accounts, pipelines, people)
|
|
413
|
+
CREATE TABLE IF NOT EXISTS public.pipeline_executions (
|
|
414
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
415
|
+
pipeline_id uuid NOT NULL REFERENCES public.pipelines(id) ON DELETE CASCADE,
|
|
416
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
417
|
+
status text DEFAULT 'pending',
|
|
418
|
+
trigger_data jsonb DEFAULT '{}'::jsonb,
|
|
419
|
+
result jsonb DEFAULT '{}'::jsonb,
|
|
420
|
+
error_message text,
|
|
421
|
+
started_at timestamptz,
|
|
422
|
+
completed_at timestamptz,
|
|
423
|
+
duration_ms integer,
|
|
424
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
425
|
+
created_at timestamptz DEFAULT now()
|
|
426
|
+
);
|
|
427
|
+
|
|
428
|
+
-- triggers (depends on accounts, apps, pipelines, people)
|
|
429
|
+
CREATE TABLE IF NOT EXISTS public.triggers (
|
|
430
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
431
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE CASCADE,
|
|
432
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
433
|
+
name text NOT NULL,
|
|
434
|
+
description text,
|
|
435
|
+
trigger_type text NOT NULL,
|
|
436
|
+
event_type text,
|
|
437
|
+
config jsonb DEFAULT '{}'::jsonb,
|
|
438
|
+
pipeline_id uuid REFERENCES public.pipelines(id) ON DELETE SET NULL,
|
|
439
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
440
|
+
ownership text DEFAULT 'tenant',
|
|
441
|
+
is_system boolean DEFAULT false,
|
|
442
|
+
is_active boolean DEFAULT true,
|
|
443
|
+
trigger_count integer DEFAULT 0,
|
|
444
|
+
last_triggered timestamptz,
|
|
445
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
446
|
+
created_at timestamptz DEFAULT now(),
|
|
447
|
+
updated_at timestamptz DEFAULT now()
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
-- trigger_executions (depends on triggers)
|
|
451
|
+
CREATE TABLE IF NOT EXISTS public.trigger_executions (
|
|
452
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
453
|
+
trigger_id uuid NOT NULL REFERENCES public.triggers(id) ON DELETE CASCADE,
|
|
454
|
+
status text DEFAULT 'pending',
|
|
455
|
+
triggered_at timestamptz DEFAULT now(),
|
|
456
|
+
started_at timestamptz,
|
|
457
|
+
completed_at timestamptz,
|
|
458
|
+
trigger_data jsonb DEFAULT '{}'::jsonb,
|
|
459
|
+
result jsonb DEFAULT '{}'::jsonb,
|
|
460
|
+
error_message text,
|
|
461
|
+
duration_ms integer,
|
|
462
|
+
created_at timestamptz DEFAULT now()
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
-- timers (depends on accounts, apps, pipelines, people)
|
|
466
|
+
CREATE TABLE IF NOT EXISTS public.timers (
|
|
467
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
468
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE CASCADE,
|
|
469
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
470
|
+
name text NOT NULL,
|
|
471
|
+
description text,
|
|
472
|
+
timer_type text NOT NULL,
|
|
473
|
+
config jsonb DEFAULT '{}'::jsonb,
|
|
474
|
+
pipeline_id uuid REFERENCES public.pipelines(id) ON DELETE SET NULL,
|
|
475
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
476
|
+
ownership text DEFAULT 'tenant',
|
|
477
|
+
is_system boolean DEFAULT false,
|
|
478
|
+
is_active boolean DEFAULT true,
|
|
479
|
+
last_execution timestamptz,
|
|
480
|
+
next_execution timestamptz,
|
|
481
|
+
execution_count integer DEFAULT 0,
|
|
482
|
+
success_count integer DEFAULT 0,
|
|
483
|
+
failure_count integer DEFAULT 0,
|
|
484
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
485
|
+
created_at timestamptz DEFAULT now(),
|
|
486
|
+
updated_at timestamptz DEFAULT now()
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
-- ai_agents (depends on accounts, apps, people)
|
|
490
|
+
CREATE TABLE IF NOT EXISTS public.ai_agents (
|
|
491
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
492
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE CASCADE,
|
|
493
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
494
|
+
name text NOT NULL,
|
|
495
|
+
description text,
|
|
496
|
+
agent_type text NOT NULL,
|
|
497
|
+
model_config jsonb DEFAULT '{}'::jsonb,
|
|
498
|
+
system_prompt text,
|
|
499
|
+
tools jsonb DEFAULT '[]'::jsonb,
|
|
500
|
+
capabilities jsonb DEFAULT '[]'::jsonb,
|
|
501
|
+
constraints jsonb DEFAULT '{}'::jsonb,
|
|
502
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
503
|
+
ownership text DEFAULT 'tenant',
|
|
504
|
+
is_system boolean DEFAULT false,
|
|
505
|
+
is_active boolean DEFAULT true,
|
|
506
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
507
|
+
created_at timestamptz DEFAULT now(),
|
|
508
|
+
updated_at timestamptz DEFAULT now()
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
-- embeddings (depends on accounts)
|
|
512
|
+
CREATE TABLE IF NOT EXISTS public.embeddings (
|
|
513
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
514
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
515
|
+
model_id text NOT NULL,
|
|
516
|
+
document_id text NOT NULL,
|
|
517
|
+
chunk_index integer NOT NULL,
|
|
518
|
+
content text NOT NULL,
|
|
519
|
+
embedding vector(1536),
|
|
520
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
521
|
+
created_at timestamptz DEFAULT now(),
|
|
522
|
+
UNIQUE (model_id, document_id, chunk_index)
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
-- integrations (depends on accounts, apps, people)
|
|
526
|
+
CREATE TABLE IF NOT EXISTS public.integrations (
|
|
527
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
528
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
529
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE CASCADE,
|
|
530
|
+
name text NOT NULL,
|
|
531
|
+
slug text,
|
|
532
|
+
provider text,
|
|
533
|
+
config jsonb DEFAULT '{}'::jsonb,
|
|
534
|
+
credentials jsonb DEFAULT '{}'::jsonb,
|
|
535
|
+
status text DEFAULT 'active',
|
|
536
|
+
is_active boolean DEFAULT true,
|
|
537
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
538
|
+
created_at timestamptz DEFAULT now(),
|
|
539
|
+
updated_at timestamptz DEFAULT now()
|
|
540
|
+
);
|
|
541
|
+
|
|
542
|
+
-- prompt_configs (depends on accounts, apps, people)
|
|
543
|
+
CREATE TABLE IF NOT EXISTS public.prompt_configs (
|
|
544
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
545
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE CASCADE,
|
|
546
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
547
|
+
slug text NOT NULL,
|
|
548
|
+
name text NOT NULL,
|
|
549
|
+
description text,
|
|
550
|
+
template text,
|
|
551
|
+
variables jsonb DEFAULT '[]'::jsonb,
|
|
552
|
+
config jsonb DEFAULT '{}'::jsonb,
|
|
553
|
+
ownership text DEFAULT 'tenant',
|
|
554
|
+
is_system boolean DEFAULT false,
|
|
555
|
+
is_active boolean DEFAULT true,
|
|
556
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
557
|
+
created_at timestamptz DEFAULT now(),
|
|
558
|
+
updated_at timestamptz DEFAULT now()
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
-- api_keys (depends on accounts, integrations, people)
|
|
562
|
+
CREATE TABLE IF NOT EXISTS public.api_keys (
|
|
563
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
564
|
+
integration_id uuid REFERENCES public.integrations(id) ON DELETE SET NULL,
|
|
565
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
566
|
+
name text NOT NULL,
|
|
567
|
+
key_value text UNIQUE NOT NULL,
|
|
568
|
+
key_prefix text NOT NULL,
|
|
569
|
+
key_type text NOT NULL,
|
|
570
|
+
permissions jsonb DEFAULT '[]'::jsonb,
|
|
571
|
+
rate_limit integer DEFAULT 1000,
|
|
572
|
+
is_active boolean DEFAULT true,
|
|
573
|
+
expires_at timestamptz,
|
|
574
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
575
|
+
ownership text DEFAULT 'tenant',
|
|
576
|
+
is_system boolean DEFAULT false,
|
|
577
|
+
machine_type text,
|
|
578
|
+
is_internal boolean DEFAULT false,
|
|
579
|
+
scopes text[] DEFAULT '{}',
|
|
580
|
+
usage_count integer DEFAULT 0,
|
|
581
|
+
last_used_at timestamptz,
|
|
582
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
583
|
+
created_at timestamptz DEFAULT now(),
|
|
584
|
+
updated_at timestamptz DEFAULT now()
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
-- api_key_usage_logs (depends on api_keys, accounts)
|
|
588
|
+
CREATE TABLE IF NOT EXISTS public.api_key_usage_logs (
|
|
589
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
590
|
+
api_key_id uuid NOT NULL REFERENCES public.api_keys(id) ON DELETE CASCADE,
|
|
591
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
592
|
+
request_method text,
|
|
593
|
+
request_path text,
|
|
594
|
+
request_ip text,
|
|
595
|
+
user_agent text,
|
|
596
|
+
response_status integer,
|
|
597
|
+
response_size integer,
|
|
598
|
+
duration_ms integer,
|
|
599
|
+
success boolean DEFAULT true,
|
|
600
|
+
error_message text,
|
|
601
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
602
|
+
created_at timestamptz DEFAULT now()
|
|
603
|
+
);
|
|
604
|
+
|
|
605
|
+
-- logs (depends on accounts, people)
|
|
606
|
+
CREATE TABLE IF NOT EXISTS public.logs (
|
|
607
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
608
|
+
level text NOT NULL,
|
|
609
|
+
message text NOT NULL,
|
|
610
|
+
context jsonb DEFAULT '{}'::jsonb,
|
|
611
|
+
source text,
|
|
612
|
+
source_type text,
|
|
613
|
+
source_id uuid,
|
|
614
|
+
person_id uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
615
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
616
|
+
metadata jsonb DEFAULT '{}'::jsonb,
|
|
617
|
+
created_at timestamptz DEFAULT now()
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
-- actions (depends on accounts, people)
|
|
621
|
+
CREATE TABLE IF NOT EXISTS public.actions (
|
|
622
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
623
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
624
|
+
name text NOT NULL,
|
|
625
|
+
slug text NOT NULL,
|
|
626
|
+
description text,
|
|
627
|
+
handler text NOT NULL,
|
|
628
|
+
handler_module text DEFAULT 'functions',
|
|
629
|
+
config jsonb DEFAULT '{}'::jsonb,
|
|
630
|
+
input_schema jsonb DEFAULT '{}'::jsonb,
|
|
631
|
+
output_schema jsonb DEFAULT '{}'::jsonb,
|
|
632
|
+
ownership text DEFAULT 'tenant',
|
|
633
|
+
is_system boolean DEFAULT false,
|
|
634
|
+
default_machine_principal_id uuid,
|
|
635
|
+
required_scopes text[] DEFAULT '{}',
|
|
636
|
+
is_active boolean DEFAULT true,
|
|
637
|
+
timeout_seconds integer DEFAULT 300,
|
|
638
|
+
retry_count integer DEFAULT 3,
|
|
639
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
640
|
+
created_at timestamptz DEFAULT now()
|
|
641
|
+
);
|
|
642
|
+
|
|
643
|
+
-- schedules (depends on accounts, actions, people)
|
|
644
|
+
CREATE TABLE IF NOT EXISTS public.schedules (
|
|
645
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
646
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
647
|
+
action_id uuid REFERENCES public.actions(id) ON DELETE CASCADE,
|
|
648
|
+
name text NOT NULL,
|
|
649
|
+
description text,
|
|
650
|
+
cron_expression text,
|
|
651
|
+
config jsonb DEFAULT '{}'::jsonb,
|
|
652
|
+
machine_principal_id uuid,
|
|
653
|
+
delegated_scopes text[] DEFAULT '{}',
|
|
654
|
+
is_active boolean DEFAULT true,
|
|
655
|
+
is_paused boolean DEFAULT false,
|
|
656
|
+
pause_reason text,
|
|
657
|
+
max_retries integer DEFAULT 3,
|
|
658
|
+
success_count integer DEFAULT 0,
|
|
659
|
+
failure_count integer DEFAULT 0,
|
|
660
|
+
last_run_at timestamptz,
|
|
661
|
+
next_run_at timestamptz,
|
|
662
|
+
last_error text,
|
|
663
|
+
last_error_at timestamptz,
|
|
664
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
665
|
+
created_at timestamptz DEFAULT now(),
|
|
666
|
+
updated_at timestamptz DEFAULT now()
|
|
667
|
+
);
|
|
668
|
+
|
|
669
|
+
-- schedule_executions (depends on accounts, schedules)
|
|
670
|
+
CREATE TABLE IF NOT EXISTS public.schedule_executions (
|
|
671
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
672
|
+
schedule_id uuid NOT NULL REFERENCES public.schedules(id) ON DELETE CASCADE,
|
|
673
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
674
|
+
machine_principal_id uuid,
|
|
675
|
+
status text DEFAULT 'pending',
|
|
676
|
+
input_params jsonb DEFAULT '{}'::jsonb,
|
|
677
|
+
output_result jsonb DEFAULT '{}'::jsonb,
|
|
678
|
+
error_message text,
|
|
679
|
+
duration_ms integer,
|
|
680
|
+
created_at timestamptz DEFAULT now()
|
|
681
|
+
);
|
|
682
|
+
|
|
683
|
+
-- test_runs (RLS disabled — written by service-role test harness only)
|
|
684
|
+
CREATE TABLE IF NOT EXISTS public.test_runs (
|
|
685
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
686
|
+
suite text NOT NULL,
|
|
687
|
+
status text NOT NULL,
|
|
688
|
+
started_at timestamptz NOT NULL DEFAULT now(),
|
|
689
|
+
finished_at timestamptz,
|
|
690
|
+
duration_ms integer,
|
|
691
|
+
total integer,
|
|
692
|
+
passed integer,
|
|
693
|
+
failed integer,
|
|
694
|
+
skipped integer,
|
|
695
|
+
triggered_by text DEFAULT 'agent',
|
|
696
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE NO ACTION
|
|
697
|
+
);
|
|
698
|
+
|
|
699
|
+
-- test_results (RLS disabled — written by service-role test harness only)
|
|
700
|
+
CREATE TABLE IF NOT EXISTS public.test_results (
|
|
701
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
702
|
+
run_id uuid NOT NULL REFERENCES public.test_runs(id) ON DELETE CASCADE,
|
|
703
|
+
suite text NOT NULL,
|
|
704
|
+
file text,
|
|
705
|
+
describe text,
|
|
706
|
+
name text NOT NULL,
|
|
707
|
+
status text NOT NULL,
|
|
708
|
+
duration_ms integer,
|
|
709
|
+
error text,
|
|
710
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
711
|
+
);
|
|
712
|
+
|
|
713
|
+
-- item_progress (depends on accounts, types, items, apps, people)
|
|
714
|
+
CREATE TABLE IF NOT EXISTS public.item_progress (
|
|
715
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
716
|
+
type_id uuid NOT NULL REFERENCES public.types(id) ON DELETE RESTRICT,
|
|
717
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
718
|
+
app_id uuid REFERENCES public.apps(id) ON DELETE SET NULL,
|
|
719
|
+
person_id uuid NOT NULL REFERENCES public.people(id) ON DELETE CASCADE,
|
|
720
|
+
item_id uuid NOT NULL REFERENCES public.items(id) ON DELETE CASCADE,
|
|
721
|
+
title text,
|
|
722
|
+
description text,
|
|
723
|
+
status text NOT NULL DEFAULT 'not_started',
|
|
724
|
+
score integer,
|
|
725
|
+
data jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
726
|
+
is_active boolean NOT NULL DEFAULT true,
|
|
727
|
+
design_schema jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
728
|
+
validation_schema jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
729
|
+
created_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
730
|
+
updated_by uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
731
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
732
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
733
|
+
);
|
|
734
|
+
|
|
735
|
+
-- webhook_handlers (depends on accounts)
|
|
736
|
+
CREATE TABLE IF NOT EXISTS public.webhook_handlers (
|
|
737
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
738
|
+
name varchar NOT NULL UNIQUE,
|
|
739
|
+
function_name varchar NOT NULL,
|
|
740
|
+
description text,
|
|
741
|
+
events jsonb DEFAULT '[]'::jsonb,
|
|
742
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
743
|
+
is_active boolean DEFAULT true,
|
|
744
|
+
is_deleted boolean DEFAULT false,
|
|
745
|
+
deleted_at timestamptz,
|
|
746
|
+
created_at timestamptz DEFAULT now(),
|
|
747
|
+
updated_at timestamptz DEFAULT now()
|
|
748
|
+
);
|
|
749
|
+
|
|
750
|
+
-- app_installations (depends on accounts)
|
|
751
|
+
CREATE TABLE IF NOT EXISTS public.app_installations (
|
|
752
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
753
|
+
account_id uuid REFERENCES public.accounts(id) ON DELETE CASCADE,
|
|
754
|
+
app_slug varchar NOT NULL,
|
|
755
|
+
is_enabled boolean DEFAULT true,
|
|
756
|
+
installed_at timestamptz DEFAULT now(),
|
|
757
|
+
updated_at timestamptz DEFAULT now(),
|
|
758
|
+
UNIQUE (account_id, app_slug)
|
|
759
|
+
);
|
|
760
|
+
|
|
761
|
+
-- ---------------------------------------------------------------------------
|
|
762
|
+
-- Indexes
|
|
763
|
+
-- ---------------------------------------------------------------------------
|
|
764
|
+
|
|
765
|
+
CREATE INDEX IF NOT EXISTS idx_account_paths_ancestor ON public.account_paths (ancestor_id);
|
|
766
|
+
CREATE INDEX IF NOT EXISTS idx_account_paths_descendant ON public.account_paths (descendant_id);
|
|
767
|
+
|
|
768
|
+
CREATE INDEX IF NOT EXISTS idx_accounts_parent_id ON public.accounts (parent_id);
|
|
769
|
+
CREATE INDEX IF NOT EXISTS idx_accounts_type_id ON public.accounts (type_id);
|
|
770
|
+
CREATE INDEX IF NOT EXISTS idx_accounts_active ON public.accounts (is_active);
|
|
771
|
+
|
|
772
|
+
CREATE INDEX IF NOT EXISTS idx_actions_account ON public.actions (account_id);
|
|
773
|
+
CREATE INDEX IF NOT EXISTS idx_actions_slug ON public.actions (slug);
|
|
774
|
+
|
|
775
|
+
CREATE INDEX IF NOT EXISTS idx_ai_agents_account ON public.ai_agents (account_id);
|
|
776
|
+
CREATE INDEX IF NOT EXISTS idx_ai_agents_app ON public.ai_agents (app_id);
|
|
777
|
+
|
|
778
|
+
CREATE INDEX IF NOT EXISTS idx_akul_account ON public.api_key_usage_logs (account_id);
|
|
779
|
+
CREATE INDEX IF NOT EXISTS idx_akul_api_key ON public.api_key_usage_logs (api_key_id);
|
|
780
|
+
CREATE INDEX IF NOT EXISTS idx_akul_created ON public.api_key_usage_logs (created_at);
|
|
781
|
+
|
|
782
|
+
CREATE INDEX IF NOT EXISTS idx_api_keys_account ON public.api_keys (account_id);
|
|
783
|
+
CREATE INDEX IF NOT EXISTS idx_api_keys_integration ON public.api_keys (integration_id);
|
|
784
|
+
CREATE INDEX IF NOT EXISTS idx_api_keys_key_value ON public.api_keys (key_value);
|
|
785
|
+
|
|
786
|
+
CREATE INDEX IF NOT EXISTS idx_app_installations_account ON public.app_installations (account_id) WHERE (is_enabled = true);
|
|
787
|
+
CREATE INDEX IF NOT EXISTS idx_app_installations_slug ON public.app_installations (app_slug) WHERE (is_enabled = true);
|
|
788
|
+
|
|
789
|
+
CREATE INDEX IF NOT EXISTS idx_apps_owner ON public.apps (owner_account_id);
|
|
790
|
+
CREATE INDEX IF NOT EXISTS idx_apps_slug ON public.apps (slug);
|
|
791
|
+
|
|
792
|
+
CREATE INDEX IF NOT EXISTS idx_attachments_account ON public.attachments (account_id);
|
|
793
|
+
CREATE INDEX IF NOT EXISTS idx_attachments_type ON public.attachments (type_id);
|
|
794
|
+
|
|
795
|
+
CREATE INDEX IF NOT EXISTS idx_embeddings_account ON public.embeddings (account_id);
|
|
796
|
+
CREATE INDEX IF NOT EXISTS idx_embeddings_model_doc ON public.embeddings (model_id, document_id);
|
|
797
|
+
|
|
798
|
+
CREATE INDEX IF NOT EXISTS idx_integrations_account ON public.integrations (account_id);
|
|
799
|
+
CREATE INDEX IF NOT EXISTS idx_integrations_app ON public.integrations (app_id);
|
|
800
|
+
|
|
801
|
+
CREATE INDEX IF NOT EXISTS idx_item_progress_account ON public.item_progress (account_id);
|
|
802
|
+
CREATE INDEX IF NOT EXISTS idx_item_progress_active ON public.item_progress (account_id, is_active) WHERE (is_active = true);
|
|
803
|
+
CREATE INDEX IF NOT EXISTS idx_item_progress_data_gin ON public.item_progress USING gin (data);
|
|
804
|
+
CREATE INDEX IF NOT EXISTS idx_item_progress_item ON public.item_progress (item_id);
|
|
805
|
+
CREATE INDEX IF NOT EXISTS idx_item_progress_person ON public.item_progress (person_id);
|
|
806
|
+
CREATE INDEX IF NOT EXISTS idx_item_progress_status ON public.item_progress (status);
|
|
807
|
+
CREATE INDEX IF NOT EXISTS idx_item_progress_type ON public.item_progress (type_id);
|
|
808
|
+
|
|
809
|
+
CREATE INDEX IF NOT EXISTS idx_items_account ON public.items (account_id);
|
|
810
|
+
CREATE INDEX IF NOT EXISTS idx_items_active ON public.items (is_active);
|
|
811
|
+
CREATE INDEX IF NOT EXISTS idx_items_created_at ON public.items (created_at);
|
|
812
|
+
CREATE INDEX IF NOT EXISTS idx_items_type ON public.items (type_id);
|
|
813
|
+
|
|
814
|
+
CREATE INDEX IF NOT EXISTS idx_link_types_slug ON public.link_types (slug);
|
|
815
|
+
|
|
816
|
+
CREATE INDEX IF NOT EXISTS idx_links_account ON public.links (account_id);
|
|
817
|
+
CREATE INDEX IF NOT EXISTS idx_links_link_type ON public.links (link_type_id);
|
|
818
|
+
CREATE INDEX IF NOT EXISTS idx_links_source ON public.links (source_type, source_id);
|
|
819
|
+
CREATE INDEX IF NOT EXISTS idx_links_target ON public.links (target_type, target_id);
|
|
820
|
+
|
|
821
|
+
CREATE INDEX IF NOT EXISTS idx_logs_account ON public.logs (account_id);
|
|
822
|
+
CREATE INDEX IF NOT EXISTS idx_logs_created ON public.logs (created_at);
|
|
823
|
+
|
|
824
|
+
CREATE INDEX IF NOT EXISTS idx_messages_thread ON public.messages (thread_id);
|
|
825
|
+
|
|
826
|
+
CREATE INDEX IF NOT EXISTS idx_people_account ON public.people (account_id);
|
|
827
|
+
CREATE INDEX IF NOT EXISTS idx_people_role ON public.people (role_id);
|
|
828
|
+
|
|
829
|
+
CREATE INDEX IF NOT EXISTS idx_pe_account ON public.pipeline_executions (account_id);
|
|
830
|
+
CREATE INDEX IF NOT EXISTS idx_pe_pipeline ON public.pipeline_executions (pipeline_id);
|
|
831
|
+
CREATE INDEX IF NOT EXISTS idx_pe_status ON public.pipeline_executions (status);
|
|
832
|
+
|
|
833
|
+
CREATE INDEX IF NOT EXISTS idx_pipelines_account ON public.pipelines (account_id);
|
|
834
|
+
CREATE INDEX IF NOT EXISTS idx_pipelines_app ON public.pipelines (app_id);
|
|
835
|
+
|
|
836
|
+
CREATE INDEX IF NOT EXISTS idx_prompt_configs_account ON public.prompt_configs (account_id);
|
|
837
|
+
CREATE INDEX IF NOT EXISTS idx_prompt_configs_app ON public.prompt_configs (app_id);
|
|
838
|
+
CREATE INDEX IF NOT EXISTS idx_prompt_configs_slug ON public.prompt_configs (slug);
|
|
839
|
+
|
|
840
|
+
CREATE INDEX IF NOT EXISTS idx_roles_slug ON public.roles (slug);
|
|
841
|
+
|
|
842
|
+
CREATE INDEX IF NOT EXISTS idx_se_account ON public.schedule_executions (account_id);
|
|
843
|
+
CREATE INDEX IF NOT EXISTS idx_se_schedule ON public.schedule_executions (schedule_id);
|
|
844
|
+
|
|
845
|
+
CREATE INDEX IF NOT EXISTS idx_schedules_account ON public.schedules (account_id);
|
|
846
|
+
CREATE INDEX IF NOT EXISTS idx_schedules_action ON public.schedules (action_id);
|
|
847
|
+
CREATE INDEX IF NOT EXISTS idx_schedules_next_run ON public.schedules (next_run_at);
|
|
848
|
+
|
|
849
|
+
CREATE INDEX IF NOT EXISTS idx_test_results_run_id ON public.test_results (run_id);
|
|
850
|
+
CREATE INDEX IF NOT EXISTS idx_test_runs_started_at ON public.test_runs (started_at DESC);
|
|
851
|
+
CREATE INDEX IF NOT EXISTS idx_test_runs_suite ON public.test_runs (suite);
|
|
852
|
+
|
|
853
|
+
CREATE INDEX IF NOT EXISTS idx_threads_account ON public.threads (account_id);
|
|
854
|
+
CREATE INDEX IF NOT EXISTS idx_threads_active ON public.threads (is_active);
|
|
855
|
+
CREATE INDEX IF NOT EXISTS idx_threads_target ON public.threads (target_type, target_id);
|
|
856
|
+
CREATE INDEX IF NOT EXISTS idx_threads_type ON public.threads (type_id);
|
|
857
|
+
|
|
858
|
+
CREATE INDEX IF NOT EXISTS idx_timers_account ON public.timers (account_id);
|
|
859
|
+
CREATE INDEX IF NOT EXISTS idx_timers_app ON public.timers (app_id);
|
|
860
|
+
CREATE INDEX IF NOT EXISTS idx_timers_pipeline ON public.timers (pipeline_id);
|
|
861
|
+
|
|
862
|
+
CREATE INDEX IF NOT EXISTS idx_te_trigger ON public.trigger_executions (trigger_id);
|
|
863
|
+
|
|
864
|
+
CREATE INDEX IF NOT EXISTS idx_triggers_account ON public.triggers (account_id);
|
|
865
|
+
CREATE INDEX IF NOT EXISTS idx_triggers_app ON public.triggers (app_id);
|
|
866
|
+
CREATE INDEX IF NOT EXISTS idx_triggers_pipeline ON public.triggers (pipeline_id);
|
|
867
|
+
|
|
868
|
+
CREATE INDEX IF NOT EXISTS idx_types_kind ON public.types (kind);
|
|
869
|
+
CREATE INDEX IF NOT EXISTS idx_types_slug ON public.types (slug);
|
|
870
|
+
|
|
871
|
+
CREATE INDEX IF NOT EXISTS idx_watchers_person ON public.watchers (person_id);
|
|
872
|
+
CREATE INDEX IF NOT EXISTS idx_watchers_target ON public.watchers (target_type, target_id);
|
|
873
|
+
CREATE INDEX IF NOT EXISTS idx_watchers_type ON public.watchers (type_id);
|
|
874
|
+
|
|
875
|
+
CREATE INDEX IF NOT EXISTS idx_webhook_handlers_account ON public.webhook_handlers (account_id) WHERE (is_deleted = false);
|
|
876
|
+
CREATE INDEX IF NOT EXISTS idx_webhook_handlers_events ON public.webhook_handlers USING gin (events) WHERE (is_active = true);
|
|
877
|
+
CREATE INDEX IF NOT EXISTS idx_webhook_handlers_name ON public.webhook_handlers (name) WHERE ((is_active = true) AND (is_deleted = false));
|
|
878
|
+
|
|
879
|
+
-- ---------------------------------------------------------------------------
|
|
880
|
+
-- Triggers
|
|
881
|
+
-- ---------------------------------------------------------------------------
|
|
882
|
+
|
|
883
|
+
CREATE OR REPLACE TRIGGER account_paths_trigger
|
|
884
|
+
AFTER INSERT OR UPDATE OR DELETE ON public.accounts
|
|
885
|
+
FOR EACH ROW EXECUTE FUNCTION public.update_account_paths();
|
|
886
|
+
|
|
887
|
+
CREATE OR REPLACE TRIGGER app_installations_updated_at
|
|
888
|
+
BEFORE UPDATE ON public.app_installations
|
|
889
|
+
FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
890
|
+
|
|
891
|
+
CREATE OR REPLACE TRIGGER webhook_handlers_updated_at
|
|
892
|
+
BEFORE UPDATE ON public.webhook_handlers
|
|
893
|
+
FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
|
|
894
|
+
|
|
895
|
+
-- ---------------------------------------------------------------------------
|
|
896
|
+
-- Row Level Security
|
|
897
|
+
-- ---------------------------------------------------------------------------
|
|
898
|
+
|
|
899
|
+
-- Enable RLS on all tables (account_paths, test_runs, test_results are explicitly skipped)
|
|
900
|
+
ALTER TABLE public.accounts ENABLE ROW LEVEL SECURITY;
|
|
901
|
+
ALTER TABLE public.actions ENABLE ROW LEVEL SECURITY;
|
|
902
|
+
ALTER TABLE public.ai_agents ENABLE ROW LEVEL SECURITY;
|
|
903
|
+
ALTER TABLE public.api_key_usage_logs ENABLE ROW LEVEL SECURITY;
|
|
904
|
+
ALTER TABLE public.api_keys ENABLE ROW LEVEL SECURITY;
|
|
905
|
+
ALTER TABLE public.app_installations ENABLE ROW LEVEL SECURITY;
|
|
906
|
+
ALTER TABLE public.apps ENABLE ROW LEVEL SECURITY;
|
|
907
|
+
ALTER TABLE public.attachments ENABLE ROW LEVEL SECURITY;
|
|
908
|
+
ALTER TABLE public.embeddings ENABLE ROW LEVEL SECURITY;
|
|
909
|
+
ALTER TABLE public.integrations ENABLE ROW LEVEL SECURITY;
|
|
910
|
+
ALTER TABLE public.item_progress ENABLE ROW LEVEL SECURITY;
|
|
911
|
+
ALTER TABLE public.items ENABLE ROW LEVEL SECURITY;
|
|
912
|
+
ALTER TABLE public.link_types ENABLE ROW LEVEL SECURITY;
|
|
913
|
+
ALTER TABLE public.links ENABLE ROW LEVEL SECURITY;
|
|
914
|
+
ALTER TABLE public.logs ENABLE ROW LEVEL SECURITY;
|
|
915
|
+
ALTER TABLE public.messages ENABLE ROW LEVEL SECURITY;
|
|
916
|
+
ALTER TABLE public.people ENABLE ROW LEVEL SECURITY;
|
|
917
|
+
ALTER TABLE public.pipeline_executions ENABLE ROW LEVEL SECURITY;
|
|
918
|
+
ALTER TABLE public.pipelines ENABLE ROW LEVEL SECURITY;
|
|
919
|
+
ALTER TABLE public.prompt_configs ENABLE ROW LEVEL SECURITY;
|
|
920
|
+
ALTER TABLE public.roles ENABLE ROW LEVEL SECURITY;
|
|
921
|
+
ALTER TABLE public.schedule_executions ENABLE ROW LEVEL SECURITY;
|
|
922
|
+
ALTER TABLE public.schedules ENABLE ROW LEVEL SECURITY;
|
|
923
|
+
ALTER TABLE public.threads ENABLE ROW LEVEL SECURITY;
|
|
924
|
+
ALTER TABLE public.timers ENABLE ROW LEVEL SECURITY;
|
|
925
|
+
ALTER TABLE public.trigger_executions ENABLE ROW LEVEL SECURITY;
|
|
926
|
+
ALTER TABLE public.triggers ENABLE ROW LEVEL SECURITY;
|
|
927
|
+
ALTER TABLE public.types ENABLE ROW LEVEL SECURITY;
|
|
928
|
+
ALTER TABLE public.watchers ENABLE ROW LEVEL SECURITY;
|
|
929
|
+
ALTER TABLE public.webhook_handlers ENABLE ROW LEVEL SECURITY;
|
|
930
|
+
|
|
931
|
+
-- NOTE: account_paths, test_runs, test_results have RLS intentionally disabled.
|
|
932
|
+
-- account_paths is managed exclusively by trigger (update_account_paths).
|
|
933
|
+
-- test_runs/test_results are written by service_role from the test harness.
|
|
934
|
+
|
|
935
|
+
-- RLS Policies
|
|
936
|
+
|
|
937
|
+
CREATE POLICY accounts_access ON public.accounts FOR ALL TO public
|
|
938
|
+
USING ((id IN (SELECT get_accessible_accounts(current_actor_id()))) OR current_actor_id() IS NULL);
|
|
939
|
+
|
|
940
|
+
CREATE POLICY actions_access ON public.actions FOR ALL TO public
|
|
941
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
942
|
+
|
|
943
|
+
CREATE POLICY ai_agents_access ON public.ai_agents FOR ALL TO public
|
|
944
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
945
|
+
|
|
946
|
+
CREATE POLICY akul_access ON public.api_key_usage_logs FOR ALL TO public
|
|
947
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
948
|
+
|
|
949
|
+
CREATE POLICY api_keys_access ON public.api_keys FOR ALL TO public
|
|
950
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR (id = auth.uid()) OR auth.uid() IS NULL);
|
|
951
|
+
|
|
952
|
+
CREATE POLICY app_installations_select ON public.app_installations FOR SELECT TO authenticated USING (true);
|
|
953
|
+
CREATE POLICY app_installations_admin ON public.app_installations FOR ALL TO authenticated
|
|
954
|
+
USING ((SELECT raw_user_meta_data->>'role' FROM auth.users WHERE id = auth.uid()) = 'system_admin')
|
|
955
|
+
WITH CHECK ((SELECT raw_user_meta_data->>'role' FROM auth.users WHERE id = auth.uid()) = 'system_admin');
|
|
956
|
+
CREATE POLICY app_installations_service ON public.app_installations FOR ALL TO service_role USING (true) WITH CHECK (true);
|
|
957
|
+
|
|
958
|
+
CREATE POLICY apps_access ON public.apps FOR ALL TO public
|
|
959
|
+
USING ((is_system = true) OR (owner_account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
960
|
+
|
|
961
|
+
CREATE POLICY attachments_access ON public.attachments FOR ALL TO public
|
|
962
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR ((design_schema->>'scope' = 'platform') AND auth.uid() IS NOT NULL) OR auth.uid() IS NULL);
|
|
963
|
+
|
|
964
|
+
CREATE POLICY embeddings_access ON public.embeddings FOR ALL TO public
|
|
965
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
966
|
+
|
|
967
|
+
CREATE POLICY integrations_access ON public.integrations FOR ALL TO public
|
|
968
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
969
|
+
|
|
970
|
+
CREATE POLICY item_progress_access ON public.item_progress FOR ALL TO public
|
|
971
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
972
|
+
|
|
973
|
+
CREATE POLICY items_access ON public.items FOR ALL TO public
|
|
974
|
+
USING ((account_id IN (SELECT get_accessible_accounts(current_actor_id()))) OR ((design_schema->>'scope' = 'platform') AND current_actor_id() IS NOT NULL) OR current_actor_id() IS NULL);
|
|
975
|
+
|
|
976
|
+
CREATE POLICY link_types_access ON public.link_types FOR ALL TO public
|
|
977
|
+
USING ((app_id IS NULL) OR (EXISTS (SELECT 1 FROM apps a WHERE a.id = link_types.app_id AND a.owner_account_id IN (SELECT get_accessible_accounts(auth.uid())))) OR auth.uid() IS NULL);
|
|
978
|
+
|
|
979
|
+
CREATE POLICY links_access ON public.links FOR ALL TO public
|
|
980
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR ((design_schema->>'scope' = 'platform') AND auth.uid() IS NOT NULL) OR auth.uid() IS NULL);
|
|
981
|
+
|
|
982
|
+
CREATE POLICY logs_access ON public.logs FOR ALL TO public
|
|
983
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
984
|
+
|
|
985
|
+
CREATE POLICY messages_access ON public.messages FOR ALL TO public
|
|
986
|
+
USING ((EXISTS (SELECT 1 FROM threads t WHERE t.id = messages.thread_id AND (t.account_id IN (SELECT get_accessible_accounts(current_actor_id())) OR (t.design_schema->>'scope' = 'platform' AND current_actor_id() IS NOT NULL)))) OR (design_schema->>'scope' = 'platform' AND current_actor_id() IS NOT NULL) OR current_actor_id() IS NULL);
|
|
987
|
+
|
|
988
|
+
CREATE POLICY people_access ON public.people FOR ALL TO public
|
|
989
|
+
USING ((id = current_actor_id()) OR (account_id IN (SELECT get_accessible_accounts(current_actor_id()))) OR current_actor_id() IS NULL);
|
|
990
|
+
|
|
991
|
+
CREATE POLICY pe_access ON public.pipeline_executions FOR ALL TO public
|
|
992
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
993
|
+
|
|
994
|
+
CREATE POLICY pipelines_access ON public.pipelines FOR ALL TO public
|
|
995
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
996
|
+
|
|
997
|
+
CREATE POLICY prompt_configs_access ON public.prompt_configs FOR ALL TO public
|
|
998
|
+
USING ((app_id IS NULL) OR (EXISTS (SELECT 1 FROM apps a WHERE a.id = prompt_configs.app_id AND a.owner_account_id IN (SELECT get_accessible_accounts(auth.uid())))) OR auth.uid() IS NULL);
|
|
999
|
+
|
|
1000
|
+
CREATE POLICY roles_read ON public.roles FOR SELECT TO public USING (true);
|
|
1001
|
+
CREATE POLICY roles_modify ON public.roles FOR ALL TO public
|
|
1002
|
+
USING (((is_system = true) AND person_is_system_admin(current_actor_id())) OR (is_system = false) OR current_actor_id() IS NULL);
|
|
1003
|
+
|
|
1004
|
+
CREATE POLICY se_access ON public.schedule_executions FOR ALL TO public
|
|
1005
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
1006
|
+
|
|
1007
|
+
CREATE POLICY schedules_access ON public.schedules FOR ALL TO public
|
|
1008
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
1009
|
+
|
|
1010
|
+
CREATE POLICY threads_access ON public.threads FOR ALL TO public
|
|
1011
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR (design_schema->>'scope' = 'platform' AND auth.uid() IS NOT NULL) OR auth.uid() IS NULL);
|
|
1012
|
+
|
|
1013
|
+
CREATE POLICY timers_access ON public.timers FOR ALL TO public
|
|
1014
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
1015
|
+
|
|
1016
|
+
CREATE POLICY te_access ON public.trigger_executions FOR ALL TO public
|
|
1017
|
+
USING ((EXISTS (SELECT 1 FROM triggers t WHERE t.id = trigger_executions.trigger_id AND t.account_id IN (SELECT get_accessible_accounts(auth.uid())))) OR auth.uid() IS NULL);
|
|
1018
|
+
|
|
1019
|
+
CREATE POLICY triggers_access ON public.triggers FOR ALL TO public
|
|
1020
|
+
USING ((account_id IN (SELECT get_accessible_accounts(auth.uid()))) OR auth.uid() IS NULL);
|
|
1021
|
+
|
|
1022
|
+
CREATE POLICY types_access ON public.types FOR ALL TO public
|
|
1023
|
+
USING (current_actor_id() IS NOT NULL OR true);
|
|
1024
|
+
|
|
1025
|
+
CREATE POLICY watchers_access ON public.watchers FOR ALL TO public
|
|
1026
|
+
USING (auth.uid() IS NOT NULL OR true);
|
|
1027
|
+
|
|
1028
|
+
CREATE POLICY webhook_handlers_service_role ON public.webhook_handlers FOR ALL TO service_role USING (true) WITH CHECK (true);
|
|
1029
|
+
CREATE POLICY webhook_handlers_system_admin ON public.webhook_handlers FOR ALL TO authenticated
|
|
1030
|
+
USING ((SELECT raw_user_meta_data->>'role' FROM auth.users WHERE id = auth.uid()) = 'system_admin')
|
|
1031
|
+
WITH CHECK ((SELECT raw_user_meta_data->>'role' FROM auth.users WHERE id = auth.uid()) = 'system_admin');
|
|
1032
|
+
|
|
1033
|
+
-- ---------------------------------------------------------------------------
|
|
1034
|
+
-- Additional Functions (depend on tables existing)
|
|
1035
|
+
-- ---------------------------------------------------------------------------
|
|
1036
|
+
|
|
1037
|
+
CREATE OR REPLACE FUNCTION public.get_account_ancestors(account_id uuid)
|
|
1038
|
+
RETURNS TABLE(id uuid, slug text, display_name text, depth integer) LANGUAGE plpgsql AS $$
|
|
1039
|
+
BEGIN
|
|
1040
|
+
RETURN QUERY
|
|
1041
|
+
SELECT a.id, a.slug, a.display_name, ap.depth
|
|
1042
|
+
FROM public.accounts a
|
|
1043
|
+
JOIN public.account_paths ap ON a.id = ap.ancestor_id
|
|
1044
|
+
WHERE ap.descendant_id = account_id
|
|
1045
|
+
ORDER BY ap.depth;
|
|
1046
|
+
END;
|
|
1047
|
+
$$;
|
|
1048
|
+
|
|
1049
|
+
CREATE OR REPLACE FUNCTION public.get_account_descendants(account_id uuid, max_depth integer DEFAULT NULL)
|
|
1050
|
+
RETURNS TABLE(id uuid, slug text, display_name text, depth integer) LANGUAGE plpgsql AS $$
|
|
1051
|
+
BEGIN
|
|
1052
|
+
RETURN QUERY
|
|
1053
|
+
WITH RECURSIVE descendants AS (
|
|
1054
|
+
SELECT a.id, a.slug, a.display_name, 0 as depth
|
|
1055
|
+
FROM public.accounts a WHERE a.id = account_id
|
|
1056
|
+
UNION ALL
|
|
1057
|
+
SELECT a.id, a.slug, a.display_name, ap.depth + 1
|
|
1058
|
+
FROM public.accounts a
|
|
1059
|
+
JOIN public.account_paths ap ON a.id = ap.descendant_id
|
|
1060
|
+
WHERE ap.ancestor_id = account_id
|
|
1061
|
+
AND (max_depth IS NULL OR ap.depth < max_depth)
|
|
1062
|
+
)
|
|
1063
|
+
SELECT d.id, d.slug, d.display_name, d.depth FROM descendants d WHERE d.id != account_id ORDER BY d.depth, d.display_name;
|
|
1064
|
+
END;
|
|
1065
|
+
$$;
|
|
1066
|
+
|
|
1067
|
+
CREATE OR REPLACE FUNCTION public.get_account_hierarchy(parent_account_id uuid)
|
|
1068
|
+
RETURNS TABLE(id uuid, slug text, display_name text, level integer) LANGUAGE plpgsql AS $$
|
|
1069
|
+
BEGIN
|
|
1070
|
+
RETURN QUERY
|
|
1071
|
+
WITH RECURSIVE account_tree AS (
|
|
1072
|
+
SELECT a.id, a.slug, a.display_name, 1 as level FROM public.accounts a
|
|
1073
|
+
WHERE a.parent_id = parent_account_id AND a.is_active = true
|
|
1074
|
+
UNION ALL
|
|
1075
|
+
SELECT a.id, a.slug, a.display_name, at.level + 1
|
|
1076
|
+
FROM public.accounts a INNER JOIN account_tree at ON a.parent_id = at.id
|
|
1077
|
+
WHERE a.is_active = true
|
|
1078
|
+
)
|
|
1079
|
+
SELECT id, slug, display_name, level FROM account_tree ORDER BY level, display_name;
|
|
1080
|
+
END;
|
|
1081
|
+
$$;
|
|
1082
|
+
|
|
1083
|
+
CREATE OR REPLACE FUNCTION public.get_account_apps(account_id uuid, include_system boolean DEFAULT true, include_inactive boolean DEFAULT false)
|
|
1084
|
+
RETURNS TABLE(id uuid, slug text, name text, description text, icon text, color text, version text, app_type text, source text, owner_account_id uuid, is_active boolean, is_system boolean, min_role text, config jsonb, nav_items jsonb, route_prefix text, renderer text, created_at timestamptz) LANGUAGE plpgsql AS $$
|
|
1085
|
+
BEGIN
|
|
1086
|
+
RETURN QUERY
|
|
1087
|
+
SELECT a.id, a.slug, a.name, a.description, a.icon, a.color, a.version, a.app_type, a.source,
|
|
1088
|
+
a.owner_account_id, a.is_active, a.is_system, a.min_role, a.config, a.nav_items, a.route_prefix, a.renderer, a.created_at
|
|
1089
|
+
FROM public.apps a
|
|
1090
|
+
WHERE (include_system OR a.is_system = false)
|
|
1091
|
+
AND (include_inactive OR a.is_active = true)
|
|
1092
|
+
AND (a.is_system OR a.owner_account_id = get_account_apps.account_id)
|
|
1093
|
+
ORDER BY a.is_system DESC, a.app_type, a.name;
|
|
1094
|
+
END;
|
|
1095
|
+
$$;
|
|
1096
|
+
|
|
1097
|
+
CREATE OR REPLACE FUNCTION public.get_app_manifest(app_slug text)
|
|
1098
|
+
RETURNS jsonb LANGUAGE plpgsql AS $$
|
|
1099
|
+
DECLARE manifest_path TEXT;
|
|
1100
|
+
BEGIN
|
|
1101
|
+
SELECT a.manifest_path INTO manifest_path FROM public.apps a WHERE a.slug = app_slug;
|
|
1102
|
+
IF manifest_path IS NULL THEN RETURN NULL; END IF;
|
|
1103
|
+
RETURN jsonb_build_object('source', 'manifest', 'path', manifest_path, 'note', 'Manifest content loaded by application layer');
|
|
1104
|
+
END;
|
|
1105
|
+
$$;
|
|
1106
|
+
|
|
1107
|
+
CREATE OR REPLACE FUNCTION public.get_app_schema(app_slug text)
|
|
1108
|
+
RETURNS jsonb LANGUAGE plpgsql AS $$
|
|
1109
|
+
DECLARE app_schema jsonb;
|
|
1110
|
+
BEGIN
|
|
1111
|
+
SELECT jsonb_build_object('id', id, 'slug', slug, 'name', name, 'description', description, 'icon', icon, 'color', color, 'version', version, 'app_type', app_type, 'source', source, 'config', config, 'nav_items', nav_items, 'min_role', min_role, 'integration_deps', integration_deps, 'metadata', metadata)
|
|
1112
|
+
INTO app_schema FROM public.apps WHERE slug = get_app_schema.app_slug AND is_active = true;
|
|
1113
|
+
RETURN COALESCE(app_schema, '{}'::jsonb);
|
|
1114
|
+
END;
|
|
1115
|
+
$$;
|
|
1116
|
+
|
|
1117
|
+
CREATE OR REPLACE FUNCTION public.is_app_available(app_slug text, account_id uuid)
|
|
1118
|
+
RETURNS boolean LANGUAGE plpgsql AS $$
|
|
1119
|
+
BEGIN
|
|
1120
|
+
RETURN EXISTS (SELECT 1 FROM public.apps WHERE slug = is_app_available.app_slug AND is_active = true AND (is_system = true OR owner_account_id = is_app_available.account_id));
|
|
1121
|
+
END;
|
|
1122
|
+
$$;
|
|
1123
|
+
|
|
1124
|
+
CREATE OR REPLACE FUNCTION public.get_type_schema(kind text, slug text, app_id uuid DEFAULT NULL)
|
|
1125
|
+
RETURNS jsonb LANGUAGE plpgsql AS $$
|
|
1126
|
+
DECLARE type_schema jsonb;
|
|
1127
|
+
BEGIN
|
|
1128
|
+
SELECT design_schema INTO type_schema FROM public.types
|
|
1129
|
+
WHERE kind = get_type_schema.kind AND slug = get_type_schema.slug
|
|
1130
|
+
AND (app_id = get_type_schema.app_id OR (app_id IS NULL AND get_type_schema.app_id IS NULL))
|
|
1131
|
+
AND is_active = true
|
|
1132
|
+
ORDER BY app_id DESC NULLS LAST LIMIT 1;
|
|
1133
|
+
RETURN COALESCE(type_schema, '{}');
|
|
1134
|
+
END;
|
|
1135
|
+
$$;
|
|
1136
|
+
|
|
1137
|
+
CREATE OR REPLACE FUNCTION public.increment_trigger_count(p_trigger_id uuid)
|
|
1138
|
+
RETURNS integer LANGUAGE plpgsql AS $$
|
|
1139
|
+
DECLARE v_count integer;
|
|
1140
|
+
BEGIN
|
|
1141
|
+
UPDATE public.triggers SET trigger_count = COALESCE(trigger_count, 0) + 1 WHERE id = p_trigger_id RETURNING trigger_count INTO v_count;
|
|
1142
|
+
RETURN v_count;
|
|
1143
|
+
END;
|
|
1144
|
+
$$;
|
|
1145
|
+
|
|
1146
|
+
CREATE OR REPLACE FUNCTION public.update_app_version(app_id uuid, new_version text)
|
|
1147
|
+
RETURNS void LANGUAGE plpgsql AS $$
|
|
1148
|
+
BEGIN
|
|
1149
|
+
UPDATE public.apps SET version = new_version, updated_at = now() WHERE id = update_app_version.app_id;
|
|
1150
|
+
END;
|
|
1151
|
+
$$;
|
|
1152
|
+
|
|
1153
|
+
CREATE OR REPLACE FUNCTION public.generate_api_key(key_type text, key_prefix text DEFAULT 'sp_')
|
|
1154
|
+
RETURNS text LANGUAGE plpgsql AS $$
|
|
1155
|
+
DECLARE key_value text; key_suffix text;
|
|
1156
|
+
BEGIN
|
|
1157
|
+
key_suffix := encode(gen_random_bytes(24), 'base64');
|
|
1158
|
+
key_suffix := replace(replace(replace(key_suffix, '/', ''), '+', ''), '=', '');
|
|
1159
|
+
key_suffix := substring(key_suffix, 1, 32);
|
|
1160
|
+
key_value := key_prefix || CASE key_type WHEN 'public' THEN 'pk_' WHEN 'secret' THEN 'sc_' WHEN 'webhook' THEN 'wh_' ELSE 'sk_' END || key_suffix;
|
|
1161
|
+
RETURN key_value;
|
|
1162
|
+
END;
|
|
1163
|
+
$$;
|
|
1164
|
+
|
|
1165
|
+
CREATE OR REPLACE FUNCTION public.get_due_schedules(p_now timestamptz DEFAULT now())
|
|
1166
|
+
RETURNS TABLE(id uuid, account_id uuid, action_id uuid, machine_principal_id uuid, config jsonb, delegated_scopes text[]) LANGUAGE plpgsql AS $$
|
|
1167
|
+
BEGIN
|
|
1168
|
+
RETURN QUERY SELECT s.id, s.account_id, s.action_id, s.machine_principal_id, s.config, s.delegated_scopes
|
|
1169
|
+
FROM public.schedules s WHERE s.is_active = true AND s.is_paused = false AND (s.next_run_at IS NULL OR s.next_run_at <= p_now);
|
|
1170
|
+
END;
|
|
1171
|
+
$$;
|
|
1172
|
+
|
|
1173
|
+
CREATE OR REPLACE FUNCTION public.get_due_timers(p_now timestamptz DEFAULT now())
|
|
1174
|
+
RETURNS TABLE(id uuid, account_id uuid, app_id uuid, name text, pipeline_id uuid, created_by uuid, execution_count integer, next_execution timestamptz) LANGUAGE plpgsql AS $$
|
|
1175
|
+
BEGIN
|
|
1176
|
+
RETURN QUERY SELECT t.id, t.account_id, t.app_id, t.name, t.pipeline_id, t.created_by, t.execution_count, t.next_execution
|
|
1177
|
+
FROM public.timers t WHERE t.is_active = true AND t.next_execution IS NOT NULL AND t.next_execution <= p_now;
|
|
1178
|
+
END;
|
|
1179
|
+
$$;
|
|
1180
|
+
|
|
1181
|
+
CREATE OR REPLACE FUNCTION public.validate_machine_principal(p_key_value text, p_required_scope text DEFAULT NULL)
|
|
1182
|
+
RETURNS TABLE(is_valid boolean, machine_id uuid, account_id uuid, scopes text[], machine_type text, is_internal boolean, created_by uuid, error_message text) LANGUAGE plpgsql AS $$
|
|
1183
|
+
DECLARE
|
|
1184
|
+
key_record RECORD;
|
|
1185
|
+
BEGIN
|
|
1186
|
+
SELECT * INTO key_record
|
|
1187
|
+
FROM public.api_keys
|
|
1188
|
+
WHERE key_value = p_key_value AND is_active = true
|
|
1189
|
+
AND (expires_at IS NULL OR expires_at > now());
|
|
1190
|
+
|
|
1191
|
+
IF NOT FOUND THEN
|
|
1192
|
+
RETURN QUERY SELECT false, NULL::uuid, NULL::uuid, NULL::text[],
|
|
1193
|
+
NULL::text, NULL::boolean, NULL::uuid, 'Invalid or inactive machine principal'::text;
|
|
1194
|
+
RETURN;
|
|
1195
|
+
END IF;
|
|
1196
|
+
|
|
1197
|
+
IF p_required_scope IS NOT NULL AND
|
|
1198
|
+
NOT (p_required_scope = ANY(key_record.scopes) OR '*:*' = ANY(key_record.scopes)) THEN
|
|
1199
|
+
RETURN QUERY SELECT false, NULL::uuid, NULL::uuid, NULL::text[],
|
|
1200
|
+
NULL::text, NULL::boolean, NULL::uuid, ('Insufficient scope: ' || p_required_scope)::text;
|
|
1201
|
+
RETURN;
|
|
1202
|
+
END IF;
|
|
1203
|
+
|
|
1204
|
+
UPDATE public.api_keys SET last_used_at = now(), usage_count = COALESCE(usage_count, 0) + 1 WHERE id = key_record.id;
|
|
1205
|
+
|
|
1206
|
+
RETURN QUERY SELECT true, key_record.id, key_record.account_id, key_record.scopes,
|
|
1207
|
+
key_record.machine_type, key_record.is_internal, key_record.created_by, NULL::text;
|
|
1208
|
+
END;
|
|
1209
|
+
$$;
|
|
1210
|
+
|
|
1211
|
+
CREATE OR REPLACE FUNCTION public.validate_schedule_creator(p_schedule_id uuid)
|
|
1212
|
+
RETURNS TABLE(is_valid boolean, error_message text) LANGUAGE plpgsql AS $$
|
|
1213
|
+
DECLARE sched RECORD; creator RECORD;
|
|
1214
|
+
BEGIN
|
|
1215
|
+
SELECT * INTO sched FROM public.schedules WHERE id = p_schedule_id;
|
|
1216
|
+
IF NOT FOUND THEN RETURN QUERY SELECT false, 'Schedule not found'::text; RETURN; END IF;
|
|
1217
|
+
|
|
1218
|
+
SELECT is_active INTO creator FROM public.people WHERE id = sched.created_by;
|
|
1219
|
+
IF creator IS NULL OR NOT creator.is_active THEN
|
|
1220
|
+
UPDATE public.schedules SET is_paused = true, pause_reason = 'Creator deactivated' WHERE id = p_schedule_id;
|
|
1221
|
+
RETURN QUERY SELECT false, 'Schedule creator deactivated; schedule paused'::text; RETURN;
|
|
1222
|
+
END IF;
|
|
1223
|
+
|
|
1224
|
+
RETURN QUERY SELECT true, NULL::text;
|
|
1225
|
+
END;
|
|
1226
|
+
$$;
|
|
1227
|
+
|
|
1228
|
+
CREATE OR REPLACE FUNCTION public.cleanup_old_logs(p_retention_days integer DEFAULT 30)
|
|
1229
|
+
RETURNS TABLE(deleted_count bigint) LANGUAGE plpgsql AS $$
|
|
1230
|
+
BEGIN
|
|
1231
|
+
RETURN QUERY WITH deleted AS (DELETE FROM logs WHERE created_at < NOW() - INTERVAL '1 day' * p_retention_days RETURNING id)
|
|
1232
|
+
SELECT COUNT(*)::bigint FROM deleted;
|
|
1233
|
+
END;
|
|
1234
|
+
$$;
|
|
1235
|
+
|
|
1236
|
+
CREATE OR REPLACE FUNCTION public.match_embeddings(query_embedding vector, match_count integer DEFAULT 10, similarity_threshold float DEFAULT 0.7, filter_account_ids uuid[] DEFAULT NULL, filter_vector_type text DEFAULT 'document')
|
|
1237
|
+
RETURNS TABLE(id uuid, document_id text, content text, metadata jsonb, account_id uuid, similarity float) LANGUAGE plpgsql AS $$
|
|
1238
|
+
BEGIN
|
|
1239
|
+
RETURN QUERY SELECT e.id, e.document_id, e.content, e.metadata, e.account_id, 1 - (e.embedding <=> query_embedding) AS similarity
|
|
1240
|
+
FROM public.embeddings e
|
|
1241
|
+
WHERE (filter_account_ids IS NULL OR e.account_id = ANY(filter_account_ids))
|
|
1242
|
+
AND e.metadata->>'vector_type' = filter_vector_type
|
|
1243
|
+
AND 1 - (e.embedding <=> query_embedding) >= similarity_threshold
|
|
1244
|
+
ORDER BY e.embedding <=> query_embedding LIMIT match_count;
|
|
1245
|
+
END;
|
|
1246
|
+
$$;
|
|
1247
|
+
|
|
1248
|
+
CREATE OR REPLACE FUNCTION public.search_similar_embeddings(p_account_id uuid, p_model_id text, p_query_embedding vector, p_threshold float DEFAULT 0.7, p_limit integer DEFAULT 10)
|
|
1249
|
+
RETURNS TABLE(id uuid, content text, similarity float, metadata jsonb, document_id text) LANGUAGE plpgsql AS $$
|
|
1250
|
+
BEGIN
|
|
1251
|
+
RETURN QUERY SELECT e.id, e.content, (1 - (e.embedding <=> p_query_embedding))::float as similarity, e.metadata, e.document_id
|
|
1252
|
+
FROM public.embeddings e
|
|
1253
|
+
WHERE e.account_id = p_account_id AND e.model_id = p_model_id AND 1 - (e.embedding <=> p_query_embedding) > p_threshold
|
|
1254
|
+
ORDER BY e.embedding <=> p_query_embedding LIMIT p_limit;
|
|
1255
|
+
END;
|
|
1256
|
+
$$;
|