Enterprise Security Review
A buyer-facing reference for IT Security, CISOs, and SOC 2 auditors. The three pillars enterprise teams must be able to audit before signing: Access Control, Audit Logs, and Data Isolation. Every control is mapped to SOC 2 CC-series, HIPAA, FERPA, and COPPA where applicable, and differentiated across the 6 FFH Gears.
1 · How access control works
Every action in the FFH platform is authorized on four axes — Role, Team (Gear scope), Resource type, and Action verb. Permissions are enforced at the database layer via Postgres Row-Level Security, so a bug in the application cannot bypass them.
① The four axes of permission
- Role —
platform_admin,super_admin,moderator,group_admin,member, plus domain roles (teacher,student,guardian,clinician,patient,chamber_director,phit_operator,donor,trustee). - Team / Gear scope — every identity carries a Gear claim in its JWT. A 360° Health Academy teacher cannot see PHIT Scores records; a Chamber of Health Systems Director cannot see Tools & Trackers health data.
- Resource type — courses, student records, PHIT score events, Chamber directory, tracker entries, Studio media, audit rows — each has its own policy set.
- Action verb —
read,create,update,delete,export,impersonate. Destructive and export actions are always logged and often require a second factor.
② Enforcement layers (defense in depth)
- Identity — Supabase Auth + SSO (Google, Microsoft, SAML for enterprise). MFA required for all admin-tier roles; optional+encouraged for everyone else.
- JWT claims — role, Gear scope,
org_id, and session expiry travel with every request. - Row-Level Security (RLS) — Postgres policies reject any query that crosses tenant, role, or Gear boundaries — even if the application code has a bug.
- UI + API — route guards and API middleware are a convenience layer; the database is the enforcement layer.
- JIT admin — elevated access is requested, approved, time-boxed, and auto-expires.
③ Least privilege & separation of duties
- No shared accounts. Every action is attributable to a named human or service identity.
- The user who approves a sensitive change is never the user who executes it (enforced for admin elevation, billing, and PHI export).
- Read-only default for new hires; write scopes granted per-Gear as needed.
- Service accounts are scoped to a single Gear and a single action type.
④ Deprovisioning & lifecycle
- Off-boarding revokes JWT + rotates session keys within 60 seconds of HR signal.
- Quarterly access reviews — owners re-attest that their team still needs the access they have.
- Dormant accounts (>90d no login) auto-downgrade to read-only; >180d auto-disable.
- Password rotation every 365 days for humans; 90 days for service keys.
SELECT attempts across roles and Gears and confirm RLS rejects cross-boundary reads.Sample role → action permission grid
| Role | Read own | Read team | Read cross-Gear | Write | Export PII/PHI | Admin elevate | Impersonate |
|---|---|---|---|---|---|---|---|
| Student / Member / Patient | Yes | No | No | Self-only | No | No | No |
| Teacher / Clinician / Director | Yes | Yes | No | Team scope | Logged + 2FA | No | No |
| Group / Gear Admin | Yes | Yes | No | Gear scope | Logged + 2FA | Within Gear | No |
| Platform Admin | Yes | Yes | JIT only | Platform | JIT + 2FA + log | JIT, time-boxed | With ticket |
| Security / Auditor | Yes | Yes | Read-only | No | No | No | No |
2 · How audit logs work
Audit logs are immutable, queryable, and physically separate from application data. The application can append, but cannot read, update, or delete. This is a SOC 2 CC7.2 / CC7.3 requirement — and a HIPAA §164.312(b) requirement for PHI-touching Gears.
① What every audit event captures
- WHO —
user_id, role, session_id, identity provider. - WHAT — action verb, resource type, resource id, pre-state hash, post-state hash.
- WHEN — UTC timestamp at microsecond precision.
- WHERE — source IP, user agent, geolocation (country/region), device fingerprint.
- WHY — intent/reason code for sensitive actions (PHI export, impersonation, admin elevation, bulk delete).
- HOW — hash chain: each row embeds the hash of the prior row so any tampering is detectable.
② Physical separation from app data
- Audit data lives in a dedicated Postgres schema (
audit.*) with its own database role. - Enterprise tier: audit data lives in a separate database instance entirely, written to via an append-only API.
- The application role has
INSERTonly. NoSELECT, noUPDATE, noDELETE— ever. - Only the
security_readerrole canSELECT— and every read is itself audited. - Backup schedules are independent; a compromise of the app backup does not compromise audit.
③ Immutability (WORM)
- Hot window (0–90 days): append-only Postgres with row-level hash chaining.
- Warm window (90d – retention end): archived nightly to S3 Object Lock (compliance mode) — literally unable to be overwritten or deleted until retention expires.
- Hash chain verification runs hourly; any break pages the on-call Security engineer.
④ Queryability & export
- Security IT dashboard (the view embedded below) — filter by user, time, resource, action, IP, Gear.
- Saved queries for common SOC 2 scenarios: "all admin elevations in Q," "all PHI exports by user X," "all failed logins from new geo."
- Streaming integration to buyer SIEM: Splunk HEC, Datadog, Elastic, Sumo Logic, Microsoft Sentinel.
- CSV / JSON export gated behind
security_reader+ ticket reason + 2FA.
Retention schedule by data class
| Data class | Regulation | Retention | Storage |
|---|---|---|---|
| PHI score events (PHIT Scores & Data Engine) | HIPAA §164.312 | 7 years | WORM, region-locked, BAA-covered |
| Self-reported health events (Tools & Trackers) | HIPAA-equiv | 7 years | WORM, field-level encrypted |
| Student record access (360° Health Academy, STEAM TEAMS) | FERPA | 5 years after withdrawal | WORM |
| Minor account events (under 13) | COPPA | Until deletion request + 1 year | WORM |
| Chamber directory & Workforce events | SOC 2 | 3 years | Standard WORM |
| Admin / security events (all Gears) | SOC 2 CC7.2 | 3 years | WORM |
SELECT by a security_reader creates its own audit event in a second-order audit table. The buyer's compliance team can verify who looked at what, when.Sample audit record (redacted)
{
"event_id": "evt_01HYZQ9M3K...",
"ts": "2026-04-23T14:07:32.184923Z",
"actor": { "user_id": "usr_7f2...", "role": "gear_admin", "gear": "phit" },
"action": "record.export",
"resource": { "type": "phit_event", "id": "phi_913...", "org_id": "org_42" },
"context": { "ip": "203.0.113.17", "geo": "US-PA", "ua": "Mozilla/5.0 ...", "mfa": true },
"intent": "Insurer request, ticket #SEC-10451",
"prev_hash": "3a7c...e91",
"row_hash": "b2d1...44f"
}
3 · How client data is isolated
Every tenant gets architectural isolation, not just logical flags. The default tier uses Row-Level Security with a tenant claim; the enterprise tier gets a fully dedicated Supabase project, storage bucket, and secret set — provisioned by clone, so no data path ever crosses tenants.
① The four tenancy tiers
- Shared multi-tenant (default) — shared DB, RLS-enforced
org_idon every row. Cross-tenant reads are rejected at the DB layer. - Dedicated schema — tenant gets its own Postgres schema within a shared cluster. Stronger blast-radius separation.
- Dedicated database — tenant gets its own database in a shared Supabase project. Own connection pool, own backups.
- Dedicated instance (enterprise) — tenant gets a cloned Supabase project, Vercel project, storage bucket, and keys. Completely separate failure domain and data plane.
② Yes — cloning produces isolation automatically
- Provisioning is scripted: running
clone-tenant.sh <tenant>creates a net-new Supabase project, Vercel project, domain, and secret set. - All keys (JWT secrets, service role keys, storage keys, SMTP creds) are regenerated per clone — no secret is ever shared across tenants.
- Networks are separate by construction — the cloned instance is not peered with any other tenant.
- An operator error that points the wrong tenant at the wrong DB is caught by RLS + org_id mismatch on the very first query.
③ Encryption & key management
- At rest — AES-256 via Supabase/Postgres storage encryption; enterprise tier can bring their own KMS key (BYOK).
- In transit — TLS 1.3 minimum, HSTS, strict cipher suites.
- Application-level — additional field-level encryption for PHI fields in PHIT Scores & Data Engine and Tools & Trackers; keys rotate quarterly.
- Secrets stored in Vercel / Supabase secret stores, never in source control.
④ Backups, DR, and data residency
- Automated daily backups with point-in-time recovery to 7 days (shared) / 35 days (enterprise).
- Backups inherit the tenancy boundary — a shared backup never contains dedicated-instance data.
- US region by default; EU/Canada/Australia regions available for dedicated-instance tenants with residency requirements.
- Quarterly restore drills to validate DR runbooks.
4 · 6-Gear security matrix
Not every Gear carries the same risk, so not every Gear carries the same controls. This is the per-Gear profile IT Security should use when scoping an enterprise rollout.
| Gear | Touches PII | Touches PHI | Touches minors | Compliance scope | Default tenancy | MFA required | Audit retention |
|---|---|---|---|---|---|---|---|
| Chamber of Health Systems Directors, chapters & Chamber directory |
Yes (directory) | No | No | SOC 2 | Shared multi-tenant (RLS) | Directors & admins | 3 yrs |
| PHIT Scores & Data Engine Population health scoring & analytics |
Yes | Yes | If pediatric | HIPAA SOC 2 | Dedicated instance (BAA) | All roles | 7 yrs |
| 360° Health Academy Learning platform, Bingo Cards, courses |
Yes | Light (wellness) | Yes | FERPA COPPA SOC 2 | Dedicated schema per district | Teachers & admins | 5 yrs post-withdrawal |
| Tools & Trackers Live It Trackers & self-reported health |
Yes | Yes (self-reported) | If minor users | HIPAA-equiv COPPA SOC 2 | Shared + field-level encryption | Required for coaches; opt-in for members | 7 yrs |
| STEAM TEAMS & Reality Health Games Classroom & team-based gameplay |
Yes | No | Yes (classroom) | FERPA COPPA SOC 2 | Dedicated schema per school | Teachers & admins | 5 yrs post-withdrawal |
| Workforce Training & OmniMedia SHARE It Studio Workforce learning + content production |
Yes (employee) | No | If HS interns | SOC 2 FERPA (student creators) | Dedicated schema per org | All users | 3 yrs |
SOC 2 control mapping (Common Criteria)
Where each pillar above lands against the SOC 2 Trust Services Criteria our Type II audit is scoped to.
Evidence & documents
What your IT/Security team should download and review.
Request .docx →
Download .docx →
Download .docx →
Download .docx →
Download .docx →
Download .docx →
Open tracker →