diff --git a/docs/database/0001-initial-schema.md b/docs/database/0001-initial-schema.md new file mode 100644 index 0000000..2243cf7 --- /dev/null +++ b/docs/database/0001-initial-schema.md @@ -0,0 +1,60 @@ +# 0001 Initial Schema + +SQL file: `supabase/schema.sql` + +## Purpose + +This is the first registered database query file for the project. It represents the schema that existed before the Freelancer OS MVP planning work started. + +## What It Creates + +- `journals` +- `tasks` +- `chat_sessions` +- `chat_messages` +- `profiles` +- Row Level Security policies for the tables above +- `handle_new_user()` trigger function for profile creation +- `on_auth_user_created` trigger +- `avatars` storage bucket and related storage policies + +## Current Product Fit + +This schema supports the earlier MindSpace/Cognis prototype: + +- mood/energy journals +- basic tasks +- chat history +- user profile storage +- avatar uploads + +It does not yet fully match the Freelancer OS MVP model. + +## Known Gaps For MVP + +The Freelancer OS MVP still needs new schema additions for: + +- `clients` +- `projects` +- `calendar_events` +- `finance_transactions` +- `daily_logs` +- `app_settings` + +The existing `journals` table can either be migrated into `daily_logs` or kept as a legacy table until the UI is moved to the new model. + +## Execution Notes + +This file should be treated as the first baseline. + +It was updated to be safer for Supabase SQL Editor retries: + +- tables use `create table if not exists` +- policies are dropped before being recreated +- the profile trigger is dropped before being recreated +- the PL/pgSQL function uses the correct `$$` delimiter +- profile creation uses `on conflict (id) do nothing` + +If a previous run failed halfway through, rerunning this baseline should be safe for the current schema shape. + +Future changes should be added as ordered migration files rather than editing this baseline after execution. diff --git a/docs/database/0002-freelancer-os-core-tables.md b/docs/database/0002-freelancer-os-core-tables.md new file mode 100644 index 0000000..812d276 --- /dev/null +++ b/docs/database/0002-freelancer-os-core-tables.md @@ -0,0 +1,72 @@ +# 0002 Freelancer OS Core Tables + +SQL file: `supabase/migrations/0002_add_freelancer_os_core_tables.sql` + +## Purpose + +Adds the database model required for the Freelancer OS MVP. + +This migration keeps the existing baseline from `supabase/schema.sql` and extends it instead of replacing it. The existing `tasks` table is reused and enriched with freelancer-specific fields. + +## What It Creates + +- `clients` +- `projects` +- `calendar_events` +- `finance_transactions` +- `daily_logs` +- `app_settings` +- `set_updated_at()` trigger function +- updated-at triggers for the new tables +- indexes for common dashboard/report queries +- RLS policies for every new table + +## What It Changes + +The existing `tasks` table gets these additional columns: + +- `client_id` +- `project_id` +- `priority` +- `due_at` +- `estimated_minutes` +- `actual_minutes` + +This lets a task belong to a client and/or project while preserving the earlier journal/task prototype schema. + +## MVP Coverage + +This migration supports: + +- client management +- client projects +- side projects +- task planning +- calendar planning +- income and expense tracking +- daily mood/energy logging +- app and AI provider settings + +## RLS Model + +Every new table has `user_id`. + +Policies follow the same pattern: + +- users can select their own rows +- users can insert rows only for themselves +- users can update their own rows +- users can delete their own rows + +## Notes + +`app_settings.api_key` exists for compatibility with the current prototype flow. For production-grade use, provider credentials should be encrypted or moved to a safer secret-management strategy. + +`daily_logs` is the new MVP-oriented replacement for the earlier `journals` concept. The old `journals` table remains available until the UI migration is complete. + +## Execution + +Run this after `supabase/schema.sql`. + +Do not add this file to `query-log.md` until it has actually been executed against a database. + diff --git a/docs/database/0003-project-planning-assets.md b/docs/database/0003-project-planning-assets.md new file mode 100644 index 0000000..55a7ede --- /dev/null +++ b/docs/database/0003-project-planning-assets.md @@ -0,0 +1,92 @@ +# 0003 - Project Planning Assets + +SQL file: `supabase/migrations/0003_add_project_planning_assets.sql` + +## Purpose + +This migration extends project management beyond task tracking. + +It adds: + +- Project cover image fields on `projects` +- A private Supabase Storage bucket for uploaded project images +- A structured `project_planning_sections` table for project planning categories + +## Project Image Fields + +The `projects` table receives: + +- `cover_image_path`: path of the uploaded file in the `project-assets` bucket +- `cover_image_alt`: optional alt text for the cover image + +Images are uploaded from the user's computer, not saved as external image links. + +## Storage Bucket + +Bucket: + +- `project-assets` + +Configuration: + +- Private bucket +- Max file size: 5 MB +- Allowed MIME types: + - `image/jpeg` + - `image/png` + - `image/webp` + - `image/gif` + +Storage object paths must start with the authenticated user id: + +```txt +/projects// +``` + +This keeps Storage RLS simple and user-scoped. + +## Planning Sections + +Table: + +- `project_planning_sections` + +Core fields: + +- `user_id` +- `project_id` +- `category` +- `title` +- `content` +- `metadata` +- `sort_order` + +Allowed categories: + +- `overview` +- `problem` +- `goal` +- `audience` +- `scope` +- `design_system` +- `color_palette` +- `typography` +- `assets` +- `notes` + +## RLS + +RLS is enabled for `project_planning_sections`. + +Users can only select, insert, update, and delete their own planning sections. + +Storage policies allow users to select, upload, update, and delete only files under their own user id folder inside `project-assets`. + +## Execution + +Run after: + +1. `supabase/schema.sql` +2. `supabase/migrations/0002_add_freelancer_os_core_tables.sql` + +After running this SQL in Supabase, add an execution record to `docs/database/query-log.md`. diff --git a/docs/database/0009-lock-registration-after-first-admin.md b/docs/database/0009-lock-registration-after-first-admin.md new file mode 100644 index 0000000..3853c04 --- /dev/null +++ b/docs/database/0009-lock-registration-after-first-admin.md @@ -0,0 +1,34 @@ +# 0009 - Lock Registration After First Admin + +SQL file: + +`supabase/migrations/0009_lock_registration_after_first_admin.sql` + +## Purpose + +Adds the first-time setup guard for self-hosted installations. + +The `/register` page is only available while the system has no profile record. After the first account creates a profile, public registration is closed. + +## Changes + +- Adds `public.is_first_admin_setup_available()`. +- Grants the function to `anon` and `authenticated` roles so the app can check setup state safely without bypassing RLS manually. +- Replaces `public.handle_new_user()` so direct public Supabase Auth signup attempts are also rejected after the first profile exists. +- Allows service-role/admin-created users when `raw_app_meta_data.internal_created` is `true`, so future invite/client-portal flows can still create accounts intentionally. + +## Behavior + +1. Fresh install has no `public.profiles` rows. +2. `/register` stays open. +3. The first signup creates an auth user and the trigger creates the first profile. +4. The setup function starts returning `false`. +5. `/register` redirects to `/login`. +6. Further public signup attempts fail at the database trigger level. +7. Admin-created internal users can still be allowed by service-role flows that set `app_metadata.internal_created = true`. + +## Notes + +- This is intended for the MVP single-admin self-host model. +- If multi-user, client portal accounts, invites, or team members are re-enabled later, keep them behind service-role/admin-created flows instead of public signup. +- Do not add this SQL file to `query-log.md` until it has actually been run in the target Supabase environment. diff --git a/docs/database/README.md b/docs/database/README.md new file mode 100644 index 0000000..f714ebc --- /dev/null +++ b/docs/database/README.md @@ -0,0 +1,44 @@ +# Database Change Process + +This directory records every database change that should be run against Supabase/PostgreSQL. + +The project currently starts with `supabase/schema.sql` as the first database query file. Future database changes must be added as separate SQL files and registered here before they are run. + +## Rules + +1. Every SQL change must have a stable order number. +2. Every SQL file must be listed in `query-order.md`. +3. Every executed query must be recorded in `query-log.md`. +4. Every meaningful schema addition must have a short documentation file under this directory. +5. Do not edit an already executed SQL file silently. Add a new ordered SQL file instead. + +## Current Files + +- `supabase/schema.sql`: Initial legacy schema. It creates the current auth/profile, journal, task, chat, and avatar storage structure. +- `supabase/migrations/0002_add_freelancer_os_core_tables.sql`: Freelancer OS MVP core schema. +- `supabase/seeds/0001_demo_freelancer_os_data.sql`: Optional local/demo data for the MVP schema. +- `docs/database/0001-initial-schema.md`: Explanation for the initial schema. +- `docs/database/0002-freelancer-os-core-tables.md`: Explanation for the MVP schema migration. +- `docs/database/seed-0001-demo-freelancer-os-data.md`: Explanation for the demo seed file. +- `docs/database/query-order.md`: Canonical order of SQL files. +- `docs/database/query-log.md`: Manual execution log for SQL files that were run against an environment. + +## Next Migration Naming + +Use this pattern for future SQL files: + +```text +supabase/migrations/0002_short_description.sql +``` + +Example: + +```text +supabase/migrations/0002_add_freelancer_os_core_tables.sql +``` + +Use this pattern for future seed files: + +```text +supabase/seeds/0002_short_description.sql +``` diff --git a/docs/database/query-log.md b/docs/database/query-log.md new file mode 100644 index 0000000..c680c29 --- /dev/null +++ b/docs/database/query-log.md @@ -0,0 +1,10 @@ +# Database Query Log + +This file records SQL files that were executed against a database environment. + +Do not mark a query as executed unless it was actually run. + +| Date | Environment | Order | SQL file | Runner | Result | Notes | +| --- | --- | --- | --- | --- | --- | --- | +| Not recorded | Unknown existing environment | 0001 | `supabase/schema.sql` | Unknown | Assumed existing baseline | File existed before this query log was introduced. Confirm manually before rerunning. | + diff --git a/docs/database/query-order.md b/docs/database/query-order.md new file mode 100644 index 0000000..5023397 --- /dev/null +++ b/docs/database/query-order.md @@ -0,0 +1,25 @@ +# Database Query Order + +This file is the canonical order of SQL files for database setup and migration. + +| Order | SQL file | Documentation | Status | +| --- | --- | --- | --- | +| 0001 | `supabase/schema.sql` | `docs/database/0001-initial-schema.md` | Baseline registered | +| 0002 | `supabase/migrations/0002_add_freelancer_os_core_tables.sql` | `docs/database/0002-freelancer-os-core-tables.md` | Pending execution | +| 0003 | `supabase/migrations/0003_add_project_planning_assets.sql` | `docs/database/0003-project-planning-assets.md` | Pending execution | +| 0009 | `supabase/migrations/0009_lock_registration_after_first_admin.sql` | `docs/database/0009-lock-registration-after-first-admin.md` | Pending execution | +| seed-0001 | `supabase/seeds/0001_demo_freelancer_os_data.sql` | `docs/database/seed-0001-demo-freelancer-os-data.md` | Optional demo seed, pending execution | + +## How To Add The Next Query + +1. Create a new SQL file under `supabase/migrations/`. +2. Use the next order number. +3. Add a documentation file under `docs/database/`. +4. Register both files in this table. +5. After running the SQL, add an entry to `query-log.md`. + +## Seed Files + +Seed files are optional and should live under `supabase/seeds/`. + +They must also be documented and registered in this file, but they should only be run in local/demo environments unless explicitly approved. diff --git a/docs/database/seed-0001-demo-freelancer-os-data.md b/docs/database/seed-0001-demo-freelancer-os-data.md new file mode 100644 index 0000000..fa2ee33 --- /dev/null +++ b/docs/database/seed-0001-demo-freelancer-os-data.md @@ -0,0 +1,43 @@ +# Seed 0001 Demo Freelancer OS Data + +SQL file: `supabase/seeds/0001_demo_freelancer_os_data.sql` + +## Purpose + +Adds demo data for local development and dashboard testing after the Freelancer OS core tables are created. + +## What It Inserts + +- demo clients +- demo projects and one side project +- demo tasks +- demo calendar events +- demo finance transactions +- demo daily mood/energy logs +- demo `app_settings` + +## Required Manual Step + +Before running the file, replace this placeholder with a real `auth.users.id`: + +```sql +'00000000-0000-0000-0000-000000000000'::uuid +``` + +Use a user id from your Supabase Auth users table. + +## Environment + +This seed is intended for local and demo environments only. + +Do not run it on production data. + +## Execution + +Run after: + +1. `supabase/schema.sql` +2. `supabase/migrations/0002_add_freelancer_os_core_tables.sql` + +After running it, add an entry to `docs/database/query-log.md`. +