Back home

Security & data residency

Australian-built. Australian-hosted. Australian-governed.

Korvos handles the most sensitive material your agency produces — customer identity documents, beneficial ownership disclosures, suspicious matter reports. Every architectural choice below was made to keep that data in Australia, prove its integrity for seven years, and survive an AUSTRAC desk review.

Hosted in
Sydney (ap-southeast-2)
AI inference
Bedrock Sydney
Retention
7 years, append-only
RLS posture
FORCE on every table

Your data stays in Australia

Every byte of agency data — customers, parties, programmes, KYC records — is stored and processed in ap-southeast-2 (Sydney). The AI itself runs on AWS Bedrock Sydney; no prompts, agency content, or compliance records ever transit US infrastructure.

  • Database: Supabase Postgres, ap-southeast-2
  • AI inference: AWS Bedrock Sydney (Claude Sonnet) — model IDs with cross-region prefixes (us.*, eu.*, ap.*) are rejected at the env-validation layer so a misconfigured deploy fails at boot, not at first inference
  • Object storage: Supabase Storage (Postgres-backed, ap-southeast-2). Identity documents, sealed PDFs, and KYC bundles all sit in tenant-prefixed paths
  • Application: Vercel syd1 — every API route and server action runs in Sydney
  • Where US-hosted services are unavoidable (Inngest workflow orchestration, Stripe billing webhooks), payloads carry only opaque UUIDs — never names, addresses, or party data. The snapshot a workflow needs is re-read inside each step from Sydney; nothing PII-shaped ever crosses the step boundary

Multi-tenant isolation, enforced at the database

Korvos is a shared platform — every agency runs on the same infrastructure — but FORCE row-level security at the PostgreSQL level means a query for one agency cannot return another agency's data even if the application code has a bug. The database itself is the boundary.

  • FORCE RLS on every public-schema table — verified by audit script
  • Every business table has a per-tenant policy keyed on current_tenant_id() (resolved from the JWT)
  • Service-role access restricted to tenant provisioning, schema migrations, and a small set of documented admin paths — enforced by a CI lint rule that refuses imports of the admin client outside the four allowed patterns
  • Cross-tenant FK references on client-supplied IDs are guarded by an explicit ownership precheck before any INSERT (matter_id, party_id, alert_id, etc.)

Tamper-evident AML records

AUSTRAC requires you to prove the integrity of your compliance records years after the fact. Korvos achieves this with append-only, hash-chained tables: AML records can only be inserted and read — never updated, never deleted. Each row's hash is chained to the previous row's hash, so any tampering anywhere in the history breaks the chain.

  • INSERT and SELECT only — UPDATE, DELETE, and TRUNCATE revoked from authenticated and anon roles at the PostgreSQL level
  • Defence-in-depth BEFORE INSERT/UPDATE/DELETE forbid_mutation() triggers reject any mutation attempt that slips past the grant model
  • SHA-256 hash chain across every AML record (compute_hash_chain function), verifiable in seconds via verify_chain()
  • Risk assessments, programmes, KYC results, screening outcomes, monitoring alert resolutions, SMR records, TTR records, sanctions list versions — all chained
  • Verifier framework re-derives generated artefacts against source data and refuses to seal on anomalies

Seven-year retention, enforced by Postgres

AML/CTF Rules 2025 r 5-15 requires reporting entities to retain records for seven years from the end of the customer relationship. Korvos enforces this at the database layer: AML records cannot be modified or deleted by anyone — including us — for the duration of the retention period.

  • Append-only tables backed by REVOKE statements on UPDATE / DELETE / TRUNCATE for every authenticated role
  • Daily Supabase managed backups (point-in-time recovery, ap-southeast-2) provide durable storage independent of application code
  • Every AUSTRAC-relevant artefact (programmes, KYC bundles, screening reports, monitoring alerts, SMRs, TTRs) lives in append-only chain tables for the full retention period
  • AUSTRAC-auditable export available on demand via the audit log for desk reviews and litigation holds

Tipping-off-controlled SMR access

Suspicious Matter Reports, sanctions matches, and PEP findings are restricted to the Compliance Officer and Senior Manager roles. Every privileged read is logged — who, when, from where — and surfaces in the audit trail. Section 123 of the AML/CTF Act treats unauthorised disclosure as a criminal offence; the platform is engineered to make it structurally impossible.

  • Role-based access enforced in the database via the can_access_smr() function, not just the UI
  • Append-only access log for every privileged read of SMR / sanctions / PEP data
  • Denied access attempts are themselves recorded as tipping-off incidents in the chain — a missed access becomes evidence
  • Generic 'not found' responses on denied access so the act of denying does not itself leak the existence of the record

Encryption at rest and in transit

Standard table stakes: TLS 1.2+ on every connection, AES-256 at rest, and no secret values in logs or error reports.

  • TLS 1.2+ on all client and service-to-service traffic
  • AES-256 at rest for database and object storage (Supabase managed)
  • Third-party API errors are unwrapped before logging — only structured fields (status code, request ID, error code) are captured. Raw response bodies that may echo passport numbers or DOBs are never written to logs
  • Supabase Vault is used for tenant-bound secrets where applicable; the schema is wired and roll-out follows each integration as it ships

Bot-gated authentication

Authentication endpoints are the most-attacked surface of any SaaS. We've engineered the signup, login, and password-reset flows to refuse the things automated abuse looks like.

  • Cloudflare Turnstile on signup, login, and forgot-password — bot challenges run before the password ever reaches Supabase
  • Per-IP rate limits on every auth endpoint (signup 3/hr, login 10/15min, forgot-password 5/hr)
  • Anti-enumeration: signup/login responses don't differentiate registered from unregistered emails. Forgot-password always returns success regardless of whether the email is on file
  • Session cookies are HttpOnly + Secure + SameSite=Lax with a Strict-Transport-Security header on every response
  • AAL2 (multi-factor) gate for principal accounts before any tenant-scoped action
  • Stripe webhooks are signature-verified and event-id deduplicated before any handler runs

Privacy by architecture

Australian Privacy Principle 8 governs cross-border data disclosure. Most platforms address it with a privacy policy. Korvos addresses it by ensuring there is no cross-border disclosure to begin with — the data simply doesn't leave the country.

  • APP 8 satisfied by infrastructure choice, not contractual workaround
  • Inngest workflow payloads carry opaque UUIDs only — every PII fetch happens inside an in-region step
  • Transactional email never carries underlying record content; compliance notifications include only a sign-in link
  • The cross-tenant identity hash registry uses a keyed HMAC-SHA256: only the digest is stored, the key is held server-side, and the function is one-way

What we don’t do

We don’t train public AI models on your data — AWS Bedrock does not use customer inputs to improve foundation models, and we never export your data to any other AI provider. We don’t sell identified agency or party data to third parties. We don’t cross-reference AML/CTF compliance data with commercial intelligence products — that separation is enforced at the database level.