spine-framework 0.3.145 → 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 +15 -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,79 @@
|
|
|
1
|
+
-- CIL[BEGIN stable_id="~/.framework/migrations/046_security_missing_rls.sql:security_missing_rls:file" type="file" identity="security_missing_rls" parent="~/.framework/migrations/046_security_missing_rls.sql"]
|
|
2
|
+
-- CIL[DOC-MACRO purpose="Enable RLS on the nine tables that currently expose all rows to any PostgREST caller"]
|
|
3
|
+
-- CIL[DOC-RESPONSIBILITY responsibility="Enable row level security on account_paths, invites, alerts, observability, integration_routes, test_runs, test_cases, test_results, and _spine_migrations with policies matching each table's intended consumer"]
|
|
4
|
+
-- CIL[DOC-CONTEXT module="migrations" layer="database" related_files=".framework/migrations/006_security_hardening_rls.sql,.framework/migrations/045_security_critical_rls.sql,.framework/migrations/035_rate_limits.sql"]
|
|
5
|
+
-- CIL[DOC-CONTRACT inputs="none" outputs="RLS enabled + policies created" errors="SQL errors if referenced objects are missing" side_effects="Blocks direct PostgREST reads/writes previously allowed by missing RLS"]
|
|
6
|
+
-- CIL[DOC-MICRO logic_summary="account_paths is system-admin read (get_accessible_accounts SECURITY DEFINER still serves all lookups); invites/alerts/observability get account-scoped access on account_id; integration_routes/test_*/_spine_migrations are service_role-only infrastructure with no tenant use case" notable_decisions="all existing consumers use adminDb which bypasses RLS entirely — these policies only gate direct PostgREST access via the anon/user keys; service_role policies are declared explicitly for documentation even though service_role holds BYPASSRLS"]
|
|
7
|
+
-- CIL[DOC-CONFIDENCE pass="first" score="0.85" flags="none"]
|
|
8
|
+
-- CIL[DOC-STABILITY stability="stable"]
|
|
9
|
+
|
|
10
|
+
-- account_paths: the tenant-hierarchy closure table. Reading it directly
|
|
11
|
+
-- reveals every parent/child relationship without going through
|
|
12
|
+
-- get_accessible_accounts(). That SECURITY DEFINER function continues to serve
|
|
13
|
+
-- all legitimate lookups; direct reads are system-admin only.
|
|
14
|
+
ALTER TABLE public.account_paths ENABLE ROW LEVEL SECURITY;
|
|
15
|
+
|
|
16
|
+
CREATE POLICY account_paths_read ON public.account_paths FOR SELECT
|
|
17
|
+
USING (public.person_is_system_admin(public.current_actor_id()));
|
|
18
|
+
|
|
19
|
+
CREATE POLICY account_paths_service_role ON public.account_paths FOR ALL
|
|
20
|
+
TO service_role USING (true) WITH CHECK (true);
|
|
21
|
+
|
|
22
|
+
-- invites: invitation metadata is scoped to the issuing account. Invite tokens
|
|
23
|
+
-- themselves live on people.data (validated server-side via adminDb), so
|
|
24
|
+
-- account-scoped access covers admin list/revoke without exposing tokens.
|
|
25
|
+
ALTER TABLE public.invites ENABLE ROW LEVEL SECURITY;
|
|
26
|
+
|
|
27
|
+
CREATE POLICY invites_access ON public.invites FOR ALL
|
|
28
|
+
USING (account_id IN (SELECT public.get_accessible_accounts(public.current_actor_id())))
|
|
29
|
+
WITH CHECK (account_id IN (SELECT public.get_accessible_accounts(public.current_actor_id())));
|
|
30
|
+
|
|
31
|
+
CREATE POLICY invites_service_role ON public.invites FOR ALL
|
|
32
|
+
TO service_role USING (true) WITH CHECK (true);
|
|
33
|
+
|
|
34
|
+
-- alerts: account-scoped operational alerts.
|
|
35
|
+
ALTER TABLE public.alerts ENABLE ROW LEVEL SECURITY;
|
|
36
|
+
|
|
37
|
+
CREATE POLICY alerts_access ON public.alerts FOR ALL
|
|
38
|
+
USING (account_id IN (SELECT public.get_accessible_accounts(public.current_actor_id())))
|
|
39
|
+
WITH CHECK (account_id IN (SELECT public.get_accessible_accounts(public.current_actor_id())));
|
|
40
|
+
|
|
41
|
+
CREATE POLICY alerts_service_role ON public.alerts FOR ALL
|
|
42
|
+
TO service_role USING (true) WITH CHECK (true);
|
|
43
|
+
|
|
44
|
+
-- observability: account-scoped telemetry (agent runs, traces). Written only
|
|
45
|
+
-- via adminDb; account members can read their own telemetry.
|
|
46
|
+
ALTER TABLE public.observability ENABLE ROW LEVEL SECURITY;
|
|
47
|
+
|
|
48
|
+
CREATE POLICY observability_access ON public.observability FOR ALL
|
|
49
|
+
USING (account_id IN (SELECT public.get_accessible_accounts(public.current_actor_id())))
|
|
50
|
+
WITH CHECK (account_id IN (SELECT public.get_accessible_accounts(public.current_actor_id())));
|
|
51
|
+
|
|
52
|
+
CREATE POLICY observability_service_role ON public.observability FOR ALL
|
|
53
|
+
TO service_role USING (true) WITH CHECK (true);
|
|
54
|
+
|
|
55
|
+
-- test_runs / test_cases / test_results / _spine_migrations:
|
|
56
|
+
-- internal infrastructure consumed exclusively by adminDb in system-cron.ts,
|
|
57
|
+
-- tests.ts, system.ts, and cli. No tenant-facing use case — service_role only
|
|
58
|
+
-- (matching the rate_limits precedent in 035). integration_routes is not
|
|
59
|
+
-- covered — 004 drops it as dead schema.
|
|
60
|
+
ALTER TABLE public.test_runs ENABLE ROW LEVEL SECURITY;
|
|
61
|
+
CREATE POLICY test_runs_service_role ON public.test_runs FOR ALL
|
|
62
|
+
TO service_role USING (true) WITH CHECK (true);
|
|
63
|
+
|
|
64
|
+
ALTER TABLE public.test_cases ENABLE ROW LEVEL SECURITY;
|
|
65
|
+
CREATE POLICY test_cases_service_role ON public.test_cases FOR ALL
|
|
66
|
+
TO service_role USING (true) WITH CHECK (true);
|
|
67
|
+
|
|
68
|
+
ALTER TABLE public.test_results ENABLE ROW LEVEL SECURITY;
|
|
69
|
+
CREATE POLICY test_results_service_role ON public.test_results FOR ALL
|
|
70
|
+
TO service_role USING (true) WITH CHECK (true);
|
|
71
|
+
|
|
72
|
+
ALTER TABLE public._spine_migrations ENABLE ROW LEVEL SECURITY;
|
|
73
|
+
CREATE POLICY spine_migrations_service_role ON public._spine_migrations FOR ALL
|
|
74
|
+
TO service_role USING (true) WITH CHECK (true);
|
|
75
|
+
-- CIL[DOC-VECTOR type="context" content="purpose='Enable RLS on nine tables that were fully exposed to PostgREST.'; No verified external callers; imports: none"]
|
|
76
|
+
-- CIL[DOC-VECTOR type="blast_radius" content="Direct PostgREST access to account_paths/invites/alerts/observability/integration_routes/test_*/_spine_migrations is now gated; adminDb consumers unaffected (service_role bypasses RLS)" status="ready"]
|
|
77
|
+
-- CIL[DOC-VECTOR type="configuration" content="Depends on public.current_actor_id, public.person_is_system_admin, public.get_accessible_accounts; requires account_id column on invites/alerts/observability" status="ready"]
|
|
78
|
+
-- CIL[DOC-VECTOR type="constraint" content="Any client that read these tables via anon/user keys must move to a function path or accept denial" status="ready"]
|
|
79
|
+
-- CIL[END stable_id="~/.framework/migrations/046_security_missing_rls.sql:security_missing_rls:file"]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-- CIL[BEGIN stable_id="~/.framework/migrations/047_people_updated_by.sql:people_updated_by:file" type="file" identity="people_updated_by" parent="~/.framework/migrations/047_people_updated_by.sql"]
|
|
2
|
+
-- CIL[DOC-MACRO purpose="Add updated_by to entity tables missing it so admin-data PATCH stops failing for human callers"]
|
|
3
|
+
-- CIL[DOC-RESPONSIBILITY responsibility="Add nullable uuid updated_by columns to people, watchers, and attachments — the three entity tables that follow the created_by/updated_by audit convention but lacked the column"]
|
|
4
|
+
-- CIL[DOC-CONTEXT module="migrations" layer="database" related_files=".framework/functions/admin-data.ts,.framework/migrations/045_security_critical_rls.sql,.framework/migrations/046_security_missing_rls.sql"]
|
|
5
|
+
-- CIL[DOC-CONTRACT inputs="none" outputs="Three new nullable uuid columns" errors="none — add column if not exists is idempotent" side_effects="Enables admin-data to stamp updated_by on PATCH for people/watchers/attachments"]
|
|
6
|
+
-- CIL[DOC-MICRO logic_summary="admin-data's update handler unconditionally writes updated_by for every non-raw entity; PATCH on these three tables failed with a schema-cache error for human callers. Column shape matches sibling tables (items/accounts/threads/messages/links): nullable uuid, no FK — created_by/updated_by across the schema are plain uuid markers, not enforced references" notable_decisions="nullable and unindexed because no read path queries by updated_by today; kept people/watchers/attachments together since they share the identical gap"]
|
|
7
|
+
-- CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
8
|
+
-- CIL[DOC-STABILITY stability="stable"]
|
|
9
|
+
|
|
10
|
+
-- Migration 047: add updated_by to entity tables that follow the created_by/
|
|
11
|
+
-- updated_by audit convention but are missing the column. admin-data's update
|
|
12
|
+
-- handler unconditionally writes updated_by for every non-raw entity, so PATCH
|
|
13
|
+
-- on people/watchers/attachments currently fails for human callers with
|
|
14
|
+
-- "Could not find the 'updated_by' column ... in the schema cache".
|
|
15
|
+
|
|
16
|
+
alter table public.people add column if not exists updated_by uuid;
|
|
17
|
+
alter table public.watchers add column if not exists updated_by uuid;
|
|
18
|
+
alter table public.attachments add column if not exists updated_by uuid;
|
|
19
|
+
|
|
20
|
+
comment on column public.people.updated_by is 'Person id of the last updater; written by admin-data update handler';
|
|
21
|
+
comment on column public.watchers.updated_by is 'Person id of the last updater; written by admin-data update handler';
|
|
22
|
+
comment on column public.attachments.updated_by is 'Person id of the last updater; written by admin-data update handler';
|
|
23
|
+
-- CIL[DOC-VECTOR type="context" content="purpose='Fix admin-data PATCH failures on people/watchers/attachments by adding the missing updated_by column.'; No verified external callers; imports: none"]
|
|
24
|
+
-- CIL[DOC-VECTOR type="blast_radius" content="Human-caller updates via admin-data to people (user settings modal), watchers, and attachments now succeed instead of failing with a schema-cache error" status="ready"]
|
|
25
|
+
-- CIL[DOC-VECTOR type="configuration" content="None — plain ALTER TABLE; admin-data update handler consumes the column automatically" status="ready"]
|
|
26
|
+
-- CIL[DOC-VECTOR type="constraint" content="Column is a plain uuid marker with no FK, matching the created_by convention across the schema" status="ready"]
|
|
27
|
+
-- CIL[END stable_id="~/.framework/migrations/047_people_updated_by.sql:people_updated_by:file"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
-- CIL[BEGIN stable_id="~/.framework/migrations/048_watcher_last_seen_at.sql:watcher_last_seen_at:file" type="file" identity="watcher_last_seen_at" parent="~/.framework/migrations/048_watcher_last_seen_at.sql"]
|
|
2
|
+
-- CIL[DOC-MACRO purpose="Declare last_seen_at in the watcher type design_schema so read sanitize and update validation accept it"]
|
|
3
|
+
-- CIL[DOC-RESPONSIBILITY responsibility="Merge the last_seen_at field definition into the watcher type's design_schema.fields and validation_schema.fields"]
|
|
4
|
+
-- CIL[DOC-CONTEXT module="migrations" layer="database" related_files=".framework/functions/_shared/permissions.ts,custom/apps/*/hooks/useWatchers.ts"]
|
|
5
|
+
-- CIL[DOC-CONTRACT inputs="none" outputs="watcher type accepts data.last_seen_at on read/write" errors="none — jsonb_set with create_missing is idempotent" side_effects="Unread tracking (markSeen/hasUnreadActivity) works for watcher rows"]
|
|
6
|
+
-- CIL[DOC-MICRO logic_summary="sanitizeRecordData strips data keys not declared in design_schema.fields on read, and validateUpdatePermissions rejects them on PATCH — so watcher.data.last_seen_at (written by downstream markSeen hooks) was dropped both ways. Declaring the field makes it readable and writable for roles with record update (member, support). Non-system field: system fields are record columns, last_seen_at lives in data." notable_decisions="type rows are global (kind+slug unique) so updating the single watcher row covers every account"]
|
|
7
|
+
-- CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
8
|
+
-- CIL[DOC-STABILITY stability="stable"]
|
|
9
|
+
|
|
10
|
+
update public.types
|
|
11
|
+
set design_schema = jsonb_set(
|
|
12
|
+
design_schema,
|
|
13
|
+
'{fields,last_seen_at}',
|
|
14
|
+
'{"data_type":"datetime","label":"Last Seen","required":false,"validation":null}'::jsonb,
|
|
15
|
+
true
|
|
16
|
+
),
|
|
17
|
+
validation_schema = jsonb_set(
|
|
18
|
+
coalesce(validation_schema, '{"fields":{}}'::jsonb),
|
|
19
|
+
'{fields,last_seen_at}',
|
|
20
|
+
'{"data_type":"datetime","required":false}'::jsonb,
|
|
21
|
+
true
|
|
22
|
+
)
|
|
23
|
+
where kind = 'watcher' and slug = 'watcher';
|
|
24
|
+
-- CIL[END stable_id="~/.framework/migrations/048_watcher_last_seen_at.sql:watcher_last_seen_at:file"]
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
-- CIL[BEGIN stable_id="~/.framework/migrations/049_security_blocklist.sql:security_blocklist:file" type="file" identity="security_blocklist" parent="~/.framework/migrations/049_security_blocklist.sql"]
|
|
2
|
+
-- CIL[DOC-MACRO purpose="Platform security layer: security_blocklist table, person geo RPCs, and schema declarations for security fields"]
|
|
3
|
+
-- CIL[DOC-RESPONSIBILITY responsibility="Create public.security_blocklist (platform-wide denylist for person/account/email/email_domain/ip), person_touch_geo + person_record_registration_geo RPCs for IP capture, and declare registration/last-seen geo fields plus AO injection flags in the affected type design_schemas"]
|
|
4
|
+
-- CIL[DOC-CONTEXT module="migrations" layer="database" related_files=".framework/functions/_shared/security.ts,.framework/functions/_shared/middleware.ts,.framework/functions/invites.ts,.framework/functions/security.ts"]
|
|
5
|
+
-- CIL[DOC-CONTRACT inputs="none" outputs="security_blocklist table, person_touch_geo + person_record_registration_geo functions, declared type fields" errors="none — CREATE IF NOT EXISTS / jsonb_set are idempotent" side_effects="Middleware geo stamping + blocklist enforcement + security admin report work"]
|
|
6
|
+
-- CIL[DOC-MICRO logic_summary="Blocklist rows are (type, value) unique with severity/expiry; geo fields live in people.data so no schema change; jsonb_set declares them on the person/ao types so admin-data sanitize doesn't strip them on read" notable_decisions="RLS service_role-only: blocklist reads/writes happen exclusively through _shared/security.ts and functions/security.ts; starter disposable-domain rows seed the email_domain check"]
|
|
7
|
+
-- CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"]
|
|
8
|
+
-- CIL[DOC-STABILITY stability="stable"]
|
|
9
|
+
|
|
10
|
+
-- ── security_blocklist ─────────────────────────────────────────────
|
|
11
|
+
-- Platform-wide denylist. Enforced at three chokepoints:
|
|
12
|
+
-- registration (invites.completeRegistration), authenticated request
|
|
13
|
+
-- (middleware.createHandler), public request IP (createPublicHandler).
|
|
14
|
+
CREATE TABLE IF NOT EXISTS public.security_blocklist (
|
|
15
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
16
|
+
type text NOT NULL CHECK (type IN ('ip', 'email', 'email_domain', 'person_id', 'account_id')),
|
|
17
|
+
value text NOT NULL,
|
|
18
|
+
severity text NOT NULL DEFAULT 'hard' CHECK (severity IN ('soft', 'hard')),
|
|
19
|
+
reason text,
|
|
20
|
+
banned_by uuid,
|
|
21
|
+
expires_at timestamptz,
|
|
22
|
+
revoked_at timestamptz,
|
|
23
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
24
|
+
UNIQUE (type, value)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
CREATE INDEX IF NOT EXISTS idx_security_blocklist_lookup
|
|
28
|
+
ON public.security_blocklist (type, value)
|
|
29
|
+
WHERE revoked_at IS NULL;
|
|
30
|
+
|
|
31
|
+
ALTER TABLE public.security_blocklist ENABLE ROW LEVEL SECURITY;
|
|
32
|
+
|
|
33
|
+
-- Service-role only: all reads/writes flow through _shared/security.ts
|
|
34
|
+
-- (adminDb) and functions/security.ts (system-admin gated).
|
|
35
|
+
DROP POLICY IF EXISTS security_blocklist_service_role ON public.security_blocklist;
|
|
36
|
+
CREATE POLICY security_blocklist_service_role ON public.security_blocklist
|
|
37
|
+
FOR ALL TO service_role USING (true) WITH CHECK (true);
|
|
38
|
+
|
|
39
|
+
-- ── person_touch_geo ───────────────────────────────────────────────
|
|
40
|
+
-- Fire-and-forget last-seen geo stamp, called from middleware on every
|
|
41
|
+
-- authenticated request. Single-statement merge; does not touch
|
|
42
|
+
-- updated_at (record content did not change).
|
|
43
|
+
CREATE OR REPLACE FUNCTION public.person_touch_geo(p_person_id uuid, p_ip text, p_country text)
|
|
44
|
+
RETURNS void
|
|
45
|
+
LANGUAGE sql
|
|
46
|
+
SECURITY DEFINER
|
|
47
|
+
SET search_path = public
|
|
48
|
+
AS $$
|
|
49
|
+
UPDATE public.people
|
|
50
|
+
SET data = data || jsonb_build_object(
|
|
51
|
+
'last_ip', p_ip,
|
|
52
|
+
'last_country', p_country,
|
|
53
|
+
'last_seen_at', now()
|
|
54
|
+
)
|
|
55
|
+
WHERE id = p_person_id;
|
|
56
|
+
$$;
|
|
57
|
+
|
|
58
|
+
REVOKE ALL ON FUNCTION public.person_touch_geo(uuid, text, text) FROM PUBLIC;
|
|
59
|
+
REVOKE ALL ON FUNCTION public.person_touch_geo(uuid, text, text) FROM anon;
|
|
60
|
+
REVOKE ALL ON FUNCTION public.person_touch_geo(uuid, text, text) FROM authenticated;
|
|
61
|
+
GRANT EXECUTE ON FUNCTION public.person_touch_geo(uuid, text, text) TO service_role;
|
|
62
|
+
|
|
63
|
+
-- ── person_record_registration_geo ─────────────────────────────────
|
|
64
|
+
-- First-seen geo stamp, called from invites.completeRegistration.
|
|
65
|
+
-- COALESCE keeps the FIRST recorded values (a later registration attempt
|
|
66
|
+
-- must not overwrite the original signup IP).
|
|
67
|
+
CREATE OR REPLACE FUNCTION public.person_record_registration_geo(p_person_id uuid, p_ip text, p_country text)
|
|
68
|
+
RETURNS void
|
|
69
|
+
LANGUAGE sql
|
|
70
|
+
SECURITY DEFINER
|
|
71
|
+
SET search_path = public
|
|
72
|
+
AS $$
|
|
73
|
+
UPDATE public.people
|
|
74
|
+
SET data = data || jsonb_build_object(
|
|
75
|
+
'registration_ip', coalesce(data->>'registration_ip', p_ip),
|
|
76
|
+
'registration_country', coalesce(data->>'registration_country', p_country)
|
|
77
|
+
)
|
|
78
|
+
WHERE id = p_person_id;
|
|
79
|
+
$$;
|
|
80
|
+
|
|
81
|
+
REVOKE ALL ON FUNCTION public.person_record_registration_geo(uuid, text, text) FROM PUBLIC;
|
|
82
|
+
REVOKE ALL ON FUNCTION public.person_record_registration_geo(uuid, text, text) FROM anon;
|
|
83
|
+
REVOKE ALL ON FUNCTION public.person_record_registration_geo(uuid, text, text) FROM authenticated;
|
|
84
|
+
GRANT EXECUTE ON FUNCTION public.person_record_registration_geo(uuid, text, text) TO service_role;
|
|
85
|
+
|
|
86
|
+
-- ── Declare geo/security fields on the person type ─────────────────
|
|
87
|
+
-- Without declaration, admin-data sanitizeRecordData strips these data
|
|
88
|
+
-- keys on read (same failure mode as watcher.last_seen_at, migration 048).
|
|
89
|
+
update public.types
|
|
90
|
+
set design_schema = jsonb_set(
|
|
91
|
+
design_schema,
|
|
92
|
+
'{fields}',
|
|
93
|
+
(design_schema->'fields') || '{
|
|
94
|
+
"registration_ip": {"data_type":"text","label":"Registration IP","required":false,"validation":null},
|
|
95
|
+
"registration_country": {"data_type":"text","label":"Registration Country","required":false,"validation":null},
|
|
96
|
+
"last_ip": {"data_type":"text","label":"Last IP","required":false,"validation":null},
|
|
97
|
+
"last_country": {"data_type":"text","label":"Last Country","required":false,"validation":null},
|
|
98
|
+
"last_seen_at": {"data_type":"datetime","label":"Last Seen","required":false,"validation":null}
|
|
99
|
+
}'::jsonb,
|
|
100
|
+
true
|
|
101
|
+
),
|
|
102
|
+
validation_schema = jsonb_set(
|
|
103
|
+
coalesce(validation_schema, '{"fields":{}}'::jsonb),
|
|
104
|
+
'{fields}',
|
|
105
|
+
(coalesce(validation_schema, '{"fields":{}}'::jsonb)->'fields') || '{
|
|
106
|
+
"registration_ip": {"data_type":"text","required":false},
|
|
107
|
+
"registration_country": {"data_type":"text","required":false},
|
|
108
|
+
"last_ip": {"data_type":"text","required":false},
|
|
109
|
+
"last_country": {"data_type":"text","required":false},
|
|
110
|
+
"last_seen_at": {"data_type":"datetime","required":false}
|
|
111
|
+
}'::jsonb,
|
|
112
|
+
true
|
|
113
|
+
)
|
|
114
|
+
where kind = 'person' and slug = 'person';
|
|
115
|
+
|
|
116
|
+
-- ── Declare injection flags on Answer Once types ───────────────────
|
|
117
|
+
update public.types
|
|
118
|
+
set design_schema = jsonb_set(
|
|
119
|
+
design_schema,
|
|
120
|
+
'{fields}',
|
|
121
|
+
(design_schema->'fields') || '{
|
|
122
|
+
"injection_detected": {"data_type":"boolean","label":"Injection Detected","required":false,"validation":null},
|
|
123
|
+
"injection_pattern": {"data_type":"text","label":"Injection Pattern","required":false,"validation":null}
|
|
124
|
+
}'::jsonb,
|
|
125
|
+
true
|
|
126
|
+
),
|
|
127
|
+
validation_schema = jsonb_set(
|
|
128
|
+
coalesce(validation_schema, '{"fields":{}}'::jsonb),
|
|
129
|
+
'{fields}',
|
|
130
|
+
(coalesce(validation_schema, '{"fields":{}}'::jsonb)->'fields') || '{
|
|
131
|
+
"injection_detected": {"data_type":"boolean","required":false},
|
|
132
|
+
"injection_pattern": {"data_type":"text","required":false}
|
|
133
|
+
}'::jsonb,
|
|
134
|
+
true
|
|
135
|
+
)
|
|
136
|
+
where slug in ('ao_ticket_message', 'ao_support_ticket');
|
|
137
|
+
|
|
138
|
+
-- ── Starter disposable-email domain denylist ───────────────────────
|
|
139
|
+
INSERT INTO public.security_blocklist (type, value, severity, reason)
|
|
140
|
+
SELECT 'email_domain', d, 'hard', 'Disposable email provider'
|
|
141
|
+
FROM (VALUES
|
|
142
|
+
('mailinator.com'), ('tempmail.com'), ('temp-mail.org'),
|
|
143
|
+
('guerrillamail.com'), ('10minutemail.com'), ('yopmail.com'),
|
|
144
|
+
('maildrop.cc'), ('sharklasers.com'), ('dispostable.com'),
|
|
145
|
+
('trashmail.com'), ('getnada.com'), ('mailnesia.com')
|
|
146
|
+
) AS v(d)
|
|
147
|
+
ON CONFLICT (type, value) DO NOTHING;
|
|
148
|
+
-- CIL[END stable_id="~/.framework/migrations/049_security_blocklist.sql:security_blocklist:file"]
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
-- ── notifications: durable notification-delivery records ─────────────────────
|
|
2
|
+
-- send_notification previously wrote into watchers, which is a SUBSCRIPTION
|
|
3
|
+
-- table (target_type/target_id/person_id, unique per target+person) — not a
|
|
4
|
+
-- delivery log. This table holds actual deliveries: one row per recipient per
|
|
5
|
+
-- notification. watchers stays the "who is subscribed" record; notifications is
|
|
6
|
+
-- "what was sent".
|
|
7
|
+
|
|
8
|
+
CREATE TABLE IF NOT EXISTS public.notifications (
|
|
9
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
10
|
+
account_id uuid NOT NULL REFERENCES public.accounts(id),
|
|
11
|
+
person_id uuid NOT NULL, -- recipient
|
|
12
|
+
source_type text NOT NULL DEFAULT 'pipeline_execution',
|
|
13
|
+
source_id text, -- pipeline execution / request id (not always a uuid)
|
|
14
|
+
target_type text, -- entity the notification concerns
|
|
15
|
+
target_id uuid,
|
|
16
|
+
message text NOT NULL,
|
|
17
|
+
data jsonb NOT NULL DEFAULT '{}',
|
|
18
|
+
is_read boolean NOT NULL DEFAULT false,
|
|
19
|
+
read_at timestamptz,
|
|
20
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_inbox
|
|
24
|
+
ON public.notifications (account_id, person_id, is_read, created_at DESC);
|
|
25
|
+
|
|
26
|
+
CREATE INDEX IF NOT EXISTS idx_notifications_target
|
|
27
|
+
ON public.notifications (target_type, target_id);
|
|
28
|
+
|
|
29
|
+
ALTER TABLE public.notifications ENABLE ROW LEVEL SECURITY;
|
|
30
|
+
|
|
31
|
+
-- Recipients read and mark-read their own notifications. Delivery inserts go
|
|
32
|
+
-- through adminDb (service_role) from pipeline-runner / agent-runner.
|
|
33
|
+
DROP POLICY IF EXISTS notifications_recipient_read ON public.notifications;
|
|
34
|
+
CREATE POLICY notifications_recipient_read ON public.notifications FOR SELECT
|
|
35
|
+
USING (person_id = public.current_actor_id());
|
|
36
|
+
|
|
37
|
+
DROP POLICY IF EXISTS notifications_recipient_update ON public.notifications;
|
|
38
|
+
CREATE POLICY notifications_recipient_update ON public.notifications FOR UPDATE
|
|
39
|
+
USING (person_id = public.current_actor_id())
|
|
40
|
+
WITH CHECK (person_id = public.current_actor_id());
|
|
41
|
+
|
|
42
|
+
-- Account members can see deliveries into their workspace (admin/audit views).
|
|
43
|
+
DROP POLICY IF EXISTS notifications_account_read ON public.notifications;
|
|
44
|
+
CREATE POLICY notifications_account_read ON public.notifications FOR SELECT
|
|
45
|
+
USING (account_id IN (SELECT public.get_accessible_accounts(public.current_actor_id())));
|
|
46
|
+
|
|
47
|
+
DROP POLICY IF EXISTS notifications_service_role ON public.notifications;
|
|
48
|
+
CREATE POLICY notifications_service_role ON public.notifications
|
|
49
|
+
FOR ALL TO service_role USING (true) WITH CHECK (true);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
-- CIL[BEGIN stable_id="~/.framework/migrations/051_message_agent_fields.sql:message_agent_fields:file" type="file" identity="message_agent_fields" parent="~/.framework/migrations/051_message_agent_fields.sql"]
|
|
2
|
+
-- CIL[DOC-MACRO purpose="Declare agent-written data keys on support_reply/community_reply so read sanitize stops stripping citations and evidence metadata"]
|
|
3
|
+
-- CIL[DOC-RESPONSIBILITY responsibility="Merge the full set of agent-runner-written data fields into the support_reply and community_reply message types' design_schema.fields and validation_schema.fields"]
|
|
4
|
+
-- CIL[DOC-CONTEXT module="migrations" layer="database" related_files=".framework/functions/_shared/permissions.ts,.framework/functions/_shared/agent-runner.ts,custom/apps/demo/views/CustomerView.tsx,custom/apps/portal/pages/TicketsPage.tsx"]
|
|
5
|
+
-- CIL[DOC-CONTRACT inputs="none" outputs="support_reply/community_reply message rows (existing and new) expose cited_sources, evidence_state and tool-step keys on admin-data reads" errors="none — jsonb concat merge and restamp are idempotent" side_effects="customer transcripts render cited-source chips, the grounded badge, and step narration identically on the feed and self-poll paths"]
|
|
6
|
+
-- CIL[DOC-MICRO logic_summary="agent-runner persists cited_sources/evidence_state/tools_used/tool-step keys into message.data, but sanitizeRecordData drops undeclared data.* keys for non-system-admin readers — so fetchThreadMessages silently returned retrieved_sources-only rows and CustomerView fell back to rendering all retrieved candidates as cited chips (8 chips for 1 citation). Same failure mode as watcher.last_seen_at (048) and person geo fields (049). Field shape mirrors sibling retrieved_sources: system-stamped, read-only for every record role." notable_decisions="types are global (kind+slug unique) so updating support_reply/community_reply covers demo and portal installs; ao_ticket_message already declares the full set and is skipped"]
|
|
7
|
+
-- CIL[DOC-LEARNING topic="stamped_schema" content="Types gain fields on two levels: updating public.types.design_schema only helps NEW records — runtime records snapshot design_schema/validation_schema at creation and must be restamped (see scripts/restamp-ao-record-schemas.ts pattern). Separately, once a field has a validation_schema entry, admin-data display-formats it on read (formatFieldData stringifies json, booleans become 'Yes'/'No') — consumers must parse defensively"]
|
|
8
|
+
-- CIL[DOC-CONFIDENCE pass="first" score="0.95" flags="none"]
|
|
9
|
+
-- CIL[DOC-STABILITY stability="stable"]
|
|
10
|
+
|
|
11
|
+
update public.types
|
|
12
|
+
set design_schema = jsonb_set(
|
|
13
|
+
design_schema,
|
|
14
|
+
'{fields}',
|
|
15
|
+
(design_schema->'fields') || '{
|
|
16
|
+
"cited_sources": {"data_type":"json","label":"Cited Sources","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
17
|
+
"evidence_state": {"data_type":"text","label":"Evidence State","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
18
|
+
"evidence_found": {"data_type":"boolean","label":"Evidence Found","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
19
|
+
"mean_similarity": {"data_type":"number","label":"Mean Similarity","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
20
|
+
"tools_used": {"data_type":"json","label":"Tools Used","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
21
|
+
"human_reply": {"data_type":"boolean","label":"Human Reply","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
22
|
+
"tool": {"data_type":"text","label":"Tool","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
23
|
+
"params": {"data_type":"json","label":"Tool Params","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
24
|
+
"tool_call_id": {"data_type":"text","label":"Tool Call ID","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
25
|
+
"result": {"data_type":"json","label":"Tool Result","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
26
|
+
"details_truncated": {"data_type":"boolean","label":"Details Truncated","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
27
|
+
"error": {"data_type":"text","label":"Error","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
28
|
+
"max_turns": {"data_type":"number","label":"Max Turns","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
29
|
+
"turn_count": {"data_type":"number","label":"Turn Count","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
30
|
+
"phase": {"data_type":"text","label":"Phase","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
31
|
+
"analysis_summary": {"data_type":"textarea","label":"Analysis Summary","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
32
|
+
"case_analysis_id": {"data_type":"text","label":"Case Analysis ID","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}},
|
|
33
|
+
"confidence_score": {"data_type":"number","label":"Confidence Score","system":true,"permissions":{"member":["read"],"support":["read"],"member_admin":["read"],"support_admin":["read"],"system_admin":["read"]}}
|
|
34
|
+
}'::jsonb,
|
|
35
|
+
true
|
|
36
|
+
),
|
|
37
|
+
validation_schema = jsonb_set(
|
|
38
|
+
coalesce(validation_schema, '{"fields":{}}'::jsonb),
|
|
39
|
+
'{fields}',
|
|
40
|
+
(coalesce(validation_schema, '{"fields":{}}'::jsonb)->'fields') || '{
|
|
41
|
+
"cited_sources": {"data_type":"json","required":false},
|
|
42
|
+
"evidence_state": {"data_type":"text","required":false},
|
|
43
|
+
"evidence_found": {"data_type":"boolean","required":false},
|
|
44
|
+
"mean_similarity": {"data_type":"number","required":false},
|
|
45
|
+
"tools_used": {"data_type":"json","required":false},
|
|
46
|
+
"human_reply": {"data_type":"boolean","required":false},
|
|
47
|
+
"tool": {"data_type":"text","required":false},
|
|
48
|
+
"params": {"data_type":"json","required":false},
|
|
49
|
+
"tool_call_id": {"data_type":"text","required":false},
|
|
50
|
+
"result": {"data_type":"json","required":false},
|
|
51
|
+
"details_truncated": {"data_type":"boolean","required":false},
|
|
52
|
+
"error": {"data_type":"text","required":false},
|
|
53
|
+
"max_turns": {"data_type":"number","required":false},
|
|
54
|
+
"turn_count": {"data_type":"number","required":false},
|
|
55
|
+
"phase": {"data_type":"text","required":false},
|
|
56
|
+
"analysis_summary": {"data_type":"textarea","required":false},
|
|
57
|
+
"case_analysis_id": {"data_type":"text","required":false},
|
|
58
|
+
"confidence_score": {"data_type":"number","required":false}
|
|
59
|
+
}'::jsonb,
|
|
60
|
+
true
|
|
61
|
+
)
|
|
62
|
+
where kind = 'message' and slug in ('support_reply', 'community_reply');
|
|
63
|
+
|
|
64
|
+
-- Restamp existing message records — design_schema/validation_schema are
|
|
65
|
+
-- snapshotted onto each record at creation, so the type-level update alone
|
|
66
|
+
-- leaves historical rows still stripping the new fields on read.
|
|
67
|
+
update public.messages m
|
|
68
|
+
set design_schema = t.design_schema,
|
|
69
|
+
validation_schema = t.validation_schema
|
|
70
|
+
from public.types t
|
|
71
|
+
where m.type_id = t.id
|
|
72
|
+
and t.kind = 'message'
|
|
73
|
+
and t.slug in ('support_reply', 'community_reply');
|
|
74
|
+
-- CIL[END stable_id="~/.framework/migrations/051_message_agent_fields.sql:message_agent_fields:file"]
|