PaperMove website security checkpoint
PaperMove website security checkpoint
The original project at /Users/ryan/Documents/GitHub/PaperMove remains the reference implementation and must not be edited during the website migration.
Complete these checks before onboarding another user or importing additional sensitive data.
Supabase configuration
- Create the owner account in Authentication > Users.
- Disable public user registration after the owner account exists.
- Run
supabase/migrations/202607180001_create_papermove_states.sqlin the Supabase SQL Editor. - Confirm that Row Level Security is enabled for
papermove_states. - Use only the project URL and publishable/anon key in browser code.
- Never commit the service-role key, database password, owner password, or an access token.
- Enable multi-factor authentication for the owner account if available.
- Restrict authentication redirect URLs to the production PaperMove address and explicit local development addresses.
- After MFA works, run
supabase/migrations/202607180003_create_papermove_file_box.sql. - Confirm that
papermove-filesis a private Storage bucket with a 20 MiB file-size limit. - Create the three owner-and-AAL2 policies through Storage > Policies using
docs/papermove-storage-policies.md. - Run
supabase/migrations/202607190004_limit_papermove_files.sql, then add the capacity helper to the Storage INSERT policy as documented.
Required access tests
Use harmless test data for all tests.
Signed-out visitor
- Cannot select any row from
papermove_states. - Cannot insert a row.
- Cannot update a row.
- Cannot open the application dashboard.
Second authenticated account
- Can never select the owner’s row.
- Can never update the owner’s row.
- Can never change a row’s
user_idto the owner’s ID.
Run supabase/tests/papermove_rls_isolation.sql in the Supabase SQL Editor to perform the select/update isolation test with a synthetic AAL2 authenticated user. The test runs inside a transaction and always rolls back.
Owner account
- Can create its own initial state.
- Can read its own state after signing in again.
- Can update its own state.
- Cannot delete its state through the browser API.
- Can upload, list, download, and delete files only after MFA verification.
Private file box
- Signed-out and AAL1 sessions cannot list or download any stored file.
- Every object path begins with its owner’s authenticated user UUID.
- A second authenticated account cannot list, download, or delete the owner’s files.
- The bucket is private and rejects files larger than 20 MiB server-side.
- Each AAL2 user can store no more than 30 files.
- The website downloads private objects through an authenticated request and never creates a permanent public URL.
Run supabase/tests/papermove_storage_isolation.sql after the Storage migrations. It checks the private bucket, the 20 MiB limit, 30-file policy, all required policies, AAL1 denial, and second-user AAL2 isolation.
Application security requirements
- Replace PaperMove’s local hard-coded login completely with Supabase Auth.
- Do not retain the current HTTP/HTTPS login bypass.
- Escape all project, task, handoff, file, and activity values before rendering.
- Permit only approved link protocols, initially
https:andhttp:. - Open external file links with
noopenerandnoreferrer. - Load a fixed, reviewed Supabase client version rather than an unpinned script.
- Add a Content Security Policy appropriate for the Supabase project domain.
- Serialize saves so older requests cannot overwrite newer requests.
- Include the current
revisionin every update condition. If another tab has already saved, stop and ask the user to reload or resolve the conflict. - Provide complete JSON export and validated JSON import for independent backups. The existing CSV export is not a full backup.
- Keep the PaperMove route out of search indexing. This reduces discovery but is not a security control.
- Treat Supabase Storage as convenient remote access, not the only backup. Free projects can pause after inactivity and do not include automatic backups.
Release gate
The web application can receive real project details only after:
- all three access-test groups pass;
- Supabase MFA is enrolled, verified, and required for database access;
- no secrets or real data appear in the Git repository;
- the browser has been tested for stored-script injection;
- a full export has been downloaded and successfully restored using harmless data; and
- the owner has confirmed that storing the intended research information with Supabase is acceptable.
