This document summarizes the repository security posture, points to implementation artifacts, and distinguishes controls that are implemented now versus planned work.
- Scope: repository and Supabase architecture baseline for user, caretaker, and practitioner data access.
- Current phase: Week 3 complete.
- Status model used in this document:
- Implemented: present in migrations and/or app code in this repository.
- Planned: defined in PRD/roadmap but explicitly scheduled for a later week.
| Control | Current Status | Where Defined / Implemented |
|---|---|---|
| TLS for client to Supabase traffic | Implemented | PRD: Architecture + Security, Supabase platform/API model |
| RLS for PHI tables | Implemented | supabase/migrations/20260327130000_rls_policies.sql |
Grant-table authorization (practitioner_access, caretaker_access) |
Implemented | supabase/migrations/20260327120000_abstrack_core_schema.sql, supabase/migrations/20260327130000_rls_policies.sql |
Append-only access_log with trusted insert path |
Implemented | supabase/migrations/20260327120000_abstrack_core_schema.sql, supabase/migrations/20260327130000_rls_policies.sql |
| Auth (email/password, persistent session, password reset/change) | Implemented | packages/supabase/src/lib/auth.ts, app auth screens/providers |
| Practitioner MFA enforcement (fail-closed) | Implemented (RLS + helpers; UI uses claim contract) | PRD: Authentication; AUTH_CLAIM_CONTRACT.md; supabase/migrations/20260416120000_practitioner_mfa_assurance_rls.sql; packages/supabase/src/lib/session-claims.ts; practitioner AuthProvider |
Media bucket privacy + storage.objects RLS |
Implemented | supabase/migrations/20260328100000_episode_media_storage_bucket.sql |
| Media access via signed URLs | Planned for app flow (Week 7) | PRD §10 + roadmap Week 7 |
| Data model: plaintext PHI under RLS (no app-layer E2E encryption) | Implemented as design baseline | PRD: Security + data model; schema comments in core migration |
| PowerSync + SQLCipher offline protections | Planned (Week 7) | PRD: Architecture/Security and roadmap Week 7 |
- Intent: all API/auth/storage traffic from clients to Supabase is over HTTPS/TLS.
- PRD references:
- PRD: Architecture overview (web apps query Supabase over TLS)
- PRD: Security controls summary and technical safeguard baseline (TLS for API/storage)
- Platform alignment (Supabase docs): API and Storage endpoints are HTTPS; production guidance requires HTTPS/TLS.
- Status: Implemented baseline assumption for all deployed environments.
- Intent: PHI access is database-enforced, not UI-enforced.
- Implementation:
- RLS enabled for
profiles, preset tables,episodes,episode_symptoms,health_markers,food_diary_entries,episode_media, grant tables, andaccess_loginsupabase/migrations/20260327130000_rls_policies.sql. - Policy pattern (PHI tables):
- Patient owner: read/write own rows.
- Caretaker: read/write when active
caretaker_accessgrant exists. - Practitioner: read-only when active
practitioner_accessgrant exists (MFA fail-closed hardening scheduled Week 5).
- Ownership hardening:
enforce_phi_row_user_id_immutabletrigger blocks changinguser_idon PHI rows except trusted paths.
- RLS enabled for
- PRD references:
- PRD: Security — Authorized access + explicit RLS requirements table.
- PRD: Security controls summary and technical safeguard baseline.
- Status: Implemented.
- Automated checks: Vitest integration suite
packages/supabase/src/preset-flows.integration.spec.tsvalidates owner vs other-user access for symptom and health marker presets against Supabase Cloud whenSUPABASE_SECRET_KEYis configured (see SUPABASE_CLOUD_DEVELOPER.md — Preset RLS integration tests). It does not exercise caretaker or practitioner grant paths (those require grant fixtures and are a coverage gap until covered elsewhere).
- Intent: patient-initiated sharing is encoded as grant rows, then enforced by RLS.
- Tables:
practitioner_access(patient <-> practitioner authorization)caretaker_access(patient <-> caretaker authorization)
- Implementation:
- Core schema includes both grant tables in
supabase/migrations/20260327120000_abstrack_core_schema.sql. - Role-validation triggers enforce proper profile roles on grant endpoints in
supabase/migrations/20260327130000_rls_policies.sql. - Grant-table policies:
- Patients manage their own grants.
- Practitioners/caretakers can select rows relevant to themselves.
- Helper functions
user_has_practitioner_accessanduser_is_caretaker_for_patientare used across PHI and storage policies.
- Core schema includes both grant tables in
- PRD references:
- PRD: Users & Roles, Authorized access, and RLS requirements table.
- Status: Implemented. Practitioner MFA assurance is enforced in SQL on the grant path; client routing uses
profiles.app_roleplus JWTaalper AUTH_CLAIM_CONTRACT.md (no ambiguous fallbacks).
- Intent: audit records are append-only and cannot be forged by normal clients.
- Implementation:
- Table shape is defined in
supabase/migrations/20260327120000_abstrack_core_schema.sqlwith explicit no-PHI intent. - Privilege revocation and trusted insert role setup in
supabase/migrations/20260327130000_rls_policies.sql:authenticatedhasSELECTonly.service_rolehasINSERT+SELECTfor trusted paths.
- Trigger
access_log_prevent_update_or_deleteblocks mutation/deletion (except FK nulling edge case). - RLS policies include explicit deny-update/deny-delete for authenticated users and service-role insert/select policies.
- Table shape is defined in
- PRD references:
- Status: Implemented.
- Intent: patient auth/session lifecycle is built on Supabase Auth, with no app-layer data re-encryption model.
- Implemented now:
- Email/password sign-up and login wrappers in
packages/supabase/src/lib/auth.ts. - Persistent session handling via Supabase session APIs and auth-state listeners:
apps/mobile/src/app/App.tsxapps/web/src/lib/auth-provider.tsx
- Optional patient re-auth-on-open preference in mobile:
apps/mobile/src/app/reauth-preference.tsapps/mobile/src/app/screens/SettingsScreen.tsx
- Password reset and password update flows:
apps/mobile/src/app/screens/ForgotPasswordScreen.tsxapps/mobile/src/app/screens/UpdatePasswordScreen.tsxapps/web/src/app/forgot-password/page.tsxapps/web/src/app/update-password/page.tsx
- Week 3 health check wiring (
healthCheckProfilesLimit1) to validate auth/session/env/RLS path:apps/mobile/src/app/screens/HomeScreen.tsxapps/web/src/app/dashboard/page.tsx
- Email/password sign-up and login wrappers in
- Planned:
- Additional practitioner app routes gated on MFA readiness (see ROADMAP).
- PRD references:
- Status: Week 3 auth baseline implemented; practitioner MFA enforcement and claim contract documented in AUTH_CLAIM_CONTRACT.md.
- Intent: optional practitioner UX to skip re-entering TOTP on a later email/password sign-in within a time window, after the user opts in post–MFA verification.
- Implementation:
apps/practitioner/src/lib/practitioner-device-trust.tsstores a bundle that includes Supabaserefresh_tokenandaccess_tokeninlocalStorage. That increases XSS blast radius: script running in this origin can read web storage and exfiltrate tokens usable until expiry or revocation—unacceptable to treat as equivalent to HttpOnly cookies. - Mitigations (product and engineering): user opt-in only; treat CSP, XSS-safe rendering (no unsanitized HTML / avoid
dangerouslySetInnerHTMLwith untrusted content), and dependency hygiene as part of the control set for this surface. Prefer deploying a strict Content-Security-Policy at the edge or host (includeconnect-src/ WebSocket hosts required by Supabase Auth and your project URL). - Preferred direction: redesign to server-managed device trust (opaque HttpOnly cookie + server validation, or short-lived scoped tokens exchanged only server-side)—not implemented in the current client-only bundle.
- Status: interim client implementation; RLS and MFA rules remain authoritative for PHI—this path is not an additional server-side authorization layer.
- Intent: optional patient/caretaker UX to skip TOTP on a later email/password sign-in within a chosen window (30 days or 1 year), after explicit opt-in post–MFA verification on
UserLoginForm. - Implementation:
apps/web/src/lib/user-mfa-device-trust.ts— same localStorage token bundle risk as practitioner (see above). - Deploy gate:
NEXT_PUBLIC_USER_MFA_DEVICE_TRUST=trueonly (unset/false → feature off). Production builds also requireNEXT_PUBLIC_USER_WEB_CSP_ENFORCE=trueat build time before trust is enabled. - Status: off by default until CSP is staged and both flags are set for a release.
- Intent: reduce XSS impact on user web (including optional trusted-device tokens) with Report-Only first, then enforce — same staged model as practitioner, separate config.
- Implementation:
apps/web/next.config.js,apps/web/csp-config.js. - Phase A (default):
Content-Security-Policy-Report-Only. - Phase B: set
USER_WEB_CSP_ENFORCE=trueat build/deploy time andNEXT_PUBLIC_USER_WEB_CSP_ENFORCE=truewhen enabling MFA device trust in production.
- Intent: reduce XSS impact on the practitioner surface (including optional trusted-device tokens in
localStorage) with a strict, staged CSP: report violations first, then enforce when noise is acceptable. - Implementation:
apps/practitioner/next.config.jssets headers globally (/:path*). Policy is built inapps/practitioner/csp-config.jsfromNEXT_PUBLIC_SUPABASE_URLat build time (same host as Auth, REST, Realtime, and Storage). - Phase A (default):
Content-Security-Policy-Report-Only— violations are logged (browser console / DevTools) but requests are not blocked. - Phase B: set server-side
PRACTITIONER_CSP_ENFORCE=true(e.g. hosting env at build time) to sendContent-Security-Policyinstead of Report-Only. Remove or flip the env after sustained clean reports. - Allowed origins (summary):
'self'— same-origin navigation, API routes, and Next.js assets.- Supabase project —
https/wss(orhttp/wsfor local CLI) origins derived fromNEXT_PUBLIC_SUPABASE_URLfor REST, Auth, Realtime, and Storage. - Local development — extra
connect-srcentries for common Next/Nx ports andlocalhost/127.0.0.1:54321so Report-Only stays usable duringnext dev(HMR and local Supabase).
- Directives (summary):
default-src 'self';script-srcincludes'unsafe-inline'(required for the theme bootstrap inline script and typical Next.js inline handling; nonces are the long-term tightening path per Next.js CSP);'unsafe-eval'is added in development only for React/Next tooling;style-src 'unsafe-inline'for Tailwind/Next;img-srcincludesdata:/blob:(e.g. TOTP QR);connect-srcas above;frame-ancestors 'none';frame-src 'none';upgrade-insecure-requestsin production when the Supabase URL ishttps://…. - Reporting: there is no dedicated violation collector in-repo yet; Phase A still helps via DevTools. A future
report-to/Reporting-Endpointsendpoint can be added without changing the staged model. - Status: Phase A deployed by default; Phase B is opt-in via env until operators confirm low violation noise.
- Intent: media confidentiality is provided by private bucket + RLS + TLS + platform encryption at rest, not client-managed DEKs.
- Implemented now:
- Private bucket creation (
episode-media) insupabase/migrations/20260328100000_episode_media_storage_bucket.sql. storage.objectsRLS policies for select/insert/update/delete scoped to owner/caretaker/practitioner access helpers in the same migration.- Path-derived owner checks (
{user_id}/...) via SQL helper functions in the same migration.
- Private bucket creation (
- Planned:
- End-user signed URL playback/download flow completion in app UX and offline queue workflow (Week 7).
- PRD references:
- PRD: Media storage security.
- PRD §10: Video & Photo Capture (storage and signed URLs).
- Status: bucket + policy baseline implemented; Week 7 app flows planned.
- Intent: PHI is stored as normal Postgres columns and protected by RLS/authorization controls; no application-layer end-to-end field encryption.
- Implementation:
- Explicitly documented in schema migration header comments and PRD.
- Enforced as architecture baseline across schema and access policy design.
- PRD references:
- Status: Implemented baseline.
Implemented now:
- TLS transport baseline for Supabase API/auth/storage usage.
- RLS on PHI and grant/audit tables.
- Grant-table authorization model.
- Append-only
access_logprotections. - Email/password auth, persistent session behavior, reset/update password flows.
- Week 3 health-check wiring using
healthCheckProfilesLimit1. - Private media bucket and
storage.objectsRLS policies. - Plaintext PHI data model under RLS.
Planned (not yet complete):
- Practitioner app navigation to patient-data routes behind explicit MFA-ready UI checks (beyond security setup page).
- PowerSync + SQLCipher offline model implementation (Week 7).
- Signed URL media playback/download flow completion in product UX and offline queue flow (Week 7).
Core implementation artifacts:
supabase/migrations/20260327120000_abstrack_core_schema.sqlsupabase/migrations/20260327130000_rls_policies.sqlsupabase/migrations/20260328100000_episode_media_storage_bucket.sqlpackages/supabase/src/lib/auth.tsapps/mobile/src/app/App.tsxapps/mobile/src/app/screens/HomeScreen.tsxapps/mobile/src/app/screens/SettingsScreen.tsxapps/mobile/src/app/screens/ForgotPasswordScreen.tsxapps/mobile/src/app/screens/UpdatePasswordScreen.tsxapps/web/src/lib/auth-provider.tsxapps/web/src/app/dashboard/page.tsxapps/web/src/lib/user-mfa-device-trust.ts(user web trusted-device UX; disabled by default; see “User web trusted device” above)apps/web/next.config.js,apps/web/csp-config.js(user web CSP; see “User web Content-Security-Policy” above)apps/practitioner/src/lib/practitioner-device-trust.ts(trusted-device UX; see XSS warning in file and subsection above)apps/practitioner/next.config.js,apps/practitioner/csp-config.js(practitioner CSP; see “Practitioner Content-Security-Policy” above)
Primary design references:
- docs/PRD.md (Security, Authentication, and Media sections)
- docs/AUTH_CLAIM_CONTRACT.md (JWT +
profiles.app_rolecontract) - docs/ROADMAP.md (Week 3, Week 5, Week 7)