Security posture assessment for partnership evaluation — covering authentication, data protection, audit controls, infrastructure security, and HIPAA compliance.
Two-role system — providers (physicians) and patients — each with distinct auth flows, session policies, and access boundaries enforced at every layer.
Auth tokens stored in iOS Keychain and Android Keystore via react-native-keychain with AFTER_FIRST_UNLOCK accessibility.
Service-role key stored in Supabase Vault. All pg_cron jobs read it at invocation time via helper function with format validation.
Service-role token verification uses constant-time comparison (timingSafeEqual) to prevent timing-based attacks.
Multi-layered data protection covering encryption, PHI handling, input validation, secure storage, and a full patient data deletion lifecycle.
Zod schemas enforce format on all PHI inputs: email, phone (E.164), ZIP, NPI, name, date of birth. Strict mode rejects unknown fields. DB constraints provide belt-and-suspenders enforcement.
Dedicated log-redact.ts module scrubs email, phone, DOB, name, MRN, NPI, SSN, and address patterns from all console output. SHA-256 truncated hashes enable correlation without exposing PHI.
Progressive migration series ensures no PHI values are stored in audit rows for any operation type (INSERT, UPDATE, DELETE). Only column names, resource IDs, and metadata are persisted.
All edge functions return generic error messages. withAudit() explicitly prevents err.message or stack traces from leaking into HTTP responses. DB constraint errors translated to user-friendly 400s.
Private bucket. 50 MB limit. text/plain MIME only. No client-facing RLS — service-role edge functions only.
Private bucket for lab PDFs and results. Access gated by provider enrollment verification. Retained for provider access post-deletion.
Object Lock Compliance mode. KMS encryption. 6-year immutable retention. Defensive bucket policy blocks delete operations even from AWS root.
RETAIN_FOR_PROVIDER (clinical records with legal retention obligations) is marked
but preserved per state medical record retention laws.
Append-only, tamper-evident audit logging with per-entity hash chains, monthly partitioning, and immutable off-box export — meeting HIPAA §164.312(b) audit control requirements.
Per-entity SHA-256 chains with advisory-lock serialization. Each row’s hash incorporates the previous hash.
RESTRICTIVE RLS blocks UPDATE/DELETE. REVOKE on all roles. Only exported_at is writable, only by audit_writer.
DDL event trigger raises exception on DROP, ALTER, or TRUNCATE against audit schema. Break-glass via session variable.
Weekly cron walks 200 recent chains via fn_verify_chain(). Mismatches generate self-audit rows + WARNINGs.
Hardened API layer with input validation, rate limiting, security headers, and resilient third-party integration patterns.
iOS Keychain / Android Keystore via react-native-keychain. Tokens never stored in plain-text AsyncStorage.
iOS ATS enforced (NSAllowsArbitraryLoads: false). Only local networking allowed for development.
No TLS certificate pinning implemented. Connections rely on default OS TLS verification.
HMAC signature verification via constructEventAsync(). Atomic idempotency with ON CONFLICT DO NOTHING.
HMAC-SHA256 with constant-time comparison. Idempotency via webhook_events table (SHA-256 dedup key).
HMAC-SHA256 with 300-second timestamp replay protection. Ignores non-v1 schemes (downgrade prevention).
All credentials (SUPABASE_ACCESS_TOKEN, SUPABASE_DB_PASSWORD) stored in GitHub Actions secrets. Supabase CLI version pinned to prevent supply-chain drift.
No SAST, DAST, or dependency vulnerability scanning (Dependabot/Snyk) in CI pipeline. Listed as P2 in pre-launch checklist.
Healthena integrates with multiple external services for clinical data, AI, payments, and communications. BAA execution status for each vendor is tracked below.
| Vendor | Purpose | PHI exposure | BAA available | BAA signed |
|---|---|---|---|---|
| Supabase | Database, Auth, Storage, Edge Functions | All PHI | Yes (HIPAA add-on) | Pending |
| AWS S3 | Audit log archival | Patient IDs in audit logs | Yes (AWS Artifact) | Pending |
| Anthropic | AI co-pilot (Claude API) | PHI in prompts | Yes (via sales) | Pending |
| OpenAI | Lab PDF extraction, eval | PHI in prompts + PDFs | Yes (baa@openai.com) | Pending |
| LifePoint | Lab ordering, results, EHR | Full clinical data | Yes (HITRUST R2, SOC 2) | Pending |
| TruDiagnostic | Epigenetic kit orders + reports | Clinical data | Yes (on request) | Pending |
| Lifenome | Genomic trait derivation | Derived from PHI | Case-by-case | Pending |
| Terra | Wearable data integration | Health/fitness data | TBD | Pending |
| Twilio | SMS OTP (via Supabase) | Low (phone + OTP only) | Yes (Enterprise) | Pending |
| Resend | Transactional email | Depends on content | Not publicly offered | May require vendor swap |
| Stripe | Payments | None (by policy) | N/A (HHS exclusion) | N/A |
| Google Gemini | LLM router (removed) | Removed from code 2026-04-27 | Public endpoint not covered | Remediated (removed) |
All third-party integrations (LifePoint, TruDiagnostic, Lifenome, Terra) use circuit breaker pattern with exponential backoff and 15-second timeouts.
Lifenome integration pins upload URLs to an allowed-host allowlist (storage.googleapis.com, HTTPS only) to prevent redirect-based SSRF.
Documented policy: no PHI in Stripe description, metadata, statement descriptor, receipt email, or webhook payloads.
Technical safeguard requirements mapped to implementation status. Each control references the specific HIPAA provision it addresses.
| HIPAA provision | Requirement | Status | Implementation |
|---|---|---|---|
| §164.312(a)(1) | Unique user identification | Pass | UUID per user in auth.users. Role derivation from app_metadata.type. Separate provider/patient tables with user_id FK. |
| §164.312(a)(2)(i) | Emergency access | Pass | Dedicated emergency-access edge function. Admin-only, rate-limited (3/hr), requires 10-char reason. Three emergency types. Full audit trail. |
| §164.312(a)(2)(iii) | Automatic logoff | Pass | Web: 15-min idle / 12-hr absolute. Mobile: 30-min idle / 12-hr absolute. Activity tracking with throttled event listeners. |
| §164.312(a)(2)(iv) | Encryption at rest | Pass | AWS EBS volume encryption (Supabase-managed). SSE-KMS with customer-managed key for S3 audit archive. |
| §164.312(b) | Audit controls | Pass | 30+ table write triggers, 35 function read logging, SHA-256 hash chains, daily S3 Object Lock export (6-year), weekly chain verification, legal holds. |
| §164.312(c)(1) | Integrity controls | Pass | Per-entity hash chains with advisory-lock serialization. S3 Object Lock Compliance mode. DDL event trigger protects audit schema. |
| §164.312(d) | Person/entity authentication | Partial | ES256 JWT + email/SMS OTP. MFA (TOTP) designed but not yet implemented in application code. |
| §164.312(e)(1) | Transmission security | Pass | TLS enforced on all connections. iOS ATS enabled. ES256 asymmetric JWT signing. |
| Requirement | Status | Notes |
|---|---|---|
| Risk assessment | Missing | No formal risk assessment document. Infrastructure and code-level controls exist but no formal assessment per §164.308(a)(1)(ii)(A). |
| Security officer designation | Missing | COMPLIANCE.md notes “TBD — assign a security owner.” |
| Security incident procedures | Exists (draft) | IR runbook v0.1 with HIPAA §164.410 notification procedures, four-factor breach analysis, triage checklists, containment playbooks. |
| Business associate contracts | Tracked, pending | 12 vendors identified and tracked. BAA sign-up paths documented. Execution pending. |
| Login monitoring | Partial | Supabase logs auth events in auth.audit_log_entries. Not yet ingested into tamper-evident audit.log. |
Prioritized list of gaps identified during this assessment, categorized by severity and estimated effort. Items are ordered by risk to the GRAIL partnership evaluation.
| Priority | Issue | Risk | Status |
|---|---|---|---|
| P0 | Execute BAAs with all PHI-touching vendors 12 vendors identified, 0 BAAs confirmed signed. Supabase, AWS, Anthropic, OpenAI, Health Gorilla are highest priority. |
Cannot legally transmit PHI to covered entities without executed BAAs | Sign-up paths documented |
| P0 | Rotate service-role JWT Historical JWT value present in git history (migration files). Vault-based retrieval is active, but the leaked key needs rotation. |
Credential compromise risk | Rotation runbook exists |
| P0 | Designate security officer HIPAA §164.308(a)(2) requires a designated security official. |
Regulatory compliance gap | Not started |
| P1 | Implement provider MFA (TOTP) Designed and documented but zero implementation in frontend code. Providers accessing PHI have only single-factor email OTP. |
Single-factor auth for PHI access | Design complete |
| P1 | Enforce CSP (switch from report-only) Content-Security-Policy is configured but running in report-only mode on the web app. |
XSS mitigations not enforced | Headers configured |
| P1 | Implement patient right-of-access export §164.524 requires patients to be able to receive a copy of their data. Currently a 501 stub. |
Regulatory exposure | API stub exists |
| P1 | Complete formal risk assessment HIPAA §164.308(a)(1)(ii)(A) requires a documented risk analysis. |
Regulatory compliance gap | Not started |
| P1 | Mobile certificate pinning No TLS certificate pinning in the React Native app. |
MITM on compromised networks | Not started |
| P1 | Enable Android ProGuardenableProguardInReleaseBuilds is set to false. Release APKs are not obfuscated. |
Reverse engineering risk | ProGuard rules exist |
| P2 | Add dependency vulnerability scanning to CI No Dependabot, Snyk, or npm audit in CI pipeline. |
Supply chain risk | Not started |
| P2 | Expand rate limiting to all endpoints Rate limiting exists but is selective. Read-only endpoints largely unprotected. |
DoS risk on unprotected endpoints | Partial implementation |
| P2 | Ingest auth events into audit.log Login/logout events exist in Supabase auth.audit_log_entries but are not in the tamper-evident audit trail. |
Incomplete auth activity trail | Deferred |
| P2 | Wire up SIEM / alerting pipeline Audit failures emit structured log events but don’t trigger alerts or page anyone. |
Delayed incident detection | Log contract exists |
| P2 | Conduct penetration test No external penetration test has been performed. |
Unknown vulnerability exposure | Pre-launch checklist item |