spine-framework 0.4.4 → 0.5.0-rc.5
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/.env.example +13 -3
- package/.framework/cli/commands/bootstrap.ts +392 -0
- package/.framework/cli/commands/dev.ts +91 -218
- package/.framework/cli/commands/doctor.ts +132 -26
- package/.framework/cli/commands/generate.ts +38 -298
- package/.framework/cli/commands/init.ts +20 -1
- package/.framework/cli/commands/install-app.ts +183 -13
- package/.framework/cli/commands/migrate.ts +36 -30
- package/.framework/cli/commands/migrations.ts +16 -56
- package/.framework/cli/commands/upgrade.ts +35 -0
- package/.framework/cli/commands/validate-app.ts +127 -1
- package/.framework/cli/commands/validate-schema.ts +147 -0
- package/.framework/cli/context.ts +223 -110
- package/.framework/cli/index.ts +6 -0
- package/.framework/cli/lib/project-files.ts +241 -1
- package/.framework/functions/_shared/app-manifest.ts +2 -0
- package/.framework/functions/_shared/hash-api-key.ts +183 -79
- package/.framework/functions/_shared/logging.ts +562 -224
- package/.framework/functions/_shared/middleware.ts +47 -44
- package/.framework/functions/_shared/permissions.ts +4 -0
- package/.framework/functions/admin-data.ts +51 -28
- package/.framework/functions/ai-agents.ts +10 -6
- package/.framework/functions/api-keys.ts +301 -122
- package/.framework/functions/apps.ts +63 -29
- package/.framework/functions/cil-ingest.ts +48 -15
- package/.framework/functions/debug-auth.ts +14 -8
- package/.framework/functions/deliveries.ts +39 -12
- package/.framework/functions/embeddings.ts +149 -78
- package/.framework/functions/integration-outbound.ts +67 -27
- package/.framework/functions/integrations.ts +254 -127
- package/.framework/functions/logs.ts +273 -133
- package/.framework/functions/observability.ts +278 -148
- package/.framework/functions/pipeline-executions.ts +1 -1
- package/.framework/functions/pipelines.ts +14 -9
- package/.framework/functions/prompt-configs.ts +7 -4
- package/.framework/functions/roles.ts +8 -5
- package/.framework/functions/security.ts +30 -17
- package/.framework/functions/system-cron.ts +240 -127
- package/.framework/functions/tests.ts +7 -6
- package/.framework/functions/timers.ts +310 -107
- package/.framework/functions/triggers.ts +28 -13
- package/.framework/functions/types.ts +13 -10
- package/.framework/migrations/069_log_stats_window.sql +54 -0
- package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
- package/.framework/migrations/071_timer_interval_keys.sql +96 -0
- package/.framework/migrations/072_slug_autofill.sql +77 -0
- package/.framework/migrations/073_seed_member_roles.sql +26 -0
- package/.framework/migrations/074_app_route_prefix_domains.sql +168 -0
- package/.framework/migrations/075_security_definer_grants.sql +157 -0
- package/.framework/src/apps/admin/index.tsx +1141 -775
- package/.framework/src/components/ErrorBoundary.tsx +136 -0
- package/.framework/src/components/admin/AdminListPage.tsx +81 -73
- package/.framework/src/components/admin/AdminSidebar.tsx +88 -79
- package/.framework/src/components/admin/EntitySelect.tsx +181 -0
- package/.framework/src/components/admin/PageInstructions.tsx +86 -127
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
- package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
- package/.framework/src/components/layout/Sidebar.tsx +300 -177
- package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
- package/.framework/src/components/runtime/DataHeader.tsx +96 -48
- package/.framework/src/components/runtime/DataListPage.tsx +3 -26
- package/.framework/src/components/runtime/DataStats.tsx +10 -10
- package/.framework/src/components/runtime/DataTable.tsx +12 -10
- package/.framework/src/components/ui/sheet.tsx +24 -26
- package/.framework/src/components/ui/textarea.tsx +74 -48
- package/.framework/src/contexts/AppContext.tsx +5 -12
- package/.framework/src/contexts/AuthContext.tsx +17 -9
- package/.framework/src/hooks/useApps.ts +18 -22
- package/.framework/src/hooks/useEntityList.ts +12 -9
- package/.framework/src/hooks/useListSchema.ts +108 -58
- package/.framework/src/instructions/README.md +74 -0
- package/.framework/src/instructions/accounts.md +97 -0
- package/.framework/src/instructions/ai-agents.md +69 -0
- package/.framework/src/instructions/alerts.md +80 -0
- package/.framework/src/instructions/api-keys.md +87 -0
- package/.framework/src/instructions/apps.md +77 -0
- package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
- package/.framework/src/instructions/concepts/apps-and-renderers.md +228 -0
- package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
- package/.framework/src/instructions/concepts/automation.md +186 -0
- package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
- package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
- package/.framework/src/instructions/concepts/design-schema.md +152 -0
- package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
- package/.framework/src/instructions/concepts/observability.md +116 -0
- package/.framework/src/instructions/concepts/permissions.md +150 -0
- package/.framework/src/instructions/concepts/runtime-records.md +111 -0
- package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
- package/.framework/src/instructions/concepts/spine-way.md +172 -0
- package/.framework/src/instructions/deliveries.md +59 -0
- package/.framework/src/instructions/guide/00-orientation.md +106 -0
- package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
- package/.framework/src/instructions/guide/02-project-map.md +147 -0
- package/.framework/src/instructions/guide/03-domain-model.md +223 -0
- package/.framework/src/instructions/guide/04-first-app.md +227 -0
- package/.framework/src/instructions/guide/05-glossary.md +183 -0
- package/.framework/src/instructions/integrations.md +96 -0
- package/.framework/src/instructions/internal/cil-markers.md +83 -0
- package/.framework/src/instructions/internal/docs-contract.md +158 -0
- package/.framework/src/instructions/invites.md +60 -0
- package/.framework/src/instructions/kb.md +80 -0
- package/.framework/src/instructions/logs.md +77 -0
- package/.framework/src/instructions/notifications.md +77 -0
- package/.framework/src/instructions/observability.md +61 -0
- package/.framework/src/instructions/operations/deployment.md +115 -0
- package/.framework/src/instructions/operations/migrations.md +125 -0
- package/.framework/src/instructions/operations/security-checklist.md +170 -0
- package/.framework/src/instructions/operations/troubleshooting.md +170 -0
- package/.framework/src/instructions/operations/upgrade.md +116 -0
- package/.framework/src/instructions/people.md +91 -0
- package/.framework/src/instructions/pipeline-executions.md +62 -0
- package/.framework/src/instructions/pipelines.md +78 -0
- package/.framework/src/instructions/prompts.md +95 -0
- package/.framework/src/instructions/reference/api/admin-data.md +162 -0
- package/.framework/src/instructions/reference/api/auth.md +113 -0
- package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
- package/.framework/src/instructions/reference/app-manifest.md +184 -0
- package/.framework/src/instructions/reference/cli.md +124 -0
- package/.framework/src/instructions/reference/database.md +132 -0
- package/.framework/src/instructions/reference/design-schema.md +280 -0
- package/.framework/src/instructions/reference/env-vars.md +133 -0
- package/.framework/src/instructions/reference/frontend-sdk.md +207 -0
- package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
- package/.framework/src/instructions/reference/functions/admin-data.md +197 -0
- package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
- package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
- package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
- package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
- package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
- package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
- package/.framework/src/instructions/reference/functions/apps.md +140 -0
- package/.framework/src/instructions/reference/functions/auth.md +99 -0
- package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
- package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
- package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
- package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
- package/.framework/src/instructions/reference/functions/index.md +103 -0
- package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
- package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
- package/.framework/src/instructions/reference/functions/integrations.md +130 -0
- package/.framework/src/instructions/reference/functions/invites.md +182 -0
- package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
- package/.framework/src/instructions/reference/functions/kb.md +166 -0
- package/.framework/src/instructions/reference/functions/logs.md +141 -0
- package/.framework/src/instructions/reference/functions/observability.md +105 -0
- package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
- package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
- package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
- package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
- package/.framework/src/instructions/reference/functions/roles.md +121 -0
- package/.framework/src/instructions/reference/functions/security.md +140 -0
- package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
- package/.framework/src/instructions/reference/functions/system.md +106 -0
- package/.framework/src/instructions/reference/functions/tests.md +97 -0
- package/.framework/src/instructions/reference/functions/timers.md +117 -0
- package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
- package/.framework/src/instructions/reference/functions/triggers.md +140 -0
- package/.framework/src/instructions/reference/functions/types.md +146 -0
- package/.framework/src/instructions/reference/seeds.md +126 -0
- package/.framework/src/instructions/reference/shared-modules.md +127 -0
- package/.framework/src/instructions/reference/spine-config.md +114 -0
- package/.framework/src/instructions/roles.md +80 -0
- package/.framework/src/instructions/runtime-collaboration.md +106 -0
- package/.framework/src/instructions/runtime-detail.md +70 -0
- package/.framework/src/instructions/runtime-list.md +77 -0
- package/.framework/src/instructions/security.md +67 -0
- package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
- package/.framework/src/instructions/tasks/add-a-role.md +96 -0
- package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
- package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
- package/.framework/src/instructions/tasks/add-a-type.md +151 -0
- package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
- package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
- package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
- package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
- package/.framework/src/instructions/tasks/document-your-app.md +117 -0
- package/.framework/src/instructions/tasks/package-and-install-an-app.md +136 -0
- package/.framework/src/instructions/tasks/register-an-app.md +137 -0
- package/.framework/src/instructions/tasks/test-your-code.md +108 -0
- package/.framework/src/instructions/tasks/write-a-function.md +132 -0
- package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
- package/.framework/src/instructions/testing.md +59 -0
- package/.framework/src/instructions/timers.md +84 -0
- package/.framework/src/instructions/triggers.md +69 -0
- package/.framework/src/instructions/types.md +93 -0
- package/.framework/src/lib/app-mount.ts +88 -0
- package/.framework/src/pages/NotFoundPage.tsx +62 -31
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
- package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
- package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
- package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
- package/.framework/src/pages/admin/AppsPage.tsx +104 -66
- package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
- package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
- package/.framework/src/pages/admin/LogsPage.tsx +144 -76
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
- package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
- package/.framework/src/pages/admin/RolesPage.tsx +86 -43
- package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
- package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
- package/.framework/src/pages/admin/TimersPage.tsx +90 -62
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
- package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
- package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
- package/.framework/src/pages/admin/TypesPage.tsx +90 -48
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
- package/.framework/src/pages/auth/LoginPage.tsx +3 -2
- package/.framework/src/pages/auth/RegisterPage.tsx +16 -8
- package/.framework/templates/agent/AGENTS.md +167 -0
- package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
- package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
- package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
- package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
- package/.framework/templates/agent/skills/spine-install-app/SKILL.md +79 -0
- package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
- package/.framework/templates/agent/skills/spine-new-app/SKILL.md +79 -0
- package/.framework/templates/agent/skills/spine-new-function/SKILL.md +71 -0
- package/.framework/templates/agent/skills/spine-new-type/SKILL.md +72 -0
- package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
- package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
- package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
- package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
- package/.framework/templates/project.json +4 -1
- package/.framework/tests/unit/account-scoping-gates.test.ts +394 -0
- package/.framework/tests/unit/agent-files.test.ts +355 -0
- package/.framework/tests/unit/agent-runner.test.ts +479 -44
- package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
- package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
- package/.framework/tests/unit/app-mount.test.ts +80 -0
- package/.framework/tests/unit/bootstrap.test.ts +242 -0
- package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
- package/.framework/tests/unit/debug-auth.test.ts +38 -0
- package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
- package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
- package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
- package/.framework/tests/unit/logging-app-id.test.ts +75 -0
- package/.framework/tests/unit/security-definer-grants.test.ts +154 -0
- package/.framework/tests/unit/system-context-denial.test.ts +145 -0
- package/.framework/tests/unit/system-cron.test.ts +240 -0
- package/.framework/tests/unit/timers.test.ts +159 -0
- package/README.md +125 -166
- package/config/tsconfig.cli.json +2 -2
- package/package.json +15 -4
- package/templates/project/package-lock.json +2 -2
- package/.framework/docs/admin-routes.md +0 -76
- package/.framework/docs/api-docs-progress.md +0 -38
- package/.framework/docs/api-governance.md +0 -146
- package/.framework/docs/api-testing-results.md +0 -212
- package/.framework/docs/assembly-launch-guide.md +0 -138
- package/.framework/docs/audit-results.md +0 -590
- package/.framework/docs/db-api-inventory.md +0 -95
- package/.framework/docs/gap-remediation-backlog.md +0 -103
- package/.framework/docs/ui-adoption-verification.md +0 -111
- package/.framework/docs/ui-api-coverage.md +0 -84
- package/.framework/docs/v2-compatibility-audit.md +0 -228
- package/.framework/mcp/index.ts +0 -133
- package/.framework/mcp/load-env.ts +0 -60
- package/.framework/mcp/shared/app-manifest.ts +0 -275
- package/.framework/mcp/shared/db.ts +0 -477
- package/.framework/mcp/shared/kb.ts +0 -118
- package/.framework/mcp/tools/architect.ts +0 -431
- package/.framework/mcp/tools/cil/context.ts +0 -345
- package/.framework/mcp/tools/cil/graph.ts +0 -242
- package/.framework/mcp/tools/cil/ingest.ts +0 -1217
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
- package/.framework/mcp/tools/cil/pipeline.ts +0 -767
- package/.framework/mcp/tools/cil/project.ts +0 -791
- package/.framework/mcp/tools/cil/retrieval.ts +0 -336
- package/.framework/mcp/tools/cil/search-core.ts +0 -454
- package/.framework/mcp/tools/cil/search.ts +0 -97
- package/.framework/mcp/tools/cil/suggest.ts +0 -186
- package/.framework/mcp/tools/cil/validate.ts +0 -1369
- package/.framework/mcp/tools/kb/delete.ts +0 -139
- package/.framework/mcp/tools/kb/index.ts +0 -52
- package/.framework/mcp/tools/kb/ingest.ts +0 -84
- package/.framework/mcp/tools/kb/list-types.ts +0 -102
- package/.framework/mcp/tools/kb/publish.ts +0 -100
- package/.framework/mcp/tools/kb/reindex.ts +0 -86
- package/.framework/mcp/tools/kb/revoke.ts +0 -85
- package/.framework/mcp/tools/kb/search.ts +0 -101
- package/.framework/mcp/tools/kb/upsert.ts +0 -125
- package/.framework/mcp/tools/observability.ts +0 -510
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
-- CIL[BEGIN stable_id="~/.framework/migrations/074_app_route_prefix_domains.sql:app_route_prefix_domains:file" type="file" identity="app_route_prefix_domains" parent="~/.framework/migrations/074_app_route_prefix_domains.sql"]
|
|
2
|
+
-- CIL[DOC-MACRO purpose="Add host-keyed mount overrides to public.apps and surface domain/prefix columns through get_account_apps."]
|
|
3
|
+
-- CIL[DOC-RESPONSIBILITY responsibility="Add prod_route_prefix/preview_route_prefix columns, restore the domain-scoped route_prefix unique index on the effective prod mount, and redefine get_account_apps to return preview_domain, prod_domain, preview_route_prefix, and prod_route_prefix."]
|
|
4
|
+
-- CIL[DOC-CONTEXT module="migrations" layer="database" related_files=".framework/migrations/013_get_account_apps_role_filter.sql,.framework/functions/apps.ts,.framework/src/lib/app-mount.ts"]
|
|
5
|
+
-- CIL[DOC-CONTRACT inputs="none" outputs="apps table with route-prefix override columns; get_account_apps returns domain fields; partial unique index on (effective prod mount, prod_domain)" errors="duplicate effective mount on same prod domain" side_effects="schema_alter; drops and recreates get_account_apps"]
|
|
6
|
+
-- CIL[DOC-MICRO logic_summary="Adds two nullable text columns, recreates the (route_prefix, prod_domain)-style unique index but keyed on COALESCE(prod_route_prefix, route_prefix) so multiple apps may own '/' on different prod domains, then redefines get_account_apps with the four domain/prefix columns appended to its return set" notable_decisions="prod_route_prefix converts prod_domain from a hard visibility filter into a mount selector — the client falls back to route_prefix on non-matching hosts; preview_route_prefix mirrors it for VITE_ENVIRONMENT=preview"]
|
|
7
|
+
-- CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
8
|
+
-- CIL[DOC-STABILITY stability="experimental"]
|
|
9
|
+
|
|
10
|
+
ALTER TABLE public.apps
|
|
11
|
+
ADD COLUMN IF NOT EXISTS prod_route_prefix text,
|
|
12
|
+
ADD COLUMN IF NOT EXISTS preview_route_prefix text;
|
|
13
|
+
|
|
14
|
+
-- One app may own a given mount per prod domain. Using the effective prod
|
|
15
|
+
-- mount (COALESCE) means two apps can both declare '/' as long as their
|
|
16
|
+
-- prod_domain values differ — the intended multi-site topology.
|
|
17
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_apps_route_prefix_domain
|
|
18
|
+
ON public.apps(COALESCE(prod_route_prefix, route_prefix), COALESCE(prod_domain, ''))
|
|
19
|
+
WHERE is_active = true AND route_prefix IS NOT NULL;
|
|
20
|
+
|
|
21
|
+
-- Return the domain + override columns so the client can resolve the
|
|
22
|
+
-- effective mount per hostname. Signature unchanged; return type extended,
|
|
23
|
+
-- so the prior overload must be dropped first.
|
|
24
|
+
DROP FUNCTION IF EXISTS public.get_account_apps(uuid, boolean, boolean, text[], boolean);
|
|
25
|
+
|
|
26
|
+
CREATE OR REPLACE FUNCTION public.get_account_apps(
|
|
27
|
+
account_id uuid,
|
|
28
|
+
include_system boolean DEFAULT true,
|
|
29
|
+
include_inactive boolean DEFAULT false,
|
|
30
|
+
user_role_slugs text[] DEFAULT NULL,
|
|
31
|
+
is_system_admin boolean DEFAULT false
|
|
32
|
+
)
|
|
33
|
+
RETURNS TABLE(
|
|
34
|
+
id uuid,
|
|
35
|
+
slug text,
|
|
36
|
+
name text,
|
|
37
|
+
description text,
|
|
38
|
+
icon text,
|
|
39
|
+
color text,
|
|
40
|
+
version text,
|
|
41
|
+
app_type text,
|
|
42
|
+
source text,
|
|
43
|
+
owner_account_id uuid,
|
|
44
|
+
is_active boolean,
|
|
45
|
+
is_system boolean,
|
|
46
|
+
min_role text,
|
|
47
|
+
required_roles jsonb,
|
|
48
|
+
config jsonb,
|
|
49
|
+
nav_items jsonb,
|
|
50
|
+
route_prefix text,
|
|
51
|
+
renderer text,
|
|
52
|
+
metadata jsonb,
|
|
53
|
+
integration_deps jsonb,
|
|
54
|
+
preview_domain text,
|
|
55
|
+
prod_domain text,
|
|
56
|
+
preview_route_prefix text,
|
|
57
|
+
prod_route_prefix text,
|
|
58
|
+
created_at timestamptz
|
|
59
|
+
)
|
|
60
|
+
LANGUAGE plpgsql
|
|
61
|
+
SECURITY DEFINER
|
|
62
|
+
AS $$
|
|
63
|
+
BEGIN
|
|
64
|
+
RETURN QUERY
|
|
65
|
+
SELECT
|
|
66
|
+
a.id,
|
|
67
|
+
a.slug,
|
|
68
|
+
a.name,
|
|
69
|
+
a.description,
|
|
70
|
+
a.icon,
|
|
71
|
+
a.color,
|
|
72
|
+
a.version,
|
|
73
|
+
a.app_type,
|
|
74
|
+
a.source,
|
|
75
|
+
a.owner_account_id,
|
|
76
|
+
a.is_active,
|
|
77
|
+
a.is_system,
|
|
78
|
+
a.min_role,
|
|
79
|
+
a.required_roles,
|
|
80
|
+
a.config,
|
|
81
|
+
a.nav_items,
|
|
82
|
+
a.route_prefix,
|
|
83
|
+
a.renderer,
|
|
84
|
+
a.metadata,
|
|
85
|
+
a.integration_deps,
|
|
86
|
+
a.preview_domain,
|
|
87
|
+
a.prod_domain,
|
|
88
|
+
a.preview_route_prefix,
|
|
89
|
+
a.prod_route_prefix,
|
|
90
|
+
a.created_at
|
|
91
|
+
FROM public.apps a
|
|
92
|
+
WHERE
|
|
93
|
+
(include_inactive OR a.is_active = true)
|
|
94
|
+
AND (
|
|
95
|
+
a.is_system = true
|
|
96
|
+
OR a.owner_account_id = get_account_apps.account_id
|
|
97
|
+
OR a.owner_account_id IS NULL
|
|
98
|
+
)
|
|
99
|
+
AND (
|
|
100
|
+
user_role_slugs IS NULL
|
|
101
|
+
OR is_system_admin
|
|
102
|
+
OR (
|
|
103
|
+
(a.required_roles IS NULL OR a.required_roles = '[]'::jsonb)
|
|
104
|
+
AND a.min_role IS NULL
|
|
105
|
+
)
|
|
106
|
+
OR (
|
|
107
|
+
a.required_roles IS NOT NULL
|
|
108
|
+
AND a.required_roles != '[]'::jsonb
|
|
109
|
+
AND EXISTS (
|
|
110
|
+
SELECT 1
|
|
111
|
+
FROM jsonb_array_elements_text(a.required_roles) AS rr(role_slug)
|
|
112
|
+
WHERE rr.role_slug = ANY(user_role_slugs)
|
|
113
|
+
)
|
|
114
|
+
)
|
|
115
|
+
OR (
|
|
116
|
+
(a.required_roles IS NULL OR a.required_roles = '[]'::jsonb)
|
|
117
|
+
AND a.min_role IS NOT NULL
|
|
118
|
+
AND a.min_role = ANY(user_role_slugs)
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
ORDER BY
|
|
122
|
+
a.is_system DESC,
|
|
123
|
+
a.app_type,
|
|
124
|
+
a.name;
|
|
125
|
+
END;
|
|
126
|
+
$$;
|
|
127
|
+
|
|
128
|
+
-- Keep get_app_schema's jsonb field list in step with the new columns so
|
|
129
|
+
-- schema-driven consumers (admin UI, admin-data) see the mount fields.
|
|
130
|
+
CREATE OR REPLACE FUNCTION public.get_app_schema(app_slug text)
|
|
131
|
+
RETURNS jsonb
|
|
132
|
+
LANGUAGE plpgsql
|
|
133
|
+
STABLE
|
|
134
|
+
AS $$
|
|
135
|
+
DECLARE
|
|
136
|
+
app_schema jsonb;
|
|
137
|
+
BEGIN
|
|
138
|
+
SELECT jsonb_build_object(
|
|
139
|
+
'id', a.id,
|
|
140
|
+
'slug', a.slug,
|
|
141
|
+
'name', a.name,
|
|
142
|
+
'description', a.description,
|
|
143
|
+
'icon', a.icon,
|
|
144
|
+
'color', a.color,
|
|
145
|
+
'version', a.version,
|
|
146
|
+
'app_type', a.app_type,
|
|
147
|
+
'source', a.source,
|
|
148
|
+
'config', a.config,
|
|
149
|
+
'nav_items', a.nav_items,
|
|
150
|
+
'min_role', a.min_role,
|
|
151
|
+
'required_roles', a.required_roles,
|
|
152
|
+
'integration_deps', a.integration_deps,
|
|
153
|
+
'metadata', a.metadata,
|
|
154
|
+
'route_prefix', a.route_prefix,
|
|
155
|
+
'preview_domain', a.preview_domain,
|
|
156
|
+
'prod_domain', a.prod_domain,
|
|
157
|
+
'preview_route_prefix', a.preview_route_prefix,
|
|
158
|
+
'prod_route_prefix', a.prod_route_prefix,
|
|
159
|
+
'renderer', a.renderer
|
|
160
|
+
) INTO app_schema
|
|
161
|
+
FROM public.apps a
|
|
162
|
+
WHERE a.slug = get_app_schema.app_slug
|
|
163
|
+
AND a.is_active = true;
|
|
164
|
+
|
|
165
|
+
RETURN COALESCE(app_schema, '{}'::jsonb);
|
|
166
|
+
END;
|
|
167
|
+
$$;
|
|
168
|
+
-- CIL[END stable_id="~/.framework/migrations/074_app_route_prefix_domains.sql:app_route_prefix_domains:file"]
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
-- CIL[BEGIN stable_id="~/.framework/migrations/075_security_definer_grants.sql:security_definer_grants:file" type="file" identity="security_definer_grants" parent="~/.framework/migrations/075_security_definer_grants.sql"]
|
|
2
|
+
-- CIL[DOC-MACRO purpose="Lock down anon/authenticated-executable SECURITY DEFINER functions, pin get_accessible_accounts to the caller, and self-check that no privileged RPC stays exposed"]
|
|
3
|
+
-- CIL[DOC-RESPONSIBILITY responsibility="Revoke PUBLIC/anon/authenticated EXECUTE from server-only definer RPCs, drop dead search_similar_embeddings, pin get_accessible_accounts actor for PostgREST roles, set search_path where missing, and assert no definer function remains callable by non-service roles"]
|
|
4
|
+
-- CIL[DOC-CONTEXT module="migrations" layer="database" related_files=".framework/migrations/044_match_embeddings_filtered_knn.sql,.framework/migrations/004_core_rpc_and_broker.sql,.framework/migrations/068_cron_schedule_timer_rpcs.sql,.framework/migrations/002_core_rls_and_functions.sql,.framework/functions/embeddings.ts,.framework/functions/apps.ts,.framework/functions/observability.ts"]
|
|
5
|
+
-- CIL[DOC-CONTRACT inputs="existing public functions from earlier migrations" outputs="revoked EXECUTE for PUBLIC/anon/authenticated on 16 server-only functions; get_accessible_accounts actor pinned for PostgREST roles; search_path set on definer functions missing it" errors="migration raises EXCEPTION if any non-allowlisted definer function remains anon/authenticated-executable" side_effects="direct PostgREST RPC calls with anon or user keys are denied; service_role access unchanged"]
|
|
6
|
+
-- CIL[DOC-MICRO logic_summary="Postgres grants EXECUTE to PUBLIC by default, so every SECURITY DEFINER function shipped reachable at /rest/v1/rpc/* with the anon key. Existence-guarded revokes (to_regprocedure) make the file safe across drifted projects. get_accessible_accounts and current_actor_id cannot be revoked (every tenant RLS policy calls them as the querying role), so the leak is closed by pinning actor_id to current_actor_id() when auth.role() is anon/authenticated. A final DO block re-derives the exposure from pg_proc and fails the migration if any definer function outside the allowlist stays callable" notable_decisions="revoke-over-pin chosen for server-only RPCs because every legit caller already uses adminDb or a wrapper that enforces scoping; drop over revoke for search_similar_embeddings because it is dead code"]
|
|
7
|
+
-- CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
8
|
+
-- CIL[DOC-STABILITY stability="stable"]
|
|
9
|
+
-- CIL[DOC-LEARNING topic="security_definer_grants" content="Every SECURITY DEFINER function must revoke EXECUTE from PUBLIC/anon/authenticated in its defining migration (or be an allowlisted RLS helper) — PUBLIC EXECUTE is the Postgres default and Supabase exposes it via PostgREST. CREATE OR REPLACE preserves grants, so a revoke in any later migration stays effective across recreations"]
|
|
10
|
+
-- CIL[DOC-VECTOR type="context" content="purpose='Lock down privileged RPCs executable by the anon key'; callers: none — migration; related: embeddings.ts searchSimilar, apps.ts list, observability.ts cleanupOldLogs (all now use adminDb)"]
|
|
11
|
+
-- CIL[DOC-VECTOR type="blast_radius" content="Anon/authenticated direct RPC calls to 16 definer functions are denied; RLS policies unaffected; /api/apps and /api/embeddings?action=search-similar keep working via adminDb"]
|
|
12
|
+
-- CIL[DOC-VECTOR type="constraint" content="current_actor_id and get_accessible_accounts must keep anon/authenticated EXECUTE — RLS policies evaluate them as the querying role"]
|
|
13
|
+
|
|
14
|
+
-- ============================================================================
|
|
15
|
+
-- A) Revoke EXECUTE from PUBLIC/anon/authenticated on server-only definer RPCs.
|
|
16
|
+
-- Existence-guarded: the three live projects have drifted (e.g.
|
|
17
|
+
-- apply_demo_flag and search_similar_embeddings are not present everywhere,
|
|
18
|
+
-- and spine-dev still carries the archived-027 leftovers
|
|
19
|
+
-- approve_embeddings_for_item / sync_item_embeddings).
|
|
20
|
+
-- ============================================================================
|
|
21
|
+
DO $$
|
|
22
|
+
DECLARE
|
|
23
|
+
v_sig text;
|
|
24
|
+
revokes text[] := ARRAY[
|
|
25
|
+
'match_embeddings(vector,integer,uuid[],text,double precision,text[],text[])',
|
|
26
|
+
'rebuild_kb_cache(uuid,text)',
|
|
27
|
+
'trg_rebuild_kb_article_list()',
|
|
28
|
+
'handle_new_auth_user()',
|
|
29
|
+
'apply_demo_flag()',
|
|
30
|
+
'approve_embeddings_for_item(uuid)',
|
|
31
|
+
'sync_item_embeddings()',
|
|
32
|
+
'revoke_embeddings_for_item(uuid)',
|
|
33
|
+
'validate_schedule_creator(uuid)',
|
|
34
|
+
'get_due_schedules(timestamp with time zone)',
|
|
35
|
+
'get_due_timers(timestamp with time zone)',
|
|
36
|
+
'update_schedule_after_run(uuid,boolean,text)',
|
|
37
|
+
'update_timer_after_run(uuid,boolean,text)',
|
|
38
|
+
'get_error_rate(integer)',
|
|
39
|
+
'get_latency_percentiles(integer)',
|
|
40
|
+
'get_pipeline_stats(integer)',
|
|
41
|
+
'cleanup_old_logs(integer)',
|
|
42
|
+
'get_account_apps(uuid,boolean,boolean,text[],boolean)'
|
|
43
|
+
];
|
|
44
|
+
BEGIN
|
|
45
|
+
FOREACH v_sig IN ARRAY revokes LOOP
|
|
46
|
+
IF to_regprocedure('public.' || v_sig) IS NOT NULL THEN
|
|
47
|
+
EXECUTE format('REVOKE ALL ON FUNCTION public.%s FROM PUBLIC', v_sig);
|
|
48
|
+
EXECUTE format('REVOKE ALL ON FUNCTION public.%s FROM anon', v_sig);
|
|
49
|
+
EXECUTE format('REVOKE ALL ON FUNCTION public.%s FROM authenticated', v_sig);
|
|
50
|
+
EXECUTE format('GRANT EXECUTE ON FUNCTION public.%s TO service_role', v_sig);
|
|
51
|
+
ELSE
|
|
52
|
+
RAISE NOTICE 'skipping % — not present on this project', v_sig;
|
|
53
|
+
END IF;
|
|
54
|
+
END LOOP;
|
|
55
|
+
END $$;
|
|
56
|
+
|
|
57
|
+
-- ============================================================================
|
|
58
|
+
-- B) Drop the dead RPC. Zero callers in the repo; it filtered by a
|
|
59
|
+
-- caller-supplied account id, i.e. an unauthenticated read of any tenant's
|
|
60
|
+
-- approved embeddings while it existed.
|
|
61
|
+
-- ============================================================================
|
|
62
|
+
DROP FUNCTION IF EXISTS public.search_similar_embeddings(uuid, text, vector, integer, double precision);
|
|
63
|
+
|
|
64
|
+
-- ============================================================================
|
|
65
|
+
-- C) Pin get_accessible_accounts to the caller for PostgREST roles.
|
|
66
|
+
-- The function cannot be revoked — tenant RLS policies evaluate it as the
|
|
67
|
+
-- querying role — but the caller-supplied actor_id let anyone enumerate
|
|
68
|
+
-- another person's account set (all accounts, for a system_admin target).
|
|
69
|
+
-- Policies already pass current_actor_id(); auth.ts passes the caller's own
|
|
70
|
+
-- person id; service callers (adminDb/cron) keep the argument honored.
|
|
71
|
+
-- ============================================================================
|
|
72
|
+
CREATE OR REPLACE FUNCTION public.get_accessible_accounts(actor_id uuid)
|
|
73
|
+
RETURNS TABLE (account_id uuid) AS $$
|
|
74
|
+
BEGIN
|
|
75
|
+
-- PostgREST roles may only inspect their own access set; the actor_id
|
|
76
|
+
-- argument is honored only for service_role and internal/cron contexts.
|
|
77
|
+
IF auth.role() IN ('anon', 'authenticated') THEN
|
|
78
|
+
actor_id := public.current_actor_id();
|
|
79
|
+
END IF;
|
|
80
|
+
|
|
81
|
+
IF EXISTS (
|
|
82
|
+
SELECT 1 FROM public.people p
|
|
83
|
+
JOIN public.roles r ON p.role_id = r.id
|
|
84
|
+
WHERE p.id = actor_id AND r.slug = 'system_admin'
|
|
85
|
+
) THEN
|
|
86
|
+
RETURN QUERY SELECT a.id FROM public.accounts a;
|
|
87
|
+
RETURN;
|
|
88
|
+
END IF;
|
|
89
|
+
RETURN QUERY
|
|
90
|
+
WITH RECURSIVE account_tree AS (
|
|
91
|
+
SELECT p.account_id as id FROM public.people p WHERE p.id = actor_id
|
|
92
|
+
UNION ALL
|
|
93
|
+
SELECT ap.descendant_id
|
|
94
|
+
FROM public.account_paths ap
|
|
95
|
+
JOIN account_tree at ON ap.ancestor_id = at.id
|
|
96
|
+
)
|
|
97
|
+
SELECT id FROM account_tree;
|
|
98
|
+
END;
|
|
99
|
+
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = public;
|
|
100
|
+
|
|
101
|
+
-- ============================================================================
|
|
102
|
+
-- D) SET search_path on definer functions that were missing it. Mutable
|
|
103
|
+
-- search_path on a privileged function is a schema-shadowing risk.
|
|
104
|
+
-- (get_accessible_accounts picked it up in the CREATE OR REPLACE above;
|
|
105
|
+
-- 021/034/044/068/071 functions already set it.)
|
|
106
|
+
-- ============================================================================
|
|
107
|
+
DO $$
|
|
108
|
+
DECLARE
|
|
109
|
+
v_sig text;
|
|
110
|
+
needs_path text[] := ARRAY[
|
|
111
|
+
'current_actor_id()',
|
|
112
|
+
'rebuild_kb_cache(uuid,text)',
|
|
113
|
+
'trg_rebuild_kb_article_list()',
|
|
114
|
+
'get_account_apps(uuid,boolean,boolean,text[],boolean)'
|
|
115
|
+
];
|
|
116
|
+
BEGIN
|
|
117
|
+
FOREACH v_sig IN ARRAY needs_path LOOP
|
|
118
|
+
IF to_regprocedure('public.' || v_sig) IS NOT NULL THEN
|
|
119
|
+
EXECUTE format('ALTER FUNCTION public.%s SET search_path = public', v_sig);
|
|
120
|
+
END IF;
|
|
121
|
+
END LOOP;
|
|
122
|
+
END $$;
|
|
123
|
+
|
|
124
|
+
-- ============================================================================
|
|
125
|
+
-- E) Self-check: derive remaining exposure from pg_proc and fail loudly.
|
|
126
|
+
-- RLS helpers (evaluated as the querying role inside policies) are the only
|
|
127
|
+
-- sanctioned anon/authenticated-executable definer functions.
|
|
128
|
+
-- ============================================================================
|
|
129
|
+
DO $$
|
|
130
|
+
DECLARE
|
|
131
|
+
bad record;
|
|
132
|
+
exposed int := 0;
|
|
133
|
+
BEGIN
|
|
134
|
+
FOR bad IN
|
|
135
|
+
SELECT p.oid::regprocedure AS sig
|
|
136
|
+
FROM pg_proc p
|
|
137
|
+
JOIN pg_namespace n ON n.oid = p.pronamespace
|
|
138
|
+
WHERE n.nspname = 'public'
|
|
139
|
+
AND p.prosecdef
|
|
140
|
+
AND p.oid::regprocedure::text NOT IN (
|
|
141
|
+
'current_actor_id()',
|
|
142
|
+
'get_accessible_accounts(uuid)'
|
|
143
|
+
)
|
|
144
|
+
AND (
|
|
145
|
+
has_function_privilege('anon', p.oid, 'EXECUTE')
|
|
146
|
+
OR has_function_privilege('authenticated', p.oid, 'EXECUTE')
|
|
147
|
+
)
|
|
148
|
+
LOOP
|
|
149
|
+
exposed := exposed + 1;
|
|
150
|
+
RAISE WARNING 'SECURITY DEFINER still executable by anon/authenticated: %', bad.sig;
|
|
151
|
+
END LOOP;
|
|
152
|
+
|
|
153
|
+
IF exposed > 0 THEN
|
|
154
|
+
RAISE EXCEPTION '% definer function(s) still exposed to anon/authenticated — refusing to finish migration', exposed;
|
|
155
|
+
END IF;
|
|
156
|
+
END $$;
|
|
157
|
+
-- CIL[END stable_id="~/.framework/migrations/075_security_definer_grants.sql:security_definer_grants:file"]
|