spine-framework 0.1.61 → 0.2.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/.framework/cli/commands/create-app.ts +1 -1
- package/.framework/cli/commands/dev.ts +215 -33
- package/.framework/cli/index.ts +37 -63
- package/.framework/functions/_shared/app-manifest.ts +8 -15
- package/.framework/functions/_shared/db.ts +11 -15
- package/.framework/functions/_shared/index.ts +0 -9
- package/.framework/functions/_shared/principal.ts +4 -62
- package/.framework/functions/_shared/resolve-ids.ts +6 -6
- package/.framework/functions/_shared/webhook-registry.ts +1 -1
- package/.framework/functions/admin-funnel.ts +104 -0
- package/.framework/functions/admin-install-funnel.ts +225 -0
- package/.framework/functions/admin-signals.ts +241 -0
- package/.framework/migrations/001_schema.sql +406 -0
- package/.framework/migrations/002_rls_and_functions.sql +710 -0
- package/.framework/migrations/003_system_data.sql +520 -0
- package/.framework/migrations/004_enhancements.sql +43 -0
- package/.framework/public/_redirects +3 -0
- package/.framework/public/spine-logo.jpg +0 -0
- package/.framework/public/spine-logo.svg +3 -0
- package/{scripts → .framework/scripts}/assemble-frontend.sh +1 -1
- package/{scripts → .framework/scripts}/assemble-functions.sh +1 -1
- package/{scripts → .framework/scripts}/assemble.sh +2 -8
- package/{scripts → .framework/scripts}/check-core-integrity.sh +0 -0
- package/.framework/seeds/link_types/account_cli_instances.json +9 -0
- package/.framework/seeds/types/funnel_signal_use.json +98 -0
- package/.framework/seeds/types/spine_instance.json +109 -0
- package/.framework/src/App.tsx +6 -4
- package/.framework/src/components/ui/accordion.tsx +1 -1
- package/.framework/src/components/ui/alert-dialog.tsx +1 -1
- package/.framework/src/components/ui/aspect-ratio.tsx +1 -1
- package/.framework/src/components/ui/avatar.tsx +1 -1
- package/.framework/src/components/ui/badge.tsx +2 -2
- package/.framework/src/components/ui/breadcrumb.tsx +2 -2
- package/.framework/src/components/ui/button-group.tsx +2 -2
- package/.framework/src/components/ui/button.tsx +2 -2
- package/.framework/src/components/ui/chart.tsx +6 -1
- package/.framework/src/components/ui/checkbox.tsx +1 -1
- package/.framework/src/components/ui/collapsible.tsx +1 -1
- package/.framework/src/components/ui/context-menu.tsx +1 -1
- package/.framework/src/components/ui/dialog.tsx +1 -1
- package/.framework/src/components/ui/direction.tsx +17 -1
- package/.framework/src/components/ui/dropdown-menu.tsx +1 -1
- package/.framework/src/components/ui/hover-card.tsx +1 -1
- package/.framework/src/components/ui/item.tsx +2 -2
- package/.framework/src/components/ui/label.tsx +1 -1
- package/.framework/src/components/ui/menubar.tsx +1 -1
- package/.framework/src/components/ui/navigation-menu.tsx +1 -1
- package/.framework/src/components/ui/popover.tsx +1 -1
- package/.framework/src/components/ui/progress.tsx +1 -1
- package/.framework/src/components/ui/radio-group.tsx +1 -1
- package/.framework/src/components/ui/scroll-area.tsx +1 -1
- package/.framework/src/components/ui/select.tsx +1 -1
- package/.framework/src/components/ui/separator.tsx +1 -1
- package/.framework/src/components/ui/sheet.tsx +1 -1
- package/.framework/src/components/ui/sidebar.tsx +6 -6
- package/.framework/src/components/ui/slider.tsx +1 -1
- package/.framework/src/components/ui/switch.tsx +1 -1
- package/.framework/src/components/ui/tabs.tsx +1 -1
- package/.framework/src/components/ui/toggle-group.tsx +1 -1
- package/.framework/src/components/ui/toggle.tsx +1 -1
- package/.framework/src/components/ui/tooltip.tsx +1 -1
- package/.framework/src/pages/auth/LoginPage.tsx +10 -9
- package/LICENSE.md +193 -0
- package/README.md +254 -0
- package/custom/.devin/skills/install-app/SKILL.md +39 -0
- package/custom/.devin/workflows/app-install.yaml +83 -0
- package/custom/README.md +79 -0
- package/docs/APPS.md +232 -0
- package/docs/ARCHITECTURE.md +246 -0
- package/docs/INSTALL.md +155 -0
- package/docs/README.md +170 -0
- package/docs/design-schema-spec.md +1837 -0
- package/docs/dev-guides/01-create-an-app.md +183 -0
- package/docs/dev-guides/02-create-a-function.md +178 -0
- package/docs/dev-guides/03-create-a-component.md +178 -0
- package/docs/dev-guides/04-webhook-handlers.md +129 -0
- package/docs/dev-guides/05-testing.md +168 -0
- package/docs/dev-guides/README.md +40 -0
- package/docs/npm-packages-plan.md +288 -0
- package/docs/spine-core--api-reference.md +822 -0
- package/package.json +78 -144
- package/.framework/cli/bin.cjs +0 -14
- package/.framework/cli/commands/init.ts +0 -186
- package/.framework/cli/commands/install-app.ts +0 -565
- package/.framework/cli/commands/migrate.ts +0 -139
- package/.framework/cli/commands/status.ts +0 -197
- package/.framework/cli/commands/uninstall-app.ts +0 -166
- package/.framework/cli/welcome.cjs +0 -45
- package/.framework/docs/STABILITY.md +0 -52
- package/.framework/docs/examples/custom-app/README.md +0 -77
- package/.framework/docs/examples/custom-function/README.md +0 -27
- package/.framework/docs/examples/custom-function/handler.ts +0 -48
- package/.framework/docs/examples/custom-webhook/README.md +0 -68
- package/.framework/migrations/000_foundation.sql +0 -1266
- package/.framework/migrations/001_seed.sql +0 -163
- package/.framework/migrations/002_seed_constraints.sql +0 -19
- package/.framework/migrations/003_auth_user_trigger.sql +0 -67
- package/.framework/src/pages/auth/RegisterPage.tsx +0 -163
- package/STRUCTURE.md +0 -150
- package/bin/spine-framework.cjs +0 -62
- package/bin/welcome.cjs +0 -45
- package/bin/ws-shim.cjs +0 -8
- package/bin/ws-shim.ts +0 -10
- package/config/components.json +0 -25
- package/config/deno.lock +0 -108
- package/config/package-lock.json +0 -17183
- package/config/postcss.config.cjs +0 -10
- package/config/tailwind.config.cjs +0 -78
- package/config/tsconfig.build.json +0 -32
- package/config/tsconfig.cli.json +0 -18
- package/config/tsconfig.json +0 -41
- package/config/tsconfig.node.json +0 -17
- package/config/tsconfig.node.tsbuildinfo +0 -1
- package/config/tsconfig.tsbuildinfo +0 -1
- package/config/typedoc.json +0 -16
- package/config/vite.config.d.ts +0 -2
- package/config/vite.config.ts +0 -72
- package/dist/cli/commands/agents.d.ts +0 -39
- package/dist/cli/commands/agents.d.ts.map +0 -1
- package/dist/cli/commands/auth.d.ts +0 -36
- package/dist/cli/commands/auth.d.ts.map +0 -1
- package/dist/cli/commands/create-app.d.ts +0 -23
- package/dist/cli/commands/create-app.d.ts.map +0 -1
- package/dist/cli/commands/dev.d.ts +0 -24
- package/dist/cli/commands/dev.d.ts.map +0 -1
- package/dist/cli/commands/doctor.d.ts +0 -42
- package/dist/cli/commands/doctor.d.ts.map +0 -1
- package/dist/cli/commands/generate.d.ts +0 -36
- package/dist/cli/commands/generate.d.ts.map +0 -1
- package/dist/cli/commands/init.d.ts +0 -20
- package/dist/cli/commands/init.d.ts.map +0 -1
- package/dist/cli/commands/install-app.d.ts +0 -30
- package/dist/cli/commands/install-app.d.ts.map +0 -1
- package/dist/cli/commands/items.d.ts +0 -45
- package/dist/cli/commands/items.d.ts.map +0 -1
- package/dist/cli/commands/migrate.d.ts +0 -21
- package/dist/cli/commands/migrate.d.ts.map +0 -1
- package/dist/cli/commands/migrations.d.ts +0 -41
- package/dist/cli/commands/migrations.d.ts.map +0 -1
- package/dist/cli/commands/pipelines.d.ts +0 -40
- package/dist/cli/commands/pipelines.d.ts.map +0 -1
- package/dist/cli/commands/status.d.ts +0 -23
- package/dist/cli/commands/status.d.ts.map +0 -1
- package/dist/cli/commands/system.d.ts +0 -29
- package/dist/cli/commands/system.d.ts.map +0 -1
- package/dist/cli/commands/test.d.ts +0 -46
- package/dist/cli/commands/test.d.ts.map +0 -1
- package/dist/cli/commands/uninstall-app.d.ts +0 -23
- package/dist/cli/commands/uninstall-app.d.ts.map +0 -1
- package/dist/cli/context.d.ts +0 -88
- package/dist/cli/context.d.ts.map +0 -1
- package/dist/cli/env-loader.d.ts +0 -14
- package/dist/cli/env-loader.d.ts.map +0 -1
- package/dist/cli/index.d.ts +0 -41
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/functions/_shared/agent-runner.d.ts +0 -156
- package/dist/functions/_shared/agent-runner.d.ts.map +0 -1
- package/dist/functions/_shared/app-manifest.d.ts +0 -68
- package/dist/functions/_shared/app-manifest.d.ts.map +0 -1
- package/dist/functions/_shared/audit.d.ts +0 -91
- package/dist/functions/_shared/audit.d.ts.map +0 -1
- package/dist/functions/_shared/db.d.ts +0 -125
- package/dist/functions/_shared/db.d.ts.map +0 -1
- package/dist/functions/_shared/index.d.ts +0 -299
- package/dist/functions/_shared/index.d.ts.map +0 -1
- package/dist/functions/_shared/middleware.d.ts +0 -315
- package/dist/functions/_shared/middleware.d.ts.map +0 -1
- package/dist/functions/_shared/permissions.d.ts +0 -626
- package/dist/functions/_shared/permissions.d.ts.map +0 -1
- package/dist/functions/_shared/pipeline-runner.d.ts +0 -124
- package/dist/functions/_shared/pipeline-runner.d.ts.map +0 -1
- package/dist/functions/_shared/principal.d.ts +0 -284
- package/dist/functions/_shared/principal.d.ts.map +0 -1
- package/dist/functions/_shared/resolve-ids.d.ts +0 -10
- package/dist/functions/_shared/resolve-ids.d.ts.map +0 -1
- package/dist/functions/_shared/schema-utils.d.ts +0 -181
- package/dist/functions/_shared/schema-utils.d.ts.map +0 -1
- package/dist/functions/_shared/testing.d.ts +0 -172
- package/dist/functions/_shared/testing.d.ts.map +0 -1
- package/dist/functions/_shared/trigger-engine.d.ts +0 -140
- package/dist/functions/_shared/trigger-engine.d.ts.map +0 -1
- package/dist/functions/_shared/webhook-registration.d.ts +0 -81
- package/dist/functions/_shared/webhook-registration.d.ts.map +0 -1
- package/dist/functions/_shared/webhook-registry.d.ts +0 -57
- package/dist/functions/_shared/webhook-registry.d.ts.map +0 -1
- package/dist/functions/account-nodes.d.ts +0 -48
- package/dist/functions/account-nodes.d.ts.map +0 -1
- package/dist/functions/admin-data.d.ts +0 -178
- package/dist/functions/admin-data.d.ts.map +0 -1
- package/dist/functions/ai-agents.d.ts +0 -125
- package/dist/functions/ai-agents.d.ts.map +0 -1
- package/dist/functions/api-keys.d.ts +0 -140
- package/dist/functions/api-keys.d.ts.map +0 -1
- package/dist/functions/apps.d.ts +0 -163
- package/dist/functions/apps.d.ts.map +0 -1
- package/dist/functions/auth.d.ts +0 -74
- package/dist/functions/auth.d.ts.map +0 -1
- package/dist/functions/debug-auth.d.ts +0 -33
- package/dist/functions/debug-auth.d.ts.map +0 -1
- package/dist/functions/embeddings.d.ts +0 -205
- package/dist/functions/embeddings.d.ts.map +0 -1
- package/dist/functions/integration-routes.d.ts +0 -45
- package/dist/functions/integration-routes.d.ts.map +0 -1
- package/dist/functions/integrations.d.ts +0 -124
- package/dist/functions/integrations.d.ts.map +0 -1
- package/dist/functions/item-progress.d.ts +0 -41
- package/dist/functions/item-progress.d.ts.map +0 -1
- package/dist/functions/logs.d.ts +0 -162
- package/dist/functions/logs.d.ts.map +0 -1
- package/dist/functions/observability.d.ts +0 -123
- package/dist/functions/observability.d.ts.map +0 -1
- package/dist/functions/pipeline-executions.d.ts +0 -190
- package/dist/functions/pipeline-executions.d.ts.map +0 -1
- package/dist/functions/pipelines.d.ts +0 -171
- package/dist/functions/pipelines.d.ts.map +0 -1
- package/dist/functions/prompt-configs.d.ts +0 -125
- package/dist/functions/prompt-configs.d.ts.map +0 -1
- package/dist/functions/roles.d.ts +0 -118
- package/dist/functions/roles.d.ts.map +0 -1
- package/dist/functions/system-cron.d.ts +0 -65
- package/dist/functions/system-cron.d.ts.map +0 -1
- package/dist/functions/system.d.ts +0 -29
- package/dist/functions/system.d.ts.map +0 -1
- package/dist/functions/tests.d.ts +0 -28
- package/dist/functions/tests.d.ts.map +0 -1
- package/dist/functions/timers.d.ts +0 -139
- package/dist/functions/timers.d.ts.map +0 -1
- package/dist/functions/triggers.d.ts +0 -203
- package/dist/functions/triggers.d.ts.map +0 -1
- package/dist/functions/types.d.ts +0 -151
- package/dist/functions/types.d.ts.map +0 -1
- package/dist/src/types/types.d.ts +0 -364
- package/dist/src/types/types.d.ts.map +0 -1
- package/index.html +0 -13
- package/netlify.toml +0 -36
- package/package-project.json +0 -64
- 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/load-test-app-install.ts +0 -484
- package/scripts/netlify-dev-wrapper.sh +0 -22
- package/vitest.config.ts +0 -45
- /package/{scripts → .framework/scripts}/app-install-cli.ts +0 -0
- /package/{scripts → .framework/scripts}/boundary-check.sh +0 -0
- /package/{scripts → .framework/scripts}/build-manifest.sh +0 -0
- /package/{scripts → .framework/scripts}/verify-integrity.sh +0 -0
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
-- =============================================================================
|
|
2
|
-
-- 001_seed.sql
|
|
3
|
-
-- Spine Framework — Bare minimum bootstrap data for a fresh install
|
|
4
|
-
-- Generated from live production DB audit: May 28, 2026
|
|
5
|
-
-- =============================================================================
|
|
6
|
-
-- Run AFTER 000_foundation.sql.
|
|
7
|
-
--
|
|
8
|
-
-- This file contains ONLY what is required for Spine to boot and for a
|
|
9
|
-
-- system_admin to log in and interact with the framework. Nothing more.
|
|
10
|
-
--
|
|
11
|
-
-- What requires seeding before the app can function:
|
|
12
|
-
-- 1. system_admin role — people.role_id FK target
|
|
13
|
-
-- 2. spine-core app — required by runtime; people/accounts ref app_id
|
|
14
|
-
-- 3. account type — accounts.type_id is NOT NULL
|
|
15
|
-
-- 4. person type — people.type_id is NOT NULL
|
|
16
|
-
-- 5. root system account — people.account_id is NOT NULL; the bootstrap
|
|
17
|
-
-- system_admin must belong to an account
|
|
18
|
-
--
|
|
19
|
-
-- Everything else (additional roles, app-specific types, tenant accounts,
|
|
20
|
-
-- app-owned link types) belongs in app seed files or is created via the admin UI.
|
|
21
|
-
-- =============================================================================
|
|
22
|
-
|
|
23
|
-
-- ---------------------------------------------------------------------------
|
|
24
|
-
-- 1. System Role
|
|
25
|
-
-- ---------------------------------------------------------------------------
|
|
26
|
-
INSERT INTO public.roles (slug, name, description, permissions, is_system, is_active, is_protected)
|
|
27
|
-
VALUES (
|
|
28
|
-
'system_admin',
|
|
29
|
-
'System Admin',
|
|
30
|
-
'Full system access — can manage all accounts, types, and system configuration',
|
|
31
|
-
'["*"]'::jsonb,
|
|
32
|
-
true,
|
|
33
|
-
true,
|
|
34
|
-
true
|
|
35
|
-
)
|
|
36
|
-
ON CONFLICT DO NOTHING;
|
|
37
|
-
|
|
38
|
-
-- ---------------------------------------------------------------------------
|
|
39
|
-
-- 1b. Core Roles
|
|
40
|
-
-- These are common roles used by apps but defined at core level
|
|
41
|
-
-- ---------------------------------------------------------------------------
|
|
42
|
-
INSERT INTO public.roles (slug, name, description, permissions, is_system, is_active, is_protected)
|
|
43
|
-
VALUES (
|
|
44
|
-
'member',
|
|
45
|
-
'Member',
|
|
46
|
-
'Standard member with read access to platform features',
|
|
47
|
-
'["*"]'::jsonb,
|
|
48
|
-
false,
|
|
49
|
-
true,
|
|
50
|
-
false
|
|
51
|
-
), (
|
|
52
|
-
'support',
|
|
53
|
-
'Support',
|
|
54
|
-
'Support agent with access to CRM, tickets, and customer data',
|
|
55
|
-
'["*"]'::jsonb,
|
|
56
|
-
false,
|
|
57
|
-
true,
|
|
58
|
-
false
|
|
59
|
-
)
|
|
60
|
-
ON CONFLICT DO NOTHING;
|
|
61
|
-
|
|
62
|
-
-- ---------------------------------------------------------------------------
|
|
63
|
-
-- 2. Spine Core App
|
|
64
|
-
-- ---------------------------------------------------------------------------
|
|
65
|
-
INSERT INTO public.apps (slug, name, description, version, app_type, source, is_active, is_system, min_role, config, nav_items, route_prefix, renderer, integration_deps, metadata)
|
|
66
|
-
VALUES (
|
|
67
|
-
'spine-core',
|
|
68
|
-
'Spine Core',
|
|
69
|
-
'Core Spine runtime — provides accounts, people, items, threads, messages, links, attachments, watchers',
|
|
70
|
-
'1.0.0',
|
|
71
|
-
'system',
|
|
72
|
-
'builtin',
|
|
73
|
-
true,
|
|
74
|
-
true,
|
|
75
|
-
NULL,
|
|
76
|
-
'{}'::jsonb,
|
|
77
|
-
'[]'::jsonb,
|
|
78
|
-
NULL,
|
|
79
|
-
'none',
|
|
80
|
-
'[]'::jsonb,
|
|
81
|
-
'{}'::jsonb
|
|
82
|
-
)
|
|
83
|
-
ON CONFLICT (slug) DO NOTHING;
|
|
84
|
-
|
|
85
|
-
-- ---------------------------------------------------------------------------
|
|
86
|
-
-- 3. Core Types
|
|
87
|
-
-- accounts.type_id and people.type_id are both NOT NULL, so these must exist
|
|
88
|
-
-- before any account or person can be created.
|
|
89
|
-
-- ---------------------------------------------------------------------------
|
|
90
|
-
INSERT INTO public.types (app_id, kind, slug, name, description, ownership, is_active, design_schema, validation_schema)
|
|
91
|
-
VALUES
|
|
92
|
-
((SELECT id FROM public.apps WHERE slug = 'spine-core'), 'account', 'account', 'Account', 'Organization or tenant account', 'pack', true,
|
|
93
|
-
'{"views":{"default_list":{"type":"list","label":"Accounts","fields":{"slug":{"sortable":true,"display_type":"text"},"is_active":{"sortable":true,"display_type":"badge"},"display_name":{"sortable":true,"display_type":"text"}},"display":"table"},"default_detail":{"type":"detail","label":"Account","sections":[{"title":"Overview","fields":["slug","display_name","description","is_active"]},{"title":"Metadata","fields":["created_at","updated_at"]}]}},"fields":{"slug":{"label":"Slug","system":true,"required":true,"data_type":"text"},"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"updated_at":{"label":"Updated","system":true,"readonly":true,"required":false,"data_type":"datetime"},"description":{"label":"Description","system":true,"required":false,"data_type":"textarea"},"display_name":{"label":"Display Name","system":true,"required":true,"data_type":"text"}},"record_permissions":{"member":["create","read","update"],"support":["create","read","update"],"system_admin":["create","read","update","delete"]}}'::jsonb,
|
|
94
|
-
'{"fields":{"slug":{"data_type":"text","required":true},"is_active":{"data_type":"boolean","required":true},"created_at":{"data_type":"datetime","required":false},"updated_at":{"data_type":"datetime","required":false},"description":{"data_type":"textarea","required":false},"display_name":{"data_type":"text","required":true}}}'::jsonb),
|
|
95
|
-
((SELECT id FROM public.apps WHERE slug = 'spine-core'), 'person', 'person', 'Person', 'User or contact person', 'pack', true,
|
|
96
|
-
'{"views":{"default_list":{"type":"list","label":"People","fields":{"email":{"sortable":true,"display_type":"text"},"status":{"sortable":true,"display_type":"badge"},"full_name":{"sortable":true,"display_type":"text"},"is_active":{"sortable":true,"display_type":"badge"}},"display":"table"},"default_detail":{"type":"detail","label":"Person","sections":[{"title":"Profile","fields":["full_name","email","phone","avatar_url"]},{"title":"Status","fields":["status","is_active"]},{"title":"Metadata","fields":["created_at","updated_at"]}]}},"fields":{"email":{"label":"Email","system":true,"required":true,"data_type":"email"},"phone":{"label":"Phone","system":true,"required":false,"data_type":"phone"},"status":{"label":"Status","system":true,"required":true,"data_type":"text"},"full_name":{"label":"Full Name","system":true,"required":true,"data_type":"text"},"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"avatar_url":{"label":"Avatar URL","system":true,"required":false,"data_type":"url"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"updated_at":{"label":"Updated","system":true,"readonly":true,"required":false,"data_type":"datetime"}},"record_permissions":{"member":["create","read","update"],"support":["create","read","update"],"system_admin":["create","read","update","delete"]}}'::jsonb,
|
|
97
|
-
'{"fields":{"email":{"data_type":"email","required":true},"phone":{"data_type":"phone","required":false},"status":{"data_type":"text","required":true},"full_name":{"data_type":"text","required":true},"is_active":{"data_type":"boolean","required":true},"avatar_url":{"data_type":"url","required":false},"created_at":{"data_type":"datetime","required":false},"updated_at":{"data_type":"datetime","required":false}}}'::jsonb)
|
|
98
|
-
ON CONFLICT (app_id, kind, slug) DO UPDATE
|
|
99
|
-
SET design_schema = EXCLUDED.design_schema,
|
|
100
|
-
validation_schema = EXCLUDED.validation_schema,
|
|
101
|
-
name = EXCLUDED.name,
|
|
102
|
-
description = EXCLUDED.description;
|
|
103
|
-
|
|
104
|
-
-- ---------------------------------------------------------------------------
|
|
105
|
-
-- 4. Root System Account
|
|
106
|
-
-- The first system_admin person must belong to an account. This is the
|
|
107
|
-
-- bootstrap account for the Spine system itself.
|
|
108
|
-
-- NOTE: The system_admin person record is NOT seeded here — it is created
|
|
109
|
-
-- via Supabase Auth invite + the onboarding flow, which stamps type_id and
|
|
110
|
-
-- role_id onto the resulting people row.
|
|
111
|
-
-- ---------------------------------------------------------------------------
|
|
112
|
-
INSERT INTO public.accounts (type_id, slug, display_name, description, is_active, design_schema, validation_schema)
|
|
113
|
-
VALUES (
|
|
114
|
-
(SELECT id FROM public.types WHERE kind = 'account' AND slug = 'account'),
|
|
115
|
-
'spine-system',
|
|
116
|
-
'Spine System',
|
|
117
|
-
'Root system account for the Spine framework',
|
|
118
|
-
true,
|
|
119
|
-
(SELECT design_schema FROM public.types WHERE kind = 'account' AND slug = 'account'),
|
|
120
|
-
'{}'::jsonb
|
|
121
|
-
)
|
|
122
|
-
ON CONFLICT (slug) DO UPDATE
|
|
123
|
-
SET design_schema = EXCLUDED.design_schema,
|
|
124
|
-
validation_schema = EXCLUDED.validation_schema;
|
|
125
|
-
|
|
126
|
-
-- ---------------------------------------------------------------------------
|
|
127
|
-
-- 5. Core Spine Types
|
|
128
|
-
-- These types are owned by spine-core and provide design_schema for all
|
|
129
|
-
-- built-in framework entities. Apps build on top of these.
|
|
130
|
-
-- ---------------------------------------------------------------------------
|
|
131
|
-
INSERT INTO public.types (app_id, kind, slug, name, description, ownership, is_active, design_schema, validation_schema)
|
|
132
|
-
SELECT
|
|
133
|
-
a.id,
|
|
134
|
-
t.kind,
|
|
135
|
-
t.slug,
|
|
136
|
-
t.name,
|
|
137
|
-
t.description,
|
|
138
|
-
t.ownership,
|
|
139
|
-
true,
|
|
140
|
-
t.design_schema,
|
|
141
|
-
t.validation_schema
|
|
142
|
-
FROM (VALUES
|
|
143
|
-
('alert', 'threshold_alert', 'Threshold Alert', 'System threshold alert configuration for observability', 'tenant', '{"scope":"account","views":{"default_list":{"type":"list","label":"Threshold Alerts","fields":{"title":{"sortable":true,"display_type":"text"},"metric":{"sortable":true,"display_type":"badge"},"status":{"sortable":true,"display_type":"badge"},"is_active":{"sortable":true,"display_type":"badge"}},"display":"table","default_sort":{"field":"created_at","direction":"desc"}},"default_detail":{"type":"detail","label":"Threshold Alert","sections":[{"title":"Alert Config","fields":["title","description","metric","operator","value","window_minutes","pipeline_id"]},{"title":"Status","fields":["status","is_active"]},{"title":"Metadata","fields":["created_at","updated_at"]}]}},"fields":{"title":{"label":"Title","system":true,"required":true,"data_type":"text"},"value":{"label":"Value","system":false,"required":true,"data_type":"number"},"metric":{"label":"Metric","system":false,"required":true,"data_type":"text"},"status":{"label":"Status","system":true,"required":false,"data_type":"text"},"operator":{"label":"Operator","system":false,"required":true,"data_type":"text"},"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"updated_at":{"label":"Updated","system":true,"readonly":true,"required":false,"data_type":"datetime"},"description":{"label":"Description","system":true,"required":false,"data_type":"textarea"},"pipeline_id":{"label":"Pipeline","system":false,"required":false,"data_type":"text"},"window_minutes":{"label":"Window (minutes)","system":false,"required":true,"data_type":"number"}},"record_permissions":{"support":["create","read","update"],"system_admin":["create","read","update","delete"]}}'::jsonb, '{"fields":{"title":{"data_type":"text","required":true},"value":{"data_type":"number","required":true},"metric":{"data_type":"text","required":true},"status":{"data_type":"text","required":false},"operator":{"data_type":"text","required":true},"is_active":{"data_type":"boolean","required":true},"created_at":{"data_type":"datetime","required":false},"updated_at":{"data_type":"datetime","required":false},"description":{"data_type":"textarea","required":false},"pipeline_id":{"data_type":"text","required":false},"window_minutes":{"data_type":"number","required":true}}}'::jsonb),
|
|
144
|
-
('attachment', 'attachment', 'Attachment', 'File attachment or document', 'pack', '{"scope":"account","views":{"default_list":{"type":"list","label":"Attachments","fields":{"filename":{"sortable":true,"display_type":"text"},"file_size":{"sortable":true,"display_type":"number"},"mime_type":{"sortable":true,"display_type":"badge"},"storage_provider":{"sortable":true,"display_type":"badge"}},"display":"table"},"default_detail":{"type":"detail","label":"Attachment","sections":[{"title":"File Info","fields":["filename","file_size","mime_type","storage_path","storage_provider"]},{"title":"Metadata","fields":["is_active","created_at"]}]}},"fields":{"filename":{"label":"Filename","system":true,"required":true,"data_type":"text"},"file_size":{"label":"File Size","system":true,"required":false,"data_type":"number"},"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"mime_type":{"label":"MIME Type","system":true,"required":false,"data_type":"text"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"storage_path":{"label":"Storage Path","system":true,"required":false,"data_type":"text"},"storage_provider":{"label":"Storage Provider","system":true,"required":false,"data_type":"text"}},"record_permissions":{"member":["read"],"support":["create","read","update"],"system_admin":["create","read","update","delete"]}}'::jsonb, '{"fields":{"filename":{"data_type":"text","required":true},"file_size":{"data_type":"number","required":false},"is_active":{"data_type":"boolean","required":true},"mime_type":{"data_type":"text","required":false},"created_at":{"data_type":"datetime","required":false},"storage_path":{"data_type":"text","required":false},"storage_provider":{"data_type":"text","required":false}}}'::jsonb),
|
|
145
|
-
('item', 'item', 'Item', 'Generic work item or record', 'pack', '{"scope":"account","views":{"default_list":{"type":"list","label":"Items","fields":{"title":{"sortable":true,"display_type":"text"},"status":{"sortable":true,"display_type":"badge"},"is_active":{"sortable":true,"display_type":"badge"}},"display":"table"},"default_detail":{"type":"detail","label":"Item","sections":[{"title":"Details","fields":["title","description","status","is_active"]},{"title":"Metadata","fields":["created_at","updated_at"]}]}},"fields":{"title":{"label":"Title","system":true,"required":true,"data_type":"text"},"status":{"label":"Status","system":true,"required":true,"data_type":"text"},"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"updated_at":{"label":"Updated","system":true,"readonly":true,"required":false,"data_type":"datetime"},"description":{"label":"Description","system":true,"required":false,"data_type":"textarea"}},"record_permissions":{"member":["create","read","update"],"support":["create","read","update"],"system_admin":["create","read","update","delete"]}}'::jsonb, '{"fields":{"title":{"data_type":"text","required":true},"status":{"data_type":"text","required":true},"is_active":{"data_type":"boolean","required":true},"created_at":{"data_type":"datetime","required":false},"updated_at":{"data_type":"datetime","required":false},"description":{"data_type":"textarea","required":false}}}'::jsonb),
|
|
146
|
-
('item', 'activity_log', 'Activity Log', 'Audit log for funnel intelligence activities', 'tenant', '{"scope":"platform","views":{"default_list":{"type":"list","label":"Activity Logs","fields":{"action":{"sortable":true,"display_type":"badge"},"account_id":{"sortable":true,"display_type":"text"},"created_at":{"sortable":true,"display_type":"timestamp"}},"display":"table","default_sort":{"field":"created_at","direction":"desc"}}},"fields":{"action":{"label":"Action","options":["lead_score_updated","lifecycle_stage_changed","signal_processed","task_created"],"required":true,"data_type":"text"},"new_score":{"label":"New Score","required":false,"data_type":"integer"},"new_stage":{"label":"New Stage","required":false,"data_type":"text"},"person_id":{"label":"Person ID","required":false,"data_type":"uuid"},"account_id":{"label":"Account ID","required":false,"data_type":"uuid"},"score_delta":{"label":"Score Delta","required":false,"data_type":"integer"},"signal_type":{"label":"Signal Type","required":false,"data_type":"text"}},"record_permissions":{"member":["read"],"support":["create","read","update"],"system_admin":["create","read","update","delete"]}}'::jsonb, '{"fields":{"action":{"data_type":"text","required":true,"options":["lead_score_updated","lifecycle_stage_changed","signal_processed","task_created"]},"new_score":{"data_type":"integer","required":false},"new_stage":{"data_type":"text","required":false},"person_id":{"data_type":"uuid","required":false},"account_id":{"data_type":"uuid","required":false},"score_delta":{"data_type":"integer","required":false},"signal_type":{"data_type":"text","required":false}}}'::jsonb),
|
|
147
|
-
('item', 'task', 'Task', 'Task or action item for follow-up and tracking', 'tenant', '{"scope":"platform","views":{"default_list":{"type":"list","label":"Tasks","fields":{"status":{"sortable":true,"display_type":"badge"},"due_date":{"sortable":true,"display_type":"timestamp"},"priority":{"sortable":true,"display_type":"badge"},"task_type":{"sortable":true,"display_type":"badge"}},"display":"table","default_sort":{"field":"created_at","direction":"desc"}},"default_detail":{"type":"detail","label":"Task","sections":[{"title":"Task Details","fields":["task_type","priority","description","due_date"]},{"title":"Assignment","fields":["account_id","person_id"]},{"title":"Metadata","fields":["status","created_at","updated_at"]}]}},"fields":{"due_date":{"label":"Due Date","required":false,"data_type":"datetime"},"priority":{"label":"Priority","default":"medium","options":["low","medium","high","urgent"],"required":true,"data_type":"text"},"person_id":{"label":"Person ID","required":false,"data_type":"uuid"},"task_type":{"label":"Task Type","options":["lead_review","customer_followup","support_escalation","health_check"],"required":true,"data_type":"text"},"account_id":{"label":"Account ID","required":false,"data_type":"uuid"},"description":{"label":"Description","required":true,"data_type":"textarea"}},"record_permissions":{"member":["read"],"support":["create","read","update"],"system_admin":["create","read","update","delete"]}}'::jsonb, '{"fields":{"due_date":{"data_type":"datetime","required":false},"priority":{"data_type":"text","required":true,"options":["low","medium","high","urgent"]},"person_id":{"data_type":"uuid","required":false},"task_type":{"data_type":"text","required":true,"options":["lead_review","customer_followup","support_escalation","health_check"]},"account_id":{"data_type":"uuid","required":false},"description":{"data_type":"textarea","required":true}}}'::jsonb),
|
|
148
|
-
('link', 'link', 'Link', 'Relationship between entities', 'pack', '{"scope":"account","views":{"default_list":{"type":"list","label":"Links","fields":{"link_type":{"sortable":true,"display_type":"badge"},"source_type":{"sortable":true,"display_type":"text"},"target_type":{"sortable":true,"display_type":"text"}},"display":"table"},"default_detail":{"type":"detail","label":"Link","sections":[{"title":"Relationship","fields":["source_type","target_type","link_type","is_active"]},{"title":"Metadata","fields":["created_at"]}]}},"fields":{"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"link_type":{"label":"Link Type","system":true,"required":false,"data_type":"text"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"source_type":{"label":"Source Type","system":true,"required":true,"data_type":"text"},"target_type":{"label":"Target Type","system":true,"required":true,"data_type":"text"}},"record_permissions":{"member":["create","read"],"support":["create","read","update"],"system_admin":["create","read","update","delete"]}}'::jsonb, '{"fields":{"is_active":{"data_type":"boolean","required":true},"link_type":{"data_type":"text","required":false},"created_at":{"data_type":"datetime","required":false},"source_type":{"data_type":"text","required":true},"target_type":{"data_type":"text","required":true}}}'::jsonb),
|
|
149
|
-
('message', 'message', 'Message', 'Individual message in a thread', 'pack', '{"scope":"platform","views":{"default_list":{"type":"list","label":"Messages","fields":{"content":{"sortable":false,"display_type":"text"},"sequence":{"sortable":true,"display_type":"number"},"direction":{"sortable":true,"display_type":"badge"}},"display":"table"},"default_detail":{"type":"detail","label":"Message","sections":[{"title":"Content","fields":["content","direction","sequence","visibility"]},{"title":"Metadata","fields":["created_at"]}]}},"fields":{"content":{"label":"Content","system":true,"required":true,"data_type":"textarea"},"sequence":{"label":"Sequence","system":true,"required":true,"data_type":"number"},"direction":{"label":"Direction","system":true,"required":true,"data_type":"text"},"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"visibility":{"label":"Visibility","system":true,"required":false,"data_type":"text"},"message_type":{"label":"Message Type","system":true,"required":false,"data_type":"text"}},"record_permissions":{"member":["read","create"],"support":["read","create","update","delete"],"system_admin":["read","create","update","delete"]}}'::jsonb, '{"fields":{"content":{"data_type":"textarea","required":true},"sequence":{"data_type":"number","required":true},"direction":{"data_type":"text","required":true},"is_active":{"data_type":"boolean","required":true},"created_at":{"data_type":"datetime","required":false},"visibility":{"data_type":"text","required":false},"message_type":{"data_type":"text","required":false}}}'::jsonb),
|
|
150
|
-
('progress', 'course_lesson_progress', 'Course Lesson Progress', 'Tracks per-student progress through a course lesson', 'pack', '{"scope":"account","views":{"default_list":{"type":"list","label":"Progress Records","fields":{"score":{"sortable":true,"display_type":"number"},"title":{"sortable":true,"display_type":"text"},"status":{"sortable":true,"display_type":"badge"},"updated_at":{"sortable":true,"display_type":"timestamp"}},"display":"table"},"default_detail":{"type":"detail","label":"Progress Record","sections":[{"title":"Overview","fields":["title","description","status","score"]},{"title":"Activity","fields":["attempts","time_spent","last_position","started_at","completed_at"]},{"title":"Metadata","fields":["is_active","created_at","updated_at"]}]}},"fields":{"score":{"label":"Score","system":true,"required":false,"data_type":"number","validation":{"max":100,"min":0,"integer":true}},"title":{"label":"Title","system":true,"readonly":true,"required":false,"data_type":"text"},"status":{"label":"Status","system":true,"options":["not_started","in_progress","completed"],"required":true,"data_type":"select"},"attempts":{"label":"Attempts","required":false,"data_type":"number","validation":{"min":0,"integer":true}},"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"started_at":{"label":"Started At","readonly":true,"required":false,"data_type":"datetime"},"time_spent":{"label":"Time Spent (s)","required":false,"data_type":"number","validation":{"min":0,"integer":true}},"updated_at":{"label":"Updated","system":true,"readonly":true,"required":false,"data_type":"datetime"},"description":{"label":"Description","system":true,"readonly":true,"required":false,"data_type":"textarea"},"completed_at":{"label":"Completed At","readonly":true,"required":false,"data_type":"datetime"},"last_position":{"label":"Last Position (s)","required":false,"data_type":"number","validation":{"min":0,"integer":true}}},"pipeline":["not_started","in_progress","completed"],"record_permissions":{"member":["create","read","update"],"support":["create","read","update"],"system_admin":["create","read","update","delete"]}}'::jsonb, '{"fields":{"score":{"data_type":"number","required":false,"max":100,"min":0,"integer":true},"title":{"data_type":"text","required":false},"status":{"data_type":"select","required":true,"options":["not_started","in_progress","completed"]},"attempts":{"data_type":"number","required":false,"min":0,"integer":true},"is_active":{"data_type":"boolean","required":true},"created_at":{"data_type":"datetime","required":false},"started_at":{"data_type":"datetime","required":false},"time_spent":{"data_type":"number","required":false,"min":0,"integer":true},"updated_at":{"data_type":"datetime","required":false},"description":{"data_type":"textarea","required":false},"completed_at":{"data_type":"datetime","required":false},"last_position":{"data_type":"number","required":false,"min":0,"integer":true}}}'::jsonb),
|
|
151
|
-
('thread', 'thread', 'Thread', 'Conversation thread for items or entities', 'pack', '{"scope":"platform","views":{"default_list":{"type":"list","label":"Threads","fields":{"title":{"sortable":true,"display_type":"text"},"status":{"sortable":true,"display_type":"badge"},"visibility":{"sortable":true,"display_type":"badge"},"target_type":{"sortable":true,"display_type":"badge"}},"display":"table"},"default_detail":{"type":"detail","label":"Thread","sections":[{"title":"Overview","fields":["title","target_type","visibility","status","is_active"]},{"title":"Metadata","fields":["created_at","updated_at"]}]}},"fields":{"title":{"label":"Title","system":true,"required":false,"data_type":"text"},"status":{"label":"Status","system":true,"required":true,"data_type":"text"},"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"updated_at":{"label":"Updated","system":true,"readonly":true,"required":false,"data_type":"datetime"},"visibility":{"label":"Visibility","system":true,"required":true,"data_type":"text"},"target_type":{"label":"Target Type","system":true,"required":true,"data_type":"text"}},"ai_routing":{"agent_id":{"type":"string","label":"Agent ID"},"prompt_config_id":{"type":"string","label":"Prompt Config ID"}},"record_permissions":{"member":["read","create"],"support":["read","create","update","delete"],"system_admin":["read","create","update","delete"]}}'::jsonb, '{"fields":{"title":{"data_type":"text","required":false},"status":{"data_type":"text","required":true},"is_active":{"data_type":"boolean","required":true},"created_at":{"data_type":"datetime","required":false},"updated_at":{"data_type":"datetime","required":false},"visibility":{"data_type":"text","required":true},"target_type":{"data_type":"text","required":true}}}'::jsonb),
|
|
152
|
-
('watcher', 'watcher', 'Watcher', 'Entity watcher subscription', 'pack', '{"scope":"account","views":{"default_list":{"type":"list","label":"Watchers","fields":{"is_active":{"sortable":true,"display_type":"badge"},"watch_type":{"sortable":true,"display_type":"badge"},"target_type":{"sortable":true,"display_type":"text"},"notification_level":{"sortable":true,"display_type":"badge"}},"display":"table"},"default_detail":{"type":"detail","label":"Watcher","sections":[{"title":"Watch Settings","fields":["target_type","watch_type","notification_level","is_active"]},{"title":"Metadata","fields":["created_at","updated_at"]}]}},"fields":{"is_active":{"label":"Active","system":true,"required":true,"data_type":"boolean"},"created_at":{"label":"Created","system":true,"readonly":true,"required":false,"data_type":"datetime"},"updated_at":{"label":"Updated","system":true,"readonly":true,"required":false,"data_type":"datetime"},"watch_type":{"label":"Watch Type","system":true,"required":false,"data_type":"text"},"target_type":{"label":"Target Type","system":true,"required":true,"data_type":"text"},"notification_level":{"label":"Notification Level","system":true,"required":true,"data_type":"text"}},"record_permissions":{"member":["create","read","delete"],"support":["create","read","delete"],"system_admin":["create","read","update","delete"]}}'::jsonb, '{"fields":{"is_active":{"data_type":"boolean","required":true},"created_at":{"data_type":"datetime","required":false},"updated_at":{"data_type":"datetime","required":false},"watch_type":{"data_type":"text","required":false},"target_type":{"data_type":"text","required":true},"notification_level":{"data_type":"text","required":true}}}'::jsonb)
|
|
153
|
-
) AS t(kind, slug, name, description, ownership, design_schema, validation_schema)
|
|
154
|
-
CROSS JOIN (SELECT id FROM public.apps WHERE slug = 'spine-core') AS a
|
|
155
|
-
ON CONFLICT (app_id, kind, slug) DO UPDATE
|
|
156
|
-
SET design_schema = EXCLUDED.design_schema,
|
|
157
|
-
validation_schema = EXCLUDED.validation_schema,
|
|
158
|
-
name = EXCLUDED.name,
|
|
159
|
-
description = EXCLUDED.description;
|
|
160
|
-
|
|
161
|
-
-- NOTE: No link types are seeded here. All link types are app-owned.
|
|
162
|
-
-- Cortex seeds: account_signals, account_opportunities, analyzed_by, tagged_with
|
|
163
|
-
-- See custom/apps/cortex/seed/link-types.json
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
-- =============================================================================
|
|
2
|
-
-- 002_seed_constraints.sql
|
|
3
|
-
-- Adds unique constraints required for idempotent seed upserts
|
|
4
|
-
-- =============================================================================
|
|
5
|
-
|
|
6
|
-
-- link_types needs unique on (app_id, slug) for seed upserts
|
|
7
|
-
DO $$ BEGIN
|
|
8
|
-
ALTER TABLE public.link_types ADD CONSTRAINT link_types_app_id_slug_key UNIQUE (app_id, slug);
|
|
9
|
-
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
|
10
|
-
|
|
11
|
-
-- triggers needs unique on (app_id, name) for seed upserts
|
|
12
|
-
DO $$ BEGIN
|
|
13
|
-
ALTER TABLE public.triggers ADD CONSTRAINT triggers_app_id_name_key UNIQUE (app_id, name);
|
|
14
|
-
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
|
15
|
-
|
|
16
|
-
-- pipelines needs unique on (app_id, name) for seed upserts
|
|
17
|
-
DO $$ BEGIN
|
|
18
|
-
ALTER TABLE public.pipelines ADD CONSTRAINT pipelines_app_id_name_key UNIQUE (app_id, name);
|
|
19
|
-
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
-- =============================================================================
|
|
2
|
-
-- 003_auth_user_trigger.sql
|
|
3
|
-
-- Creates a people record whenever a new Supabase auth user signs up.
|
|
4
|
-
-- Run AFTER 001_seed.sql (requires spine-system account and person type).
|
|
5
|
-
--
|
|
6
|
-
-- First user ever → system_admin role (bootstrap)
|
|
7
|
-
-- Subsequent users → no role (assigned later via admin invite flow)
|
|
8
|
-
-- =============================================================================
|
|
9
|
-
|
|
10
|
-
CREATE OR REPLACE FUNCTION public.handle_new_auth_user()
|
|
11
|
-
RETURNS TRIGGER LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$
|
|
12
|
-
DECLARE
|
|
13
|
-
v_account_id uuid;
|
|
14
|
-
v_type_id uuid;
|
|
15
|
-
v_role_id uuid;
|
|
16
|
-
v_is_first boolean;
|
|
17
|
-
v_design_schema jsonb;
|
|
18
|
-
v_validation_schema jsonb;
|
|
19
|
-
BEGIN
|
|
20
|
-
SELECT id INTO v_account_id FROM public.accounts WHERE slug = 'spine-system' LIMIT 1;
|
|
21
|
-
SELECT id, design_schema, validation_schema
|
|
22
|
-
INTO v_type_id, v_design_schema, v_validation_schema
|
|
23
|
-
FROM public.types WHERE kind = 'person' AND slug = 'person' LIMIT 1;
|
|
24
|
-
|
|
25
|
-
IF v_account_id IS NULL OR v_type_id IS NULL THEN
|
|
26
|
-
RAISE WARNING 'handle_new_auth_user: spine-system account or person type not found — skipping people insert';
|
|
27
|
-
RETURN NEW;
|
|
28
|
-
END IF;
|
|
29
|
-
|
|
30
|
-
-- First person ever gets system_admin; subsequent users get no role
|
|
31
|
-
SELECT NOT EXISTS (SELECT 1 FROM public.people LIMIT 1) INTO v_is_first;
|
|
32
|
-
IF v_is_first THEN
|
|
33
|
-
SELECT id INTO v_role_id FROM public.roles WHERE slug = 'system_admin' LIMIT 1;
|
|
34
|
-
END IF;
|
|
35
|
-
|
|
36
|
-
INSERT INTO public.people (
|
|
37
|
-
id,
|
|
38
|
-
auth_uid,
|
|
39
|
-
email,
|
|
40
|
-
full_name,
|
|
41
|
-
account_id,
|
|
42
|
-
type_id,
|
|
43
|
-
role_id,
|
|
44
|
-
is_active,
|
|
45
|
-
design_schema,
|
|
46
|
-
validation_schema
|
|
47
|
-
) VALUES (
|
|
48
|
-
NEW.id,
|
|
49
|
-
NEW.id,
|
|
50
|
-
NEW.email,
|
|
51
|
-
COALESCE(NEW.raw_user_meta_data->>'full_name', split_part(NEW.email, '@', 1)),
|
|
52
|
-
v_account_id,
|
|
53
|
-
v_type_id,
|
|
54
|
-
v_role_id,
|
|
55
|
-
true,
|
|
56
|
-
v_design_schema,
|
|
57
|
-
COALESCE(v_validation_schema, '{}'::jsonb)
|
|
58
|
-
)
|
|
59
|
-
ON CONFLICT (id) DO NOTHING;
|
|
60
|
-
|
|
61
|
-
RETURN NEW;
|
|
62
|
-
END;
|
|
63
|
-
$$;
|
|
64
|
-
|
|
65
|
-
CREATE OR REPLACE TRIGGER on_auth_user_created
|
|
66
|
-
AFTER INSERT ON auth.users
|
|
67
|
-
FOR EACH ROW EXECUTE FUNCTION public.handle_new_auth_user();
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module src/pages/auth/RegisterPage
|
|
3
|
-
* @audience installer
|
|
4
|
-
* @layer frontend-page
|
|
5
|
-
* @stability stable
|
|
6
|
-
*
|
|
7
|
-
* Self-registration page. Renders a centred card with email/password/name
|
|
8
|
-
* inputs. On submit, calls Supabase signUp and navigates to /login with
|
|
9
|
-
* a confirmation message.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import React, { useState } from 'react'
|
|
13
|
-
import { Link, useNavigate } from 'react-router-dom'
|
|
14
|
-
import { useAuth } from '../../contexts/AuthContext'
|
|
15
|
-
import { LoadingSpinner } from '../../components/ui/LoadingSpinner'
|
|
16
|
-
import { supabase } from '../../lib/supabase'
|
|
17
|
-
|
|
18
|
-
export function RegisterPage() {
|
|
19
|
-
const [email, setEmail] = useState('')
|
|
20
|
-
const [password, setPassword] = useState('')
|
|
21
|
-
const [fullName, setFullName] = useState('')
|
|
22
|
-
const [error, setError] = useState('')
|
|
23
|
-
const [success, setSuccess] = useState('')
|
|
24
|
-
const [isLoading, setIsLoading] = useState(false)
|
|
25
|
-
|
|
26
|
-
const navigate = useNavigate()
|
|
27
|
-
|
|
28
|
-
const handleSubmit = async (e: React.FormEvent) => {
|
|
29
|
-
e.preventDefault()
|
|
30
|
-
setError('')
|
|
31
|
-
setSuccess('')
|
|
32
|
-
setIsLoading(true)
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const { error: signUpError } = await supabase.auth.signUp({
|
|
36
|
-
email,
|
|
37
|
-
password,
|
|
38
|
-
options: {
|
|
39
|
-
data: {
|
|
40
|
-
full_name: fullName,
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
if (signUpError) {
|
|
46
|
-
setError(signUpError.message)
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
setSuccess('Account created! Check your email for a confirmation link.')
|
|
51
|
-
setTimeout(() => navigate('/login'), 3000)
|
|
52
|
-
} catch (err: any) {
|
|
53
|
-
setError(err.message || 'Registration failed')
|
|
54
|
-
} finally {
|
|
55
|
-
setIsLoading(false)
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
<div className="min-h-screen flex items-center justify-center bg-slate-50 py-12 px-4 sm:px-6 lg:px-8">
|
|
61
|
-
<div className="max-w-md w-full space-y-8">
|
|
62
|
-
<div>
|
|
63
|
-
<div className="mx-auto h-12 w-12 flex items-center justify-center rounded-full bg-slate-900">
|
|
64
|
-
<span className="text-white font-bold text-xl">S</span>
|
|
65
|
-
</div>
|
|
66
|
-
<h2 className="mt-6 text-center text-3xl font-extrabold text-slate-900">
|
|
67
|
-
Create your account
|
|
68
|
-
</h2>
|
|
69
|
-
<p className="mt-2 text-center text-sm text-slate-600">
|
|
70
|
-
Already have an account?{' '}
|
|
71
|
-
<Link to="/login" className="font-medium text-accent-blue hover:text-accent-blue-light">
|
|
72
|
-
Sign in
|
|
73
|
-
</Link>
|
|
74
|
-
</p>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<form className="mt-8 space-y-6" onSubmit={handleSubmit}>
|
|
78
|
-
{error && (
|
|
79
|
-
<div className="rounded-md bg-red-50 p-4">
|
|
80
|
-
<div className="text-sm text-red-800">{error}</div>
|
|
81
|
-
</div>
|
|
82
|
-
)}
|
|
83
|
-
|
|
84
|
-
{success && (
|
|
85
|
-
<div className="rounded-md bg-green-50 p-4">
|
|
86
|
-
<div className="text-sm text-green-800">{success}</div>
|
|
87
|
-
</div>
|
|
88
|
-
)}
|
|
89
|
-
|
|
90
|
-
<div className="space-y-4">
|
|
91
|
-
<div>
|
|
92
|
-
<label htmlFor="fullName" className="block text-sm font-medium text-slate-700">
|
|
93
|
-
Full name
|
|
94
|
-
</label>
|
|
95
|
-
<input
|
|
96
|
-
id="fullName"
|
|
97
|
-
name="fullName"
|
|
98
|
-
type="text"
|
|
99
|
-
required
|
|
100
|
-
value={fullName}
|
|
101
|
-
onChange={(e) => setFullName(e.target.value)}
|
|
102
|
-
className="mt-1 block w-full px-3 py-2 border border-slate-300 rounded-[5px] shadow-sm placeholder-slate-400 focus:outline-none focus:ring-accent-blue focus:border-accent-blue sm:text-sm"
|
|
103
|
-
placeholder="Enter your full name"
|
|
104
|
-
/>
|
|
105
|
-
</div>
|
|
106
|
-
|
|
107
|
-
<div>
|
|
108
|
-
<label htmlFor="email" className="block text-sm font-medium text-slate-700">
|
|
109
|
-
Email address
|
|
110
|
-
</label>
|
|
111
|
-
<input
|
|
112
|
-
id="email"
|
|
113
|
-
name="email"
|
|
114
|
-
type="email"
|
|
115
|
-
autoComplete="email"
|
|
116
|
-
required
|
|
117
|
-
value={email}
|
|
118
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
119
|
-
className="mt-1 block w-full px-3 py-2 border border-slate-300 rounded-[5px] shadow-sm placeholder-slate-400 focus:outline-none focus:ring-accent-blue focus:border-accent-blue sm:text-sm"
|
|
120
|
-
placeholder="Enter your email"
|
|
121
|
-
/>
|
|
122
|
-
</div>
|
|
123
|
-
|
|
124
|
-
<div>
|
|
125
|
-
<label htmlFor="password" className="block text-sm font-medium text-slate-700">
|
|
126
|
-
Password
|
|
127
|
-
</label>
|
|
128
|
-
<input
|
|
129
|
-
id="password"
|
|
130
|
-
name="password"
|
|
131
|
-
type="password"
|
|
132
|
-
autoComplete="new-password"
|
|
133
|
-
required
|
|
134
|
-
minLength={6}
|
|
135
|
-
value={password}
|
|
136
|
-
onChange={(e) => setPassword(e.target.value)}
|
|
137
|
-
className="mt-1 block w-full px-3 py-2 border border-slate-300 rounded-[5px] shadow-sm placeholder-slate-400 focus:outline-none focus:ring-accent-blue focus:border-accent-blue sm:text-sm"
|
|
138
|
-
placeholder="Choose a password (min 6 characters)"
|
|
139
|
-
/>
|
|
140
|
-
</div>
|
|
141
|
-
</div>
|
|
142
|
-
|
|
143
|
-
<div>
|
|
144
|
-
<button
|
|
145
|
-
type="submit"
|
|
146
|
-
disabled={isLoading}
|
|
147
|
-
className="group relative w-full flex justify-center py-2 px-4 border border-transparent rounded-[5px] shadow-sm text-sm font-medium text-white bg-slate-900 hover:bg-slate-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-accent-blue disabled:opacity-50 disabled:cursor-not-allowed"
|
|
148
|
-
>
|
|
149
|
-
{isLoading ? (
|
|
150
|
-
<>
|
|
151
|
-
<LoadingSpinner size="sm" />
|
|
152
|
-
<span className="ml-2">Creating account...</span>
|
|
153
|
-
</>
|
|
154
|
-
) : (
|
|
155
|
-
'Create account'
|
|
156
|
-
)}
|
|
157
|
-
</button>
|
|
158
|
-
</div>
|
|
159
|
-
</form>
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
|
-
)
|
|
163
|
-
}
|
package/STRUCTURE.md
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
# Spine Enterprise Directory Structure
|
|
2
|
-
|
|
3
|
-
This document explains the directory layout for the Spine framework.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
my-app/
|
|
9
|
-
├── .framework/ # 🔒 CLI-managed framework code (read-only)
|
|
10
|
-
├── custom/ # ✏️ Developer workspace (your code)
|
|
11
|
-
├── .assembled/ # 🏗️ Build output (gitignored)
|
|
12
|
-
├── config/ # ⚙️ Build tool configuration
|
|
13
|
-
├── scripts/ # 🔧 Build automation
|
|
14
|
-
├── archive/ # 📦 Historical artifacts
|
|
15
|
-
├── docs/ # 📚 Documentation
|
|
16
|
-
├── netlify.toml # 🌐 Netlify configuration (must be at root)
|
|
17
|
-
├── package.json # Root package manifest
|
|
18
|
-
└── STRUCTURE.md # This file
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Directory Details
|
|
22
|
-
|
|
23
|
-
### `.framework/` — Framework Core (Hidden)
|
|
24
|
-
**Managed by:** Spine CLI (read-only)
|
|
25
|
-
**Contains:**
|
|
26
|
-
- `functions/` — Core Netlify function handlers
|
|
27
|
-
- `src/` — Core React components (Admin shell, app router)
|
|
28
|
-
- `migrations/` — Base database schema
|
|
29
|
-
- `cli/` — Framework CLI tools
|
|
30
|
-
- `tests/` — Core test suites
|
|
31
|
-
|
|
32
|
-
**You should not edit files here.** The CLI manages updates to this directory.
|
|
33
|
-
|
|
34
|
-
### `custom/` — Developer Workspace
|
|
35
|
-
**Managed by:** You
|
|
36
|
-
**Contains:**
|
|
37
|
-
- `functions/` — Your custom Netlify function handlers
|
|
38
|
-
- `apps/` — Your applications (one folder per app)
|
|
39
|
-
- `components/` — Shared UI components across your apps
|
|
40
|
-
- `migrations/` — Your database schema changes
|
|
41
|
-
- `tests/` — Your test suites
|
|
42
|
-
|
|
43
|
-
**This is where you build your product.** Everything here is yours.
|
|
44
|
-
|
|
45
|
-
### `.assembled/` — Build Output (Hidden, Gitignored)
|
|
46
|
-
**Generated by:** Assembly scripts
|
|
47
|
-
**Contains:**
|
|
48
|
-
- `netlify/functions/` — Merged: `.framework/functions` + `custom/functions`
|
|
49
|
-
- `src/` — Merged: `.framework/src` + `custom/apps/*`
|
|
50
|
-
|
|
51
|
-
**Never edit files here.** This is rebuilt on every `netlify dev` or deployment.
|
|
52
|
-
|
|
53
|
-
### `config/` — Build Tool Configuration
|
|
54
|
-
**Contains:**
|
|
55
|
-
- `vite.config.ts` — Vite build configuration
|
|
56
|
-
- `tsconfig.json` — TypeScript configuration
|
|
57
|
-
- `tailwind.config.ts` — Styling configuration
|
|
58
|
-
- `postcss.config.js` — CSS processing
|
|
59
|
-
|
|
60
|
-
### `netlify.toml` — Netlify Configuration (Root)
|
|
61
|
-
**Must be at project root** (Netlify CLI requirement)
|
|
62
|
-
- Functions path: `.assembled/netlify/functions/`
|
|
63
|
-
- Dev server settings: port 3001 (Vite) → 8888 (Netlify proxy)
|
|
64
|
-
|
|
65
|
-
### `scripts/` — Build Automation
|
|
66
|
-
**Contains:**
|
|
67
|
-
- Assembly scripts that merge `.framework/` + `custom/` → `.assembled/`
|
|
68
|
-
- Verification scripts for integrity checking
|
|
69
|
-
|
|
70
|
-
### `archive/` — Historical Artifacts
|
|
71
|
-
**Contains:**
|
|
72
|
-
- Old audit documents
|
|
73
|
-
- Completed project reports
|
|
74
|
-
- Test artifacts
|
|
75
|
-
|
|
76
|
-
## Assembly Flow
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
Development:
|
|
80
|
-
.framework/ + custom/ ──► scripts/assemble.sh ──► .assembled/
|
|
81
|
-
──► netlify dev
|
|
82
|
-
|
|
83
|
-
Production:
|
|
84
|
-
.framework/ + custom/ ──► scripts/assemble.sh ──► .assembled/
|
|
85
|
-
──► Netlify deploy
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Path Aliases
|
|
89
|
-
|
|
90
|
-
After assembly, code uses these aliases:
|
|
91
|
-
- `@core` → `.framework/src/`
|
|
92
|
-
- `@custom` → `custom/apps/`
|
|
93
|
-
|
|
94
|
-
## Adding New Code
|
|
95
|
-
|
|
96
|
-
### New App
|
|
97
|
-
```bash
|
|
98
|
-
mkdir custom/apps/my-app
|
|
99
|
-
cd custom/apps/my-app
|
|
100
|
-
# Create src/, components/, pages/
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### New Function
|
|
104
|
-
```bash
|
|
105
|
-
touch custom/functions/my-handler.ts
|
|
106
|
-
# Edit with your logic
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### New Migration
|
|
110
|
-
```bash
|
|
111
|
-
touch custom/migrations/101_my_change.sql
|
|
112
|
-
# Write ALTER TABLE statements
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## Updating Framework
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
spine-framework update
|
|
119
|
-
# CLI updates .framework/ to latest version
|
|
120
|
-
# Your custom/ code is untouched
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## Important Rules
|
|
124
|
-
|
|
125
|
-
1. **Never edit `.framework/`** — use `custom/` instead
|
|
126
|
-
2. **Never commit `.assembled/`** — it's in `.gitignore`
|
|
127
|
-
3. **Always use assembly** — don't manually copy to `.assembled/`
|
|
128
|
-
4. **Test after update** — run `netlify dev` after `spine-framework update`
|
|
129
|
-
|
|
130
|
-
## Troubleshooting
|
|
131
|
-
|
|
132
|
-
### "Where do I put X?"
|
|
133
|
-
- Framework extension → `.framework/` (via CLI or PR)
|
|
134
|
-
- Custom business logic → `custom/`
|
|
135
|
-
- App-specific code → `custom/apps/{app-name}/`
|
|
136
|
-
|
|
137
|
-
### "Assembly failed"
|
|
138
|
-
1. Check both `.framework/` and `custom/` exist
|
|
139
|
-
2. Verify no duplicate function names
|
|
140
|
-
3. Run `scripts/assemble.sh` manually for error details
|
|
141
|
-
|
|
142
|
-
### "Functions not found"
|
|
143
|
-
1. Check `.assembled/netlify/functions/` exists
|
|
144
|
-
2. Verify `netlify.toml` (in project root) points to correct path
|
|
145
|
-
3. Ensure assembly ran without errors
|
|
146
|
-
|
|
147
|
-
### "Netlify dev can't connect"
|
|
148
|
-
1. Check Vite is running on port 3001
|
|
149
|
-
2. Verify `netlify.toml` is in project root (not config/)
|
|
150
|
-
3. Check `targetPort = 3001` in netlify.toml [dev] section
|