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,253 @@
1
+ ---
2
+ title: Install and first run
3
+ audience: developers, agents
4
+ kind: guide
5
+ verified_against: d0c49d4
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - .framework/cli/commands/init.ts
9
+ - .framework/cli/lib/project-files.ts
10
+ - .framework/templates/project.json
11
+ - .framework/templates/spine.config.neutral.json
12
+ - .framework/cli/commands/migrate.ts
13
+ - .framework/cli/commands/bootstrap.ts
14
+ - .env.example
15
+ - netlify.toml
16
+ - scripts/dev-netlify.sh
17
+ - scripts/netlify-dev-wrapper.sh
18
+ - config/vite.config.ts
19
+ - .framework/public/_redirects
20
+ - .framework/src/App.tsx
21
+ - .framework/src/pages/SetupPage.tsx
22
+ - .framework/src/pages/auth/RegisterPage.tsx
23
+ - .framework/functions/invites.ts
24
+ - .framework/migrations/052_registration_security.sql
25
+ ---
26
+
27
+ # Install and first run
28
+
29
+ Prerequisites: Node ≥ 22.13 and npm ≥ 10 (recorded in `.spine-manifest.json`
30
+ by init), a Supabase project, and (for local dev) the Netlify CLI — pinned as a
31
+ devDependency, so `npm install` puts it in `node_modules`.
32
+
33
+ ## Step 1 — scaffold
34
+
35
+ ```bash
36
+ npm install spine-framework
37
+ npx spine-framework init # or: init <dir>
38
+ ```
39
+
40
+ Tarball/pre-release installs work the same way: `npm i
41
+ ./spine-framework-<ver>.tgz` — `init` keeps the `file:` spec in
42
+ `package.json` rather than overwriting it with a registry version.
43
+
44
+ `init` (`.framework/cli/commands/init.ts`) copies the framework-owned file set
45
+ declared by `.framework/templates/project.json` into the target directory:
46
+
47
+ - **`.framework/`** — `cli`, `functions`, `migrations`, `public`, `schemas`,
48
+ `scripts`, `seeds`, `src`, `tests`, `docs`, `templates`, plus `index.html`
49
+ and `README.md`.
50
+ - **`config/`** — `vite.config.ts`, the tsconfig family, `tailwind.config.cjs`,
51
+ `postcss.config.cjs`, `components.json`.
52
+ - **Root files** — the shipped `scripts/*.sh` / `*.mts` / `verify-install.ts`
53
+ set, `bin/`, `vitest.config.ts`, `.env.example`, `LICENSE.md`.
54
+ - **`custom/`** — the empty workspace `init` creates for your code:
55
+ `custom/apps`, `custom/functions`, `custom/components`,
56
+ `custom/migrations`, `custom/tests`.
57
+ - **Generated files** — `package.json` (your name, framework scripts, the
58
+ framework's dependency set inlined, plus an exact `spine-framework` pin),
59
+ `package-lock.json` (when the package ships the verified lock template),
60
+ `.gitignore`, `netlify.toml`, a neutral `spine.config.json`, and the frozen
61
+ `.spine-manifest.json` integrity manifest.
62
+ - **Agent assets** — `AGENTS.md` (the framework-owned rules block between the
63
+ `spine-framework:begin/end` markers — refreshed on upgrade; keep your own
64
+ notes outside the markers) and `.devin/skills/spine-*/` task skills, synced
65
+ from `.framework/templates/agent/`. These are hashed into the manifest's
66
+ `agent_files` map rather than `files`.
67
+
68
+ `init` is deliberately file-only: it does **not** run `npm install`, write
69
+ `.env`, or touch any database or network resource. It refuses to run into a
70
+ directory that already has `.framework/` — that is what
71
+ `npx spine-framework upgrade` is for.
72
+
73
+ ## Step 2 — `.env`
74
+
75
+ ```bash
76
+ cp .env.example .env
77
+ ```
78
+
79
+ Required for a working install (`.env.example` has the full list):
80
+
81
+ | Variable | Used by |
82
+ |---|---|
83
+ | `VITE_SUPABASE_URL`, `VITE_SUPABASE_ANON_KEY` | the browser app (`.framework/src/lib/supabase.ts`) |
84
+ | `SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`, `SUPABASE_ANON_KEY` | Netlify functions (service-role + user-scoped clients) |
85
+ | `SUPABASE_DB_PASSWORD` | `npx spine-framework migrate` — connects directly to `db.<project-ref>.supabase.co:5432` as `postgres` (`.framework/cli/commands/migrate.ts`) |
86
+ | `APP_BASE_URL` | invite links and auth redirects (`http://localhost:8888` in dev) |
87
+
88
+ Where to find them: the URL and both keys are on one page — **Supabase
89
+ Dashboard → Project Settings → API Keys** (older dashboards: Settings →
90
+ API / Data API); `SUPABASE_DB_PASSWORD` is under **Project Settings →
91
+ Database**. Current dashboards issue new-style keys: the **Publishable
92
+ key** (`sb_publishable_…`) is the anon key and a **Secret key**
93
+ (`sb_secret_…`) is the service-role key — set `*_ANON_KEY` /
94
+ `SUPABASE_SERVICE_ROLE_KEY` to them directly. Legacy `anon`/`service_role`
95
+ JWTs work identically (verified end-to-end on a hosted project:
96
+ `signInWithPassword`, `auth.admin.createUser`, and PostgREST all accept the
97
+ new formats).
98
+
99
+ Optional but worth knowing early: `RESEND_API_KEY` (invite/notification
100
+ email), `OPENAI_API_KEY` (AI stage types), `VITE_TURNSTILE_SITE_KEY` (bot
101
+ protection on auth pages), `SCHEDULER_API_KEY` (system-cron HTTP guard), and
102
+ `INTERNAL_INVOKE_SECRET` — **required for trigger-dispatched pipelines**: if it
103
+ is unset, triggers write a `queued` execution row but the pipeline runner is
104
+ never invoked (`.framework/functions/_shared/trigger-engine.ts`).
105
+
106
+ ## Step 3 — install deps and verify
107
+
108
+ ```bash
109
+ npm install
110
+ npm run verify # scripts/verify-integrity.sh — checks the tree against .spine-manifest.json
111
+ ```
112
+
113
+ Expect `npm audit` findings — the pinned dependency set (mostly the
114
+ `netlify-cli` devDependency tree) carries known advisories, and the count
115
+ jumps between the tarball-only install and the full post-init install. The
116
+ shipped `package-lock.json` template is the verified set: do **not** run
117
+ `npm audit fix`, which moves pinned versions the manifest was generated
118
+ against. Findings are tracked upstream, not per-project.
119
+
120
+ ## Step 4 — migrate the database
121
+
122
+ ```bash
123
+ npx spine-framework migrate
124
+ ```
125
+
126
+ This applies every `.framework/migrations/*.sql` file (and anything in
127
+ `custom/migrations/`, unless `--framework-only`) in order, recording each in a
128
+ `_spine_migrations` table so reruns are idempotent (`--dry-run` shows pending
129
+ files without applying them). File numbering is non-contiguous — retired
130
+ migrations are removed from the package rather than renumbered, so gaps are
131
+ expected and only lexical order matters. The core migration seeds the `system_admin`
132
+ role, the `spine-core` and `admin` apps, the `spine-system` account, and the
133
+ core runtime types (`.framework/migrations/003_core_system_data.sql`,
134
+ `.framework/migrations/011_spine_system_account.sql`).
135
+
136
+ ## Step 5 — run it
137
+
138
+ ```bash
139
+ npm run dev:netlify
140
+ ```
141
+
142
+ `dev:netlify` runs `npm run assemble` first (via `predev:netlify`) and then
143
+ `scripts/dev-netlify.sh`, which cleans stale processes and launches the pinned
144
+ `netlify dev`. Netlify serves the site on **http://localhost:8888** and starts
145
+ the Vite dev server on 3001 via `scripts/netlify-dev-wrapper.sh`.
146
+ **Wait for the "Local dev server ready" banner** — the first `dev:netlify`
147
+ run bundles ~80 functions and can take a couple of minutes before the banner
148
+ appears; this is normal, not a hang. Early requests during function bundling
149
+ can crash the dev server (noted in `scripts/dev-netlify.sh`).
150
+
151
+ Ports are **fixed**: `netlify dev` must bind 8888 and Vite 3001 — both are
152
+ set in manifest-protected files (`netlify.toml` `[dev]` port/targetPort,
153
+ `config/vite.config.ts`), and there is no supported alternate-port
154
+ configuration. Moving only one side breaks the `/api` proxy and can
155
+ silently cross-connect two Spine projects on the same machine. Check the
156
+ ports are free first (`lsof -i :8888 -i :3001`): `dev-netlify.sh` cleans up
157
+ stale processes it owns but will not kill an unrelated server holding the
158
+ port — a second Spine project's dev stack is the usual culprit; stop that
159
+ one yourself.
160
+
161
+ Ignore `Failed to fetch AI Gateway token … Unauthorized` in `netlify dev`
162
+ output — that is the Netlify CLI's own AI feature probing your Netlify
163
+ account, unrelated to Spine.
164
+
165
+ Two URL spaces matter:
166
+
167
+ - `/api/*` → `/.netlify/functions/:splat`. In dev this is the Vite proxy to
168
+ `localhost:8888` (`config/vite.config.ts`); in production it is the
169
+ `_redirects` rule in `.framework/public/_redirects`.
170
+ - Everything else → the React SPA.
171
+
172
+ `npm run dev` alone starts *only* Vite on 3001 — fine for frontend work, but
173
+ `/api/*` calls still proxy to 8888, so functions need `netlify dev` running.
174
+
175
+ ## First admin — browser-free bootstrap (recommended for automation)
176
+
177
+ ```bash
178
+ npx spine-framework bootstrap --email you@example.com --password '<pick-one>'
179
+ ```
180
+
181
+ This is the scriptable path (`S-002`): it creates the first `system_admin`
182
+ person bound to the `spine-system` account — the same row shape the
183
+ `handle_new_auth_user` trigger writes on registration — creates a confirmed
184
+ auth user through `auth.admin.createUser(email_confirm: true)`, and mints a
185
+ `sk_` API key, all without a browser. The raw key is printed **once**; only
186
+ its PBKDF2 hash is stored. `--scope <scope>` (repeatable) narrows the key —
187
+ the default `*:*` resolves to the `system_admin` role on the machine
188
+ principal. Omit `--email`/`--password` and the person record is created
189
+ DB-only (no UI login; the minted key still works for `x-api-key` callers).
190
+ The command is idempotent: when a `system_admin` already exists in
191
+ `spine-system` it skips person creation and just mints another key
192
+ (`.framework/cli/commands/bootstrap.ts`).
193
+
194
+ ## First login — what actually happens
195
+
196
+ Alternatively, register in the browser. The real flow, as the code
197
+ implements it:
198
+
199
+ 1. An unauthenticated visitor is redirected to `/login`
200
+ (`.framework/src/App.tsx`). If `VITE_SETUP_MODE=true` is set, the `/` route
201
+ instead shows a static `SetupPage` listing the same steps as this page
202
+ (`.framework/src/pages/SetupPage.tsx`).
203
+ 2. Go to `/register` and create an account. **The first user to register gets
204
+ `system_admin`**: the `handle_new_auth_user` database trigger detects an
205
+ empty `people` table and binds the new person to the `spine-system` account
206
+ with the `system_admin` role
207
+ (`.framework/migrations/052_registration_security.sql`). If the seeds are
208
+ missing, registration raises instead of creating a rootless user.
209
+ 3. Non-first, non-invited signups get **no account and no role** — placement
210
+ happens when `complete-registration` runs the server-side RPC
211
+ (`.framework/functions/invites.ts`). An authenticated user without an
212
+ account is routed to `/register?resume=1` until placement finishes, never
213
+ to a 404 (`.framework/src/App.tsx`).
214
+ 4. After login, a `system_admin` lands on `/spine-framework/admin` — the
215
+ schema-driven admin app from `.framework/src/apps/admin/index.tsx`. Other
216
+ users land on the first app their role can see, or `NoAppPage` when nothing
217
+ is routable.
218
+
219
+ ## Giving your agent access
220
+
221
+ The verified path for letting an agent (or any machine caller) reach the
222
+ runtime API:
223
+
224
+ 1. **Bootstrap an admin + key** — one step, no browser: `npx
225
+ spine-framework bootstrap` (see "First admin" above) both creates the
226
+ `system_admin` and prints a `sk_` key. The browser alternative: register
227
+ at `/register` (first user becomes `system_admin`), then create a scoped
228
+ key under **Admin → Configs → API Keys**. Either way the raw key is shown
229
+ **once** — copy it immediately (`.framework/functions/api-keys.ts`).
230
+ 2. **Give the key to the agent** as the environment variable `SPINE_API_KEY`.
231
+ Agents send `x-api-key: sk_…` on `/api/*` requests; the header resolves to
232
+ a machine principal carrying the key's scopes and account binding
233
+ (`.framework/functions/_shared/principal.ts`). Turnstile is not in this
234
+ path — bot protection only guards the human auth pages.
235
+
236
+ **Caveat:** for the browser path, Supabase **email confirmation must be
237
+ off** in the project (Auth → Providers), or the first registrant cannot sign
238
+ in without access to a real inbox. `bootstrap` is unaffected — it creates
239
+ the auth user with `email_confirm: true` through the service role.
240
+
241
+ ## Gaps
242
+
243
+ - **`npx spine-framework dev` runs the same flow as the package scripts** —
244
+ `scripts/assemble.sh`, then Vite via `config/vite.config.ts` (`--netlify`
245
+ for the full `netlify dev` stack on :8888). `npm run dev` /
246
+ `npm run dev:netlify` remain the canonical entry points.
247
+ - **`bootstrap` covers first-run provisioning only.** Subsequent admins are
248
+ added through the invite flow in the admin app (or another `bootstrap`
249
+ run, which skips person creation and only mints a new key).
250
+ - **Timers only tick under the Netlify scheduler.** `trigger-scheduler` is a
251
+ scheduled function (`* * * * *` in `netlify.toml`); pipelines triggered by
252
+ timers do not run without it, and trigger dispatch additionally needs
253
+ `INTERNAL_INVOKE_SECRET` (see Step 2).
@@ -0,0 +1,147 @@
1
+ ---
2
+ title: Anatomy of an installed project
3
+ audience: developers, agents
4
+ kind: guide
5
+ verified_against: f69c37d
6
+ verified_on: 2026-10-29
7
+ source_files:
8
+ - .framework/templates/project.json
9
+ - .framework/cli/commands/init.ts
10
+ - .framework/cli/commands/upgrade.ts
11
+ - .framework/cli/lib/project-files.ts
12
+ - scripts/checksum-manifest.mts
13
+ - scripts/verify-integrity.sh
14
+ - scripts/assemble.sh
15
+ - scripts/assemble-frontend.sh
16
+ - scripts/assemble-functions.sh
17
+ - config/vite.config.ts
18
+ - netlify.toml
19
+ - .framework/cli/commands/create-app.ts
20
+ - .framework/cli/commands/install-app.ts
21
+ - .framework/src/components/CustomAppLoader.tsx
22
+ - .framework/schemas/spine.config.schema.json
23
+ ---
24
+
25
+ # Anatomy of an installed project
26
+
27
+ A Spine project is two concentric layers: a **sealed framework layer** the
28
+ package owns and overwrites on upgrade, and a **customer layer** the framework
29
+ never writes to.
30
+
31
+ ```
32
+ my-project/
33
+ ├─ .framework/ # SEALED — framework source, vendored by init/upgrade
34
+ │ ├─ cli/ # the spine-framework CLI source
35
+ │ ├─ functions/ # Netlify functions (the whole API surface)
36
+ │ ├─ migrations/ # SQL migrations applied by `migrate`
37
+ │ ├─ public/ # static assets + _redirects
38
+ │ ├─ schemas/ # spine.config.schema.json
39
+ │ ├─ scripts/ seeds/ docs/ templates/
40
+ │ ├─ src/ # React frontend + admin app + this book
41
+ │ └─ tests/
42
+ ├─ config/ # SEALED — build config (vite, tsconfig, tailwind…)
43
+ ├─ scripts/ # SEALED — assemble/verify/dev shell scripts
44
+ ├─ bin/ # SEALED — spine-framework bin shims
45
+ ├─ custom/ # YOURS — apps, functions, components, migrations, tests
46
+ ├─ .assembled/ # GENERATED — build output, never edit
47
+ ├─ .spine-manifest.json # GENERATED — frozen integrity manifest
48
+ ├─ spine.config.json # YOURS — branding + registration policy
49
+ ├─ netlify.toml # mixed — framework blocks + your custom_* sections
50
+ ├─ package.json # merged — framework scripts/deps + your own
51
+ └─ .env # YOURS — secrets; never written by the framework
52
+ ```
53
+
54
+ ## The sealed layer
55
+
56
+ The file set is declared in `.framework/templates/project.json`
57
+ (`framework_dirs`, `framework_files`, `config_files`, `root_scripts`, `bin`)
58
+ and every protected file's sha256 is recorded in `.spine-manifest.json` — the
59
+ protected trees are `.framework`, `config`, `scripts`, and `bin`
60
+ (`scripts/checksum-manifest.mts`, `PROTECTED_DIRS`).
61
+
62
+ - `npm run verify` (`scripts/verify-integrity.sh` → `scripts/verify-manifest.mts`)
63
+ re-hashes the tree and fails on drift. `SPINE_INTEGRITY=warn` downgrades to
64
+ warnings.
65
+ - `npx spine-framework upgrade` re-syncs the sealed layer to the
66
+ `spine-framework` version installed in `node_modules`
67
+ (`.framework/cli/commands/upgrade.ts`). It first verifies the tree against
68
+ the manifest and **aborts on any locally modified or missing protected file**
69
+ unless `--force` is passed — so do not edit `.framework/`, `config/`,
70
+ `scripts/`, or `bin/`; changes there are destroyed on the next upgrade
71
+ anyway.
72
+ - Deletions on upgrade are confined to `.framework/`; sealed files dropped
73
+ upstream outside it are left in place with a warning.
74
+
75
+ ## `custom/` — your code
76
+
77
+ `init` creates `custom/apps`, `custom/functions`, `custom/components`,
78
+ `custom/migrations`, and `custom/tests` (`.framework/cli/commands/init.ts`).
79
+ Everything in it is yours: not integrity-tracked, never touched by upgrade.
80
+
81
+ - **Custom apps** live at `custom/apps/<slug>/`.
82
+ `npx spine-framework create-app <slug>` scaffolds `manifest.json`,
83
+ `index.tsx`, and `components/`, then inserts the `apps` row with
84
+ `renderer: 'custom'` (`.framework/cli/commands/create-app.ts`).
85
+ `CustomAppLoader` resolves the UI via
86
+ `import.meta.glob('../../../custom/apps/*/index.tsx')`
87
+ (`.framework/src/components/CustomAppLoader.tsx`), and the Vite alias
88
+ `@custom` points at `custom/apps` (`config/vite.config.ts`).
89
+ - **Custom functions** live at `custom/functions/` or inside an app at
90
+ `custom/apps/<slug>/functions/`; assembly merges them into the flat
91
+ functions directory and hard-fails on basename collisions with framework
92
+ functions (`scripts/assemble-functions.sh`). Name yours `custom_*`.
93
+ - **Custom migrations** in `custom/migrations/` run with
94
+ `npx spine-framework migrate` (skip them with `--framework-only`).
95
+ - **Packaged apps** installed via `npx spine-framework install-app <pkg>` also
96
+ land under `custom/apps/<slug>/`; their `manifest.json` can seed types,
97
+ roles, pipelines, and registration policy into the database
98
+ (`.framework/cli/commands/install-app.ts`).
99
+
100
+ ## `.assembled/` — build output
101
+
102
+ `npm run assemble` (`scripts/assemble.sh`) produces `.assembled/` fresh on
103
+ every dev start and build:
104
+
105
+ - `.assembled/src` — the framework frontend plus each `custom/apps/<slug>/`
106
+ copied verbatim (never basename-flattened), plus the fixed-up `index.html`
107
+ (`scripts/assemble-frontend.sh`). Vite builds and serves from here.
108
+ - `.assembled/netlify/functions` — framework + custom functions flattened into
109
+ the single directory Netlify requires (`netlify.toml`
110
+ `functions.directory`); duplicate basenames are a hard error, not a
111
+ last-wins overwrite (`scripts/assemble-functions.sh`).
112
+
113
+ Never edit `.assembled/` — it is regenerated and deleted freely.
114
+
115
+ ## `.spine-manifest.json` — the integrity contract
116
+
117
+ Written by `init` and regenerated by `upgrade`
118
+ (`.framework/cli/lib/project-files.ts` → `writeFrozenManifest`): the package
119
+ version (`framework_version`), the framework-owned dependency list, a tree
120
+ digest, and a sha256 per protected file. It is the input to `npm run verify`
121
+ and to upgrade's local-modification check.
122
+
123
+ ## `spine.config.json` — project runtime config
124
+
125
+ Customer-owned; `init` seeds the neutral template
126
+ (`.framework/templates/spine.config.neutral.json`) and
127
+ `install-app`/`update-db-app` merge per-app registration policy into it
128
+ (`.framework/cli/commands/install-app.ts`). It carries `branding` and the
129
+ `registration` block that drives signup routing/role assignment — schema at
130
+ `.framework/schemas/spine.config.schema.json`. Upgrade never writes it.
131
+
132
+ ## `netlify.toml` and `package.json` — mixed ownership
133
+
134
+ - `netlify.toml`: framework blocks are rewritten on upgrade, but
135
+ `[functions."custom_*"]` sections are treated as app-owned and preserved
136
+ verbatim (`.framework/cli/lib/project-files.ts` → `splitNetlifyToml` /
137
+ `renderNetlifyToml`). Scheduled custom functions belong there.
138
+ - `package.json`: framework-owned scripts and dependencies are merged in and
139
+ `spine-framework` pinned exactly; your own scripts and deps are preserved.
140
+ Upgrade removes a dependency only if the previous framework version owned it
141
+ and the new one does not.
142
+
143
+ ## `.env` — yours, always
144
+
145
+ No framework command writes `.env`; it is gitignored and excluded from the
146
+ file set (`.framework/templates/project.json` `exclude_globs`). `.env.example`
147
+ ships as the documented baseline.
@@ -0,0 +1,223 @@
1
+ ---
2
+ title: The Spine domain model
3
+ audience: developers, agents
4
+ kind: guide
5
+ verified_against: f69c37d
6
+ verified_on: 2026-10-29
7
+ source_files:
8
+ - .framework/migrations/001_core_schema.sql
9
+ - .framework/migrations/003_core_system_data.sql
10
+ - .framework/migrations/004_core_rpc_and_broker.sql
11
+ - .framework/migrations/020_schema_reconciliation.sql
12
+ - .framework/functions/admin-data.ts
13
+ - .framework/functions/_shared/permissions.ts
14
+ - .framework/functions/_shared/principal.ts
15
+ - .framework/functions/_shared/trigger-engine.ts
16
+ - .framework/functions/_shared/pipeline-runner.ts
17
+ - .framework/functions/system-cron.ts
18
+ - .framework/functions/trigger-scheduler.ts
19
+ - .framework/functions/pipeline-runner-background.ts
20
+ - .framework/src/App.tsx
21
+ - .framework/src/components/app-shell/GenericAppShell.tsx
22
+ - .framework/src/components/CustomAppLoader.tsx
23
+ - .framework/src/contexts/AppContext.tsx
24
+ - .framework/src/hooks/useApps.ts
25
+ - netlify.toml
26
+ ---
27
+
28
+ # The Spine domain model
29
+
30
+ Everything in Spine is one of about ten primitives. Once you can name them and
31
+ say how they connect, the whole system — admin UI, APIs, automation — is just
32
+ compositions of the diagram below.
33
+
34
+ ```
35
+ ┌──────────────────────── IDENTITY ────────────────────────┐
36
+ │ │
37
+ auth.users (Supabase) │ account ──< people >── role │
38
+ │ │ (tenant, (human, (permission │
39
+ │ auth_uid │ tree via auth_uid, set; system_admin │
40
+ ▼ │ parent_id account_id, is the seeded root) │
41
+ JWT / x-api-key ──────┤ + account_ role_id) │
42
+ │ │ paths) │
43
+ ▼ └──────────────────────────┬─────────────────────────────┘
44
+ principal ─────────── every request resolves one │
45
+ (anonymous | human | machine | system) │
46
+ ▼
47
+ ┌──────────────────────── SCHEMA ─────────────────────────┐
48
+ │ type (kind + slug) → design_schema → validation_schema │
49
+ │ fields · views · record_permissions · scope │
50
+ └──────────────────────────┬─────────────────────────────┘
51
+ │ stamped at create
52
+ ▼
53
+ ┌──────────────────────── RECORDS ────────────────────────┐
54
+ │ items · threads · messages · links · attachments · │
55
+ │ watchers (+ accounts, people as records) │
56
+ │ system columns + data jsonb + stamped schemas │
57
+ └──────────────────────────┬─────────────────────────────┘
58
+ │ CRUD via /api/admin-data
59
+ ┌──────────────────────── APPS ◄────────────┘ renders / consumes
60
+ │ generic | custom | none │
61
+ │ app row: slug, route_prefix, renderer, ▼
62
+ │ nav_items, roles ┌────────────────────── AUTOMATION ───────┐
63
+ └───────────────┬────────────────┤ triggers (event) → pipelines (stages) │
64
+ │ seeds/owns │ timers (cron/interval/once) ──┘ │
65
+ ▼ │ integrations (adapters+creds) │
66
+ ┌──────────────────────── AI ────┤ ai_agents · prompt_configs · │
67
+ │ embeddings (pgvector search) │ embeddings │
68
+ └────────────────────────────────┴──────────────┬────────────────────────┘
69
+ ▼
70
+ ┌──────────────────────── OBSERVE ────────────────────────┐
71
+ │ logs · observability · pipeline_executions · │
72
+ │ trigger_executions · webhook_deliveries · │
73
+ │ api_key_usage_logs · audit │
74
+ └─────────────────────────────────────────────────────────┘
75
+ ```
76
+
77
+ ## Identity: account → person → role → principal
78
+
79
+ - **Account** (`public.accounts`) — the tenant. Accounts form a hierarchy via
80
+ `parent_id` + the `account_paths` closure table; the seeded `spine-system`
81
+ account is the platform root
82
+ (`.framework/migrations/011_spine_system_account.sql`).
83
+ - **Person** (`public.people`) — a human user, bound to `auth.users` by
84
+ `auth_uid`, placed in one `account_id`, holding one `role_id`. Like every
85
+ runtime record, a person row also carries `type_id` and `data`.
86
+ - **Role** (`public.roles`) — a named permission set with a globally unique
87
+ `slug`. `system_admin` is seeded, protected, and bypasses record-level
88
+ checks (`.framework/migrations/003_core_system_data.sql`).
89
+ - **Principal** — the *resolved* identity of a request, computed per call by
90
+ `.framework/functions/_shared/principal.ts`: `x-api-key` header → machine
91
+ principal (verified against `api_keys` hash), internal-invoke headers →
92
+ cron/trigger/system, `Authorization: Bearer` JWT → human principal, anything
93
+ else → anonymous. Handlers receive it as `ctx.principal` with
94
+ `ctx.accountId`.
95
+
96
+ ## Schema: type → design_schema → validation_schema
97
+
98
+ A **type** (`public.types`) is the schema for a record kind. `kind` selects the
99
+ runtime table — `item`, `thread`, `message`, `link`, `attachment`, `watcher`,
100
+ `account`, `person` — and `(kind, slug)` is unique. Its `design_schema` JSON
101
+ carries:
102
+
103
+ - `fields` — each with `data_type`, `label`, `required`, and optional
104
+ `system` flag.
105
+ - `views` — `default_list` / `default_detail` consumed by the generic UI.
106
+ - `record_permissions` — per-role base grant of `create`/`read`/`update`/
107
+ `delete`; `fields.*.permissions` exists only to *override* that base per
108
+ field (`.framework/functions/_shared/permissions.ts`).
109
+ - `scope` — `account` (tenant data, the default) or `platform` (record is
110
+ re-anchored to the `spine-system` account at create).
111
+
112
+ `validation_schema` is **generated from `design_schema`** on every save
113
+ (`.framework/functions/types.ts` via `_shared/schema-utils.ts`) — never
114
+ hand-edit it.
115
+
116
+ ## Records: the runtime tables
117
+
118
+ Six typed record tables — `items`, `threads`, `messages`, `links`,
119
+ `attachments`, `watchers` — plus `accounts` and `people` in the same shape
120
+ (`.framework/migrations/001_core_schema.sql`). Every record has:
121
+
122
+ - **system columns** — `id`, `type_id`, `account_id`, `app_id`, `created_at`,
123
+ `updated_at`, `created_by`, `is_active`, plus kind-specific ones
124
+ (`items.title/status`, `threads.target_type/target_id`,
125
+ `messages.thread_id/sequence`, `links.source_*/target_*`,
126
+ `attachments.storage_path`, `watchers.person_id`).
127
+ - **`data` jsonb** — where all non-system schema fields live. Convention:
128
+ `system: true` fields read from `record.<field>`; everything else from
129
+ `record.data.<field>` (see `GenericDetailPage` splitting on
130
+ `fieldDef.system` in `.framework/src/components/app-shell/GenericDetailPage.tsx`).
131
+ - **stamped `design_schema` + `validation_schema`** — copied from the type at
132
+ create time by `admin-data` (`create` in `.framework/functions/admin-data.ts`),
133
+ so the record is the source of truth for its own permissions even if the
134
+ type changes later.
135
+
136
+ All CRUD flows through `/api/admin-data` (`action=list|get|stats|create|
137
+ update|remove`, `entity=<table>`; GET for reads, POST/PATCH/DELETE for writes). The handler maps entity → kind
138
+ (`ENTITY_TO_KIND`), resolves `type_slug`/`type_id`, evaluates record/field
139
+ permissions, writes, then fires create/update/delete triggers.
140
+
141
+ ## Apps: registry + two renderers
142
+
143
+ An **app** (`public.apps`) is a registered application: `slug`,
144
+ `route_prefix`, `renderer`, `nav_items`, `min_role`/`required_roles`,
145
+ `config`, `is_active`, `is_system`. The authenticated router
146
+ (`.framework/src/App.tsx`) mounts every routable app at its `route_prefix`:
147
+
148
+ - **`renderer: 'generic'`** — `GenericAppShell` builds the UI *from data*: the
149
+ sidebar comes from `nav_items`, and each nav item with a `type_slug` gets
150
+ list/new/detail routes rendered by `GenericListPage`/`GenericDetailPage`
151
+ straight from the type's `views`
152
+ (`.framework/src/components/app-shell/GenericAppShell.tsx`).
153
+ - **`renderer: 'custom'`** — `CustomAppLoader` lazy-loads
154
+ `custom/apps/<slug>/index.tsx` (falling back to
155
+ `.framework/src/apps/<slug>/index.tsx`)
156
+ (`.framework/src/components/CustomAppLoader.tsx`). Custom apps render their
157
+ own pages but still use `/api/admin-data` for record CRUD.
158
+ - **`renderer: 'none'`** — registry-only; not routable.
159
+
160
+ ## Automation: triggers → pipelines, timers → pipelines
161
+
162
+ - **Pipeline** (`public.pipelines`) — a `stages` array executed in order by
163
+ `runPipeline` (`.framework/functions/_shared/pipeline-runner.ts`). Each
164
+ stage's `stage_type` resolves to a `public.actions` row or a built-in
165
+ handler (`update_item`, `create_record`, `http_request`,
166
+ `send_notification`, `send_email`, `run_pipeline`, `query_items`,
167
+ `agent_inference`, `search_knowledge`, `generate_embeddings`,
168
+ `revoke_embeddings`, `kb_ingest`, `kb_revoke`, `create_interaction`).
169
+ Every run writes a `pipeline_executions` row.
170
+ - **Trigger** (`public.triggers`) — `event_type` + `pipeline_id` (+ optional
171
+ `config` filters). `admin-data` calls `fireCreate/Update/DeleteTriggers`
172
+ after each write; events are named `<entity>_<created|updated|deleted>`
173
+ (e.g. `item_created`). A match enqueues a `pipeline_executions` row and
174
+ dispatches to the `pipeline-runner-background` function over HTTP — which
175
+ requires `INTERNAL_INVOKE_SECRET` to be set
176
+ (`.framework/functions/_shared/trigger-engine.ts`).
177
+ - **Timer** (`public.timers`) — `timer_type` (`interval` | `cron` | `once`) +
178
+ `pipeline_id` + schedule in `config`. The scheduled function
179
+ `trigger-scheduler` (every minute, `netlify.toml`) runs `system-cron`,
180
+ which calls the `get_due_timers` RPC and executes each due timer's pipeline
181
+ under a `timer:*` machine principal
182
+ (`.framework/functions/system-cron.ts`).
183
+
184
+ ## Integrations and AI
185
+
186
+ - **Integration** (`public.integrations`) — a named adapter + `config` +
187
+ `credentials` (`{"env_var": "NAME"}` resolved in the function environment,
188
+ or a literal `{"value": …}`). Inbound webhooks arrive via
189
+ `integration-routes`; outbound calls go through `integration-outbound`,
190
+ which records each attempt in `public.webhook_deliveries` (the deliveries
191
+ ledger — `system-cron` retries pending ones via
192
+ `.framework/functions/_shared/retry-deliveries.ts`).
193
+ - **AI agent** (`public.ai_agents`) — a model/prompt/tool config invocable via
194
+ `/api/ai-agents?action=run` or the `agent_inference` pipeline stage.
195
+ **Prompt config** (`public.prompt_configs`) — named, versioned prompt
196
+ templates agents and stages reference.
197
+ - **Embedding** (`public.embeddings`) — pgvector vectors with the
198
+ `match_embeddings` / `search_similar_embeddings` RPCs
199
+ (`.framework/migrations/004_core_rpc_and_broker.sql`), powering semantic
200
+ search and the `search_knowledge` stage type.
201
+
202
+ ## Observability: everything leaves a trail
203
+
204
+ `public.logs` (per-account log stream), `public.observability` (metrics),
205
+ `pipeline_executions` + `trigger_executions` (automation history),
206
+ `webhook_deliveries` (outbound attempts), `api_key_usage_logs` (machine
207
+ principal usage), and audit events emitted by `emitAudit` on privileged
208
+ actions. The admin UI surfaces them under Observability, Deliveries, and
209
+ Executions (`.framework/functions/logs.ts`,
210
+ `.framework/functions/observability.ts`,
211
+ `.framework/functions/pipeline-executions.ts`,
212
+ `.framework/functions/deliveries.ts`).
213
+
214
+ ## Where to go next
215
+
216
+ - Entity deep-dives: [types](../types.md), [apps](../apps.md),
217
+ [roles](../roles.md), [pipelines](../pipelines.md),
218
+ [triggers](../triggers.md), [timers](../timers.md),
219
+ [integrations](../integrations.md), [ai-agents](../ai-agents.md),
220
+ [prompts](../prompts.md), [api-keys](../api-keys.md),
221
+ [deliveries](../deliveries.md).
222
+ - Build something: [04-first-app.md](./04-first-app.md).
223
+ - Terminology: [05-glossary.md](./05-glossary.md).