The code that implements every claim below is AGPL-3.0 open source on GitHub. This is the engineering detail behind the commitments on the Security overview, our BAA, and our Privacy Policy. We keep the receipts here so the values you read are the values that ship.
In transit
TLS required. All connections to app.pablo.health use TLS. Plain HTTP requests are rejected with HTTP 400 by the application's HTTPS-enforcement middleware.
HSTS. Response header on every production response: Strict-Transport-Security: max-age=63072000; includeSubDomains; preload (two years, with subdomains, preload-list eligible). The two-year window is the IETF + browser-vendor recommendation for preloaded production sites; longer is more secure because the browser remembers the HTTPS-only commitment longer.
WebSocket authentication. Real-time channels (Practice Mode) require a single-use opaque ticket with a 30-second lifetime, issued through an authenticated REST call. Firebase ID tokens are never embedded in WebSocket URLs (which are logged by proxies, CDNs, and browsers).
At rest
Cloud SQL. Every block on disk encrypted with AES-256 using Google-managed keys.
Cloud Storage. Every object encrypted with AES-256.
Application-layer column encryption. Google Calendar OAuth tokens and iCal feed URLs are additionally encrypted with AES-256-GCM at the application layer before storage.
Tenant isolation
Schema-per-tenant. Each practice receives its own PostgreSQL schema (practice_<id>). Application code resolves the practice schema from the authenticated email at the start of every request and sets the database session's search_path before any handler runs.
Commit-time template-schema guard. The request middleware refuses to commit a database transaction if the session is still pointed at the default template schema — a defense-in-depth check against bugs that bypass schema resolution.
Postgres Row-Level Security. RLS is FORCE-enabled on every table that carries a user_id column. The RLS policy fails closed when the per-request user context (app.current_user_id) is unset, so a query that somehow ran outside our middleware returns zero rows rather than leaking across users.
Identity and access
MFA required. Time-based one-time-password (TOTP) MFA is required by default for all production users. The signup flow gates application access on enrollment.
Session-token revocation on every request. Firebase ID tokens are verified with the check_revoked=true flag on every request, not just at sign-in, so a revoked token cannot continue to ride a long-lived browser tab.
AI processing
Routed through Vertex AI. All large-language-model inference (Google Gemini and Anthropic Claude) runs through Google Cloud Vertex AI under Google Cloud's HIPAA BAA and the Cloud Data Processing Addendum, both of which contractually prohibit the use of customer content for model training.
What goes where. Note generation, Practice-mode AI patient, EHR navigation: Gemini via Vertex. Audit-log behavioral review: Anthropic Claude via Vertex, on PHI-free metadata only.
No consumer-tier APIs. Production code does not call api.openai.com, api.anthropic.com, or generativelanguage.googleapis.com. The weekly internal pentest probes for egress to those hosts and surfaces any finding in the next dated report; an active finding triggers a release hold.
Defense-in-depth. The optional “Improve Gemini for Google Cloud” project setting (which only affects certain Duet AI / Cloud Code features, not the raw Vertex AI generate-content path Pablo uses) is disabled on our project.
Audit logging and behavioral monitoring
PHI-free audit log. Every action that touches PHI writes a structured audit record. Audit-log contents are PHI-free by contract — a runtime assertion in the audit-write path rejects a write that would include a denylisted PHI field.
Seven-year retention with auto-purge. Audit records expire seven years after the action date and are physically removed by a daily purge job.
Daily HIPAA log review. A daily job runs over every tenant's audit logs and looks for behavioral patterns that indicate possible misuse — off-hours access bursts, novel user/patient pairings, surname matches between user and patient, no-treatment-relationship views, bulk deletes, and export-rate spikes against a per-user baseline. Findings are summarized by an LLM (Anthropic Claude on Vertex, run on PHI-free behavioral metadata only) and written to a retention-locked compliance bucket. High-severity findings emit an alerting log entry that operators wire to Cloud Monitoring for paging.
Backup and retention
Cloud SQL backups. Encrypted, rotated on a thirty-day cycle. PHI deleted from the live database disappears from every backup within thirty days as the rotation progresses. Backups are not used to recover deleted data except under the Covered Entity's written instruction.
Three-stage deletion. See Privacy Policy §10 and BAA §7 for the user-facing retention timeline; the implementation runs as scheduled Cloud Run Jobs (hard_purge_cron, audit_retention_cron, audio_retention_purge).
Egress allowlist
The application boundary is allowlisted to the subprocessors named in the BAA §5.2, our Privacy Policy §5, and the Where your data lives table on the Security overview. The weekly internal pentest probes for egress to non-allowlisted hosts; any finding is surfaced in the next dated pentest report and triggers a release hold while it is investigated. The release hold is operational today (an on-call engineer reviews the report and pauses release) — automating it as a hard CI gate is on our roadmap.