Privacy Policy
1. Who we are
Controller: CrewMark, operated by a sole proprietor based in Belgium.
Contact: privacy@crewmark.tech
Service domain: crewmark.tech
Full controller identity and registered address are available to data subjects on written request to the contact above.
CrewMark is in beta. The legal entity will transition to an EU corporate vehicle (e.g. Belgian SRL or Estonian OÜ) before public launch — this policy will be updated when that happens.
2. Personal data we process
| Category | Examples | Where stored | Legal basis |
|---|---|---|---|
| Account identity | Personal email, first/last name, display name | PostgreSQL on our EU server | Art 6(1)(b) — performance of contract |
| Work identity | Work email, crew ID, airline, home base, rank | Same | Art 6(1)(b) |
| Career history | Past airlines, qualifications, contractual bases with dates | Same | Art 6(1)(b) + 6(1)(f) legitimate interest |
| Authentication artifacts | Magic-link tokens (hashed), JWT sessions, login IP + user-agent | Same — tokens stored as SHA-256 hash, never plaintext | Art 6(1)(b) + 6(1)(f) security |
| Roster contents (snapshots) | Duty codes, flight legs, check-in/out times, hotel layovers, crew lineup. Stored as encrypted JSON since v1.1. | PostgreSQL on our EU server, encrypted at rest with a per-user key derived from a server master secret + your account ID. Even our own database administrator cannot read your roster without the live application's decryption keys. | Art 6(1)(b) — performance of contract (FTL audit, change detection, career archive) |
| Roster bytes (transient) | Your uploaded PDF file | In-memory only. Parsed and dropped immediately after extraction; never written to disk. | Art 6(1)(b) |
| Other crew members' names (in your snapshots) | The crew lineup printed on your roster — captains, first officers, pursers, cabin crew on each leg | Pseudonymized at write time (HMAC-SHA256 with your account-specific salt) + encrypted (Fernet, per-account key). Plain names never reach our database. Only you can decrypt them via your browser. | Art 6(1)(f) — legitimate interest (balancing test passed: pseudonymization + encryption + opt-out form + professional-context data). See § 13. |
| Employment timeline | Past and current airlines + crew IDs + dates, optionally added by you or auto-detected from roster metadata | PostgreSQL on our EU server (plain — it's your own data) | Art 6(1)(b) — required for career archive + certificate |
| Cross-user identity links | Records of "this CrewMark user is the same person as the pseudonym X in user Y's archive" — created only after BOTH parties consent | PostgreSQL on our EU server | Art 6(1)(a) — explicit consent from both data subjects. Default is OFF for every account. |
| Free-text duty notes | Your private notes per duty day | PostgreSQL on our EU server | Art 6(1)(b) |
| Swap-market listings | A duty you offer, your roster context window visible to peers | In-memory only. Wiped on server restart. | Art 6(1)(a) consent — you actively post |
| Local browser storage | Last parsed roster, user preferences, auth token | Your browser only (localStorage) — never sent to us except the auth token on each request | Strictly necessary — service can't function without it |
2.1 What we do NOT collect
- No PDF bytes stored on our server — in-memory parse only
- No passwords (passwordless magic-link login only)
- No analytics SDKs (no Google Analytics, no Mixpanel, no Segment, no Hotjar)
- No tracking pixels, no third-party cookies
- No marketing / advertising data
- No biometric, health, genetic, political, religious, or trade-union data
3. Why we process this data
- Account creation and login — so you can authenticate
- Roster parsing — the core service you signed up for
- FTL compliance check + salary estimate — runs in your browser; no data sent to us beyond what's needed to parse your PDF
- Career history tracking — to give you a lifetime "Crew Passport"
- Swap marketplace — to connect you with other crew on the platform
- Admin spam vetting — your registration "why I want access" note is read by the CrewMark admin team to approve genuine crew accounts
- Transactional email — magic-link emails and approval notifications, sent via Google Workspace (EU tenant)
4. Where your data lives — sub-processors
| Provider | Role | Location | Safeguards |
|---|---|---|---|
| Hostinger International Ltd | VPS hosting (database + application) | Frankfurt, Germany 🇩🇪 | EU controller, GDPR DPA, ISO/IEC 27001 |
| Google Workspace (Gmail SMTP) | Transactional email delivery | EU Workspace tenant | EU-US Data Privacy Framework, standard contractual clauses |
| Let's Encrypt / ISRG | TLS certificate issuance | Global | No personal data — domain name only |
All personal data is processed inside the European Economic Area. We do not intentionally transfer personal data to a third country.
5. Your rights under the GDPR
| Right | How to exercise it |
|---|---|
| Access (Art 15) | Settings → "Download my data". Returns a ZIP of all your account data as JSON. |
| Rectification (Art 16) | Edit your profile in Settings. Some fields (airline, home base, rank) require admin approval to prevent identity churn. |
| Erasure (Art 17) | Settings → "Delete my account". This permanently deletes your account, magic links, career history, and duty notes. Cannot be undone. |
| Restriction (Art 18) | Email us at privacy@crewmark.tech. We can suspend your account without deleting it. |
| Portability (Art 20) | Same as Access — the export is machine-readable JSON. |
| Object (Art 21) | We do not process for marketing or profiling, so there is nothing to object to. If you disagree with any processing, email us. |
| Complaint | You can lodge a complaint with the Belgian Data Protection Authority — www.dataprotectionauthority.be |
6. Retention
- Roster snapshots (since v1.1) — kept for the lifetime of your account. This is intentional: snapshots ARE your career archive. You can delete any individual snapshot at any time (Settings → Roster history → 🗑), or wipe all roster history at once (Settings → Roster history → Delete all). Account deletion wipes them within 30 days. Older versions of the same period stay in the archive (the latest is marked "current"); we never delete on your behalf without your action.
- Inactive accounts (safety net) — if you don't log in for 5 years, we email you to confirm you still want your roster archive kept. If we get no response after 30 days, we soft-delete the snapshots (your account stays — you can still log back in to re-upload).
- Active account data — kept while your account exists. Deleted within 30 days of you using "Delete my account", purged from backups in the next backup cycle.
- Employment timeline — kept for the lifetime of your account; you can edit or remove individual employments.
- Magic-link tokens — expire 15 minutes after issue; rows kept 90 days for audit, then purged.
- Roster PDF bytes (the file itself) — zero retention. Dropped from memory immediately after parse.
- Swap-market listings — max 30 days or until the next server restart, whichever comes first.
- Backups — 30-day rolling, then permanent purge. Encrypted columns stay encrypted in backups.
6a. Why we keep roster snapshots for the lifetime of your account
Three reasons:
- Change detection. When your airline pushes an updated roster mid-month, we compare it against your last upload and show you exactly what changed (added duties, removed duties, FDP extensions, aircraft swaps). Without prior history this feature is impossible.
- Long-window FTL legality. EASA's rolling 28-day duty cap (190h) and 12-month flight time cap (900h) require months — sometimes years — of historical duty data. Storing snapshots lets us compute them accurately, not just approximate from the current period.
- Portable career archive + certificate. Crew change airlines 2-4 times in a career. No employer's logbook survives that. CrewMark snapshots ARE your portable lifetime record — usable when you change employers, apply for promotion, renew licenses, or need proof-of-profession for immigration / mortgage / insurance.
Because this purpose requires long retention to deliver value, GDPR's storage-limitation principle (Art 5(1)(e)) is satisfied: retention duration matches purpose. You always retain control — delete anything at any time, no questions asked.
7. Security
We follow industry-standard controls aligned with GDPR Article 32 and ISO/IEC 27001 Annex A. Notably:
- TLS 1.2+ everywhere via auto-renewed Let's Encrypt certificates
- Passwordless authentication — no passwords to leak
- Magic-link tokens stored as SHA-256 hashes (never plaintext)
- Database not accessible from the public internet
- Container isolation for application services
- SSH access by key only (no passwords)
- Automatic OS security updates
- Admin accounts use multi-factor authentication
If a breach occurs, we will notify the Belgian Data Protection Authority within 72 hours per Article 33, and we will notify affected users without undue delay per Article 34.
8. Cookies and local storage
We use no third-party cookies, no analytics cookies, and no advertising cookies. The only client-side storage we use is your browser's localStorage, holding:
- Your authentication token (so you stay logged in)
- Your last parsed roster (so the app works offline)
- Your UI preferences
This is strictly necessary for the service to function and does not require consent under the ePrivacy Directive. You can clear it any time via your browser settings.
9. International users
CrewMark is designed for EU/EEA-based crew. If you access it from outside the EEA, your data is still processed exclusively on EU servers — no extra-EEA transfer takes place.
10. Children
CrewMark is a B2C tool for working airline crew. We do not knowingly collect data from anyone under 18. If you believe a minor has registered, email us and we will delete the account.
11. Changes to this policy
We will post any material changes here at least 30 days before they take effect, and notify registered users by email. Prior versions are archived in our Git repository.
12. Contact
Questions, requests, or complaints:
CrewMark — Controller
privacy@crewmark.tech
Belgium
We respond within 30 days as required by Article 12(3).
13. How we handle other crew members' names
Your roster's crew_information section lists the captains, first officers, pursers and cabin crew you operated with on each leg. We store those names so you get features like "I've flown with this person 14 times" and so your roster snapshots are faithful copies of what your airline published. But other crew members are data subjects too — they never signed up for CrewMark. We protect them as follows:
- Pseudonymization at write time. Before any other crew member's name reaches our database, it's converted to a 12-character HMAC-SHA256 hash using a 32-byte salt unique to your account. The plain name does not exist in our database.
- Encrypted name copy. Alongside the pseudonym, we store a Fernet-encrypted ciphertext of the plain name, encrypted with a key derived from your account ID + a server master secret. Only you, signed in, can decrypt it. Other CrewMark users — and our own DBA — cannot.
- Per-account isolation. Captain Smith shows as a different hash in your archive vs. another crew member's archive. There is no way to cross-reference identities across users.
- Operational right to erasure (Art. 17 for non-users). Any crew member who is mentioned in a CrewMark archive — whether they have a CrewMark account or not — can request to be erased via our public form at crewmark.tech/scrub-me. We verify the request by emailing a confirmation link to their work or personal address, then run a scrub job that removes their pseudonym + encrypted name from every affected snapshot within 30 days.
- No third-party sharing. Crew names — pseudonymized or not — are never sold, never shared with advertisers, never used for marketing or profiling.
Lawful basis: GDPR Art. 6(1)(f) legitimate interest. The balancing test (necessity vs. data subject's interests) passes because: data is professional not intimate; rosters already circulate within the airline; pseudonymization + encryption are state-of-the-art safeguards; /scrub-me provides an operational opt-out; no profiling or marketing happens. We document this assessment in an internal Data Protection Impact Assessment available to data subjects on written request.
14. Cross-user identity linking (opt-in only)
If you and another CrewMark user have flown together, our system can recognize that you're the same person they have in their archive — but only after both parties explicitly opt in. Without your consent (set in Settings → "Let CrewMark members find me?"), your CrewMark account is never linked to any pseudonym in any other user's archive. Default for every new account is hidden.
You can change visibility at three levels:
- Hidden (default) — never linked, never shown
- Badge only — other CrewMark members see a "★ CrewMark member · N flights together" pill, but not your name
- Badge + name — full name visible to confirmed peers + badge
Linking happens only after a confirmation flow: when you register, we show you the matches your account might have in other users' archives (high-confidence matches based on crew_id + airline; medium / low based on name fallbacks). You explicitly tick which ones are actually you. Nothing is auto-linked.
Revoke at any time from Settings — revoking deletes the relevant rows from our crew_identity_links table within 24 hours.
15. Encryption details (technical)
For users who want to verify the cryptographic posture:
- Master key. A 32-byte random secret (
ROSTER_MASTER_KEY) lives in our application server's environment, never in the database, never in source control, never logged. Rotation requires a one-off re-encryption job. - Per-user key derivation. Each user's encryption key is derived via HKDF-SHA256 with
info=b"roster-key-v1", salt=user UUID bytes, output 32 bytes. Deterministic but unique per account. If a database snapshot leaks without the master key, individual snapshots remain unreadable. - Symmetric encryption. Fernet (AES-128-CBC + HMAC-SHA256, 128-bit random IV per encryption). Built-in tamper detection.
- Pseudonymization. HMAC-SHA256 with a 32-byte per-user salt stored in our database. Same crew member → same hash for the same viewer. Different viewers → different hashes for the same person.
- Key separation. The pseudonym salt and the encryption key are derived from independent HKDF info parameters — leaking one doesn't compromise the other.
Source code for the encryption helpers lives in our parser repository — parser/auth/crypto.py — and is open for inspection by anyone with code review credentials.