Skip to main content
Security at X3 Compass

Defense in depth. Transparency in everything.

This is the deeper read. The summary version lives on the Trust page. Below: cloud architecture, threat model, RLS isolation, encryption story, incident response, compliance roadmap.

Encryption at rest
AES-256 (Supabase + R2)
Encryption in flight
TLS 1.3 + HSTS
Tenant isolation
Postgres RLS on every table
Payment processing
Stripe (we never see card data)

01 · Cloud architecture

X3 Compass runs on a small, audited stack:

  • Cloudflare Pages — static marketing + Pages Functions for the API. Cloudflare WAF + DDoS in front of every request.
  • Supabase (Postgres + Auth) — per-carrier tenant data, JWT-based authentication, every row protected by Row-Level Security policies.
  • Cloudflare R2 — customer document storage. Object-level access requires a signed token issued by an authenticated Pages Function.
  • Stripe — all subscription and payment data. We never store card numbers; we hold only a Stripe customer ID per carrier.
  • Anthropic API — Claude inference for the AI brains. No carrier data is sent except what the user explicitly types into Ask Compass.
  • Resend — transactional email only (auth links, daily digest). No marketing list, no third-party trackers in transactional mail.

02 · Tenant isolation (the part most carriers ask about)

Every customer-data row in our database carries a carrier_id column. Postgres Row-Level Security policies enforce that at the database layer, not at the API layer. Even if a future Pages Function had a bug that forgot to filter by carrier, the database would still refuse the read.

The policy on compass_drivers for example reads:carrier_id IN (SELECT carrier_id FROM compass_carrier_users WHERE user_id = auth.uid())The same shape exists on all 14 compass_* tables that hold customer data.

03 · Authentication

Supabase Auth handles password + magic-link sign-in. Sessions are JWTs stored in HTTP-only cookies — never in localStorage, never in URL parameters. The Ask Compass endpoint and every other authed function verifies the JWT signature on every request via the Supabase service role.

Password policy: minimum 8 characters, bcrypt-hashed. Forgot-password flows expire links in 1 hour and consume on first use.

04 · Threat model — what we plan against

  • Cross-tenant read. Mitigated by Postgres RLS at the database tier; the failure-closed default is "return zero rows."
  • Stripe webhook spoofing. Every webhook event signature is verified using HMAC-SHA256 against STRIPE_WEBHOOK_SECRET before any state change.
  • Prompt injection in Ask Compass. Carrier data isn't sent to the LLM unless the user explicitly types it. CFR citations in answers are round-tripped against eCFR — fabricated section numbers fail the verification and surface a warning chip.
  • Credential leakage in client bundle. No service-role keys or third-party API keys are ever in client code. The build pipeline fails if a non-NEXT_PUBLIC env var appears in a client bundle.
  • Brute-force on sign-in. Per-IP rate-limit on /api/auth/* via the same in-edge rate-limit infra as /api/ask. Lockout escalates with attempt count.
  • Insider risk. Only Joshua has Supabase project-owner rights today; service-role keys rotated quarterly. As we hire, every employee gets least-privilege access via Supabase & Cloudflare role policies.

05 · Incident response

We run an autonomous SRE stack we call Fort Knox:

  • Synthetic journey probes every 15 min against production user flows
  • Cloudflare deploy-failure watcher every 10 min — catches silent build failures
  • Stripe webhook health poller every 30 min
  • Supabase advisor scan every 30 min — catches RLS misconfig and slow-query regressions
  • Client-error spike aggregator every 15 min over the compass_client_errors table

When something trips, a doctor agentdiagnoses against a 14-pattern playbook and auto-resolves where safe (e.g. Cloudflare deploy-swap 522s, transient 403s). When the doctor can't self-resolve, the on-call human is paged with the diagnosis attached. SLAs target: detect < 10 min, customer-impact-resolve < 60 min.

We will publish a public status page when we cross 50 paying customers. Until then, transparency is via the /changelog + open GitHub.

06 · Data residency + export

Customer data lives in Supabase us-east-1 by default. Enterprise customers needing other regions (EU, FedRAMP-equivalent) can be moved on request as part of an MSA.

Full data export is one click from /app/audit-export— every compass_* table for your carrier, CSV format. We don't lock you in.

07 · Compliance roadmap

FrameworkStatusTarget
SOC 2 Type II →PreparationQ4 2026 · milestones
FCRA-compliant background checksIn productionLive via Checkr
DPA (GDPR / CCPA)AvailableOn request
HIPAA BAANot pursuing (no PHI processed)
ISO 27001Considering post-SOC 2Q2 2027 if customer demand

08 · Reporting a vulnerability

We don't have a bug bounty yet but we take security reports seriously. Email [email protected]. Initial reply within 24 hours, validated reports get a fix timeline within 72 hours. Coordinated disclosure: 90 days standard.

Enterprise security questionnaire?

Send it to [email protected]. Most one-page CAIQ/SIG-Lite filled within 48 hours.

← Back to Trust overview