Skip to content

Latest commit

 

History

History
217 lines (179 loc) · 19.7 KB

File metadata and controls

217 lines (179 loc) · 19.7 KB

ABStrack Security Baseline

This document summarizes the repository security posture, points to implementation artifacts, and distinguishes controls that are implemented now versus planned work.

Scope and Status

  • 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.

Security Posture at a Glance

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

Control Details

1) TLS: all client <-> Supabase traffic over HTTPS

  • Intent: all API/auth/storage traffic from clients to Supabase is over HTTPS/TLS.
  • PRD references:
  • Platform alignment (Supabase docs): API and Storage endpoints are HTTPS; production guidance requires HTTPS/TLS.
  • Status: Implemented baseline assumption for all deployed environments.

2) Row-Level Security (RLS): PHI tables and policy intent

  • 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, and access_log in supabase/migrations/20260327130000_rls_policies.sql.
    • Policy pattern (PHI tables):
      • Patient owner: read/write own rows.
      • Caretaker: read/write when active caretaker_access grant exists.
      • Practitioner: read-only when active practitioner_access grant exists (MFA fail-closed hardening scheduled Week 5).
    • Ownership hardening:
      • enforce_phi_row_user_id_immutable trigger blocks changing user_id on PHI rows except trusted paths.
  • PRD references:
  • Status: Implemented.
  • Automated checks: Vitest integration suite packages/supabase/src/preset-flows.integration.spec.ts validates owner vs other-user access for symptom and health marker presets against Supabase Cloud when SUPABASE_SECRET_KEY is 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).

3) Grant tables: authorized sharing model

  • 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_access and user_is_caretaker_for_patient are used across PHI and storage policies.
  • PRD references:
  • Status: Implemented. Practitioner MFA assurance is enforced in SQL on the grant path; client routing uses profiles.app_role plus JWT aal per AUTH_CLAIM_CONTRACT.md (no ambiguous fallbacks).

4) access_log: append-only audit logging with trusted insert path

  • 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.sql with explicit no-PHI intent.
    • Privilege revocation and trusted insert role setup in supabase/migrations/20260327130000_rls_policies.sql:
      • authenticated has SELECT only.
      • service_role has INSERT + SELECT for trusted paths.
    • Trigger access_log_prevent_update_or_delete blocks mutation/deletion (except FK nulling edge case).
    • RLS policies include explicit deny-update/deny-delete for authenticated users and service-role insert/select policies.
  • PRD references:
  • Status: Implemented.

5) Authentication baseline (Week 3)

  • 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.tsx
      • apps/web/src/lib/auth-provider.tsx
    • Optional patient re-auth-on-open preference in mobile:
      • apps/mobile/src/app/reauth-preference.ts
      • apps/mobile/src/app/screens/SettingsScreen.tsx
    • Password reset and password update flows:
      • apps/mobile/src/app/screens/ForgotPasswordScreen.tsx
      • apps/mobile/src/app/screens/UpdatePasswordScreen.tsx
      • apps/web/src/app/forgot-password/page.tsx
      • apps/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.tsx
      • apps/web/src/app/dashboard/page.tsx
  • 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.

Practitioner “trusted device” (browser storage — documented risk)

  • 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.ts stores a bundle that includes Supabase refresh_token and access_token in localStorage. 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 dangerouslySetInnerHTML with 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 (include connect-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.

User web “trusted device” (browser storage — disabled by default)

  • 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=true only (unset/false → feature off). Production builds also require NEXT_PUBLIC_USER_WEB_CSP_ENFORCE=true at build time before trust is enabled.
  • Status: off by default until CSP is staged and both flags are set for a release.

User web Content-Security-Policy (staged)

  • 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=true at build/deploy time and NEXT_PUBLIC_USER_WEB_CSP_ENFORCE=true when enabling MFA device trust in production.

Practitioner Content-Security-Policy (staged)

  • 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.js sets headers globally (/:path*). Policy is built in apps/practitioner/csp-config.js from NEXT_PUBLIC_SUPABASE_URL at 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 send Content-Security-Policy instead 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 (or http/ws for local CLI) origins derived from NEXT_PUBLIC_SUPABASE_URL for REST, Auth, Realtime, and Storage.
    • Local development — extra connect-src entries for common Next/Nx ports and localhost / 127.0.0.1:54321 so Report-Only stays usable during next dev (HMR and local Supabase).
  • Directives (summary): default-src 'self'; script-src includes '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-src includes data:/blob: (e.g. TOTP QR); connect-src as above; frame-ancestors 'none'; frame-src 'none'; upgrade-insecure-requests in production when the Supabase URL is https://….
  • Reporting: there is no dedicated violation collector in-repo yet; Phase A still helps via DevTools. A future report-to / Reporting-Endpoints endpoint 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.

6) Media storage security

  • 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) in supabase/migrations/20260328100000_episode_media_storage_bucket.sql.
    • storage.objects RLS 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.
  • Planned:
    • End-user signed URL playback/download flow completion in app UX and offline queue workflow (Week 7).
  • PRD references:
  • Status: bucket + policy baseline implemented; Week 7 app flows planned.

7) Data model posture (plaintext PHI under RLS)

Implemented vs Planned Summary

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_log protections.
  • Email/password auth, persistent session behavior, reset/update password flows.
  • Week 3 health-check wiring using healthCheckProfilesLimit1.
  • Private media bucket and storage.objects RLS 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).

Traceability Index

Core implementation artifacts:

  • supabase/migrations/20260327120000_abstrack_core_schema.sql
  • supabase/migrations/20260327130000_rls_policies.sql
  • supabase/migrations/20260328100000_episode_media_storage_bucket.sql
  • packages/supabase/src/lib/auth.ts
  • apps/mobile/src/app/App.tsx
  • apps/mobile/src/app/screens/HomeScreen.tsx
  • apps/mobile/src/app/screens/SettingsScreen.tsx
  • apps/mobile/src/app/screens/ForgotPasswordScreen.tsx
  • apps/mobile/src/app/screens/UpdatePasswordScreen.tsx
  • apps/web/src/lib/auth-provider.tsx
  • apps/web/src/app/dashboard/page.tsx
  • apps/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: