From ba6f7711449de47bd25cad7ac21bdc2a53355963 Mon Sep 17 00:00:00 2001 From: willchen96 Date: Fri, 8 May 2026 20:45:16 +0800 Subject: [PATCH] Sync security and backend profile updates --- README.md | 6 +- backend/.gitignore | 1 - backend/bun.lock | 8 + backend/migrations/000_one_shot_schema.sql | 340 ------ backend/package-lock.json | 39 +- backend/package.json | 6 +- backend/schema.sql | 1046 +++++++++++++++++ backend/src/index.ts | 87 ++ backend/src/lib/chatTools.ts | 493 +++++--- backend/src/lib/llm/claude.ts | 13 - backend/src/lib/llm/gemini.ts | 1 - backend/src/lib/storage.ts | 4 +- backend/src/lib/userApiKeys.ts | 143 +++ backend/src/lib/userSettings.ts | 19 +- backend/src/routes/chat.ts | 270 +++-- backend/src/routes/user.ts | 235 +++- backend/tsconfig.json | 1 + frontend/bun.lock | 2 +- frontend/package-lock.json | 1 - frontend/package.json | 4 +- frontend/public/link-image.jpg | Bin 0 -> 214619 bytes .../src/app/(pages)/account/models/page.tsx | 45 +- .../(pages)/projects/[id]/assistant/page.tsx | 13 + .../projects/[id]/tabular-reviews/page.tsx | 13 + .../app/components/assistant/ChatInput.tsx | 12 +- .../app/components/projects/ProjectPage.tsx | 5 +- .../app/components/tabular/TRChatPanel.tsx | 52 +- frontend/src/app/global-error.tsx | 4 +- frontend/src/app/hooks/useAssistantChat.ts | 29 +- frontend/src/app/layout.tsx | 24 + frontend/src/app/lib/mikeApi.ts | 63 +- frontend/src/app/login/page.tsx | 8 +- frontend/src/app/privacy/page.tsx | 160 +++ frontend/src/app/signup/page.tsx | 34 +- frontend/src/app/support/page.tsx | 273 +++++ frontend/src/app/terms/page.tsx | 202 ++++ frontend/src/contexts/AuthContext.tsx | 13 - frontend/src/contexts/UserProfileContext.tsx | 209 +--- frontend/src/lib/auth.ts | 11 +- 39 files changed, 3033 insertions(+), 856 deletions(-) delete mode 100644 backend/migrations/000_one_shot_schema.sql create mode 100644 backend/schema.sql create mode 100644 backend/src/lib/userApiKeys.ts create mode 100644 frontend/public/link-image.jpg create mode 100644 frontend/src/app/(pages)/projects/[id]/assistant/page.tsx create mode 100644 frontend/src/app/(pages)/projects/[id]/tabular-reviews/page.tsx create mode 100644 frontend/src/app/privacy/page.tsx create mode 100644 frontend/src/app/support/page.tsx create mode 100644 frontend/src/app/terms/page.tsx diff --git a/README.md b/README.md index 37cd725..aa673cb 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Open-source release containing the Mike frontend and backend. ## Contents - `frontend/` - Next.js application -- `backend/` - Express API, Supabase access, document processing, and migrations -- `backend/migrations/000_one_shot_schema.sql` - one-shot Supabase schema for fresh databases +- `backend/` - Express API, Supabase access, document processing, and database schema +- `backend/schema.sql` - Supabase schema for fresh databases ## Setup @@ -24,7 +24,7 @@ cp backend/.env.example backend/.env cp frontend/.env.local.example frontend/.env.local ``` -Run `backend/migrations/000_one_shot_schema.sql` in the Supabase SQL editor for a fresh database. +Run `backend/schema.sql` in the Supabase SQL editor for a fresh database. Start the backend: diff --git a/backend/.gitignore b/backend/.gitignore index bcbd2ce..12bb4bb 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,6 +1,5 @@ node_modules dist .env* -!.env.example *.log .DS_Store diff --git a/backend/bun.lock b/backend/bun.lock index eb64b68..90061e1 100644 --- a/backend/bun.lock +++ b/backend/bun.lock @@ -14,8 +14,10 @@ "docx": "^9.5.0", "dotenv": "^17.4.1", "express": "^4.21.2", + "express-rate-limit": "^8.5.1", "fast-diff": "^1.3.0", "fast-xml-parser": "^5.7.1", + "helmet": "^8.1.0", "jszip": "^3.10.1", "libreoffice-convert": "^1.6.0", "mammoth": "^1.9.0", @@ -471,6 +473,8 @@ "express": ["express@4.22.1", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "~1.20.3", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.3.1", "fresh": "~0.5.2", "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", "serve-static": "~1.16.2", "setprototypeof": "1.2.0", "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g=="], + "express-rate-limit": ["express-rate-limit@8.5.1", "", { "dependencies": { "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-5O6KYmyJEpuPJV5hNTXKbAHWRqrzyu+OI3vUnSd2kXFubIVpG7ezpgxQy76Zo5GQZtrQBg86hF+CM/NX+cioiQ=="], + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], "fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="], @@ -517,6 +521,8 @@ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + "helmet": ["helmet@8.1.0", "", {}, "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg=="], + "html-to-text": ["html-to-text@9.0.5", "", { "dependencies": { "@selderee/plugin-htmlparser2": "^0.11.0", "deepmerge": "^4.3.1", "dom-serializer": "^2.0.0", "htmlparser2": "^8.0.2", "selderee": "^0.11.0" } }, "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg=="], "htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="], @@ -533,6 +539,8 @@ "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + "ip-address": ["ip-address@10.2.0", "", {}, "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA=="], + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], diff --git a/backend/migrations/000_one_shot_schema.sql b/backend/migrations/000_one_shot_schema.sql deleted file mode 100644 index 80d563a..0000000 --- a/backend/migrations/000_one_shot_schema.sql +++ /dev/null @@ -1,340 +0,0 @@ --- Mike one-shot Supabase schema --- Based on supabase-migration.sql plus the later backend/migrations/*.sql files. --- Use this for a fresh Supabase database. Existing deployments should continue --- to apply the incremental migration files instead. - -create extension if not exists "pgcrypto"; - --- --------------------------------------------------------------------------- --- User profiles --- --------------------------------------------------------------------------- - -create table if not exists public.user_profiles ( - id uuid primary key default gen_random_uuid(), - user_id uuid not null unique references auth.users(id) on delete cascade, - display_name text, - organisation text, - tier text not null default 'Free', - message_credits_used integer not null default 0, - credits_reset_date timestamptz not null default (now() + interval '30 days'), - tabular_model text not null default 'gemini-3-flash-preview', - claude_api_key text, - gemini_api_key text, - created_at timestamptz not null default now(), - updated_at timestamptz not null default now() -); - -create index if not exists idx_user_profiles_user - on public.user_profiles(user_id); - -alter table public.user_profiles enable row level security; - -drop policy if exists "Users can view their own profile" on public.user_profiles; -create policy "Users can view their own profile" - on public.user_profiles for select - using (auth.uid() = user_id); - -drop policy if exists "Users can update their own profile" on public.user_profiles; -create policy "Users can update their own profile" - on public.user_profiles for update - using (auth.uid() = user_id); - -create or replace function public.handle_new_user() -returns trigger -language plpgsql -security definer -set search_path = public -as $$ -begin - insert into public.user_profiles (user_id) - values (new.id) - on conflict (user_id) do nothing; - return new; -exception when others then - -- Never block signup if the profile insert fails. - return new; -end; -$$; - -drop trigger if exists on_auth_user_created on auth.users; -create trigger on_auth_user_created - after insert on auth.users - for each row execute procedure public.handle_new_user(); - --- --------------------------------------------------------------------------- --- Projects and documents --- --------------------------------------------------------------------------- - -create table if not exists public.projects ( - id uuid primary key default gen_random_uuid(), - user_id text not null, - name text not null, - cm_number text, - visibility text not null default 'private', - shared_with jsonb not null default '[]'::jsonb, - created_at timestamptz not null default now(), - updated_at timestamptz not null default now() -); - -create index if not exists idx_projects_user - on public.projects(user_id); - -create index if not exists projects_shared_with_idx - on public.projects using gin (shared_with); - -create table if not exists public.project_subfolders ( - id uuid primary key default gen_random_uuid(), - project_id uuid not null references public.projects(id) on delete cascade, - user_id text not null, - name text not null, - parent_folder_id uuid references public.project_subfolders(id) on delete cascade, - created_at timestamptz not null default now(), - updated_at timestamptz not null default now() -); - -create index if not exists idx_project_subfolders_project - on public.project_subfolders(project_id); - -create table if not exists public.documents ( - id uuid primary key default gen_random_uuid(), - project_id uuid references public.projects(id) on delete cascade, - user_id text not null, - filename text not null, - file_type text, - size_bytes integer not null default 0, - page_count integer, - structure_tree jsonb, - status text not null default 'pending', - folder_id uuid references public.project_subfolders(id) on delete set null, - created_at timestamptz not null default now(), - updated_at timestamptz not null default now() -); - -create index if not exists idx_documents_user_project - on public.documents(user_id, project_id); - -create index if not exists idx_documents_project_folder - on public.documents(project_id, folder_id); - -create table if not exists public.document_versions ( - id uuid primary key default gen_random_uuid(), - document_id uuid not null references public.documents(id) on delete cascade, - storage_path text not null, - pdf_storage_path text, - source text not null default 'upload', - version_number integer, - display_name text, - created_at timestamptz not null default now(), - constraint document_versions_source_check - check (source = any (array[ - 'upload'::text, - 'user_upload'::text, - 'assistant_edit'::text, - 'user_accept'::text, - 'user_reject'::text, - 'generated'::text - ])) -); - -create index if not exists document_versions_document_id_idx - on public.document_versions(document_id, created_at desc); - -create index if not exists document_versions_doc_vnum_idx - on public.document_versions(document_id, version_number); - -alter table public.documents - add column if not exists current_version_id uuid - references public.document_versions(id) on delete set null; - -create table if not exists public.document_edits ( - id uuid primary key default gen_random_uuid(), - document_id uuid not null references public.documents(id) on delete cascade, - chat_message_id uuid, - version_id uuid not null references public.document_versions(id) on delete cascade, - change_id text not null, - del_w_id text, - ins_w_id text, - deleted_text text not null default '', - inserted_text text not null default '', - context_before text, - context_after text, - status text not null default 'pending' - check (status = any (array[ - 'pending'::text, - 'accepted'::text, - 'rejected'::text - ])), - created_at timestamptz not null default now(), - resolved_at timestamptz -); - -create index if not exists document_edits_document_id_idx - on public.document_edits(document_id, created_at desc); - -create index if not exists document_edits_message_id_idx - on public.document_edits(chat_message_id); - -create index if not exists document_edits_version_id_idx - on public.document_edits(version_id); - --- --------------------------------------------------------------------------- --- Workflows --- --------------------------------------------------------------------------- - -create table if not exists public.workflows ( - id uuid primary key default gen_random_uuid(), - user_id text, - title text not null, - type text not null, - prompt_md text, - columns_config jsonb, - practice text, - is_system boolean not null default false, - created_at timestamptz not null default now() -); - -create index if not exists idx_workflows_user - on public.workflows(user_id); - -create table if not exists public.hidden_workflows ( - id uuid primary key default gen_random_uuid(), - user_id text not null, - workflow_id text not null, - created_at timestamptz not null default now(), - unique(user_id, workflow_id) -); - -create index if not exists idx_hidden_workflows_user - on public.hidden_workflows(user_id); - -create table if not exists public.workflow_shares ( - id uuid primary key default gen_random_uuid(), - workflow_id uuid not null references public.workflows(id) on delete cascade, - shared_by_user_id text not null, - shared_with_email text not null, - allow_edit boolean not null default false, - created_at timestamptz not null default now(), - constraint workflow_shares_workflow_email_unique - unique(workflow_id, shared_with_email) -); - -create index if not exists workflow_shares_workflow_id_idx - on public.workflow_shares(workflow_id); - -create index if not exists workflow_shares_email_idx - on public.workflow_shares(shared_with_email); - --- --------------------------------------------------------------------------- --- Assistant chats --- --------------------------------------------------------------------------- - -create table if not exists public.chats ( - id uuid primary key default gen_random_uuid(), - project_id uuid references public.projects(id) on delete cascade, - user_id text not null, - title text, - created_at timestamptz not null default now() -); - -create index if not exists idx_chats_user - on public.chats(user_id); - -create index if not exists idx_chats_project - on public.chats(project_id); - -create table if not exists public.chat_messages ( - id uuid primary key default gen_random_uuid(), - chat_id uuid not null references public.chats(id) on delete cascade, - role text not null, - content jsonb, - files jsonb, - annotations jsonb, - created_at timestamptz not null default now() -); - -create index if not exists idx_chat_messages_chat - on public.chat_messages(chat_id); - -do $$ -begin - if not exists ( - select 1 - from pg_constraint - where conname = 'document_edits_chat_message_id_fkey' - and conrelid = 'public.document_edits'::regclass - ) then - alter table public.document_edits - add constraint document_edits_chat_message_id_fkey - foreign key (chat_message_id) - references public.chat_messages(id) - on delete set null; - end if; -end; -$$; - --- --------------------------------------------------------------------------- --- Tabular reviews --- --------------------------------------------------------------------------- - -create table if not exists public.tabular_reviews ( - id uuid primary key default gen_random_uuid(), - project_id uuid references public.projects(id) on delete cascade, - user_id text not null, - title text, - columns_config jsonb, - workflow_id uuid references public.workflows(id) on delete set null, - practice text, - shared_with jsonb not null default '[]'::jsonb, - created_at timestamptz not null default now(), - updated_at timestamptz not null default now() -); - -create index if not exists idx_tabular_reviews_user - on public.tabular_reviews(user_id); - -create index if not exists idx_tabular_reviews_project - on public.tabular_reviews(project_id); - -create index if not exists tabular_reviews_shared_with_idx - on public.tabular_reviews using gin (shared_with); - -create table if not exists public.tabular_cells ( - id uuid primary key default gen_random_uuid(), - review_id uuid not null references public.tabular_reviews(id) on delete cascade, - document_id uuid not null references public.documents(id) on delete cascade, - column_index integer not null, - content text, - citations jsonb, - status text not null default 'pending', - created_at timestamptz not null default now() -); - -create index if not exists idx_tabular_cells_review - on public.tabular_cells(review_id, document_id, column_index); - -create table if not exists public.tabular_review_chats ( - id uuid primary key default gen_random_uuid(), - review_id uuid not null references public.tabular_reviews(id) on delete cascade, - user_id text not null, - title text, - created_at timestamptz not null default now(), - updated_at timestamptz not null default now() -); - -create index if not exists tabular_review_chats_review_idx - on public.tabular_review_chats(review_id, updated_at desc); - -create index if not exists tabular_review_chats_user_idx - on public.tabular_review_chats(user_id); - -create table if not exists public.tabular_review_chat_messages ( - id uuid primary key default gen_random_uuid(), - chat_id uuid not null references public.tabular_review_chats(id) on delete cascade, - role text not null, - content jsonb, - annotations jsonb, - created_at timestamptz not null default now() -); - -create index if not exists tabular_review_chat_messages_chat_idx - on public.tabular_review_chat_messages(chat_id, created_at); diff --git a/backend/package-lock.json b/backend/package-lock.json index 86f8238..effa2ad 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -7,7 +7,6 @@ "": { "name": "mike-backend", "version": "1.0.0", - "license": "AGPL-3.0-only", "dependencies": { "@anthropic-ai/sdk": "^0.90.0", "@aws-sdk/client-s3": "^3.787.0", @@ -18,8 +17,10 @@ "docx": "^9.5.0", "dotenv": "^17.4.1", "express": "^4.21.2", + "express-rate-limit": "^8.5.1", "fast-diff": "^1.3.0", "fast-xml-parser": "^5.7.1", + "helmet": "^8.1.0", "jszip": "^3.10.1", "libreoffice-convert": "^1.6.0", "mammoth": "^1.9.0", @@ -3351,6 +3352,24 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-rate-limit": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.1.tgz", + "integrity": "sha512-5O6KYmyJEpuPJV5hNTXKbAHWRqrzyu+OI3vUnSd2kXFubIVpG7ezpgxQy76Zo5GQZtrQBg86hF+CM/NX+cioiQ==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.2.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -3650,6 +3669,15 @@ "node": ">= 0.4" } }, + "node_modules/helmet": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz", + "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/html-to-text": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", @@ -3774,6 +3802,15 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", diff --git a/backend/package.json b/backend/package.json index 50dfb58..8451ab8 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,7 +1,6 @@ { "name": "mike-backend", "version": "1.0.0", - "license": "AGPL-3.0-only", "private": true, "scripts": { "dev": "tsx watch src/index.ts", @@ -18,8 +17,10 @@ "docx": "^9.5.0", "dotenv": "^17.4.1", "express": "^4.21.2", + "express-rate-limit": "^8.5.1", "fast-diff": "^1.3.0", "fast-xml-parser": "^5.7.1", + "helmet": "^8.1.0", "jszip": "^3.10.1", "libreoffice-convert": "^1.6.0", "mammoth": "^1.9.0", @@ -35,5 +36,6 @@ "prettier": "^3.8.1", "tsx": "^4.19.3", "typescript": "^5.8.3" - } + }, + "license": "AGPL-3.0-only" } diff --git a/backend/schema.sql b/backend/schema.sql new file mode 100644 index 0000000..cf72870 --- /dev/null +++ b/backend/schema.sql @@ -0,0 +1,1046 @@ +-- Mike Supabase schema +-- Based on supabase-migration.sql plus the later backend/migrations/*.sql files. +-- Use this for a fresh Supabase database. Existing deployments should continue +-- to apply the incremental migration files instead. + +create extension if not exists "pgcrypto"; + +-- --------------------------------------------------------------------------- +-- User profiles +-- --------------------------------------------------------------------------- + +create table if not exists public.user_profiles ( + id uuid primary key default gen_random_uuid(), + user_id uuid not null unique references auth.users(id) on delete cascade, + display_name text, + organisation text, + tier text not null default 'Free', + message_credits_used integer not null default 0, + credits_reset_date timestamptz not null default (now() + interval '30 days'), + tabular_model text not null default 'gemini-3-flash-preview', + created_at timestamptz not null default now(), + updated_at timestamptz not null default now() +); + +create index if not exists idx_user_profiles_user + on public.user_profiles(user_id); + +alter table public.user_profiles enable row level security; + +drop policy if exists "Users can view their own profile" on public.user_profiles; +create policy "Users can view their own profile" + on public.user_profiles for select + using (auth.uid() = user_id); + +drop policy if exists "Users can update their own profile" on public.user_profiles; +create policy "Users can update their own profile" + on public.user_profiles for update + using (auth.uid() = user_id); + +create or replace function public.handle_new_user() +returns trigger +language plpgsql +security definer +set search_path = public +as $$ +begin + insert into public.user_profiles (user_id) + values (new.id) + on conflict (user_id) do nothing; + return new; +exception when others then + -- Never block signup if the profile insert fails. + return new; +end; +$$; + +drop trigger if exists on_auth_user_created on auth.users; +create trigger on_auth_user_created + after insert on auth.users + for each row execute procedure public.handle_new_user(); + +create table if not exists public.user_api_keys ( + id uuid primary key default gen_random_uuid(), + user_id uuid not null references auth.users(id) on delete cascade, + provider text not null check (provider in ('claude', 'gemini')), + encrypted_key text not null, + iv text not null, + auth_tag text not null, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now(), + unique(user_id, provider) +); + +create index if not exists idx_user_api_keys_user + on public.user_api_keys(user_id); + +alter table public.user_api_keys enable row level security; + +-- --------------------------------------------------------------------------- +-- Projects and documents +-- --------------------------------------------------------------------------- + +create table if not exists public.projects ( + id uuid primary key default gen_random_uuid(), + user_id text not null, + name text not null, + cm_number text, + visibility text not null default 'private', + shared_with jsonb not null default '[]'::jsonb, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now() +); + +create index if not exists idx_projects_user + on public.projects(user_id); + +create index if not exists projects_shared_with_idx + on public.projects using gin (shared_with); + +create table if not exists public.project_subfolders ( + id uuid primary key default gen_random_uuid(), + project_id uuid not null references public.projects(id) on delete cascade, + user_id text not null, + name text not null, + parent_folder_id uuid references public.project_subfolders(id) on delete cascade, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now() +); + +create index if not exists idx_project_subfolders_project + on public.project_subfolders(project_id); + +create table if not exists public.documents ( + id uuid primary key default gen_random_uuid(), + project_id uuid references public.projects(id) on delete cascade, + user_id text not null, + filename text not null, + file_type text, + size_bytes integer not null default 0, + page_count integer, + structure_tree jsonb, + status text not null default 'pending', + folder_id uuid references public.project_subfolders(id) on delete set null, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now() +); + +create index if not exists idx_documents_user_project + on public.documents(user_id, project_id); + +create index if not exists idx_documents_project_folder + on public.documents(project_id, folder_id); + +create table if not exists public.document_versions ( + id uuid primary key default gen_random_uuid(), + document_id uuid not null references public.documents(id) on delete cascade, + storage_path text not null, + pdf_storage_path text, + source text not null default 'upload', + version_number integer, + display_name text, + created_at timestamptz not null default now(), + constraint document_versions_source_check + check (source = any (array[ + 'upload'::text, + 'user_upload'::text, + 'assistant_edit'::text, + 'user_accept'::text, + 'user_reject'::text, + 'generated'::text + ])) +); + +create index if not exists document_versions_document_id_idx + on public.document_versions(document_id, created_at desc); + +create index if not exists document_versions_doc_vnum_idx + on public.document_versions(document_id, version_number); + +alter table public.documents + add column if not exists current_version_id uuid + references public.document_versions(id) on delete set null; + +create table if not exists public.document_edits ( + id uuid primary key default gen_random_uuid(), + document_id uuid not null references public.documents(id) on delete cascade, + chat_message_id uuid, + version_id uuid not null references public.document_versions(id) on delete cascade, + change_id text not null, + del_w_id text, + ins_w_id text, + deleted_text text not null default '', + inserted_text text not null default '', + context_before text, + context_after text, + status text not null default 'pending' + check (status = any (array[ + 'pending'::text, + 'accepted'::text, + 'rejected'::text + ])), + created_at timestamptz not null default now(), + resolved_at timestamptz +); + +create index if not exists document_edits_document_id_idx + on public.document_edits(document_id, created_at desc); + +create index if not exists document_edits_message_id_idx + on public.document_edits(chat_message_id); + +create index if not exists document_edits_version_id_idx + on public.document_edits(version_id); + +-- --------------------------------------------------------------------------- +-- Workflows +-- --------------------------------------------------------------------------- + +create table if not exists public.workflows ( + id uuid primary key default gen_random_uuid(), + user_id text, + title text not null, + type text not null, + prompt_md text, + columns_config jsonb, + practice text, + is_system boolean not null default false, + created_at timestamptz not null default now() +); + +create index if not exists idx_workflows_user + on public.workflows(user_id); + +create table if not exists public.hidden_workflows ( + id uuid primary key default gen_random_uuid(), + user_id text not null, + workflow_id text not null, + created_at timestamptz not null default now(), + unique(user_id, workflow_id) +); + +create index if not exists idx_hidden_workflows_user + on public.hidden_workflows(user_id); + +create table if not exists public.workflow_shares ( + id uuid primary key default gen_random_uuid(), + workflow_id uuid not null references public.workflows(id) on delete cascade, + shared_by_user_id text not null, + shared_with_email text not null, + allow_edit boolean not null default false, + created_at timestamptz not null default now(), + constraint workflow_shares_workflow_email_unique + unique(workflow_id, shared_with_email) +); + +create index if not exists workflow_shares_workflow_id_idx + on public.workflow_shares(workflow_id); + +create index if not exists workflow_shares_email_idx + on public.workflow_shares(shared_with_email); + +-- --------------------------------------------------------------------------- +-- Assistant chats +-- --------------------------------------------------------------------------- + +create table if not exists public.chats ( + id uuid primary key default gen_random_uuid(), + project_id uuid references public.projects(id) on delete cascade, + user_id text not null, + title text, + created_at timestamptz not null default now() +); + +create index if not exists idx_chats_user + on public.chats(user_id); + +create index if not exists idx_chats_project + on public.chats(project_id); + +create table if not exists public.chat_messages ( + id uuid primary key default gen_random_uuid(), + chat_id uuid not null references public.chats(id) on delete cascade, + role text not null, + content jsonb, + files jsonb, + annotations jsonb, + created_at timestamptz not null default now() +); + +create index if not exists idx_chat_messages_chat + on public.chat_messages(chat_id); + +do $$ +begin + if not exists ( + select 1 + from pg_constraint + where conname = 'document_edits_chat_message_id_fkey' + and conrelid = 'public.document_edits'::regclass + ) then + alter table public.document_edits + add constraint document_edits_chat_message_id_fkey + foreign key (chat_message_id) + references public.chat_messages(id) + on delete set null; + end if; +end; +$$; + +-- --------------------------------------------------------------------------- +-- Tabular reviews +-- --------------------------------------------------------------------------- + +create table if not exists public.tabular_reviews ( + id uuid primary key default gen_random_uuid(), + project_id uuid references public.projects(id) on delete cascade, + user_id text not null, + title text, + columns_config jsonb, + workflow_id uuid references public.workflows(id) on delete set null, + practice text, + shared_with jsonb not null default '[]'::jsonb, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now() +); + +create index if not exists idx_tabular_reviews_user + on public.tabular_reviews(user_id); + +create index if not exists idx_tabular_reviews_project + on public.tabular_reviews(project_id); + +create index if not exists tabular_reviews_shared_with_idx + on public.tabular_reviews using gin (shared_with); + +create table if not exists public.tabular_cells ( + id uuid primary key default gen_random_uuid(), + review_id uuid not null references public.tabular_reviews(id) on delete cascade, + document_id uuid not null references public.documents(id) on delete cascade, + column_index integer not null, + content text, + citations jsonb, + status text not null default 'pending', + created_at timestamptz not null default now() +); + +create index if not exists idx_tabular_cells_review + on public.tabular_cells(review_id, document_id, column_index); + +create table if not exists public.tabular_review_chats ( + id uuid primary key default gen_random_uuid(), + review_id uuid not null references public.tabular_reviews(id) on delete cascade, + user_id text not null, + title text, + created_at timestamptz not null default now(), + updated_at timestamptz not null default now() +); + +create index if not exists tabular_review_chats_review_idx + on public.tabular_review_chats(review_id, updated_at desc); + +create index if not exists tabular_review_chats_user_idx + on public.tabular_review_chats(user_id); + +create table if not exists public.tabular_review_chat_messages ( + id uuid primary key default gen_random_uuid(), + chat_id uuid not null references public.tabular_review_chats(id) on delete cascade, + role text not null, + content jsonb, + annotations jsonb, + created_at timestamptz not null default now() +); + +create index if not exists tabular_review_chat_messages_chat_idx + on public.tabular_review_chat_messages(chat_id, created_at); + +-- --------------------------------------------------------------------------- +-- Row-level security +-- --------------------------------------------------------------------------- + +create or replace function public.current_user_id_text() +returns text +language sql +stable +set search_path = public, auth +as $$ + select auth.uid()::text; +$$; + +create or replace function public.current_user_email() +returns text +language sql +stable +set search_path = public, auth +as $$ + select lower(coalesce(auth.jwt() ->> 'email', '')); +$$; + +create or replace function public.email_is_shared(shared_with jsonb) +returns boolean +language sql +stable +set search_path = public +as $$ + select public.current_user_email() <> '' + and exists ( + select 1 + from jsonb_array_elements_text(coalesce(shared_with, '[]'::jsonb)) as emails(email) + where lower(emails.email) = public.current_user_email() + ); +$$; + +create or replace function public.project_is_accessible(target_project_id uuid) +returns boolean +language sql +stable +security definer +set search_path = public, auth +as $$ + select exists ( + select 1 + from public.projects p + where p.id = target_project_id + and ( + p.user_id = public.current_user_id_text() + or public.email_is_shared(p.shared_with) + ) + ); +$$; + +create or replace function public.review_is_accessible(target_review_id uuid) +returns boolean +language sql +stable +security definer +set search_path = public, auth +as $$ + select exists ( + select 1 + from public.tabular_reviews r + where r.id = target_review_id + and ( + r.user_id = public.current_user_id_text() + or public.email_is_shared(r.shared_with) + or ( + r.project_id is not null + and public.project_is_accessible(r.project_id) + ) + ) + ); +$$; + +create or replace function public.workflow_can_view(target_workflow_id uuid) +returns boolean +language sql +stable +security definer +set search_path = public, auth +as $$ + select exists ( + select 1 + from public.workflows w + where w.id = target_workflow_id + and ( + w.is_system + or w.user_id = public.current_user_id_text() + or exists ( + select 1 + from public.workflow_shares s + where s.workflow_id = w.id + and s.shared_with_email = public.current_user_email() + ) + ) + ); +$$; + +create or replace function public.workflow_can_edit(target_workflow_id uuid) +returns boolean +language sql +stable +security definer +set search_path = public, auth +as $$ + select exists ( + select 1 + from public.workflows w + where w.id = target_workflow_id + and ( + w.user_id = public.current_user_id_text() + or exists ( + select 1 + from public.workflow_shares s + where s.workflow_id = w.id + and s.shared_with_email = public.current_user_email() + and s.allow_edit + ) + ) + ); +$$; + +alter table public.user_profiles enable row level security; +alter table public.user_api_keys enable row level security; +alter table public.projects enable row level security; +alter table public.project_subfolders enable row level security; +alter table public.documents enable row level security; +alter table public.document_versions enable row level security; +alter table public.document_edits enable row level security; +alter table public.workflows enable row level security; +alter table public.hidden_workflows enable row level security; +alter table public.workflow_shares enable row level security; +alter table public.chats enable row level security; +alter table public.chat_messages enable row level security; +alter table public.tabular_reviews enable row level security; +alter table public.tabular_cells enable row level security; +alter table public.tabular_review_chats enable row level security; +alter table public.tabular_review_chat_messages enable row level security; + +drop policy if exists "Users can insert their own profile" on public.user_profiles; +create policy "Users can insert their own profile" + on public.user_profiles for insert + with check (auth.uid() = user_id); + +drop policy if exists "Users can view their own profile" on public.user_profiles; +create policy "Users can view their own profile" + on public.user_profiles for select + using (auth.uid() = user_id); + +drop policy if exists "Users can update their own profile" on public.user_profiles; +create policy "Users can update their own profile" + on public.user_profiles for update + using (auth.uid() = user_id) + with check (auth.uid() = user_id); + +-- user_api_keys is intentionally service-role only. The browser can only see +-- key status through backend routes, never encrypted key material. + +drop policy if exists "Users can view accessible projects" on public.projects; +create policy "Users can view accessible projects" + on public.projects for select + using ( + user_id = public.current_user_id_text() + or public.email_is_shared(shared_with) + ); + +drop policy if exists "Users can insert their own projects" on public.projects; +create policy "Users can insert their own projects" + on public.projects for insert + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Owners can update projects" on public.projects; +create policy "Owners can update projects" + on public.projects for update + using (user_id = public.current_user_id_text()) + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Owners can delete projects" on public.projects; +create policy "Owners can delete projects" + on public.projects for delete + using (user_id = public.current_user_id_text()); + +drop policy if exists "Users can view accessible project folders" on public.project_subfolders; +create policy "Users can view accessible project folders" + on public.project_subfolders for select + using ( + user_id = public.current_user_id_text() + or public.project_is_accessible(project_id) + ); + +drop policy if exists "Users can insert their own project folders" on public.project_subfolders; +create policy "Users can insert their own project folders" + on public.project_subfolders for insert + with check ( + user_id = public.current_user_id_text() + and public.project_is_accessible(project_id) + ); + +drop policy if exists "Owners can update project folders" on public.project_subfolders; +create policy "Owners can update project folders" + on public.project_subfolders for update + using (user_id = public.current_user_id_text()) + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Owners can delete project folders" on public.project_subfolders; +create policy "Owners can delete project folders" + on public.project_subfolders for delete + using (user_id = public.current_user_id_text()); + +drop policy if exists "Users can view accessible documents" on public.documents; +create policy "Users can view accessible documents" + on public.documents for select + using ( + user_id = public.current_user_id_text() + or ( + project_id is not null + and public.project_is_accessible(project_id) + ) + ); + +drop policy if exists "Users can insert their own documents" on public.documents; +create policy "Users can insert their own documents" + on public.documents for insert + with check ( + user_id = public.current_user_id_text() + and ( + project_id is null + or public.project_is_accessible(project_id) + ) + ); + +drop policy if exists "Owners can update documents" on public.documents; +create policy "Owners can update documents" + on public.documents for update + using (user_id = public.current_user_id_text()) + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Owners can delete documents" on public.documents; +create policy "Owners can delete documents" + on public.documents for delete + using (user_id = public.current_user_id_text()); + +drop policy if exists "Users can view accessible document versions" on public.document_versions; +create policy "Users can view accessible document versions" + on public.document_versions for select + using ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and ( + d.user_id = public.current_user_id_text() + or ( + d.project_id is not null + and public.project_is_accessible(d.project_id) + ) + ) + ) + ); + +drop policy if exists "Document owners can insert versions" on public.document_versions; +create policy "Document owners can insert versions" + on public.document_versions for insert + with check ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and d.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Document owners can update versions" on public.document_versions; +create policy "Document owners can update versions" + on public.document_versions for update + using ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and d.user_id = public.current_user_id_text() + ) + ) + with check ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and d.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Document owners can delete versions" on public.document_versions; +create policy "Document owners can delete versions" + on public.document_versions for delete + using ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and d.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Users can view accessible document edits" on public.document_edits; +create policy "Users can view accessible document edits" + on public.document_edits for select + using ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and ( + d.user_id = public.current_user_id_text() + or ( + d.project_id is not null + and public.project_is_accessible(d.project_id) + ) + ) + ) + ); + +drop policy if exists "Document owners can insert edits" on public.document_edits; +create policy "Document owners can insert edits" + on public.document_edits for insert + with check ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and d.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Document owners can update edits" on public.document_edits; +create policy "Document owners can update edits" + on public.document_edits for update + using ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and d.user_id = public.current_user_id_text() + ) + ) + with check ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and d.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Document owners can delete edits" on public.document_edits; +create policy "Document owners can delete edits" + on public.document_edits for delete + using ( + exists ( + select 1 + from public.documents d + where d.id = document_id + and d.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Users can view accessible workflows" on public.workflows; +create policy "Users can view accessible workflows" + on public.workflows for select + using (public.workflow_can_view(id)); + +drop policy if exists "Users can insert their own workflows" on public.workflows; +create policy "Users can insert their own workflows" + on public.workflows for insert + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Workflow owners can update workflows" on public.workflows; +create policy "Workflow owners can update workflows" + on public.workflows for update + using (user_id = public.current_user_id_text()) + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Workflow owners can delete workflows" on public.workflows; +create policy "Workflow owners can delete workflows" + on public.workflows for delete + using (user_id = public.current_user_id_text()); + +drop policy if exists "Users can manage their hidden workflows" on public.hidden_workflows; +create policy "Users can manage their hidden workflows" + on public.hidden_workflows for all + using (user_id = public.current_user_id_text()) + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Users can view relevant workflow shares" on public.workflow_shares; +create policy "Users can view relevant workflow shares" + on public.workflow_shares for select + using ( + shared_by_user_id = public.current_user_id_text() + or shared_with_email = public.current_user_email() + ); + +drop policy if exists "Workflow owners can insert shares" on public.workflow_shares; +create policy "Workflow owners can insert shares" + on public.workflow_shares for insert + with check ( + shared_by_user_id = public.current_user_id_text() + and exists ( + select 1 + from public.workflows w + where w.id = workflow_id + and w.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Workflow owners can update shares" on public.workflow_shares; +create policy "Workflow owners can update shares" + on public.workflow_shares for update + using (shared_by_user_id = public.current_user_id_text()) + with check (shared_by_user_id = public.current_user_id_text()); + +drop policy if exists "Workflow owners can delete shares" on public.workflow_shares; +create policy "Workflow owners can delete shares" + on public.workflow_shares for delete + using (shared_by_user_id = public.current_user_id_text()); + +drop policy if exists "Users can view accessible chats" on public.chats; +create policy "Users can view accessible chats" + on public.chats for select + using ( + user_id = public.current_user_id_text() + or ( + project_id is not null + and public.project_is_accessible(project_id) + ) + ); + +drop policy if exists "Users can insert their own chats" on public.chats; +create policy "Users can insert their own chats" + on public.chats for insert + with check ( + user_id = public.current_user_id_text() + and ( + project_id is null + or public.project_is_accessible(project_id) + ) + ); + +drop policy if exists "Chat owners can update chats" on public.chats; +create policy "Chat owners can update chats" + on public.chats for update + using (user_id = public.current_user_id_text()) + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Chat owners can delete chats" on public.chats; +create policy "Chat owners can delete chats" + on public.chats for delete + using (user_id = public.current_user_id_text()); + +drop policy if exists "Users can view accessible chat messages" on public.chat_messages; +create policy "Users can view accessible chat messages" + on public.chat_messages for select + using ( + exists ( + select 1 + from public.chats c + where c.id = chat_id + and ( + c.user_id = public.current_user_id_text() + or ( + c.project_id is not null + and public.project_is_accessible(c.project_id) + ) + ) + ) + ); + +drop policy if exists "Chat owners can insert messages" on public.chat_messages; +create policy "Chat owners can insert messages" + on public.chat_messages for insert + with check ( + exists ( + select 1 + from public.chats c + where c.id = chat_id + and c.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Chat owners can update messages" on public.chat_messages; +create policy "Chat owners can update messages" + on public.chat_messages for update + using ( + exists ( + select 1 + from public.chats c + where c.id = chat_id + and c.user_id = public.current_user_id_text() + ) + ) + with check ( + exists ( + select 1 + from public.chats c + where c.id = chat_id + and c.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Chat owners can delete messages" on public.chat_messages; +create policy "Chat owners can delete messages" + on public.chat_messages for delete + using ( + exists ( + select 1 + from public.chats c + where c.id = chat_id + and c.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Users can view accessible tabular reviews" on public.tabular_reviews; +create policy "Users can view accessible tabular reviews" + on public.tabular_reviews for select + using ( + user_id = public.current_user_id_text() + or public.email_is_shared(shared_with) + or ( + project_id is not null + and public.project_is_accessible(project_id) + ) + ); + +drop policy if exists "Users can insert their own tabular reviews" on public.tabular_reviews; +create policy "Users can insert their own tabular reviews" + on public.tabular_reviews for insert + with check ( + user_id = public.current_user_id_text() + and ( + project_id is null + or public.project_is_accessible(project_id) + ) + ); + +drop policy if exists "Review owners can update tabular reviews" on public.tabular_reviews; +create policy "Review owners can update tabular reviews" + on public.tabular_reviews for update + using (user_id = public.current_user_id_text()) + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Review owners can delete tabular reviews" on public.tabular_reviews; +create policy "Review owners can delete tabular reviews" + on public.tabular_reviews for delete + using (user_id = public.current_user_id_text()); + +drop policy if exists "Users can view accessible tabular cells" on public.tabular_cells; +create policy "Users can view accessible tabular cells" + on public.tabular_cells for select + using (public.review_is_accessible(review_id)); + +drop policy if exists "Review owners can insert tabular cells" on public.tabular_cells; +create policy "Review owners can insert tabular cells" + on public.tabular_cells for insert + with check ( + exists ( + select 1 + from public.tabular_reviews r + where r.id = review_id + and r.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Review owners can update tabular cells" on public.tabular_cells; +create policy "Review owners can update tabular cells" + on public.tabular_cells for update + using ( + exists ( + select 1 + from public.tabular_reviews r + where r.id = review_id + and r.user_id = public.current_user_id_text() + ) + ) + with check ( + exists ( + select 1 + from public.tabular_reviews r + where r.id = review_id + and r.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Review owners can delete tabular cells" on public.tabular_cells; +create policy "Review owners can delete tabular cells" + on public.tabular_cells for delete + using ( + exists ( + select 1 + from public.tabular_reviews r + where r.id = review_id + and r.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Users can view accessible tabular review chats" on public.tabular_review_chats; +create policy "Users can view accessible tabular review chats" + on public.tabular_review_chats for select + using ( + user_id = public.current_user_id_text() + or public.review_is_accessible(review_id) + ); + +drop policy if exists "Users can insert their own tabular review chats" on public.tabular_review_chats; +create policy "Users can insert their own tabular review chats" + on public.tabular_review_chats for insert + with check ( + user_id = public.current_user_id_text() + and public.review_is_accessible(review_id) + ); + +drop policy if exists "Tabular chat owners can update chats" on public.tabular_review_chats; +create policy "Tabular chat owners can update chats" + on public.tabular_review_chats for update + using (user_id = public.current_user_id_text()) + with check (user_id = public.current_user_id_text()); + +drop policy if exists "Tabular chat owners can delete chats" on public.tabular_review_chats; +create policy "Tabular chat owners can delete chats" + on public.tabular_review_chats for delete + using (user_id = public.current_user_id_text()); + +drop policy if exists "Users can view accessible tabular chat messages" on public.tabular_review_chat_messages; +create policy "Users can view accessible tabular chat messages" + on public.tabular_review_chat_messages for select + using ( + exists ( + select 1 + from public.tabular_review_chats c + where c.id = chat_id + and ( + c.user_id = public.current_user_id_text() + or public.review_is_accessible(c.review_id) + ) + ) + ); + +drop policy if exists "Tabular chat owners can insert messages" on public.tabular_review_chat_messages; +create policy "Tabular chat owners can insert messages" + on public.tabular_review_chat_messages for insert + with check ( + exists ( + select 1 + from public.tabular_review_chats c + where c.id = chat_id + and c.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Tabular chat owners can update messages" on public.tabular_review_chat_messages; +create policy "Tabular chat owners can update messages" + on public.tabular_review_chat_messages for update + using ( + exists ( + select 1 + from public.tabular_review_chats c + where c.id = chat_id + and c.user_id = public.current_user_id_text() + ) + ) + with check ( + exists ( + select 1 + from public.tabular_review_chats c + where c.id = chat_id + and c.user_id = public.current_user_id_text() + ) + ); + +drop policy if exists "Tabular chat owners can delete messages" on public.tabular_review_chat_messages; +create policy "Tabular chat owners can delete messages" + on public.tabular_review_chat_messages for delete + using ( + exists ( + select 1 + from public.tabular_review_chats c + where c.id = chat_id + and c.user_id = public.current_user_id_text() + ) + ); diff --git a/backend/src/index.ts b/backend/src/index.ts index 0e99fff..07b3b84 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -1,6 +1,8 @@ import "dotenv/config"; import express from "express"; import cors from "cors"; +import helmet from "helmet"; +import rateLimit from "express-rate-limit"; import { chatRouter } from "./routes/chat"; import { projectsRouter } from "./routes/projects"; import { projectChatRouter } from "./routes/projectChat"; @@ -12,6 +14,79 @@ import { downloadsRouter } from "./routes/downloads"; const app = express(); const PORT = process.env.PORT ?? 3001; +const isProduction = process.env.NODE_ENV === "production"; + +function envInt(name: string, fallback: number): number { + const raw = process.env[name]; + if (!raw) return fallback; + const parsed = Number.parseInt(raw, 10); + return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback; +} + +function minutes(value: number): number { + return value * 60 * 1000; +} + +function hours(value: number): number { + return minutes(value * 60); +} + +function makeLimiter(options: { + windowMs: number; + max: number; + message?: string; +}) { + return rateLimit({ + windowMs: options.windowMs, + max: options.max, + standardHeaders: true, + legacyHeaders: false, + skip: (req) => req.method === "OPTIONS", + message: { + detail: + options.message ?? "Too many requests. Please try again later.", + }, + }); +} + +const generalLimiter = makeLimiter({ + windowMs: minutes(envInt("RATE_LIMIT_GENERAL_WINDOW_MINUTES", 15)), + max: envInt("RATE_LIMIT_GENERAL_MAX", 300), +}); + +const chatLimiter = makeLimiter({ + windowMs: minutes(envInt("RATE_LIMIT_CHAT_WINDOW_MINUTES", 15)), + max: envInt("RATE_LIMIT_CHAT_MAX", 30), + message: "Too many chat requests. Please try again later.", +}); + +const chatCreateLimiter = makeLimiter({ + windowMs: minutes(envInt("RATE_LIMIT_CHAT_CREATE_WINDOW_MINUTES", 15)), + max: envInt("RATE_LIMIT_CHAT_CREATE_MAX", 60), +}); + +const uploadLimiter = makeLimiter({ + windowMs: hours(envInt("RATE_LIMIT_UPLOAD_WINDOW_HOURS", 1)), + max: envInt("RATE_LIMIT_UPLOAD_MAX", 50), + message: "Too many upload requests. Please try again later.", +}); + +app.disable("x-powered-by"); +app.set("trust proxy", envInt("TRUST_PROXY_HOPS", 1)); + +app.use( + helmet({ + contentSecurityPolicy: false, + crossOriginEmbedderPolicy: false, + hsts: isProduction + ? { + maxAge: 15552000, + includeSubDomains: true, + } + : false, + referrerPolicy: { policy: "no-referrer" }, + }), +); app.use( cors({ @@ -20,8 +95,20 @@ app.use( }), ); +app.use(generalLimiter); + app.use(express.json({ limit: "50mb" })); +app.post("/chat", chatLimiter); +app.post("/projects/:projectId/chat", chatLimiter); +app.post("/tabular-review/:reviewId/chat", chatLimiter); +app.post("/tabular-review/:reviewId/generate", chatLimiter); +app.post("/chat/create", chatCreateLimiter); +app.post("/chat/:chatId/generate-title", chatCreateLimiter); +app.post("/single-documents", uploadLimiter); +app.post("/single-documents/:documentId/versions", uploadLimiter); +app.post("/projects/:projectId/documents", uploadLimiter); + app.use("/chat", chatRouter); app.use("/projects", projectsRouter); app.use("/projects/:projectId/chat", projectChatRouter); diff --git a/backend/src/lib/chatTools.ts b/backend/src/lib/chatTools.ts index c3ab243..d2a2491 100644 --- a/backend/src/lib/chatTools.ts +++ b/backend/src/lib/chatTools.ts @@ -13,7 +13,10 @@ import { type EditInput, } from "./docxTrackedChanges"; import { buildDownloadUrl } from "./downloadTokens"; -import { attachActiveVersionPaths, loadActiveVersion } from "./documentVersions"; +import { + attachActiveVersionPaths, + loadActiveVersion, +} from "./documentVersions"; import { streamChatWithTools, resolveModel, @@ -56,7 +59,10 @@ export type TabularCellStore = { columns: { index: number; name: string }[]; documents: { id: string; filename: string }[]; /** key: `${colIndex}:${docId}` */ - cells: Map; + cells: Map< + string, + { summary: string; flag?: string; reasoning?: string } | null + >; }; export type ToolCall = { @@ -320,25 +326,43 @@ export const TOOLS = [ properties: { title: { type: "string", - description: "Document title (used as filename and heading)", + description: + "Document title (used as filename and heading)", }, landscape: { type: "boolean", - description: "Set to true for landscape page orientation. Default is portrait.", + description: + "Set to true for landscape page orientation. Default is portrait.", }, sections: { type: "array", - description: "List of document sections. Each section may contain a heading, prose content, or a table.", + description: + "List of document sections. Each section may contain a heading, prose content, or a table.", items: { type: "object", properties: { - heading: { type: "string", description: "Optional section heading" }, - level: { type: "integer", description: "Heading level: 1, 2, or 3" }, - content: { type: "string", description: "Prose text content (paragraphs separated by double newlines)" }, - pageBreak: { type: "boolean", description: "Set to true to start this section on a new page. Use for contract signature pages." }, + heading: { + type: "string", + description: "Optional section heading", + }, + level: { + type: "integer", + description: "Heading level: 1, 2, or 3", + }, + content: { + type: "string", + description: + "Prose text content (paragraphs separated by double newlines)", + }, + pageBreak: { + type: "boolean", + description: + "Set to true to start this section on a new page. Use for contract signature pages.", + }, table: { type: "object", - description: "Optional table to render in this section", + description: + "Optional table to render in this section", properties: { headers: { type: "array", @@ -351,7 +375,8 @@ export const TOOLS = [ type: "array", items: { type: "string" }, }, - description: "Array of rows, each row is an array of cell strings matching the headers order", + description: + "Array of rows, each row is an array of cell strings matching the headers order", }, }, required: ["headers", "rows"], @@ -390,22 +415,31 @@ export const TOOLS = [ }, replace: { type: "string", - description: "Replacement text. Empty string = pure deletion.", + description: + "Replacement text. Empty string = pure deletion.", }, context_before: { type: "string", - description: "~40 chars immediately preceding `find`, used to disambiguate.", + description: + "~40 chars immediately preceding `find`, used to disambiguate.", }, context_after: { type: "string", - description: "~40 chars immediately following `find`.", + description: + "~40 chars immediately following `find`.", }, reason: { type: "string", - description: "Short explanation shown to the user on the card.", + description: + "Short explanation shown to the user on the card.", }, }, - required: ["find", "replace", "context_before", "context_after"], + required: [ + "find", + "replace", + "context_before", + "context_after", + ], }, }, }, @@ -578,7 +612,11 @@ export async function enrichWithPriorEvents( export function buildMessages( messages: ChatMessage[], - docAvailability: { doc_id: string; filename: string; folder_path?: string }[], + docAvailability: { + doc_id: string; + filename: string; + folder_path?: string; + }[], systemPromptExtra?: string, docIndex?: DocIndex, ) { @@ -592,7 +630,9 @@ export function buildMessages( if (docAvailability.length) { systemContent += "\n\n---\nAVAILABLE DOCUMENTS:\n"; for (const doc of docAvailability) { - const label = doc.folder_path ? `${doc.folder_path} / ${doc.filename}` : doc.filename; + const label = doc.folder_path + ? `${doc.folder_path} / ${doc.filename}` + : doc.filename; systemContent += `- ${doc.doc_id}: ${label}\n`; } systemContent += @@ -620,9 +660,7 @@ export function buildMessages( const slug = f.document_id ? slugByDocumentId.get(f.document_id) : undefined; - return slug - ? `- ${slug}: ${f.filename}` - : `- ${f.filename}`; + return slug ? `- ${slug}: ${f.filename}` : `- ${f.filename}`; }); content = `[The user attached the following document(s) to this message:\n${lines.join("\n")}]\n\n${content}`; } @@ -676,30 +714,50 @@ export async function generateDocx( ) { try { const { - Document, Paragraph, HeadingLevel, Packer, - Table, TableRow, TableCell, WidthType, BorderStyle, - TextRun, AlignmentType, PageOrientation, PageBreak, + Document, + Paragraph, + HeadingLevel, + Packer, + Table, + TableRow, + TableCell, + WidthType, + BorderStyle, + TextRun, + AlignmentType, + PageOrientation, + PageBreak, } = await import("docx"); const FONT = "Times New Roman"; const SIZE = 22; // 11pt in half-points - type DocChild = InstanceType | InstanceType; + type DocChild = + | InstanceType + | InstanceType; const children: DocChild[] = []; children.push( new Paragraph({ heading: HeadingLevel.TITLE, spacing: { after: 200 }, alignment: AlignmentType.CENTER, - children: [new TextRun({ text: title.toUpperCase(), color: "000000", font: FONT, size: SIZE, bold: true })], + children: [ + new TextRun({ + text: title.toUpperCase(), + color: "000000", + font: FONT, + size: SIZE, + bold: true, + }), + ], }), ); const cellBorder = { - top: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }, + top: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }, bottom: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }, - left: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }, - right: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }, + left: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }, + right: { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" }, }; const headingLevels = [ @@ -718,9 +776,7 @@ export async function generateDocx( table?: { headers: string[]; rows: string[][] }; }[]) { if (section.pageBreak) { - children.push( - new Paragraph({ children: [new PageBreak()] }), - ); + children.push(new Paragraph({ children: [new PageBreak()] })); } if (section.heading) { const idx = Math.min((section.level ?? 1) - 1, 3); @@ -732,7 +788,15 @@ export async function generateDocx( new Paragraph({ heading: headingLevels[idx], spacing: { after: 160 }, - children: [new TextRun({ text: headingText, color: "000000", font: FONT, size: SIZE, bold: true })], + children: [ + new TextRun({ + text: headingText, + color: "000000", + font: FONT, + size: SIZE, + bold: true, + }), + ], }), ); } @@ -751,7 +815,14 @@ export async function generateDocx( shading: { fill: "F2F2F2" }, children: [ new Paragraph({ - children: [new TextRun({ text: h, bold: true, font: FONT, size: SIZE })], + children: [ + new TextRun({ + text: h, + bold: true, + font: FONT, + size: SIZE, + }), + ], alignment: AlignmentType.LEFT, }), ], @@ -784,7 +855,13 @@ export async function generateDocx( borders: cellBorder, children: [ new Paragraph({ - children: [new TextRun({ text: cell, font: FONT, size: SIZE })], + children: [ + new TextRun({ + text: cell, + font: FONT, + size: SIZE, + }), + ], }), ], }), @@ -810,14 +887,26 @@ export async function generateDocx( new Paragraph({ bullet: { level: 0 }, spacing: { after: 120 }, - children: [new TextRun({ text: bulletMatch[1], font: FONT, size: SIZE })], + children: [ + new TextRun({ + text: bulletMatch[1], + font: FONT, + size: SIZE, + }), + ], }), ); } else { children.push( new Paragraph({ spacing: { after: 120 }, - children: [new TextRun({ text: trimmed, font: FONT, size: SIZE })], + children: [ + new TextRun({ + text: trimmed, + font: FONT, + size: SIZE, + }), + ], }), ); } @@ -829,7 +918,9 @@ export async function generateDocx( ? { page: { size: { orientation: PageOrientation.LANDSCAPE } } } : {}; - const doc = new Document({ sections: [{ properties: pageSetup, children }] }); + const doc = new Document({ + sections: [{ properties: pageSetup, children }], + }); const buf = await Packer.toBuffer(doc); const docId = crypto.randomUUID().replace(/-/g, ""); const safeTitle = @@ -973,11 +1064,11 @@ export async function runEditDocument(params: { const current = await loadCurrentVersionBytes(documentId, db); if (!current) return { ok: false, error: "Could not load document bytes." }; - const { bytes: editedBytes, changes, errors } = await applyTrackedEdits( - current.bytes, - edits, - { author: "Mike" }, - ); + const { + bytes: editedBytes, + changes, + errors, + } = await applyTrackedEdits(current.bytes, edits, { author: "Mike" }); if (changes.length === 0) { return { @@ -1028,7 +1119,8 @@ export async function runEditDocument(params: { .order("version_number", { ascending: false, nullsFirst: false }) .limit(1) .maybeSingle(); - nextVersionNumber = ((maxRow?.version_number as number | null) ?? 1) + 1; + nextVersionNumber = + ((maxRow?.version_number as number | null) ?? 1) + 1; // Inherit the display name from the most recent prior version so // user-applied renames carry forward through further edits. Falls @@ -1081,7 +1173,9 @@ export async function runEditDocument(params: { const { data: insertedEdits, error: editsErr } = await db .from("document_edits") .insert(editRows) - .select("id, change_id, del_w_id, ins_w_id, deleted_text, inserted_text, context_before, context_after"); + .select( + "id, change_id, del_w_id, ins_w_id, deleted_text, inserted_text, context_before, context_after", + ); if (editsErr || !insertedEdits) { return { ok: false, error: "Failed to record edits." }; @@ -1092,25 +1186,34 @@ export async function runEditDocument(params: { .update({ current_version_id: versionRowId }) .eq("id", documentId); - const annotations: EditAnnotation[] = insertedEdits.map((r: { id: string; change_id: string; deleted_text: string; inserted_text: string; context_before: string | null; context_after: string | null }) => { - const src = changes.find((c) => c.id === r.change_id); - return { - kind: "edit", - edit_id: r.id, - document_id: documentId, - version_id: versionRowId, - version_number: nextVersionNumber, - change_id: r.change_id, - del_w_id: src?.delId, - ins_w_id: src?.insId, - deleted_text: r.deleted_text ?? "", - inserted_text: r.inserted_text ?? "", - context_before: r.context_before ?? "", - context_after: r.context_after ?? "", - reason: src?.reason, - status: "pending", - }; - }); + const annotations: EditAnnotation[] = insertedEdits.map( + (r: { + id: string; + change_id: string; + deleted_text: string; + inserted_text: string; + context_before: string | null; + context_after: string | null; + }) => { + const src = changes.find((c) => c.id === r.change_id); + return { + kind: "edit", + edit_id: r.id, + document_id: documentId, + version_id: versionRowId, + version_number: nextVersionNumber, + change_id: r.change_id, + del_w_id: src?.delId, + ins_w_id: src?.insId, + deleted_text: r.deleted_text ?? "", + inserted_text: r.inserted_text ?? "", + context_before: r.context_before ?? "", + context_after: r.context_after ?? "", + reason: src?.reason, + status: "pending", + }; + }, + ); // Persistent, non-expiring permalink. The backend streams fresh bytes // on each request, so this URL stays valid as long as the file exists. @@ -1216,9 +1319,7 @@ async function readDocumentContent( { const head = Buffer.from(raw).subarray(0, 8); const hex = head.toString("hex"); - const ascii = head - .toString("binary") - .replace(/[^\x20-\x7e]/g, "."); + const ascii = head.toString("binary").replace(/[^\x20-\x7e]/g, "."); console.log( `[read_document] magic bytes hex=${hex} ascii="${ascii}" for filename="${docInfo.filename}"`, ); @@ -1273,7 +1374,9 @@ async function readDocumentContent( err, ); if (emitEvents) - write(`data: ${JSON.stringify({ type: "doc_read", filename: docInfo.filename })}\n\n`); + write( + `data: ${JSON.stringify({ type: "doc_read", filename: docInfo.filename })}\n\n`, + ); return "Document could not be read."; } } @@ -1385,7 +1488,10 @@ async function findInDocumentContent(params: { const { norm, origIdx } = normalizeWithMap(text); const needle = normalizeQuery(query); if (!needle) { - return JSON.stringify({ ok: false, error: "Empty query after normalization." }); + return JSON.stringify({ + ok: false, + error: "Empty query after normalization.", + }); } type Hit = { @@ -1528,19 +1634,30 @@ export async function runToolCalls( const rawDocId = args.doc_id as string; const docId = resolveDocLabel(rawDocId, docStore, docIndex) ?? rawDocId; - const content = await readDocumentContent(docId, docStore, write, docIndex, db); + const content = await readDocumentContent( + docId, + docStore, + write, + docIndex, + db, + ); const filename = docStore.get(docId)?.filename; const documentId = docIndex?.[docId]?.document_id; if (filename) docsRead.push({ filename, document_id: documentId }); toolResults.push({ role: "tool", tool_call_id: tc.id, content }); - } else if (tc.function.name === "find_in_document") { const rawDocId = args.doc_id as string; const docId = resolveDocLabel(rawDocId, docStore, docIndex) ?? rawDocId; const query = (args.query as string) ?? ""; - const maxResults = typeof args.max_results === "number" ? args.max_results : undefined; - const contextChars = typeof args.context_chars === "number" ? args.context_chars : undefined; + const maxResults = + typeof args.max_results === "number" + ? args.max_results + : undefined; + const contextChars = + typeof args.context_chars === "number" + ? args.context_chars + : undefined; const content = await findInDocumentContent({ docLabel: docId, query, @@ -1569,7 +1686,6 @@ export async function runToolCalls( }); } toolResults.push({ role: "tool", tool_call_id: tc.id, content }); - } else if (tc.function.name === "list_documents") { const list = Array.from(docStore.entries()).map( ([doc_id, info]) => ({ @@ -1583,7 +1699,6 @@ export async function runToolCalls( tool_call_id: tc.id, content: JSON.stringify(list), }); - } else if (tc.function.name === "fetch_documents") { const rawDocIds = (args.doc_ids as string[]) ?? []; const docIds = rawDocIds.map( @@ -1591,7 +1706,13 @@ export async function runToolCalls( ); const parts: string[] = []; for (const docId of docIds) { - const content = await readDocumentContent(docId, docStore, write, docIndex, db); + const content = await readDocumentContent( + docId, + docStore, + write, + docIndex, + db, + ); const filename = docStore.get(docId)?.filename ?? docId; parts.push(`--- ${filename} (${docId}) ---\n${content}`); if (docStore.get(docId)) { @@ -1604,18 +1725,25 @@ export async function runToolCalls( tool_call_id: tc.id, content: parts.join("\n\n"), }); - } else if (tc.function.name === "list_workflows") { const list = workflowStore - ? Array.from(workflowStore.entries()).map(([id, w]) => ({ id, title: w.title })) + ? Array.from(workflowStore.entries()).map(([id, w]) => ({ + id, + title: w.title, + })) : []; - toolResults.push({ role: "tool", tool_call_id: tc.id, content: JSON.stringify(list) }); - + toolResults.push({ + role: "tool", + tool_call_id: tc.id, + content: JSON.stringify(list), + }); } else if (tc.function.name === "read_workflow") { const wfId = args.workflow_id as string; const wf = workflowStore?.get(wfId); if (wf) { - write(`data: ${JSON.stringify({ type: "workflow_applied", workflow_id: wfId, title: wf.title })}\n\n`); + write( + `data: ${JSON.stringify({ type: "workflow_applied", workflow_id: wfId, title: wf.title })}\n\n`, + ); workflowsApplied.push({ workflow_id: wfId, title: wf.title }); } toolResults.push({ @@ -1623,7 +1751,6 @@ export async function runToolCalls( tool_call_id: tc.id, content: wf ? wf.prompt_md : `Workflow '${wfId}' not found.`, }); - } else if (tc.function.name === "read_table_cells" && tabularStore) { const colIndices = args.col_indices as number[] | undefined; const rowIndices = args.row_indices as number[] | undefined; @@ -1632,23 +1759,36 @@ export async function runToolCalls( ? tabularStore.columns.filter((_, i) => colIndices.includes(i)) : tabularStore.columns; const filteredDocs = rowIndices?.length - ? tabularStore.documents.filter((_, i) => rowIndices.includes(i)) + ? tabularStore.documents.filter((_, i) => + rowIndices.includes(i), + ) : tabularStore.documents; const label = `${filteredCols.length} ${filteredCols.length === 1 ? "column" : "columns"} × ${filteredDocs.length} ${filteredDocs.length === 1 ? "row" : "rows"}`; - write(`data: ${JSON.stringify({ type: "doc_read_start", filename: label })}\n\n`); + write( + `data: ${JSON.stringify({ type: "doc_read_start", filename: label })}\n\n`, + ); const lines: string[] = []; for (const col of filteredCols) { - const colPos = tabularStore.columns.findIndex((c) => c.index === col.index); + const colPos = tabularStore.columns.findIndex( + (c) => c.index === col.index, + ); for (const doc of filteredDocs) { - const rowPos = tabularStore.documents.findIndex((d) => d.id === doc.id); - const cell = tabularStore.cells.get(`${col.index}:${doc.id}`); - lines.push(`[COL:${colPos} "${col.name}" | ROW:${rowPos} "${doc.filename}"]`); + const rowPos = tabularStore.documents.findIndex( + (d) => d.id === doc.id, + ); + const cell = tabularStore.cells.get( + `${col.index}:${doc.id}`, + ); + lines.push( + `[COL:${colPos} "${col.name}" | ROW:${rowPos} "${doc.filename}"]`, + ); if (cell?.summary) { lines.push(`Summary: ${cell.summary}`); if (cell.flag) lines.push(`Flag: ${cell.flag}`); - if (cell.reasoning) lines.push(`Reasoning: ${cell.reasoning}`); + if (cell.reasoning) + lines.push(`Reasoning: ${cell.reasoning}`); } else { lines.push(`(not yet generated)`); } @@ -1656,14 +1796,15 @@ export async function runToolCalls( } } - write(`data: ${JSON.stringify({ type: "doc_read", filename: label })}\n\n`); + write( + `data: ${JSON.stringify({ type: "doc_read", filename: label })}\n\n`, + ); docsRead.push({ filename: label }); toolResults.push({ role: "tool", tool_call_id: tc.id, content: lines.join("\n") || "No cells found.", }); - } else if (tc.function.name === "edit_document" && docIndex) { const rawDocId = args.doc_id as string; const editsRaw = args.edits as unknown[] | undefined; @@ -1707,10 +1848,7 @@ export async function runToolCalls( tool_call_id: tc.id, content: JSON.stringify({ error: err }), }); - } else if ( - !Array.isArray(editsRaw) || - editsRaw.length === 0 - ) { + } else if (!Array.isArray(editsRaw) || editsRaw.length === 0) { const err = "edits array is required and must not be empty."; emitEditError(docInfo.filename, indexed.document_id, err); toolResults.push({ @@ -1733,15 +1871,15 @@ export async function runToolCalls( filename: docInfo.filename, })}\n\n`, ); - const edits: EditInput[] = (editsRaw as Record[]).map( - (e) => ({ - find: String(e.find ?? ""), - replace: String(e.replace ?? ""), - context_before: String(e.context_before ?? ""), - context_after: String(e.context_after ?? ""), - reason: e.reason ? String(e.reason) : undefined, - }), - ); + const edits: EditInput[] = ( + editsRaw as Record[] + ).map((e) => ({ + find: String(e.find ?? ""), + replace: String(e.replace ?? ""), + context_before: String(e.context_before ?? ""), + context_after: String(e.context_after ?? ""), + reason: e.reason ? String(e.reason) : undefined, + })); const reuseVersion = turnEditState?.get(indexed.document_id); const result = await runEditDocument({ documentId: indexed.document_id, @@ -1824,7 +1962,6 @@ export async function runToolCalls( }); } } - } else if (tc.function.name === "replicate_document" && docIndex) { const rawDocId = args.doc_id as string; const requestedFilename = @@ -1933,7 +2070,11 @@ export async function runToolCalls( .from("documents") .insert(docRows) .select("id, filename"); - if (docErr || !insertedDocs || insertedDocs.length === 0) { + if ( + docErr || + !insertedDocs || + insertedDocs.length === 0 + ) { fail( `Failed to record replicated documents: ${docErr?.message ?? "unknown"}`, ); @@ -2008,7 +2149,10 @@ export async function runToolCalls( `Failed to record replicated document versions: ${verErr?.message ?? "unknown"}`, ); } else { - const versionByDocId = new Map(); + const versionByDocId = new Map< + string, + string + >(); for (const v of insertedVersions as { id: string; document_id: string; @@ -2119,13 +2263,21 @@ export async function runToolCalls( fail(`replicate_document failed: ${String(e)}`); } } - } else if (tc.function.name === "generate_docx") { const title = args.title as string; - const landscape = !!(args.landscape); - console.log(`[generate_docx] title="${title}" landscape=${landscape} args.landscape=${args.landscape}`); - const previewFilename = `${(title.replace(/[^a-zA-Z0-9 _-]/g, "").trim().slice(0, 64) || "document")}.docx`; - write(`data: ${JSON.stringify({ type: "doc_created_start", filename: previewFilename })}\n\n`); + const landscape = !!args.landscape; + console.log( + `[generate_docx] title="${title}" landscape=${landscape} args.landscape=${args.landscape}`, + ); + const previewFilename = `${ + title + .replace(/[^a-zA-Z0-9 _-]/g, "") + .trim() + .slice(0, 64) || "document" + }.docx`; + write( + `data: ${JSON.stringify({ type: "doc_created_start", filename: previewFilename })}\n\n`, + ); const result = await generateDocx( title, args.sections as unknown[], @@ -2137,10 +2289,15 @@ export async function runToolCalls( if ("filename" in result && "download_url" in result) { const dlFilename = result.filename as string; const dlUrl = result.download_url as string; - const documentId = (result as { document_id?: string }).document_id; - const versionId = (result as { version_id?: string }).version_id; - const versionNumber = (result as { version_number?: number }).version_number ?? null; - const storagePath = (result as { storage_path?: string }).storage_path; + const documentId = (result as { document_id?: string }) + .document_id; + const versionId = (result as { version_id?: string }) + .version_id; + const versionNumber = + (result as { version_number?: number }).version_number ?? + null; + const storagePath = (result as { storage_path?: string }) + .storage_path; // Register the generated doc in the chat context so // edit_document (and read_document / find_in_document) @@ -2181,14 +2338,19 @@ export async function runToolCalls( version_number: versionNumber, }); } else { - write(`data: ${JSON.stringify({ type: "doc_created", filename: previewFilename, download_url: "" })}\n\n`); + write( + `data: ${JSON.stringify({ type: "doc_created", filename: previewFilename, download_url: "" })}\n\n`, + ); } // Surface the chat-local doc label in the tool result so the // model can pass it as `doc_id` to edit_document / read_document // / find_in_document in the same turn. Without this the model // only sees the DB UUID, which isn't valid as a doc_id anchor. const toolResultPayload = newDocLabel - ? { ...(result as Record), doc_id: newDocLabel } + ? { + ...(result as Record), + doc_id: newDocLabel, + } : result; toolResults.push({ role: "tool", @@ -2313,7 +2475,21 @@ export async function runLLMStream(params: { */ projectId?: string | null; }): Promise<{ fullText: string; events: AssistantEvent[] }> { - const { apiMessages, docStore, docIndex, userId, db, write, extraTools, workflowStore, tabularStore, buildCitations, model, apiKeys, projectId } = params; + const { + apiMessages, + docStore, + docIndex, + userId, + db, + write, + extraTools, + workflowStore, + tabularStore, + buildCitations, + model, + apiKeys, + projectId, + } = params; const activeTools = extraTools?.length ? [...TOOLS, ...WORKFLOW_TOOLS, ...extraTools] : [...TOOLS, ...WORKFLOW_TOOLS]; @@ -2323,14 +2499,6 @@ export async function runLLMStream(params: { const rawMsgs = apiMessages as { role: string; content: string | null }[]; const systemPrompt = rawMsgs[0]?.role === "system" ? (rawMsgs[0].content ?? "") : ""; - console.log( - "[runLLMStream] system prompt:\n" + - "─".repeat(80) + - "\n" + - systemPrompt + - "\n" + - "─".repeat(80), - ); const chatMessages: LlmMessage[] = rawMsgs .filter((m) => m.role !== "system") .map((m) => ({ @@ -2473,17 +2641,17 @@ export async function runLLMStream(params: { workflowsApplied, docsEdited, } = await runToolCalls( - toolCalls, - docStore, - userId, - db, - write, - workflowStore, - tabularStore, - docIndex, - turnEditState, - projectId, - ); + toolCalls, + docStore, + userId, + db, + write, + workflowStore, + tabularStore, + docIndex, + turnEditState, + projectId, + ); for (const r of docsRead) { events.push({ type: "doc_read", @@ -2589,7 +2757,7 @@ export async function runLLMStream(params: { export function extractAnnotations( fullText: string, docIndex: DocIndex, - events?: { type: string } & Record[] | unknown[], + events?: ({ type: string } & Record[]) | unknown[], ): unknown[] { const out: unknown[] = parseCitations(fullText).map((c) => { const docInfo = resolveDoc(c.doc_id, docIndex); @@ -2606,9 +2774,13 @@ export function extractAnnotations( }; }); if (Array.isArray(events)) { - for (const ev of events as { type?: string; annotations?: EditAnnotation[] }[]) { + for (const ev of events as { + type?: string; + annotations?: EditAnnotation[]; + }[]) { if (ev?.type === "doc_edited" && Array.isArray(ev.annotations)) { - for (const a of ev.annotations) out.push({ ...a, type: "edit_data" }); + for (const a of ev.annotations) + out.push({ ...a, type: "edit_data" }); } } } @@ -2652,8 +2824,7 @@ export async function buildDocContext( if (!Array.isArray(content)) continue; for (const ev of content as Record[]) { if ( - (ev?.type === "doc_created" || - ev?.type === "doc_edited") && + (ev?.type === "doc_created" || ev?.type === "doc_edited") && typeof ev.document_id === "string" ) { documentIds.add(ev.document_id); @@ -2713,17 +2884,25 @@ export async function buildProjectDocContext( projectId: string, _userId: string, db: ReturnType, -): Promise<{ docIndex: DocIndex; docStore: DocStore; folderPaths: Map }> { +): Promise<{ + docIndex: DocIndex; + docStore: DocStore; + folderPaths: Map; +}> { const docIndex: DocIndex = {}; const docStore: DocStore = new Map(); const [{ data: docs }, { data: folders }] = await Promise.all([ - db.from("documents") - .select("id, filename, file_type, current_version_id, status, folder_id") + db + .from("documents") + .select( + "id, filename, file_type, current_version_id, status, folder_id", + ) .eq("project_id", projectId) .eq("status", "ready") .order("created_at", { ascending: true }), - db.from("project_subfolders") + db + .from("project_subfolders") .select("id, name, parent_folder_id") .eq("project_id", projectId), ]); @@ -2739,8 +2918,15 @@ export async function buildProjectDocContext( await attachActiveVersionPaths(db, docList); // Build folder id → full path map - const folderMap = new Map(); - for (const f of folders ?? []) folderMap.set(f.id, { name: f.name, parent_folder_id: f.parent_folder_id }); + const folderMap = new Map< + string, + { name: string; parent_folder_id: string | null } + >(); + for (const f of folders ?? []) + folderMap.set(f.id, { + name: f.name, + parent_folder_id: f.parent_folder_id, + }); function resolvePath(folderId: string | null): string { if (!folderId) return ""; @@ -2820,7 +3006,9 @@ export async function buildWorkflowStore( .from("workflow_shares") .select("workflow_id") .eq("shared_with_email", normalizedUserEmail); - const sharedIds = [...new Set((shares ?? []).map((share) => share.workflow_id))]; + const sharedIds = [ + ...new Set((shares ?? []).map((share) => share.workflow_id)), + ]; if (sharedIds.length > 0) { const { data: sharedWorkflows } = await db .from("workflows") @@ -2829,7 +3017,10 @@ export async function buildWorkflowStore( .eq("type", "assistant"); for (const wf of sharedWorkflows ?? []) { if (wf.prompt_md) { - store.set(wf.id, { title: wf.title, prompt_md: wf.prompt_md }); + store.set(wf.id, { + title: wf.title, + prompt_md: wf.prompt_md, + }); } } } diff --git a/backend/src/lib/llm/claude.ts b/backend/src/lib/llm/claude.ts index 9ed625e..0ecef37 100644 --- a/backend/src/lib/llm/claude.ts +++ b/backend/src/lib/llm/claude.ts @@ -1,7 +1,5 @@ import Anthropic from "@anthropic-ai/sdk"; import type { Tool } from "@anthropic-ai/sdk/resources/messages/messages"; -import * as fs from "fs"; -import * as path from "path"; import type { StreamChatParams, StreamChatResult, @@ -10,11 +8,6 @@ import type { } from "./types"; import { toClaudeTools } from "./tools"; -const RAW_STREAM_LOG_PATH = path.resolve( - process.cwd(), - "claude-raw-stream.log", -); - type ContentBlock = | { type: "text"; text: string } | { type: "tool_use"; id: string; name: string; input: unknown } @@ -80,12 +73,6 @@ export async function streamClaude( let sawThinking = false; - stream.on("streamEvent", (event) => { - const line = JSON.stringify(event); - console.log("[claude raw stream]", line); - fs.appendFile(RAW_STREAM_LOG_PATH, line + "\n", () => {}); - }); - stream.on("text", (delta) => { callbacks.onContentDelta?.(delta); }); diff --git a/backend/src/lib/llm/gemini.ts b/backend/src/lib/llm/gemini.ts index ee43d61..57e62d7 100644 --- a/backend/src/lib/llm/gemini.ts +++ b/backend/src/lib/llm/gemini.ts @@ -77,7 +77,6 @@ export async function streamGemini( let sawThinking = false; for await (const chunk of stream) { - console.log("[gemini stream chunk]", JSON.stringify(chunk, null, 2)); const parts = (chunk as { candidates?: { content?: { parts?: GeminiPart[] } }[] }) .candidates?.[0]?.content?.parts ?? []; diff --git a/backend/src/lib/storage.ts b/backend/src/lib/storage.ts index 82e7f23..6b4f749 100644 --- a/backend/src/lib/storage.ts +++ b/backend/src/lib/storage.ts @@ -122,7 +122,9 @@ export function normalizeDownloadFilename(name: string): string { } export function sanitizeDispositionFilename(name: string): string { - return normalizeDownloadFilename(name).replace(/["\\]/g, "_"); + return normalizeDownloadFilename(name) + .replace(/["\\]/g, "_") + .replace(/[^\x20-\x7E]/g, "_"); } export function encodeRFC5987(str: string): string { diff --git a/backend/src/lib/userApiKeys.ts b/backend/src/lib/userApiKeys.ts new file mode 100644 index 0000000..51b26bd --- /dev/null +++ b/backend/src/lib/userApiKeys.ts @@ -0,0 +1,143 @@ +import crypto from "crypto"; +import { createServerSupabase } from "./supabase"; +import type { UserApiKeys } from "./llm"; + +type Db = ReturnType; +export type ApiKeyProvider = "claude" | "gemini"; + +type EncryptedKeyRow = { + provider: ApiKeyProvider; + encrypted_key: string; + iv: string; + auth_tag: string; +}; + +const PROVIDERS: ApiKeyProvider[] = ["claude", "gemini"]; + +function encryptionKey(): Buffer { + const secret = + process.env.USER_API_KEYS_ENCRYPTION_SECRET || + process.env.API_KEYS_ENCRYPTION_SECRET || + process.env.SUPABASE_SECRET_KEY; + if (!secret) { + throw new Error("API key encryption secret is not configured"); + } + return crypto.createHash("sha256").update(secret).digest(); +} + +function encrypt(value: string): Omit { + const iv = crypto.randomBytes(12); + const cipher = crypto.createCipheriv("aes-256-gcm", encryptionKey(), iv); + const encrypted = Buffer.concat([ + cipher.update(value, "utf8"), + cipher.final(), + ]); + return { + encrypted_key: encrypted.toString("base64"), + iv: iv.toString("base64"), + auth_tag: cipher.getAuthTag().toString("base64"), + }; +} + +function decrypt(row: EncryptedKeyRow): string | null { + try { + const decipher = crypto.createDecipheriv( + "aes-256-gcm", + encryptionKey(), + Buffer.from(row.iv, "base64"), + ); + decipher.setAuthTag(Buffer.from(row.auth_tag, "base64")); + const decrypted = Buffer.concat([ + decipher.update(Buffer.from(row.encrypted_key, "base64")), + decipher.final(), + ]); + return decrypted.toString("utf8"); + } catch (err) { + console.error("[user-api-keys] failed to decrypt stored key", { + provider: row.provider, + error: err instanceof Error ? err.message : String(err), + }); + return null; + } +} + +function isProvider(value: string): value is ApiKeyProvider { + return (PROVIDERS as string[]).includes(value); +} + +export function normalizeApiKeyProvider(value: string): ApiKeyProvider | null { + return isProvider(value) ? value : null; +} + +export async function getUserApiKeyStatus( + userId: string, + db: Db = createServerSupabase(), +): Promise> { + const status: Record = { + claude: false, + gemini: false, + }; + + const { data, error } = await db + .from("user_api_keys") + .select("provider") + .eq("user_id", userId); + if (error) throw error; + + for (const row of data ?? []) { + const provider = normalizeApiKeyProvider(String(row.provider)); + if (provider) status[provider] = true; + } + + return status; +} + +export async function getUserApiKeys( + userId: string, + db: Db = createServerSupabase(), +): Promise { + const apiKeys: UserApiKeys = { claude: null, gemini: null }; + + const { data, error } = await db + .from("user_api_keys") + .select("provider, encrypted_key, iv, auth_tag") + .eq("user_id", userId); + if (error) throw error; + + for (const row of (data ?? []) as EncryptedKeyRow[]) { + const provider = normalizeApiKeyProvider(row.provider); + if (!provider) continue; + apiKeys[provider] = decrypt(row); + } + + return apiKeys; +} + +export async function saveUserApiKey( + userId: string, + provider: ApiKeyProvider, + value: string | null, + db: Db = createServerSupabase(), +): Promise { + const normalized = value?.trim() || null; + if (!normalized) { + const { error } = await db + .from("user_api_keys") + .delete() + .eq("user_id", userId) + .eq("provider", provider); + if (error) throw error; + return; + } + + const { error } = await db.from("user_api_keys").upsert( + { + user_id: userId, + provider, + ...encrypt(normalized), + updated_at: new Date().toISOString(), + }, + { onConflict: "user_id,provider" }, + ); + if (error) throw error; +} diff --git a/backend/src/lib/userSettings.ts b/backend/src/lib/userSettings.ts index c798b63..2476060 100644 --- a/backend/src/lib/userSettings.ts +++ b/backend/src/lib/userSettings.ts @@ -5,6 +5,7 @@ import { DEFAULT_TABULAR_MODEL, type UserApiKeys, } from "./llm"; +import { getUserApiKeys as getStoredUserApiKeys } from "./userApiKeys"; export type UserModelSettings = { title_model: string; @@ -29,14 +30,10 @@ export async function getUserModelSettings( const client = db ?? createServerSupabase(); const { data } = await client .from("user_profiles") - .select("tabular_model, claude_api_key, gemini_api_key") + .select("tabular_model") .eq("user_id", userId) .single(); - - const api_keys: UserApiKeys = { - claude: data?.claude_api_key ?? null, - gemini: data?.gemini_api_key ?? null, - }; + const api_keys = await getStoredUserApiKeys(userId, client); return { title_model: resolveTitleModel(api_keys), @@ -50,13 +47,5 @@ export async function getUserApiKeys( db?: ReturnType, ): Promise { const client = db ?? createServerSupabase(); - const { data } = await client - .from("user_profiles") - .select("claude_api_key, gemini_api_key") - .eq("user_id", userId) - .single(); - return { - claude: data?.claude_api_key ?? null, - gemini: data?.gemini_api_key ?? null, - }; + return getStoredUserApiKeys(userId, client); } diff --git a/backend/src/routes/chat.ts b/backend/src/routes/chat.ts index b56c293..206148f 100644 --- a/backend/src/routes/chat.ts +++ b/backend/src/routes/chat.ts @@ -16,6 +16,118 @@ import { checkProjectAccess } from "../lib/access"; export const chatRouter = Router(); +type Db = ReturnType; + +type AccessibleChat = { + id: string; + title: string | null; + user_id: string; + project_id: string | null; +} & Record; + +function parseOptionalProjectId(value: unknown): + | { ok: true; provided: boolean; projectId: string | null } + | { ok: false; detail: string } { + if (value === undefined) + return { ok: true, provided: false, projectId: null }; + if (value === null) return { ok: true, provided: true, projectId: null }; + if (typeof value !== "string" || !value.trim()) { + return { + ok: false, + detail: "project_id must be a non-empty string or null", + }; + } + return { ok: true, provided: true, projectId: value.trim() }; +} + +function parseOptionalChatId(value: unknown): + | { ok: true; chatId: string | null } + | { ok: false; detail: string } { + if (value === undefined || value === null) return { ok: true, chatId: null }; + if (typeof value !== "string" || !value.trim()) { + return { ok: false, detail: "chat_id must be a non-empty string" }; + } + return { ok: true, chatId: value.trim() }; +} + +function parseChatMessages(value: unknown): + | { ok: true; messages: ChatMessage[] } + | { ok: false; detail: string } { + if (!Array.isArray(value) || value.length === 0) { + return { ok: false, detail: "messages must be a non-empty array" }; + } + + for (const message of value) { + if (!message || typeof message !== "object" || Array.isArray(message)) { + return { ok: false, detail: "messages must contain objects" }; + } + const row = message as Record; + if (typeof row.role !== "string") { + return { ok: false, detail: "message.role must be a string" }; + } + if (row.content !== null && typeof row.content !== "string") { + return { + ok: false, + detail: "message.content must be a string or null", + }; + } + } + + return { ok: true, messages: value as ChatMessage[] }; +} + +function parseOptionalModel(value: unknown): + | { ok: true; model: string | undefined } + | { ok: false; detail: string } { + if (value === undefined) return { ok: true, model: undefined }; + if (typeof value !== "string" || !value.trim()) { + return { ok: false, detail: "model must be a non-empty string" }; + } + return { ok: true, model: value.trim() }; +} + +async function validateAccessibleProjectId( + projectId: string | null, + userId: string, + userEmail: string | null | undefined, + db: Db, +): Promise<{ ok: true } | { ok: false; status: number; detail: string }> { + if (!projectId) return { ok: true }; + const access = await checkProjectAccess(projectId, userId, userEmail, db); + if (!access.ok) + return { ok: false, status: 404, detail: "Project not found" }; + return { ok: true }; +} + +async function getAccessibleChat( + chatId: string, + userId: string, + userEmail: string | null | undefined, + db: Db, +): Promise { + const { data: chat, error } = await db + .from("chats") + .select("*") + .eq("id", chatId) + .maybeSingle(); + if (error || !chat) return null; + + const row = chat as AccessibleChat; + if (row.user_id === userId) return row; + + if (row.project_id) { + const access = await checkProjectAccess( + row.project_id, + userId, + userEmail, + db, + ); + if (access.ok) return row; + } + + return null; +} + // GET /chat // Visible chats = the user's own chats + every chat under a project the // user owns (so a project owner sees all collaborator chats in their @@ -52,11 +164,27 @@ chatRouter.get("/", requireAuth, async (req, res) => { // POST /chat/create chatRouter.post("/create", requireAuth, async (req, res) => { const userId = res.locals.userId as string; - const projectId: string | null = req.body.project_id ?? null; + const userEmail = res.locals.userEmail as string | undefined; + const parsedProjectId = parseOptionalProjectId(req.body?.project_id); + if (!parsedProjectId.ok) { + return void res.status(400).json({ detail: parsedProjectId.detail }); + } + const projectId = parsedProjectId.projectId; const db = createServerSupabase(); + const projectAccess = await validateAccessibleProjectId( + projectId, + userId, + userEmail, + db, + ); + if (!projectAccess.ok) + return void res + .status(projectAccess.status) + .json({ detail: projectAccess.detail }); + const { data, error } = await db .from("chats") - .insert({ user_id: userId, project_id: projectId ?? undefined }) + .insert({ user_id: userId, project_id: projectId ?? null }) .select("id") .single(); @@ -71,25 +199,8 @@ chatRouter.get("/:chatId", requireAuth, async (req, res) => { const { chatId } = req.params; const db = createServerSupabase(); - const { data: chat, error } = await db - .from("chats") - .select("*") - .eq("id", chatId) - .single(); - if (error || !chat) - return void res.status(404).json({ detail: "Chat not found" }); - // Owner of the chat OR a member of the chat's project can view it. - let canView = chat.user_id === userId; - if (!canView && chat.project_id) { - const access = await checkProjectAccess( - chat.project_id, - userId, - userEmail, - db, - ); - canView = access.ok; - } - if (!canView) + const chat = await getAccessibleChat(chatId, userId, userEmail, db); + if (!chat) return void res.status(404).json({ detail: "Chat not found" }); const { data: messages } = await db @@ -261,30 +372,14 @@ chatRouter.post("/:chatId/generate-title", requireAuth, async (req, res) => { const userId = res.locals.userId as string; const userEmail = res.locals.userEmail as string | undefined; const { chatId } = req.params; - const message: string = (req.body.message ?? "").trim(); + const message = + typeof req.body?.message === "string" ? req.body.message.trim() : ""; if (!message) return void res.status(400).json({ detail: "message is required" }); const db = createServerSupabase(); - const { data: chat, error } = await db - .from("chats") - .select("id, user_id, project_id") - .eq("id", chatId) - .single(); - - if (error || !chat) - return void res.status(404).json({ detail: "Chat not found" }); - let canTitle = chat.user_id === userId; - if (!canTitle && chat.project_id) { - const access = await checkProjectAccess( - chat.project_id, - userId, - userEmail, - db, - ); - canTitle = access.ok; - } - if (!canTitle) + const chat = await getAccessibleChat(chatId, userId, userEmail, db); + if (!chat) return void res.status(404).json({ detail: "Chat not found" }); try { @@ -303,8 +398,7 @@ chatRouter.post("/:chatId/generate-title", requireAuth, async (req, res) => { await db .from("chats") .update({ title }) - .eq("id", chatId) - .eq("user_id", userId); + .eq("id", chatId); res.json({ title }); } catch (err) { @@ -316,12 +410,31 @@ chatRouter.post("/:chatId/generate-title", requireAuth, async (req, res) => { // POST /chat — streaming chatRouter.post("/", requireAuth, async (req, res) => { const userId = res.locals.userId as string; - const { messages, chat_id, project_id, model } = req.body as { - messages: ChatMessage[]; - chat_id?: string; - project_id?: string; - model?: string; - }; + const body = + req.body && typeof req.body === "object" && !Array.isArray(req.body) + ? (req.body as Record) + : {}; + const parsedMessages = parseChatMessages(body.messages); + if (!parsedMessages.ok) { + return void res.status(400).json({ detail: parsedMessages.detail }); + } + const parsedChatId = parseOptionalChatId(body.chat_id); + if (!parsedChatId.ok) { + return void res.status(400).json({ detail: parsedChatId.detail }); + } + const parsedProjectId = parseOptionalProjectId(body.project_id); + if (!parsedProjectId.ok) { + return void res.status(400).json({ detail: parsedProjectId.detail }); + } + const parsedModel = parseOptionalModel(body.model); + if (!parsedModel.ok) { + return void res.status(400).json({ detail: parsedModel.detail }); + } + + const messages = parsedMessages.messages; + const chat_id = parsedChatId.chatId; + const project_id = parsedProjectId.projectId; + const model = parsedModel.model; console.log("[chat/stream] incoming request", { userId, @@ -335,46 +448,43 @@ chatRouter.post("/", requireAuth, async (req, res) => { const db = createServerSupabase(); let chatId = chat_id ?? null; let chatTitle: string | null = null; + let resolvedProjectId: string | null = parsedProjectId.projectId; if (chatId) { - // Either chat owner OR a member of the chat's project can post. - const { data: existing } = await db - .from("chats") - .select("id, title, user_id, project_id") - .eq("id", chatId) - .single(); - let canUse = !!existing && existing.user_id === userId; - if (!canUse && existing?.project_id) { - const access = await checkProjectAccess( - existing.project_id, - userId, - userEmail, - db, - ); - canUse = access.ok; + const existing = await getAccessibleChat(chatId, userId, userEmail, db); + if (!existing) + return void res.status(404).json({ detail: "Chat not found" }); + + const existingProjectId = existing.project_id ?? null; + if ( + parsedProjectId.provided && + parsedProjectId.projectId !== existingProjectId + ) { + return void res + .status(400) + .json({ detail: "project_id does not match chat" }); } - if (!canUse || !existing) chatId = null; - else chatTitle = existing.title; + resolvedProjectId = existingProjectId; + chatTitle = existing.title; } if (!chatId) { // If creating a chat tied to a project, the user must have access // to the project (own or shared). - if (project_id) { - const access = await checkProjectAccess( - project_id, - userId, - userEmail, - db, - ); - if (!access.ok) - return void res - .status(404) - .json({ detail: "Project not found" }); - } + const projectAccess = await validateAccessibleProjectId( + resolvedProjectId, + userId, + userEmail, + db, + ); + if (!projectAccess.ok) + return void res + .status(projectAccess.status) + .json({ detail: projectAccess.detail }); + const { data: newChat, error } = await db .from("chats") - .insert({ user_id: userId, project_id: project_id ?? null }) + .insert({ user_id: userId, project_id: resolvedProjectId }) .select("id, title") .single(); if (error || !newChat) { @@ -449,7 +559,7 @@ chatRouter.post("/", requireAuth, async (req, res) => { workflowStore, model, apiKeys, - projectId: project_id ?? null, + projectId: resolvedProjectId, }); console.log("[chat/stream] LLM stream finished", { diff --git a/backend/src/routes/user.ts b/backend/src/routes/user.ts index aeddd3a..f0674ed 100644 --- a/backend/src/routes/user.ts +++ b/backend/src/routes/user.ts @@ -1,23 +1,250 @@ import { Router } from "express"; import { requireAuth } from "../middleware/auth"; import { createServerSupabase } from "../lib/supabase"; +import { DEFAULT_TABULAR_MODEL, resolveModel } from "../lib/llm"; +import { + getUserApiKeyStatus, + normalizeApiKeyProvider, + saveUserApiKey, +} from "../lib/userApiKeys"; export const userRouter = Router(); -// POST /user/profile -userRouter.post("/profile", requireAuth, async (req, res) => { - const userId = res.locals.userId as string; - const db = createServerSupabase(); +const MONTHLY_CREDIT_LIMIT = 999999; + +type UserProfileRow = { + display_name: string | null; + organisation: string | null; + message_credits_used: number; + credits_reset_date: string; + tier: string; + tabular_model: string; +}; + +function serializeProfile( + row: UserProfileRow, + apiKeyStatus?: { claude: boolean; gemini: boolean }, +) { + const creditsUsed = row.message_credits_used ?? 0; + return { + displayName: row.display_name, + organisation: row.organisation, + messageCreditsUsed: creditsUsed, + creditsResetDate: row.credits_reset_date, + creditsRemaining: Math.max(MONTHLY_CREDIT_LIMIT - creditsUsed, 0), + tier: row.tier || "Free", + tabularModel: resolveModel(row.tabular_model, DEFAULT_TABULAR_MODEL), + ...(apiKeyStatus ? { apiKeyStatus } : {}), + }; +} + +function validateProfilePayload(body: unknown): + | { + ok: true; + update: { + display_name?: string | null; + organisation?: string | null; + tabular_model?: string; + updated_at: string; + }; + } + | { ok: false; detail: string } { + if (!body || typeof body !== "object" || Array.isArray(body)) { + return { ok: false, detail: "Expected a JSON object" }; + } + + const raw = body as Record; + const allowedFields = new Set([ + "displayName", + "organisation", + "tabularModel", + ]); + const invalidField = Object.keys(raw).find((key) => !allowedFields.has(key)); + if (invalidField) { + return { ok: false, detail: `Unsupported profile field: ${invalidField}` }; + } + + const update: { + display_name?: string | null; + organisation?: string | null; + tabular_model?: string; + updated_at: string; + } = { updated_at: new Date().toISOString() }; + + if ("displayName" in raw) { + if (raw.displayName !== null && typeof raw.displayName !== "string") { + return { ok: false, detail: "displayName must be a string or null" }; + } + update.display_name = raw.displayName?.trim() || null; + } + + if ("organisation" in raw) { + if (raw.organisation !== null && typeof raw.organisation !== "string") { + return { ok: false, detail: "organisation must be a string or null" }; + } + update.organisation = raw.organisation?.trim() || null; + } + + if ("tabularModel" in raw) { + if (typeof raw.tabularModel !== "string") { + return { ok: false, detail: "tabularModel must be a string" }; + } + const resolved = resolveModel(raw.tabularModel, ""); + if (!resolved) { + return { ok: false, detail: "Unsupported tabularModel" }; + } + update.tabular_model = resolved; + } + + return { ok: true, update }; +} + +async function ensureProfileRow( + db: ReturnType, + userId: string, +) { const { error } = await db .from("user_profiles") .upsert( { user_id: userId }, { onConflict: "user_id", ignoreDuplicates: true }, ); + return error; +} + +async function loadProfile( + db: ReturnType, + userId: string, + options: { repairMissing?: boolean } = {}, +) { + let { data, error } = await db + .from("user_profiles") + .select( + "display_name, organisation, message_credits_used, credits_reset_date, tier, tabular_model", + ) + .eq("user_id", userId) + .maybeSingle(); + + if (error) return { data: null, error }; + if (!data) { + if (!options.repairMissing) { + return { data: null, error: new Error("Profile not found") }; + } + + const ensureError = await ensureProfileRow(db, userId); + if (ensureError) return { data: null, error: ensureError }; + + const created = await db + .from("user_profiles") + .select( + "display_name, organisation, message_credits_used, credits_reset_date, tier, tabular_model", + ) + .eq("user_id", userId) + .single(); + if (created.error) return { data: null, error: created.error }; + data = created.data; + } + + let row = data as UserProfileRow; + if (row.credits_reset_date && new Date() > new Date(row.credits_reset_date)) { + const creditsResetDate = new Date(); + creditsResetDate.setDate(creditsResetDate.getDate() + 30); + const { data: resetData, error: resetError } = await db + .from("user_profiles") + .update({ + message_credits_used: 0, + credits_reset_date: creditsResetDate.toISOString(), + updated_at: new Date().toISOString(), + }) + .eq("user_id", userId) + .select( + "display_name, organisation, message_credits_used, credits_reset_date, tier, tabular_model", + ) + .single(); + + if (resetError) return { data: null, error: resetError }; + row = resetData as UserProfileRow; + } + + return { data: serializeProfile(row), error: null }; +} + +// POST /user/profile +userRouter.post("/profile", requireAuth, async (_req, res) => { + const userId = res.locals.userId as string; + const db = createServerSupabase(); + const error = await ensureProfileRow(db, userId); if (error) return void res.status(500).json({ detail: error.message }); res.json({ ok: true }); }); +// GET /user/profile +userRouter.get("/profile", requireAuth, async (_req, res) => { + const userId = res.locals.userId as string; + const db = createServerSupabase(); + const { data, error } = await loadProfile(db, userId, { + repairMissing: true, + }); + if (error) return void res.status(500).json({ detail: error.message }); + const apiKeyStatus = await getUserApiKeyStatus(userId, db); + res.json({ ...data, apiKeyStatus }); +}); + +// PATCH /user/profile +userRouter.patch("/profile", requireAuth, async (req, res) => { + const userId = res.locals.userId as string; + const parsed = validateProfilePayload(req.body); + if (!parsed.ok) return void res.status(400).json({ detail: parsed.detail }); + + const db = createServerSupabase(); + const ensureError = await ensureProfileRow(db, userId); + if (ensureError) + return void res.status(500).json({ detail: ensureError.message }); + + const { error: updateError } = await db + .from("user_profiles") + .update(parsed.update) + .eq("user_id", userId); + if (updateError) + return void res.status(500).json({ detail: updateError.message }); + + const { data, error } = await loadProfile(db, userId); + if (error) return void res.status(500).json({ detail: error.message }); + const apiKeyStatus = await getUserApiKeyStatus(userId, db); + res.json({ ...data, apiKeyStatus }); +}); + +// GET /user/api-keys +userRouter.get("/api-keys", requireAuth, async (_req, res) => { + const userId = res.locals.userId as string; + const db = createServerSupabase(); + const status = await getUserApiKeyStatus(userId, db); + res.json(status); +}); + +// PUT /user/api-keys/:provider +userRouter.put("/api-keys/:provider", requireAuth, async (req, res) => { + const userId = res.locals.userId as string; + const provider = normalizeApiKeyProvider(req.params.provider); + if (!provider) + return void res.status(400).json({ detail: "Unsupported provider" }); + + const apiKey = + typeof req.body?.api_key === "string" ? req.body.api_key : null; + const db = createServerSupabase(); + try { + await saveUserApiKey(userId, provider, apiKey, db); + const status = await getUserApiKeyStatus(userId, db); + res.json(status); + } catch (err) { + console.error("[user/api-keys] save failed", { + provider, + error: err instanceof Error ? err.message : String(err), + }); + res.status(500).json({ detail: "Failed to save API key" }); + } +}); + // DELETE /user/account userRouter.delete("/account", requireAuth, async (_req, res) => { const userId = res.locals.userId as string; diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 00bc0c5..a4b3abf 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -10,6 +10,7 @@ "esModuleInterop": true, "skipLibCheck": true, "resolveJsonModule": true, + "types": ["node", "express", "cors", "multer"], "paths": { "@/*": ["./src/*"] } diff --git a/frontend/bun.lock b/frontend/bun.lock index 0ffcaed..90f252b 100644 --- a/frontend/bun.lock +++ b/frontend/bun.lock @@ -3,7 +3,7 @@ "configVersion": 1, "workspaces": { "": { - "name": "frontend-app", + "name": "mike", "dependencies": { "@aws-sdk/client-s3": "^3.1025.0", "@aws-sdk/s3-request-presigner": "^3.1025.0", diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5782999..decbac1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -7,7 +7,6 @@ "": { "name": "mike", "version": "0.1.0", - "license": "AGPL-3.0-only", "dependencies": { "@aws-sdk/client-s3": "^3.1025.0", "@aws-sdk/s3-request-presigner": "^3.1025.0", diff --git a/frontend/package.json b/frontend/package.json index 520d74d..7c1725e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,6 @@ { "name": "mike", "version": "0.1.0", - "license": "AGPL-3.0-only", "private": true, "scripts": { "dev": "next dev", @@ -69,5 +68,6 @@ "tw-animate-css": "^1.4.0", "typescript": "^5", "wrangler": "^4.51.0" - } + }, + "license": "AGPL-3.0-only" } diff --git a/frontend/public/link-image.jpg b/frontend/public/link-image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..796213e1173c5faf05a31bcb2ad10a1dcef09d88 GIT binary patch literal 214619 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�LBsU)?Nh)0g(2 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

kxXH-(_02hgJa-nEDuPUfA2Gqm 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

rJ=Gufs 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 updateApiKey("claude", value.trim() || null) } + onRemove={() => updateApiKey("claude", null)} /> updateApiKey("gemini", value.trim() || null) } + onRemove={() => updateApiKey("gemini", null)} /> @@ -183,30 +185,33 @@ function TabularModelDropdown({ function ApiKeyField({ label, placeholder, - initialValue, + hasSavedKey, onSave, + onRemove, }: { label: string; placeholder: string; - initialValue: string; + hasSavedKey: boolean; onSave: (value: string) => Promise; + onRemove: () => Promise; }) { - const [value, setValue] = useState(initialValue); + const [value, setValue] = useState(""); const [reveal, setReveal] = useState(false); const [isSaving, setIsSaving] = useState(false); const [saved, setSaved] = useState(false); useEffect(() => { - setValue(initialValue); - }, [initialValue]); + setValue(""); + }, [hasSavedKey]); - const dirty = value !== initialValue; + const dirty = value.trim().length > 0; const handleSave = async () => { setIsSaving(true); const ok = await onSave(value); setIsSaving(false); if (ok) { + setValue(""); setSaved(true); setTimeout(() => setSaved(false), 2000); } else { @@ -214,16 +219,28 @@ function ApiKeyField({ } }; + const handleRemove = async () => { + setIsSaving(true); + const ok = await onRemove(); + setIsSaving(false); + if (!ok) alert(`Failed to remove ${label}.`); + }; + return (

+ {hasSavedKey && ( +

+ A key is saved. Paste a new key to replace it. +

+ )}
setValue(e.target.value)} - placeholder={placeholder} + placeholder={hasSavedKey ? "Saved key hidden" : placeholder} className="pr-10" autoComplete="off" spellCheck={false} @@ -257,6 +274,16 @@ function ApiKeyField({ "Save" )} + {hasSavedKey && ( + + )}
); diff --git a/frontend/src/app/(pages)/projects/[id]/assistant/page.tsx b/frontend/src/app/(pages)/projects/[id]/assistant/page.tsx new file mode 100644 index 0000000..7f38730 --- /dev/null +++ b/frontend/src/app/(pages)/projects/[id]/assistant/page.tsx @@ -0,0 +1,13 @@ +"use client"; + +import { use } from "react"; +import { ProjectPage } from "@/app/components/projects/ProjectPage"; + +interface Props { + params: Promise<{ id: string }>; +} + +export default function ProjectAssistantPage({ params }: Props) { + const { id } = use(params); + return ; +} diff --git a/frontend/src/app/(pages)/projects/[id]/tabular-reviews/page.tsx b/frontend/src/app/(pages)/projects/[id]/tabular-reviews/page.tsx new file mode 100644 index 0000000..54b185d --- /dev/null +++ b/frontend/src/app/(pages)/projects/[id]/tabular-reviews/page.tsx @@ -0,0 +1,13 @@ +"use client"; + +import { use } from "react"; +import { ProjectPage } from "@/app/components/projects/ProjectPage"; + +interface Props { + params: Promise<{ id: string }>; +} + +export default function ProjectTabularReviewsPage({ params }: Props) { + const { id } = use(params); + return ; +} diff --git a/frontend/src/app/components/assistant/ChatInput.tsx b/frontend/src/app/components/assistant/ChatInput.tsx index 7f56192..4c79c68 100644 --- a/frontend/src/app/components/assistant/ChatInput.tsx +++ b/frontend/src/app/components/assistant/ChatInput.tsx @@ -67,10 +67,12 @@ export const ChatInput = forwardRef(function ChatInput( } | null>(null); const [model, setModel] = useSelectedModel(); const { profile } = useUserProfile(); - const apiKeys = { - claudeApiKey: profile?.claudeApiKey ?? null, - geminiApiKey: profile?.geminiApiKey ?? null, - }; + const apiKeys = profile + ? { + claudeApiKey: profile?.claudeApiKey ?? null, + geminiApiKey: profile?.geminiApiKey ?? null, + } + : undefined; const textareaRef = useRef(null); const [docSelectorOpen, setDocSelectorOpen] = useState(false); const [workflowModalOpen, setWorkflowModalOpen] = useState(false); @@ -116,7 +118,7 @@ export const ChatInput = forwardRef(function ChatInput( const handleSubmit = () => { const query = value.trim(); if (!query || isLoading) return; - if (!isModelAvailable(model, apiKeys)) { + if (apiKeys && !isModelAvailable(model, apiKeys)) { setApiKeyModalProvider(getModelProvider(model)); return; } diff --git a/frontend/src/app/components/projects/ProjectPage.tsx b/frontend/src/app/components/projects/ProjectPage.tsx index a2f7f5a..e82128d 100644 --- a/frontend/src/app/components/projects/ProjectPage.tsx +++ b/frontend/src/app/components/projects/ProjectPage.tsx @@ -66,6 +66,7 @@ import { useChatHistoryContext } from "@/app/contexts/ChatHistoryContext"; interface Props { projectId: string; + initialTab?: Tab; } type Tab = "documents" | "assistant" | "reviews"; @@ -271,7 +272,7 @@ function DocVersionHistory({ ); } -export function ProjectPage({ projectId }: Props) { +export function ProjectPage({ projectId, initialTab = "documents" }: Props) { const [project, setProject] = useState(null); const [folders, setFolders] = useState([]); const [chats, setChats] = useState([]); @@ -282,7 +283,7 @@ export function ProjectPage({ projectId }: Props) { const tab: Tab = tabParam === "assistant" || tabParam === "reviews" ? tabParam - : "documents"; + : initialTab; const [addDocsOpen, setAddDocsOpen] = useState(false); const [peopleModalOpen, setPeopleModalOpen] = useState(false); const [ownerOnlyAction, setOwnerOnlyAction] = useState(null); diff --git a/frontend/src/app/components/tabular/TRChatPanel.tsx b/frontend/src/app/components/tabular/TRChatPanel.tsx index 3522df3..86e3caa 100644 --- a/frontend/src/app/components/tabular/TRChatPanel.tsx +++ b/frontend/src/app/components/tabular/TRChatPanel.tsx @@ -447,6 +447,7 @@ function TRChatInput({ model, onModelChange, apiKeys, + onHeightChange, }: { isLoading: boolean; onSubmit: (value: string) => void; @@ -454,10 +455,42 @@ function TRChatInput({ model: string; onModelChange: (id: string) => void; apiKeys: { claudeApiKey: string | null; geminiApiKey: string | null }; + onHeightChange: (height: number) => void; }) { const [value, setValue] = useState(""); + const rootRef = useRef(null); const textareaRef = useRef(null); + useEffect(() => { + const root = rootRef.current; + if (!root) return; + + const notify = () => { + onHeightChange(root.getBoundingClientRect().height); + }; + notify(); + + const observer = new ResizeObserver(notify); + observer.observe(root); + window.addEventListener("resize", notify); + return () => { + observer.disconnect(); + window.removeEventListener("resize", notify); + }; + }, [onHeightChange]); + + function resizeTextarea(el: HTMLTextAreaElement) { + el.style.height = "auto"; + el.style.height = `${Math.min(el.scrollHeight, 192)}px`; + el.style.overflowY = el.scrollHeight > 192 ? "auto" : "hidden"; + } + + function resetTextarea() { + if (!textareaRef.current) return; + textareaRef.current.style.height = "auto"; + textareaRef.current.style.overflowY = "hidden"; + } + function handleAction() { if (isLoading) { onCancel(); @@ -466,13 +499,16 @@ function TRChatInput({ const trimmed = value.trim(); if (!trimmed) return; setValue(""); - if (textareaRef.current) textareaRef.current.style.height = "auto"; + resetTextarea(); onSubmit(trimmed); } return ( -
-
+
+

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