Trust Center

Security & Privacy Architecture

StrataView stores data used in regulatory proceedings and legal exhibits. This page describes how that data is protected, who can access it, and how incidents are handled. Last reviewed: June 2026.

Overview

Architecture principles

StrataView is a Netlify-hosted static site backed by Supabase for authentication, database, and storage. All sensitive operations run in Netlify Functions (Node.js) or Supabase database functions. The browser never receives a service-role key. Every assessment record and audit event is stored in Supabase Postgres with row-level security (RLS) enforced at the database layer.

Assessment records produced by StrataView are used as exhibits in environmental permitting proceedings and legislative filings. The security model reflects this: our primary concern is data integrity (can a record be silently altered?) and data isolation (can one tenant see another's data?), not just confidentiality.

Security issues should be reported to security@strataview.earth. Our responsible disclosure policy is at /.well-known/security.txt.

Identity & Authentication

Who can access what

Authentication is handled by Supabase Auth (GoTrue), a purpose-built identity service based on PostgreSQL. StrataView does not implement a custom authentication stack.

Authentication flow

  1. User enters email + password at /login/.
  2. Supabase Auth validates credentials and issues a short-lived JWT (1 hour) plus a long-lived refresh token stored in localStorage behind the site origin.
  3. If the user has enrolled TOTP MFA, the session is held in the "aal1" assurance level until the TOTP challenge is satisfied, which upgrades it to "aal2". Protected routes require aal2.
  4. JWTs are validated at the database layer via Supabase's auth.jwt() function. The application server never stores session state.

TOTP MFA

Time-based one-time passwords (TOTP / RFC 6238) are available for all accounts. New users are prompted to enroll during first login. Enrollment state is tracked in Supabase's auth.mfa_factors table and surfaced in the app shell. TOTP codes are verified against the Supabase MFA challenge API. The TOTP seed never transits the application layer.

Optional SAML SSO (Enterprise)

Enterprise-tier tenants may configure SAML 2.0 single sign-on via Supabase's identity provider integration. SAML assertions are validated by Supabase; the SP-initiated login flow redirects to /app/ on success. SAML configuration is performed in the Supabase Auth dashboard under "SSO Providers" and requires a dedicated subdomain or relay state parameter.

Password policy

Supabase Auth enforces a minimum password length of 12 characters. Passwords are stored as bcrypt hashes (cost factor 10) within the Supabase-managed auth.users table, which is inaccessible to application-layer RLS policies.

Data Isolation

Row-level security per tenant

Every table in the app schema carries a tenant_id column. Row-level security policies enforce that authenticated queries can only return or mutate rows where tenant_id matches the tenant extracted from the caller's JWT, using the app.jwt_tenant_id() helper function which reads the custom claim injected at login.

RLS is enabled on every application table: tenants, app_users, audit_events, rate_limits, tenant_counties, briefs, brief_grants, contact_messages. Disabling RLS on any table requires explicit migration and review.

The public_analytics schema stores visitor and session data. It is isolated from the app schema. Analytics tables have no tenant_id and are not accessible to tenant-scoped JWT tokens. Analytics reads require the service-role key, which is restricted to Netlify Functions.

Tenant provisioning

Tenants are created by the StrataView administrator using the service-role key. There is no self-service tenant creation path. New users are added to a tenant by the tenant owner; they cannot add themselves. User shell records are pre-created in app.app_users with status 'invited'; the on-signup database trigger links the Supabase Auth user ID on first sign-in.

Audit Trail

Hash-chained audit events

Every write to any application table appends a row to app.audit_events. Each event carries:

  • id: UUID (immutable primary key)
  • tenant_id: owning tenant
  • actor_id: the app_users.id who performed the action
  • action: verb (INSERT, UPDATE, DELETE, LOGIN, EXPORT, etc.)
  • table_name, row_id: subject of the action
  • payload: JSONB snapshot of changed fields (new values only; passwords excluded)
  • prev_hash: SHA-256 hash of the preceding event row in insertion order
  • event_hash: SHA-256 of (id || actor_id || action || payload || prev_hash)
  • created_at: server-side timestamp (not client-supplied)

The app.verify_audit_chain() Postgres function re-computes every hash in sequence and returns the count of mismatches, the total rows checked, and a valid boolean. The API endpoint GET /api/audit/verify exposes this to authorized callers.

Audit rows are append-only. There are no UPDATE or DELETE policies on audit_events, not even for the service-role key at the application layer. Any modification attempt would require direct database access, which is logged by Supabase's audit logging at the infrastructure level.

Encryption

In transit and at rest

Transport (TLS 1.3)

All traffic between clients and strataview.earth is encrypted with TLS 1.3 via Netlify's edge. HTTP requests are permanently redirected to HTTPS (301). The Strict-Transport-Security header is set with a two-year max-age and includeSubDomains. TLS termination for Supabase API calls uses the same TLS 1.3 standard on AWS infrastructure.

At-rest encryption (AES-256)

Supabase Postgres storage is encrypted at rest with AES-256 on AWS EBS volumes. Supabase manages key rotation on a schedule controlled by AWS KMS. StrataView does not operate its own encryption keys for database storage. Key management is delegated to Supabase and AWS. This is documented for SOC 2 purposes as a sub-processor control.

Policy brief PDFs are stored in Supabase Storage (S3-backed). Download links are time-limited signed URLs generated by api-brief-grant.js using a separate HMAC token. The token is short-lived (15 minutes) and single-use, marked in the database.

SOC 2 Common Criteria

Key control mappings

The following table maps StrataView controls to SOC 2 Trust Services Criteria (2017 version). This is a self-assessment and has not yet been independently audited.

CC Criterion Description StrataView Implementation Status
CC6.1 Logical access security Supabase Auth JWT + RLS per tenant; TOTP MFA available Implemented
CC6.2 New user provisioning Pre-created invited shells; owner-only seat assignment; on-signup trigger links auth ID Implemented
CC6.3 Access removal Offboarding runbook: set status='suspended', invalidate Supabase session, revoke grants Implemented
CC6.7 Data transmission controls TLS 1.3 enforced; HSTS with 2-year max-age; all APIs HTTPS-only Implemented
CC7.2 Monitoring for anomalies Rate-limit table + rate_limit_check(); Netlify function logs; Supabase log drain Partial
CC7.4 Incident response Documented runbook in SECURITY-RUNBOOKS.md; security@ contact; 72hr breach notification target Implemented
CC9.2 Risk assessment Architecture review (StrataView-Architecture-Review.md); annual re-review committed Partial
A1.2 Availability & capacity Netlify Edge CDN; Supabase managed Postgres; no single-host dependency Implemented
PI1.1 Processing integrity Hash-chained audit log; verify_audit_chain(); append-only audit table Implemented
P3.1 Privacy notice Privacy policy at /legal/privacy/; analytics self-hosted; no third-party trackers Implemented

Incident Response

How we respond to security events

Security incidents are reported to security@strataview.earth. Our responsible disclosure policy is at /.well-known/security.txt. We acknowledge reports within 48 hours and commit to status updates every 7 days until resolution.

If you have discovered a vulnerability, please do not publish it publicly until we have had at least 90 days to investigate and remediate. Coordinated disclosure is appreciated.

Breach notification

In the event of a confirmed data breach affecting personal data, we will notify affected users and, where required, the applicable supervisory authority (Michigan Attorney General consumer protection division for Michigan residents) within 72 hours of confirmation. Notification will include: nature of the incident, categories of data affected, likely consequences, and measures taken or proposed.

Runbooks

Detailed operational runbooks are maintained in SECURITY-RUNBOOKS.md in the project repository. Topics include: incident response, suspected account takeover, credential rotation, data subject requests, audit chain verification, disaster recovery test, and user offboarding.

Compliance Posture

SOC 2 readiness statement

StrataView is designed in alignment with SOC 2 Type II Trust Services Criteria for Security, Availability, and Processing Integrity. As of June 2026, we are in the pre-audit phase: controls are implemented and documented, but an independent audit has not yet been conducted.

We are evaluating Vanta and Drata for continuous compliance monitoring. Quarterly audit chain verification runs are automated via the soc2-evidence.yml GitHub Actions workflow, which calls /api/audit/verify and stores the JSON result as a signed GitHub Actions artifact.

If your organization requires a current SOC 2 report as a condition of procurement, please contact security@strataview.earth to discuss our controls documentation and timeline.

Third Parties

Sub-processors

StrataView uses the following sub-processors that may handle personal data. We do not use third-party analytics, advertising, or tracking services.

Sub-Processor Role Data Processed Location
Supabase Authentication, database, file storage Account credentials, application data, audit events AWS us-east-1 (default)
Netlify Web hosting, edge CDN, serverless functions Request logs (IP, user agent), function invocations US + global edge
Cloudflare DNS resolution only (no proxy) DNS query logs (standard) Global
Transactional email provider Brief download link delivery, contact confirmation Name, email address, download intent Configured per deployment

For questions about sub-processor agreements or data processing agreements (DPAs), contact privacy@strataview.earth.

See also: Privacy Policy · Terms of Service