Auth hardening: RLS migration, server-side security middleware, and HTML sanitization
nwhitehouse ran a broad security pass across 36 files, shipping a 451-line RLS migration, server-side HTTP security middleware, download-token tightening, and frontend HTML sanitization for assistant message rendering. This is the kind of sweep you do once you've decided the fork is hosting real user data.
The core of this commit (325ff20c) is migration 002_enable_rls_tenant_tables.sql (451 LOC), which enables row-level security across all tenant-owned tables: projects, folders, documents, versions, edits, chats, workflows, workflow shares, tabular reviews, cells, and tabular chat messages. The backend still runs with a service-role key - RLS here is defense-in-depth for direct Supabase client access and any app-layer check that gets missed.
backend/src/lib/httpSecurity.ts (55 LOC, new) adds server-side middleware covering stricter CORS, helmet, JSON body limits, upload concurrency caps, and required DOWNLOAD_SIGNING_SECRET. The commit also tightens project and document ID authorization checks and removes raw-stream logging of model content.
On the frontend, safeMarkdown.ts and sanitizeHtml.ts are added to sanitize assistant message rendering. The storage client consolidation deletes frontend/src/lib/storage.ts (-136 LOC) and removes some dead Anthropic/Gemini-specific code paths from chatTools.ts and olava.ts. A 315-line security regression test suite (backend/tests/security.test.ts) accompanies the migration.
One dependency note: this commit adds canvas@^3.2.3 to backend/package.json but only updates bun.lock, not package-lock.json. Railway uses npm ci, which then fails with a lockfile mismatch. A separate follow-up commit regenerates the npm lockfile. Worth knowing if you're picking this apart.
The migration is Supabase-specific: RLS policies reference auth.uid() and auth.users. If your fork uses a different auth backend, treat the migration as a checklist of what to enforce rather than a drop-in.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?