This document defines the current security model and operational controls for Document Hub.
- Ensure each user can only access their own documents, bookmarks, profile updates, and storage objects.
- Prevent public exposure of private user files (documents and avatars).
- Keep secrets out of source control and CI logs.
- Maintain reproducible, migration-driven policy hardening.
- Browser client (untrusted runtime).
- Supabase Auth (identity and sessions).
- Supabase Postgres with RLS (authorization for table data).
- Supabase Storage with policies (authorization for file objects).
- Email/password auth handled by Supabase Auth.
- Password reset flow uses recovery mode in
/auth?mode=reset. - Route guards block:
- unauthenticated access to protected routes,
- authenticated access to public-only auth route.
RLS is enabled on user-owned tables:
public.profilespublic.user_rolespublic.documentspublic.bookmarkspublic.activity_logs
Policy pattern:
auth.uid() = user_idfor user-owned data access.- Insert/update/delete constrained to the authenticated owner.
Buckets:
documents-> privateprofile-avatars-> private
Storage object policy pattern:
- bucket-scoped access plus folder ownership check:
auth.uid()::text = (storage.foldername(name))[1]
Additional constraints:
- file size and MIME type limits configured in migrations.
profile-avatarshardened by idempotent migration:supabase/migrations/20260306100000_harden_profile_avatar_policies.sql
Never commit:
.env.env.local- service-role keys
- database passwords
Committed safely:
.env.examplewith placeholders onlyVITE_SUPABASE_PUBLISHABLE_KEYis safe for client usage (publishable key)
Required environment variables:
VITE_SUPABASE_URLVITE_SUPABASE_PUBLISHABLE_KEY
Before release:
- Apply all migrations in order.
- Verify both storage buckets are private.
- Verify RLS policies exist for all user-owned tables.
- Validate avatar upload + display using signed/private access.
- Validate document upload/download/delete permissions by user boundary.
- Run:
npm run format:checknpm run testnpm run test:e2enpm run build
If unauthorized access is suspected:
- Rotate compromised credentials immediately.
- Re-run hardening migration:
20260306100000_harden_profile_avatar_policies.sql
- Review Supabase Auth logs and database/storage access logs.
- Invalidate active sessions if needed (from app settings or Supabase admin tools).
- Create a post-incident note in release/docs before next deploy.
- CI lint step is currently non-blocking due existing legacy lint errors.
- Seed SQL creates demo metadata rows; run only in non-production environments unless intended.
- Enforce stricter CSP headers for production hosting.
- Add automated policy validation checks in CI (schema smoke checks).
- Add dependency vulnerability scanning in CI (
npm auditgate policy). - Add centralized error/incident monitoring (Phase 3 Step 4).