spine-framework 0.4.3 → 0.5.0-rc.4

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 (320) 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/migrate.ts +36 -30
  8. package/.framework/cli/commands/migrations.ts +16 -56
  9. package/.framework/cli/commands/upgrade.ts +35 -0
  10. package/.framework/cli/commands/validate-schema.ts +147 -0
  11. package/.framework/cli/context.ts +223 -110
  12. package/.framework/cli/index.ts +6 -0
  13. package/.framework/cli/lib/project-files.ts +241 -1
  14. package/.framework/functions/_shared/agent-runner.ts +1000 -81
  15. package/.framework/functions/_shared/cil.ts +2 -1
  16. package/.framework/functions/_shared/db.ts +3 -6
  17. package/.framework/functions/_shared/hash-api-key.ts +183 -79
  18. package/.framework/functions/_shared/kb.ts +61 -7
  19. package/.framework/functions/_shared/logging.ts +562 -224
  20. package/.framework/functions/_shared/message-sequence.ts +53 -0
  21. package/.framework/functions/_shared/middleware.ts +47 -44
  22. package/.framework/functions/_shared/pipeline-runner.ts +150 -37
  23. package/.framework/functions/_shared/principal.ts +9 -6
  24. package/.framework/functions/_shared/trigger-engine.ts +149 -40
  25. package/.framework/functions/admin-data.ts +48 -31
  26. package/.framework/functions/ai-agents.ts +103 -33
  27. package/.framework/functions/api-keys.ts +301 -122
  28. package/.framework/functions/apps.ts +43 -26
  29. package/.framework/functions/cil-ingest.ts +48 -15
  30. package/.framework/functions/debug-auth.ts +14 -8
  31. package/.framework/functions/deliveries.ts +39 -12
  32. package/.framework/functions/embeddings.ts +145 -76
  33. package/.framework/functions/integration-outbound.ts +67 -27
  34. package/.framework/functions/integrations.ts +254 -127
  35. package/.framework/functions/logs.ts +273 -133
  36. package/.framework/functions/observability.ts +277 -147
  37. package/.framework/functions/pipeline-executions.ts +1 -1
  38. package/.framework/functions/pipeline-runner-background.ts +120 -0
  39. package/.framework/functions/pipelines.ts +14 -9
  40. package/.framework/functions/prompt-configs.ts +7 -4
  41. package/.framework/functions/roles.ts +8 -5
  42. package/.framework/functions/security.ts +30 -17
  43. package/.framework/functions/system-cron.ts +250 -128
  44. package/.framework/functions/tests.ts +7 -6
  45. package/.framework/functions/timers.ts +310 -107
  46. package/.framework/functions/trigger-scheduler.ts +65 -5
  47. package/.framework/functions/triggers.ts +28 -13
  48. package/.framework/functions/types.ts +13 -10
  49. package/.framework/migrations/064_episode_leases.sql +196 -0
  50. package/.framework/migrations/065_execution_tables_updated_at.sql +20 -0
  51. package/.framework/migrations/066_episode_steal_thread_merge.sql +148 -0
  52. package/.framework/migrations/067_episode_lease_stale_steal.sql +93 -0
  53. package/.framework/migrations/068_cron_schedule_timer_rpcs.sql +251 -0
  54. package/.framework/migrations/069_log_stats_window.sql +54 -0
  55. package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
  56. package/.framework/migrations/071_timer_interval_keys.sql +96 -0
  57. package/.framework/migrations/072_slug_autofill.sql +77 -0
  58. package/.framework/migrations/073_seed_member_roles.sql +26 -0
  59. package/.framework/schemas/spine.config.schema.json +62 -0
  60. package/.framework/src/App.tsx +3 -1
  61. package/.framework/src/apps/admin/index.tsx +1141 -775
  62. package/.framework/src/components/ErrorBoundary.tsx +136 -0
  63. package/.framework/src/components/admin/AdminListPage.tsx +81 -73
  64. package/.framework/src/components/admin/AdminSidebar.tsx +92 -81
  65. package/.framework/src/components/admin/EntitySelect.tsx +181 -0
  66. package/.framework/src/components/admin/PageInstructions.tsx +86 -127
  67. package/.framework/src/components/app-shell/GenericAppShell.tsx +3 -1
  68. package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
  69. package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
  70. package/.framework/src/components/auth/TurnstileWidget.tsx +9 -6
  71. package/.framework/src/components/kb/KBArticleEditor.tsx +49 -6
  72. package/.framework/src/components/layout/Layout.tsx +4 -2
  73. package/.framework/src/components/layout/Sidebar.tsx +304 -179
  74. package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
  75. package/.framework/src/components/runtime/DataHeader.tsx +96 -48
  76. package/.framework/src/components/runtime/DataListPage.tsx +3 -26
  77. package/.framework/src/components/runtime/DataStats.tsx +10 -10
  78. package/.framework/src/components/runtime/DataTable.tsx +12 -10
  79. package/.framework/src/components/ui/sheet.tsx +24 -26
  80. package/.framework/src/components/ui/textarea.tsx +74 -48
  81. package/.framework/src/hooks/useBranding.ts +47 -0
  82. package/.framework/src/hooks/useEntityList.ts +12 -9
  83. package/.framework/src/hooks/useListSchema.ts +108 -58
  84. package/.framework/src/instructions/README.md +57 -0
  85. package/.framework/src/instructions/ai-agents.md +69 -0
  86. package/.framework/src/instructions/alerts.md +80 -0
  87. package/.framework/src/instructions/api-keys.md +87 -0
  88. package/.framework/src/instructions/apps.md +77 -0
  89. package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
  90. package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
  91. package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
  92. package/.framework/src/instructions/concepts/automation.md +186 -0
  93. package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
  94. package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
  95. package/.framework/src/instructions/concepts/design-schema.md +152 -0
  96. package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
  97. package/.framework/src/instructions/concepts/observability.md +116 -0
  98. package/.framework/src/instructions/concepts/permissions.md +150 -0
  99. package/.framework/src/instructions/concepts/runtime-records.md +111 -0
  100. package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
  101. package/.framework/src/instructions/concepts/spine-way.md +172 -0
  102. package/.framework/src/instructions/deliveries.md +59 -0
  103. package/.framework/src/instructions/guide/00-orientation.md +106 -0
  104. package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
  105. package/.framework/src/instructions/guide/02-project-map.md +147 -0
  106. package/.framework/src/instructions/guide/03-domain-model.md +223 -0
  107. package/.framework/src/instructions/guide/04-first-app.md +227 -0
  108. package/.framework/src/instructions/guide/05-glossary.md +183 -0
  109. package/.framework/src/instructions/integrations.md +96 -0
  110. package/.framework/src/instructions/internal/cil-markers.md +83 -0
  111. package/.framework/src/instructions/invites.md +60 -0
  112. package/.framework/src/instructions/kb.md +80 -0
  113. package/.framework/src/instructions/logs.md +77 -0
  114. package/.framework/src/instructions/observability.md +61 -0
  115. package/.framework/src/instructions/operations/deployment.md +115 -0
  116. package/.framework/src/instructions/operations/migrations.md +125 -0
  117. package/.framework/src/instructions/operations/security-checklist.md +148 -0
  118. package/.framework/src/instructions/operations/troubleshooting.md +170 -0
  119. package/.framework/src/instructions/operations/upgrade.md +116 -0
  120. package/.framework/src/instructions/pipeline-executions.md +62 -0
  121. package/.framework/src/instructions/pipelines.md +78 -0
  122. package/.framework/src/instructions/prompts.md +95 -0
  123. package/.framework/src/instructions/reference/api/admin-data.md +162 -0
  124. package/.framework/src/instructions/reference/api/auth.md +113 -0
  125. package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
  126. package/.framework/src/instructions/reference/app-manifest.md +150 -0
  127. package/.framework/src/instructions/reference/cli.md +124 -0
  128. package/.framework/src/instructions/reference/database.md +132 -0
  129. package/.framework/src/instructions/reference/design-schema.md +280 -0
  130. package/.framework/src/instructions/reference/env-vars.md +133 -0
  131. package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
  132. package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
  133. package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
  134. package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
  135. package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
  136. package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
  137. package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
  138. package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
  139. package/.framework/src/instructions/reference/functions/apps.md +140 -0
  140. package/.framework/src/instructions/reference/functions/auth.md +99 -0
  141. package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
  142. package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
  143. package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
  144. package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
  145. package/.framework/src/instructions/reference/functions/index.md +103 -0
  146. package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
  147. package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
  148. package/.framework/src/instructions/reference/functions/integrations.md +130 -0
  149. package/.framework/src/instructions/reference/functions/invites.md +182 -0
  150. package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
  151. package/.framework/src/instructions/reference/functions/kb.md +166 -0
  152. package/.framework/src/instructions/reference/functions/logs.md +141 -0
  153. package/.framework/src/instructions/reference/functions/observability.md +105 -0
  154. package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
  155. package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
  156. package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
  157. package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
  158. package/.framework/src/instructions/reference/functions/roles.md +121 -0
  159. package/.framework/src/instructions/reference/functions/security.md +140 -0
  160. package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
  161. package/.framework/src/instructions/reference/functions/system.md +106 -0
  162. package/.framework/src/instructions/reference/functions/tests.md +97 -0
  163. package/.framework/src/instructions/reference/functions/timers.md +117 -0
  164. package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
  165. package/.framework/src/instructions/reference/functions/triggers.md +140 -0
  166. package/.framework/src/instructions/reference/functions/types.md +146 -0
  167. package/.framework/src/instructions/reference/seeds.md +126 -0
  168. package/.framework/src/instructions/reference/shared-modules.md +127 -0
  169. package/.framework/src/instructions/reference/spine-config.md +114 -0
  170. package/.framework/src/instructions/roles.md +80 -0
  171. package/.framework/src/instructions/runtime-detail.md +70 -0
  172. package/.framework/src/instructions/runtime-list.md +77 -0
  173. package/.framework/src/instructions/security.md +67 -0
  174. package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
  175. package/.framework/src/instructions/tasks/add-a-role.md +96 -0
  176. package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
  177. package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
  178. package/.framework/src/instructions/tasks/add-a-type.md +151 -0
  179. package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
  180. package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
  181. package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
  182. package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
  183. package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
  184. package/.framework/src/instructions/tasks/test-your-code.md +108 -0
  185. package/.framework/src/instructions/tasks/write-a-function.md +132 -0
  186. package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
  187. package/.framework/src/instructions/testing.md +59 -0
  188. package/.framework/src/instructions/timers.md +82 -0
  189. package/.framework/src/instructions/triggers.md +69 -0
  190. package/.framework/src/instructions/types.md +93 -0
  191. package/.framework/src/lib/branding.ts +128 -0
  192. package/.framework/src/pages/NoAppPage.tsx +3 -1
  193. package/.framework/src/pages/NotFoundPage.tsx +62 -31
  194. package/.framework/src/pages/SetupPage.tsx +5 -2
  195. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
  196. package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
  197. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
  198. package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
  199. package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
  200. package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
  201. package/.framework/src/pages/admin/AppsPage.tsx +104 -66
  202. package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
  203. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
  204. package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
  205. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
  206. package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
  207. package/.framework/src/pages/admin/LogsPage.tsx +144 -76
  208. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
  209. package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
  210. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
  211. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
  212. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
  213. package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
  214. package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
  215. package/.framework/src/pages/admin/RolesPage.tsx +86 -43
  216. package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
  217. package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
  218. package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
  219. package/.framework/src/pages/admin/TimersPage.tsx +90 -62
  220. package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
  221. package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
  222. package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
  223. package/.framework/src/pages/admin/TypesPage.tsx +90 -48
  224. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
  225. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
  226. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
  227. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
  228. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
  229. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
  230. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
  231. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
  232. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
  233. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
  234. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
  235. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
  236. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
  237. package/.framework/src/pages/auth/AuthConfirmPage.tsx +3 -1
  238. package/.framework/src/pages/auth/ForgotPasswordPage.tsx +3 -1
  239. package/.framework/src/pages/auth/LoginPage.tsx +4 -2
  240. package/.framework/src/pages/auth/RegisterPage.tsx +3 -1
  241. package/.framework/templates/agent/AGENTS.md +150 -0
  242. package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
  243. package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
  244. package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
  245. package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
  246. package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
  247. package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
  248. package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
  249. package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
  250. package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
  251. package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
  252. package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
  253. package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
  254. package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
  255. package/.framework/templates/project.json +5 -1
  256. package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
  257. package/.framework/tests/unit/agent-files.test.ts +355 -0
  258. package/.framework/tests/unit/agent-runner.test.ts +496 -47
  259. package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
  260. package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
  261. package/.framework/tests/unit/bootstrap.test.ts +242 -0
  262. package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
  263. package/.framework/tests/unit/debug-auth.test.ts +38 -0
  264. package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
  265. package/.framework/tests/unit/episode-lease.test.ts +695 -0
  266. package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
  267. package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
  268. package/.framework/tests/unit/kb-ingest-lease.test.ts +19 -0
  269. package/.framework/tests/unit/logging-app-id.test.ts +75 -0
  270. package/.framework/tests/unit/pipeline-runner-background.test.ts +120 -0
  271. package/.framework/tests/unit/pipeline-runner.test.ts +153 -1
  272. package/.framework/tests/unit/principal-cache.test.ts +15 -0
  273. package/.framework/tests/unit/system-context-denial.test.ts +145 -0
  274. package/.framework/tests/unit/system-cron.test.ts +240 -0
  275. package/.framework/tests/unit/timers.test.ts +159 -0
  276. package/.framework/tests/unit/trigger-engine.test.ts +278 -91
  277. package/.framework/tests/unit/trigger-scheduler.test.ts +78 -0
  278. package/README.md +125 -166
  279. package/config/tsconfig.cli.json +2 -2
  280. package/netlify.toml +5 -0
  281. package/package.json +15 -4
  282. package/templates/project/package-lock.json +2 -2
  283. package/.framework/docs/admin-routes.md +0 -76
  284. package/.framework/docs/api-docs-progress.md +0 -38
  285. package/.framework/docs/api-governance.md +0 -146
  286. package/.framework/docs/api-testing-results.md +0 -212
  287. package/.framework/docs/assembly-launch-guide.md +0 -138
  288. package/.framework/docs/audit-results.md +0 -590
  289. package/.framework/docs/db-api-inventory.md +0 -95
  290. package/.framework/docs/gap-remediation-backlog.md +0 -103
  291. package/.framework/docs/ui-adoption-verification.md +0 -111
  292. package/.framework/docs/ui-api-coverage.md +0 -84
  293. package/.framework/docs/v2-compatibility-audit.md +0 -228
  294. package/.framework/mcp/index.ts +0 -133
  295. package/.framework/mcp/load-env.ts +0 -60
  296. package/.framework/mcp/shared/app-manifest.ts +0 -275
  297. package/.framework/mcp/shared/db.ts +0 -477
  298. package/.framework/mcp/shared/kb.ts +0 -118
  299. package/.framework/mcp/tools/architect.ts +0 -431
  300. package/.framework/mcp/tools/cil/context.ts +0 -345
  301. package/.framework/mcp/tools/cil/graph.ts +0 -242
  302. package/.framework/mcp/tools/cil/ingest.ts +0 -1217
  303. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
  304. package/.framework/mcp/tools/cil/pipeline.ts +0 -767
  305. package/.framework/mcp/tools/cil/project.ts +0 -791
  306. package/.framework/mcp/tools/cil/retrieval.ts +0 -336
  307. package/.framework/mcp/tools/cil/search-core.ts +0 -454
  308. package/.framework/mcp/tools/cil/search.ts +0 -97
  309. package/.framework/mcp/tools/cil/suggest.ts +0 -186
  310. package/.framework/mcp/tools/cil/validate.ts +0 -1369
  311. package/.framework/mcp/tools/kb/delete.ts +0 -139
  312. package/.framework/mcp/tools/kb/index.ts +0 -52
  313. package/.framework/mcp/tools/kb/ingest.ts +0 -84
  314. package/.framework/mcp/tools/kb/list-types.ts +0 -102
  315. package/.framework/mcp/tools/kb/publish.ts +0 -100
  316. package/.framework/mcp/tools/kb/reindex.ts +0 -86
  317. package/.framework/mcp/tools/kb/revoke.ts +0 -85
  318. package/.framework/mcp/tools/kb/search.ts +0 -101
  319. package/.framework/mcp/tools/kb/upsert.ts +0 -125
  320. package/.framework/mcp/tools/observability.ts +0 -510
@@ -0,0 +1,96 @@
1
+ ---
2
+ title: Integrations
3
+ audience: both
4
+ kind: entity
5
+ verified_against: e13127d
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - .framework/functions/integrations.ts
9
+ - .framework/functions/integration-outbound.ts
10
+ - .framework/functions/integration-routes.ts
11
+ - .framework/functions/_shared/resolve-credentials.ts
12
+ - .framework/src/pages/admin/IntegrationsPage.tsx
13
+ - .framework/src/pages/admin/IntegrationDetailPage.tsx
14
+ ---
15
+
16
+ ## What this is for
17
+
18
+ An **integration** connects Spine to an external service (OpenAI, Resend, a generic HTTP endpoint, a database, ...). The record stores the provider, runtime `config` (including which adapter handles calls), and `credentials`. Pipelines and app code reference the integration by slug.
19
+
20
+ ## Fields and settings
21
+
22
+ - **Name** *(required)* — display name. The slug is **derived from it** server-side (`OpenAI` → `openai`); pass `slug` in the body only to override.
23
+ - **Type** *(required)* — select: `webhook`, `api`, `database`, `file`, `custom`. Categorizes the integration; the create form pre-fills sensible `config`/`credentials` templates per type.
24
+ - **Provider** *(required)* — free-text provider name (e.g. `openai`, `resend`, `postgres`).
25
+ - **Version** — string, default `1.0.0`.
26
+ - **Config (JSON)** — adapter and runtime settings. The adapter is named **here**, not as a top-level field: `config.outbound_adapter` (or `config.inbound_adapter` for inbound webhooks) points at an adapter module such as `adapters/openai-outbound`.
27
+ - **Credentials (JSON)** — secrets keyed by field name, each `{ "source": "env_var" | "value", "value": "..." }`. `source: "env_var"` resolves the named env var inside the function runtime; `source: "value"` stores the literal secret in the DB. The credential field callers read defaults to `api_token`.
28
+ - **Configured** — computed, read-only. `is_configured` is re-derived on every save from `credentials` (all entries must resolve); the UI shows it as Configured/Pending.
29
+ - **App ID** — select, optional. Owning app; blank = account-scoped.
30
+ - **Active** — boolean. Inactive integrations fail closed — callers get an error, not a fallback.
31
+ - **Description / Metadata** — optional notes and free-form data.
32
+
33
+ **Downstream effects**
34
+
35
+ - `env_var` credentials are resolved inside the function runtime — the variable must exist in the deployed env or calls fail at request time (`credential_env_missing`), not at save time. `source: "value"` persists the literal secret — prefer `env_var` for anything real.
36
+ - An absent or explicitly-empty (`source: "value"`, `value: ""`) credential entry means "call without auth" — the outbound broker sends no credential and the adapter decides whether one is required (the seeded `generic-http` integration works unauthenticated out of the box this way).
37
+ - Built-in outbound adapters: `adapters/openai-outbound`, `adapters/generic-webhook-outbound`, `adapters/resend-outbound`. Any other adapter path is dynamically imported — a typo saves fine but fails on first call.
38
+ - Outbound calls create a `webhook_deliveries` row (`pending`, `max_attempts` default 3 or `config.retry_policy.max_attempts`) and show up under Deliveries.
39
+ - Apps declare `integration_deps`; installing an app without its integrations leaves features broken until the records exist.
40
+ - The list/detail APIs use `adminDb` for system admins — integrations exist per account and per system scope.
41
+
42
+ ## Minimal configuration
43
+
44
+ ```json
45
+ {
46
+ "name": "OpenAI",
47
+ "integration_type": "api",
48
+ "provider": "openai",
49
+ "is_active": true,
50
+ "config": {
51
+ "outbound_adapter": "adapters/openai-outbound",
52
+ "model": "gpt-4o"
53
+ },
54
+ "credentials": { "api_token": { "source": "env_var", "value": "OPENAI_API_KEY" } }
55
+ }
56
+ ```
57
+
58
+ ## Full configuration
59
+
60
+ ```json
61
+ {
62
+ "name": "Outbound webhook",
63
+ "integration_type": "api",
64
+ "provider": "custom",
65
+ "version": "1.2.0",
66
+ "is_active": true,
67
+ "config": {
68
+ "outbound_adapter": "adapters/generic-webhook-outbound",
69
+ "base_url": "https://hooks.example.com",
70
+ "timeout_ms": 10000,
71
+ "retry_policy": { "max_attempts": 5 }
72
+ },
73
+ "credentials": { "api_token": { "source": "env_var", "value": "ACME_HOOK_TOKEN" } },
74
+ "metadata": { "owner": "platform" }
75
+ }
76
+ ```
77
+
78
+ ## Example
79
+
80
+ A support app lists `integration_deps: ["openai"]` — the AI agents resolve the `openai` integration by slug for model calls (credential field `api_token`), and a second integration (`config.outbound_adapter: "adapters/generic-webhook-outbound"`) delivers outbound ticket events, each attempt logged under Deliveries.
81
+
82
+ ## Core files
83
+
84
+ - `.framework/functions/integrations.ts` — API (list/get/create/update; `is_configured` computed on write; non-admin reads are sanitized)
85
+ - `.framework/functions/integration-outbound.ts` — outbound broker (adapter registry, delivery rows, retry math)
86
+ - `.framework/functions/integration-routes.ts` — inbound webhook entry
87
+ - `.framework/functions/_shared/resolve-credentials.ts` — `env_var`/`value` credential resolution
88
+ - `.framework/src/pages/admin/IntegrationsPage.tsx` / `IntegrationDetailPage.tsx` — admin UI (per-type config templates on the detail form)
89
+ - Table: `public.integrations`
90
+
91
+ ## Agent notes
92
+
93
+ - Credentials shape is `{ "api_token": { "source": "env_var", "value": "OPENAI_API_KEY" } }` — nested `source`/`value` objects, not `{ "env_var": "..." }`. The latter saves but never resolves.
94
+ - Never put real secrets in `credentials.*.value` with `source: "value"` in seeds or docs — always `env_var`.
95
+ - There is no top-level `adapter` or `configuration` column — the field is `config`, and the adapter lives at `config.outbound_adapter` / `config.inbound_adapter`.
96
+ - After changing credentials, the broker picks them up on the next call — no cache flush needed.
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: "CIL markers and generated doc tags"
3
+ audience: developers, agents
4
+ kind: reference
5
+ verified_against: f69c37d
6
+ verified_on: 2026-10-29
7
+ source_files:
8
+ - .framework/functions/_shared/pipeline-runner.ts
9
+ - .framework/scripts/cil-migrate-markers.ts
10
+ - AGENTS.md
11
+ ---
12
+
13
+ # CIL markers and generated doc tags
14
+
15
+ Files throughout `.framework/` — `src`, `functions`, `cli`, `migrations` —
16
+ carry dense comment blocks that look like this:
17
+
18
+ ```ts
19
+ // CIL[BEGIN stable_id="~/.framework/functions/_shared/pipeline-runner.ts:isuuid:function" type="function" identity="isUuid" parent="~/.framework/functions/_shared/pipeline-runner.ts"]
20
+ // CIL[DOC-MACRO purpose="isUuid function"]
21
+ // CIL[DOC-CONTRACT inputs="none" outputs="none" errors="none" side_effects="none"]
22
+ function isUuid(v: string | undefined | null): v is string { ... }
23
+ // CIL[END stable_id="~/.framework/functions/_shared/pipeline-runner.ts:isuuid:function"]
24
+ // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
25
+ ```
26
+
27
+ and generated JSDoc like this:
28
+
29
+ ```ts
30
+ /**
31
+ * Validates whether a given string is a properly formatted UUID.
32
+ * @inputSpec - v: string — the value to be checked
33
+ * @outputSpec v is string — true if the value is a valid UUID
34
+ * @sideEffects none
35
+ * @stability stable
36
+ * @calls UUID_RE.test
37
+ * @cil-generated
38
+ */
39
+ ```
40
+
41
+ ## What they are
42
+
43
+ **CIL** (Code Intelligence Layer) is the repository's internal
44
+ code-indexing tooling — it chunks the codebase into addressable units,
45
+ attaches generated documentation, and keeps embeddings in sync for semantic
46
+ search inside the monorepo. The comments are its on-disk metadata:
47
+
48
+ - `// CIL[BEGIN ...]` / `// CIL[END ...]` — delimit one tracked code chunk.
49
+ `stable_id` is the chunk's durable identity
50
+ (`<file>:<slug>:<kind>`); `type`, `identity`, and `parent` describe it.
51
+ - `// CIL[DOC-* …]` — generated or curated facts about the chunk:
52
+ `DOC-MACRO` (purpose), `DOC-RESPONSIBILITY`, `DOC-CONTEXT`
53
+ (module/layer/related files), `DOC-CONTRACT` (inputs/outputs/errors/
54
+ side_effects), `DOC-MICRO` (logic summary, notable decisions),
55
+ `DOC-CONFIDENCE` (pass + score), `DOC-STABILITY`, `DOC-AUDIENCE`,
56
+ `DOC-PARAM`, `DOC-NOTE`, and `DOC-LEARNING`.
57
+ - `// CIL[DOC-VECTOR type="…" content="…" status="…"]` — the payload that
58
+ becomes a search embedding (types include `context`, `blast_radius`,
59
+ `constraint`, `configuration`, `implementation_pattern`, `user_journey`).
60
+ `status="ready"` means it was generated; **`status="pending_human_input"`
61
+ means the field is intentionally blank until an author fills it** — it is
62
+ not an error and not a warning about the code itself.
63
+ - JSDoc tags `@macro`, `@micro`, `@inputSpec`, `@outputSpec`, `@sideEffects`,
64
+ `@calls`, `@seeAlso`, `@errorHandling`, `@stability`, `@module`, `@layer`,
65
+ `@audience`, `@cil-generated` mirror the same metadata in human-readable
66
+ form; `@cil-generated` marks text written by the pipeline rather than a
67
+ person.
68
+
69
+ ## What they mean for you
70
+
71
+ - **Safe to ignore.** They are comments; they have no runtime effect, no API
72
+ surface, and no effect on how you build apps on Spine. CIL is maintainer
73
+ tooling, not a framework feature.
74
+ - **Read them as hints, not truth.** `DOC-*` summaries and JSDoc are
75
+ generated interpretation — usually accurate, occasionally stale. The code
76
+ is the authority; treat the tags like any other doc comment.
77
+ - **In framework files, leave them in place.** Editing or deleting markers by
78
+ hand is harmless locally but gets rebuilt/renumbered the next time the
79
+ repo's marker tooling runs (see `cil:migrate-markers` /
80
+ `.framework/scripts/cil-migrate-markers.ts`). In your own `custom/` code
81
+ you're free to add or omit them — nothing requires them.
82
+ - The contributor-facing conventions live in the repo's `AGENTS.md`; this
83
+ page is only the legend for readers who meet the markers in shipped source.
@@ -0,0 +1,60 @@
1
+ ---
2
+ title: Invites & Access
3
+ audience: both
4
+ kind: entity
5
+ verified_against: e13127d
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - .framework/src/pages/admin/InvitesPage.tsx
9
+ - .framework/src/components/shared/InviteManager.tsx
10
+ - .framework/functions/invites.ts
11
+ ---
12
+
13
+ ## What this is for
14
+
15
+ **Invites & Access** (`/spine-framework/admin/access/invites`) manages how people join the account: generating invite links, tracking their status, re-sending or revoking them, and approving access requests. The admin page is scoped to the `system_admin` role; the shared `InviteManager` component underneath supports other role sets.
16
+
17
+ ## Fields and settings
18
+
19
+ - **Generate invite form** — name, email, and role picker (shown only when more than one role is allowed; here it is fixed to `system_admin`). Produces an `invite_url` copied to the clipboard: `{APP_BASE_URL}/register?t=<invite_token>`.
20
+ - **Invites table** — the person's name/email, assigned role, status, and actions: reinvite (new link), revoke, approve (access requests), block.
21
+ - **Status semantics** — `invited`/`pending` (link issued or request awaiting approval), `approved`, `active`/`claimed` (registered), `revoked` (`inactive`), `expired`, `blocked`. `kind` distinguishes `invite` from `access_request`.
22
+ - **Search + sortable columns** over the list from `action=list-invites` (filtered to the allowed role slugs).
23
+
24
+ **Downstream effects**
25
+
26
+ - `create-invite` inserts a stub `people` row carrying `invite_token` (16 chars) and `invite_expires_at` (7 days); the register flow consumes the token via `complete-registration` → `complete_registration_placement` RPC.
27
+ - Only `system_admin` (or an `*_admin` role on the account) can create invites; creating an invite for `role_slug: system_admin` is refused unless the caller is already `system_admin`.
28
+ - `revoke-invite` marks the person `inactive`, killing the unclaimed link; `reinvite` mints a fresh token/link. `block-invite`/`deny` handle abusive requests.
29
+ - Registration and account-creation calls are rate-limited per person and per IP.
30
+
31
+ ## Minimal configuration
32
+
33
+ Fill name + email → Generate → the invite URL lands on your clipboard; send it out of band. The invitee registers within 7 days or you reinvite.
34
+
35
+ ## Full configuration
36
+
37
+ The backing API (`/.netlify/functions/invites?action=`) also covers the public registration path and member management:
38
+
39
+ - `check-first-user`, `check-domain`, `validate-token`, `complete-registration` — anonymous signup flow
40
+ - `create-invite`, `list-invites`, `revoke-invite`, `reinvite`, `block-invite`
41
+ - `approve`, `deny` — access-request review
42
+ - `list-members`, `update-member`, `deactivate-member` — existing members
43
+
44
+ ## Example
45
+
46
+ An admin generates a `system_admin` invite for a new hire, pastes the link into chat. Until they register, the row shows `pending`; if the link is lost, Reinvite mints a new URL and invalidates the old token; if they never join, Revoke marks the stub `inactive`.
47
+
48
+ ## Core files
49
+
50
+ - `.framework/src/pages/admin/InvitesPage.tsx` — this page (scopes InviteManager to `system_admin`)
51
+ - `.framework/src/components/shared/InviteManager.tsx` — invite list/form/actions (reusable in other apps)
52
+ - `.framework/functions/invites.ts` — API (all actions above)
53
+ - Table: `public.people` (invite stub rows carry `invite_token`/`invite_expires_at`)
54
+
55
+ ## Agent notes
56
+
57
+ - The invite URL is shown/copied **once** at create/reinvite — the API never returns it again; a lost link means Reinvite, not retrieve.
58
+ - Invites expire after 7 days (`invite_expires_at`); expired rows show `expired` until reinvited or revoked.
59
+ - This admin page is hardcoded to `system_admin` invites; app-level member invites use the same `InviteManager` with a different `allowedRoles` set.
60
+ - Stub invite rows are real `people` rows — they are excluded from normal principal resolution until registration completes.
@@ -0,0 +1,80 @@
1
+ ---
2
+ title: Knowledge Base
3
+ audience: both
4
+ kind: entity
5
+ verified_against: e13127d
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - .framework/src/pages/admin/kb/KBAdminPage.tsx
9
+ - .framework/src/components/kb/KBArticleList.tsx
10
+ - .framework/src/components/kb/KBArticleEditor.tsx
11
+ - .framework/src/pages/admin/EmbeddingsPage.tsx
12
+ - .framework/src/pages/admin/EmbeddingDetailPage.tsx
13
+ - .framework/functions/kb.ts
14
+ - .framework/functions/embeddings.ts
15
+ - .framework/functions/admin-data.ts
16
+ ---
17
+
18
+ ## What this is for
19
+
20
+ The **KB** section (`/spine-framework/admin/kb/*`) covers three surfaces that share this doc:
21
+
22
+ - `kb/:typeSlug` — the article admin list/editor (`KBAdminPage`) for the KB item types `kb-spine-admin`, `kb-spine-internal`, `kb-spine-public`, `kb-account`. Articles are `items` records created/edited via `admin-data` and published via `kb`.
23
+ - `kb/embeddings` — the embedding record browser (`EmbeddingsPage`): every generated embedding row with its approval state.
24
+ - `kb/embeddings/:id` — single embedding detail (`EmbeddingDetailPage`): content, vector type, chunk index, model, approval/revocation timestamps, optional raw vector.
25
+
26
+ ## Fields and settings
27
+
28
+ **Articles** (`KBArticleList` / `KBArticleEditor`)
29
+
30
+ - **Type slug tabs** — the four KB type slugs above; articles are `items` records of that type.
31
+ - **List** — title, status, created date; search hits `/api/kb?action=search` (sources `['kb']`).
32
+ - **Editor** — schema-driven form from the type's `design_schema` (main fields + metadata sidebar); Save writes `admin-data` create/update; **Publish** additionally calls `/api/kb?action=publish`; Delete uses `admin-data` remove.
33
+ - **Modes** — `view` (read-only), `edit`, `new` via route (`:id`, `:id/edit`, `new`).
34
+
35
+ **Embeddings** (`EmbeddingsPage` / `EmbeddingDetailPage`)
36
+
37
+ - **List** — content/document/model search + sortable columns; status badge: `Revoked` (revoked_at set) > `Approved` (approved_at set) > `Pending`.
38
+ - **Detail** — document_id, vector_type, chunk_index, model_id, token count, content preview, approved/revoked timestamps, and a show-vector toggle for the raw embedding.
39
+
40
+ **Downstream effects**
41
+
42
+ - Articles are plain `items` records — they inherit the type's `record_permissions` and `validation_schema`; `kb?action=publish` handles the publishing step (ingest/indexing) on top.
43
+ - Embeddings are generated per type `design_schema.vector_types` (default `['semantic','structure']`) and feed `match_embeddings`/semantic search used by agents and `search_knowledge` pipeline stages.
44
+ - `embeddings` actions: list/get/create/update + `generate`, `revoke`, `approve`, `stats`, `batch-create`, `delete-document`, `cleanup`, `search-similar`, `search-semantic`. `revoke` stamps `revoked_at` (excluded from search); `approve` stamps `approved_at` and clears revocation.
45
+
46
+ ## Minimal configuration
47
+
48
+ Pick a KB type slug tab → New → fill the schema form → Save → Publish. The article is now searchable via `kb?action=search`.
49
+
50
+ ## Full configuration
51
+
52
+ ```jsonc
53
+ // article write — POST /api/admin-data?entity=items
54
+ { "type_id": "kb-account", "title": "Refund policy", "data": { "body": "..." } }
55
+ // publish — POST /api/kb?action=publish { "id": "<article uuid>" }
56
+ // regenerate vectors — POST /api/embeddings?action=generate { "item_id": "<article uuid>" }
57
+ // curate — POST /api/embeddings?action=approve|revoke { "id": "<embedding uuid>" }
58
+ ```
59
+
60
+ ## Example
61
+
62
+ A support team writes refund-policy articles under `kb-account`, publishes them, then checks `kb/embeddings` — the new chunks show `Pending` until reviewed; approving the good ones and revoking a stale `semantic` chunk changes what `search_knowledge` returns to the reply-drafting agent.
63
+
64
+ ## Core files
65
+
66
+ - `.framework/src/pages/admin/kb/KBAdminPage.tsx` — article page shell (list vs editor by mode)
67
+ - `.framework/src/components/kb/KBArticleList.tsx` / `KBArticleEditor.tsx` — list + schema-driven editor, publish call
68
+ - `.framework/src/pages/admin/EmbeddingsPage.tsx` / `EmbeddingDetailPage.tsx` — embedding browser/detail
69
+ - `.framework/functions/kb.ts` — `search`, `publish`, and KB pipeline actions
70
+ - `.framework/functions/embeddings.ts` — embedding CRUD + generate/approve/revoke/search
71
+ - `.framework/functions/admin-data.ts` — the underlying record CRUD
72
+ - Tables: `public.items` (articles), `public.embeddings` (vectors)
73
+
74
+ ## Agent notes
75
+
76
+ - `instructionKeyFor` maps every `kb/*` route to this doc — there is no separate `embeddings` page key.
77
+ - Articles are records, not files — edit them through this UI or `admin-data`, never direct table writes that skip validation/triggers.
78
+ - `Pending` embeddings still count toward `stats`; only `revoked_at` removes a vector from similarity search.
79
+ - Deleting an article does not cascade to its embedding rows — use `embeddings?action=delete-document` to clean up vectors for a removed document.
80
+ - Re-publish after large edits: publishing re-ingests; stale chunks otherwise linger until `generate`/`cleanup` runs.
@@ -0,0 +1,77 @@
1
+ ---
2
+ title: Logs
3
+ audience: both
4
+ kind: entity
5
+ verified_against: e13127d
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - .framework/src/pages/admin/LogsPage.tsx
9
+ - .framework/functions/logs.ts
10
+ - .framework/functions/_shared/logging.ts
11
+ - .framework/functions/system-cron.ts
12
+ - .framework/migrations/069_log_stats_window.sql
13
+ ---
14
+
15
+ ## What this is for
16
+
17
+ **Logs** (`/spine-framework/admin/observability/logs`) is the account's audit-trail and event-history viewer — every `emitLog`/`emitAudit`/`emitSpan`/`emitActivity` write lands in the `logs` table and shows up here. Use it to trace a request end-to-end (via `trace_id`), answer "who did what when", and debug trigger/pipeline/delivery failures.
18
+
19
+ ## Fields and settings
20
+
21
+ - **Stats cards** — Total Events, Event Types, Errors, User Actions over the current filter window (`/api/logs?action=stats`).
22
+ - **Search** — free text over message/actor fields; debounced 300ms.
23
+ - **Level** — `event_type` of the log row (error/audit/span/activity categories surface as selectable values from the stats payload).
24
+ - **Source / Source Type** — `action` and `target_type` of the row (e.g. `type.updated`, `item`).
25
+ - **Source ID / Actor ID / Trace ID** — UUID/prefix filters: `target_id`, `actor_id`, `trace_id`.
26
+ - **From / To dates** — `date_from`/`date_to`; defaults to the last 24h. Stats default to a 7-day window when no `date_from` is given.
27
+ - **Row click** — expands the row to show `details`, `metadata`, span info (`span_name`, `span_id`, `parent_span_id`, `duration_ms`, `outcome`).
28
+ - **Trace button** — clicking a `trace_id` filters the whole grid to that trace (all spans of one request).
29
+ - Paged at 100 rows per page; sortable columns (Time, Trace, Level, Source, Source Type, Source ID, Person, Message).
30
+
31
+ **Downstream effects**
32
+
33
+ - What gets written is gated by `system_settings` key `logging`: levels `off | timing | warnings | errors | all` (default `['timing','errors']`). Rows at unconfigured levels are dropped at write time — they never reach this page.
34
+ - Retention is `cleanup` with `days_to_keep` (default 30); `system-cron` runs `cleanup_old_logs` at 00:00 UTC. Debugging a week-old issue? Check before it ages out.
35
+ - `logs` is also a queryable `admin-data` entity, so pipelines and agents can read the same rows.
36
+ - The Observability dashboard and Security page both read this table (`threshold.breached` events, security signals).
37
+
38
+ ## Minimal configuration
39
+
40
+ Nothing to configure on the page itself. To see useful data, ensure the account's `system_settings.logging.levels` includes the level you need (e.g. `errors`), then filter:
41
+
42
+ ```
43
+ Level = error · From = <incident date> · Trace ID = <trace from a failed request>
44
+ ```
45
+
46
+ ## Full configuration
47
+
48
+ Combine all filters for a forensic query — e.g. every log row for one record by one person in a window:
49
+
50
+ ```
51
+ query = "ticket"
52
+ target_type = "items" · source_id = "<record uuid>"
53
+ actor_id = "<person uuid>" · trace_id = "<trace uuid>"
54
+ date_from = 2026-10-01 · date_to = 2026-10-30
55
+ ```
56
+
57
+ API equivalents: `/api/logs?action=account` (paged rows), `action=stats`, plus `target`, `person`, `search`, `cleanup` actions server-side.
58
+
59
+ ## Example
60
+
61
+ A user reports a failed save at 14:03. Open Logs, set From to that day, paste the `trace_id` from the error toast into Trace ID — the grid now shows the request's full span tree (`api.request` → `db.update` → `trigger.fired`), and the red `error` row's expanded `details` names the failing stage.
62
+
63
+ ## Core files
64
+
65
+ - `.framework/src/pages/admin/LogsPage.tsx` — this page
66
+ - `.framework/functions/logs.ts` — API (`account`, `target`, `person`, `stats`, `search`, `cleanup` actions)
67
+ - `.framework/functions/_shared/logging.ts` — `emitLog`, level resolution from `system_settings`
68
+ - `.framework/functions/_shared/audit.ts` / `.framework/functions/_shared/tracing.ts` — `emitAudit`/`emitSpan` writers, W3C trace context
69
+ - `.framework/functions/system-cron.ts` — daily `cleanup_old_logs` at 00:00 UTC
70
+ - Table: `public.logs`
71
+
72
+ ## Agent notes
73
+
74
+ - Empty page with active traffic almost always means log **levels** filter writes, not that nothing happened — check `system_settings.logging` first.
75
+ - `trace_id` is the fastest debugging primitive: every function request shares one, so one click reconstructs the whole call including trigger dispatch.
76
+ - System admins query across accounts via `adminDb`; everyone else sees only their account's rows.
77
+ - Cleanup is destructive and daily — export anything worth keeping before the 30-day default window closes.
@@ -0,0 +1,61 @@
1
+ ---
2
+ title: Observability Dashboard
3
+ audience: both
4
+ kind: entity
5
+ verified_against: e13127d
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - .framework/src/pages/admin/ObservabilityDashboard.tsx
9
+ - .framework/functions/observability.ts
10
+ - .framework/functions/logs.ts
11
+ - .framework/functions/_shared/logging.ts
12
+ ---
13
+
14
+ ## What this is for
15
+
16
+ The **Observability Dashboard** (`/spine-framework/admin/observability`, also `/observability/dashboard`) is the account's health console: event volume, error rate, latency percentiles, per-pipeline run stats, top actors, and recent threshold-alert breaches — all computed from the `logs` table and refreshed on an interval.
17
+
18
+ ## Fields and settings
19
+
20
+ - **Time range** — Last Hour / Last 24 Hours / Last 7 Days (`from`/`to` sent to every query; the volume chart buckets by minute/hour/day respectively).
21
+ - **Refresh interval** — auto-refetch every 10s / 30s / 1m, plus a manual Refresh Now button.
22
+ - **Stats cards** — Total Events, Error Rate (%), P95 Latency (ms, red above 2000ms), Pipelines with runs.
23
+ - **Charts** — Event Volume line chart (bucketed counts), error rate, latency percentiles (p50/p95/p99), per-pipeline success/failure/avg-duration, Top Actors (limit 5).
24
+ - **Recent alerts** — last 5 `threshold.breached` log events in the window (metric, threshold, actual value, time).
25
+
26
+ **Downstream effects**
27
+
28
+ - Everything derives from `public.logs` rows written by `emitLog`/`emitAudit`/`emitSpan` — if log levels drop a category (`system_settings.logging.levels`), it disappears from these charts too.
29
+ - Queries are account-scoped for normal users; `system_admin` principals get cross-account reads (`adminDb`).
30
+ - The metrics here are exactly what threshold alerts compare against (`error_rate`, `latency_percentiles`, `pipeline_stats` actions).
31
+ - This page is read-only — it writes nothing.
32
+
33
+ ## Minimal configuration
34
+
35
+ Open the page — defaults (24h range, 30s refresh) are sane for monitoring. There is nothing to configure.
36
+
37
+ ## Full configuration
38
+
39
+ The backing API exposes more than the charts use:
40
+
41
+ - `GET /api/observability?action=event_volume&from=&to=&bucket=minute|hour|day`
42
+ - `action=error_rate` · `action=latency_percentiles` · `action=pipeline_stats` · `action=top_actors&limit=` · `action=ai_support_metrics` · `action=cleanup` (POST)
43
+
44
+ ## Example
45
+
46
+ After deploying a new pipeline, set the range to Last Hour and refresh to 10s: Event Volume climbs with each run, the pipeline stats panel shows success vs failure counts and average duration, and a spike in the error-rate card correlates to the `error`-level rows you can drill into under Logs.
47
+
48
+ ## Core files
49
+
50
+ - `.framework/src/pages/admin/ObservabilityDashboard.tsx` — this page (recharts)
51
+ - `.framework/functions/observability.ts` — metrics API (all `action=` queries above)
52
+ - `.framework/functions/logs.ts` — the `threshold.breached` alert feed (`action=account&event=`)
53
+ - `.framework/functions/_shared/logging.ts` — the emit path and level gating that decides what reaches `logs`
54
+ - Table: `public.logs` (source of all charts)
55
+
56
+ ## Agent notes
57
+
58
+ - Flat charts with healthy traffic = log-level filtering, not broken metrics — the dashboard can only chart what `system_settings.logging.levels` allowed to be written.
59
+ - `system_admin` sees cross-account aggregates here; account members see only their own account.
60
+ - The 10s refresh is client-side polling — each tick re-runs all five metric queries; don't leave it open on a metered connection.
61
+ - Breach alerts shown here are read from `logs`, not from the alert records — see Threshold Alerts for the rules themselves.
@@ -0,0 +1,115 @@
1
+ ---
2
+ title: Netlify Deployment
3
+ audience: both
4
+ kind: reference
5
+ verified_against: e13127d
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - netlify.toml
9
+ - .framework/public/_redirects
10
+ - scripts/assemble.sh
11
+ - scripts/assemble-frontend.sh
12
+ - scripts/assemble-functions.sh
13
+ - config/vite.config.ts
14
+ - .env.example
15
+ - .framework/functions/system.ts
16
+ ---
17
+
18
+ # Netlify Deployment
19
+
20
+ Spine deploys as a single Netlify site: a Vite-built SPA in `dist/` plus a
21
+ flat directory of functions in `.assembled/netlify/functions`, backed by a
22
+ Supabase (Postgres) project. Both halves are produced by the same build
23
+ command — there is no separate function deploy step.
24
+
25
+ ## `netlify.toml` anatomy
26
+
27
+ The root `netlify.toml` is partly framework-owned (regenerated on
28
+ `npx spine-framework upgrade`, preserving `[functions."custom_*"]` sections):
29
+
30
+ | Block | Contents |
31
+ |---|---|
32
+ | `[build]` | `command = "npm run assemble && npm run build"`, `publish = "dist"`, `functions = ".assembled/netlify/functions"` |
33
+ | `[build.environment]` | `SECRETS_SCAN_OMIT_KEYS` whitelists the intentionally-public vars (`VITE_SUPABASE_URL`, `VITE_SUPABASE_ANON_KEY`, `APP_BASE_URL`, `SITE_URL`, …) so Netlify's secrets scanner does not flag them; `SECRETS_SCAN_OMIT_PATHS` covers `.framework/.xenv*` |
34
+ | `[functions]` | `directory = ".assembled/netlify/functions"`, `included_files` for `_shared/**`, `node_bundler = "esbuild"`, `external_node_modules = ["typescript"]` (the esbuild printer panic workaround — typescript.js ships unbundled) |
35
+ | `[dev]` | `netlify dev` runs `scripts/netlify-dev-wrapper.sh`, site on `8888`, Vite `targetPort` `3001`, `startTimeout 300` |
36
+ | `[functions."<name>"]` | per-function config: `trigger-scheduler` gets `schedule = "* * * * *"`; `cil-ingest`, `cil-embeddings`, `cil-callmap`, `cil-agent`, `ai-agents`, `kb` get `timeout` overrides |
37
+ | `[[redirects]]` | `/* → /index.html` with status `200` (SPA fallback) |
38
+ | `[[headers]]` | `X-Frame-Options DENY`, `nosniff`, HSTS, `Referrer-Policy`, `Permissions-Policy`, and a CSP that allows `*.supabase.co` (https+wss) and `challenges.cloudflare.com` (Turnstile) |
39
+
40
+ Dispatched trigger pipelines run as Netlify **background functions**
41
+ (`pipeline-runner-background`): the dispatcher gets a `202` immediately and
42
+ each run gets the fixed 15-minute background budget — which is why no
43
+ `timeout` entry exists for it.
44
+
45
+ ## How `.assembled/` is produced
46
+
47
+ `npm run assemble` (`scripts/assemble.sh`) runs before every dev start
48
+ (`predev:netlify`) and every build (`prebuild`). It wipes stale `dist/`,
49
+ then:
50
+
51
+ 1. `scripts/assemble-functions.sh` flattens `.framework/functions` plus
52
+ `custom/functions` and `custom/apps/*/functions` into
53
+ `.assembled/netlify/functions`. Basename collisions are a **hard error**
54
+ naming both sources — Netlify needs one flat dir, so last-wins overwrite
55
+ is forbidden. `_quarantine` and `*-test.ts`/`*.test.ts` are excluded.
56
+ 2. `scripts/assemble-frontend.sh` copies `.framework/src` as the base layer,
57
+ each `custom/apps/<slug>` verbatim to `.assembled/src/<slug>/`, fixes up
58
+ `index.html`, merges `.framework/public` + app `public/` dirs into the
59
+ project `public/` (same-path collisions are a hard error), copies
60
+ `_redirects` into `.assembled/src/` for `netlify dev`, and stages the
61
+ project `spine.config.json` into `public/`.
62
+
63
+ `config/vite.config.ts` then builds with `root: .assembled/src`,
64
+ `publicDir: public/`, `build.outDir: dist/` — matching `publish = "dist"`.
65
+ Never edit `.assembled/`; it is regenerated freely.
66
+
67
+ ## The `/api/*` URL space
68
+
69
+ Requests to `/api/*` are rewritten to `/.netlify/functions/:splat`:
70
+
71
+ - **Production:** the published `_redirects` file — sourced from
72
+ `.framework/public/_redirects`, merged into `public/` at assemble time —
73
+ carries `/api/* → /.netlify/functions/:splat 200`, plus
74
+ `/spine.config.json` passthrough and the `/* → /index.html` fallback.
75
+ - **Dev:** the Vite proxy in `config/vite.config.ts` maps `/api/*` to
76
+ `localhost:8888` with the same rewrite.
77
+
78
+ Because the SPA fallback is `/* → /index.html 200`, **any unmatched URL
79
+ returns HTTP 200 with HTML** — including typos under `/api/`. A probe that
80
+ gets HTML instead of JSON is hitting the SPA fallback, not a function.
81
+
82
+ ## Environment variables in production
83
+
84
+ Set these in the Netlify site environment (not in `netlify.toml`).
85
+ The full annotated list is [Environment Variables](../reference/env-vars.md);
86
+
87
+ | Variable | Needed for |
88
+ |---|---|
89
+ | `VITE_SUPABASE_URL`, `VITE_SUPABASE_ANON_KEY` | browser bundle (public by design) |
90
+ | `SUPABASE_URL`, `SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY` | all functions — service-role key is server-only, never `VITE_`-prefixed |
91
+ | `INTERNAL_INVOKE_SECRET` | trigger-dispatched pipelines — unset means `queued` rows that never run |
92
+ | `APP_BASE_URL` | invite links, auth redirects, `base_url` allowlist |
93
+ | `SCHEDULER_API_KEY` | key-gated `system-cron`/`trigger-scheduler` invocation |
94
+ | `SITE_URL` | CORS `Access-Control-Allow-Origin`; falls back to Netlify's auto-set `URL` |
95
+ | `RESEND_API_KEY`, `EMAIL_FROM` | outbound email (invites, notification stages) |
96
+ | `OPENAI_API_KEY` | AI stage types, agents, embeddings |
97
+ | `NETLIFY_ACCESS_TOKEN`, `NETLIFY_SITE_ID` | optional — push banned IPs to the edge firewall (security function skips silently without them) |
98
+
99
+ `SUPABASE_DB_PASSWORD` is **not** a function env var — it is used locally by
100
+ `npx spine-framework migrate` to connect to Postgres directly.
101
+
102
+ ## Deploy checklist
103
+
104
+ - [ ] Supabase project exists; `SUPABASE_*` + `VITE_SUPABASE_*` vars set in Netlify.
105
+ - [ ] `INTERNAL_INVOKE_SECRET` generated (`openssl rand -hex 32`) if triggers are used; `APP_BASE_URL`/`SITE_URL` set to the production origin.
106
+ - [ ] Migrations applied: `npx spine-framework migrate` against the production DB (see [Migrations](migrations.md)).
107
+ - [ ] Deploy via git push or `netlify deploy --prod` — the build command runs `assemble` then `vite build` automatically.
108
+ - [ ] Post-deploy smoke: `/api/system?action=health` and `?action=manifest` answer; first registration grants `system_admin` (see [Install and first run](../guide/01-install-and-first-run.md)).
109
+ - [ ] If timers/triggers are used: `trigger-scheduler` ticks appear in function logs within a minute; a test record write produces a `trigger.fired` log row.
110
+
111
+ ## Related
112
+
113
+ - [Migrations](migrations.md) · [Upgrade](upgrade.md) · [Troubleshooting](troubleshooting.md)
114
+ - [Environment Variables](../reference/env-vars.md) · [CLI Reference](../reference/cli.md)
115
+ - [Anatomy of an installed project](../guide/02-project-map.md) — sealed vs customer trees