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,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: triggers
|
|
3
|
+
audience: both
|
|
4
|
+
kind: reference
|
|
5
|
+
verified_against: f69c37d
|
|
6
|
+
verified_on: 2026-10-30
|
|
7
|
+
source_files:
|
|
8
|
+
- .framework/functions/triggers.ts
|
|
9
|
+
- .framework/functions/_shared/middleware.ts
|
|
10
|
+
- .framework/functions/_shared/trigger-engine.ts
|
|
11
|
+
- .framework/migrations/020_schema_reconciliation.sql
|
|
12
|
+
- .framework/public/_redirects
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# triggers
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
CRUD plus `toggle`, `listByEvent`, and `getExecutions` over
|
|
20
|
+
`public.triggers` — the config rows that bind an `event_type` to a
|
|
21
|
+
`pipeline_id`. **This function never fires anything**: matching and
|
|
22
|
+
dispatch happen in `.framework/functions/_shared/trigger-engine.ts`
|
|
23
|
+
(`checkAndFireTriggers`/`fireCreateTriggers`/`fireUpdateTriggers`,
|
|
24
|
+
invoked by `admin-data` on record writes), which reserves a
|
|
25
|
+
`trigger_executions` row and POSTs the run to the
|
|
26
|
+
`pipeline-runner-background` function. See
|
|
27
|
+
[Automation](../../concepts/automation.md).
|
|
28
|
+
|
|
29
|
+
## Route and methods
|
|
30
|
+
|
|
31
|
+
`/.netlify/functions/triggers`, reachable as `/api/triggers` (`/api/*` →
|
|
32
|
+
`/.netlify/functions/:splat`, `.framework/public/_redirects`). `?action=`
|
|
33
|
+
takes precedence; without it the dispatcher falls back to the HTTP method —
|
|
34
|
+
`GET` → `get` (with `id`) else `list`, `POST` → `create`, `PATCH` →
|
|
35
|
+
`update`, `DELETE` → `remove`:
|
|
36
|
+
|
|
37
|
+
| Call | Handler |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `/api/triggers?action=list` | `list` |
|
|
40
|
+
| `/api/triggers?action=listByEvent&event_type=<e>` | `listByEvent` |
|
|
41
|
+
| `/api/triggers?action=get&id=<uuid>` | `get` |
|
|
42
|
+
| `/api/triggers?action=getExecutions&trigger_id=<uuid>` | `getExecutions` |
|
|
43
|
+
| `/api/triggers?action=create` | `create` |
|
|
44
|
+
| `/api/triggers?action=update` (`id` in body or query) | `update` |
|
|
45
|
+
| `/api/triggers?action=remove` (`id` in body or query) | `remove` |
|
|
46
|
+
| `/api/triggers?action=toggle` (`id` in body or query) | `toggle` |
|
|
47
|
+
|
|
48
|
+
A bare `GET /api/triggers` returns the active trigger list.
|
|
49
|
+
|
|
50
|
+
## Authentication
|
|
51
|
+
|
|
52
|
+
Standard `createHandler` auth: `x-api-key` → machine principal,
|
|
53
|
+
`x-internal-secret` → internal principal, `Bearer <jwt>` → human;
|
|
54
|
+
anonymous → 401.
|
|
55
|
+
|
|
56
|
+
- `list`/`listByEvent`/`getExecutions`/`create` require `ctx.accountId`.
|
|
57
|
+
- `create` requires `system_admin` or a `canCreate` grant from
|
|
58
|
+
`resolveFirstSurfacePermissions(..., 'trigger', 'create')`.
|
|
59
|
+
- `update`/`remove`/`toggle` have no explicit gate — humans are bounded
|
|
60
|
+
by RLS on `ctx.db`; machines run service-role.
|
|
61
|
+
- Reads are sanitized: non-admins get `{ id }` per row (trigger rows
|
|
62
|
+
carry no `design_schema`).
|
|
63
|
+
|
|
64
|
+
## Request contract
|
|
65
|
+
|
|
66
|
+
**list** (query): `app_id`, `event_type`, `include_inactive` (`'true'`
|
|
67
|
+
to include; default active only). Ordered by `name`.
|
|
68
|
+
|
|
69
|
+
**listByEvent** (query): `event_type` required; `app_id`,
|
|
70
|
+
`include_inactive` optional.
|
|
71
|
+
|
|
72
|
+
**get** (query): `id`. **getExecutions** (query): `trigger_id`
|
|
73
|
+
required; `limit` (default 50), `offset` — reads
|
|
74
|
+
`public.trigger_executions` ordered `executed_at` desc.
|
|
75
|
+
|
|
76
|
+
**create** (body): `name`, `event_type`, `pipeline_id` required.
|
|
77
|
+
Optional: `app_id`, `description`, `trigger_type` (defaults `'event'`),
|
|
78
|
+
`config` `{}`, `metadata` `{}`. `account_id`/`created_by` stamped —
|
|
79
|
+
`created_by` is `null` for machine principals. (`event_type`,
|
|
80
|
+
`trigger_type`, `pipeline_id` columns were added by
|
|
81
|
+
`.framework/migrations/020_schema_reconciliation.sql`.)
|
|
82
|
+
|
|
83
|
+
**update** (`id` in body or query + body): allowlist — `name`,
|
|
84
|
+
`description`, `config`, `pipeline_id`, `metadata`, `is_active`,
|
|
85
|
+
`event_type`, `trigger_type`, `app_id`.
|
|
86
|
+
|
|
87
|
+
**remove** (`id` in body or query): soft delete (`is_active = false`).
|
|
88
|
+
|
|
89
|
+
**toggle** (`id` in body or query): flips `is_active` — no target-state
|
|
90
|
+
argument.
|
|
91
|
+
|
|
92
|
+
## Response contract
|
|
93
|
+
|
|
94
|
+
Standard `{ data, error, meta }` envelope.
|
|
95
|
+
|
|
96
|
+
- `list`/`listByEvent`/`get`/`create`/`update`/`toggle` → sanitized
|
|
97
|
+
row(s); `remove` → `{ success: true }`; `getExecutions` → raw
|
|
98
|
+
`trigger_executions` array (unsanitized).
|
|
99
|
+
- The file also exports `AGENT_EVENT_TYPES` — the `agent.*` event names
|
|
100
|
+
(`agent.inference.completed`, `agent.tool.called`,
|
|
101
|
+
`agent.message.received`, …) usable as `event_type` values — but
|
|
102
|
+
`event_type` is free-form text; any string is accepted.
|
|
103
|
+
|
|
104
|
+
## Side effects
|
|
105
|
+
|
|
106
|
+
- `toggle`/`update`/`remove` stamp `updated_at`; `is_active` is what the
|
|
107
|
+
trigger engine filters on when matching events.
|
|
108
|
+
- `emitLog` writes `trigger.created` / `.updated` / `.deleted` /
|
|
109
|
+
`.toggled` audit rows to `public.logs`.
|
|
110
|
+
- Writing a trigger has no immediate run effect — the row is only read
|
|
111
|
+
the next time `admin-data` (or another caller of the trigger engine)
|
|
112
|
+
emits a matching event.
|
|
113
|
+
|
|
114
|
+
## Errors
|
|
115
|
+
|
|
116
|
+
| Condition | HTTP | Message |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| No account context | 500 | `Account context required` |
|
|
119
|
+
| `listByEvent` without `event_type` | 500 | `event_type is required` |
|
|
120
|
+
| `getExecutions` without `trigger_id` | 500 | `trigger_id is required` |
|
|
121
|
+
| Missing create fields | 500 | `name, event_type, and pipeline_id are required` |
|
|
122
|
+
| Non-admin without create grant | 500 | `Insufficient permissions to create triggers` |
|
|
123
|
+
| Missing `id` | 500 | `Trigger ID is required` |
|
|
124
|
+
| Missing row | 500 | `Trigger not found` |
|
|
125
|
+
| Missing/unknown action | 500 | `Unsupported action: <action>` |
|
|
126
|
+
|
|
127
|
+
## Agent notes
|
|
128
|
+
|
|
129
|
+
- Trigger→pipeline wiring is `pipeline_id` on the row; the engine reads
|
|
130
|
+
`config.entity_type`, `config.type_slug`, `config.filters`, and
|
|
131
|
+
`config.fire_on_transition` at match time — none of that is validated
|
|
132
|
+
by this endpoint, so a malformed `config` fails silently at match time
|
|
133
|
+
(the trigger simply never fires or always fires).
|
|
134
|
+
- `getExecutions` is read-only bookkeeping written by the trigger
|
|
135
|
+
engine's `record_trigger_fire` path — execution lifecycle (queued →
|
|
136
|
+
running → complete/failed) is covered by `pipeline-executions` and
|
|
137
|
+
`pipeline-runner-background`, not this function.
|
|
138
|
+
- `remove` is a soft delete; a deleted trigger stops matching on the
|
|
139
|
+
next event (the engine queries `is_active = true`).
|
|
140
|
+
- `toggle` flips blindly — read first if you need a target state.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: types
|
|
3
|
+
audience: both
|
|
4
|
+
kind: reference
|
|
5
|
+
verified_against: f69c37d
|
|
6
|
+
verified_on: 2026-10-30
|
|
7
|
+
source_files:
|
|
8
|
+
- .framework/functions/types.ts
|
|
9
|
+
- .framework/functions/_shared/middleware.ts
|
|
10
|
+
- .framework/functions/_shared/schema-utils.ts
|
|
11
|
+
- .framework/functions/_shared/permissions.ts
|
|
12
|
+
- .framework/migrations/015_types_kind_slug_unique.sql
|
|
13
|
+
- .framework/public/_redirects
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# types
|
|
17
|
+
|
|
18
|
+
## What it does
|
|
19
|
+
|
|
20
|
+
CRUD over `public.types` — the type-definition registry whose
|
|
21
|
+
`design_schema`/`validation_schema` columns drive record validation,
|
|
22
|
+
permissions, and the generic UI (see
|
|
23
|
+
[Design Schema](../../concepts/design-schema.md)). Also resolves single
|
|
24
|
+
types by `slug` and exposes a schema-lookup RPC pass-through.
|
|
25
|
+
|
|
26
|
+
## Route and methods
|
|
27
|
+
|
|
28
|
+
`/.netlify/functions/types`, reachable as `/api/types` (`/api/*` →
|
|
29
|
+
`/.netlify/functions/:splat`, `.framework/public/_redirects`). Dispatch is
|
|
30
|
+
by `?action=` plus the HTTP method (`?method=` can override the method):
|
|
31
|
+
|
|
32
|
+
| Call | Handler |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `GET /api/types?action=schema&kind=<k>&slug=<s>[&app_id=<uuid>]` | `getSchema` → RPC `get_type_schema` |
|
|
35
|
+
| `GET /api/types?action=list` (or bare `GET` with no `id`/`slug`/`kind`) | `list` |
|
|
36
|
+
| `GET /api/types?slug=<s>` | `getBySlug` (active rows only, joins `apps`) |
|
|
37
|
+
| `GET /api/types?id=<uuid>` | `get` |
|
|
38
|
+
| `POST /api/types` | `create` |
|
|
39
|
+
| `PATCH /api/types?id=<uuid>` | `update` |
|
|
40
|
+
| `DELETE /api/types?id=<uuid>` | `remove` |
|
|
41
|
+
|
|
42
|
+
Quirk: a bare `GET` carrying `kind` (without `action=list` or
|
|
43
|
+
`action=schema`) routes to `get`, which then fails with
|
|
44
|
+
`Type ID is required` — kind-filtered listing requires `action=list`.
|
|
45
|
+
|
|
46
|
+
## Authentication
|
|
47
|
+
|
|
48
|
+
Standard `createHandler` auth (`resolvePrincipal` in
|
|
49
|
+
`.framework/functions/_shared/principal.ts`): `x-api-key` → machine
|
|
50
|
+
principal, `x-internal-secret` → internal principal,
|
|
51
|
+
`Authorization: Bearer <jwt>` → human. Anonymous → 401.
|
|
52
|
+
|
|
53
|
+
- `create`, `update`, `remove` require a `system_admin` role
|
|
54
|
+
(`PermissionEngine.isSystemAdmin(ctx)`) — no fallback permission path.
|
|
55
|
+
- `list`/`get`/`getBySlug`/`getSchema` only require authentication.
|
|
56
|
+
System admins read via `adminDb` (all accounts); other principals use
|
|
57
|
+
`ctx.db` — JWT-scoped (RLS) for humans, service role for machines.
|
|
58
|
+
|
|
59
|
+
## Request contract
|
|
60
|
+
|
|
61
|
+
**list** (query): `kind`, `app_id` (`'null'` filters to global types),
|
|
62
|
+
`ownership`, `active` (`'false'` → inactive only, `'all'` → everything,
|
|
63
|
+
default → active only), `limit` (default 50), `offset` (default 0),
|
|
64
|
+
`include_schema` (`'true'` also returns `validation_schema`).
|
|
65
|
+
|
|
66
|
+
**getBySlug** (query): `slug` — active rows only.
|
|
67
|
+
|
|
68
|
+
**getSchema** (query): `kind`, `slug` required; `app_id` optional
|
|
69
|
+
(passed to the RPC as `null` when absent).
|
|
70
|
+
|
|
71
|
+
**create** (body): `name`, `slug`, `kind` required. Optional:
|
|
72
|
+
`ownership` (default `'system'`), `app_id` (default `null`),
|
|
73
|
+
`design_schema` (default `{}`), `validation_schema` (default `null` →
|
|
74
|
+
generated), `description`, `icon`, `color`.
|
|
75
|
+
|
|
76
|
+
**update** (query `id` + body): `name`, `slug`, `description`, `icon`,
|
|
77
|
+
`color`, `is_active`, `kind`, `app_id`, `ownership`, `design_schema` —
|
|
78
|
+
only keys present in the body are written. An empty update returns the
|
|
79
|
+
existing row unchanged.
|
|
80
|
+
|
|
81
|
+
**remove** (query): `id`.
|
|
82
|
+
|
|
83
|
+
## Response contract
|
|
84
|
+
|
|
85
|
+
Standard `{ data, error, meta }` envelope.
|
|
86
|
+
|
|
87
|
+
- `list` → array of sanitized type rows. `get`/`getBySlug`/`create`/
|
|
88
|
+
`update` → single row. `remove` → `{ success: true }`. `getSchema` →
|
|
89
|
+
`{ design_schema }`.
|
|
90
|
+
- Sanitization (`sanitizeRecordData`): system admins get the full row.
|
|
91
|
+
Other principals go through first-surface logic — the row's own
|
|
92
|
+
`design_schema.record_permissions` decides visibility; rows without
|
|
93
|
+
them collapse to `{ id }`. `list` re-attaches `design_schema` to the
|
|
94
|
+
sanitized row when it was stripped, and attaches `validation_schema`
|
|
95
|
+
when `include_schema=true`.
|
|
96
|
+
|
|
97
|
+
## Side effects
|
|
98
|
+
|
|
99
|
+
- `create` inserts into `public.types` with `is_active: true`; when the
|
|
100
|
+
body omits `validation_schema` it is generated from `design_schema` by
|
|
101
|
+
`generateValidationSchema` (`.framework/functions/_shared/schema-utils.ts`).
|
|
102
|
+
- `update` regenerates `validation_schema` **every time `design_schema`
|
|
103
|
+
is present in the body** — the derived schema is never hand-editable.
|
|
104
|
+
- `remove` is a soft delete (`is_active = false`); `ownership: 'system'`
|
|
105
|
+
rows cannot be deleted, and their `ownership` cannot be changed away
|
|
106
|
+
from `'system'`.
|
|
107
|
+
- `emitLog` writes `type.created` / `type.updated` / `type.deleted`
|
|
108
|
+
audit rows to `public.logs`.
|
|
109
|
+
- Updating a type does **not** restamp `design_schema` onto existing
|
|
110
|
+
records — records keep the schema stamped at their own creation.
|
|
111
|
+
|
|
112
|
+
## Errors
|
|
113
|
+
|
|
114
|
+
| Condition | HTTP | Message |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| Not system admin (create/update/remove) | 500 | `System admin required` |
|
|
117
|
+
| Missing create fields | 500 | `name, slug, and kind are required` |
|
|
118
|
+
| Duplicate active slug/kind/app_id | 500 | `Type with slug '<s>' already exists for kind '<k>'` |
|
|
119
|
+
| Missing `id` / `slug` / `kind`+`slug` | 500 | `Type ID is required` / `Type slug is required` / `kind and slug are required` |
|
|
120
|
+
| Update/delete of missing row | 500 | `Type not found` |
|
|
121
|
+
| Ownership change on system type | 500 | `Cannot change ownership of system types` |
|
|
122
|
+
| Delete system type | 500 | `Cannot delete system types` |
|
|
123
|
+
| Bad action/method | 500 | `Invalid action or method` |
|
|
124
|
+
|
|
125
|
+
Validation failures surface as HTTP 500 — the shared error path maps
|
|
126
|
+
thrown `Error`s without a `statusCode` to 500.
|
|
127
|
+
|
|
128
|
+
## Agent notes
|
|
129
|
+
|
|
130
|
+
- Slug uniqueness is global per `kind`: the `types_kind_slug_unique`
|
|
131
|
+
index on `types(kind, slug)`
|
|
132
|
+
(`.framework/migrations/015_types_kind_slug_unique.sql`) is stricter
|
|
133
|
+
than `create`'s pre-check (which scopes to `app_id` + `is_active`), so
|
|
134
|
+
a same-kind/same-slug insert under a different `app_id` passes the
|
|
135
|
+
pre-check and then fails at the database. Pick globally unique slugs.
|
|
136
|
+
- `kind` must match the runtime table the type governs (`item`,
|
|
137
|
+
`thread`, `message`, …); `admin-data` resolves types by kind+slug.
|
|
138
|
+
- `getSchema` delegates to the Postgres RPC
|
|
139
|
+
`get_type_schema(kind, slug, app_id)`, provided by migration
|
|
140
|
+
`070_app_type_schema_rpcs.sql` (along with `get_app_schema`,
|
|
141
|
+
`is_app_available`, `update_app_version`). Installs missing that
|
|
142
|
+
migration will see `function does not exist` errors.
|
|
143
|
+
- `update` accepts `kind` and `app_id` changes — there is no guard
|
|
144
|
+
keeping `kind` aligned with already-stamped records.
|
|
145
|
+
- The unauthenticated "minimal row" branch in `list` is unreachable via
|
|
146
|
+
HTTP: `createHandler` rejects anonymous callers with 401 first.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Seeds Reference
|
|
3
|
+
audience: developers, agents
|
|
4
|
+
kind: reference
|
|
5
|
+
verified_against: f69c37d
|
|
6
|
+
verified_on: 2026-10-30
|
|
7
|
+
source_files:
|
|
8
|
+
- .framework/cli/commands/install-app.ts
|
|
9
|
+
- .framework/cli/commands/migrate.ts
|
|
10
|
+
- .framework/functions/_shared/app-manifest.ts
|
|
11
|
+
- .framework/seeds/types/spine_instance.json
|
|
12
|
+
- .framework/seeds/link_types/account_cli_instances.json
|
|
13
|
+
- .framework/migrations/003_core_system_data.sql
|
|
14
|
+
- .framework/migrations/053_builtin_action_seeds.sql
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Seeds Reference
|
|
18
|
+
|
|
19
|
+
Seeds are JSON row files that materialize an app's database contract — types,
|
|
20
|
+
roles, link types, agents, prompt configs, pipelines, triggers — at install
|
|
21
|
+
time. They are distinct from migrations: **migrations are SQL and change
|
|
22
|
+
schema; seeds are data and are applied by the app installer.**
|
|
23
|
+
|
|
24
|
+
## Where seeds live
|
|
25
|
+
|
|
26
|
+
| Location | Contents | Format |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `custom/apps/<slug>/seed/*.json` | app-owned rows, declared in `manifest.json` `seed[]` | JSON **array** of row objects |
|
|
29
|
+
| `.framework/seeds/` | framework-owned seed payloads (e.g. `.framework/seeds/types/spine_instance.json`, `.framework/seeds/link_types/account_cli_instances.json`) | single JSON object per file |
|
|
30
|
+
| `.framework/migrations/` | system rows written by SQL (`003_core_system_data.sql` seeds roles/types/apps; `053_builtin_action_seeds.sql` seeds `public.actions`) | SQL `INSERT … ON CONFLICT DO NOTHING` |
|
|
31
|
+
|
|
32
|
+
## When seeds run
|
|
33
|
+
|
|
34
|
+
Seeds are applied by `seedApp` in `.framework/cli/commands/install-app.ts`:
|
|
35
|
+
|
|
36
|
+
| Command | Runs seeds? |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `install-app <pkg>` | yes — after `runMigrations` succeeds, unless `--no-seed`. Migration failure aborts before seeding; without `SUPABASE_URL`/`SUPABASE_DB_PASSWORD` only `--no-seed` installs may proceed |
|
|
39
|
+
| `seed-app <slug>` | yes — seed block only, no npm, no file changes |
|
|
40
|
+
| `update-db-app <slug>` | no — upserts the `apps` row and syncs `registration` only |
|
|
41
|
+
| `update-app <pkg>` | no — refreshes files from npm only |
|
|
42
|
+
| `migrate` | no — migrations apply SQL only; system seeds inside migrations run as SQL |
|
|
43
|
+
| `uninstall-app <pkg>` | no — removes files and the npm dependency; it does not delete seeded rows |
|
|
44
|
+
|
|
45
|
+
Requires `SUPABASE_URL` and `SUPABASE_SERVICE_ROLE_KEY`; seeding uses the
|
|
46
|
+
service-role client and bypasses RLS.
|
|
47
|
+
|
|
48
|
+
## Apply order
|
|
49
|
+
|
|
50
|
+
Entries are stable-sorted by `SEED_TABLE_ORDER`
|
|
51
|
+
(`.framework/cli/commands/install-app.ts`), regardless of declaration order:
|
|
52
|
+
|
|
53
|
+
1. `roles`
|
|
54
|
+
2. `types`
|
|
55
|
+
3. `permissions_patch` entries (rank 1.5 — always after types)
|
|
56
|
+
4. `link_types`
|
|
57
|
+
5. `actions`
|
|
58
|
+
6. `ai_agents`
|
|
59
|
+
7. `prompt_configs`
|
|
60
|
+
8. `pipelines`
|
|
61
|
+
9. `triggers`
|
|
62
|
+
10. unknown tables — last, in declared order
|
|
63
|
+
|
|
64
|
+
Ordering exists so dependents resolve: a `triggers` row's `pipeline_slug` is
|
|
65
|
+
looked up in `public.pipelines` (scoped to this app's `app_id`) and rewritten
|
|
66
|
+
to `pipeline_id`, and a `pipelines` row's `stages[].stage_type` is validated
|
|
67
|
+
against `public.actions` — so a bad stage type fails at install, not at first
|
|
68
|
+
trigger fire.
|
|
69
|
+
|
|
70
|
+
## Per-entry behavior
|
|
71
|
+
|
|
72
|
+
Each record is upserted into `entry.table` with `onConflict: entry.conflict`.
|
|
73
|
+
|
|
74
|
+
- **`inject_app_id`** (default `true`): stamps `app_id` on every row. Set
|
|
75
|
+
`false` for global rows — `types` seeds use `conflict: "kind,slug"` with
|
|
76
|
+
`inject_app_id: false` because type slugs are global, not per-app.
|
|
77
|
+
- **`ignore_duplicates`**: rows that conflict are skipped, not updated.
|
|
78
|
+
Always forced on for `types` (the read-then-compare below decides the real
|
|
79
|
+
outcome) and opt-in per entry via `ignore_duplicates: true`.
|
|
80
|
+
- **`types` rows are never silently overwritten.** Before each types upsert
|
|
81
|
+
the existing row is read: an identical `design_schema` skips cleanly; a
|
|
82
|
+
differing one throws — unless the slug is declared in
|
|
83
|
+
`manifest.owned_types` and `--reconcile-owned-types` was passed, which
|
|
84
|
+
prompts `[U]pdate / [K]eep` and merges (`seed` wins shared fields,
|
|
85
|
+
DB-only fields are preserved) with a regenerated `validation_schema`.
|
|
86
|
+
- **`permissions_patch` rows** (`{kind, slug, record_permissions}`) replace
|
|
87
|
+
`design_schema.record_permissions` on an existing type after a
|
|
88
|
+
`[R]eplace / [K]eep` prompt; grant lists may only contain
|
|
89
|
+
`create`/`read`/`update`/`delete`. A `seed/type_permissions.json` file is
|
|
90
|
+
auto-declared when no patch entry exists.
|
|
91
|
+
- **`types` seeds get a fresh `validation_schema`** generated from
|
|
92
|
+
`design_schema` at apply time — author `design_schema` only.
|
|
93
|
+
- **`pipelines` seeds** are validated before upsert: every `stages[].stage_type`
|
|
94
|
+
must exist in `public.actions`; `send_notification`/`send_email`
|
|
95
|
+
`config.recipients` must be `role:<slug>`, `self`, `owner`, `watchers`, a
|
|
96
|
+
person UUID, or (email only) an email address.
|
|
97
|
+
- **`triggers` seeds** may use `pipeline_slug`; it is resolved to
|
|
98
|
+
`pipeline_id` within the app's pipelines and removed before upsert.
|
|
99
|
+
|
|
100
|
+
## Failure model
|
|
101
|
+
|
|
102
|
+
Seeding is fail-closed: a malformed manifest, a missing declared seed file,
|
|
103
|
+
an unparseable file, a non-array file, a missing referenced
|
|
104
|
+
type/pipeline/role, or any row-write error throws and aborts the run. Files
|
|
105
|
+
not declared in `manifest.seed` are skipped silently (except the auto-added
|
|
106
|
+
`type_permissions.json`). All validation runs **before** the database client
|
|
107
|
+
is created, so bad input produces zero writes.
|
|
108
|
+
|
|
109
|
+
After all entries apply, `syncAppRegistration` writes the resolved
|
|
110
|
+
`registration` policy to `apps.config.registration` and `spine.config.json`.
|
|
111
|
+
|
|
112
|
+
## Authoring checklist
|
|
113
|
+
|
|
114
|
+
- [ ] Every `seed[]` entry's `file` exists inside the app dir and parses as a JSON array of objects
|
|
115
|
+
- [ ] `conflict` names real unique columns (`slug` for roles; `kind,slug` for types; `app_id,slug` for app-scoped config tables)
|
|
116
|
+
- [ ] `types` rows have a complete `design_schema` — see [Design Schema](design-schema.md); `validation_schema` is generated
|
|
117
|
+
- [ ] `inject_app_id: false` on `types` entries
|
|
118
|
+
- [ ] `pipeline_slug` used in trigger seeds; pipelines seeded (they always apply first)
|
|
119
|
+
- [ ] `owned_types` declared in the manifest for any type the app must reconcile
|
|
120
|
+
- [ ] `manifest.seed` omitted only when the conventional trio (`seed/roles.json`, `seed/types.json`, `seed/link-types.json`) covers everything
|
|
121
|
+
|
|
122
|
+
## Related files
|
|
123
|
+
|
|
124
|
+
- `.framework/cli/commands/install-app.ts` — `seedApp`, `SEED_TABLE_ORDER`, `reconcileOwnedType`, `validatePipelineSeedStages`
|
|
125
|
+
- `.framework/cli/commands/migrate.ts` — migration runner (SQL only)
|
|
126
|
+
- [App Manifest](app-manifest.md) · [CLI](cli.md) · [Design Schema](design-schema.md)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shared Modules Reference
|
|
3
|
+
audience: developers, agents
|
|
4
|
+
kind: reference
|
|
5
|
+
verified_against: f69c37d
|
|
6
|
+
verified_on: 2026-10-30
|
|
7
|
+
source_files:
|
|
8
|
+
- .framework/functions/_shared/index.ts
|
|
9
|
+
- .framework/functions/_shared/middleware.ts
|
|
10
|
+
- .framework/functions/_shared/principal.ts
|
|
11
|
+
- .framework/functions/_shared/db.ts
|
|
12
|
+
- .framework/functions/_shared/permissions.ts
|
|
13
|
+
- .framework/functions/_shared/schema-utils.ts
|
|
14
|
+
- .framework/functions/_shared/trigger-engine.ts
|
|
15
|
+
- .framework/functions/_shared/pipeline-runner.ts
|
|
16
|
+
- .framework/functions/_shared/agent-runner.ts
|
|
17
|
+
- .framework/functions/_shared/logging.ts
|
|
18
|
+
- .framework/functions/_shared/audit.ts
|
|
19
|
+
- .framework/functions/_shared/tracing.ts
|
|
20
|
+
- .framework/functions/_shared/rate-limit.ts
|
|
21
|
+
- .framework/functions/_shared/resolve-credentials.ts
|
|
22
|
+
- .framework/functions/_shared/resolve-ids.ts
|
|
23
|
+
- .framework/functions/_shared/hash-api-key.ts
|
|
24
|
+
- .framework/functions/_shared/webhook-registration.ts
|
|
25
|
+
- .framework/functions/_shared/webhook-registry.ts
|
|
26
|
+
- .framework/functions/_shared/message-sequence.ts
|
|
27
|
+
- .framework/functions/_shared/security.ts
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
# Shared Modules Reference
|
|
31
|
+
|
|
32
|
+
`.framework/functions/_shared/` is the library every Netlify function builds
|
|
33
|
+
on — bundled per function, never deployed as an endpoint itself.
|
|
34
|
+
`.framework/functions/_shared/index.ts` re-exports the common surface
|
|
35
|
+
(`createHandler`, `createPublicHandler`, `requireUserContext`,
|
|
36
|
+
`requireSystemContextWithAudit`, `json`, `errorResponse`, `cors`, the
|
|
37
|
+
`Principal`/`RequestContext`/`CoreContext`/`HandlerFunction`/`HandlerResult`
|
|
38
|
+
types). Import a sibling as `from './_shared/<module>'`.
|
|
39
|
+
|
|
40
|
+
## Request handling
|
|
41
|
+
|
|
42
|
+
| Module | Exports | Import when |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `middleware.ts` | `createHandler`, `createPublicHandler`, `json`, `error`, `cors`, `parseBody`, `requireUserContext`, `requireSystemContextWithAudit`; `RequestContext`, `CoreContext`, `HandlerFunction`, `HandlerResult` | every function — wraps auth, tracing, envelope, and error mapping around your handler |
|
|
45
|
+
| `principal.ts` | `resolvePrincipal`, `SYSTEM_PRINCIPAL`, `ANONYMOUS_PRINCIPAL`, `getPrincipalDb`, `isSystemAdmin`, `humanHasRole`, `machineHasScope`, `resolveInternalPersonId`, `formatPrincipalForAudit` | reading `ctx.principal`, checking roles/scopes, internal invocations |
|
|
46
|
+
| `db.ts` | `adminDb` (service-role, bypasses RLS), `getUserDb(token)` (RLS-scoped), `joins` | direct table access — prefer `ctx.db` (already principal-scoped) inside handlers |
|
|
47
|
+
|
|
48
|
+
## Permissions & data shape
|
|
49
|
+
|
|
50
|
+
| Module | Exports | Import when |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `permissions.ts` | `PermissionEngine`, `resolveFirstSurfacePermissions`, `sanitizeRecordData`, `validateUpdatePermissions`, `canAccessRecord`, `isSystemAdmin`, `PermissionResult` | evaluating `design_schema` grants, stripping fields a principal can't read, validating writes |
|
|
53
|
+
| `schema-utils.ts` | `generateValidationSchema`, `sanitizeFieldData`, `formatFieldData`, `transformRecordData`, `ValidationSchema` | field validation/sanitization against `data_type`; generating `validation_schema` |
|
|
54
|
+
| `resolve-ids.ts` | `resolveTypeId`, `resolveTypeIds`, `resolveTypeRecord`, `resolveAccountId`, `resolveLinkTypeId(s)`, `resolveAgentId`, `resolvePromptConfigId` | slug→uuid lookups for types, link types, accounts, agents, prompts |
|
|
55
|
+
|
|
56
|
+
## Automation & agents
|
|
57
|
+
|
|
58
|
+
| Module | Exports | Import when |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `trigger-engine.ts` | `fireCreateTriggers`, `fireUpdateTriggers`, `fireDeleteTriggers`, `checkAndFireTriggers`, `dispatchTriggerPipeline`, `EventType` | firing record-change triggers; dispatching a pipeline run (needs `INTERNAL_INVOKE_SECRET`) |
|
|
61
|
+
| `pipeline-runner.ts` | `runPipeline`, `sweepStaleExecutions`, `ExecutionResult`, `StageResult` | executing a pipeline's stages inside a function/background context |
|
|
62
|
+
| `agent-runner.ts` | `runAgent`, `runAgentStep`, `claimAgentEpisode`, `kickAgentEpisode`, `acquireEpisodeLease`, `resolveAgentConfig`, `executeToolAction`, `retrieveKnowledge`, `AgentConfig`, `ToolCall`, `ToolResult` | running an AI agent turn against a thread |
|
|
63
|
+
| `message-sequence.ts` | `insertMessageSequenced` | inserting a message outside `runAgent` — allocates `MAX(sequence)+1` and retries on the `(thread_id, sequence)` race |
|
|
64
|
+
| `notify.ts` | `resolveNotificationRecipients` | resolving `role:<slug>` / `self` / UUID recipients to `people.id` |
|
|
65
|
+
|
|
66
|
+
## Observability & audit
|
|
67
|
+
|
|
68
|
+
| Module | Exports | Import when |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `logging.ts` | `withAdminLogging`, `logAdminDataOperation`, `resolveLogLevels`, `resolveAppUuid`, `LogLevel` | wrapping handlers with the instance log-level-aware logging pipeline |
|
|
71
|
+
| `audit.ts` | `emitAudit`, `emitLog`, `emitSpan`, `emitActivity` | writing structured log/audit/span rows into `public.logs` |
|
|
72
|
+
| `tracing.ts` | `newTrace`, `startSpan`, `endSpan`, `withSpan(Sync)`, `traceDb`, `formatTraceParent/State`, `parseTraceParent/State`, `generateTraceId/SpanId`, `isSampled` | W3C trace-context propagation and span wrapping of DB calls |
|
|
73
|
+
| `outcomes.ts` | `emitOutcome` | recording outcome audit rows |
|
|
74
|
+
|
|
75
|
+
## Security
|
|
76
|
+
|
|
77
|
+
| Module | Exports | Import when |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `hash-api-key.ts` | `hashApiKey`, `verifyApiKey`, `omitSecretFields` | minting/verifying API keys (`pbkdf2$iter$salt$hash`, 100k sha256); stripping key material from responses |
|
|
80
|
+
| `rate-limit.ts` | `checkRateLimit`, `resolveRateLimitPolicies`, `RateLimitError`, `RateLimitPolicy` | enforcing `config.rate_limits` policies via the atomic `rate_limit_hit` RPC |
|
|
81
|
+
| `security.ts` | `isBlockedRequest`, `isBlockedIp`, `checkTypeSlugRateLimit`, `detectInjection`, `emitSecurityEvent`, `getAppSecurityConfig`, `checkRegistrationBlocklist`, `touchPersonGeo`, `INJECTION_PATTERNS` | blocklist checks, per-type-slug rate limits, prompt-injection screening |
|
|
82
|
+
| `geo.ts` | `getClientGeo`, `ClientGeo` | best-effort client IP/geo from request headers |
|
|
83
|
+
|
|
84
|
+
## Integrations & webhooks
|
|
85
|
+
|
|
86
|
+
| Module | Exports | Import when |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| `resolve-credentials.ts` | `resolveCredential`, `resolveCredentials`, `ResolvedCredential` | resolving `integrations.config.credentials` (`value` literal or `env_var` lookup) server-side |
|
|
89
|
+
| `webhook-registration.ts` | `registerWebhookHandler`, `deregisterWebhookHandler`, `isHandlerRegistered` | self-registering a custom function as a webhook handler (`webhook_handlers` upsert) |
|
|
90
|
+
| `webhook-registry.ts` | `lookupHandler`, `resolveHandler`, `loadHandler`, `listRegisteredHandlers`, `clearHandlerCache` | resolving which registered handler receives an inbound event |
|
|
91
|
+
| `retry-deliveries.ts` | `retryPendingDeliveries` | sweeping due `webhook_deliveries` rows for retry |
|
|
92
|
+
|
|
93
|
+
## Knowledge & LLM
|
|
94
|
+
|
|
95
|
+
| Module | Exports | Import when |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| `kb.ts` | `kbIngest`, `kbPublish`, `kbReindex`, `kbRevoke`, `kbSearch`, `resolveKnowledgeScope`, `knowledgeRowAllowed`, `resolveSecurityLevel`, `matchItemType`, `KnowledgeScope`, `KnowledgeEnvelope` | ingesting/searching embeddings with scope + security-level enforcement |
|
|
98
|
+
| `llm.ts` | `callOpenAI`, `callOpenAIChat`, `callOpenAIEmbeddings`, `callEmbeddingApi`, `LlmContext` | thin wrappers over the `openai` outbound integration |
|
|
99
|
+
| `funnel.ts` | `emitSignal`, `accountDataFlag`, `SignalInput` | emitting typed funnel/signal events that can fire triggers |
|
|
100
|
+
| `access.ts` | `hasInternalAudience`, `projectMessageForCustomer`, `INTERNAL_AUDIENCE_ROLES`, `CUSTOMER_STEP_TYPES` | deciding whether a principal may read `visibility: 'internal'` rows and projecting customer-safe message shapes |
|
|
101
|
+
|
|
102
|
+
## Framework internals
|
|
103
|
+
|
|
104
|
+
| Module | Purpose |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `app-manifest.ts` | `loadManifest`, `mergeWithManifest`, `discoverManifests`, `clearManifestCache` — `manifest.json` loading for app rows with `config_source = 'manifest'` |
|
|
107
|
+
| `ast.ts` | `extractIdentities` — TypeScript compiler API for code-analysis pipelines |
|
|
108
|
+
| `cil.ts` | stable-id generation, content hashing, file-tree helpers for the code-intelligence pipeline — not needed by custom apps |
|
|
109
|
+
| `testing.ts` | `mockEvent`, `mockPrincipal`, `makeTestContext`, `expectSuccessResponse`, `expectErrorResponse`, `setupTests` — function-level test harness |
|
|
110
|
+
|
|
111
|
+
## Usage notes
|
|
112
|
+
|
|
113
|
+
- `ctx.db` is already the right client for the request's principal — humans
|
|
114
|
+
get an RLS-scoped client, machines get `adminDb`. Reach for `adminDb`
|
|
115
|
+
directly only when you must deliberately bypass RLS (system writes,
|
|
116
|
+
cross-account lookups like `types`/`accounts` resolution).
|
|
117
|
+
- Never `JSON.stringify(ctx.principal)` — `authContext.jwt` rides on it; use
|
|
118
|
+
`formatPrincipalForAudit`.
|
|
119
|
+
- Circular-import hazards are real in this layer (`middleware → security →
|
|
120
|
+
rate-limit → funnel → trigger-engine → pipeline-runner → kb → llm →
|
|
121
|
+
integration-outbound → admin-data → middleware`); some modules import
|
|
122
|
+
lazily on purpose — copy that pattern rather than adding a static edge.
|
|
123
|
+
|
|
124
|
+
## Related
|
|
125
|
+
|
|
126
|
+
- [admin-data](api/admin-data.md) · [Authentication](api/auth.md) · [Errors and Envelopes](api/errors-and-envelopes.md)
|
|
127
|
+
- [Design Schema](design-schema.md) · [Database](database.md)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: spine.config.json Reference
|
|
3
|
+
audience: developers, agents
|
|
4
|
+
kind: reference
|
|
5
|
+
verified_against: f69c37d
|
|
6
|
+
verified_on: 2026-10-30
|
|
7
|
+
source_files:
|
|
8
|
+
- .framework/schemas/spine.config.schema.json
|
|
9
|
+
- .framework/templates/spine.config.neutral.json
|
|
10
|
+
- .framework/src/lib/branding.ts
|
|
11
|
+
- .framework/src/hooks/useBranding.ts
|
|
12
|
+
- .framework/cli/commands/install-app.ts
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# `spine.config.json` Reference
|
|
16
|
+
|
|
17
|
+
`spine.config.json` is the per-project instance config. It lives at the
|
|
18
|
+
project root and is served to the browser as a static public asset — the
|
|
19
|
+
frontend fetches `/spine.config.json`. **Everything in it is client-visible;
|
|
20
|
+
never put secrets here.** The JSON Schema is
|
|
21
|
+
`.framework/schemas/spine.config.schema.json`; the neutral starting point is
|
|
22
|
+
`.framework/templates/spine.config.neutral.json`.
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"branding": {
|
|
27
|
+
"app_name": "My Product",
|
|
28
|
+
"title": "My Product",
|
|
29
|
+
"logo_url": "/logo.svg",
|
|
30
|
+
"favicon_url": "/favicon.svg"
|
|
31
|
+
},
|
|
32
|
+
"registration": {
|
|
33
|
+
"default_app": "my-app",
|
|
34
|
+
"default_role": "member",
|
|
35
|
+
"allow_url_override": false,
|
|
36
|
+
"default_app_by_role": { "support": "my-app" },
|
|
37
|
+
"apps": {
|
|
38
|
+
"my-app": {
|
|
39
|
+
"roles": ["member", "member_admin"],
|
|
40
|
+
"default_role": "member_admin",
|
|
41
|
+
"path": "/my-app",
|
|
42
|
+
"enabled": true,
|
|
43
|
+
"account_strategy": "new",
|
|
44
|
+
"parent_account": "spine-system"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## `branding`
|
|
52
|
+
|
|
53
|
+
Read by `.framework/src/lib/branding.ts` (`loadBranding` fetches
|
|
54
|
+
`/spine.config.json` and caches it) and applied to framework-owned pages —
|
|
55
|
+
login, register, setup, sidebars — plus `document.title` and the favicon via
|
|
56
|
+
`useBranding` (`.framework/src/hooks/useBranding.ts`). All keys optional;
|
|
57
|
+
an absent block falls back to Spine defaults.
|
|
58
|
+
|
|
59
|
+
| Key | Default | Effect |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `app_name` | `"Spine"` | display name in headings and logo alt text |
|
|
62
|
+
| `title` | `app_name` (or `"Spine Framework"`) | `document.title` and sidebar wordmark |
|
|
63
|
+
| `logo_url` | `"/spine-logo.svg"` | public asset path for the brand logo |
|
|
64
|
+
| `favicon_url` | `"/spine-logo.svg"` | swapped into `link[rel=icon]` at runtime |
|
|
65
|
+
|
|
66
|
+
## `registration`
|
|
67
|
+
|
|
68
|
+
Consumed by the registration/login pages and kept in sync with
|
|
69
|
+
`apps.config.registration` by the installer (`syncAppRegistration` and
|
|
70
|
+
`updateRegistrationConfig` in `.framework/cli/commands/install-app.ts` — the
|
|
71
|
+
DB write lands first, then the file).
|
|
72
|
+
|
|
73
|
+
| Key | Type | Effect |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `default_app` | string (app slug) | where registrants land when no role rule matches; auto-set to the first enabled app when absent |
|
|
76
|
+
| `default_role` | string (role slug) | role assigned when the app entry has no `default_role` |
|
|
77
|
+
| `allow_url_override` | boolean | allow a `?app=`/`?role=` URL override at registration; installer sets `true` when undefined |
|
|
78
|
+
| `default_app_by_role` | `{role: appSlug}` | per-role landing-app map |
|
|
79
|
+
| `apps` | `{appSlug: AppEntry}` | per-app registration policy, see below |
|
|
80
|
+
|
|
81
|
+
### `registration.apps.<slug>`
|
|
82
|
+
|
|
83
|
+
| Key | Type | Effect |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `roles` | string[] | roles registrants may be placed into through this app |
|
|
86
|
+
| `default_role` | string | role assigned by default |
|
|
87
|
+
| `path` | string | redirect path after registration completes |
|
|
88
|
+
| `enabled` | boolean | `true` opens self-service registration for this app; explicit `false` persists a disabled policy |
|
|
89
|
+
| `account_strategy` | `"new" \| "existing"` | create a new account or join `target_account` |
|
|
90
|
+
| `parent_account` | string | account slug new accounts are parented under (e.g. `spine-system`) |
|
|
91
|
+
| `target_account` | string (uuid) | account to join under `existing` strategy |
|
|
92
|
+
| `default_workspace_name` | string | name for the workspace created at registration |
|
|
93
|
+
| `allow_domain_join` | boolean | allow signups whose email domain matches an existing account to join it |
|
|
94
|
+
|
|
95
|
+
## File vs. schema notes
|
|
96
|
+
|
|
97
|
+
- `additionalProperties: true` at the root — extra top-level keys are allowed
|
|
98
|
+
and preserved.
|
|
99
|
+
- `loadSpineConfig` throws on malformed JSON, a non-object root, a non-object
|
|
100
|
+
`registration`, or a non-object `registration.apps`; a missing file returns
|
|
101
|
+
`{registration: {apps: {}}}`.
|
|
102
|
+
- The installer writes `registration.apps.<slug>` and `default_app`/`default_role`
|
|
103
|
+
when an app manifest declares `registration.enabled: true` — see
|
|
104
|
+
[App Manifest](app-manifest.md).
|
|
105
|
+
- `.framework/public/spine.config.json` is the framework's copy of the served
|
|
106
|
+
asset; the project root file is what `init` scaffolds and the frontend
|
|
107
|
+
actually fetches at runtime.
|
|
108
|
+
|
|
109
|
+
## Related files
|
|
110
|
+
|
|
111
|
+
- `.framework/schemas/spine.config.schema.json` — validation schema
|
|
112
|
+
- `.framework/templates/spine.config.neutral.json` — minimal valid config
|
|
113
|
+
- `.framework/src/lib/branding.ts` — branding resolution and defaults
|
|
114
|
+
- `.framework/cli/commands/install-app.ts` — `loadSpineConfig`, `saveSpineConfig`, `updateRegistrationConfig`
|