Atrium counts the days a person spends in each country from the trips and documents they record. It does not decide anyone's tax residence. The records it holds are sensitive, so this page says plainly what protects them and where the protection stops. Items marked Live are in the current release; Partial means some of it is live; Planned means it is not in the product yet.
1. What Atrium stores and why
Only what is needed to count days and show the evidence behind them:
- Trips: dates and times, countries, airports or stations, flight or train numbers, transit flag, who added the trip and how it was verified.
- Documents you attach (boarding passes, tickets, stamps) as the image or PDF you uploaded, plus a record linking each file to a trip.
- Profile facts and settings that change a country's day limit.
- Location fixes, only if you turn on border-crossing detection: the fix before and after a crossing, and at most one check-in every eight hours. Never a movement track.
- Account data: email address, display name, and who you have given access to.
A passenger name read from a boarding pass is shown during capture but is not saved as a trip field; the image itself, which carries the name, is kept as evidence.
2. Architecture and regions
Atrium is a Flutter app for iPhone, Android and the browser, backed by Google Firebase: Authentication, Firestore (database), Cloud Storage (files) and Cloud Functions (server code). The database is in asia-east2 (Hong Kong). Functions run there too, except the document-reading function, which runs in europe-west1 (Belgium) because the OCR provider does not accept traffic from Hong Kong. Files are kept in the project's default bucket, which Firebase creates in the project's default location, also Hong Kong.
The web app is served by Firebase Hosting at daytrack.atrium.tax; this website is on Vercel. Atrium is made and operated by Wan Family Office Limited, Hong Kong.
3. Encryption
In transit. Live Every connection between app, servers and providers uses HTTPS or TLS. Both hosts send HSTS, allow framing only by themselves, refuse content-type sniffing and limit referrers and browser permissions. This website enforces a content-security policy that allows only its own scripts, and styles from itself and Google Fonts. The app host enforces the frame, plugin and base-URL parts of its policy and runs the full policy in report-only mode while we test sign-in, uploads and exports against it; then it is enforced. The app's own pages contain no inline scripts.
Records. Live Trip, document and profile contents are encrypted on your device before they reach the database: AES-256-GCM, a fresh random nonce per record, and an authentication tag bound to your account. The database holds the ciphertext plus the few plaintext fields needed to find a record: owner, timestamps, document kind and linked trip.
Keys. Live Each account has its own 256-bit data key, created on our server and stored only in wrapped form; the wrapping key lives in Google Secret Manager and is never in the database or the source code. The app fetches the data key over an authenticated call, available to the owner and to anyone the owner has granted access. On iPhone it is kept in the Keychain (this device only, excluded from iCloud and backups); on Android in Keystore-backed encrypted storage, with system backups of app data switched off; in the browser in memory only. Keys for other people's workspaces are never stored on a device. Signing out removes the key.
Plainly: this is not end-to-end encryption. An Atrium operator with access to Secret Manager and the database can unwrap any account's data key and read its records. The design protects against a leaked database export, a lost laptop or a hijacked browser session; it does not protect against Atrium itself. A key you hold yourself, which Atrium cannot unwrap, is on the roadmap.
Files. Live Uploaded documents are stored as uploaded, protected by Google's encryption at rest and by the access rules in section 4. Atrium adds no encryption of its own to file bytes. Uploads are limited at the storage layer to images and PDFs of at most 20 MB (avatars: images of at most 5 MB); HTML, scripts or anything else a browser would run are refused.
Earlier records. Before September 2026 records used a weaker key derived from the account id. A one-time migration re-encrypts them; the old format stays readable until every account has migrated.
4. Who can see what
Nothing is readable or writable without a signed-in account with a verified email address. Three roles:
- Owner: full access to their own records; the only role that can delete trips, documents or the account, invite people, or choose which phone detects crossings.
- Assistant: for assigned people, may read, add and edit trips, add documents and confirm detections. Cannot delete.
- Tax adviser: for assigned people, may read trips, documents and settings; may write only tax-profile and tax-settings records, encrypted; may issue sealed reports. Cannot upload or delete.
Roles are scoped per owner, so an adviser in one family's workspace has no rights in another's, and per person, so a delegate granted one family member cannot read a sibling's records. The rules are enforced by Firebase security rules on the database and file store, re-implemented identically in the one server function that reads files on a user's behalf, and covered by 35 automated rules tests that run against the Firebase emulator.
Invitations are one-time links: a 32-byte random token, of which only the SHA-256 hash is stored, expiring after 14 days. Accepting requires signing in with the invited, verified email address. Owners can revoke access or reissue a link at any time; reissuing invalidates the old one.
Planned One limit: a delegate holding the owner's data key keeps it until they sign out, and revoking access does not change the owner's key. Key rotation on revocation is planned.
5. Verifiable reports
Live Every Journey Report is sealed when it is made. The app computes a SHA-256 digest of the report's figures in a fixed order (country, tax year, period, each stay's dates and counted days, the total). Our server signs report id | digest | time issued with an Ed25519 key held in Secret Manager and keeps a record of the digest and a numeric summary; it never receives names or document images for this. The report carries a QR code and a link to atrium.tax/verify, where anyone can confirm that Atrium issued a record with that id, see the figures as issued, and compare them with the document in hand. If the PDF was saved from the app, its file fingerprint is recorded too, so a modified file can be told from the original.
The check proves that the figures are the ones Atrium issued at that time. It does not prove that the trips behind them are true, and it does not say anything about residence. Only the owner or a tax adviser can issue a seal; assistants cannot. When an account is deleted, the figures are deleted and only the id remains, so the verify page can say "withdrawn" rather than "never existed". The public key is published at /.well-known/atrium-report-key.txt for offline verification.
6. Providers and what each receives
- Google Firebase / Cloud: hosting, database, files, functions, Secret Manager, in the regions above.
- Anthropic (boarding-pass reading): a compressed copy of the image (under 1 MB) and a fixed instruction, sent from our Belgian function; the reply is a short JSON of the printed fields. Atrium does not keep the copy sent. The app never contacts Anthropic directly. Anthropic's handling of API inputs follows its commercial terms, linked from our privacy policy.
- Flightradar24 (flight verification): flight number or registration, airport codes, and a time window around departure, sent from our server.
- Realtime Trains (Eurostar verification): station codes and service date, sent from our server.
- Google Places (address suggestions, browser only): the address text you type, a session token and a country code, sent through our server. The app sends it only when an owner types in their own workspace; never for assistants or advisers.
- OpenStreetMap: on a manual location check-in your phone sends that one latitude and longitude to Nominatim to get a city and country name, and the map preview on a trip loads tiles for the area shown.
- airplanes.live: when you refresh a scanned boarding pass, your phone looks up the flight identifier against live aircraft positions.
- Resend: your email address and the content of verification, reset, password-changed, welcome and invitation emails.
- Apple and Google: sign-in; App Attest, Play Integrity and reCAPTCHA for app verification.
- Vercel hosts this website, which loads the Inter typeface from Google Fonts. No cookies, no analytics.
No provider receives your trip history; lookups send one flight or train at a time.
7. Location
Live Border-crossing detection is off until you turn it on. Your phone decides "crossing or not" on the device, against a bundled map of country boundaries; no coordinates are sent to make that decision. On iPhone it listens for significant location changes and visits at roughly 100-metre accuracy; on Android it asks the fused location service for balanced-power fixes about every fifteen minutes or kilometre. Either way a country counts as entered only when the fix lies wholly inside it or a second fix confirms it. At most one presence check-in is kept every eight hours.
What is uploaded, as encrypted evidence: the fix before and after a crossing, on a pending trip, and the presence check-ins; each carries its accuracy, the phone's install id and time-zone name. Pending trips are not counted until you or an assistant confirm them. One phone per account detects; any other phone stops when it sees it is not designated. Turning detection off stops monitoring and deletes anything queued but not yet uploaded. Crossing notifications are generated on the phone; Atrium uses no push service.
Partial Each detection is also written to an encrypted log on the account, with what became of it (confirmed, changed, merged, not a crossing) and whether a trip recorded by hand had no detection, so the app can show "Accuracy on this account" and we can publish measured figures on the detection accuracy page. Counts only leave the account, and only when the owner copies them.
8. Retention and deletion
Live Deleting a trip or document removes it immediately. Deleting your account, from Profile, requires signing in again within five minutes and then removes, in order: invitations sent and received, your access from every delegate's account, the figures behind any sealed reports, your files and the encrypted snapshot made during the September 2026 key migration, your whole database tree, your data key, server-side counters, and the sign-in itself. With Apple sign-in, Atrium's Apple authorisation is revoked. Access you held to others' workspaces ends; their data is unaffected.
The database is backed up once a day and each backup is kept for seven days (Firestore scheduled backups, in the same region; point-in-time recovery is off). A deleted account therefore leaves our live systems at once and our backups within seven days; the one-time snapshot from the key migration is deleted with the account. What else remains after deletion: ordinary server logs, which expire under Google Cloud Logging's default 30-day retention; abuse counters keyed by network address, which hold no account data; and the id-only record that a report was issued and withdrawn.
9. Operations
- Abuse controls. Live Per verified account: document reading 3 per minute and 20 per day (1,000 per day for all users); address suggestions 60 per minute and 300 per day (5,000 for all users); flight lookups 8 per minute and 80 per day (2,000 for all users); train lookups 20 per minute and 100 per day (2,000 for all users); invitations 10 per hour; verification emails 10 per day; password resets 3 per hour per address and 20 per hour per network address. Report verification: 30 per minute per network address, 2,000 per hour in total.
- App verification. Partial Firebase App Check is active in the browser (reCAPTCHA Enterprise) and, from this release, on iPhone (App Attest) and Android (Play Integrity). The server runs it in monitor mode: requests without a valid token are logged, not refused. Enforcement follows once the phone builds have been live long enough to show near-zero unverified requests.
- Secrets. Live Provider keys, the key-wrapping key and the report-signing key live in Secret Manager and are injected at runtime; none is in source code or the app bundle.
- Logging. Live Server logs hold no tokens, keys, document contents or email bodies. Flight and train lookups log number, route and date without the account id. The app writes diagnostic lines to the device's own log; they are not sent anywhere.
- Releases. Live iPhone builds are signed with an Apple Distribution certificate kept outside the repository and uploaded through App Store Connect; Android release builds use an upload key kept outside the repository.
- Testing. Live 35 security-rules tests, 132 server tests and 235 app and package test files run before release. Automated dependency scanning is planned.
What we do not do
- No advertising, analytics or crash-reporting SDK in the app; no third-party script on the website.
- We do not sell or share your data for anyone else's purposes.
- We do not read your documents in the normal course of operating Atrium; reading is done by software you invoke, one document at a time.
- We do not conclude that you are, or are not, tax resident anywhere. Atrium shows counts and numeric conditions; residence questions belong with your adviser.
10. Reporting a security problem
Write to security@atrium.tax. We aim to acknowledge within three business days, give an initial assessment within ten, and fix issues that expose user data within thirty days of confirmation, telling you when we have. We will not pursue good-faith research that does not access, change or delete other users' data, does not disrupt the service, and gives us reasonable time to fix before publishing.
11. Status and roadmap
Atrium holds no SOC 2, ISO 27001 or Cyber Essentials certification; Google Cloud holds its own. No independent penetration test has been performed; one is planned before general availability.
| Item | Status |
|---|---|
| Per-account encryption of records; keys in Secret Manager | Live |
| Role-scoped access rules with emulator tests | Live |
| Sealed, verifiable Journey Reports with public verification | Live |
| In-app account deletion, including migration snapshots and report figures | Live |
| Upload size and type limits | Live |
| Daily caps on lookup services | Live |
| Browser security headers; content-security policy on the website | Live |
| Content-security policy enforced on the app host | Partial report-only, then enforced |
| App Check on all platforms, then enforced | Partial monitor mode |
| Published detection accuracy, measured on real devices | Partial measuring since this release; figures after 4 weeks or 20 crossings |
| Key rotation when a delegate is removed | Planned |
| Customer-held key option | Planned |
| Independent penetration test; automated dependency scanning | Planned |
This page is updated, with the date, as each item ships.