Data Residency Posture — Audit Intelligence
Status: production. Owner: Eden Pearson, EDENIC Consulting. Last reviewed: 2026-05.
Audit Intelligence handles sensitive Australian audit data — trial balances, working papers, evidence files, fraud analytics, client correspondence, and the immutable audit trail. Every customer is an Australian audit firm. All client data is treated as if it must remain within Australia, in line with the audit profession's expectations and the requirements of the Privacy Act 1988 (Cth) including the Australian Privacy Principles (APPs).
This document is suitable for sharing with firms conducting due diligence.
1. Summary for diligence
| Question | Answer |
|---|---|
| Where is structured customer data stored at rest? | Neon Postgres, pinned to AWS ap-southeast-2 (Sydney). No replicas outside Australia. |
| Where are uploaded files (evidence, trial balances, archived audit files) stored? | Cloudflare R2, buckets pinned to the APAC location hint (Sydney/Melbourne data centres). |
| Where does application compute run? | Cloudflare Workers at Cloudflare's Sydney / Melbourne / Perth Points of Presence (POPs) for Australian users. |
| Does customer data leave Australia at rest? | No. Structured data, files, backups all remain in ap-southeast-2 / APAC. |
| Does customer data leave Australia in transit? | Only via two named flows: (1) AI inference calls to OpenAI / Anthropic / Google (US endpoints), disclosed below; and (2) outbound email via Resend (US infrastructure). Both flows are TLS 1.3, contractually bound by Standard Contractual Clauses / DPA, and disclosed in the privacy policy. AU-only AI inference is available as a configurable option. |
| What's the retention period? | 7 years (ASIC + APES 320 + ASA 230). |
| What's the breach notification commitment? | 72 hours to OAIC under the Notifiable Data Breaches scheme. |
2. Applicable regulation
| Instrument | Obligation |
|---|---|
| Privacy Act 1988 (Cth) + APPs | Lawful collection, secure storage, transparency, access & correction rights. APP 8 governs cross-border disclosure. |
| Privacy Act Reforms (2024–26) | Privacy Impact Assessment (PIA) for new SaaS with AI; tiered penalties for serious interferences. |
| Notifiable Data Breaches (NDB) scheme | Assess within 30 days; notify OAIC + affected individuals within 72 hours of becoming aware of an "eligible data breach". |
| APES 320 — Quality Management | Audit firms must retain quality-management records. Platform preserves them immutably for the retention period. |
| ASIC Corporations Act recordkeeping | 7-year retention for audit working papers and supporting evidence. |
| ASA 230 / ISA 230 | Audit documentation retention 7 years post audit report date. |
| APES 110 — independence & confidentiality | Strict access control; auditor sign-off on every WP / journal / suggestion. |
The platform is designed so that compliance with each obligation is enforced architecturally, not just procedurally — see §6.
3. Architecture (current, production)
┌──────────────────────────────┐
AU user (browser) ───▶ │ Cloudflare Pages (SYD POP) │
│ - Next.js Edge runtime │
│ - tRPC + middleware │
└──────────────┬───────────────┘
│
┌──────────────────────────────┼──────────────────────────────┐
│ │ │
┌────────▼─────────┐ ┌──────────▼──────────┐ ┌────────▼─────────┐
│ Neon Postgres │ │ Cloudflare R2 │ │ Outbound flows │
│ ap-southeast-2 │ │ APAC location hint │ │ │
│ Sydney (SYD) │ │ Sydney/Melbourne │ │ - OpenAI (US)* │
│ │ │ │ │ - Anthropic (US)*│
│ - schema/firm │ │ - evidence │ │ - Google (US)* │
│ - audit trail │ │ - tb-imports │ │ - Resend (US) │
│ - WP content │ │ - archive │ │ │
│ - 7yr retention │ │ - lifecycle policy │ │ All TLS 1.3 │
└──────────────────┘ └─────────────────────┘ └───────────────────┘
* STRICT_AU_AI=1 routes sensitive AI features through AWS Bedrock
in ap-southeast-2, keeping inference in Australia.3.1 Structured data — Neon Postgres
- Region:
ap-southeast-2(Sydney), set at project creation. Region is
immutable on the Neon project; cannot be changed without dump + restore.
- Replicas: none outside
ap-southeast-2. Neon's optional multi-region
read replicas feature is deliberately not enabled.
- Multi-tenancy: schema-per-firm —
firm_{firmId}Postgres schema for
every audit firm. Cross-firm queries are architecturally impossible (the tRPC middleware sets search_path per request).
- Backups: Neon point-in-time recovery (PITR) — 7 days. All backup data
remains in ap-southeast-2.
- Encryption at rest: AES-256 (managed by Neon on AWS storage).
- Encryption in transit: TLS 1.3 mandatory (Neon HTTP driver enforces it).
- Driver:
@neondatabase/serverlessHTTP driver, called from Cloudflare
Workers. Each query is a stateless HTTPS request; no long-lived connections cross the Cloudflare → Neon boundary.
3.2 Files — Cloudflare R2
Three buckets, all created with the APAC location hint:
wrangler r2 bucket create audit-intel-evidence --location apac
wrangler r2 bucket create audit-intel-tb-imports --location apac
wrangler r2 bucket create audit-intel-archive --location apac| Bucket | Contents | Retention |
|---|---|---|
audit-intel-evidence | Client-uploaded evidence files (board minutes, contracts, confirmations) | 7 years post file-lock |
audit-intel-tb-imports | Raw trial balance imports (PDF, CSV, XLSX) | 7 years |
audit-intel-archive | Locked / archived audit files | 7 years |
- Object naming: every object is prefixed with
/{firmId}/{engagementId}/.
The R2 bindings + application middleware enforce that a request from firm A cannot read firm B's prefix.
- Encryption at rest: AES-256 managed by Cloudflare.
- Encryption in transit: TLS 1.3.
- Public access: disabled on all buckets.
3.3 Application compute — Cloudflare Workers
- Cloudflare Workers (Pages Functions) execute at the POP closest to the
requester. For Australian users this is Sydney (SYD), Melbourne (MEL), or Perth (PER). All three are in Australia.
- For overseas access (e.g. an Australian partner travelling), the
Worker may run on an overseas POP. Customer data is loaded into the Worker's memory for the duration of the request only, then discarded. Data at rest never leaves Australia.
- Hardening option: Cloudflare Data Localisation Suite (Enterprise
add-on) can pin Worker execution to a named jurisdiction. Enable if a customer's contract requires guaranteed AU-only compute. See §7.
3.4 Cache — Cloudflare KV
KV replicates writes globally for low-latency reads. The platform uses KV only for non-personal ephemeral data:
| Use case | Contains PII? |
|---|---|
| Rate-limit counters | No (keyed by hashed IP + route) |
| Feature flags | No |
| FSA mapping suggestion cache (content-hash → suggestion) | No (hash, not content) |
A code-level guard (lib/platform/cloudflare.ts) is the only writer to KV_CACHE. There is no path that stores tenant data in KV.
3.5 Queues + Durable Objects
- Cloudflare Queues are used as a producer-only binding from the web tier
for async jobs (AI summarisation, TB parse, email send).
- Queue messages are stored in Durable Objects, configured with
locationHint: 'oc' so the queue state lives at a SYD/MEL POP.
- The consumer Worker runs on Cloudflare's worldwide fleet but is
configured to dequeue only from the OC-hinted DO.
3.6 Authentication
- Sessions are HMAC-signed cookies (HS256 with a SYD-stored secret) — no
external identity provider in the data path.
- No third-party identity provider currently stores customer PII.
- Clerk (planned for v2) will be configured with its EU/APAC data region.
4. Data flows that leave Australia
There are two named outbound flows. Both are disclosed in the privacy policy and bound by Data Processing Addenda. Customers may disable Flow 1 via the STRICT_AU_AI=1 deployment flag.
Flow 1: AI inference (default: US, optional: AU-only)
| Feature | Default model | Default endpoint |
|---|---|---|
| FSA mapping suggestion | Gemini 2.5 Flash | Google (US) |
| Field autofill | Gemini 2.5 Flash | Google (US) |
| Materiality benchmark | Gemini 2.5 Flash | Google (US) |
| MUS random start | Gemini 2.5 Flash | Google (US) |
| Entity profile search | Gemini 2.5 Flash | Google (US) |
| Risk statement draft | GPT-4o-mini | OpenAI (US) |
| IRL generation | GPT-4o-mini | OpenAI (US) |
| Procedure suggestion | GPT-4o-mini | OpenAI (US) |
| AuditBot chatbot | GPT-4o-mini | OpenAI (US) |
| Document summarisation | Claude Sonnet 4.5 | Anthropic (US) ¹ |
| Journal fraud analytics | Claude Sonnet 4.5 | Anthropic (US) ¹ |
| Final checklist validation | Claude Sonnet 4.5 | Anthropic (US) ¹ |
| WP narrative autofill | Claude Sonnet 4.5 | Anthropic (US) ¹ |
| Journal rationale | Claude Sonnet 4.5 | Anthropic (US) ¹ |
| Pre-lock checklist | Claude Sonnet 4.5 | Anthropic (US) ¹ |
¹ When STRICT_AU_AI=1 is set, these six features route through AWS Bedrock in `ap-southeast-2` (Sydney) instead. Anthropic Claude Sonnet 4.5 is available on Bedrock Sydney; inference happens on AWS Sydney soil. See lib/ai/router.ts → STRICT_AU_FEATURES.
Controls:
- TLS 1.3 to every endpoint.
- Every AI call is logged to
ai_interactions— model, region, prompt hash,
output hash, latency, tokens. Customers can request a per-engagement export.
- Every AI suggestion requires explicit auditor sign-off before being
committed to the audit file. No autonomous AI actions.
- Vendor DPAs in place: OpenAI, Anthropic, Google.
- The platform never sends raw client PII fields (TFN, ABN, etc.) as part
of an AI prompt unless they are inherent to the working paper content (e.g. the directors' interests register). Prompts are content-scoped.
Flow 2: Outbound email (Resend, US)
| Use case | Recipient | Contents |
|---|---|---|
| Magic-link portal invitation | Client contact | Engagement name, signed link |
| Review note assignment | Team member | Note subject, link |
| Independence questionnaire dispatch | Team member | Engagement name, link |
| Partner sign-off required | Partner | WP code, engagement, link |
- Email body never contains audit findings, journal entries, evidence, or
trial-balance numbers. Body = notification + deep-link only.
- Customers can deploy with
RESEND_API_KEYblank to disable outbound
email; the platform falls back to in-app notifications only.
- Roadmap: swap to an Australian-hosted SMTP relay for firms requiring
strict AU-only email transit.
5. Sub-processors
See docs/SUBPROCESSORS.md for the maintained list with DPA references. At time of writing:
| Vendor | Service | Region | Data category |
|---|---|---|---|
| Cloudflare | Workers, R2, KV, Queues, Pages | APAC (storage); global compute | All application data |
| Neon | Postgres | ap-southeast-2 (Sydney) | Structured audit data |
| OpenAI | LLM inference | US | AI feature inputs (see §4) |
| Anthropic | LLM inference | US (or AWS Bedrock ap-southeast-2 if STRICT_AU_AI=1) | AI feature inputs (see §4) |
| Google AI Studio | LLM inference | US | AI feature inputs (see §4) |
| Resend | Email delivery | US | Notification email metadata + body |
| AWS (via Neon and optionally Bedrock) | Underlying compute/storage | ap-southeast-2 (Sydney) | Same as Neon / Bedrock above |
6. Architectural compliance enforcement
| Principle | How it's enforced |
|---|---|
| Region pinning | Neon project region is immutable at creation. R2 buckets are created with --location apac; verified via wrangler r2 bucket info. KV writers are restricted to non-PII data by code path (lib/platform/cloudflare.ts). |
| Multi-tenancy isolation | Schema-per-firm in Postgres. The tRPC authedProcedure middleware sets search_path from the session-bound firm ID. Cross-firm queries cannot be expressed in the DSL. |
| Audit trail immutability | audit_events rows are insert-only. No UPDATE or DELETE permission granted to the application role on this table. Every state transition writes an event with before/after JSON. |
| AI human-in-the-loop | ai_interactions records every call; accepted_by_user_id + accepted_at are required before an AI output is committed to a working paper. Type-checked at the tRPC layer. |
| Retention | engagements.fileLockedAt + INTERVAL '7 years' is the deletion eligibility marker. A scheduled task moves objects to cold storage after 2 years and deletes after 7. |
| RBAC | 7 roles enforced at the tRPC procedure level via requireRole(...). Independence sign-off is a hard gate enforced in middleware before any engagement file is accessible. |
7. Hardening options for higher-assurance customers
If a customer's diligence requires guarantees beyond the defaults:
7.1 AU-only AI inference
Set STRICT_AU_AI=1 and provide AWS Bedrock credentials. Sensitive features (document summarisation, journal fraud analytics, pre-lock checklist, WP narrative autofill, journal rationale, final checklist) route through AWS Bedrock in ap-southeast-2. Other features (FSA mapping, IRL, risk-statement drafts) continue using the default vendors — those features operate on lower-sensitivity data.
7.2 AU-pinned compute (Data Localisation Suite)
Enrol the Cloudflare account in the Data Localisation Suite (Enterprise add-on). Configure Regional Services to pin Worker execution to the APAC jurisdiction. Cost: contact Cloudflare. Recommended for firms with PIE clients or government work.
7.3 AWS migration (Stage 2)
Stage 2 of the platform roadmap migrates structured data + compute to AWS in ap-southeast-2:
- RDS Aurora Postgres (Sydney)
- S3 (Sydney) with bucket policies denying non-Sydney requests
- ECS Fargate (Sydney)
- ElastiCache (Sydney)
- SQS (Sydney)
- KMS customer-managed keys (Sydney)
- Service Control Policy at the AWS Organisation level denying all writes
outside ap-southeast-2 for the entire account
A draft SCP, bucket policies, and infrastructure-as-code plan are in docs/AWS_MIGRATION.md.
7.4 Customer-managed encryption keys (CMEK)
Not currently offered — Cloudflare/Neon manage keys. Available in Stage 2 under AWS KMS. Contact us if required for due diligence.
7.5 SOC 2 / ISAE 3402
Type I readiness work begins after the first commercial cohort. Type II report achievable 12 months after Stage 2 launch. Available on request once issued.
8. Incident response
- Detection: Sentry (frontend + Workers) + Cloudflare Logpush to a
SYD-resident logs bucket (created with --location apac).
- On-call: Eden Pearson, primary. Escalation tree documented in
docs/INCIDENT_RESPONSE.md (lives outside this repo for security).
- Assessment window: 30 days maximum per NDB scheme.
- Notification: OAIC within 72 hours of assessment as an eligible data
breach. Affected individuals + customer firm CISO/MLRO notified in parallel.
- Customer communication: templated; customer firm IT/security lead
receives notification within 4 hours of incident classification, even before formal NDB assessment is complete.
9. Data portability + deletion
Every firm can, at any time, request:
- Full data export: structured data (
pg_dump --schema=firm_xxx) +
all R2 prefixes (zip archive). Delivered via signed time-limited URL. SLA: 5 business days.
- Full deletion (subject to ASIC + APES 320 retention obligations):
- Schema dropped, R2 prefix deleted. - 30-day soft-delete window before physical deletion (allows recovery from accidental cancellation). - Retention overrides: if regulatory retention (7 years) has not elapsed, data is moved to a sealed archive bucket with no application access path. Physical deletion at end of retention. - Certificate of deletion provided.
10. Open commitments
| Item | Owner | Target |
|---|---|---|
| Privacy Impact Assessment (PIA) sign-off | Eden + DPO | Before first commercial customer |
| SOC 2 Type I readiness | EDENIC | Q3 2026 |
| Stage 2 AWS migration | EDENIC | Q4 2026 |
INCIDENT_RESPONSE.md published to customer portal | EDENIC | Before first commercial customer |
| Customer-managed encryption keys | EDENIC | Stage 2 |
| Cloudflare Data Localisation Suite enrolled | EDENIC | First customer requiring it |
Appendix A — Verifying residency yourself
A customer's IT / security reviewer can independently verify the residency posture as follows:
# 1. Confirm Neon project region (requires Neon API key or dashboard)
curl -H "Authorization: Bearer $NEON_API_KEY" \
https://console.neon.tech/api/v2/projects/{project_id} \
| jq '.project.region_id'
# expected: "aws-ap-southeast-2"
# 2. Confirm R2 bucket regions
wrangler r2 bucket info audit-intel-evidence
wrangler r2 bucket info audit-intel-tb-imports
wrangler r2 bucket info audit-intel-archive
# expected for each: location: APAC
# 3. Confirm wrangler config DATA_RESIDENCY_REGION
grep DATA_RESIDENCY_REGION wrangler.toml
# expected: DATA_RESIDENCY_REGION = "ap-southeast-2"
# 4. Confirm AI strict-AU flag (per customer)
grep STRICT_AU_AI wrangler.toml
# customer-configurable: "0" (default) or "1" (sensitive features through Bedrock Sydney)Customers can also request a live screen-share where Eden demonstrates each of the above against the production environment.
This document is reviewed at minimum every 12 months and on any material change to data flows. Reviewers add an entry to `docs/CHANGELOG.md`.