spine-framework 0.4.4 → 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 (283) 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/hash-api-key.ts +183 -79
  15. package/.framework/functions/_shared/logging.ts +562 -224
  16. package/.framework/functions/_shared/middleware.ts +47 -44
  17. package/.framework/functions/admin-data.ts +39 -28
  18. package/.framework/functions/ai-agents.ts +10 -6
  19. package/.framework/functions/api-keys.ts +301 -122
  20. package/.framework/functions/apps.ts +43 -26
  21. package/.framework/functions/cil-ingest.ts +48 -15
  22. package/.framework/functions/debug-auth.ts +14 -8
  23. package/.framework/functions/deliveries.ts +39 -12
  24. package/.framework/functions/embeddings.ts +145 -76
  25. package/.framework/functions/integration-outbound.ts +67 -27
  26. package/.framework/functions/integrations.ts +254 -127
  27. package/.framework/functions/logs.ts +273 -133
  28. package/.framework/functions/observability.ts +277 -147
  29. package/.framework/functions/pipeline-executions.ts +1 -1
  30. package/.framework/functions/pipelines.ts +14 -9
  31. package/.framework/functions/prompt-configs.ts +7 -4
  32. package/.framework/functions/roles.ts +8 -5
  33. package/.framework/functions/security.ts +30 -17
  34. package/.framework/functions/system-cron.ts +240 -127
  35. package/.framework/functions/tests.ts +7 -6
  36. package/.framework/functions/timers.ts +310 -107
  37. package/.framework/functions/triggers.ts +28 -13
  38. package/.framework/functions/types.ts +13 -10
  39. package/.framework/migrations/069_log_stats_window.sql +54 -0
  40. package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
  41. package/.framework/migrations/071_timer_interval_keys.sql +96 -0
  42. package/.framework/migrations/072_slug_autofill.sql +77 -0
  43. package/.framework/migrations/073_seed_member_roles.sql +26 -0
  44. package/.framework/src/apps/admin/index.tsx +1141 -775
  45. package/.framework/src/components/ErrorBoundary.tsx +136 -0
  46. package/.framework/src/components/admin/AdminListPage.tsx +81 -73
  47. package/.framework/src/components/admin/AdminSidebar.tsx +88 -79
  48. package/.framework/src/components/admin/EntitySelect.tsx +181 -0
  49. package/.framework/src/components/admin/PageInstructions.tsx +86 -127
  50. package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
  51. package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
  52. package/.framework/src/components/layout/Sidebar.tsx +300 -177
  53. package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
  54. package/.framework/src/components/runtime/DataHeader.tsx +96 -48
  55. package/.framework/src/components/runtime/DataListPage.tsx +3 -26
  56. package/.framework/src/components/runtime/DataStats.tsx +10 -10
  57. package/.framework/src/components/runtime/DataTable.tsx +12 -10
  58. package/.framework/src/components/ui/sheet.tsx +24 -26
  59. package/.framework/src/components/ui/textarea.tsx +74 -48
  60. package/.framework/src/hooks/useEntityList.ts +12 -9
  61. package/.framework/src/hooks/useListSchema.ts +108 -58
  62. package/.framework/src/instructions/README.md +57 -0
  63. package/.framework/src/instructions/ai-agents.md +69 -0
  64. package/.framework/src/instructions/alerts.md +80 -0
  65. package/.framework/src/instructions/api-keys.md +87 -0
  66. package/.framework/src/instructions/apps.md +77 -0
  67. package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
  68. package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
  69. package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
  70. package/.framework/src/instructions/concepts/automation.md +186 -0
  71. package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
  72. package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
  73. package/.framework/src/instructions/concepts/design-schema.md +152 -0
  74. package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
  75. package/.framework/src/instructions/concepts/observability.md +116 -0
  76. package/.framework/src/instructions/concepts/permissions.md +150 -0
  77. package/.framework/src/instructions/concepts/runtime-records.md +111 -0
  78. package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
  79. package/.framework/src/instructions/concepts/spine-way.md +172 -0
  80. package/.framework/src/instructions/deliveries.md +59 -0
  81. package/.framework/src/instructions/guide/00-orientation.md +106 -0
  82. package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
  83. package/.framework/src/instructions/guide/02-project-map.md +147 -0
  84. package/.framework/src/instructions/guide/03-domain-model.md +223 -0
  85. package/.framework/src/instructions/guide/04-first-app.md +227 -0
  86. package/.framework/src/instructions/guide/05-glossary.md +183 -0
  87. package/.framework/src/instructions/integrations.md +96 -0
  88. package/.framework/src/instructions/internal/cil-markers.md +83 -0
  89. package/.framework/src/instructions/invites.md +60 -0
  90. package/.framework/src/instructions/kb.md +80 -0
  91. package/.framework/src/instructions/logs.md +77 -0
  92. package/.framework/src/instructions/observability.md +61 -0
  93. package/.framework/src/instructions/operations/deployment.md +115 -0
  94. package/.framework/src/instructions/operations/migrations.md +125 -0
  95. package/.framework/src/instructions/operations/security-checklist.md +148 -0
  96. package/.framework/src/instructions/operations/troubleshooting.md +170 -0
  97. package/.framework/src/instructions/operations/upgrade.md +116 -0
  98. package/.framework/src/instructions/pipeline-executions.md +62 -0
  99. package/.framework/src/instructions/pipelines.md +78 -0
  100. package/.framework/src/instructions/prompts.md +95 -0
  101. package/.framework/src/instructions/reference/api/admin-data.md +162 -0
  102. package/.framework/src/instructions/reference/api/auth.md +113 -0
  103. package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
  104. package/.framework/src/instructions/reference/app-manifest.md +150 -0
  105. package/.framework/src/instructions/reference/cli.md +124 -0
  106. package/.framework/src/instructions/reference/database.md +132 -0
  107. package/.framework/src/instructions/reference/design-schema.md +280 -0
  108. package/.framework/src/instructions/reference/env-vars.md +133 -0
  109. package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
  110. package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
  111. package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
  112. package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
  113. package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
  114. package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
  115. package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
  116. package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
  117. package/.framework/src/instructions/reference/functions/apps.md +140 -0
  118. package/.framework/src/instructions/reference/functions/auth.md +99 -0
  119. package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
  120. package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
  121. package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
  122. package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
  123. package/.framework/src/instructions/reference/functions/index.md +103 -0
  124. package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
  125. package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
  126. package/.framework/src/instructions/reference/functions/integrations.md +130 -0
  127. package/.framework/src/instructions/reference/functions/invites.md +182 -0
  128. package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
  129. package/.framework/src/instructions/reference/functions/kb.md +166 -0
  130. package/.framework/src/instructions/reference/functions/logs.md +141 -0
  131. package/.framework/src/instructions/reference/functions/observability.md +105 -0
  132. package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
  133. package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
  134. package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
  135. package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
  136. package/.framework/src/instructions/reference/functions/roles.md +121 -0
  137. package/.framework/src/instructions/reference/functions/security.md +140 -0
  138. package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
  139. package/.framework/src/instructions/reference/functions/system.md +106 -0
  140. package/.framework/src/instructions/reference/functions/tests.md +97 -0
  141. package/.framework/src/instructions/reference/functions/timers.md +117 -0
  142. package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
  143. package/.framework/src/instructions/reference/functions/triggers.md +140 -0
  144. package/.framework/src/instructions/reference/functions/types.md +146 -0
  145. package/.framework/src/instructions/reference/seeds.md +126 -0
  146. package/.framework/src/instructions/reference/shared-modules.md +127 -0
  147. package/.framework/src/instructions/reference/spine-config.md +114 -0
  148. package/.framework/src/instructions/roles.md +80 -0
  149. package/.framework/src/instructions/runtime-detail.md +70 -0
  150. package/.framework/src/instructions/runtime-list.md +77 -0
  151. package/.framework/src/instructions/security.md +67 -0
  152. package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
  153. package/.framework/src/instructions/tasks/add-a-role.md +96 -0
  154. package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
  155. package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
  156. package/.framework/src/instructions/tasks/add-a-type.md +151 -0
  157. package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
  158. package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
  159. package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
  160. package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
  161. package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
  162. package/.framework/src/instructions/tasks/test-your-code.md +108 -0
  163. package/.framework/src/instructions/tasks/write-a-function.md +132 -0
  164. package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
  165. package/.framework/src/instructions/testing.md +59 -0
  166. package/.framework/src/instructions/timers.md +82 -0
  167. package/.framework/src/instructions/triggers.md +69 -0
  168. package/.framework/src/instructions/types.md +93 -0
  169. package/.framework/src/pages/NotFoundPage.tsx +62 -31
  170. package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
  171. package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
  172. package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
  173. package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
  174. package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
  175. package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
  176. package/.framework/src/pages/admin/AppsPage.tsx +104 -66
  177. package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
  178. package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
  179. package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
  180. package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
  181. package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
  182. package/.framework/src/pages/admin/LogsPage.tsx +144 -76
  183. package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
  184. package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
  185. package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
  186. package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
  187. package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
  188. package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
  189. package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
  190. package/.framework/src/pages/admin/RolesPage.tsx +86 -43
  191. package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
  192. package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
  193. package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
  194. package/.framework/src/pages/admin/TimersPage.tsx +90 -62
  195. package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
  196. package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
  197. package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
  198. package/.framework/src/pages/admin/TypesPage.tsx +90 -48
  199. package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
  200. package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
  201. package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
  202. package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
  203. package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
  204. package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
  205. package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
  206. package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
  207. package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
  208. package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
  209. package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
  210. package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
  211. package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
  212. package/.framework/templates/agent/AGENTS.md +150 -0
  213. package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
  214. package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
  215. package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
  216. package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
  217. package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
  218. package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
  219. package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
  220. package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
  221. package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
  222. package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
  223. package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
  224. package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
  225. package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
  226. package/.framework/templates/project.json +4 -1
  227. package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
  228. package/.framework/tests/unit/agent-files.test.ts +355 -0
  229. package/.framework/tests/unit/agent-runner.test.ts +479 -44
  230. package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
  231. package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
  232. package/.framework/tests/unit/bootstrap.test.ts +242 -0
  233. package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
  234. package/.framework/tests/unit/debug-auth.test.ts +38 -0
  235. package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
  236. package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
  237. package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
  238. package/.framework/tests/unit/logging-app-id.test.ts +75 -0
  239. package/.framework/tests/unit/system-context-denial.test.ts +145 -0
  240. package/.framework/tests/unit/system-cron.test.ts +240 -0
  241. package/.framework/tests/unit/timers.test.ts +159 -0
  242. package/README.md +125 -166
  243. package/config/tsconfig.cli.json +2 -2
  244. package/package.json +15 -4
  245. package/templates/project/package-lock.json +2 -2
  246. package/.framework/docs/admin-routes.md +0 -76
  247. package/.framework/docs/api-docs-progress.md +0 -38
  248. package/.framework/docs/api-governance.md +0 -146
  249. package/.framework/docs/api-testing-results.md +0 -212
  250. package/.framework/docs/assembly-launch-guide.md +0 -138
  251. package/.framework/docs/audit-results.md +0 -590
  252. package/.framework/docs/db-api-inventory.md +0 -95
  253. package/.framework/docs/gap-remediation-backlog.md +0 -103
  254. package/.framework/docs/ui-adoption-verification.md +0 -111
  255. package/.framework/docs/ui-api-coverage.md +0 -84
  256. package/.framework/docs/v2-compatibility-audit.md +0 -228
  257. package/.framework/mcp/index.ts +0 -133
  258. package/.framework/mcp/load-env.ts +0 -60
  259. package/.framework/mcp/shared/app-manifest.ts +0 -275
  260. package/.framework/mcp/shared/db.ts +0 -477
  261. package/.framework/mcp/shared/kb.ts +0 -118
  262. package/.framework/mcp/tools/architect.ts +0 -431
  263. package/.framework/mcp/tools/cil/context.ts +0 -345
  264. package/.framework/mcp/tools/cil/graph.ts +0 -242
  265. package/.framework/mcp/tools/cil/ingest.ts +0 -1217
  266. package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
  267. package/.framework/mcp/tools/cil/pipeline.ts +0 -767
  268. package/.framework/mcp/tools/cil/project.ts +0 -791
  269. package/.framework/mcp/tools/cil/retrieval.ts +0 -336
  270. package/.framework/mcp/tools/cil/search-core.ts +0 -454
  271. package/.framework/mcp/tools/cil/search.ts +0 -97
  272. package/.framework/mcp/tools/cil/suggest.ts +0 -186
  273. package/.framework/mcp/tools/cil/validate.ts +0 -1369
  274. package/.framework/mcp/tools/kb/delete.ts +0 -139
  275. package/.framework/mcp/tools/kb/index.ts +0 -52
  276. package/.framework/mcp/tools/kb/ingest.ts +0 -84
  277. package/.framework/mcp/tools/kb/list-types.ts +0 -102
  278. package/.framework/mcp/tools/kb/publish.ts +0 -100
  279. package/.framework/mcp/tools/kb/reindex.ts +0 -86
  280. package/.framework/mcp/tools/kb/revoke.ts +0 -85
  281. package/.framework/mcp/tools/kb/search.ts +0 -101
  282. package/.framework/mcp/tools/kb/upsert.ts +0 -125
  283. package/.framework/mcp/tools/observability.ts +0 -510
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: Timers
3
+ audience: both
4
+ kind: entity
5
+ verified_against: e13127d
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - .framework/functions/timers.ts
9
+ - .framework/functions/system-cron.ts
10
+ - .framework/functions/trigger-scheduler.ts
11
+ - .framework/src/pages/admin/TimersPage.tsx
12
+ - .framework/src/pages/admin/TimerDetailPage.tsx
13
+ - .framework/migrations/068_cron_schedule_timer_rpcs.sql
14
+ - .framework/migrations/020_schema_reconciliation.sql
15
+ ---
16
+
17
+ ## What this is for
18
+
19
+ A **timer** is a scheduled job that invokes a pipeline when it comes due — Spine's recurring/one-off background task primitive. `system-cron` (invoked every minute by the `trigger-scheduler` Netlify scheduled function) asks the `get_due_timers` RPC for due timers and runs each one's pipeline.
20
+
21
+ ## Fields and settings
22
+
23
+ - **Name** — string. Display name; required (`name` and `timer_type` are the API's required fields).
24
+ - **Type** — select: `interval`, `cron`, `once`. **Stored but not read by the scheduler** — it labels intent only; see Downstream effects.
25
+ - **App ID** — select, optional. Owning app; blank = account-scoped.
26
+ - **Pipeline ID** — select. The pipeline invoked when the timer fires. `get_due_timers` skips rows where `pipeline_id IS NULL`, so a blank pipeline means the timer never runs.
27
+ - **Active** — checkbox. Inactive timers are skipped by `get_due_timers`.
28
+ - **Description** — string, optional.
29
+ - **Config (JSON)** — the schedule. The only key the rescheduler reads today is `interval_minutes` (minutes between runs). The form seeds `{ "schedule": "", "interval_seconds": 3600 }` — neither key is honored by the current RPCs.
30
+ - **Metadata (JSON)** — optional metadata.
31
+
32
+ **Downstream effects**
33
+
34
+ - `get_due_timers` returns active timers with `pipeline_id IS NOT NULL` and `next_execution <= now()`. The timers API arms `next_execution` automatically on create/activate when `config.interval_minutes` (or `interval_seconds`) resolves to a positive interval — or pass `next_execution` explicitly.
35
+ - `update_timer_after_run` reschedules `next_execution = now() + interval` only when `config.interval_minutes` is a positive number; otherwise it sets `next_execution = NULL` and the timer becomes one-shot/dead. `timer_type`, `interval_seconds`, `schedule`, and `run_at` are ignored by the RPC.
36
+ - Each firing also stamps `last_execution` and increments `execution_count` / `success_count` / `failure_count` — the source of the list page's Executions and Success Rate columns.
37
+ - True cron expressions live on the separate `public.schedules` table (read by `get_due_schedules`), not on `timers` — a `cron`-type timer is a label, not a working cron.
38
+
39
+ ## Minimal configuration
40
+
41
+ ```json
42
+ {
43
+ "name": "Hourly sync",
44
+ "timer_type": "interval",
45
+ "pipeline_id": "<pipeline uuid>",
46
+ "is_active": true,
47
+ "config": { "interval_minutes": 60 }
48
+ }
49
+ ```
50
+
51
+ ## Full configuration
52
+
53
+ ```json
54
+ {
55
+ "name": "Nightly-ish rollup",
56
+ "timer_type": "interval",
57
+ "pipeline_id": "<pipeline uuid>",
58
+ "is_active": true,
59
+ "config": { "interval_minutes": 1440 },
60
+ "metadata": { "owner": "platform", "notes": "fires ~daily once next_execution is seeded" }
61
+ }
62
+ ```
63
+
64
+ ## Example
65
+
66
+ A support app keeps an `interval` timer with `interval_minutes: 360` to re-check stale tickets every six hours, and a second timer whose `interval_minutes` was left blank to run a one-off backfill — after its first fire, `update_timer_after_run` writes `next_execution = NULL` so it never re-fires.
67
+
68
+ ## Core files
69
+
70
+ - `.framework/functions/timers.ts` — API (list/get/create/update/delete; does not set `next_execution`)
71
+ - `.framework/functions/system-cron.ts` — per-tick driver: calls `get_due_timers`, runs `runPipeline` as a `timer:<id>` principal, then `update_timer_after_run`
72
+ - `.framework/functions/trigger-scheduler.ts` — Netlify scheduled entry point that delegates to `system-cron`
73
+ - `.framework/migrations/068_cron_schedule_timer_rpcs.sql` — the `get_due_timers` / `update_timer_after_run` RPCs
74
+ - `.framework/src/pages/admin/TimersPage.tsx` / `TimerDetailPage.tsx` — admin UI
75
+ - Table: `public.timers` (`timer_type`, `pipeline_id`, `next_execution`, `execution_count` added by migration 020)
76
+
77
+ ## Agent notes
78
+
79
+ - The list's "Next Execution" column shows `Not scheduled` when `next_execution` is NULL — an active timer in that state cannot fire until it is re-armed (edit its interval or toggle it off/on).
80
+ - A timer with a blank `pipeline_id` saves fine but is filtered out by `get_due_timers` — always pick the pipeline.
81
+ - To arm a new timer, set `next_execution` in the DB (e.g. `now() + interval`); after the first successful run, `interval_minutes` keeps it rescheduling.
82
+ - "Success Rate" is `success_count / execution_count`; failures still reschedule — a broken pipeline does not stop the cadence.
@@ -0,0 +1,69 @@
1
+ ---
2
+ title: Triggers
3
+ audience: both
4
+ kind: entity
5
+ verified_against: e13127d
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - .framework/functions/triggers.ts
9
+ - .framework/functions/_shared/trigger-engine.ts
10
+ - .framework/functions/trigger-scheduler.ts
11
+ - .framework/src/pages/admin/TriggersPage.tsx
12
+ - .framework/src/pages/admin/TriggerDetailPage.tsx
13
+ - .framework/migrations/064_episode_leases.sql
14
+ ---
15
+
16
+ ## What this is for
17
+
18
+ A **trigger** listens for a Spine event and, when active, hands the event payload to a pipeline for processing. It is the link between emitted platform events (e.g. `item_created`) and the workflows that react to them.
19
+
20
+ ## Fields and settings
21
+
22
+ - **Name** — string. Display name; missing name prevents saving.
23
+ - **Event Type** — string. The event to listen to, e.g. `item_created`. Must match the emitted event name **exactly** — a typo means the trigger never fires.
24
+ - **App ID** — select, optional. Owning app; blank = account-scoped.
25
+ - **Pipeline ID** — select, required at create (`name`, `event_type`, `pipeline_id` are all required by the API). The pipeline invoked when the trigger fires; a stale ID means the queued execution fails instead of running.
26
+ - **Active** — checkbox. Inactive triggers are skipped at fire time — matching events produce no run.
27
+ - **Description** — string, optional.
28
+ - **Config (JSON)** — trigger-engine configuration, e.g. filters or payload mapping.
29
+ - **Metadata (JSON)** — optional metadata.
30
+
31
+ **Downstream effects**
32
+
33
+ - The trigger engine (`admin-data` writes → `_shared/trigger-engine`) matches emitted events to active triggers by `event_type`; real event names use underscores — `item_created`, `item_updated`, `item_deleted`, `thread_created`, `message_created`, etc. (see the `EventType` union in `_shared/trigger-engine.ts`).
34
+ - `config` filters narrow which matching events actually invoke the pipeline.
35
+ - A wrong or stale `pipeline_id` means the trigger fires, queues an execution row, and the run fails — check Pipeline Executions, not just the trigger, when "nothing happened".
36
+
37
+ ## Minimal configuration
38
+
39
+ ```json
40
+ {
41
+ "name": "On item created",
42
+ "event_type": "item_created",
43
+ "pipeline_id": "<pipeline uuid>",
44
+ "is_active": true
45
+ }
46
+ ```
47
+
48
+ ## Full configuration
49
+
50
+ Adds `config` with payload filters (e.g. match only `item_created` where `type_slug = "ticket"`), field mappings into the pipeline input, and `metadata` documenting the contract the event producer is expected to emit.
51
+
52
+ ## Example
53
+
54
+ A support app fires `item_created` filtered to `type_slug = "ticket"`; the trigger invokes its triage pipeline, which assigns the ticket and posts a thread message. A second trigger on `item_updated` handles SLA warnings — both share the same pipeline pattern but different filters.
55
+
56
+ ## Core files
57
+
58
+ - `.framework/functions/triggers.ts` — API
59
+ - `.framework/functions/_shared/trigger-engine.ts` — event matching and dispatch to `pipeline-runner-background`
60
+ - `.framework/functions/trigger-scheduler.ts` — Netlify scheduled entry point (delegates to `system-cron`)
61
+ - `.framework/src/pages/admin/TriggersPage.tsx` / `TriggerDetailPage.tsx` — admin UI
62
+ - Table: `public.triggers`
63
+
64
+ ## Agent notes
65
+
66
+ - Event names are `<entity>_<past tense>` (`item_created`, `message_deleted`, ...) — the Event Type input's own placeholder still shows the stale `item.created` form; use underscores.
67
+ - `config` filters (`entity_type`, `type_slug`, `filters` with `$eq`/`$ne`/`$gt`/etc.) narrow which matching events actually invoke the pipeline.
68
+ - The list's "Total Fires" stat and "Fires"/"Last Fired" columns count trigger firings (the `record_trigger_fire` RPC), not successful pipeline runs — a trigger can fire while its pipeline fails.
69
+ - `config` must be a JSON **object**, not a string — the second most common save failure after event-type typos.
@@ -0,0 +1,93 @@
1
+ ---
2
+ title: Types
3
+ audience: both
4
+ kind: entity
5
+ verified_against: e13127d
6
+ verified_on: 2026-10-30
7
+ source_files:
8
+ - .framework/functions/types.ts
9
+ - .framework/src/pages/admin/TypesPage.tsx
10
+ - .framework/src/pages/admin/TypeDetailPage.tsx
11
+ - .framework/functions/_shared/permissions.ts
12
+ - .framework/functions/_shared/resolve-ids.ts
13
+ - .framework/functions/_shared/schema-utils.ts
14
+ - .framework/cli/commands/install-app.ts
15
+ - .framework/migrations/015_types_kind_slug_unique.sql
16
+ ---
17
+
18
+ ## What this is for
19
+
20
+ A **type** is the design schema for a runtime record kind. It defines the fields, default list/detail views, record permissions, icon, and color that the generic admin and runtime UIs use to create, validate, and display records. Every `items`/`threads`/`messages`/etc. record is stamped with its type's `design_schema` at creation.
21
+
22
+ ## Fields and settings
23
+
24
+ - **Name** — string. Display label for the type. Empty name blocks save.
25
+ - **Slug** — string. URL-friendly identifier, unique per `kind`. Callers resolve types by slug; duplicates break `resolveTypeId`/`.single()` lookups. Rarely change after records exist.
26
+ - **Description** — string, optional. Human-readable context.
27
+ - **Kind** — select: `item`, `account`, `person`, `thread`, `message`, `link`, `attachment`, `watcher`. Determines which runtime table the type governs.
28
+ - **Ownership** — select: `system` (platform types, protected from deletion), `app` (owned by an app), `tenant` (account-specific).
29
+ - **Is Active** — checkbox. Inactive types are hidden from lists and cannot have records created.
30
+ - **App ID** — select. Required whenever ownership is not `system` — the form rejects save otherwise.
31
+ - **Icon / Color** — UI presentation stored on the `types` row.
32
+ - **Design Schema (JSON)** — the full schema: `fields`, `views` (`default_list`, `default_detail`), `record_permissions`, `scope`, `functionality`.
33
+ - **Validation Schema** — read-only, regenerated from `design_schema` on every save by the API.
34
+
35
+ **Downstream effects**
36
+
37
+ - Generic list/detail pages render directly from `views`. A missing `default_list`/`default_detail` or unknown `display_type` breaks those pages.
38
+ - `record_permissions` is the **base, most restrictive grant**: if a role can read/update a record, all fields default to read/write. `fields.*.permissions` only *loosen* access per field or restrict `system: true` fields.
39
+ - `system: true` fields are read from `record.<field>`; non-system fields from `record.data.<field>`.
40
+ - Changing `data_type` on a field with existing records does not migrate data — old values remain until rewritten.
41
+ - Type seeds use `conflict: "kind,slug"` with `inject_app_id: false` — types are global, not duplicated per app install.
42
+
43
+ ## Minimal configuration
44
+
45
+ ```json
46
+ {
47
+ "scope": "account",
48
+ "fields": {
49
+ "title": { "data_type": "text", "label": "Title", "required": true, "system": true }
50
+ },
51
+ "views": {
52
+ "default_list": {
53
+ "type": "list", "display": "table", "label": "List",
54
+ "fields": {
55
+ "title": { "sortable": true, "display_type": "text" },
56
+ "created_at": { "sortable": true, "display_type": "timestamp" }
57
+ },
58
+ "default_sort": { "field": "created_at", "direction": "desc" }
59
+ },
60
+ "default_detail": {
61
+ "type": "detail", "label": "Detail",
62
+ "sections": [{ "title": "Details", "fields": { "title": { "display_type": "input" } } }]
63
+ }
64
+ },
65
+ "record_permissions": { "system_admin": ["create", "read", "update", "delete"] },
66
+ "functionality": null
67
+ }
68
+ ```
69
+
70
+ ## Full configuration
71
+
72
+ Adds typed fields, select `options`, per-field `permissions` overrides, multiple views with sorting/badges, and per-role record grants (`admin`, `member`). See the [design schema reference](reference/design-schema.md) for the full `data_type` list (`text`, `number`, `select`, `multiselect`, `reference`, `json`, `date`, `boolean`, ...) and `display_type` list (`badge`, `timestamp`, `select`, `currency`, ...).
73
+
74
+ ## Example
75
+
76
+ A support app defines a `ticket` type (kind `item`, ownership `app`): `title` (system text), `status` (select: open/pending/closed), `priority` (select), `assignee_id` (reference). `record_permissions` grants `system_admin` all actions, `admin` create/read/update, `member` read. `fields.assignee_id.permissions` loosens `write` to `member` so agents can self-assign.
77
+
78
+ ## Core files
79
+
80
+ - `.framework/functions/types.ts` — API (list/get/create/update/delete; regenerates `validation_schema`)
81
+ - `.framework/src/pages/admin/TypesPage.tsx` / `TypeDetailPage.tsx` — admin UI
82
+ - `.framework/src/components/app-shell/GenericListPage.tsx` / `GenericDetailPage.tsx` — generic renderer
83
+ - `.framework/functions/_shared/permissions.ts` — record/field permission evaluation
84
+ - [Design schema reference](reference/design-schema.md) — full field/view schema reference in this book
85
+ - Table: `public.types`
86
+
87
+ ## Agent notes
88
+
89
+ - Never hand-edit `validation_schema`; change `design_schema` and the API regenerates it.
90
+ - Slug uniqueness is per `(kind, slug)` — reuse across kinds is fine, reuse within a kind breaks lookups.
91
+ - Every field needs `data_type`, `label`, `required`; `select`/`multiselect`/`radio` also need `options`.
92
+ - Don't add `fields.*.permissions` unless overriding the base grant — the common mistake is re-stating record-level permissions per field.
93
+ - Custom apps CRUD runtime records through `/api/admin-data` — never custom wrappers.
@@ -1,35 +1,65 @@
1
1
  // CIL[BEGIN stable_id="~/.framework/src/pages/NotFoundPage.tsx:module_header:module_header" type="module_header" identity="module_header" parent="~/.framework/src/pages/NotFoundPage.tsx"]
2
- // CIL[DOC-MACRO purpose="Import dependencies used by the NotFoundPage 404 component"]
3
- // CIL[DOC-RESPONSIBILITY responsibility="Provide React, react-router-dom Link, and lucide-react Home icon for the page"]
4
- // CIL[DOC-CONTEXT module=".framework/src/pages" layer="page" related_files=".framework/src/pages/NotFoundPage.tsx"]
5
- // CIL[DOC-CONTRACT inputs="N/A" outputs="N/A" errors="N/A" side_effects="N/A"]
6
- // CIL[DOC-MICRO logic_summary="Imports React, Link, and Home icon; no runtime logic" notable_decisions="[]"]
7
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
8
- // CIL[DOC-STABILITY stability="stable"]
9
- // CIL[DOC-AUDIENCE audience="Spine framework page authors"]
2
+ /**
3
+ * @module NotFoundPage
4
+ * @audience both
5
+ * @layer shared-core
6
+ * @stability stable
7
+ *
8
+ * This module renders a Not Found page for the application, providing users with a friendly message when they navigate to an undefined route. It serves as a fallback UI component, enhancing user experience by guiding them back to the home page. INVARIANT: The Not Found page should always be accessible for any invalid routes.
9
+ *
10
+ * @seeAlso react-router-dom (provides routing capabilities).
11
+ * @seeAlso lucide-react (used for icons).
12
+ *
13
+ * @cil-generated
14
+ */
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
10
25
 
11
26
 
12
27
 
13
28
  import React from 'react'
14
29
  import { Link } from 'react-router-dom'
15
30
  import { Home } from 'lucide-react';
16
- // CIL[DOC-VECTOR type="context" content="purpose='Import dependencies used by the NotFoundPage 404 component'; No verified external callers; imports: none"]
17
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
18
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
19
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
20
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
21
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
22
31
  // CIL[END stable_id="~/.framework/src/pages/NotFoundPage.tsx:module_header:module_header"]
23
32
 
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
24
51
  // CIL[BEGIN stable_id="~/.framework/src/pages/NotFoundPage.tsx:NotFoundPage:component" type="component" identity="NotFoundPage" parent="~/.framework/src/pages/NotFoundPage.tsx"]
25
- // CIL[DOC-MACRO purpose="Render a friendly 404 not found page with a link back to sign in"]
26
- // CIL[DOC-RESPONSIBILITY responsibility="Display a centered 404 message and a Home icon link that navigates to /login"]
27
- // CIL[DOC-CONTEXT module=".framework/src/pages" layer="page" related_files=".framework/src/pages/NotFoundPage.tsx"]
28
- // CIL[DOC-CONTRACT inputs="None" outputs="JSX 404 page" errors="None" side_effects="None"]
29
- // CIL[DOC-MICRO logic_summary="Renders a full-screen 404 page with a heading, description, and a Link to /login" notable_decisions="[]"]
30
- // CIL[DOC-CONFIDENCE pass="second" score="0.90" flags="none"]
31
- // CIL[DOC-STABILITY stability="stable"]
32
- // CIL[DOC-AUDIENCE audience="End users who reach an unknown route"]
52
+ /**
53
+ * The NotFoundPage component displays a 404 error message when a page is not found, providing a user-friendly interface to guide users back to the home page.
54
+ *
55
+ * @macro React functional component responsible for rendering a 404 error page.
56
+ * @micro Utilizes JSX to structure the layout and styling of the error message and navigation link.
57
+ * @outputSpec JSX.Element
58
+ * @sideEffects none
59
+ * @stability internal
60
+ * @calls Link
61
+ * @cil-generated
62
+ */
33
63
  export function NotFoundPage() {
34
64
  return (
35
65
  <div className="min-h-screen bg-slate-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
@@ -43,11 +73,11 @@ export function NotFoundPage() {
43
73
 
44
74
  <div className="mt-6">
45
75
  <Link
46
- to="/login"
76
+ to="/"
47
77
  className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
48
78
  >
49
79
  <Home className="w-4 h-4 mr-2" />
50
- Go to sign in
80
+ Go home
51
81
  </Link>
52
82
  </div>
53
83
  </div>
@@ -55,10 +85,11 @@ export function NotFoundPage() {
55
85
  </div>
56
86
  )
57
87
  }
58
- // CIL[DOC-VECTOR type="context" content="purpose='Render a friendly 404 not found page with a link back to sign in'; No verified external callers; imports: none"]
59
- // CIL[DOC-VECTOR type="blast_radius" content="No direct caller data from CIL graph; local impact only"]
60
- // CIL[DOC-VECTOR type="configuration" content="No environment or build configuration dependencies identified"]
61
- // CIL[DOC-VECTOR type="constraint" content="Standard runtime; no special invariants documented"]
62
- // CIL[DOC-VECTOR type="implementation_pattern" content="" status="pending_human_input"]
63
- // CIL[DOC-VECTOR type="user_journey" content="" status="pending_human_input"]
64
- // CIL[END stable_id="~/.framework/src/pages/NotFoundPage.tsx:NotFoundPage:component"]
88
+ // CIL[END stable_id="~/.framework/src/pages/NotFoundPage.tsx:NotFoundPage:component"]
89
+
90
+
91
+
92
+
93
+
94
+
95
+