spine-framework 0.3.144 → 0.4.0
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 +76 -0
- package/.framework/.spine-manifest.json +19 -0
- package/.framework/cli/commands/agents.ts +61 -33
- package/.framework/cli/commands/auth.ts +60 -28
- package/.framework/cli/commands/create-app.ts +212 -80
- package/.framework/cli/commands/dev.ts +184 -68
- package/.framework/cli/commands/doctor.ts +324 -152
- package/.framework/cli/commands/generate.ts +119 -68
- package/.framework/cli/commands/init.ts +141 -242
- package/.framework/cli/commands/install-app.ts +1336 -314
- package/.framework/cli/commands/items.ts +31 -29
- package/.framework/cli/commands/migrate.ts +299 -156
- package/.framework/cli/commands/migrations.ts +62 -30
- package/.framework/cli/commands/pipelines.ts +31 -29
- package/.framework/cli/commands/status.ts +105 -45
- package/.framework/cli/commands/system.ts +47 -42
- package/.framework/cli/commands/test.ts +161 -102
- package/.framework/cli/commands/upgrade.ts +260 -0
- package/.framework/cli/commands/validate-app.ts +517 -161
- package/.framework/cli/context.ts +117 -85
- package/.framework/cli/env-loader.ts +74 -43
- package/.framework/cli/index.ts +70 -46
- package/.framework/cli/lib/project-files.ts +404 -0
- package/.framework/docs/guides/testing-guide.md +1 -1
- package/.framework/docs/runtime-types.md +72 -72
- package/.framework/functions/_shared/access.ts +84 -0
- package/.framework/functions/_shared/agent-runner.ts +5051 -1026
- package/.framework/functions/_shared/app-manifest.ts +214 -94
- package/.framework/functions/_shared/ast.ts +214 -0
- package/.framework/functions/_shared/audit.ts +91 -55
- package/.framework/functions/_shared/cil.ts +368 -127
- package/.framework/functions/_shared/db.ts +337 -68
- package/.framework/functions/_shared/funnel.ts +228 -0
- package/.framework/functions/_shared/geo.ts +105 -0
- package/.framework/functions/_shared/hash-api-key.ts +94 -17
- package/.framework/functions/_shared/index.ts +22 -224
- package/.framework/functions/_shared/kb.ts +832 -58
- package/.framework/functions/_shared/llm.ts +118 -18
- package/.framework/functions/_shared/logging.ts +317 -19
- package/.framework/functions/_shared/middleware.ts +701 -131
- package/.framework/functions/_shared/notify.ts +70 -0
- package/.framework/functions/_shared/outcomes.ts +34 -19
- package/.framework/functions/_shared/permissions.ts +501 -315
- package/.framework/functions/_shared/pipeline-runner.ts +704 -155
- package/.framework/functions/_shared/principal.ts +436 -263
- package/.framework/functions/_shared/rate-limit.ts +233 -0
- package/.framework/functions/_shared/resolve-credentials.ts +86 -19
- package/.framework/functions/_shared/resolve-ids.ts +203 -139
- package/.framework/functions/_shared/retry-deliveries.ts +51 -16
- package/.framework/functions/_shared/schema-utils.ts +602 -521
- package/.framework/functions/_shared/security.ts +345 -0
- package/.framework/functions/_shared/testing.ts +197 -172
- package/.framework/functions/_shared/tracing.ts +351 -21
- package/.framework/functions/_shared/trigger-engine.ts +425 -136
- package/.framework/functions/_shared/webhook-registration.ts +71 -70
- package/.framework/functions/_shared/webhook-registry.ts +126 -83
- package/.framework/functions/account-nodes.ts +30 -30
- package/.framework/functions/adapters/generic-webhook-inbound.ts +49 -16
- package/.framework/functions/adapters/generic-webhook-outbound.ts +17 -17
- package/.framework/functions/adapters/openai-outbound.ts +15 -16
- package/.framework/functions/admin-data.ts +596 -173
- package/.framework/functions/admin-funnel.ts +64 -60
- package/.framework/functions/admin-install-funnel.ts +84 -66
- package/.framework/functions/admin-signals.ts +69 -51
- package/.framework/functions/ai-agents.ts +431 -106
- package/.framework/functions/ai-interactions.ts +186 -112
- package/.framework/functions/api-keys.ts +107 -107
- package/.framework/functions/apps.ts +154 -136
- package/.framework/functions/auth.ts +83 -65
- package/.framework/functions/cil-agent-ingest.ts +189 -232
- package/.framework/functions/cil-agent.ts +433 -177
- package/.framework/functions/cil-callmap.ts +642 -430
- package/.framework/functions/cil-config.ts +139 -135
- package/.framework/functions/cil-context.ts +214 -127
- package/.framework/functions/cil-doc.ts +587 -458
- package/.framework/functions/cil-embeddings.ts +453 -364
- package/.framework/functions/cil-graph.ts +427 -142
- package/.framework/functions/cil-ingest.ts +1418 -1154
- package/.framework/functions/cil-pipeline.ts +276 -21
- package/.framework/functions/cil-project.ts +659 -132
- package/.framework/functions/cil-validate.ts +198 -164
- package/.framework/functions/debug-auth.ts +57 -55
- package/.framework/functions/deliveries.ts +80 -21
- package/.framework/functions/embeddings.ts +1023 -318
- package/.framework/functions/eval-harness.ts +146 -108
- package/.framework/functions/integration-outbound.ts +205 -75
- package/.framework/functions/integration-routes.ts +128 -23
- package/.framework/functions/integrations.ts +125 -100
- package/.framework/functions/invites.ts +1095 -460
- package/.framework/functions/item-progress.ts +158 -102
- package/.framework/functions/kb.ts +34 -10
- package/.framework/functions/logs.ts +133 -133
- package/.framework/functions/observability.ts +152 -122
- package/.framework/functions/pipeline-executions.ts +147 -132
- package/.framework/functions/pipelines.ts +134 -119
- package/.framework/functions/prompt-configs.ts +96 -80
- package/.framework/functions/roles.ts +112 -82
- package/.framework/functions/security.ts +450 -0
- package/.framework/functions/system-cron.ts +117 -80
- package/.framework/functions/system.ts +158 -98
- package/.framework/functions/tests.ts +29 -29
- package/.framework/functions/timers.ts +94 -95
- package/.framework/functions/trigger-scheduler.ts +10 -0
- package/.framework/functions/triggers.ts +179 -149
- package/.framework/functions/types.ts +137 -125
- package/.framework/mcp/index.ts +133 -0
- package/.framework/mcp/load-env.ts +60 -0
- package/.framework/mcp/shared/app-manifest.ts +275 -0
- package/.framework/mcp/shared/db.ts +477 -0
- package/.framework/mcp/shared/kb.ts +118 -0
- package/.framework/mcp/tools/architect.ts +431 -0
- package/.framework/mcp/tools/cil/context.ts +345 -0
- package/.framework/mcp/tools/cil/graph.ts +242 -0
- package/.framework/mcp/tools/cil/ingest.ts +1217 -0
- package/.framework/mcp/tools/cil/pipeline-orchestrator.ts +693 -0
- package/.framework/mcp/tools/cil/pipeline.ts +767 -0
- package/.framework/mcp/tools/cil/project.ts +791 -0
- package/.framework/mcp/tools/cil/retrieval.ts +336 -0
- package/.framework/mcp/tools/cil/search-core.ts +454 -0
- package/.framework/mcp/tools/cil/search.ts +97 -0
- package/.framework/mcp/tools/cil/suggest.ts +186 -0
- package/.framework/mcp/tools/cil/validate.ts +1369 -0
- package/.framework/mcp/tools/kb/delete.ts +139 -0
- package/.framework/mcp/tools/kb/index.ts +52 -0
- package/.framework/mcp/tools/kb/ingest.ts +84 -0
- package/.framework/mcp/tools/kb/list-types.ts +102 -0
- package/.framework/mcp/tools/kb/publish.ts +100 -0
- package/.framework/mcp/tools/kb/reindex.ts +86 -0
- package/.framework/mcp/tools/kb/revoke.ts +85 -0
- package/.framework/mcp/tools/kb/search.ts +101 -0
- package/.framework/mcp/tools/kb/upsert.ts +125 -0
- package/.framework/mcp/tools/observability.ts +510 -0
- package/.framework/migrations/001_core_schema.sql +15 -0
- package/.framework/migrations/002_core_rls_and_functions.sql +15 -0
- package/.framework/migrations/003_core_system_data.sql +16 -1
- package/.framework/migrations/004_core_rpc_and_broker.sql +17 -1
- package/.framework/migrations/005_core_observability.sql +17 -1
- package/.framework/migrations/006_security_hardening_rls.sql +15 -0
- package/.framework/migrations/007_kb_article_list.sql +17 -1
- package/.framework/migrations/008_items_target.sql +15 -0
- package/.framework/migrations/009_roles_slug_unique.sql +15 -0
- package/.framework/migrations/010_auth_user_trigger.sql +15 -0
- package/.framework/migrations/011_spine_system_account.sql +16 -0
- package/.framework/migrations/012_service_role_grants.sql +16 -0
- package/.framework/migrations/013_get_account_apps_role_filter.sql +15 -0
- package/.framework/migrations/014_apps_required_roles.sql +16 -0
- package/.framework/migrations/015_types_kind_slug_unique.sql +20 -0
- package/.framework/migrations/016_cil_types.sql +281 -0
- package/.framework/migrations/017_cil_stable_ids.sql +37 -0
- package/.framework/migrations/018_runtime_tables.sql +129 -0
- package/.framework/migrations/019_agent_prompt_columns.sql +56 -0
- package/.framework/migrations/020_schema_reconciliation.sql +67 -0
- package/.framework/migrations/021_kb_embedding_lifecycle.sql +31 -0
- package/.framework/migrations/032_cil_status_migration.sql +73 -0
- package/.framework/migrations/033_cil_versioning.sql +73 -0
- package/.framework/migrations/034_match_embeddings_knn.sql +115 -0
- package/.framework/migrations/035_rate_limits.sql +55 -0
- package/.framework/migrations/036_demo_record_flags.sql +72 -0
- package/.framework/migrations/037_kb_types_canonical.sql +244 -0
- package/.framework/migrations/038_drop_demo_record_flags.sql +38 -0
- package/.framework/migrations/042_registration_hierarchy.sql +309 -0
- package/.framework/migrations/043_policy_actor_cleanup.sql +39 -0
- package/.framework/migrations/044_match_embeddings_filtered_knn.sql +151 -0
- package/.framework/migrations/045_security_critical_rls.sql +139 -0
- package/.framework/migrations/046_security_missing_rls.sql +79 -0
- package/.framework/migrations/047_people_updated_by.sql +27 -0
- package/.framework/migrations/048_watcher_last_seen_at.sql +24 -0
- package/.framework/migrations/049_security_blocklist.sql +148 -0
- package/.framework/migrations/050_notifications.sql +49 -0
- package/.framework/migrations/051_message_agent_fields.sql +74 -0
- package/.framework/migrations/052_registration_security.sql +421 -0
- package/.framework/migrations/053_builtin_action_seeds.sql +66 -0
- package/.framework/migrations/054_kb_ingest_lease.sql +157 -0
- package/.framework/migrations/055_type_id_drift_reconciliation.sql +33 -0
- package/.framework/migrations/056_slug_column_reconciliation.sql +38 -0
- package/.framework/migrations/057_pipelines_slug_identity.sql +14 -0
- package/.framework/migrations/058_account_data_field_declarations.sql +53 -0
- package/.framework/migrations/059_registration_placement_fixes.sql +269 -0
- package/.framework/migrations/060_account_person_record_permissions.sql +38 -0
- package/.framework/migrations/061_fk_dedup.sql +32 -0
- package/.framework/public/spine-logo.svg +10 -3
- package/.framework/scripts/app-install-cli.ts +190 -93
- package/.framework/scripts/assemble-frontend.sh +127 -44
- package/.framework/scripts/assemble-functions.sh +128 -30
- package/.framework/scripts/boundary-check.sh +6 -2
- package/.framework/scripts/build-manifest.sh +24 -68
- package/.framework/scripts/check-core-integrity.sh +15 -76
- package/.framework/scripts/checksum-manifest.mts +343 -0
- package/.framework/scripts/cil-migrate-markers.ts +403 -0
- package/.framework/scripts/fix-cil-markers.mjs +176 -0
- package/.framework/scripts/verify-integrity.sh +21 -57
- package/.framework/scripts/verify-manifest.mts +305 -0
- package/.framework/seeds/types/funnel_signal_use.json +74 -21
- package/.framework/seeds/types/spine_instance.json +73 -21
- package/.framework/src/App.tsx +118 -72
- package/.framework/src/apps/admin/index.tsx +855 -58
- package/.framework/src/components/AppWrapper.tsx +43 -45
- package/.framework/src/components/CustomAppLoader.tsx +160 -116
- package/.framework/src/components/admin/AdminListPage.tsx +46 -44
- package/.framework/src/components/admin/AdminSidebar.tsx +57 -47
- package/.framework/src/components/admin/AdminStatsCard.tsx +46 -44
- package/.framework/src/components/admin/PageInstructions.tsx +98 -2
- package/.framework/src/components/admin/SortableTableHeader.tsx +44 -45
- package/.framework/src/components/app-shell/GenericAppShell.tsx +64 -65
- package/.framework/src/components/app-shell/GenericDetailPage.tsx +44 -47
- package/.framework/src/components/app-shell/GenericListPage.tsx +45 -49
- package/.framework/src/components/app-sidebar.tsx +42 -45
- package/.framework/src/components/auth/ProtectedRoute.tsx +48 -41
- package/.framework/src/components/auth/TurnstileWidget.tsx +27 -0
- package/.framework/src/components/kb/KBArticleEditor.tsx +231 -22
- package/.framework/src/components/kb/KBArticleList.tsx +251 -10
- package/.framework/src/components/layout/AppShell.tsx +51 -45
- package/.framework/src/components/layout/Header.tsx +42 -43
- package/.framework/src/components/layout/Layout.tsx +46 -46
- package/.framework/src/components/layout/Sidebar.tsx +196 -96
- package/.framework/src/components/runtime/DataDetailHeader.tsx +55 -30
- package/.framework/src/components/runtime/DataDetailPage.tsx +31 -269
- package/.framework/src/components/runtime/DataFilters.tsx +49 -74
- package/.framework/src/components/runtime/DataHeader.tsx +53 -32
- package/.framework/src/components/runtime/DataListPage.tsx +51 -155
- package/.framework/src/components/runtime/DataStats.tsx +66 -44
- package/.framework/src/components/runtime/DataTable.tsx +49 -149
- package/.framework/src/components/runtime/SchemaDetailForm.tsx +45 -75
- package/.framework/src/components/runtime/index.ts +119 -16
- package/.framework/src/components/search-form.tsx +46 -29
- package/.framework/src/components/shared/AgentView.tsx +65 -48
- package/.framework/src/components/shared/FieldRenderer.tsx +144 -50
- package/.framework/src/components/shared/InviteManager.tsx +207 -97
- package/.framework/src/components/shared/MemberList.tsx +97 -0
- package/.framework/src/components/shared/SchemaFields.tsx +107 -86
- package/.framework/src/components/ui/DataTable.tsx +80 -68
- package/.framework/src/components/ui/Form.tsx +157 -146
- package/.framework/src/components/ui/ItemCard.tsx +74 -67
- package/.framework/src/components/ui/ItemListView.tsx +73 -68
- package/.framework/src/components/ui/LoadingSpinner.tsx +43 -48
- package/.framework/src/components/ui/Modal.tsx +78 -68
- package/.framework/src/components/ui/RichTextEditor.tsx +89 -69
- package/.framework/src/components/ui/accordion.tsx +85 -86
- package/.framework/src/components/ui/alert-dialog.tsx +197 -184
- package/.framework/src/components/ui/alert.tsx +105 -94
- package/.framework/src/components/ui/aspect-ratio.tsx +57 -43
- package/.framework/src/components/ui/avatar.tsx +122 -107
- package/.framework/src/components/ui/badge.tsx +60 -55
- package/.framework/src/components/ui/breadcrumb.tsx +127 -128
- package/.framework/src/components/ui/button-group.tsx +86 -72
- package/.framework/src/components/ui/button.tsx +71 -50
- package/.framework/src/components/ui/calendar.tsx +72 -57
- package/.framework/src/components/ui/card.tsx +136 -129
- package/.framework/src/components/ui/carousel.tsx +226 -107
- package/.framework/src/components/ui/chart.tsx +252 -147
- package/.framework/src/components/ui/checkbox.tsx +43 -44
- package/.framework/src/components/ui/collapsible.tsx +86 -71
- package/.framework/src/components/ui/combobox.tsx +282 -249
- package/.framework/src/components/ui/command.tsx +158 -146
- package/.framework/src/components/ui/context-menu.tsx +239 -240
- package/.framework/src/components/ui/dialog.tsx +174 -157
- package/.framework/src/components/ui/direction.tsx +72 -56
- package/.framework/src/components/ui/drawer.tsx +168 -169
- package/.framework/src/components/ui/dropdown-menu.tsx +254 -223
- package/.framework/src/components/ui/empty.tsx +131 -120
- package/.framework/src/components/ui/field.tsx +205 -173
- package/.framework/src/components/ui/hover-card.tsx +71 -72
- package/.framework/src/components/ui/input-group.tsx +148 -133
- package/.framework/src/components/ui/input-otp.tsx +99 -86
- package/.framework/src/components/ui/input.tsx +43 -41
- package/.framework/src/components/ui/item.tsx +207 -185
- package/.framework/src/components/ui/kbd.tsx +57 -56
- package/.framework/src/components/ui/label.tsx +45 -41
- package/.framework/src/components/ui/menubar.tsx +268 -236
- package/.framework/src/components/ui/native-select.tsx +85 -86
- package/.framework/src/components/ui/navigation-menu.tsx +166 -156
- package/.framework/src/components/ui/pagination.tsx +131 -141
- package/.framework/src/components/ui/popover.tsx +125 -128
- package/.framework/src/components/ui/progress.tsx +47 -44
- package/.framework/src/components/ui/radio-group.tsx +60 -55
- package/.framework/src/components/ui/resizable.tsx +85 -72
- package/.framework/src/components/ui/scroll-area.tsx +57 -58
- package/.framework/src/components/ui/select.tsx +182 -169
- package/.framework/src/components/ui/separator.tsx +42 -43
- package/.framework/src/components/ui/sheet.tsx +170 -159
- package/.framework/src/components/ui/sidebar.tsx +395 -398
- package/.framework/src/components/ui/skeleton.tsx +42 -43
- package/.framework/src/components/ui/slider.tsx +61 -44
- package/.framework/src/components/ui/sonner.tsx +44 -44
- package/.framework/src/components/ui/spinner.tsx +47 -42
- package/.framework/src/components/ui/switch.tsx +56 -42
- package/.framework/src/components/ui/table-primitives.tsx +272 -132
- package/.framework/src/components/ui/table.tsx +140 -142
- package/.framework/src/components/ui/tabs.tsx +110 -93
- package/.framework/src/components/ui/textarea.tsx +43 -44
- package/.framework/src/components/ui/toggle-group.tsx +87 -71
- package/.framework/src/components/ui/toggle.tsx +56 -56
- package/.framework/src/components/ui/tooltip.tsx +99 -85
- package/.framework/src/contexts/AppContext.tsx +166 -114
- package/.framework/src/contexts/AuthContext.tsx +232 -137
- package/.framework/src/hooks/use-mobile.ts +43 -44
- package/.framework/src/hooks/useApi.ts +185 -172
- package/.framework/src/hooks/useAppPath.ts +31 -29
- package/.framework/src/hooks/useApps.ts +77 -42
- package/.framework/src/hooks/useEntityList.ts +66 -29
- package/.framework/src/hooks/useEntityRecord.ts +76 -32
- package/.framework/src/hooks/useForm.ts +62 -30
- package/.framework/src/hooks/useListSchema.ts +60 -43
- package/.framework/src/hooks/useSchemaRecord.ts +115 -95
- package/.framework/src/lib/api.ts +258 -134
- package/.framework/src/lib/registration.ts +181 -0
- package/.framework/src/lib/supabase.ts +118 -81
- package/.framework/src/lib/utils.ts +266 -266
- package/.framework/src/main.tsx +43 -44
- package/.framework/src/pages/DashboardPage.tsx +44 -43
- package/.framework/src/pages/NoAppPage.tsx +50 -0
- package/.framework/src/pages/NotFoundPage.tsx +32 -29
- package/.framework/src/pages/SetupPage.tsx +34 -33
- package/.framework/src/pages/admin/AIAgentDetailPage.tsx +69 -58
- package/.framework/src/pages/admin/AIAgentsPage.tsx +43 -40
- package/.framework/src/pages/admin/APIKeyDetailPage.tsx +63 -55
- package/.framework/src/pages/admin/APIKeysPage.tsx +44 -42
- package/.framework/src/pages/admin/AlertsConfigPage.tsx +117 -94
- package/.framework/src/pages/admin/AppDetailPage.tsx +48 -42
- package/.framework/src/pages/admin/AppsPage.tsx +45 -42
- package/.framework/src/pages/admin/DeliveriesPage.tsx +49 -17
- package/.framework/src/pages/admin/DesignedPage.tsx +31 -30
- package/.framework/src/pages/admin/EmbeddingDetailPage.tsx +58 -0
- package/.framework/src/pages/admin/EmbeddingsPage.tsx +49 -0
- package/.framework/src/pages/admin/ExtendedShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/IncrementalShadcnTestPage.tsx +46 -29
- package/.framework/src/pages/admin/IntegratedDashboard.tsx +32 -29
- package/.framework/src/pages/admin/IntegrationDetailPage.tsx +68 -55
- package/.framework/src/pages/admin/IntegrationsPage.tsx +45 -42
- package/.framework/src/pages/admin/InvitesPage.tsx +60 -44
- package/.framework/src/pages/admin/LogsPage.tsx +87 -137
- package/.framework/src/pages/admin/MinimalShadcnTestPage.tsx +31 -29
- package/.framework/src/pages/admin/ObservabilityDashboard.tsx +150 -89
- package/.framework/src/pages/admin/PipelineDetailPage.tsx +77 -104
- package/.framework/src/pages/admin/PipelineExecutionsPage.tsx +44 -43
- package/.framework/src/pages/admin/PipelinesPage.tsx +59 -145
- package/.framework/src/pages/admin/PromptConfigDetailPage.tsx +53 -42
- package/.framework/src/pages/admin/PromptConfigsPage.tsx +47 -117
- package/.framework/src/pages/admin/ProperlyDesignedPage.tsx +31 -44
- package/.framework/src/pages/admin/RoleDetailPage.tsx +49 -92
- package/.framework/src/pages/admin/RolesPage.tsx +47 -164
- package/.framework/src/pages/admin/SecurityPage.tsx +310 -0
- package/.framework/src/pages/admin/SelectTestPage.tsx +30 -32
- package/.framework/src/pages/admin/ShadcnTestPage.tsx +37 -44
- package/.framework/src/pages/admin/SimpleDashboard.tsx +32 -44
- package/.framework/src/pages/admin/TestRunDetailPage.tsx +97 -44
- package/.framework/src/pages/admin/TestingDashboard.tsx +126 -71
- package/.framework/src/pages/admin/TimerDetailPage.tsx +67 -55
- package/.framework/src/pages/admin/TimersPage.tsx +44 -42
- package/.framework/src/pages/admin/TriggerDetailPage.tsx +47 -42
- package/.framework/src/pages/admin/TriggersPage.tsx +58 -57
- package/.framework/src/pages/admin/TypeDetailPage.tsx +91 -55
- package/.framework/src/pages/admin/TypesPage.tsx +45 -42
- package/.framework/src/pages/admin/cil/CILAgentPage.tsx +258 -128
- package/.framework/src/pages/admin/cil/CILChunkDetailPage.tsx +127 -123
- package/.framework/src/pages/admin/cil/CILDashboardPage.tsx +308 -235
- package/.framework/src/pages/admin/cil/CILFileListPage.tsx +159 -110
- package/.framework/src/pages/admin/cil/CILFileSelectPage.tsx +432 -0
- package/.framework/src/pages/admin/cil/CILGraphPage.tsx +200 -178
- package/.framework/src/pages/admin/cil/CILIngestionPage.tsx +286 -239
- package/.framework/src/pages/admin/cil/CILProjectsPage.tsx +211 -90
- package/.framework/src/pages/admin/cil/CILSearchPage.tsx +156 -143
- package/.framework/src/pages/admin/cil/CILSuggestionsPage.tsx +379 -0
- package/.framework/src/pages/admin/cil/CILVersionsPage.tsx +337 -0
- package/.framework/src/pages/admin/cil/FlexiblePipelinePage.tsx +219 -214
- package/.framework/src/pages/admin/kb/KBAdminPage.tsx +64 -0
- package/.framework/src/pages/auth/AuthConfirmPage.tsx +135 -65
- package/.framework/src/pages/auth/ForgotPasswordPage.tsx +39 -31
- package/.framework/src/pages/auth/LoginPage.tsx +38 -32
- package/.framework/src/pages/auth/PendingApprovalPage.tsx +31 -28
- package/.framework/src/pages/auth/RegisterPage.tsx +429 -155
- package/.framework/src/pages/spine-framework/APIPage.tsx +33 -30
- package/.framework/src/pages/spine-framework/CLIPage.tsx +32 -30
- package/.framework/src/types/auth.ts +101 -93
- package/.framework/src/types/types.ts +283 -262
- package/.framework/templates/project.json +87 -0
- package/.framework/templates/spine.config.neutral.json +7 -0
- package/.framework/tests/api/api-surface.test.ts +381 -0
- package/.framework/tests/fixtures/seed.ts +427 -0
- package/.framework/tests/fixtures/teardown.ts +228 -0
- package/.framework/tests/reporter.ts +351 -0
- package/.framework/tests/setup.ts +135 -0
- package/.framework/tests/ui/ui-sweep.ts +278 -0
- package/.framework/tests/unit/admin-data-logger.test.ts +310 -0
- package/.framework/tests/unit/agent-runner.test.ts +2389 -0
- package/.framework/tests/unit/ai-interactions.test.ts +81 -0
- package/.framework/tests/unit/app-manifest.test.ts +359 -0
- package/.framework/tests/unit/assembly-scripts.test.ts +172 -0
- package/.framework/tests/unit/cil-determinism.test.ts +85 -0
- package/.framework/tests/unit/core-isolation.test.ts +153 -0
- package/.framework/tests/unit/funnel-signals.test.ts +135 -0
- package/.framework/tests/unit/install-app.test.ts +1759 -0
- package/.framework/tests/unit/invites-security.test.ts +572 -0
- package/.framework/tests/unit/kb-ingest-lease.test.ts +287 -0
- package/.framework/tests/unit/kb-search.test.ts +119 -0
- package/.framework/tests/unit/migrate.test.ts +509 -0
- package/.framework/tests/unit/notify.test.ts +136 -0
- package/.framework/tests/unit/permissions.test.ts +269 -0
- package/.framework/tests/unit/pipeline-runner.test.ts +755 -0
- package/.framework/tests/unit/principal-cache.test.ts +138 -0
- package/.framework/tests/unit/retrieval-golden.test.ts +520 -0
- package/.framework/tests/unit/runtime-isolation.test.ts +642 -0
- package/.framework/tests/unit/schema-utils.test.ts +225 -0
- package/.framework/tests/unit/trigger-engine.test.ts +513 -0
- package/.framework/tests/unit/validate-app.test.ts +527 -0
- package/README.md +34 -3
- package/bin/spine-framework.cjs +1 -0
- package/config/tailwind.config.cjs +7 -0
- package/config/tsconfig.functions.json +42 -0
- package/config/tsconfig.json +37 -9
- package/config/vite.config.ts +31 -2
- package/netlify.toml +31 -3
- package/package.json +46 -29
- package/scripts/assemble-frontend.sh +127 -44
- package/scripts/assemble-functions.sh +127 -29
- package/scripts/boundary-check.sh +6 -2
- package/scripts/build-manifest.sh +24 -68
- package/scripts/checksum-manifest.mts +345 -0
- package/scripts/dev-clean.sh +86 -0
- package/scripts/dev-netlify.sh +49 -0
- package/scripts/netlify-dev-wrapper.sh +2 -0
- package/scripts/verify-install.ts +358 -0
- package/scripts/verify-integrity.sh +21 -57
- package/scripts/verify-manifest.mts +305 -0
- package/templates/project/gitignore +45 -0
- package/{config → templates/project}/package-lock.json +22335 -9366
- package/vitest.config.ts +46 -0
- package/.framework/public/spine.config.json +0 -91
- package/config/deno.lock +0 -108
- package/config/tsconfig.node.tsbuildinfo +0 -1
- package/config/tsconfig.tsbuildinfo +0 -1
- package/config/vite.config.d.ts +0 -2
- package/custom/.devin/AGENT.md +0 -357
- package/custom/.devin/skills/install-app/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-discovery/SKILL.md +0 -39
- package/custom/.devin/skills/spine-workbench-idea/SKILL.md +0 -36
- package/custom/.devin/skills/spine-workbench-implement/SKILL.md +0 -46
- package/custom/.devin/skills/spine-workbench-initiative/SKILL.md +0 -28
- package/custom/.devin/skills/spine-workbench-plan/SKILL.md +0 -38
- package/custom/.devin/workflows/app-install.yaml +0 -83
- package/custom/README.md +0 -79
- package/docs/README.md +0 -15
- package/scripts/app-install-cli.ts +0 -286
- package/scripts/check-core-integrity.sh +0 -82
- package/scripts/ingest-chunks.cjs +0 -202
- package/scripts/kb-chunk-parser.cjs +0 -312
- package/scripts/kb-chunk-parser.ts +0 -330
- package/scripts/kb-ingest-docs.ts +0 -203
- package/scripts/load-test-app-install.ts +0 -484
- package/scripts/test-login.js +0 -33
- package/spine.config.json +0 -91
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Typecheck for the ASSEMBLED functions layout.
|
|
3
|
+
//
|
|
4
|
+
// Function sources (.framework/functions, custom/functions,
|
|
5
|
+
// custom/apps/<app>/functions) are merged flat into
|
|
6
|
+
// .assembled/netlify/functions by scripts/assemble-functions.sh. Their
|
|
7
|
+
// imports only resolve in that layout:
|
|
8
|
+
// - './_shared/*' resolves to the assembled _shared/ sibling dir
|
|
9
|
+
// - './<other-function>' resolves to other flat-assembled files
|
|
10
|
+
// - '@shared/*' is a runtime/bundler alias → assembled _shared/
|
|
11
|
+
// So this config checks the assembled output, not the source trees. Run:
|
|
12
|
+
// npx tsc --noEmit -p config/tsconfig.functions.json
|
|
13
|
+
// (Intentionally NOT in tsconfig.json's references — `tsc -b` would require
|
|
14
|
+
// composite+emit and fail the vite build on unrelated functions errors.)
|
|
15
|
+
"compilerOptions": {
|
|
16
|
+
"target": "ES2020",
|
|
17
|
+
"lib": ["ES2020"],
|
|
18
|
+
"types": ["node"],
|
|
19
|
+
"module": "ESNext",
|
|
20
|
+
"skipLibCheck": true,
|
|
21
|
+
"moduleResolution": "bundler",
|
|
22
|
+
"allowImportingTsExtensions": true,
|
|
23
|
+
"isolatedModules": true,
|
|
24
|
+
"moduleDetection": "force",
|
|
25
|
+
"noEmit": true,
|
|
26
|
+
"strict": false,
|
|
27
|
+
"noUnusedLocals": false,
|
|
28
|
+
"noUnusedParameters": false,
|
|
29
|
+
"resolveJsonModule": true,
|
|
30
|
+
"forceConsistentCasingInFileNames": true,
|
|
31
|
+
"baseUrl": ".",
|
|
32
|
+
"paths": {
|
|
33
|
+
"@shared/*": ["../.assembled/netlify/functions/_shared/*"],
|
|
34
|
+
"@/*": ["../.assembled/netlify/functions/*"]
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"include": ["../.assembled/netlify/functions"],
|
|
38
|
+
"exclude": [
|
|
39
|
+
"../node_modules",
|
|
40
|
+
"../.assembled/netlify/functions/_quarantine"
|
|
41
|
+
]
|
|
42
|
+
}
|
package/config/tsconfig.json
CHANGED
|
@@ -21,21 +21,49 @@
|
|
|
21
21
|
"baseUrl": ".",
|
|
22
22
|
"paths": {
|
|
23
23
|
"@/*": ["../.assembled/src/*"], // Assembled frontend
|
|
24
|
-
"@core/*": ["../.framework/src/*"],
|
|
25
|
-
"@custom/*": ["../custom/*"],
|
|
24
|
+
"@core/*": ["../.framework/src/*"], // Core source (same tree as .assembled/src base layer)
|
|
25
|
+
"@custom/*": ["../custom/*"], // Custom source
|
|
26
26
|
"@shared/*": ["../.framework/functions/_shared/*"] // Shared functions (resolved at runtime via assembly)
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
|
-
|
|
29
|
+
// NOTE: include/exclude paths are relative to THIS directory (config/), so
|
|
30
|
+
// everything real needs a "../" prefix — the previous values silently
|
|
31
|
+
// matched nothing and typecheck covered zero files.
|
|
32
|
+
//
|
|
33
|
+
// Coverage: assembled frontend, framework source, and every custom app's
|
|
34
|
+
// index.tsx + source tree (components/pages/hooks/lib/utils/views).
|
|
35
|
+
// Function code is deliberately EXCLUDED here — both .framework/functions
|
|
36
|
+
// and custom/apps/*/functions assume the assembled flat layout
|
|
37
|
+
// (./_shared/* sibling imports only resolve post-assembly). Typecheck them
|
|
38
|
+
// separately against the assembled output:
|
|
39
|
+
// npx tsc --noEmit -p config/tsconfig.functions.json
|
|
40
|
+
"include": [
|
|
41
|
+
"../.assembled/src",
|
|
42
|
+
"../.framework/src",
|
|
43
|
+
"../custom/apps",
|
|
44
|
+
"../custom/components",
|
|
45
|
+
"../custom/hooks"
|
|
46
|
+
],
|
|
30
47
|
"exclude": [
|
|
31
48
|
"node_modules",
|
|
32
49
|
"dist",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
50
|
+
"../node_modules",
|
|
51
|
+
"../dist",
|
|
52
|
+
"../netlify",
|
|
53
|
+
"../supabase",
|
|
54
|
+
"../scripts",
|
|
55
|
+
"../.netlify",
|
|
56
|
+
"../.framework/functions",
|
|
57
|
+
"../.assembled/netlify",
|
|
58
|
+
"../custom/functions",
|
|
59
|
+
"../custom/apps/*/functions",
|
|
60
|
+
"../custom/apps/*/seed",
|
|
61
|
+
"../custom/apps/*/public",
|
|
62
|
+
"../custom/apps/*/docs",
|
|
63
|
+
"../custom/apps/*/mcp",
|
|
64
|
+
"../custom/apps/*/migrations-archive",
|
|
65
|
+
"../custom/apps/*/node_modules",
|
|
66
|
+
"../custom/apps/*/dist"
|
|
39
67
|
],
|
|
40
68
|
"references": [{ "path": "./tsconfig.node.json" }]
|
|
41
69
|
}
|
package/config/vite.config.ts
CHANGED
|
@@ -2,10 +2,39 @@ import { defineConfig } from 'vite'
|
|
|
2
2
|
import react from '@vitejs/plugin-react'
|
|
3
3
|
import path from 'path'
|
|
4
4
|
|
|
5
|
+
// CIL[BEGIN stable_id="~/config/vite.config.ts:module:config" type="config" identity="vite-config" parent="~/config/vite.config.ts"]
|
|
6
|
+
// CIL[DOC-MACRO purpose="Vite build/dev config for Spine: assembled src root, /api proxy to Netlify dev, manual vendor chunks, @/ @core @custom @shared aliases."]
|
|
7
|
+
// CIL[DOC-RESPONSIBILITY responsibility="Point Vite at .assembled/src, wire SPA fallback middleware, public dir, PostCSS (config/postcss.config.cjs), and dev-server fs/proxy settings."]
|
|
8
|
+
// CIL[DOC-CONTEXT module="build-config" layer="build" related_files="scripts/assemble-frontend.sh,config/postcss.config.cjs,netlify.toml"]
|
|
9
|
+
// CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
10
|
+
// CIL[DOC-STABILITY stability="stable"]
|
|
11
|
+
// CIL[DOC-NOTE type="gotcha" content="css.postcss must reference postcss.config.cjs — the .js filename does not exist on disk."]
|
|
12
|
+
// CIL[END stable_id="~/config/vite.config.ts:module:config"]
|
|
13
|
+
|
|
5
14
|
// Vite config for Spine - assembled src as working root
|
|
6
15
|
export default defineConfig({
|
|
7
16
|
plugins: [
|
|
8
17
|
react(),
|
|
18
|
+
{
|
|
19
|
+
name: 'spa-fallback-first',
|
|
20
|
+
configureServer(server) {
|
|
21
|
+
// Runs before Vite's transform middleware. Browser navigation to an
|
|
22
|
+
// app route like /demo would otherwise resolve to demo/index.tsx
|
|
23
|
+
// (directory index) and be served as a JS module instead of the SPA.
|
|
24
|
+
server.middlewares.use((req, _res, next) => {
|
|
25
|
+
const accept = req.headers.accept || ''
|
|
26
|
+
const pathname = (req.url || '').split('?')[0]
|
|
27
|
+
if (
|
|
28
|
+
req.method === 'GET' &&
|
|
29
|
+
accept.includes('text/html') &&
|
|
30
|
+
!/\.[a-zA-Z0-9]+$/.test(pathname)
|
|
31
|
+
) {
|
|
32
|
+
req.url = '/index.html'
|
|
33
|
+
}
|
|
34
|
+
next()
|
|
35
|
+
})
|
|
36
|
+
},
|
|
37
|
+
},
|
|
9
38
|
],
|
|
10
39
|
|
|
11
40
|
// Root directory for the assembled app
|
|
@@ -70,8 +99,8 @@ export default defineConfig({
|
|
|
70
99
|
// Environment directory (project root for .env files)
|
|
71
100
|
envDir: path.resolve(__dirname, '..'),
|
|
72
101
|
|
|
73
|
-
// PostCSS configuration
|
|
102
|
+
// PostCSS configuration (file on disk is postcss.config.cjs — must match exactly)
|
|
74
103
|
css: {
|
|
75
|
-
postcss: path.resolve(__dirname, 'postcss.config.
|
|
104
|
+
postcss: path.resolve(__dirname, 'postcss.config.cjs'),
|
|
76
105
|
},
|
|
77
106
|
})
|
package/netlify.toml
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[build]
|
|
2
|
-
command = "npm run build"
|
|
2
|
+
command = "npm run assemble && npm run build"
|
|
3
3
|
publish = "dist"
|
|
4
4
|
functions = ".assembled/netlify/functions"
|
|
5
5
|
|
|
6
6
|
[build.environment]
|
|
7
7
|
# Supabase VITE variables are meant to be public in the browser
|
|
8
|
-
SECRETS_SCAN_OMIT_KEYS = "VITE_SUPABASE_URL,VITE_SUPABASE_ANON_KEY,VITE_DB_SCHEMA,VITE_APP_NAME,VITE_ENVIRONMENT,SUPABASE_URL,DB_SCHEMA"
|
|
8
|
+
SECRETS_SCAN_OMIT_KEYS = "VITE_SUPABASE_URL,VITE_SUPABASE_ANON_KEY,VITE_DB_SCHEMA,VITE_APP_NAME,VITE_ENVIRONMENT,SUPABASE_URL,DB_SCHEMA,APP_BASE_URL,SITE_URL"
|
|
9
9
|
SECRETS_SCAN_OMIT_PATHS = ".framework/.xenv,.framework/.xenv.test"
|
|
10
10
|
|
|
11
11
|
# Spine functions configuration - assembled from .framework + custom
|
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
directory = ".assembled/netlify/functions"
|
|
14
14
|
included_files = [".assembled/netlify/functions/_shared/**"]
|
|
15
15
|
node_bundler = "esbuild"
|
|
16
|
+
# typescript.js trips a flaky esbuild printer panic under parallel function
|
|
17
|
+
# bundling (cil-*, ai-agents, custom_case_analysis). Ship it unbundled —
|
|
18
|
+
# it's a real dependency loaded lazily at runtime.
|
|
19
|
+
external_node_modules = ["typescript"]
|
|
16
20
|
|
|
17
21
|
[dev]
|
|
18
22
|
command = "bash scripts/netlify-dev-wrapper.sh"
|
|
@@ -20,11 +24,15 @@
|
|
|
20
24
|
port = 8888
|
|
21
25
|
targetPort = 3001
|
|
22
26
|
autoLaunch = false
|
|
23
|
-
startTimeout =
|
|
27
|
+
startTimeout = 300
|
|
24
28
|
|
|
25
29
|
[functions."trigger-scheduler"]
|
|
26
30
|
schedule = "* * * * *"
|
|
27
31
|
|
|
32
|
+
# NOTE: app-specific schedules were removed — the root netlify.toml serves the
|
|
33
|
+
# monorepo and must stay generic. Scheduled functions belong to each app's own
|
|
34
|
+
# deployed Netlify config; app installers declare their own custom_* sections.
|
|
35
|
+
|
|
28
36
|
# CIL ingestion passes are long-running — extend timeout for local dev
|
|
29
37
|
# TODO: migrate to background functions for production
|
|
30
38
|
[functions."cil-ingest"]
|
|
@@ -33,6 +41,21 @@
|
|
|
33
41
|
[functions."cil-embeddings"]
|
|
34
42
|
timeout = 300
|
|
35
43
|
|
|
44
|
+
[functions."cil-callmap"]
|
|
45
|
+
timeout = 60
|
|
46
|
+
|
|
47
|
+
# CIL agent can need multiple LLM tool-call rounds for broad questions
|
|
48
|
+
[functions."cil-agent"]
|
|
49
|
+
timeout = 120
|
|
50
|
+
|
|
51
|
+
# ai-agents run action drives multi-turn research steps (retrieval + tools + LLM)
|
|
52
|
+
[functions."ai-agents"]
|
|
53
|
+
timeout = 120
|
|
54
|
+
|
|
55
|
+
# kb reindex ingests an entire published corpus (batched, ~10 items in flight)
|
|
56
|
+
[functions."kb"]
|
|
57
|
+
timeout = 120
|
|
58
|
+
|
|
36
59
|
[[redirects]]
|
|
37
60
|
from = "/*"
|
|
38
61
|
to = "/index.html"
|
|
@@ -47,3 +70,8 @@
|
|
|
47
70
|
Referrer-Policy = "strict-origin-when-cross-origin"
|
|
48
71
|
Permissions-Policy = "camera=(), microphone=(), geolocation=()"
|
|
49
72
|
X-XSS-Protection = "1; mode=block"
|
|
73
|
+
# CSP: 'unsafe-inline' in script-src is required by the Vite dev
|
|
74
|
+
# preamble and module-preload; challenges.cloudflare.com covers
|
|
75
|
+
# Turnstile. Supabase needs https + wss for realtime. No
|
|
76
|
+
# upgrade-insecure-requests — local dev runs over plain HTTP.
|
|
77
|
+
Content-Security-Policy = "default-src 'self'; script-src 'self' 'unsafe-inline' https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' data: https://fonts.gstatic.com; img-src 'self' data: https: blob:; connect-src 'self' https://*.supabase.co wss://*.supabase.co https://api.netlify.com https://challenges.cloudflare.com; frame-src https://challenges.cloudflare.com; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spine-framework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Multi-tenant, modular application platform for modern SaaS systems",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,31 +8,40 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin/",
|
|
11
|
-
"scripts/",
|
|
11
|
+
"scripts/assemble.sh",
|
|
12
|
+
"scripts/assemble-frontend.sh",
|
|
13
|
+
"scripts/assemble-functions.sh",
|
|
14
|
+
"scripts/dev-netlify.sh",
|
|
15
|
+
"scripts/dev-clean.sh",
|
|
16
|
+
"scripts/netlify-dev-wrapper.sh",
|
|
17
|
+
"scripts/verify-integrity.sh",
|
|
18
|
+
"scripts/build-manifest.sh",
|
|
19
|
+
"scripts/checksum-manifest.mts",
|
|
20
|
+
"scripts/verify-manifest.mts",
|
|
21
|
+
"scripts/boundary-check.sh",
|
|
22
|
+
"scripts/verify-install.ts",
|
|
12
23
|
"config/",
|
|
24
|
+
"!config/*.tsbuildinfo",
|
|
25
|
+
"!config/deno.lock",
|
|
26
|
+
"!config/package-lock.json",
|
|
27
|
+
"templates/project/",
|
|
28
|
+
"vitest.config.ts",
|
|
13
29
|
"netlify.toml",
|
|
14
|
-
"
|
|
15
|
-
".framework/
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
".
|
|
24
|
-
".
|
|
25
|
-
".
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"docs/ARCHITECTURE.md",
|
|
30
|
-
"docs/INSTALL.md",
|
|
31
|
-
"docs/README.md",
|
|
32
|
-
"docs/spine-core--api-reference.md",
|
|
33
|
-
"docs/design-schema-spec.md",
|
|
34
|
-
"docs/dev-guides/",
|
|
35
|
-
"docs/npm-packages-plan.md",
|
|
30
|
+
".env.example",
|
|
31
|
+
".framework/",
|
|
32
|
+
"!.framework/migrations/archive/",
|
|
33
|
+
"!.framework/functions/_quarantine/",
|
|
34
|
+
"!.framework/tests/integration/",
|
|
35
|
+
"!.framework/public/spine.config.json",
|
|
36
|
+
"!**/*.tsbuildinfo",
|
|
37
|
+
"!**/.DS_Store",
|
|
38
|
+
"!**/.env",
|
|
39
|
+
"!**/.env.local",
|
|
40
|
+
"!**/.env.production",
|
|
41
|
+
"!**/.env.development",
|
|
42
|
+
"!**/.env.test",
|
|
43
|
+
"!**/.xenv",
|
|
44
|
+
"!**/.xenv.*",
|
|
36
45
|
"README.md",
|
|
37
46
|
"LICENSE.md"
|
|
38
47
|
],
|
|
@@ -57,13 +66,15 @@
|
|
|
57
66
|
"scripts": {
|
|
58
67
|
"spine-framework": "tsx .framework/cli/index.ts",
|
|
59
68
|
"dev": "vite --config config/vite.config.ts",
|
|
69
|
+
"dev:netlify": "bash scripts/dev-netlify.sh",
|
|
70
|
+
"dev:stop": "bash scripts/dev-clean.sh",
|
|
60
71
|
"assemble": "bash scripts/assemble.sh",
|
|
61
72
|
"assemble:frontend": "bash scripts/assemble-frontend.sh",
|
|
62
73
|
"assemble:functions": "bash scripts/assemble-functions.sh",
|
|
63
74
|
"manifest": "bash scripts/build-manifest.sh",
|
|
64
75
|
"verify": "bash scripts/verify-integrity.sh",
|
|
65
76
|
"prebuild": "npm run assemble && npm run verify",
|
|
66
|
-
"build": "
|
|
77
|
+
"build": "vite build --config config/vite.config.ts",
|
|
67
78
|
"preview": "vite preview --config config/vite.config.ts",
|
|
68
79
|
"lint": "eslint .",
|
|
69
80
|
"app-install": "tsx scripts/app-install-cli.ts",
|
|
@@ -75,12 +86,18 @@
|
|
|
75
86
|
"test:boundary": "bash scripts/boundary-check.sh",
|
|
76
87
|
"docs": "typedoc --entryPoints .framework/functions/_shared/index.ts --out docs/generated",
|
|
77
88
|
"mcp": "tsx --env-file=.env .framework/mcp/index.ts",
|
|
78
|
-
"mcp:spine-framework": "tsx --env-file=.env .framework/mcp/index.ts"
|
|
89
|
+
"mcp:spine-framework": "tsx --env-file=.env .framework/mcp/index.ts",
|
|
90
|
+
"prepack": "node custom/npm/scripts/prepack-framework.mjs stage",
|
|
91
|
+
"postpack": "node custom/npm/scripts/prepack-framework.mjs clean",
|
|
92
|
+
"cil:migrate-markers": "tsx .framework/scripts/cil-migrate-markers.ts",
|
|
93
|
+
"typecheck": "tsc -b config/tsconfig.json",
|
|
94
|
+
"typecheck:functions": "tsc --noEmit -p config/tsconfig.functions.json"
|
|
79
95
|
},
|
|
80
96
|
"dependencies": {
|
|
81
97
|
"@base-ui/react": "^1.4.1",
|
|
82
98
|
"@fontsource-variable/inter": "^5.2.8",
|
|
83
99
|
"@heroicons/react": "^2.2.0",
|
|
100
|
+
"@marsidev/react-turnstile": "^1.1.0",
|
|
84
101
|
"@radix-ui/react-accordion": "^1.2.12",
|
|
85
102
|
"@radix-ui/react-avatar": "^1.1.3",
|
|
86
103
|
"@radix-ui/react-dialog": "^1.1.6",
|
|
@@ -115,6 +132,7 @@
|
|
|
115
132
|
"class-variance-authority": "^0.7.1",
|
|
116
133
|
"clsx": "^2.1.1",
|
|
117
134
|
"cmdk": "^1.1.1",
|
|
135
|
+
"commander": "^12.0.0",
|
|
118
136
|
"dagre": "^0.8.5",
|
|
119
137
|
"date-fns": "^4.1.0",
|
|
120
138
|
"dompurify": "^3.4.13",
|
|
@@ -153,6 +171,7 @@
|
|
|
153
171
|
"tiptap-markdown": "^0.9.0",
|
|
154
172
|
"tsx": "^4.21.0",
|
|
155
173
|
"tw-animate-css": "^1.4.0",
|
|
174
|
+
"typescript": "~5.6.2",
|
|
156
175
|
"vaul": "^1.1.2",
|
|
157
176
|
"ws": "^8.18.0"
|
|
158
177
|
},
|
|
@@ -168,14 +187,12 @@
|
|
|
168
187
|
"@vitejs/plugin-react": "^4.3.4",
|
|
169
188
|
"ajv": "^8.12.0",
|
|
170
189
|
"autoprefixer": "^10.4.20",
|
|
171
|
-
"commander": "^12.0.0",
|
|
172
190
|
"js-yaml": "^4.1.0",
|
|
191
|
+
"netlify-cli": "27.8.0",
|
|
173
192
|
"postcss": "^8.5.1",
|
|
174
193
|
"react-refresh": "^0.14.0",
|
|
175
194
|
"tailwindcss": "^3.4.17",
|
|
176
|
-
"tsx": "^4.21.0",
|
|
177
195
|
"typedoc": "^0.27.0",
|
|
178
|
-
"typescript": "~5.6.2",
|
|
179
196
|
"vite": "^6.0.11",
|
|
180
197
|
"vitest": "^2.1.9"
|
|
181
198
|
},
|
|
@@ -1,89 +1,172 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# CIL[BEGIN stable_id="~/scripts/assemble-frontend.sh:module:script" type="script" identity="assemble-frontend" parent="~/scripts/assemble-frontend.sh"]
|
|
4
|
+
# CIL[DOC-MACRO purpose="Assemble .framework/src base layer + each custom app under .assembled/src/<app-slug>/ and merge public assets with collision detection, for the Vite build."]
|
|
5
|
+
# CIL[DOC-RESPONSIBILITY responsibility="Stage core src, per-app dirs (verbatim, no basename flattening), index.html path fix, _redirects, and public assets; then mtime-preserving rsync into .assembled/src and public/."]
|
|
6
|
+
# CIL[DOC-CONTEXT module="assembly" layer="build" related_files="scripts/assemble-functions.sh,scripts/assemble.sh,config/vite.config.ts,.framework/src/components/CustomAppLoader.tsx"]
|
|
7
|
+
# CIL[DOC-CONTRACT inputs=".framework/src,.framework/public,custom/apps/*,spine.config.json; env SPINE_PROJECT_ROOT (fixture override for tests)" outputs=".assembled/src + merged public/; exit 1 on public-path collision" errors="hard error naming both sources when two public assets share a relative path with different content" side_effects="rewrites .assembled/src and public/"]
|
|
8
|
+
# CIL[DOC-MICRO logic_summary="Temp-dir staging → core copy → per-app rsync with excludes (functions/seed/public/node_modules/dist/dotfiles) → public manifest-tracked collision check → rsync -rlc (no -t) publish." notable_decisions="identical duplicate public assets skip silently; root spine.config.json wins over framework template; no .gitkeep rsync exclude so --delete can remove stale dirs"]
|
|
9
|
+
# CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
10
|
+
# CIL[DOC-STABILITY stability="stable"]
|
|
11
|
+
# CIL[DOC-NOTE type="invariant" content="import.meta.glob('../../../custom/apps/*/index.tsx') in CustomAppLoader must keep resolving — app dirs are copied verbatim under src/<slug>/, never flattened by basename."]
|
|
12
|
+
# CIL[END stable_id="~/scripts/assemble-frontend.sh:module:script"]
|
|
13
|
+
|
|
14
|
+
# Frontend Assembly - Merge .framework/src + custom/apps/* → .assembled/src
|
|
4
15
|
#
|
|
5
16
|
# Purpose: Create unified frontend source directory for Vite build process.
|
|
6
|
-
# - .framework/src is the canonical Spine frontend
|
|
7
|
-
# - custom/apps
|
|
8
|
-
#
|
|
17
|
+
# - .framework/src is the canonical Spine frontend (base layer at root)
|
|
18
|
+
# - each custom/apps/<app> is copied to .assembled/src/<app-slug>/ VERBATIM —
|
|
19
|
+
# no basename flattening (two apps' components/ must never merge silently)
|
|
20
|
+
# - custom app index resolution uses import.meta.glob('../../../custom/apps/*/index.tsx')
|
|
21
|
+
# in .framework/src/components/CustomAppLoader.tsx — assembled app dirs exist
|
|
22
|
+
# for @/(@core)-style imports and layout consistency, not for the glob
|
|
9
23
|
#
|
|
10
24
|
# Process:
|
|
11
|
-
# 1.
|
|
12
|
-
# 2. Copy core src files
|
|
13
|
-
# 3.
|
|
25
|
+
# 1. Assemble into temp directory first
|
|
26
|
+
# 2. Copy core src files (base layer)
|
|
27
|
+
# 3. Copy each app to <app-slug>/, excluding functions/, seed/, public/,
|
|
28
|
+
# node_modules, dist, and dotfiles
|
|
29
|
+
# 4. Merge public assets with same-relative-path collision detection
|
|
30
|
+
# 5. rsync -c into target so unchanged files keep their mtimes — Vite then only
|
|
31
|
+
# reloads modules that actually changed instead of every file
|
|
32
|
+
#
|
|
33
|
+
# SPINE_PROJECT_ROOT (optional): override the project root — used by the
|
|
34
|
+
# fixture-based unit tests; production use leaves it unset.
|
|
14
35
|
#
|
|
15
|
-
# Dependencies: standard bash utilities, find, cp, rsync
|
|
36
|
+
# Dependencies: standard bash utilities, find, cp, rsync, cmp
|
|
16
37
|
|
|
17
38
|
set -euo pipefail
|
|
18
39
|
|
|
19
40
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
20
|
-
|
|
41
|
+
# Canonicalize (-P resolves symlinks) — consistent with assemble-functions.sh
|
|
42
|
+
# and safe when the repo itself is reached through a symlinked path.
|
|
43
|
+
PROJECT_ROOT="$(cd "${SPINE_PROJECT_ROOT:-$(dirname "$SCRIPT_DIR")}" && pwd -P)"
|
|
21
44
|
|
|
22
45
|
CORE_SRC_DIR="$PROJECT_ROOT/.framework/src"
|
|
23
46
|
CUSTOM_SRC_DIR="$PROJECT_ROOT/custom/apps"
|
|
24
47
|
TARGET_SRC_DIR="$PROJECT_ROOT/.assembled/src"
|
|
48
|
+
VITE_PUBLIC_DIR="$PROJECT_ROOT/public"
|
|
49
|
+
TMP_ROOT="$PROJECT_ROOT/.frontend-assemble-tmp"
|
|
50
|
+
TMP_SRC_DIR="$TMP_ROOT/src"
|
|
51
|
+
TMP_PUBLIC_DIR="$TMP_ROOT/public"
|
|
52
|
+
# rel-path → source-file map for public-asset collision errors
|
|
53
|
+
PUBLIC_MANIFEST="$TMP_ROOT/public-manifest.tsv"
|
|
25
54
|
|
|
26
55
|
echo "🔧 Assembling frontend → $TARGET_SRC_DIR"
|
|
27
56
|
|
|
28
|
-
# 1.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
mkdir -p "$TARGET_SRC_DIR"
|
|
33
|
-
fi
|
|
57
|
+
# 1. Stage into temp dir
|
|
58
|
+
rm -rf "$TMP_ROOT"
|
|
59
|
+
mkdir -p "$TMP_SRC_DIR" "$TMP_PUBLIC_DIR"
|
|
60
|
+
: > "$PUBLIC_MANIFEST"
|
|
34
61
|
|
|
35
62
|
# 2. Copy core src (base layer)
|
|
36
63
|
if [ -d "$CORE_SRC_DIR" ]; then
|
|
37
|
-
|
|
38
|
-
cp -r "$CORE_SRC_DIR"/* "$TARGET_SRC_DIR"/ 2>/dev/null || true
|
|
64
|
+
cp -r "$CORE_SRC_DIR"/* "$TMP_SRC_DIR"/ 2>/dev/null || true
|
|
39
65
|
echo " ✓ Core: $(find "$CORE_SRC_DIR" -name '*.tsx' -o -name '*.ts' -o -name '*.css' | wc -l | tr -d ' ') files"
|
|
40
66
|
else
|
|
41
67
|
echo " ⚠ Core: $CORE_SRC_DIR not found"
|
|
42
68
|
fi
|
|
43
69
|
|
|
44
|
-
#
|
|
70
|
+
# 3. Copy index.html, fixing the script src path for assembled structure
|
|
45
71
|
if [ -f "$PROJECT_ROOT/.framework/index.html" ]; then
|
|
46
|
-
|
|
47
|
-
sed 's|/src/main.tsx|./main.tsx|g' "$PROJECT_ROOT/.framework/index.html" > "$TARGET_SRC_DIR/index.html"
|
|
72
|
+
sed 's|/src/main.tsx|./main.tsx|g' "$PROJECT_ROOT/.framework/index.html" > "$TMP_SRC_DIR/index.html"
|
|
48
73
|
echo " ✓ Core: index.html (paths fixed)"
|
|
49
74
|
fi
|
|
50
75
|
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
|
|
76
|
+
# 4. Stage a public-asset source dir into TMP_PUBLIC_DIR with collision
|
|
77
|
+
# detection. The SAME relative path may never come from two different sources:
|
|
78
|
+
# - identical content → skip silently (duplicate copy is harmless)
|
|
79
|
+
# - differing content → hard error naming both source files
|
|
80
|
+
stage_public_dir() {
|
|
81
|
+
local src_dir="$1"
|
|
82
|
+
local f rel staged prev
|
|
83
|
+
while IFS= read -r -d '' f; do
|
|
84
|
+
rel="${f#"$src_dir"/}"
|
|
85
|
+
staged="$TMP_PUBLIC_DIR/$rel"
|
|
86
|
+
if [ -e "$staged" ]; then
|
|
87
|
+
if cmp -s "$f" "$staged"; then
|
|
88
|
+
continue
|
|
89
|
+
fi
|
|
90
|
+
prev="$(awk -F '\t' -v r="$rel" '$1 == r { print $2; exit }' "$PUBLIC_MANIFEST")"
|
|
91
|
+
echo " ✗ Public asset collision: '$rel' is provided by both" >&2
|
|
92
|
+
echo " - $prev" >&2
|
|
93
|
+
echo " - $f" >&2
|
|
94
|
+
echo " Rename one of them — public/ merges flat, last-wins is forbidden." >&2
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
mkdir -p "$(dirname "$staged")"
|
|
98
|
+
cp "$f" "$staged"
|
|
99
|
+
printf '%s\t%s\n' "$rel" "$f" >> "$PUBLIC_MANIFEST"
|
|
100
|
+
done < <(find "$src_dir" -type f ! -name '.*' -print0 | sort -z)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# 5. Framework public assets merge first — Vite's publicDir is
|
|
104
|
+
# PROJECT_ROOT/public, so static files must land there to be served at root URL
|
|
55
105
|
if [ -d "$PROJECT_ROOT/.framework/public" ]; then
|
|
56
|
-
|
|
57
|
-
cp -r "$PROJECT_ROOT/.framework/public"/* "$VITE_PUBLIC_DIR/" 2>/dev/null || true
|
|
106
|
+
stage_public_dir "$PROJECT_ROOT/.framework/public"
|
|
58
107
|
echo " ✓ Core: $(find "$PROJECT_ROOT/.framework/public" -type f | wc -l | tr -d ' ') public files"
|
|
59
108
|
fi
|
|
60
109
|
|
|
61
|
-
#
|
|
110
|
+
# 6. Copy _redirects to Vite-served root for Netlify dev (served from .assembled/src root)
|
|
62
111
|
if [ -f "$PROJECT_ROOT/.framework/public/_redirects" ]; then
|
|
63
|
-
cp "$PROJECT_ROOT/.framework/public/_redirects" "$
|
|
112
|
+
cp "$PROJECT_ROOT/.framework/public/_redirects" "$TMP_SRC_DIR/_redirects"
|
|
64
113
|
echo " ✓ Core: _redirects copied to Vite-served directory for Netlify dev"
|
|
65
114
|
fi
|
|
66
115
|
|
|
67
|
-
#
|
|
116
|
+
# 7. Per-app copy: custom/apps/<app> → .assembled/src/<app-slug>/ verbatim.
|
|
117
|
+
# Excluded: functions (goes to .assembled/netlify/functions), seed, public
|
|
118
|
+
# (merged into /public above), node_modules, dist, dotfiles.
|
|
119
|
+
CUSTOM_COUNT=0
|
|
120
|
+
if [ -d "$CUSTOM_SRC_DIR" ]; then
|
|
121
|
+
for app_dir in "$CUSTOM_SRC_DIR"/*/; do
|
|
122
|
+
[ -d "$app_dir" ] || continue
|
|
123
|
+
slug="$(basename "$app_dir")"
|
|
124
|
+
|
|
125
|
+
rsync -a \
|
|
126
|
+
--exclude='functions' \
|
|
127
|
+
--exclude='seed' \
|
|
128
|
+
--exclude='public' \
|
|
129
|
+
--exclude='node_modules' \
|
|
130
|
+
--exclude='dist' \
|
|
131
|
+
--exclude='.*' \
|
|
132
|
+
"$app_dir" "$TMP_SRC_DIR/$slug/"
|
|
133
|
+
|
|
134
|
+
# App public assets merge into /public AFTER framework public; a same
|
|
135
|
+
# relative path in two sources (or vs framework) is a hard error above.
|
|
136
|
+
if [ -d "$app_dir/public" ]; then
|
|
137
|
+
stage_public_dir "$app_dir/public"
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
app_count=$(find "$TMP_SRC_DIR/$slug" -name '*.tsx' -o -name '*.ts' -o -name '*.css' 2>/dev/null | wc -l | tr -d ' ')
|
|
141
|
+
CUSTOM_COUNT=$((CUSTOM_COUNT + app_count))
|
|
142
|
+
echo " ✓ $slug: $app_count files → src/$slug/"
|
|
143
|
+
done
|
|
144
|
+
fi
|
|
145
|
+
if [ "$CUSTOM_COUNT" -eq 0 ]; then
|
|
146
|
+
echo " ○ Custom: (empty)"
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# 8. spine.config.json → staged public (root config, served at /spine.config.json).
|
|
150
|
+
# The ROOT copy is the instance config and intentionally wins over the
|
|
151
|
+
# framework template of the same name (framework/public/spine.config.json).
|
|
68
152
|
if [ -f "$PROJECT_ROOT/spine.config.json" ]; then
|
|
69
|
-
|
|
70
|
-
cp "$PROJECT_ROOT/spine.config.json" "$VITE_PUBLIC_DIR/spine.config.json"
|
|
153
|
+
cp -f "$PROJECT_ROOT/spine.config.json" "$TMP_PUBLIC_DIR/spine.config.json"
|
|
71
154
|
echo " ✓ Config: spine.config.json copied to public/"
|
|
72
155
|
fi
|
|
73
156
|
|
|
74
|
-
#
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
157
|
+
# 9. Publish staged public assets. -c compares content checksums; deliberately
|
|
158
|
+
# NO -t so unchanged files keep mtimes (see final sync note below).
|
|
159
|
+
mkdir -p "$VITE_PUBLIC_DIR"
|
|
160
|
+
rsync -rlc "$TMP_PUBLIC_DIR"/ "$VITE_PUBLIC_DIR"/
|
|
161
|
+
|
|
162
|
+
# 10. Sync temp into place. -c compares content checksums; deliberately NO -t —
|
|
163
|
+
# otherwise rsync "corrects" mtimes of unchanged files to the fresh temp-copy
|
|
164
|
+
# time and Vite reloads the entire module graph on every assemble.
|
|
165
|
+
mkdir -p "$TARGET_SRC_DIR"
|
|
166
|
+
# No .gitkeep exclusion: .assembled/ is gitignored, and leftover .gitkeep
|
|
167
|
+
# files inside stale dirs would make --delete treat them as non-empty.
|
|
168
|
+
rsync -rlc --delete "$TMP_SRC_DIR"/ "$TARGET_SRC_DIR"/
|
|
169
|
+
rm -rf "$TMP_ROOT"
|
|
87
170
|
|
|
88
171
|
echo " ✓ Assembled: $(find "$TARGET_SRC_DIR" -name '*.tsx' -o -name '*.ts' -o -name '*.css' | wc -l | tr -d ' ') total files"
|
|
89
172
|
echo "✅ Done"
|