Security Architecture

Built secure from the ground up.

MOVO-X Canada is engineered with a defence-in-depth approach to protect patient data. Every layer — encryption, authentication, database access, network, and CI/CD — is independently hardened and audited.

Encryption at rest
AES-256 — every row, every document
Encryption in transit
TLS 1.3 — enforced on all connections
Data residency
Canada only · ca-central-1 (Montréal)
Audit log retention
7 years · Immutable · Append-only

Encryption.

At rest — AES-256
Every database record and uploaded document is encrypted at rest using AES-256. Supabase-managed encryption applies at the volume level (AWS EBS encrypted volumes in ca-central-1). Application-level encryption is additionally applied to the most sensitive PHI fields before they reach the database, ensuring data is protected even against a database dump.
In transit — TLS 1.3
All traffic between clients, the MOVO-X API, and Supabase uses TLS 1.3. HTTP Strict Transport Security (HSTS) is enforced with max-age=31536000; includeSubDomains, preventing any downgrade to HTTP. The TLS certificate is managed by Vercel with auto-renewal.

Authentication & session management.

JWT in httpOnly cookies
Session tokens are HS256-signed JSON Web Tokens stored exclusively in httpOnly, sameSite=lax, Secure cookies. No tokens are ever written to localStorage or sessionStorage, making them inaccessible to JavaScript and immune to XSS-based token theft.
Clinic-scoped JWT
Every JWT embeds the clinicId claim. Every server route verifies the JWT and applies a mandatory WHERE clinicId = :jwt_clinic_id filter to every Prisma query. A compromised credential from Clinic A cannot access Clinic B's data — the application layer enforces this independently of the database layer.
Kiosk HMAC authentication
Physical kiosks authenticate using a per-kiosk API key and HMAC-SHA256 request signature. The kiosk cannot impersonate another clinic — each API key is bound to a single clinicId at registration time, verified on every request.
Role-based access control
Five roles define what each user can see and do: SUPER_ADMIN (MOVO-X internal), CLINIC_OWNER, CLINIC_ADMIN, DOCTOR, and RECEPTIONIST. Roles are enforced in both middleware and individual route handlers. No patient PHI is accessible to anonymous users.

Database security — Supabase RLS.

Deny-all on anon and authenticated roles
Row Level Security (RLS) is enabled on every clinic-scoped table. Policies set USING (false) on both the anon and authenticated Postgres roles. Even if the Supabase anon key were leaked, zero rows would be returned. The anon key can only be used for the public queue display screen, which has its own narrowly scoped policy.
service_role from server only
The Supabase service_role key (which bypasses RLS) is never sent to the browser. It is only used by Vercel Functions running in the Node.js runtime, and it is stored in Vercel's encrypted environment variable store. The key is rotated on a quarterly schedule.
No raw SQL in routes
All application queries use Prisma's typed query builder. Raw SQL is prohibited in route handlers (enforced in code review). This eliminates SQL-injection attack surfaces in the application layer. Raw SQL is only used in append-only database migrations.
Connection pooling
PgBouncer (port 6543) is used for application connections. The Prisma DATABASE_URL points to the pooler, limiting max open connections. Direct Postgres access (port 5432) is used only for migrations and admin scripts — never from production application code.

CI/CD security pipeline.

OWASP ZAP scanning
Every pull request triggers an OWASP ZAP dynamic scan against a staging environment. Critical and high-severity findings block the merge. Results are attached to each PR as an artefact.
Pre-commit secret blocker
A pre-commit hook (and CI step) scans every commit for secrets, tokens, private keys, and connection strings using pattern matching. Any detected secret blocks the push. Historical secret exposure is checked on every dependency update.
Dependency audit
pnpm audit runs on every push. High and critical CVEs in direct dependencies block deployment. Dependabot alerts are triaged weekly.

Audit logging & data residency.

Audit log retention — PHI vs operational
PHI audit logs (who accessed which patient record, when, and from where) are retained for 7 years per PHIPA standards — applicable to all Ontario clinics and adopted as the MOVO-X Canada baseline. Log entries include: actor (user ID + role), action, affected table and row IDs, timestamp (UTC), and source IP. Operational/access logs (server access, API calls, infrastructure events) are retained for 90 days and rotated. All logs are append-only and cannot be modified or deleted by any application role.
Canada-only data residency
The Supabase database project is in AWS ca-central-1 (Montréal, Québec). The Vercel production region is yul1 (also Montréal). No patient personal information is replicated to servers outside Canada. Cross-border support access requires a Law 25 Privacy Impact Assessment.
No PHI to third parties
Patient personal health information is never transmitted to third-party analytics providers, advertising networks, or AI training pipelines. The only permitted sub-processors are Supabase (ca-central-1), Vercel (yul1), Resend (transactional email), and optionally Twilio (SMS notifications) — all contractually bound to process data only as directed and not to use it for their own purposes.
Vercel security headers
Every response includes: X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, a strict Content-Security-Policy, and Permissions-Policy blocking camera and geolocation APIs.

Request the security architecture doc.

Full security architecture documentation, penetration test reports, and SOC 2 artefacts are available under NDA to healthcare organisations evaluating MOVO-X.