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.
- package/.env.example +13 -3
- package/.framework/cli/commands/bootstrap.ts +392 -0
- package/.framework/cli/commands/dev.ts +91 -218
- package/.framework/cli/commands/doctor.ts +132 -26
- package/.framework/cli/commands/generate.ts +38 -298
- package/.framework/cli/commands/init.ts +20 -1
- package/.framework/cli/commands/migrate.ts +36 -30
- package/.framework/cli/commands/migrations.ts +16 -56
- package/.framework/cli/commands/upgrade.ts +35 -0
- package/.framework/cli/commands/validate-schema.ts +147 -0
- package/.framework/cli/context.ts +223 -110
- package/.framework/cli/index.ts +6 -0
- package/.framework/cli/lib/project-files.ts +241 -1
- package/.framework/functions/_shared/agent-runner.ts +1000 -81
- package/.framework/functions/_shared/cil.ts +2 -1
- package/.framework/functions/_shared/db.ts +3 -6
- package/.framework/functions/_shared/hash-api-key.ts +183 -79
- package/.framework/functions/_shared/kb.ts +61 -7
- package/.framework/functions/_shared/logging.ts +562 -224
- package/.framework/functions/_shared/message-sequence.ts +53 -0
- package/.framework/functions/_shared/middleware.ts +47 -44
- package/.framework/functions/_shared/pipeline-runner.ts +150 -37
- package/.framework/functions/_shared/principal.ts +9 -6
- package/.framework/functions/_shared/trigger-engine.ts +149 -40
- package/.framework/functions/admin-data.ts +48 -31
- package/.framework/functions/ai-agents.ts +103 -33
- package/.framework/functions/api-keys.ts +301 -122
- package/.framework/functions/apps.ts +43 -26
- package/.framework/functions/cil-ingest.ts +48 -15
- package/.framework/functions/debug-auth.ts +14 -8
- package/.framework/functions/deliveries.ts +39 -12
- package/.framework/functions/embeddings.ts +145 -76
- package/.framework/functions/integration-outbound.ts +67 -27
- package/.framework/functions/integrations.ts +254 -127
- package/.framework/functions/logs.ts +273 -133
- package/.framework/functions/observability.ts +277 -147
- package/.framework/functions/pipeline-executions.ts +1 -1
- package/.framework/functions/pipeline-runner-background.ts +120 -0
- package/.framework/functions/pipelines.ts +14 -9
- package/.framework/functions/prompt-configs.ts +7 -4
- package/.framework/functions/roles.ts +8 -5
- package/.framework/functions/security.ts +30 -17
- package/.framework/functions/system-cron.ts +250 -128
- package/.framework/functions/tests.ts +7 -6
- package/.framework/functions/timers.ts +310 -107
- package/.framework/functions/trigger-scheduler.ts +65 -5
- package/.framework/functions/triggers.ts +28 -13
- package/.framework/functions/types.ts +13 -10
- package/.framework/migrations/064_episode_leases.sql +196 -0
- package/.framework/migrations/065_execution_tables_updated_at.sql +20 -0
- package/.framework/migrations/066_episode_steal_thread_merge.sql +148 -0
- package/.framework/migrations/067_episode_lease_stale_steal.sql +93 -0
- package/.framework/migrations/068_cron_schedule_timer_rpcs.sql +251 -0
- package/.framework/migrations/069_log_stats_window.sql +54 -0
- package/.framework/migrations/070_app_type_schema_rpcs.sql +166 -0
- package/.framework/migrations/071_timer_interval_keys.sql +96 -0
- package/.framework/migrations/072_slug_autofill.sql +77 -0
- package/.framework/migrations/073_seed_member_roles.sql +26 -0
- package/.framework/schemas/spine.config.schema.json +62 -0
- package/.framework/src/App.tsx +3 -1
- package/.framework/src/apps/admin/index.tsx +1141 -775
- package/.framework/src/components/ErrorBoundary.tsx +136 -0
- package/.framework/src/components/admin/AdminListPage.tsx +81 -73
- package/.framework/src/components/admin/AdminSidebar.tsx +92 -81
- package/.framework/src/components/admin/EntitySelect.tsx +181 -0
- package/.framework/src/components/admin/PageInstructions.tsx +86 -127
- package/.framework/src/components/app-shell/GenericAppShell.tsx +3 -1
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +37 -13
- package/.framework/src/components/app-shell/GenericListPage.tsx +28 -32
- package/.framework/src/components/auth/TurnstileWidget.tsx +9 -6
- package/.framework/src/components/kb/KBArticleEditor.tsx +49 -6
- package/.framework/src/components/layout/Layout.tsx +4 -2
- package/.framework/src/components/layout/Sidebar.tsx +304 -179
- package/.framework/src/components/runtime/DataDetailPage.tsx +67 -35
- package/.framework/src/components/runtime/DataHeader.tsx +96 -48
- package/.framework/src/components/runtime/DataListPage.tsx +3 -26
- package/.framework/src/components/runtime/DataStats.tsx +10 -10
- package/.framework/src/components/runtime/DataTable.tsx +12 -10
- package/.framework/src/components/ui/sheet.tsx +24 -26
- package/.framework/src/components/ui/textarea.tsx +74 -48
- package/.framework/src/hooks/useBranding.ts +47 -0
- package/.framework/src/hooks/useEntityList.ts +12 -9
- package/.framework/src/hooks/useListSchema.ts +108 -58
- package/.framework/src/instructions/README.md +57 -0
- package/.framework/src/instructions/ai-agents.md +69 -0
- package/.framework/src/instructions/alerts.md +80 -0
- package/.framework/src/instructions/api-keys.md +87 -0
- package/.framework/src/instructions/apps.md +77 -0
- package/.framework/src/instructions/concepts/ai-and-prompts.md +150 -0
- package/.framework/src/instructions/concepts/apps-and-renderers.md +162 -0
- package/.framework/src/instructions/concepts/auth-and-api-keys.md +133 -0
- package/.framework/src/instructions/concepts/automation.md +186 -0
- package/.framework/src/instructions/concepts/concurrency-and-idempotency.md +125 -0
- package/.framework/src/instructions/concepts/core-vs-custom.md +124 -0
- package/.framework/src/instructions/concepts/design-schema.md +152 -0
- package/.framework/src/instructions/concepts/integrations-and-webhooks.md +127 -0
- package/.framework/src/instructions/concepts/observability.md +116 -0
- package/.framework/src/instructions/concepts/permissions.md +150 -0
- package/.framework/src/instructions/concepts/runtime-records.md +111 -0
- package/.framework/src/instructions/concepts/scope-and-accounts.md +112 -0
- package/.framework/src/instructions/concepts/spine-way.md +172 -0
- package/.framework/src/instructions/deliveries.md +59 -0
- package/.framework/src/instructions/guide/00-orientation.md +106 -0
- package/.framework/src/instructions/guide/01-install-and-first-run.md +253 -0
- package/.framework/src/instructions/guide/02-project-map.md +147 -0
- package/.framework/src/instructions/guide/03-domain-model.md +223 -0
- package/.framework/src/instructions/guide/04-first-app.md +227 -0
- package/.framework/src/instructions/guide/05-glossary.md +183 -0
- package/.framework/src/instructions/integrations.md +96 -0
- package/.framework/src/instructions/internal/cil-markers.md +83 -0
- package/.framework/src/instructions/invites.md +60 -0
- package/.framework/src/instructions/kb.md +80 -0
- package/.framework/src/instructions/logs.md +77 -0
- package/.framework/src/instructions/observability.md +61 -0
- package/.framework/src/instructions/operations/deployment.md +115 -0
- package/.framework/src/instructions/operations/migrations.md +125 -0
- package/.framework/src/instructions/operations/security-checklist.md +148 -0
- package/.framework/src/instructions/operations/troubleshooting.md +170 -0
- package/.framework/src/instructions/operations/upgrade.md +116 -0
- package/.framework/src/instructions/pipeline-executions.md +62 -0
- package/.framework/src/instructions/pipelines.md +78 -0
- package/.framework/src/instructions/prompts.md +95 -0
- package/.framework/src/instructions/reference/api/admin-data.md +162 -0
- package/.framework/src/instructions/reference/api/auth.md +113 -0
- package/.framework/src/instructions/reference/api/errors-and-envelopes.md +113 -0
- package/.framework/src/instructions/reference/app-manifest.md +150 -0
- package/.framework/src/instructions/reference/cli.md +124 -0
- package/.framework/src/instructions/reference/database.md +132 -0
- package/.framework/src/instructions/reference/design-schema.md +280 -0
- package/.framework/src/instructions/reference/env-vars.md +133 -0
- package/.framework/src/instructions/reference/functions/account-nodes.md +75 -0
- package/.framework/src/instructions/reference/functions/admin-data.md +195 -0
- package/.framework/src/instructions/reference/functions/admin-funnel.md +90 -0
- package/.framework/src/instructions/reference/functions/admin-install-funnel.md +107 -0
- package/.framework/src/instructions/reference/functions/admin-signals.md +102 -0
- package/.framework/src/instructions/reference/functions/ai-agents.md +148 -0
- package/.framework/src/instructions/reference/functions/ai-interactions.md +156 -0
- package/.framework/src/instructions/reference/functions/api-keys.md +130 -0
- package/.framework/src/instructions/reference/functions/apps.md +140 -0
- package/.framework/src/instructions/reference/functions/auth.md +99 -0
- package/.framework/src/instructions/reference/functions/debug-auth.md +91 -0
- package/.framework/src/instructions/reference/functions/deliveries.md +110 -0
- package/.framework/src/instructions/reference/functions/embeddings.md +166 -0
- package/.framework/src/instructions/reference/functions/eval-harness.md +149 -0
- package/.framework/src/instructions/reference/functions/index.md +103 -0
- package/.framework/src/instructions/reference/functions/integration-outbound.md +200 -0
- package/.framework/src/instructions/reference/functions/integration-routes.md +151 -0
- package/.framework/src/instructions/reference/functions/integrations.md +130 -0
- package/.framework/src/instructions/reference/functions/invites.md +182 -0
- package/.framework/src/instructions/reference/functions/item-progress.md +107 -0
- package/.framework/src/instructions/reference/functions/kb.md +166 -0
- package/.framework/src/instructions/reference/functions/logs.md +141 -0
- package/.framework/src/instructions/reference/functions/observability.md +105 -0
- package/.framework/src/instructions/reference/functions/pipeline-executions.md +132 -0
- package/.framework/src/instructions/reference/functions/pipeline-runner-background.md +121 -0
- package/.framework/src/instructions/reference/functions/pipelines.md +136 -0
- package/.framework/src/instructions/reference/functions/prompt-configs.md +121 -0
- package/.framework/src/instructions/reference/functions/roles.md +121 -0
- package/.framework/src/instructions/reference/functions/security.md +140 -0
- package/.framework/src/instructions/reference/functions/system-cron.md +136 -0
- package/.framework/src/instructions/reference/functions/system.md +106 -0
- package/.framework/src/instructions/reference/functions/tests.md +97 -0
- package/.framework/src/instructions/reference/functions/timers.md +117 -0
- package/.framework/src/instructions/reference/functions/trigger-scheduler.md +102 -0
- package/.framework/src/instructions/reference/functions/triggers.md +140 -0
- package/.framework/src/instructions/reference/functions/types.md +146 -0
- package/.framework/src/instructions/reference/seeds.md +126 -0
- package/.framework/src/instructions/reference/shared-modules.md +127 -0
- package/.framework/src/instructions/reference/spine-config.md +114 -0
- package/.framework/src/instructions/roles.md +80 -0
- package/.framework/src/instructions/runtime-detail.md +70 -0
- package/.framework/src/instructions/runtime-list.md +77 -0
- package/.framework/src/instructions/security.md +67 -0
- package/.framework/src/instructions/tasks/add-a-pipeline.md +110 -0
- package/.framework/src/instructions/tasks/add-a-role.md +96 -0
- package/.framework/src/instructions/tasks/add-a-timer.md +114 -0
- package/.framework/src/instructions/tasks/add-a-trigger.md +106 -0
- package/.framework/src/instructions/tasks/add-a-type.md +151 -0
- package/.framework/src/instructions/tasks/add-a-webhook.md +108 -0
- package/.framework/src/instructions/tasks/add-an-ai-agent.md +108 -0
- package/.framework/src/instructions/tasks/add-an-integration.md +124 -0
- package/.framework/src/instructions/tasks/build-a-custom-page.md +118 -0
- package/.framework/src/instructions/tasks/package-and-install-an-app.md +127 -0
- package/.framework/src/instructions/tasks/test-your-code.md +108 -0
- package/.framework/src/instructions/tasks/write-a-function.md +132 -0
- package/.framework/src/instructions/tasks/write-a-migration.md +110 -0
- package/.framework/src/instructions/testing.md +59 -0
- package/.framework/src/instructions/timers.md +82 -0
- package/.framework/src/instructions/triggers.md +69 -0
- package/.framework/src/instructions/types.md +93 -0
- package/.framework/src/lib/branding.ts +128 -0
- package/.framework/src/pages/NoAppPage.tsx +3 -1
- package/.framework/src/pages/NotFoundPage.tsx +62 -31
- package/.framework/src/pages/SetupPage.tsx +5 -2
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +117 -106
- package/.framework/src/pages/admin/AIAgentsPage.tsx +86 -48
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +153 -152
- package/.framework/src/pages/admin/APIKeysPage.tsx +91 -90
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +29 -18
- package/.framework/src/pages/admin/AppDetailPage.tsx +6 -60
- package/.framework/src/pages/admin/AppsPage.tsx +104 -66
- package/.framework/src/pages/admin/DeliveriesPage.tsx +5 -5
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +5 -23
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +5 -26
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +7 -7
- package/.framework/src/pages/admin/IntegrationsPage.tsx +85 -43
- package/.framework/src/pages/admin/LogsPage.tsx +144 -76
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +223 -140
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +134 -113
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +108 -45
- package/.framework/src/pages/admin/PipelinesPage.tsx +160 -115
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +96 -98
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +101 -59
- package/.framework/src/pages/admin/RoleDetailPage.tsx +90 -79
- package/.framework/src/pages/admin/RolesPage.tsx +86 -43
- package/.framework/src/pages/admin/SecurityPage.tsx +1 -1
- package/.framework/src/pages/admin/TestingDashboard.tsx +16 -28
- package/.framework/src/pages/admin/TimerDetailPage.tsx +117 -100
- package/.framework/src/pages/admin/TimersPage.tsx +90 -62
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +90 -83
- package/.framework/src/pages/admin/TriggersPage.tsx +124 -99
- package/.framework/src/pages/admin/TypeDetailPage.tsx +152 -138
- package/.framework/src/pages/admin/TypesPage.tsx +90 -48
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +17 -25
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +17 -27
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +72 -40
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +321 -129
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +18 -29
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +26 -38
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +34 -46
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +189 -103
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +246 -136
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +11 -22
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +9 -20
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +26 -38
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +7 -26
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +3 -1
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +3 -1
- package/.framework/src/pages/auth/LoginPage.tsx +4 -2
- package/.framework/src/pages/auth/RegisterPage.tsx +3 -1
- package/.framework/templates/agent/AGENTS.md +150 -0
- package/.framework/templates/agent/skills/spine-add-ai-agent/SKILL.md +58 -0
- package/.framework/templates/agent/skills/spine-add-automation/SKILL.md +62 -0
- package/.framework/templates/agent/skills/spine-add-integration/SKILL.md +63 -0
- package/.framework/templates/agent/skills/spine-architect/SKILL.md +86 -0
- package/.framework/templates/agent/skills/spine-install-app/SKILL.md +72 -0
- package/.framework/templates/agent/skills/spine-migration/SKILL.md +75 -0
- package/.framework/templates/agent/skills/spine-new-app/SKILL.md +67 -0
- package/.framework/templates/agent/skills/spine-new-function/SKILL.md +65 -0
- package/.framework/templates/agent/skills/spine-new-type/SKILL.md +65 -0
- package/.framework/templates/agent/skills/spine-schema/SKILL.md +77 -0
- package/.framework/templates/agent/skills/spine-test/SKILL.md +67 -0
- package/.framework/templates/agent/skills/spine-troubleshoot/SKILL.md +74 -0
- package/.framework/templates/agent/skills/spine-upgrade/SKILL.md +69 -0
- package/.framework/templates/project.json +5 -1
- package/.framework/tests/unit/account-scoping-gates.test.ts +392 -0
- package/.framework/tests/unit/agent-files.test.ts +355 -0
- package/.framework/tests/unit/agent-runner.test.ts +496 -47
- package/.framework/tests/unit/api-keys-create-scope-gate.test.ts +160 -0
- package/.framework/tests/unit/api-keys-omit-secret-fields.test.ts +38 -0
- package/.framework/tests/unit/bootstrap.test.ts +242 -0
- package/.framework/tests/unit/cli-context-api-key.test.ts +114 -0
- package/.framework/tests/unit/debug-auth.test.ts +38 -0
- package/.framework/tests/unit/deliveries-account-scoping.test.ts +185 -0
- package/.framework/tests/unit/episode-lease.test.ts +695 -0
- package/.framework/tests/unit/integration-outbound-credentials.test.ts +167 -0
- package/.framework/tests/unit/integrations-audit-redaction.test.ts +130 -0
- package/.framework/tests/unit/kb-ingest-lease.test.ts +19 -0
- package/.framework/tests/unit/logging-app-id.test.ts +75 -0
- package/.framework/tests/unit/pipeline-runner-background.test.ts +120 -0
- package/.framework/tests/unit/pipeline-runner.test.ts +153 -1
- package/.framework/tests/unit/principal-cache.test.ts +15 -0
- package/.framework/tests/unit/system-context-denial.test.ts +145 -0
- package/.framework/tests/unit/system-cron.test.ts +240 -0
- package/.framework/tests/unit/timers.test.ts +159 -0
- package/.framework/tests/unit/trigger-engine.test.ts +278 -91
- package/.framework/tests/unit/trigger-scheduler.test.ts +78 -0
- package/README.md +125 -166
- package/config/tsconfig.cli.json +2 -2
- package/netlify.toml +5 -0
- package/package.json +15 -4
- package/templates/project/package-lock.json +2 -2
- package/.framework/docs/admin-routes.md +0 -76
- package/.framework/docs/api-docs-progress.md +0 -38
- package/.framework/docs/api-governance.md +0 -146
- package/.framework/docs/api-testing-results.md +0 -212
- package/.framework/docs/assembly-launch-guide.md +0 -138
- package/.framework/docs/audit-results.md +0 -590
- package/.framework/docs/db-api-inventory.md +0 -95
- package/.framework/docs/gap-remediation-backlog.md +0 -103
- package/.framework/docs/ui-adoption-verification.md +0 -111
- package/.framework/docs/ui-api-coverage.md +0 -84
- package/.framework/docs/v2-compatibility-audit.md +0 -228
- package/.framework/mcp/index.ts +0 -133
- package/.framework/mcp/load-env.ts +0 -60
- package/.framework/mcp/shared/app-manifest.ts +0 -275
- package/.framework/mcp/shared/db.ts +0 -477
- package/.framework/mcp/shared/kb.ts +0 -118
- package/.framework/mcp/tools/architect.ts +0 -431
- package/.framework/mcp/tools/cil/context.ts +0 -345
- package/.framework/mcp/tools/cil/graph.ts +0 -242
- package/.framework/mcp/tools/cil/ingest.ts +0 -1217
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +0 -693
- package/.framework/mcp/tools/cil/pipeline.ts +0 -767
- package/.framework/mcp/tools/cil/project.ts +0 -791
- package/.framework/mcp/tools/cil/retrieval.ts +0 -336
- package/.framework/mcp/tools/cil/search-core.ts +0 -454
- package/.framework/mcp/tools/cil/search.ts +0 -97
- package/.framework/mcp/tools/cil/suggest.ts +0 -186
- package/.framework/mcp/tools/cil/validate.ts +0 -1369
- package/.framework/mcp/tools/kb/delete.ts +0 -139
- package/.framework/mcp/tools/kb/index.ts +0 -52
- package/.framework/mcp/tools/kb/ingest.ts +0 -84
- package/.framework/mcp/tools/kb/list-types.ts +0 -102
- package/.framework/mcp/tools/kb/publish.ts +0 -100
- package/.framework/mcp/tools/kb/reindex.ts +0 -86
- package/.framework/mcp/tools/kb/revoke.ts +0 -85
- package/.framework/mcp/tools/kb/search.ts +0 -101
- package/.framework/mcp/tools/kb/upsert.ts +0 -125
- package/.framework/mcp/tools/observability.ts +0 -510
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: The Spine domain model
|
|
3
|
+
audience: developers, agents
|
|
4
|
+
kind: guide
|
|
5
|
+
verified_against: f69c37d
|
|
6
|
+
verified_on: 2026-10-29
|
|
7
|
+
source_files:
|
|
8
|
+
- .framework/migrations/001_core_schema.sql
|
|
9
|
+
- .framework/migrations/003_core_system_data.sql
|
|
10
|
+
- .framework/migrations/004_core_rpc_and_broker.sql
|
|
11
|
+
- .framework/migrations/020_schema_reconciliation.sql
|
|
12
|
+
- .framework/functions/admin-data.ts
|
|
13
|
+
- .framework/functions/_shared/permissions.ts
|
|
14
|
+
- .framework/functions/_shared/principal.ts
|
|
15
|
+
- .framework/functions/_shared/trigger-engine.ts
|
|
16
|
+
- .framework/functions/_shared/pipeline-runner.ts
|
|
17
|
+
- .framework/functions/system-cron.ts
|
|
18
|
+
- .framework/functions/trigger-scheduler.ts
|
|
19
|
+
- .framework/functions/pipeline-runner-background.ts
|
|
20
|
+
- .framework/src/App.tsx
|
|
21
|
+
- .framework/src/components/app-shell/GenericAppShell.tsx
|
|
22
|
+
- .framework/src/components/CustomAppLoader.tsx
|
|
23
|
+
- .framework/src/contexts/AppContext.tsx
|
|
24
|
+
- .framework/src/hooks/useApps.ts
|
|
25
|
+
- netlify.toml
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
# The Spine domain model
|
|
29
|
+
|
|
30
|
+
Everything in Spine is one of about ten primitives. Once you can name them and
|
|
31
|
+
say how they connect, the whole system — admin UI, APIs, automation — is just
|
|
32
|
+
compositions of the diagram below.
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
┌──────────────────────── IDENTITY ────────────────────────┐
|
|
36
|
+
│ │
|
|
37
|
+
auth.users (Supabase) │ account ──< people >── role │
|
|
38
|
+
│ │ (tenant, (human, (permission │
|
|
39
|
+
│ auth_uid │ tree via auth_uid, set; system_admin │
|
|
40
|
+
▼ │ parent_id account_id, is the seeded root) │
|
|
41
|
+
JWT / x-api-key ──────┤ + account_ role_id) │
|
|
42
|
+
│ │ paths) │
|
|
43
|
+
▼ └──────────────────────────┬─────────────────────────────┘
|
|
44
|
+
principal ─────────── every request resolves one │
|
|
45
|
+
(anonymous | human | machine | system) │
|
|
46
|
+
▼
|
|
47
|
+
┌──────────────────────── SCHEMA ─────────────────────────┐
|
|
48
|
+
│ type (kind + slug) → design_schema → validation_schema │
|
|
49
|
+
│ fields · views · record_permissions · scope │
|
|
50
|
+
└──────────────────────────┬─────────────────────────────┘
|
|
51
|
+
│ stamped at create
|
|
52
|
+
▼
|
|
53
|
+
┌──────────────────────── RECORDS ────────────────────────┐
|
|
54
|
+
│ items · threads · messages · links · attachments · │
|
|
55
|
+
│ watchers (+ accounts, people as records) │
|
|
56
|
+
│ system columns + data jsonb + stamped schemas │
|
|
57
|
+
└──────────────────────────┬─────────────────────────────┘
|
|
58
|
+
│ CRUD via /api/admin-data
|
|
59
|
+
┌──────────────────────── APPS ◄────────────┘ renders / consumes
|
|
60
|
+
│ generic | custom | none │
|
|
61
|
+
│ app row: slug, route_prefix, renderer, ▼
|
|
62
|
+
│ nav_items, roles ┌────────────────────── AUTOMATION ───────┐
|
|
63
|
+
└───────────────┬────────────────┤ triggers (event) → pipelines (stages) │
|
|
64
|
+
│ seeds/owns │ timers (cron/interval/once) ──┘ │
|
|
65
|
+
▼ │ integrations (adapters+creds) │
|
|
66
|
+
┌──────────────────────── AI ────┤ ai_agents · prompt_configs · │
|
|
67
|
+
│ embeddings (pgvector search) │ embeddings │
|
|
68
|
+
└────────────────────────────────┴──────────────┬────────────────────────┘
|
|
69
|
+
▼
|
|
70
|
+
┌──────────────────────── OBSERVE ────────────────────────┐
|
|
71
|
+
│ logs · observability · pipeline_executions · │
|
|
72
|
+
│ trigger_executions · webhook_deliveries · │
|
|
73
|
+
│ api_key_usage_logs · audit │
|
|
74
|
+
└─────────────────────────────────────────────────────────┘
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Identity: account → person → role → principal
|
|
78
|
+
|
|
79
|
+
- **Account** (`public.accounts`) — the tenant. Accounts form a hierarchy via
|
|
80
|
+
`parent_id` + the `account_paths` closure table; the seeded `spine-system`
|
|
81
|
+
account is the platform root
|
|
82
|
+
(`.framework/migrations/011_spine_system_account.sql`).
|
|
83
|
+
- **Person** (`public.people`) — a human user, bound to `auth.users` by
|
|
84
|
+
`auth_uid`, placed in one `account_id`, holding one `role_id`. Like every
|
|
85
|
+
runtime record, a person row also carries `type_id` and `data`.
|
|
86
|
+
- **Role** (`public.roles`) — a named permission set with a globally unique
|
|
87
|
+
`slug`. `system_admin` is seeded, protected, and bypasses record-level
|
|
88
|
+
checks (`.framework/migrations/003_core_system_data.sql`).
|
|
89
|
+
- **Principal** — the *resolved* identity of a request, computed per call by
|
|
90
|
+
`.framework/functions/_shared/principal.ts`: `x-api-key` header → machine
|
|
91
|
+
principal (verified against `api_keys` hash), internal-invoke headers →
|
|
92
|
+
cron/trigger/system, `Authorization: Bearer` JWT → human principal, anything
|
|
93
|
+
else → anonymous. Handlers receive it as `ctx.principal` with
|
|
94
|
+
`ctx.accountId`.
|
|
95
|
+
|
|
96
|
+
## Schema: type → design_schema → validation_schema
|
|
97
|
+
|
|
98
|
+
A **type** (`public.types`) is the schema for a record kind. `kind` selects the
|
|
99
|
+
runtime table — `item`, `thread`, `message`, `link`, `attachment`, `watcher`,
|
|
100
|
+
`account`, `person` — and `(kind, slug)` is unique. Its `design_schema` JSON
|
|
101
|
+
carries:
|
|
102
|
+
|
|
103
|
+
- `fields` — each with `data_type`, `label`, `required`, and optional
|
|
104
|
+
`system` flag.
|
|
105
|
+
- `views` — `default_list` / `default_detail` consumed by the generic UI.
|
|
106
|
+
- `record_permissions` — per-role base grant of `create`/`read`/`update`/
|
|
107
|
+
`delete`; `fields.*.permissions` exists only to *override* that base per
|
|
108
|
+
field (`.framework/functions/_shared/permissions.ts`).
|
|
109
|
+
- `scope` — `account` (tenant data, the default) or `platform` (record is
|
|
110
|
+
re-anchored to the `spine-system` account at create).
|
|
111
|
+
|
|
112
|
+
`validation_schema` is **generated from `design_schema`** on every save
|
|
113
|
+
(`.framework/functions/types.ts` via `_shared/schema-utils.ts`) — never
|
|
114
|
+
hand-edit it.
|
|
115
|
+
|
|
116
|
+
## Records: the runtime tables
|
|
117
|
+
|
|
118
|
+
Six typed record tables — `items`, `threads`, `messages`, `links`,
|
|
119
|
+
`attachments`, `watchers` — plus `accounts` and `people` in the same shape
|
|
120
|
+
(`.framework/migrations/001_core_schema.sql`). Every record has:
|
|
121
|
+
|
|
122
|
+
- **system columns** — `id`, `type_id`, `account_id`, `app_id`, `created_at`,
|
|
123
|
+
`updated_at`, `created_by`, `is_active`, plus kind-specific ones
|
|
124
|
+
(`items.title/status`, `threads.target_type/target_id`,
|
|
125
|
+
`messages.thread_id/sequence`, `links.source_*/target_*`,
|
|
126
|
+
`attachments.storage_path`, `watchers.person_id`).
|
|
127
|
+
- **`data` jsonb** — where all non-system schema fields live. Convention:
|
|
128
|
+
`system: true` fields read from `record.<field>`; everything else from
|
|
129
|
+
`record.data.<field>` (see `GenericDetailPage` splitting on
|
|
130
|
+
`fieldDef.system` in `.framework/src/components/app-shell/GenericDetailPage.tsx`).
|
|
131
|
+
- **stamped `design_schema` + `validation_schema`** — copied from the type at
|
|
132
|
+
create time by `admin-data` (`create` in `.framework/functions/admin-data.ts`),
|
|
133
|
+
so the record is the source of truth for its own permissions even if the
|
|
134
|
+
type changes later.
|
|
135
|
+
|
|
136
|
+
All CRUD flows through `/api/admin-data` (`action=list|get|stats|create|
|
|
137
|
+
update|remove`, `entity=<table>`; GET for reads, POST/PATCH/DELETE for writes). The handler maps entity → kind
|
|
138
|
+
(`ENTITY_TO_KIND`), resolves `type_slug`/`type_id`, evaluates record/field
|
|
139
|
+
permissions, writes, then fires create/update/delete triggers.
|
|
140
|
+
|
|
141
|
+
## Apps: registry + two renderers
|
|
142
|
+
|
|
143
|
+
An **app** (`public.apps`) is a registered application: `slug`,
|
|
144
|
+
`route_prefix`, `renderer`, `nav_items`, `min_role`/`required_roles`,
|
|
145
|
+
`config`, `is_active`, `is_system`. The authenticated router
|
|
146
|
+
(`.framework/src/App.tsx`) mounts every routable app at its `route_prefix`:
|
|
147
|
+
|
|
148
|
+
- **`renderer: 'generic'`** — `GenericAppShell` builds the UI *from data*: the
|
|
149
|
+
sidebar comes from `nav_items`, and each nav item with a `type_slug` gets
|
|
150
|
+
list/new/detail routes rendered by `GenericListPage`/`GenericDetailPage`
|
|
151
|
+
straight from the type's `views`
|
|
152
|
+
(`.framework/src/components/app-shell/GenericAppShell.tsx`).
|
|
153
|
+
- **`renderer: 'custom'`** — `CustomAppLoader` lazy-loads
|
|
154
|
+
`custom/apps/<slug>/index.tsx` (falling back to
|
|
155
|
+
`.framework/src/apps/<slug>/index.tsx`)
|
|
156
|
+
(`.framework/src/components/CustomAppLoader.tsx`). Custom apps render their
|
|
157
|
+
own pages but still use `/api/admin-data` for record CRUD.
|
|
158
|
+
- **`renderer: 'none'`** — registry-only; not routable.
|
|
159
|
+
|
|
160
|
+
## Automation: triggers → pipelines, timers → pipelines
|
|
161
|
+
|
|
162
|
+
- **Pipeline** (`public.pipelines`) — a `stages` array executed in order by
|
|
163
|
+
`runPipeline` (`.framework/functions/_shared/pipeline-runner.ts`). Each
|
|
164
|
+
stage's `stage_type` resolves to a `public.actions` row or a built-in
|
|
165
|
+
handler (`update_item`, `create_record`, `http_request`,
|
|
166
|
+
`send_notification`, `send_email`, `run_pipeline`, `query_items`,
|
|
167
|
+
`agent_inference`, `search_knowledge`, `generate_embeddings`,
|
|
168
|
+
`revoke_embeddings`, `kb_ingest`, `kb_revoke`, `create_interaction`).
|
|
169
|
+
Every run writes a `pipeline_executions` row.
|
|
170
|
+
- **Trigger** (`public.triggers`) — `event_type` + `pipeline_id` (+ optional
|
|
171
|
+
`config` filters). `admin-data` calls `fireCreate/Update/DeleteTriggers`
|
|
172
|
+
after each write; events are named `<entity>_<created|updated|deleted>`
|
|
173
|
+
(e.g. `item_created`). A match enqueues a `pipeline_executions` row and
|
|
174
|
+
dispatches to the `pipeline-runner-background` function over HTTP — which
|
|
175
|
+
requires `INTERNAL_INVOKE_SECRET` to be set
|
|
176
|
+
(`.framework/functions/_shared/trigger-engine.ts`).
|
|
177
|
+
- **Timer** (`public.timers`) — `timer_type` (`interval` | `cron` | `once`) +
|
|
178
|
+
`pipeline_id` + schedule in `config`. The scheduled function
|
|
179
|
+
`trigger-scheduler` (every minute, `netlify.toml`) runs `system-cron`,
|
|
180
|
+
which calls the `get_due_timers` RPC and executes each due timer's pipeline
|
|
181
|
+
under a `timer:*` machine principal
|
|
182
|
+
(`.framework/functions/system-cron.ts`).
|
|
183
|
+
|
|
184
|
+
## Integrations and AI
|
|
185
|
+
|
|
186
|
+
- **Integration** (`public.integrations`) — a named adapter + `config` +
|
|
187
|
+
`credentials` (`{"env_var": "NAME"}` resolved in the function environment,
|
|
188
|
+
or a literal `{"value": …}`). Inbound webhooks arrive via
|
|
189
|
+
`integration-routes`; outbound calls go through `integration-outbound`,
|
|
190
|
+
which records each attempt in `public.webhook_deliveries` (the deliveries
|
|
191
|
+
ledger — `system-cron` retries pending ones via
|
|
192
|
+
`.framework/functions/_shared/retry-deliveries.ts`).
|
|
193
|
+
- **AI agent** (`public.ai_agents`) — a model/prompt/tool config invocable via
|
|
194
|
+
`/api/ai-agents?action=run` or the `agent_inference` pipeline stage.
|
|
195
|
+
**Prompt config** (`public.prompt_configs`) — named, versioned prompt
|
|
196
|
+
templates agents and stages reference.
|
|
197
|
+
- **Embedding** (`public.embeddings`) — pgvector vectors with the
|
|
198
|
+
`match_embeddings` / `search_similar_embeddings` RPCs
|
|
199
|
+
(`.framework/migrations/004_core_rpc_and_broker.sql`), powering semantic
|
|
200
|
+
search and the `search_knowledge` stage type.
|
|
201
|
+
|
|
202
|
+
## Observability: everything leaves a trail
|
|
203
|
+
|
|
204
|
+
`public.logs` (per-account log stream), `public.observability` (metrics),
|
|
205
|
+
`pipeline_executions` + `trigger_executions` (automation history),
|
|
206
|
+
`webhook_deliveries` (outbound attempts), `api_key_usage_logs` (machine
|
|
207
|
+
principal usage), and audit events emitted by `emitAudit` on privileged
|
|
208
|
+
actions. The admin UI surfaces them under Observability, Deliveries, and
|
|
209
|
+
Executions (`.framework/functions/logs.ts`,
|
|
210
|
+
`.framework/functions/observability.ts`,
|
|
211
|
+
`.framework/functions/pipeline-executions.ts`,
|
|
212
|
+
`.framework/functions/deliveries.ts`).
|
|
213
|
+
|
|
214
|
+
## Where to go next
|
|
215
|
+
|
|
216
|
+
- Entity deep-dives: [types](../types.md), [apps](../apps.md),
|
|
217
|
+
[roles](../roles.md), [pipelines](../pipelines.md),
|
|
218
|
+
[triggers](../triggers.md), [timers](../timers.md),
|
|
219
|
+
[integrations](../integrations.md), [ai-agents](../ai-agents.md),
|
|
220
|
+
[prompts](../prompts.md), [api-keys](../api-keys.md),
|
|
221
|
+
[deliveries](../deliveries.md).
|
|
222
|
+
- Build something: [04-first-app.md](./04-first-app.md).
|
|
223
|
+
- Terminology: [05-glossary.md](./05-glossary.md).
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Build your first app
|
|
3
|
+
audience: developers, agents
|
|
4
|
+
kind: guide
|
|
5
|
+
verified_against: f69c37d
|
|
6
|
+
verified_on: 2026-10-29
|
|
7
|
+
source_files:
|
|
8
|
+
- .framework/functions/types.ts
|
|
9
|
+
- .framework/functions/apps.ts
|
|
10
|
+
- .framework/functions/admin-data.ts
|
|
11
|
+
- .framework/functions/_shared/trigger-engine.ts
|
|
12
|
+
- .framework/functions/_shared/schema-utils.ts
|
|
13
|
+
- .framework/src/components/app-shell/GenericAppShell.tsx
|
|
14
|
+
- .framework/src/components/app-shell/GenericListPage.tsx
|
|
15
|
+
- .framework/src/components/app-shell/GenericDetailPage.tsx
|
|
16
|
+
- .framework/src/components/CustomAppLoader.tsx
|
|
17
|
+
- .framework/src/contexts/AppContext.tsx
|
|
18
|
+
- .framework/src/lib/api.ts
|
|
19
|
+
- .framework/cli/commands/create-app.ts
|
|
20
|
+
- .framework/cli/commands/generate.ts
|
|
21
|
+
- .framework/cli/commands/install-app.ts
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# Build your first app
|
|
25
|
+
|
|
26
|
+
The smallest useful Spine app is one type + one app row — no code at all.
|
|
27
|
+
This walkthrough builds a `task` tracker end to end, then adds a custom page
|
|
28
|
+
and a pipeline. You need a `system_admin` login (see
|
|
29
|
+
[01-install-and-first-run.md](./01-install-and-first-run.md)) — app creation
|
|
30
|
+
is restricted to system admins (`.framework/functions/apps.ts`).
|
|
31
|
+
|
|
32
|
+
## Step 1 — define the type
|
|
33
|
+
|
|
34
|
+
Admin UI → **Configs → Types → New** (or `POST /api/types`). Set:
|
|
35
|
+
|
|
36
|
+
- **Kind**: `item` — records land in `public.items`.
|
|
37
|
+
- **Slug**: `task` — unique within `kind`; callers resolve types by it.
|
|
38
|
+
- **Design schema** — the fields, views, and permissions below.
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"scope": "account",
|
|
43
|
+
"fields": {
|
|
44
|
+
"title": { "data_type": "text", "label": "Title", "required": true, "system": true },
|
|
45
|
+
"status": { "data_type": "select", "label": "Status", "required": true,
|
|
46
|
+
"options": ["todo", "doing", "done"] },
|
|
47
|
+
"priority": { "data_type": "select", "label": "Priority", "required": false,
|
|
48
|
+
"options": ["low", "normal", "high"] },
|
|
49
|
+
"notes": { "data_type": "textarea", "label": "Notes", "required": false }
|
|
50
|
+
},
|
|
51
|
+
"views": {
|
|
52
|
+
"default_list": {
|
|
53
|
+
"type": "list", "display": "table", "label": "Tasks",
|
|
54
|
+
"fields": {
|
|
55
|
+
"title": { "sortable": true, "display_type": "text" },
|
|
56
|
+
"status": { "sortable": true, "display_type": "badge" },
|
|
57
|
+
"priority": { "sortable": true, "display_type": "badge" },
|
|
58
|
+
"created_at": { "sortable": true, "display_type": "timestamp" }
|
|
59
|
+
},
|
|
60
|
+
"default_sort": { "field": "created_at", "direction": "desc" }
|
|
61
|
+
},
|
|
62
|
+
"default_detail": {
|
|
63
|
+
"type": "detail", "label": "Task",
|
|
64
|
+
"sections": [
|
|
65
|
+
{ "title": "Core",
|
|
66
|
+
"fields": {
|
|
67
|
+
"title": { "display_type": "input" },
|
|
68
|
+
"status": { "display_type": "select" },
|
|
69
|
+
"priority": { "display_type": "select" },
|
|
70
|
+
"notes": { "display_type": "textarea" }
|
|
71
|
+
} }
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"record_permissions": {
|
|
76
|
+
"system_admin": ["create", "read", "update", "delete"],
|
|
77
|
+
"engineering": ["create", "read", "update"]
|
|
78
|
+
},
|
|
79
|
+
"functionality": null
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
On save, `validation_schema` is regenerated from `design_schema` by the types
|
|
84
|
+
API (`.framework/functions/types.ts`,
|
|
85
|
+
`.framework/functions/_shared/schema-utils.ts`) — you never write it yourself.
|
|
86
|
+
The rules that matter here: `select` fields need `options`; `title` is
|
|
87
|
+
`system: true` so it maps to the `items.title` column while `status`,
|
|
88
|
+
`priority`, and `notes` live in `items.data`; `record_permissions` is the base
|
|
89
|
+
grant evaluated on every `/api/admin-data` call, and its keys are matched
|
|
90
|
+
**verbatim** against `roles.slug` — so use real seeded slugs (`system_admin`,
|
|
91
|
+
`engineering`, `support`, …); a nonexistent or misspelled slug silently grants
|
|
92
|
+
nothing (`.framework/functions/_shared/permissions.ts`).
|
|
93
|
+
|
|
94
|
+
## Step 2 — register the app
|
|
95
|
+
|
|
96
|
+
Admin UI → **Configs → Apps → New** (or `POST /api/apps`):
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"slug": "taskboard",
|
|
101
|
+
"name": "Taskboard",
|
|
102
|
+
"route_prefix": "/taskboard",
|
|
103
|
+
"renderer": "generic",
|
|
104
|
+
"min_role": "engineering",
|
|
105
|
+
"is_active": true,
|
|
106
|
+
"nav_items": [
|
|
107
|
+
{ "id": "tasks", "label": "Tasks", "path": "tasks", "type_slug": "task" }
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`route_prefix` mounts the app at `/taskboard`; `renderer: "generic"` tells the
|
|
113
|
+
router to use `GenericAppShell`; each `nav_items` entry with a `type_slug`
|
|
114
|
+
gets list, `new`, and `:id` routes rendered from the type's views
|
|
115
|
+
(`.framework/src/components/app-shell/GenericAppShell.tsx`,
|
|
116
|
+
`GenericListPage.tsx`, `GenericDetailPage.tsx`). An app is routable when it
|
|
117
|
+
has a `route_prefix` and a renderer other than `none`
|
|
118
|
+
(`.framework/src/contexts/AppContext.tsx`).
|
|
119
|
+
|
|
120
|
+
Sign out/in (or wait for the apps registry refetch) and `/taskboard` renders
|
|
121
|
+
the Tasks list — create, edit, sort, and detail all work with zero code.
|
|
122
|
+
|
|
123
|
+
## Step 3 — add custom UI
|
|
124
|
+
|
|
125
|
+
When the generic views are not enough, switch `renderer` to `custom` and put
|
|
126
|
+
your code where the loader looks for it:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npx spine-framework create-app taskboard --role engineering
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
This scaffolds `custom/apps/taskboard/` with `manifest.json`, `index.tsx`
|
|
133
|
+
(a React Router stub), and `components/`, and registers the `apps` row with
|
|
134
|
+
`renderer: 'custom'` (`.framework/cli/commands/create-app.ts` — if the row
|
|
135
|
+
already exists it skips the insert). `CustomAppLoader` lazy-loads
|
|
136
|
+
`custom/apps/taskboard/index.tsx` via `import.meta.glob`
|
|
137
|
+
(`.framework/src/components/CustomAppLoader.tsx`), so edit the component, then:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npm run dev:netlify # assemble runs automatically; or: npm run assemble && netlify dev
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Your app is a normal React app under the `/taskboard/*` route, inside
|
|
144
|
+
`AppWrapper`. Custom functions go in `custom/functions/` (prefix filenames
|
|
145
|
+
`custom_` — assembly hard-fails on basename collisions with framework
|
|
146
|
+
functions; see [02-project-map.md](./02-project-map.md)).
|
|
147
|
+
|
|
148
|
+
## Step 4 — CRUD via `/api/admin-data`
|
|
149
|
+
|
|
150
|
+
Custom pages use the same endpoint as the generic renderer — never write a
|
|
151
|
+
bespoke CRUD function:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
import { apiFetch } from '@core/lib/api' // assembled alias → .framework/src
|
|
155
|
+
|
|
156
|
+
// list
|
|
157
|
+
await apiFetch('/api/admin-data?action=list&entity=items&type_slug=task&limit=50')
|
|
158
|
+
|
|
159
|
+
// create — type_slug resolves the type; non-system fields go in `data`
|
|
160
|
+
await apiFetch('/api/admin-data?action=create', {
|
|
161
|
+
method: 'POST',
|
|
162
|
+
headers: { 'Content-Type': 'application/json' },
|
|
163
|
+
body: JSON.stringify({
|
|
164
|
+
entity: 'items',
|
|
165
|
+
type_slug: 'task',
|
|
166
|
+
title: 'Ship the docs',
|
|
167
|
+
data: { status: 'todo', priority: 'high' }
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
// update — entity + id are query params; the body is the field patch
|
|
172
|
+
await apiFetch('/api/admin-data?action=update&entity=items&id=<uuid>', {
|
|
173
|
+
method: 'PATCH',
|
|
174
|
+
headers: { 'Content-Type': 'application/json' },
|
|
175
|
+
body: JSON.stringify({ data: { status: 'doing' } })
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
// remove — soft-deletes (is_active = false) unless soft=false is passed
|
|
179
|
+
await apiFetch(`/api/admin-data?action=remove&entity=items&id=<uuid>`, { method: 'DELETE' })
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
`apiFetch` (`.framework/src/lib/api.ts`) attaches the Supabase Bearer token and
|
|
183
|
+
the `X-Account-Id` header; `admin-data` resolves `task` → its `type_id`,
|
|
184
|
+
stamps `design_schema`/`validation_schema` onto the new record, evaluates
|
|
185
|
+
`record_permissions` for the caller's role, writes, and fires
|
|
186
|
+
`item_created` triggers (`.framework/functions/admin-data.ts`).
|
|
187
|
+
|
|
188
|
+
## Step 5 — wire a pipeline
|
|
189
|
+
|
|
190
|
+
1. Admin UI → **Configs → Pipelines → New**: name it, `trigger_type` =
|
|
191
|
+
`event`, `stages` = e.g. a `send_notification` stage
|
|
192
|
+
(`.framework/functions/_shared/pipeline-runner.ts` has the built-in
|
|
193
|
+
`stage_type` list).
|
|
194
|
+
2. Admin UI → **Configs → Triggers → New**: `event_type` = `item_created`,
|
|
195
|
+
`pipeline_id` = the pipeline from step 1, `config.type_slug` = `task` to
|
|
196
|
+
scope it (`.framework/functions/_shared/trigger-engine.ts`).
|
|
197
|
+
3. Ensure `INTERNAL_INVOKE_SECRET` is set — trigger dispatch POSTs to the
|
|
198
|
+
`pipeline-runner-background` function and silently no-ops without it.
|
|
199
|
+
4. Create a task → the trigger queues a `pipeline_executions` row and the
|
|
200
|
+
background runner executes the stages; watch it under
|
|
201
|
+
**Observability → Executions**.
|
|
202
|
+
|
|
203
|
+
## Gaps
|
|
204
|
+
|
|
205
|
+
- **`npx spine-framework generate` was removed.** The old scaffold wrote
|
|
206
|
+
stubs to a `v2-custom/` tree with `../v2-core/...` imports and a legacy
|
|
207
|
+
`design_schema` shape (`type`/`layout` instead of `data_type`/`views`). It
|
|
208
|
+
now prints migration guidance and exits 1
|
|
209
|
+
(`.framework/cli/commands/generate.ts`). Author types in the admin UI or via
|
|
210
|
+
`/api/types` instead.
|
|
211
|
+
- **`create-app` defaults `--role member`.** `member` and `member_admin`
|
|
212
|
+
are seeded by `.framework/migrations/073_seed_member_roles.sql` (003
|
|
213
|
+
seeds `system_admin`, `engineering`, `engineering_admin`, `product`,
|
|
214
|
+
`docs`, `qa`, `devops`, `management`, `sales`, `csm`, `tam`, `support`,
|
|
215
|
+
`support_admin`), so the default is valid on current installs. On a
|
|
216
|
+
database that predates 073, pass `--role` a slug that exists in your
|
|
217
|
+
`roles` table or create the role first.
|
|
218
|
+
- **`create-app` scaffold is minimal** — a `Routes` stub only. There is no
|
|
219
|
+
generated CRUD page, `admin-data` hook, or seed block in the manifest it
|
|
220
|
+
writes; the pattern in Step 4 is the integration contract.
|
|
221
|
+
- **Generic renderer is list/detail only.** `GenericAppShell` generates routes
|
|
222
|
+
solely for nav items carrying `type_slug`; a nav item without one renders a
|
|
223
|
+
sidebar button that navigates nowhere routable. Dashboards, wizards, or
|
|
224
|
+
bespoke layouts require `renderer: 'custom'`.
|
|
225
|
+
- **No packaged example app ships in the npm package** — `custom/` is created
|
|
226
|
+
empty by `init`, so there is no reference implementation to copy inside an
|
|
227
|
+
installed project.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Glossary
|
|
3
|
+
audience: developers, agents
|
|
4
|
+
kind: guide
|
|
5
|
+
verified_against: f69c37d
|
|
6
|
+
verified_on: 2026-10-29
|
|
7
|
+
source_files:
|
|
8
|
+
- .framework/migrations/001_core_schema.sql
|
|
9
|
+
- .framework/migrations/004_core_rpc_and_broker.sql
|
|
10
|
+
- .framework/migrations/011_spine_system_account.sql
|
|
11
|
+
- .framework/migrations/020_schema_reconciliation.sql
|
|
12
|
+
- .framework/functions/admin-data.ts
|
|
13
|
+
- .framework/functions/_shared/principal.ts
|
|
14
|
+
- .framework/functions/_shared/permissions.ts
|
|
15
|
+
- .framework/functions/_shared/trigger-engine.ts
|
|
16
|
+
- .framework/functions/_shared/pipeline-runner.ts
|
|
17
|
+
- .framework/functions/system-cron.ts
|
|
18
|
+
- .framework/cli/lib/project-files.ts
|
|
19
|
+
- .framework/src/components/CustomAppLoader.tsx
|
|
20
|
+
- .framework/src/components/app-shell/GenericAppShell.tsx
|
|
21
|
+
- scripts/assemble.sh
|
|
22
|
+
- scripts/assemble-frontend.sh
|
|
23
|
+
- scripts/assemble-functions.sh
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# Glossary
|
|
27
|
+
|
|
28
|
+
The Spine vocabulary, in dependency order. Terms in **bold** are defined
|
|
29
|
+
elsewhere on this page or in the [domain model](./03-domain-model.md).
|
|
30
|
+
|
|
31
|
+
## Identity
|
|
32
|
+
|
|
33
|
+
**account** — a tenant boundary (`public.accounts`). Every runtime record is
|
|
34
|
+
scoped to an `account_id`; accounts nest via `parent_id` with the
|
|
35
|
+
`account_paths` closure table for descendant lookups. The seeded `spine-system`
|
|
36
|
+
account is the platform root (see **scope**).
|
|
37
|
+
|
|
38
|
+
**person** — a human user (`public.people`), linked to Supabase `auth.users`
|
|
39
|
+
by `auth_uid` and placed in one account with one role. Non-first,
|
|
40
|
+
non-invited signups have no account until registration placement assigns one.
|
|
41
|
+
|
|
42
|
+
**principal** — the resolved identity attached to a request (`ctx.principal`),
|
|
43
|
+
computed per call by `.framework/functions/_shared/principal.ts`. One of:
|
|
44
|
+
`human` (Bearer JWT → person), `machine` (`x-api-key` header → API key, or
|
|
45
|
+
internal cron/trigger principal), `system` (internal invoke), or `anonymous`.
|
|
46
|
+
Carries `id`, `type`, `accountId`, `roles`, `scopes`, and provenance.
|
|
47
|
+
|
|
48
|
+
**role** — a named permission set (`public.roles`, unique `slug`) assigned to
|
|
49
|
+
a person. Roles are referenced throughout `design_schema.record_permissions`.
|
|
50
|
+
`system_admin` is the seeded superuser role; roles ending in `_admin` can
|
|
51
|
+
manage invites/members within their own account.
|
|
52
|
+
|
|
53
|
+
## Schema
|
|
54
|
+
|
|
55
|
+
**type** — the schema definition for a record kind (`public.types`), unique
|
|
56
|
+
per `(kind, slug)`. Carries `design_schema` (generated into
|
|
57
|
+
`validation_schema`), `ownership` (`system` | `app` | `tenant`), `icon`,
|
|
58
|
+
`color`, `is_active`.
|
|
59
|
+
|
|
60
|
+
**design_schema** — the authoring-format JSON on a type: `fields`, `views`,
|
|
61
|
+
`record_permissions`, `scope`, `functionality`. See [types](../types.md) and
|
|
62
|
+
the worked example in [04-first-app.md](./04-first-app.md).
|
|
63
|
+
|
|
64
|
+
**validation_schema** — the runtime-format schema derived from
|
|
65
|
+
`design_schema` on every save by `.framework/functions/types.ts` /
|
|
66
|
+
`.framework/functions/_shared/schema-utils.ts`. Read-only; used to validate
|
|
67
|
+
record writes.
|
|
68
|
+
|
|
69
|
+
**kind** — which runtime table a type governs: `item`, `thread`, `message`,
|
|
70
|
+
`link`, `attachment`, `watcher`, `account`, `person` (the `ENTITY_TO_KIND`
|
|
71
|
+
map in `.framework/functions/admin-data.ts`).
|
|
72
|
+
|
|
73
|
+
**runtime record** — a row in one of the typed tables (`items`, `threads`,
|
|
74
|
+
`messages`, `links`, `attachments`, `watchers`, `accounts`, `people`). Always
|
|
75
|
+
has `type_id`, `account_id`, `data` jsonb, and the `design_schema`/
|
|
76
|
+
`validation_schema` stamped at creation.
|
|
77
|
+
|
|
78
|
+
**system field** — a `design_schema` field flagged `system: true`, stored as
|
|
79
|
+
a real table column and read as `record.<field>` (e.g. `title` →
|
|
80
|
+
`items.title`). Non-system fields live in `data` and read as
|
|
81
|
+
`record.data.<field>` (split implemented in
|
|
82
|
+
`.framework/src/components/app-shell/GenericDetailPage.tsx`).
|
|
83
|
+
|
|
84
|
+
## Apps
|
|
85
|
+
|
|
86
|
+
**app** — a registered application (`public.apps`): `slug`, `route_prefix`,
|
|
87
|
+
`renderer`, `nav_items`, `min_role`/`required_roles`, `config`, `is_active`,
|
|
88
|
+
`is_system`. Appears in the authenticated router when it has a
|
|
89
|
+
`route_prefix` and `renderer != 'none'`
|
|
90
|
+
(`.framework/src/contexts/AppContext.tsx`).
|
|
91
|
+
|
|
92
|
+
**renderer** — how an app's UI is produced. `generic` = schema-driven shell
|
|
93
|
+
(`GenericAppShell` renders `nav_items` → list/detail pages from type views).
|
|
94
|
+
`custom` = lazy-loaded React entry (`custom/apps/<slug>/index.tsx`, falling
|
|
95
|
+
back to `.framework/src/apps/<slug>/index.tsx`) via
|
|
96
|
+
`.framework/src/components/CustomAppLoader.tsx`. `none` = registry-only, not
|
|
97
|
+
routed.
|
|
98
|
+
|
|
99
|
+
**manifest** — two meanings, both frozen JSON contracts: (a) an app
|
|
100
|
+
`manifest.json` in `custom/apps/<slug>/` declaring routes, `nav_items`,
|
|
101
|
+
`required_roles`, `registration`, and a `seed` block consumed by
|
|
102
|
+
`install-app`/`seed-app`/`update-db-app`
|
|
103
|
+
(`.framework/cli/commands/install-app.ts`); (b) `.spine-manifest.json`, the
|
|
104
|
+
project's frozen integrity manifest of per-file sha256 hashes
|
|
105
|
+
(`.framework/cli/lib/project-files.ts`).
|
|
106
|
+
|
|
107
|
+
## Automation
|
|
108
|
+
|
|
109
|
+
**pipeline** — a multi-step workflow (`public.pipelines`, `stages` jsonb)
|
|
110
|
+
executed by `runPipeline` in
|
|
111
|
+
`.framework/functions/_shared/pipeline-runner.ts`. Each stage's `stage_type`
|
|
112
|
+
maps to a `public.actions` row or a built-in handler (`http_request`,
|
|
113
|
+
`send_notification`, `agent_inference`, `query_items`, …).
|
|
114
|
+
|
|
115
|
+
**trigger** — an event subscription (`public.triggers`): `event_type` +
|
|
116
|
+
`pipeline_id` + optional `config` filters. `admin-data` emits
|
|
117
|
+
`<entity>_<created|updated|deleted>` events (e.g. `item_created`); matching
|
|
118
|
+
triggers enqueue an execution and dispatch the pipeline via the
|
|
119
|
+
`pipeline-runner-background` function (requires `INTERNAL_INVOKE_SECRET`).
|
|
120
|
+
|
|
121
|
+
**timer** — a schedule (`public.timers`): `timer_type`
|
|
122
|
+
(`interval` | `cron` | `once`) + `pipeline_id`. The `trigger-scheduler`
|
|
123
|
+
Netlify scheduled function (every minute, `netlify.toml`) runs `system-cron`,
|
|
124
|
+
which runs due timers through `runPipeline` under a `timer:*` principal.
|
|
125
|
+
|
|
126
|
+
**integration** — a named external connection (`public.integrations`):
|
|
127
|
+
adapter slug + `config` + `credentials` (`env_var` reference or literal
|
|
128
|
+
`value`). Inbound webhooks arrive via `integration-routes`; outbound calls
|
|
129
|
+
via `integration-outbound` write **deliveries**.
|
|
130
|
+
|
|
131
|
+
## AI
|
|
132
|
+
|
|
133
|
+
**prompt config** — a named, versioned prompt template
|
|
134
|
+
(`public.prompt_configs`) referenced by AI agents and pipeline stages.
|
|
135
|
+
|
|
136
|
+
**AI agent** — a reusable model + prompt + tool configuration
|
|
137
|
+
(`public.ai_agents`), invocable via `/api/ai-agents?action=run` or the
|
|
138
|
+
`agent_inference` pipeline stage.
|
|
139
|
+
|
|
140
|
+
**embedding** — a pgvector embedding (`public.embeddings`) queried through
|
|
141
|
+
the `match_embeddings`/`search_similar_embeddings` RPCs; backs semantic
|
|
142
|
+
search and knowledge stages.
|
|
143
|
+
|
|
144
|
+
## Access and delivery
|
|
145
|
+
|
|
146
|
+
**API key** — a machine credential (`public.api_keys`) presented as the
|
|
147
|
+
`x-api-key` header; resolved by prefix and verified against a stored hash
|
|
148
|
+
(`.framework/functions/_shared/principal.ts`,
|
|
149
|
+
`.framework/functions/_shared/hash-api-key.ts`). Has `rate_limit` and usage
|
|
150
|
+
logged in `api_key_usage_logs`.
|
|
151
|
+
|
|
152
|
+
**delivery** — an outbound delivery attempt record
|
|
153
|
+
(`public.webhook_deliveries`) written by `integration-outbound`; retried by
|
|
154
|
+
`retry-deliveries` inside `system-cron`. See [deliveries](../deliveries.md).
|
|
155
|
+
|
|
156
|
+
**execution** — a run record: `pipeline_executions` for pipelines,
|
|
157
|
+
`trigger_executions` for trigger fires, `schedule_executions` for scheduled
|
|
158
|
+
actions. Statuses progress `queued` → `running` → `completed`/`failed`.
|
|
159
|
+
|
|
160
|
+
**audit log** — privileged-action events written by `emitAudit`
|
|
161
|
+
(`.framework/functions/_shared/audit.ts`) plus the `public.logs` stream —
|
|
162
|
+
e.g. `trigger.fired`, `app.created`, `app.version_updated`.
|
|
163
|
+
|
|
164
|
+
## Project layout
|
|
165
|
+
|
|
166
|
+
**scope** — `design_schema.scope`: `account` (records belong to the caller's
|
|
167
|
+
tenant, the default) or `platform` (`admin-data` re-anchors created records
|
|
168
|
+
to the `spine-system` account).
|
|
169
|
+
|
|
170
|
+
**assembled** — `.assembled/`, the generated build tree:
|
|
171
|
+
`.assembled/src` (framework frontend + verbatim `custom/apps/<slug>/`) and
|
|
172
|
+
`.assembled/netlify/functions` (flattened functions for Netlify), produced by
|
|
173
|
+
`npm run assemble` (`scripts/assemble.sh`).
|
|
174
|
+
|
|
175
|
+
**`.framework/`** — the sealed, framework-owned tree vendored into your
|
|
176
|
+
project. Checksummed in `.spine-manifest.json`; overwritten by
|
|
177
|
+
`npx spine-framework upgrade`. See
|
|
178
|
+
[02-project-map.md](./02-project-map.md).
|
|
179
|
+
|
|
180
|
+
**CIL** — the Code Intelligence Layer: Spine's code-intelligence subsystem
|
|
181
|
+
(ingested code chunks, embeddings, and a searchable project graph) surfaced
|
|
182
|
+
under the admin `cil` pages (`.framework/src/pages/admin/cil/`). Optional;
|
|
183
|
+
your apps do not depend on it.
|