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.
Files changed (305) hide show
  1. package/.env.example +13 -3
  2. package/.framework/cli/commands/bootstrap.ts +392 -0
  3. package/.framework/cli/commands/dev.ts +91 -218
  4. package/.framework/cli/commands/doctor.ts +132 -26
  5. package/.framework/cli/commands/generate.ts +38 -298
  6. package/.framework/cli/commands/init.ts +20 -1
  7. package/.framework/cli/commands/install-app.ts +183 -13
  8. package/.framework/cli/commands/migrate.ts +36 -30
  9. package/.framework/cli/commands/migrations.ts +16 -56
  10. package/.framework/cli/commands/upgrade.ts +35 -0
  11. package/.framework/cli/commands/validate-app.ts +127 -1
  12. package/.framework/cli/commands/validate-schema.ts +147 -0
  13. package/.framework/cli/context.ts +223 -110
  14. package/.framework/cli/index.ts +6 -0
  15. package/.framework/cli/lib/project-files.ts +241 -1
  16. package/.framework/functions/_shared/app-manifest.ts +2 -0
  17. package/.framework/functions/_shared/hash-api-key.ts +183 -79
  18. package/.framework/functions/_shared/logging.ts +562 -224
  19. package/.framework/functions/_shared/middleware.ts +47 -44
  20. package/.framework/functions/_shared/permissions.ts +4 -0
  21. package/.framework/functions/admin-data.ts +51 -28
  22. package/.framework/functions/ai-agents.ts +10 -6
  23. package/.framework/functions/api-keys.ts +301 -122
  24. package/.framework/functions/apps.ts +63 -29
  25. package/.framework/functions/cil-ingest.ts +48 -15
  26. package/.framework/functions/debug-auth.ts +14 -8
  27. package/.framework/functions/deliveries.ts +39 -12
  28. package/.framework/functions/embeddings.ts +149 -78
  29. package/.framework/functions/integration-outbound.ts +67 -27
  30. package/.framework/functions/integrations.ts +254 -127
  31. package/.framework/functions/logs.ts +273 -133
  32. package/.framework/functions/observability.ts +278 -148
  33. package/.framework/functions/pipeline-executions.ts +1 -1
  34. package/.framework/functions/pipelines.ts +14 -9
  35. package/.framework/functions/prompt-configs.ts +7 -4
  36. package/.framework/functions/roles.ts +8 -5
  37. package/.framework/functions/security.ts +30 -17
  38. package/.framework/functions/system-cron.ts +240 -127
  39. package/.framework/functions/tests.ts +7 -6
  40. package/.framework/functions/timers.ts +310 -107
  41. package/.framework/functions/triggers.ts +28 -13
  42. package/.framework/functions/types.ts +13 -10
  43. package/.framework/migrations/069_log_stats_window.sql +54 -0
  44. package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
  45. package/.framework/migrations/071_timer_interval_keys.sql +96 -0
  46. package/.framework/migrations/072_slug_autofill.sql +77 -0
  47. package/.framework/migrations/073_seed_member_roles.sql +26 -0
  48. package/.framework/migrations/074_app_route_prefix_domains.sql +168 -0
  49. package/.framework/migrations/075_security_definer_grants.sql +157 -0
  50. package/.framework/src/apps/admin/index.tsx +1141 -775
  51. package/.framework/src/components/ErrorBoundary.tsx +136 -0
  52. package/.framework/src/components/admin/AdminListPage.tsx +81 -73
  53. package/.framework/src/components/admin/AdminSidebar.tsx +88 -79
  54. package/.framework/src/components/admin/EntitySelect.tsx +181 -0
  55. package/.framework/src/components/admin/PageInstructions.tsx +86 -127
  56. package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
  57. package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
  58. package/.framework/src/components/layout/Sidebar.tsx +300 -177
  59. package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
  60. package/.framework/src/components/runtime/DataHeader.tsx +96 -48
  61. package/.framework/src/components/runtime/DataListPage.tsx +3 -26
  62. package/.framework/src/components/runtime/DataStats.tsx +10 -10
  63. package/.framework/src/components/runtime/DataTable.tsx +12 -10
  64. package/.framework/src/components/ui/sheet.tsx +24 -26
  65. package/.framework/src/components/ui/textarea.tsx +74 -48
  66. package/.framework/src/contexts/AppContext.tsx +5 -12
  67. package/.framework/src/contexts/AuthContext.tsx +17 -9
  68. package/.framework/src/hooks/useApps.ts +18 -22
  69. package/.framework/src/hooks/useEntityList.ts +12 -9
  70. package/.framework/src/hooks/useListSchema.ts +108 -58
  71. package/.framework/src/instructions/README.md +74 -0
  72. package/.framework/src/instructions/accounts.md +97 -0
  73. package/.framework/src/instructions/ai-agents.md +69 -0
  74. package/.framework/src/instructions/alerts.md +80 -0
  75. package/.framework/src/instructions/api-keys.md +87 -0
  76. package/.framework/src/instructions/apps.md +77 -0
  77. package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
  78. package/.framework/src/instructions/concepts/apps-and-renderers.md +228 -0
  79. package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
  80. package/.framework/src/instructions/concepts/automation.md +186 -0
  81. package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
  82. package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
  83. package/.framework/src/instructions/concepts/design-schema.md +152 -0
  84. package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
  85. package/.framework/src/instructions/concepts/observability.md +116 -0
  86. package/.framework/src/instructions/concepts/permissions.md +150 -0
  87. package/.framework/src/instructions/concepts/runtime-records.md +111 -0
  88. package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
  89. package/.framework/src/instructions/concepts/spine-way.md +172 -0
  90. package/.framework/src/instructions/deliveries.md +59 -0
  91. package/.framework/src/instructions/guide/00-orientation.md +106 -0
  92. package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
  93. package/.framework/src/instructions/guide/02-project-map.md +147 -0
  94. package/.framework/src/instructions/guide/03-domain-model.md +223 -0
  95. package/.framework/src/instructions/guide/04-first-app.md +227 -0
  96. package/.framework/src/instructions/guide/05-glossary.md +183 -0
  97. package/.framework/src/instructions/integrations.md +96 -0
  98. package/.framework/src/instructions/internal/cil-markers.md +83 -0
  99. package/.framework/src/instructions/internal/docs-contract.md +158 -0
  100. package/.framework/src/instructions/invites.md +60 -0
  101. package/.framework/src/instructions/kb.md +80 -0
  102. package/.framework/src/instructions/logs.md +77 -0
  103. package/.framework/src/instructions/notifications.md +77 -0
  104. package/.framework/src/instructions/observability.md +61 -0
  105. package/.framework/src/instructions/operations/deployment.md +115 -0
  106. package/.framework/src/instructions/operations/migrations.md +125 -0
  107. package/.framework/src/instructions/operations/security-checklist.md +170 -0
  108. package/.framework/src/instructions/operations/troubleshooting.md +170 -0
  109. package/.framework/src/instructions/operations/upgrade.md +116 -0
  110. package/.framework/src/instructions/people.md +91 -0
  111. package/.framework/src/instructions/pipeline-executions.md +62 -0
  112. package/.framework/src/instructions/pipelines.md +78 -0
  113. package/.framework/src/instructions/prompts.md +95 -0
  114. package/.framework/src/instructions/reference/api/admin-data.md +162 -0
  115. package/.framework/src/instructions/reference/api/auth.md +113 -0
  116. package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
  117. package/.framework/src/instructions/reference/app-manifest.md +184 -0
  118. package/.framework/src/instructions/reference/cli.md +124 -0
  119. package/.framework/src/instructions/reference/database.md +132 -0
  120. package/.framework/src/instructions/reference/design-schema.md +280 -0
  121. package/.framework/src/instructions/reference/env-vars.md +133 -0
  122. package/.framework/src/instructions/reference/frontend-sdk.md +207 -0
  123. package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
  124. package/.framework/src/instructions/reference/functions/admin-data.md +197 -0
  125. package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
  126. package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
  127. package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
  128. package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
  129. package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
  130. package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
  131. package/.framework/src/instructions/reference/functions/apps.md +140 -0
  132. package/.framework/src/instructions/reference/functions/auth.md +99 -0
  133. package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
  134. package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
  135. package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
  136. package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
  137. package/.framework/src/instructions/reference/functions/index.md +103 -0
  138. package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
  139. package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
  140. package/.framework/src/instructions/reference/functions/integrations.md +130 -0
  141. package/.framework/src/instructions/reference/functions/invites.md +182 -0
  142. package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
  143. package/.framework/src/instructions/reference/functions/kb.md +166 -0
  144. package/.framework/src/instructions/reference/functions/logs.md +141 -0
  145. package/.framework/src/instructions/reference/functions/observability.md +105 -0
  146. package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
  147. package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
  148. package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
  149. package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
  150. package/.framework/src/instructions/reference/functions/roles.md +121 -0
  151. package/.framework/src/instructions/reference/functions/security.md +140 -0
  152. package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
  153. package/.framework/src/instructions/reference/functions/system.md +106 -0
  154. package/.framework/src/instructions/reference/functions/tests.md +97 -0
  155. package/.framework/src/instructions/reference/functions/timers.md +117 -0
  156. package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
  157. package/.framework/src/instructions/reference/functions/triggers.md +140 -0
  158. package/.framework/src/instructions/reference/functions/types.md +146 -0
  159. package/.framework/src/instructions/reference/seeds.md +126 -0
  160. package/.framework/src/instructions/reference/shared-modules.md +127 -0
  161. package/.framework/src/instructions/reference/spine-config.md +114 -0
  162. package/.framework/src/instructions/roles.md +80 -0
  163. package/.framework/src/instructions/runtime-collaboration.md +106 -0
  164. package/.framework/src/instructions/runtime-detail.md +70 -0
  165. package/.framework/src/instructions/runtime-list.md +77 -0
  166. package/.framework/src/instructions/security.md +67 -0
  167. package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
  168. package/.framework/src/instructions/tasks/add-a-role.md +96 -0
  169. package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
  170. package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
  171. package/.framework/src/instructions/tasks/add-a-type.md +151 -0
  172. package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
  173. package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
  174. package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
  175. package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
  176. package/.framework/src/instructions/tasks/document-your-app.md +117 -0
  177. package/.framework/src/instructions/tasks/package-and-install-an-app.md +136 -0
  178. package/.framework/src/instructions/tasks/register-an-app.md +137 -0
  179. package/.framework/src/instructions/tasks/test-your-code.md +108 -0
  180. package/.framework/src/instructions/tasks/write-a-function.md +132 -0
  181. package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
  182. package/.framework/src/instructions/testing.md +59 -0
  183. package/.framework/src/instructions/timers.md +84 -0
  184. package/.framework/src/instructions/triggers.md +69 -0
  185. package/.framework/src/instructions/types.md +93 -0
  186. package/.framework/src/lib/app-mount.ts +88 -0
  187. package/.framework/src/pages/NotFoundPage.tsx +62 -31
  188. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
  189. package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
  190. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
  191. package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
  192. package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
  193. package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
  194. package/.framework/src/pages/admin/AppsPage.tsx +104 -66
  195. package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
  196. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
  197. package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
  198. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
  199. package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
  200. package/.framework/src/pages/admin/LogsPage.tsx +144 -76
  201. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
  202. package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
  203. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
  204. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
  205. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
  206. package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
  207. package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
  208. package/.framework/src/pages/admin/RolesPage.tsx +86 -43
  209. package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
  210. package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
  211. package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
  212. package/.framework/src/pages/admin/TimersPage.tsx +90 -62
  213. package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
  214. package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
  215. package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
  216. package/.framework/src/pages/admin/TypesPage.tsx +90 -48
  217. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
  218. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
  219. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
  220. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
  221. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
  222. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
  223. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
  224. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
  225. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
  226. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
  227. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
  228. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
  229. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
  230. package/.framework/src/pages/auth/LoginPage.tsx +3 -2
  231. package/.framework/src/pages/auth/RegisterPage.tsx +16 -8
  232. package/.framework/templates/agent/AGENTS.md +167 -0
  233. package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
  234. package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
  235. package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
  236. package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
  237. package/.framework/templates/agent/skills/spine-install-app/SKILL.md +79 -0
  238. package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
  239. package/.framework/templates/agent/skills/spine-new-app/SKILL.md +79 -0
  240. package/.framework/templates/agent/skills/spine-new-function/SKILL.md +71 -0
  241. package/.framework/templates/agent/skills/spine-new-type/SKILL.md +72 -0
  242. package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
  243. package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
  244. package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
  245. package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
  246. package/.framework/templates/project.json +4 -1
  247. package/.framework/tests/unit/account-scoping-gates.test.ts +394 -0
  248. package/.framework/tests/unit/agent-files.test.ts +355 -0
  249. package/.framework/tests/unit/agent-runner.test.ts +479 -44
  250. package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
  251. package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
  252. package/.framework/tests/unit/app-mount.test.ts +80 -0
  253. package/.framework/tests/unit/bootstrap.test.ts +242 -0
  254. package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
  255. package/.framework/tests/unit/debug-auth.test.ts +38 -0
  256. package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
  257. package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
  258. package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
  259. package/.framework/tests/unit/logging-app-id.test.ts +75 -0
  260. package/.framework/tests/unit/security-definer-grants.test.ts +154 -0
  261. package/.framework/tests/unit/system-context-denial.test.ts +145 -0
  262. package/.framework/tests/unit/system-cron.test.ts +240 -0
  263. package/.framework/tests/unit/timers.test.ts +159 -0
  264. package/README.md +125 -166
  265. package/config/tsconfig.cli.json +2 -2
  266. package/package.json +15 -4
  267. package/templates/project/package-lock.json +2 -2
  268. package/.framework/docs/admin-routes.md +0 -76
  269. package/.framework/docs/api-docs-progress.md +0 -38
  270. package/.framework/docs/api-governance.md +0 -146
  271. package/.framework/docs/api-testing-results.md +0 -212
  272. package/.framework/docs/assembly-launch-guide.md +0 -138
  273. package/.framework/docs/audit-results.md +0 -590
  274. package/.framework/docs/db-api-inventory.md +0 -95
  275. package/.framework/docs/gap-remediation-backlog.md +0 -103
  276. package/.framework/docs/ui-adoption-verification.md +0 -111
  277. package/.framework/docs/ui-api-coverage.md +0 -84
  278. package/.framework/docs/v2-compatibility-audit.md +0 -228
  279. package/.framework/mcp/index.ts +0 -133
  280. package/.framework/mcp/load-env.ts +0 -60
  281. package/.framework/mcp/shared/app-manifest.ts +0 -275
  282. package/.framework/mcp/shared/db.ts +0 -477
  283. package/.framework/mcp/shared/kb.ts +0 -118
  284. package/.framework/mcp/tools/architect.ts +0 -431
  285. package/.framework/mcp/tools/cil/context.ts +0 -345
  286. package/.framework/mcp/tools/cil/graph.ts +0 -242
  287. package/.framework/mcp/tools/cil/ingest.ts +0 -1217
  288. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
  289. package/.framework/mcp/tools/cil/pipeline.ts +0 -767
  290. package/.framework/mcp/tools/cil/project.ts +0 -791
  291. package/.framework/mcp/tools/cil/retrieval.ts +0 -336
  292. package/.framework/mcp/tools/cil/search-core.ts +0 -454
  293. package/.framework/mcp/tools/cil/search.ts +0 -97
  294. package/.framework/mcp/tools/cil/suggest.ts +0 -186
  295. package/.framework/mcp/tools/cil/validate.ts +0 -1369
  296. package/.framework/mcp/tools/kb/delete.ts +0 -139
  297. package/.framework/mcp/tools/kb/index.ts +0 -52
  298. package/.framework/mcp/tools/kb/ingest.ts +0 -84
  299. package/.framework/mcp/tools/kb/list-types.ts +0 -102
  300. package/.framework/mcp/tools/kb/publish.ts +0 -100
  301. package/.framework/mcp/tools/kb/reindex.ts +0 -86
  302. package/.framework/mcp/tools/kb/revoke.ts +0 -85
  303. package/.framework/mcp/tools/kb/search.ts +0 -101
  304. package/.framework/mcp/tools/kb/upsert.ts +0 -125
  305. 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"]