spine-framework 0.3.124 → 0.3.126
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/cli/commands/agents.ts +35 -37
- package/.framework/cli/commands/auth.ts +35 -34
- package/.framework/cli/commands/create-app.ts +104 -40
- package/.framework/cli/commands/dev.ts +104 -69
- package/.framework/cli/commands/doctor.ts +179 -69
- package/.framework/cli/commands/generate.ts +83 -143
- package/.framework/cli/commands/init.ts +72 -34
- package/.framework/cli/commands/install-app.ts +260 -125
- package/.framework/cli/commands/items.ts +33 -44
- package/.framework/cli/commands/migrate.ts +122 -40
- package/.framework/cli/commands/migrations.ts +33 -40
- package/.framework/cli/commands/pipelines.ts +31 -39
- package/.framework/cli/commands/status.ts +47 -23
- package/.framework/cli/commands/system.ts +47 -37
- package/.framework/cli/commands/test.ts +112 -68
- package/.framework/cli/commands/validate-app.ts +215 -121
- package/.framework/cli/context.ts +112 -130
- package/.framework/cli/env-loader.ts +47 -18
- package/.framework/cli/index.ts +81 -42
- package/.framework/docs/runtime-types.md +1024 -0
- package/.framework/functions/_shared/agent-runner.ts +1296 -961
- package/.framework/functions/_shared/app-manifest.ts +82 -68
- package/.framework/functions/_shared/audit.ts +135 -83
- package/.framework/functions/_shared/{cil-state.ts → cil.ts} +158 -56
- package/.framework/functions/_shared/db.ts +80 -126
- package/.framework/functions/_shared/hash-api-key.ts +63 -0
- package/.framework/functions/_shared/index.ts +224 -335
- package/.framework/functions/_shared/kb.ts +319 -0
- package/.framework/functions/_shared/llm.ts +92 -0
- package/.framework/functions/_shared/logging.ts +288 -0
- package/.framework/functions/_shared/middleware.ts +329 -365
- package/.framework/functions/_shared/outcomes.ts +36 -0
- package/.framework/functions/_shared/permissions.ts +359 -643
- package/.framework/functions/_shared/pipeline-runner.ts +243 -316
- package/.framework/functions/_shared/principal.ts +376 -468
- package/.framework/functions/_shared/resolve-credentials.ts +102 -0
- package/.framework/functions/_shared/resolve-ids.ts +188 -16
- package/.framework/functions/_shared/retry-deliveries.ts +104 -0
- package/.framework/functions/_shared/schema-utils.ts +611 -373
- package/.framework/functions/_shared/testing.ts +207 -137
- package/.framework/functions/_shared/tracing.ts +276 -0
- package/.framework/functions/_shared/trigger-engine.ts +159 -211
- package/.framework/functions/_shared/webhook-registration.ts +95 -81
- package/.framework/functions/_shared/webhook-registry.ts +153 -75
- package/.framework/functions/account-nodes.ts +31 -53
- package/.framework/functions/adapters/generic-webhook-inbound.ts +56 -0
- package/.framework/functions/adapters/generic-webhook-outbound.ts +43 -0
- package/.framework/functions/adapters/openai-outbound.ts +40 -0
- package/.framework/functions/admin-data.ts +685 -537
- package/.framework/functions/admin-funnel.ts +31 -20
- package/.framework/functions/admin-install-funnel.ts +47 -28
- package/.framework/functions/admin-signals.ts +47 -29
- package/.framework/functions/ai-agents.ts +122 -147
- package/.framework/functions/ai-interactions.ts +180 -90
- package/.framework/functions/api-keys.ts +250 -192
- package/.framework/functions/apps.ts +203 -197
- package/.framework/functions/auth.ts +98 -91
- package/.framework/functions/cil-agent-ingest.ts +773 -0
- package/.framework/functions/cil-agent.ts +592 -0
- package/.framework/functions/cil-callmap.ts +1227 -0
- package/.framework/functions/cil-config.ts +583 -0
- package/.framework/functions/cil-context.ts +445 -0
- package/.framework/functions/cil-doc.ts +1752 -0
- package/.framework/functions/cil-embeddings.ts +1202 -0
- package/.framework/functions/cil-graph.ts +585 -0
- package/.framework/functions/cil-ingest.ts +2416 -0
- package/.framework/functions/cil-pipeline.ts +318 -0
- package/.framework/functions/cil-project.ts +499 -0
- package/.framework/functions/cil-validate.ts +469 -0
- package/.framework/functions/debug-auth.ts +73 -53
- package/.framework/functions/deliveries.ts +117 -0
- package/.framework/functions/embeddings.ts +528 -516
- package/.framework/functions/eval-harness.ts +158 -106
- package/.framework/functions/integration-outbound.ts +311 -0
- package/.framework/functions/integration-routes.ts +240 -466
- package/.framework/functions/integrations.ts +132 -140
- package/.framework/functions/invites.ts +401 -201
- package/.framework/functions/item-progress.ts +113 -53
- package/.framework/functions/kb.ts +28 -0
- package/.framework/functions/logs.ts +239 -222
- package/.framework/functions/observability.ts +308 -259
- package/.framework/functions/pipeline-executions.ts +179 -235
- package/.framework/functions/pipelines.ts +163 -205
- package/.framework/functions/prompt-configs.ts +109 -156
- package/.framework/functions/roles.ts +97 -147
- package/.framework/functions/system-cron.ts +132 -218
- package/.framework/functions/system.ts +112 -52
- package/.framework/functions/tests.ts +32 -28
- package/.framework/functions/timers.ts +162 -210
- package/.framework/functions/triggers.ts +282 -346
- package/.framework/functions/types.ts +283 -400
- package/.framework/migrations/001_core_schema.sql +630 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +532 -0
- package/.framework/migrations/{003_system_data.sql → 003_core_system_data.sql} +26 -153
- package/.framework/migrations/004_core_rpc_and_broker.sql +421 -0
- package/.framework/migrations/005_core_observability.sql +598 -0
- package/.framework/migrations/006_security_hardening_rls.sql +97 -0
- package/.framework/migrations/007_kb_article_list.sql +237 -0
- package/.framework/migrations/008_items_target.sql +8 -0
- package/.framework/migrations/009_roles_slug_unique.sql +11 -0
- package/.framework/public/spine.config.json +91 -0
- package/.framework/scripts/app-install-cli.ts +112 -98
- package/.framework/src/App.tsx +67 -20
- package/.framework/src/apps/admin/index.tsx +97 -27
- package/.framework/src/components/AppWrapper.tsx +50 -11
- package/.framework/src/components/CustomAppLoader.tsx +131 -22
- package/.framework/src/components/admin/AdminListPage.tsx +75 -8
- package/.framework/src/components/admin/AdminSidebar.tsx +148 -36
- package/.framework/src/components/admin/AdminStatsCard.tsx +48 -29
- package/.framework/src/components/admin/PageInstructions.tsx +49 -0
- package/.framework/src/components/admin/SortableTableHeader.tsx +49 -2
- package/.framework/src/components/app-shell/GenericAppShell.tsx +69 -11
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +55 -10
- package/.framework/src/components/app-shell/GenericListPage.tsx +76 -9
- package/.framework/src/components/app-sidebar.tsx +50 -3
- package/.framework/src/components/auth/ProtectedRoute.tsx +53 -45
- package/.framework/src/components/kb/KBArticleEditor.tsx +409 -0
- package/.framework/src/components/kb/KBArticleList.tsx +557 -0
- package/.framework/src/components/layout/AppShell.tsx +54 -16
- package/.framework/src/components/layout/Header.tsx +50 -38
- package/.framework/src/components/layout/Layout.tsx +48 -32
- package/.framework/src/components/layout/Sidebar.tsx +167 -16
- package/.framework/src/components/runtime/DataDetailHeader.tsx +33 -1
- package/.framework/src/components/runtime/DataDetailPage.tsx +289 -4
- package/.framework/src/components/runtime/DataFilters.tsx +78 -1
- package/.framework/src/components/runtime/DataHeader.tsx +32 -29
- package/.framework/src/components/runtime/DataListPage.tsx +161 -2
- package/.framework/src/components/runtime/DataStats.tsx +48 -1
- package/.framework/src/components/runtime/DataTable.tsx +153 -1
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +77 -46
- package/.framework/src/components/runtime/index.ts +16 -9
- package/.framework/src/components/search-form.tsx +33 -1
- package/.framework/src/components/shared/AgentView.tsx +48 -51
- package/.framework/src/components/shared/FieldRenderer.tsx +84 -67
- package/.framework/src/components/shared/InviteManager.tsx +113 -52
- package/.framework/src/components/shared/MemberList.tsx +182 -0
- package/.framework/src/components/shared/SchemaFields.tsx +96 -78
- package/.framework/src/components/ui/DataTable.tsx +86 -56
- package/.framework/src/components/ui/Form.tsx +188 -109
- package/.framework/src/components/ui/ItemCard.tsx +86 -58
- package/.framework/src/components/ui/ItemListView.tsx +88 -61
- package/.framework/src/components/ui/LoadingSpinner.tsx +52 -27
- package/.framework/src/components/ui/Modal.tsx +81 -4
- package/.framework/src/components/ui/RichTextEditor.tsx +101 -9
- package/.framework/src/components/ui/accordion.tsx +97 -5
- package/.framework/src/components/ui/alert-dialog.tsx +225 -13
- package/.framework/src/components/ui/alert.tsx +113 -6
- package/.framework/src/components/ui/aspect-ratio.tsx +49 -2
- package/.framework/src/components/ui/avatar.tsx +129 -7
- package/.framework/src/components/ui/badge.tsx +65 -3
- package/.framework/src/components/ui/breadcrumb.tsx +145 -8
- package/.framework/src/components/ui/button-group.tsx +81 -4
- package/.framework/src/components/ui/button.tsx +49 -2
- package/.framework/src/components/ui/calendar.tsx +65 -3
- package/.framework/src/components/ui/card.tsx +145 -8
- package/.framework/src/components/ui/carousel.tsx +129 -7
- package/.framework/src/components/ui/chart.tsx +161 -10
- package/.framework/src/components/ui/checkbox.tsx +49 -2
- package/.framework/src/components/ui/collapsible.tsx +81 -5
- package/.framework/src/components/ui/combobox.tsx +305 -20
- package/.framework/src/components/ui/command.tsx +177 -11
- package/.framework/src/components/ui/context-menu.tsx +273 -17
- package/.framework/src/components/ui/dialog.tsx +209 -27
- package/.framework/src/components/ui/direction.tsx +64 -4
- package/.framework/src/components/ui/drawer.tsx +193 -12
- package/.framework/src/components/ui/dropdown-menu.tsx +273 -18
- package/.framework/src/components/ui/empty.tsx +145 -9
- package/.framework/src/components/ui/field.tsx +209 -14
- package/.framework/src/components/ui/hover-card.tsx +81 -4
- package/.framework/src/components/ui/input-group.tsx +162 -10
- package/.framework/src/components/ui/input-otp.tsx +98 -5
- package/.framework/src/components/ui/input.tsx +49 -2
- package/.framework/src/components/ui/item.tsx +225 -13
- package/.framework/src/components/ui/kbd.tsx +65 -3
- package/.framework/src/components/ui/label.tsx +49 -2
- package/.framework/src/components/ui/menubar.tsx +289 -17
- package/.framework/src/components/ui/native-select.tsx +97 -5
- package/.framework/src/components/ui/navigation-menu.tsx +177 -10
- package/.framework/src/components/ui/pagination.tsx +161 -9
- package/.framework/src/components/ui/popover.tsx +145 -8
- package/.framework/src/components/ui/progress.tsx +49 -2
- package/.framework/src/components/ui/radio-group.tsx +65 -3
- package/.framework/src/components/ui/resizable.tsx +82 -4
- package/.framework/src/components/ui/scroll-area.tsx +65 -3
- package/.framework/src/components/ui/select.tsx +193 -11
- package/.framework/src/components/ui/separator.tsx +49 -2
- package/.framework/src/components/ui/sheet.tsx +193 -11
- package/.framework/src/components/ui/sidebar.tsx +481 -38
- package/.framework/src/components/ui/skeleton.tsx +49 -2
- package/.framework/src/components/ui/slider.tsx +49 -2
- package/.framework/src/components/ui/sonner.tsx +49 -2
- package/.framework/src/components/ui/spinner.tsx +49 -2
- package/.framework/src/components/ui/switch.tsx +49 -2
- package/.framework/src/components/ui/table-primitives.tsx +160 -33
- package/.framework/src/components/ui/table.tsx +161 -9
- package/.framework/src/components/ui/tabs.tsx +113 -6
- package/.framework/src/components/ui/textarea.tsx +49 -2
- package/.framework/src/components/ui/toggle-group.tsx +81 -4
- package/.framework/src/components/ui/toggle.tsx +65 -3
- package/.framework/src/components/ui/tooltip.tsx +97 -5
- package/.framework/src/contexts/AppContext.tsx +129 -45
- package/.framework/src/contexts/AuthContext.tsx +187 -144
- package/.framework/src/hooks/use-mobile.ts +48 -2
- package/.framework/src/hooks/useApi.ts +208 -159
- package/.framework/src/hooks/useAppPath.ts +32 -23
- package/.framework/src/hooks/useApps.ts +51 -20
- package/.framework/src/hooks/useEntityList.ts +32 -78
- package/.framework/src/hooks/useEntityRecord.ts +35 -96
- package/.framework/src/hooks/useForm.ts +32 -92
- package/.framework/src/hooks/useListSchema.ts +49 -78
- package/.framework/src/hooks/useSchemaRecord.ts +114 -105
- package/.framework/src/lib/api.ts +195 -116
- package/.framework/src/lib/supabase.ts +98 -64
- package/.framework/src/lib/utils.ts +287 -151
- package/.framework/src/main.tsx +49 -3
- package/.framework/src/pages/DashboardPage.tsx +52 -29
- package/.framework/src/pages/NotFoundPage.tsx +32 -10
- package/.framework/src/pages/SetupPage.tsx +32 -12
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +119 -10
- package/.framework/src/pages/admin/AIAgentsPage.tsx +48 -19
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +187 -17
- package/.framework/src/pages/admin/APIKeysPage.tsx +98 -22
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +113 -26
- package/.framework/src/pages/admin/AppDetailPage.tsx +125 -8
- package/.framework/src/pages/admin/AppsPage.tsx +49 -2
- package/.framework/src/pages/admin/DeliveriesPage.tsx +196 -0
- package/.framework/src/pages/admin/DesignedPage.tsx +32 -18
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +215 -484
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +116 -319
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -16
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +183 -26
- package/.framework/src/pages/admin/IntegrationsPage.tsx +48 -19
- package/.framework/src/pages/admin/InvitesPage.tsx +48 -14
- package/.framework/src/pages/admin/LogsPage.tsx +422 -75
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +113 -24
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +206 -34
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +50 -17
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -21
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +378 -88
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +125 -16
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +49 -10
- package/.framework/src/pages/admin/RoleDetailPage.tsx +130 -10
- package/.framework/src/pages/admin/RolesPage.tsx +171 -18
- package/.framework/src/pages/admin/SelectTestPage.tsx +34 -9
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +49 -11
- package/.framework/src/pages/admin/SimpleDashboard.tsx +49 -10
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +49 -4
- package/.framework/src/pages/admin/TestingDashboard.tsx +98 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +143 -33
- package/.framework/src/pages/admin/TimersPage.tsx +48 -20
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +118 -30
- package/.framework/src/pages/admin/TriggersPage.tsx +64 -19
- package/.framework/src/pages/admin/TypeDetailPage.tsx +138 -15
- package/.framework/src/pages/admin/TypesPage.tsx +48 -20
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +465 -0
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +787 -0
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +699 -0
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +647 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +616 -0
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +1402 -0
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +614 -0
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +571 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +731 -0
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +52 -51
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +31 -22
- package/.framework/src/pages/auth/LoginPage.tsx +50 -23
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -15
- package/.framework/src/pages/auth/RegisterPage.tsx +281 -317
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -0
- package/.framework/src/pages/spine-framework/CLIPage.tsx +33 -0
- package/.framework/src/types/auth.ts +128 -71
- package/.framework/src/types/types.ts +373 -157
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +39 -0
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +36 -0
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +46 -0
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +28 -0
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +38 -0
- package/docs/README.md +9 -130
- package/netlify.toml +5 -2
- package/package.json +13 -25
- package/scripts/kb-ingest-docs.ts +203 -0
- package/spine.config.json +65 -4
- package/.framework/migrations/001_schema.sql +0 -425
- package/.framework/migrations/002_rls_and_functions.sql +0 -763
- package/.framework/migrations/004_enhancements.sql +0 -43
- package/.framework/migrations/005_auth_user_trigger.sql +0 -105
- package/.framework/migrations/006_fix_current_actor_id.sql +0 -21
- package/.framework/migrations/016_invites.sql +0 -27
- package/.framework/migrations/017_fix_get_account_apps.sql +0 -78
- package/.framework/migrations/018_apps_required_roles.sql +0 -17
- package/.framework/migrations/019_triggers_unique_constraint.sql +0 -13
- package/.framework/migrations/020_get_account_apps_role_filter.sql +0 -117
- package/.framework/migrations/021_app_domains.sql +0 -112
- package/.framework/migrations/022_route_prefix_domain_unique.sql +0 -21
- package/.framework/migrations/023_match_embeddings_rpc.sql +0 -78
- package/.framework/migrations/024_messages_account_id.sql +0 -9
- package/.framework/migrations/025_retype_threads_messages.sql +0 -240
- package/.framework/migrations/026_fix_rls_policies.sql +0 -47
- package/.framework/migrations/027_embedding_lifecycle.sql +0 -176
- package/.framework/migrations/028_fix_message_data_permissions.sql +0 -49
- package/.framework/migrations/029_tighten_support_triage_prompt.sql +0 -41
- package/.framework/migrations/030_messages_updated_by.sql +0 -6
- package/.framework/migrations/031_seed_upsert_constraints.sql +0 -35
- package/docs/APPS.md +0 -232
- package/docs/ARCHITECTURE.md +0 -246
- package/docs/INSTALL.md +0 -155
- package/docs/design-schema-spec.md +0 -1837
- package/docs/dev-guides/01-create-an-app.md +0 -183
- package/docs/dev-guides/02-create-a-function.md +0 -178
- package/docs/dev-guides/03-create-a-component.md +0 -178
- package/docs/dev-guides/04-webhook-handlers.md +0 -129
- package/docs/dev-guides/05-testing.md +0 -168
- package/docs/dev-guides/README.md +0 -40
- package/docs/npm-packages-plan.md +0 -288
- package/docs/spine-core--api-reference.md +0 -822
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
-- Migration 004: Enhancements
|
|
2
|
-
-- Additional enhancements and refinements to the Spine schema
|
|
3
|
-
|
|
4
|
-
-- ============================================
|
|
5
|
-
-- TYPE SCOPE STAMPING (from 012_type_scope.sql)
|
|
6
|
-
-- ============================================
|
|
7
|
-
-- Platform-scoped types: owned by spine-system, any authenticated user can read
|
|
8
|
-
UPDATE public.types
|
|
9
|
-
SET design_schema = design_schema || '{"scope":"platform"}'::jsonb
|
|
10
|
-
WHERE slug IN ('kb_article', 'course_lesson', 'community_post', 'community_question');
|
|
11
|
-
|
|
12
|
-
-- Customer-scoped types: owned by the customer's account
|
|
13
|
-
UPDATE public.types
|
|
14
|
-
SET design_schema = design_schema || '{"scope":"customer"}'::jsonb
|
|
15
|
-
WHERE slug IN ('support_ticket');
|
|
16
|
-
|
|
17
|
-
-- Account-scoped types: owned by the calling account (default, explicit for clarity)
|
|
18
|
-
UPDATE public.types
|
|
19
|
-
SET design_schema = design_schema || '{"scope":"account"}'::jsonb
|
|
20
|
-
WHERE design_schema->>'scope' IS NULL;
|
|
21
|
-
|
|
22
|
-
-- ============================================
|
|
23
|
-
-- TABLE COMMENTS
|
|
24
|
-
-- ============================================
|
|
25
|
-
|
|
26
|
-
COMMENT ON TABLE public.account_paths IS
|
|
27
|
-
'Stores ancestor-descendant relationships for account hierarchy traversal';
|
|
28
|
-
|
|
29
|
-
COMMENT ON TABLE public.webhook_handlers IS
|
|
30
|
-
'Dynamic registry for webhook handlers. Custom functions self-register here to be discoverable by the integration-routes handler without static imports.';
|
|
31
|
-
|
|
32
|
-
-- ============================================
|
|
33
|
-
-- ENHANCEMENT NOTES
|
|
34
|
-
-- ============================================
|
|
35
|
-
-- This file contains miscellaneous enhancements that refine the core schema:
|
|
36
|
-
--
|
|
37
|
-
-- 1. Type scope stamping: Ensures all types have an explicit scope field
|
|
38
|
-
-- in their design_schema for proper RLS and visibility control.
|
|
39
|
-
--
|
|
40
|
-
-- 2. Table comments: Documentation for key infrastructure tables.
|
|
41
|
-
--
|
|
42
|
-
-- Future enhancements should be added here as ALTER statements or
|
|
43
|
-
-- configuration updates that don't require new table creation.
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
-- =============================================================================
|
|
2
|
-
-- 005_auth_user_trigger.sql
|
|
3
|
-
-- Creates or updates a people record whenever a new Supabase auth user signs up.
|
|
4
|
-
-- Run AFTER 001_schema.sql (requires spine-system account and person type).
|
|
5
|
-
--
|
|
6
|
-
-- Resolution order on new auth.users insert:
|
|
7
|
-
--
|
|
8
|
-
-- 1. Stub match (invited/pending):
|
|
9
|
-
-- If a people row exists with matching email, status IN ('invited','pending'),
|
|
10
|
-
-- and no auth_uid yet → update it (set auth_uid, full_name).
|
|
11
|
-
-- - 'invited' stub → flip status to 'active' (invite = pre-approval)
|
|
12
|
-
-- - 'pending' stub → keep status 'pending' (access request needs approval)
|
|
13
|
-
--
|
|
14
|
-
-- 2. First user ever → system_admin on spine-system (bootstrap).
|
|
15
|
-
--
|
|
16
|
-
-- 3. Walk-up fallback → minimal active shell on spine-system with no role.
|
|
17
|
-
-- The frontend completes registration via the invites function
|
|
18
|
-
-- (creates account, assigns role, or creates access_request stub).
|
|
19
|
-
-- =============================================================================
|
|
20
|
-
|
|
21
|
-
CREATE OR REPLACE FUNCTION public.handle_new_auth_user()
|
|
22
|
-
RETURNS TRIGGER LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$
|
|
23
|
-
DECLARE
|
|
24
|
-
v_account_id uuid;
|
|
25
|
-
v_type_id uuid;
|
|
26
|
-
v_role_id uuid;
|
|
27
|
-
v_is_first boolean;
|
|
28
|
-
v_design_schema jsonb;
|
|
29
|
-
v_validation_schema jsonb;
|
|
30
|
-
v_stub_id uuid;
|
|
31
|
-
v_stub_status text;
|
|
32
|
-
BEGIN
|
|
33
|
-
-- ── Resolve core references ──────────────────────────────────────────────
|
|
34
|
-
SELECT id INTO v_account_id FROM public.accounts WHERE slug = 'spine-system' LIMIT 1;
|
|
35
|
-
SELECT id, design_schema, validation_schema
|
|
36
|
-
INTO v_type_id, v_design_schema, v_validation_schema
|
|
37
|
-
FROM public.types WHERE kind = 'person' AND slug = 'person' LIMIT 1;
|
|
38
|
-
|
|
39
|
-
IF v_account_id IS NULL OR v_type_id IS NULL THEN
|
|
40
|
-
RAISE WARNING 'handle_new_auth_user: spine-system account or person type not found — skipping';
|
|
41
|
-
RETURN NEW;
|
|
42
|
-
END IF;
|
|
43
|
-
|
|
44
|
-
-- ── 1. Stub match: invited or pending people row for this email ───────────
|
|
45
|
-
SELECT id, status
|
|
46
|
-
INTO v_stub_id, v_stub_status
|
|
47
|
-
FROM public.people
|
|
48
|
-
WHERE email = NEW.email
|
|
49
|
-
AND status IN ('invited', 'pending')
|
|
50
|
-
AND auth_uid IS NULL
|
|
51
|
-
LIMIT 1;
|
|
52
|
-
|
|
53
|
-
IF v_stub_id IS NOT NULL THEN
|
|
54
|
-
UPDATE public.people SET
|
|
55
|
-
auth_uid = NEW.id,
|
|
56
|
-
full_name = COALESCE(NEW.raw_user_meta_data->>'full_name', full_name, split_part(NEW.email, '@', 1)),
|
|
57
|
-
-- invited = pre-approved; pending = still needs approval
|
|
58
|
-
status = CASE WHEN v_stub_status = 'invited' THEN 'active' ELSE 'pending' END,
|
|
59
|
-
updated_at = now()
|
|
60
|
-
WHERE id = v_stub_id;
|
|
61
|
-
|
|
62
|
-
RETURN NEW;
|
|
63
|
-
END IF;
|
|
64
|
-
|
|
65
|
-
-- ── 2. First user bootstrap → system_admin ───────────────────────────────
|
|
66
|
-
SELECT NOT EXISTS (SELECT 1 FROM public.people LIMIT 1) INTO v_is_first;
|
|
67
|
-
IF v_is_first THEN
|
|
68
|
-
SELECT id INTO v_role_id FROM public.roles WHERE slug = 'system_admin' LIMIT 1;
|
|
69
|
-
END IF;
|
|
70
|
-
|
|
71
|
-
-- ── 3. Walk-up fallback → minimal shell (frontend completes via invites fn) ─
|
|
72
|
-
INSERT INTO public.people (
|
|
73
|
-
id,
|
|
74
|
-
auth_uid,
|
|
75
|
-
email,
|
|
76
|
-
full_name,
|
|
77
|
-
account_id,
|
|
78
|
-
type_id,
|
|
79
|
-
role_id,
|
|
80
|
-
status,
|
|
81
|
-
is_active,
|
|
82
|
-
design_schema,
|
|
83
|
-
validation_schema
|
|
84
|
-
) VALUES (
|
|
85
|
-
NEW.id,
|
|
86
|
-
NEW.id,
|
|
87
|
-
NEW.email,
|
|
88
|
-
COALESCE(NEW.raw_user_meta_data->>'full_name', split_part(NEW.email, '@', 1)),
|
|
89
|
-
v_account_id,
|
|
90
|
-
v_type_id,
|
|
91
|
-
v_role_id, -- NULL unless first user
|
|
92
|
-
'active', -- frontend will update if this becomes an access_request
|
|
93
|
-
true,
|
|
94
|
-
v_design_schema,
|
|
95
|
-
COALESCE(v_validation_schema, '{}'::jsonb)
|
|
96
|
-
)
|
|
97
|
-
ON CONFLICT (id) DO NOTHING;
|
|
98
|
-
|
|
99
|
-
RETURN NEW;
|
|
100
|
-
END;
|
|
101
|
-
$$;
|
|
102
|
-
|
|
103
|
-
CREATE OR REPLACE TRIGGER on_auth_user_created
|
|
104
|
-
AFTER INSERT ON auth.users
|
|
105
|
-
FOR EACH ROW EXECUTE FUNCTION public.handle_new_auth_user();
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
-- Patch: fix uuid = text operator error in current_actor_id()
|
|
2
|
-
-- The previous version cast v_auth_id to text before comparing with auth_uid (uuid),
|
|
3
|
-
-- which causes PostgreSQL error 42883. This re-creates the function with matching types.
|
|
4
|
-
|
|
5
|
-
CREATE OR REPLACE FUNCTION public.current_actor_id()
|
|
6
|
-
RETURNS uuid AS $$
|
|
7
|
-
DECLARE
|
|
8
|
-
v_auth_id UUID;
|
|
9
|
-
v_person_id UUID;
|
|
10
|
-
BEGIN
|
|
11
|
-
v_auth_id := auth.uid();
|
|
12
|
-
|
|
13
|
-
-- Look up internal person ID from auth_uid
|
|
14
|
-
SELECT p.id INTO v_person_id
|
|
15
|
-
FROM public.people p
|
|
16
|
-
WHERE p.auth_uid = v_auth_id AND p.is_active = true
|
|
17
|
-
LIMIT 1;
|
|
18
|
-
|
|
19
|
-
RETURN v_person_id;
|
|
20
|
-
END;
|
|
21
|
-
$$ LANGUAGE plpgsql SECURITY DEFINER STABLE;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
-- Migration 016: Invite system indexes
|
|
2
|
-
-- Invite and access_request stubs are stored as people rows with status
|
|
3
|
-
-- 'invited' or 'pending' and invite metadata in the data jsonb column.
|
|
4
|
-
--
|
|
5
|
-
-- people.status values:
|
|
6
|
-
-- active — normal active person
|
|
7
|
-
-- inactive — deactivated
|
|
8
|
-
-- invited — admin-generated invite stub, unclaimed (pre-approval by definition)
|
|
9
|
-
-- pending — walk-up access request stub, awaiting member_admin approval
|
|
10
|
-
--
|
|
11
|
-
-- Invite metadata stored in people.data:
|
|
12
|
-
-- invite_token text — 16-char random lookup key (URL: /register?t=TOKEN)
|
|
13
|
-
-- invite_kind text — 'invite' | 'access_request'
|
|
14
|
-
-- invite_expires_at text — ISO timestamp
|
|
15
|
-
-- invite_attempts integer — failed validation attempts
|
|
16
|
-
-- invite_blocked_at text — ISO timestamp, set after too many attempts
|
|
17
|
-
-- invite_invited_by uuid — person UUID of the inviter
|
|
18
|
-
|
|
19
|
-
-- Fast token lookup
|
|
20
|
-
CREATE INDEX IF NOT EXISTS people_invite_token_idx
|
|
21
|
-
ON public.people ((data->>'invite_token'))
|
|
22
|
-
WHERE data->>'invite_token' IS NOT NULL;
|
|
23
|
-
|
|
24
|
-
-- Efficient scoped invite list queries
|
|
25
|
-
CREATE INDEX IF NOT EXISTS people_invite_kind_account_idx
|
|
26
|
-
ON public.people (account_id, status)
|
|
27
|
-
WHERE data->>'invite_kind' IS NOT NULL;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
-- Migration 017: Fix get_account_apps() to include globally-available apps
|
|
2
|
-
--
|
|
3
|
-
-- Problem: The RPC function excluded apps where owner_account_id IS NULL,
|
|
4
|
-
-- meaning installed apps (source='npm', owner_account_id=NULL) were invisible
|
|
5
|
-
-- to all users in the apps list.
|
|
6
|
-
--
|
|
7
|
-
-- Fix: Include apps where owner_account_id IS NULL (globally available apps).
|
|
8
|
-
-- Must DROP first because the return type changed (added route_prefix, renderer, etc.)
|
|
9
|
-
|
|
10
|
-
DROP FUNCTION IF EXISTS public.get_account_apps(uuid, boolean, boolean);
|
|
11
|
-
|
|
12
|
-
CREATE OR REPLACE FUNCTION public.get_account_apps(
|
|
13
|
-
account_id uuid,
|
|
14
|
-
include_system boolean DEFAULT true,
|
|
15
|
-
include_inactive boolean DEFAULT false
|
|
16
|
-
)
|
|
17
|
-
RETURNS TABLE(
|
|
18
|
-
id uuid,
|
|
19
|
-
slug text,
|
|
20
|
-
name text,
|
|
21
|
-
description text,
|
|
22
|
-
icon text,
|
|
23
|
-
color text,
|
|
24
|
-
version text,
|
|
25
|
-
app_type text,
|
|
26
|
-
source text,
|
|
27
|
-
owner_account_id uuid,
|
|
28
|
-
is_active boolean,
|
|
29
|
-
is_system boolean,
|
|
30
|
-
min_role text,
|
|
31
|
-
config jsonb,
|
|
32
|
-
nav_items jsonb,
|
|
33
|
-
route_prefix text,
|
|
34
|
-
renderer text,
|
|
35
|
-
metadata jsonb,
|
|
36
|
-
integration_deps jsonb,
|
|
37
|
-
created_at timestamptz
|
|
38
|
-
)
|
|
39
|
-
LANGUAGE plpgsql
|
|
40
|
-
SECURITY DEFINER
|
|
41
|
-
AS $$
|
|
42
|
-
BEGIN
|
|
43
|
-
RETURN QUERY
|
|
44
|
-
SELECT
|
|
45
|
-
a.id,
|
|
46
|
-
a.slug,
|
|
47
|
-
a.name,
|
|
48
|
-
a.description,
|
|
49
|
-
a.icon,
|
|
50
|
-
a.color,
|
|
51
|
-
a.version,
|
|
52
|
-
a.app_type,
|
|
53
|
-
a.source,
|
|
54
|
-
a.owner_account_id,
|
|
55
|
-
a.is_active,
|
|
56
|
-
a.is_system,
|
|
57
|
-
a.min_role,
|
|
58
|
-
a.config,
|
|
59
|
-
a.nav_items,
|
|
60
|
-
a.route_prefix,
|
|
61
|
-
a.renderer,
|
|
62
|
-
a.metadata,
|
|
63
|
-
a.integration_deps,
|
|
64
|
-
a.created_at
|
|
65
|
-
FROM public.apps a
|
|
66
|
-
WHERE
|
|
67
|
-
(include_inactive OR a.is_active = true)
|
|
68
|
-
AND (
|
|
69
|
-
a.is_system = true -- always include system apps
|
|
70
|
-
OR a.owner_account_id = get_account_apps.account_id -- owned by this account
|
|
71
|
-
OR a.owner_account_id IS NULL -- globally available (npm-installed apps)
|
|
72
|
-
)
|
|
73
|
-
ORDER BY
|
|
74
|
-
a.is_system DESC,
|
|
75
|
-
a.app_type,
|
|
76
|
-
a.name;
|
|
77
|
-
END;
|
|
78
|
-
$$;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
-- Migration 018: Add required_roles array to apps table
|
|
2
|
-
--
|
|
3
|
-
-- min_role (single string) only supports one role gate.
|
|
4
|
-
-- required_roles (jsonb array) supports gating by any of several roles.
|
|
5
|
-
-- e.g. ["support", "support_admin"] — user needs either role to access the app.
|
|
6
|
-
--
|
|
7
|
-
-- Both columns coexist. required_roles takes precedence at runtime;
|
|
8
|
-
-- min_role is kept as a legacy fallback and for display purposes.
|
|
9
|
-
|
|
10
|
-
ALTER TABLE public.apps
|
|
11
|
-
ADD COLUMN IF NOT EXISTS required_roles jsonb DEFAULT '[]'::jsonb;
|
|
12
|
-
|
|
13
|
-
-- Backfill: migrate existing min_role values into the array
|
|
14
|
-
UPDATE public.apps
|
|
15
|
-
SET required_roles = jsonb_build_array(min_role)
|
|
16
|
-
WHERE min_role IS NOT NULL
|
|
17
|
-
AND (required_roles = '[]'::jsonb OR required_roles IS NULL);
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
-- Migration 019: Add unique constraint on triggers(app_id, name)
|
|
2
|
-
--
|
|
3
|
-
-- The triggers table had no unique constraint, making idempotent upserts
|
|
4
|
-
-- impossible (re-runs would create duplicate rows). This adds a partial unique
|
|
5
|
-
-- index scoped to (app_id, name) so install-app can safely upsert seed triggers
|
|
6
|
-
-- using onConflict: 'app_id,name'.
|
|
7
|
-
--
|
|
8
|
-
-- NULL app_id rows (global triggers) are excluded from the uniqueness check
|
|
9
|
-
-- via the WHERE clause to avoid false conflicts between global triggers.
|
|
10
|
-
|
|
11
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_triggers_app_id_name
|
|
12
|
-
ON public.triggers(app_id, name)
|
|
13
|
-
WHERE app_id IS NOT NULL;
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
-- Migration 020: Add role-based filtering to get_account_apps()
|
|
2
|
-
--
|
|
3
|
-
-- Previously the RPC returned all apps for an account and the frontend
|
|
4
|
-
-- filtered by role client-side. This was fragile (race conditions around
|
|
5
|
-
-- stale roles) and leaked app metadata to users who couldn't access them.
|
|
6
|
-
--
|
|
7
|
-
-- New signature adds two optional params:
|
|
8
|
-
-- user_role_slugs text[] — the calling user's role slugs (e.g. ARRAY['support'])
|
|
9
|
-
-- is_system_admin boolean — true bypasses all role checks
|
|
10
|
-
--
|
|
11
|
-
-- Filtering logic:
|
|
12
|
-
-- 1. system_admin always sees everything
|
|
13
|
-
-- 2. Apps with no required_roles AND no min_role are visible to everyone
|
|
14
|
-
-- 3. Apps with required_roles: user must have at least one matching role
|
|
15
|
-
-- 4. Apps with only min_role (legacy): treated as required_roles = ARRAY[min_role]
|
|
16
|
-
--
|
|
17
|
-
-- Existing callers that omit the new params get the old behaviour (no filtering).
|
|
18
|
-
|
|
19
|
-
DROP FUNCTION IF EXISTS public.get_account_apps(uuid, boolean, boolean);
|
|
20
|
-
DROP FUNCTION IF EXISTS public.get_account_apps(uuid, boolean, boolean, text[], boolean);
|
|
21
|
-
|
|
22
|
-
CREATE OR REPLACE FUNCTION public.get_account_apps(
|
|
23
|
-
account_id uuid,
|
|
24
|
-
include_system boolean DEFAULT true,
|
|
25
|
-
include_inactive boolean DEFAULT false,
|
|
26
|
-
user_role_slugs text[] DEFAULT NULL,
|
|
27
|
-
is_system_admin boolean DEFAULT false
|
|
28
|
-
)
|
|
29
|
-
RETURNS TABLE(
|
|
30
|
-
id uuid,
|
|
31
|
-
slug text,
|
|
32
|
-
name text,
|
|
33
|
-
description text,
|
|
34
|
-
icon text,
|
|
35
|
-
color text,
|
|
36
|
-
version text,
|
|
37
|
-
app_type text,
|
|
38
|
-
source text,
|
|
39
|
-
owner_account_id uuid,
|
|
40
|
-
is_active boolean,
|
|
41
|
-
is_system boolean,
|
|
42
|
-
min_role text,
|
|
43
|
-
required_roles jsonb,
|
|
44
|
-
config jsonb,
|
|
45
|
-
nav_items jsonb,
|
|
46
|
-
route_prefix text,
|
|
47
|
-
renderer text,
|
|
48
|
-
metadata jsonb,
|
|
49
|
-
integration_deps jsonb,
|
|
50
|
-
created_at timestamptz
|
|
51
|
-
)
|
|
52
|
-
LANGUAGE plpgsql
|
|
53
|
-
SECURITY DEFINER
|
|
54
|
-
AS $$
|
|
55
|
-
BEGIN
|
|
56
|
-
RETURN QUERY
|
|
57
|
-
SELECT
|
|
58
|
-
a.id,
|
|
59
|
-
a.slug,
|
|
60
|
-
a.name,
|
|
61
|
-
a.description,
|
|
62
|
-
a.icon,
|
|
63
|
-
a.color,
|
|
64
|
-
a.version,
|
|
65
|
-
a.app_type,
|
|
66
|
-
a.source,
|
|
67
|
-
a.owner_account_id,
|
|
68
|
-
a.is_active,
|
|
69
|
-
a.is_system,
|
|
70
|
-
a.min_role,
|
|
71
|
-
a.required_roles,
|
|
72
|
-
a.config,
|
|
73
|
-
a.nav_items,
|
|
74
|
-
a.route_prefix,
|
|
75
|
-
a.renderer,
|
|
76
|
-
a.metadata,
|
|
77
|
-
a.integration_deps,
|
|
78
|
-
a.created_at
|
|
79
|
-
FROM public.apps a
|
|
80
|
-
WHERE
|
|
81
|
-
-- Active filter
|
|
82
|
-
(include_inactive OR a.is_active = true)
|
|
83
|
-
-- Ownership / visibility filter
|
|
84
|
-
AND (
|
|
85
|
-
a.is_system = true
|
|
86
|
-
OR a.owner_account_id = get_account_apps.account_id
|
|
87
|
-
OR a.owner_account_id IS NULL
|
|
88
|
-
)
|
|
89
|
-
-- Role filter (only applied when user_role_slugs is provided)
|
|
90
|
-
AND (
|
|
91
|
-
user_role_slugs IS NULL -- no filter requested (backward compat)
|
|
92
|
-
OR is_system_admin -- system_admin sees everything
|
|
93
|
-
OR ( -- no role requirement on this app
|
|
94
|
-
(a.required_roles IS NULL OR a.required_roles = '[]'::jsonb)
|
|
95
|
-
AND a.min_role IS NULL
|
|
96
|
-
)
|
|
97
|
-
OR ( -- user has a matching required_role
|
|
98
|
-
a.required_roles IS NOT NULL
|
|
99
|
-
AND a.required_roles != '[]'::jsonb
|
|
100
|
-
AND EXISTS (
|
|
101
|
-
SELECT 1
|
|
102
|
-
FROM jsonb_array_elements_text(a.required_roles) AS rr(role_slug)
|
|
103
|
-
WHERE rr.role_slug = ANY(user_role_slugs)
|
|
104
|
-
)
|
|
105
|
-
)
|
|
106
|
-
OR ( -- legacy min_role fallback
|
|
107
|
-
(a.required_roles IS NULL OR a.required_roles = '[]'::jsonb)
|
|
108
|
-
AND a.min_role IS NOT NULL
|
|
109
|
-
AND a.min_role = ANY(user_role_slugs)
|
|
110
|
-
)
|
|
111
|
-
)
|
|
112
|
-
ORDER BY
|
|
113
|
-
a.is_system DESC,
|
|
114
|
-
a.app_type,
|
|
115
|
-
a.name;
|
|
116
|
-
END;
|
|
117
|
-
$$;
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
-- Migration 021: Add preview/prod domain scoping to apps
|
|
2
|
-
--
|
|
3
|
-
-- Allows each app to declare which hostnames it should be served on
|
|
4
|
-
-- in preview and production environments. The frontend uses VITE_ENVIRONMENT
|
|
5
|
-
-- to pick the correct field and filters the routable app list by the
|
|
6
|
-
-- current hostname.
|
|
7
|
-
--
|
|
8
|
-
-- Apps with null preview_domain and prod_domain remain global (backward compatible).
|
|
9
|
-
|
|
10
|
-
ALTER TABLE public.apps
|
|
11
|
-
ADD COLUMN IF NOT EXISTS preview_domain text,
|
|
12
|
-
ADD COLUMN IF NOT EXISTS prod_domain text;
|
|
13
|
-
|
|
14
|
-
DROP FUNCTION IF EXISTS public.get_account_apps(uuid, boolean, boolean, text[], boolean);
|
|
15
|
-
|
|
16
|
-
CREATE OR REPLACE FUNCTION public.get_account_apps(
|
|
17
|
-
account_id uuid,
|
|
18
|
-
include_system boolean DEFAULT true,
|
|
19
|
-
include_inactive boolean DEFAULT false,
|
|
20
|
-
user_role_slugs text[] DEFAULT NULL,
|
|
21
|
-
is_system_admin boolean DEFAULT false
|
|
22
|
-
)
|
|
23
|
-
RETURNS TABLE(
|
|
24
|
-
id uuid,
|
|
25
|
-
slug text,
|
|
26
|
-
name text,
|
|
27
|
-
description text,
|
|
28
|
-
icon text,
|
|
29
|
-
color text,
|
|
30
|
-
version text,
|
|
31
|
-
app_type text,
|
|
32
|
-
source text,
|
|
33
|
-
owner_account_id uuid,
|
|
34
|
-
is_active boolean,
|
|
35
|
-
is_system boolean,
|
|
36
|
-
min_role text,
|
|
37
|
-
required_roles jsonb,
|
|
38
|
-
preview_domain text,
|
|
39
|
-
prod_domain text,
|
|
40
|
-
config jsonb,
|
|
41
|
-
nav_items jsonb,
|
|
42
|
-
route_prefix text,
|
|
43
|
-
renderer text,
|
|
44
|
-
metadata jsonb,
|
|
45
|
-
integration_deps jsonb,
|
|
46
|
-
created_at timestamptz
|
|
47
|
-
)
|
|
48
|
-
LANGUAGE plpgsql
|
|
49
|
-
SECURITY DEFINER
|
|
50
|
-
AS $$
|
|
51
|
-
BEGIN
|
|
52
|
-
RETURN QUERY
|
|
53
|
-
SELECT
|
|
54
|
-
a.id,
|
|
55
|
-
a.slug,
|
|
56
|
-
a.name,
|
|
57
|
-
a.description,
|
|
58
|
-
a.icon,
|
|
59
|
-
a.color,
|
|
60
|
-
a.version,
|
|
61
|
-
a.app_type,
|
|
62
|
-
a.source,
|
|
63
|
-
a.owner_account_id,
|
|
64
|
-
a.is_active,
|
|
65
|
-
a.is_system,
|
|
66
|
-
a.min_role,
|
|
67
|
-
a.required_roles,
|
|
68
|
-
a.preview_domain,
|
|
69
|
-
a.prod_domain,
|
|
70
|
-
a.config,
|
|
71
|
-
a.nav_items,
|
|
72
|
-
a.route_prefix,
|
|
73
|
-
a.renderer,
|
|
74
|
-
a.metadata,
|
|
75
|
-
a.integration_deps,
|
|
76
|
-
a.created_at
|
|
77
|
-
FROM public.apps a
|
|
78
|
-
WHERE
|
|
79
|
-
(include_inactive OR a.is_active = true)
|
|
80
|
-
AND (
|
|
81
|
-
a.is_system = true
|
|
82
|
-
OR a.owner_account_id = get_account_apps.account_id
|
|
83
|
-
OR a.owner_account_id IS NULL
|
|
84
|
-
)
|
|
85
|
-
AND (
|
|
86
|
-
user_role_slugs IS NULL
|
|
87
|
-
OR is_system_admin
|
|
88
|
-
OR (
|
|
89
|
-
(a.required_roles IS NULL OR a.required_roles = '[]'::jsonb)
|
|
90
|
-
AND a.min_role IS NULL
|
|
91
|
-
)
|
|
92
|
-
OR (
|
|
93
|
-
a.required_roles IS NOT NULL
|
|
94
|
-
AND a.required_roles != '[]'::jsonb
|
|
95
|
-
AND EXISTS (
|
|
96
|
-
SELECT 1
|
|
97
|
-
FROM jsonb_array_elements_text(a.required_roles) AS rr(role_slug)
|
|
98
|
-
WHERE rr.role_slug = ANY(user_role_slugs)
|
|
99
|
-
)
|
|
100
|
-
)
|
|
101
|
-
OR (
|
|
102
|
-
(a.required_roles IS NULL OR a.required_roles = '[]'::jsonb)
|
|
103
|
-
AND a.min_role IS NOT NULL
|
|
104
|
-
AND a.min_role = ANY(user_role_slugs)
|
|
105
|
-
)
|
|
106
|
-
)
|
|
107
|
-
ORDER BY
|
|
108
|
-
a.is_system DESC,
|
|
109
|
-
a.app_type,
|
|
110
|
-
a.name;
|
|
111
|
-
END;
|
|
112
|
-
$$;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
-- Migration 022: Allow multiple apps to share a route_prefix when they have
|
|
2
|
-
-- different prod_domains (i.e. they are served from different subdomains).
|
|
3
|
-
--
|
|
4
|
-
-- Before: UNIQUE(route_prefix) WHERE is_active AND route_prefix IS NOT NULL
|
|
5
|
-
-- → only one app could claim "/" across the entire database
|
|
6
|
-
--
|
|
7
|
-
-- After: UNIQUE(route_prefix, COALESCE(prod_domain, '')) WHERE is_active AND route_prefix IS NOT NULL
|
|
8
|
-
-- → two apps can both use "/" as long as they have different prod_domains
|
|
9
|
-
-- → apps with no prod_domain still get a unique slot (COALESCE maps NULL → '')
|
|
10
|
-
--
|
|
11
|
-
-- This is required to support multiple domain-scoped apps (e.g. Cortex on
|
|
12
|
-
-- cortex.spine-framework.com and Portal on portal.spine-framework.com) that
|
|
13
|
-
-- each serve from the root path "/" of their respective domains.
|
|
14
|
-
|
|
15
|
-
-- Drop the old single-column unique index
|
|
16
|
-
DROP INDEX IF EXISTS idx_apps_route_prefix;
|
|
17
|
-
|
|
18
|
-
-- Create the new composite unique index
|
|
19
|
-
CREATE UNIQUE INDEX IF NOT EXISTS idx_apps_route_prefix_domain
|
|
20
|
-
ON public.apps(route_prefix, COALESCE(prod_domain, ''))
|
|
21
|
-
WHERE is_active = true AND route_prefix IS NOT NULL;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
-- Migration 023: match_embeddings RPC for vector similarity search
|
|
2
|
-
--
|
|
3
|
-
-- Provides the `match_embeddings` Postgres function used by:
|
|
4
|
-
-- - custom_kb-embeddings.ts (handleSearchEmbeddings)
|
|
5
|
-
-- - agent-runner.ts (retrieveKnowledge — after upgrade)
|
|
6
|
-
--
|
|
7
|
-
-- Requires the `vector` extension (enabled in migration 002).
|
|
8
|
-
-- Uses cosine distance (<=>). Returns rows ordered best-first.
|
|
9
|
-
|
|
10
|
-
-- ============================================
|
|
11
|
-
-- HNSW INDEX (idempotent)
|
|
12
|
-
-- ============================================
|
|
13
|
-
-- Create HNSW index on the embedding column for fast approximate nearest-neighbour search.
|
|
14
|
-
-- Skip if it already exists (Postgres 15+ supports IF NOT EXISTS for indexes).
|
|
15
|
-
DO $$
|
|
16
|
-
BEGIN
|
|
17
|
-
IF NOT EXISTS (
|
|
18
|
-
SELECT 1 FROM pg_indexes
|
|
19
|
-
WHERE schemaname = 'public'
|
|
20
|
-
AND tablename = 'embeddings'
|
|
21
|
-
AND indexname = 'embeddings_embedding_hnsw_idx'
|
|
22
|
-
) THEN
|
|
23
|
-
EXECUTE 'CREATE INDEX embeddings_embedding_hnsw_idx
|
|
24
|
-
ON public.embeddings
|
|
25
|
-
USING hnsw (embedding vector_cosine_ops)
|
|
26
|
-
WITH (m = 16, ef_construction = 64)';
|
|
27
|
-
END IF;
|
|
28
|
-
END
|
|
29
|
-
$$;
|
|
30
|
-
|
|
31
|
-
-- ============================================
|
|
32
|
-
-- match_embeddings RPC
|
|
33
|
-
-- ============================================
|
|
34
|
-
CREATE OR REPLACE FUNCTION public.match_embeddings(
|
|
35
|
-
query_embedding vector(1536),
|
|
36
|
-
match_count int DEFAULT 10,
|
|
37
|
-
filter_account_ids uuid[] DEFAULT NULL,
|
|
38
|
-
filter_vector_type text DEFAULT NULL,
|
|
39
|
-
similarity_threshold float DEFAULT 0.15
|
|
40
|
-
)
|
|
41
|
-
RETURNS TABLE (
|
|
42
|
-
id uuid,
|
|
43
|
-
document_id text,
|
|
44
|
-
content text,
|
|
45
|
-
metadata jsonb,
|
|
46
|
-
account_id uuid,
|
|
47
|
-
similarity float
|
|
48
|
-
)
|
|
49
|
-
LANGUAGE plpgsql
|
|
50
|
-
SECURITY DEFINER
|
|
51
|
-
SET search_path = public
|
|
52
|
-
AS $$
|
|
53
|
-
BEGIN
|
|
54
|
-
RETURN QUERY
|
|
55
|
-
SELECT
|
|
56
|
-
e.id,
|
|
57
|
-
e.document_id,
|
|
58
|
-
e.content,
|
|
59
|
-
e.metadata,
|
|
60
|
-
e.account_id,
|
|
61
|
-
1 - (e.embedding <=> query_embedding) AS similarity
|
|
62
|
-
FROM public.embeddings e
|
|
63
|
-
WHERE
|
|
64
|
-
-- account scope filter (NULL = no filter — platform-wide search)
|
|
65
|
-
(filter_account_ids IS NULL OR e.account_id = ANY(filter_account_ids))
|
|
66
|
-
-- vector type filter (NULL = all types)
|
|
67
|
-
AND (filter_vector_type IS NULL OR e.metadata->>'vector_type' = filter_vector_type)
|
|
68
|
-
-- similarity gate (cosine similarity = 1 - cosine distance)
|
|
69
|
-
AND (1 - (e.embedding <=> query_embedding)) >= similarity_threshold
|
|
70
|
-
ORDER BY e.embedding <=> query_embedding -- ascending distance = descending similarity
|
|
71
|
-
LIMIT match_count;
|
|
72
|
-
END;
|
|
73
|
-
$$;
|
|
74
|
-
|
|
75
|
-
-- Grant execute to authenticated and service roles
|
|
76
|
-
GRANT EXECUTE ON FUNCTION public.match_embeddings(vector, int, uuid[], text, float) TO authenticated;
|
|
77
|
-
GRANT EXECUTE ON FUNCTION public.match_embeddings(vector, int, uuid[], text, float) TO service_role;
|
|
78
|
-
GRANT EXECUTE ON FUNCTION public.match_embeddings(vector, int, uuid[], text, float) TO anon;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
-- Migration 024: Add account_id to messages table
|
|
2
|
-
-- messages was the only runtime table missing account_id.
|
|
3
|
-
-- Required by admin-data's create() (which stamps account_id on all runtime records)
|
|
4
|
-
-- and by RLS policies that scope rows to an account.
|
|
5
|
-
|
|
6
|
-
ALTER TABLE public.messages
|
|
7
|
-
ADD COLUMN IF NOT EXISTS account_id uuid REFERENCES public.accounts(id);
|
|
8
|
-
|
|
9
|
-
CREATE INDEX IF NOT EXISTS idx_messages_account_id ON public.messages(account_id);
|