Privacy Policy (GDPR Art 13 + ePrivacy)
Status: self-authored draft (AI-assisted), appropriate for the current closed-beta scale, revised against an external legal research memo dated 7 August 2026 and then reconciled, the same day, against a line-by-line audit of the shipped source code. Where the two disagreed, the code won: several passages that described an intended design now say plainly what the app does today, and are marked [planned] where the design is still being built. This notice is drafted to satisfy the information obligations of GDPR Article 13 (information to be provided where personal data are collected from the data subject) and the device-access consent rule of Article 5(3) of the ePrivacy Directive 2002/58/EC (as amended by 2009/136/EC), transposed in Denmark as cookiebekendtgørelsen, BEK nr 1148 of 9 December 2011, § 3. It also reflects Apple App Store Guideline 5.1.1(i) and Google Play's User Data / Data safety requirements. These documents are not legal advice and are not a substitute for a professional review — a lawyer review is recommended as the user base and data processing grow, and is advisable before enabling ID/biometric verification.
Last updated: 7 August 2026 — second revision the same day, reconciling this notice against a source-code audit of the shipped build Applies to: the Flybi mobile application ("Flybi", "the app", "we", "us")
1. Who we are (the controller) — GDPR Art 13(1)(a)
Flybi is operated by:
- Controller: Nicholas Gerster Toft Simonsen, operating Flybi as a registered Danish enkeltmandsvirksomhed (sole proprietorship), based in Aarhus, Denmark. As a sole proprietorship, the named individual remains personally the controller.
- CVR number / registered entity: CVR 46574184 — a registered Danish enkeltmandsvirksomhed (sole proprietorship); VAT-registered (MOMS, quarterly returns) since 19 June 2026.
-
Postal address: none is published here. GDPR Art 13(1)(a) requires the identity and the contact details of the controller, not a postal address — the name, CVR number and e-mail address above and below satisfy it, and DSA Arts 11 and 12 likewise require a contact point rather than an address. Write to us by e-mail.
-
Contact e-mail:
ngts91@gmail.com(this will move to a company/branded address as the project grows). This is the contact for support and for privacy/data-protection matters. - Privacy policy URL: https://flybi.app/privacy (the canonical URL referenced as
LegalLinks.privacyPolicyUrl; live and published — #646).
EU representative (GDPR Art 27): Not applicable — the controller is established in the EU (Denmark). Art 27 applies only to controllers not established in the Union (Art 3(2)). The Danish establishment is itself the contact point for the supervisory authority and for data subjects.
Data Protection Officer — GDPR Art 13(1)(b)
No Data Protection Officer is appointed; one is not legally required at the
current scale. The controller (Nicholas Gerster Toft Simonsen,
ngts91@gmail.com) is the contact for privacy matters. This position is
re-assessed if scale grows or biometric/ID verification is enabled. We do not
consider a DPO mandatory under GDPR Art 37(1): we are not a public authority,
and our core activity is operating a single consumer app rather than large-scale
monitoring or large-scale special-category processing as our core business in
the Art 37 sense. At the current closed-beta size the "large scale" thresholds in
Art 37(1)(b) and (c) are not met. That will change as we grow: a proximity
service doing background location and processing special-category data crosses
those thresholds well before it feels like a large company, and we re-run the
assessment at each order of magnitude of growth.
Note that a DPO is not required for a Data Protection Impact Assessment to be required — see Section 12.
2. Who Flybi is for — 18+ only (children) — GDPR Art 8
Flybi is an 18-and-over service. You must be at least 18 to create an account. We do not knowingly process the personal data of anyone under 18.
- At registration you must confirm acceptance of our Terms/EULA, and during
onboarding we collect a date of birth to operate an 18+ age gate
(stored as
dateOfBirthon your profile — see Section 3.8). - Under GDPR Art 8 the age at which a child may self-consent to information society services is 16, which Member States may lower to no less than 13. Denmark set this at 13 via the Danish Data Protection Act (Databeskyttelsesloven) § 6(2). Because Flybi is an adults-only (18+) service, that age-of-consent threshold does not in practice apply to our user base — our binding rule is our own 18+ minimum age.
- GDPR Art 6(1)(f) legitimate-interest balancing expressly weighs against processing "in particular where the data subject is a child." Our age gate exists precisely to keep minors off an adults' service.
If we learn that a user is under 18, we will close and erase the account.
3. The data we process, why, and our legal basis — GDPR Art 13(1)(c)–(d)
The table below lists each category of personal data, the purpose, and the
lawful basis under GDPR Art 6 (and, where relevant, the special-category
condition under Art 9(2)). The field names in brackets are the actual
Firestore fields (see lib/core/constants/firestore_fields.dart) and are given
for transparency.
3.1 Account & authentication
- Data: e-mail address; authentication identifiers from your chosen sign-in
provider (e-mail/password, Google, or Apple). (
email) - Purpose: to create and secure your account and let you sign in.
- Lawful basis: Art 6(1)(b) — performance of a contract (you cannot use the service without an account). Where you sign in with Apple, we honour Apple's private-relay e-mail.
- Provision: providing an e-mail/identifier is a contractual requirement (Art 13(2)(e)); without it the service cannot be provided.
3.2 Profile & personality
- Data: display name (
displayName); biography text (bio); profile and tag photos (photoUrl, stored in Firebase Storage); your personality / Big Five self-assessment and its chosen visibility (personality); displayed badges and member number (displayedBadges,signupOrdinal); locale (locale). - Purpose: to present you to other users — in Flybi "the people are the content" — so others can discover and connect with you.
- Lawful basis: Art 6(1)(b) contract for the core profile needed to deliver discovery; Art 6(1)(a) consent for genuinely optional enrichment fields you choose to add (e.g. an optional bio/photo or making your personality profile visible).
- Provision: a minimal profile is a contractual requirement; optional fields are voluntary and may be left blank.
3.3 Interests as "tags", including secret tags
- Data: the interest tags you add to your profile, each marked as an
identity or seeking intent, and optionally flagged secret
(
isSecret); secret tags are only revealed to another user through a mutual reveal handshake (reveal_requests). - Purpose: to find and surface the people who best fit you, and to power the shared-interest discovery experience.
- Lawful basis: Art 6(1)(b) contract (surfacing best-fit people is the core service).
- ⚠️ Special category — Art 9. Free-text tags and "seeking" preferences reveal special-category data under Art 9(1) — sexual orientation and sex life in particular, and potentially health, religious or philosophical beliefs. On a bi/queer-oriented service this is not a borderline case: data that indirectly discloses sexual orientation is special-category data (CJEU C-184/20 OT), and the disclosure does not have to be direct.
- The condition we rely on is Art 9(2)(a) explicit consent, in addition to the Art 6 basis above. We do not rely on Art 9(2)(e) "manifestly made public" for any of it. Publishing a tag on your own profile does not make your other data — your location, your secret tags, who you have connected with — public, and Art 9(2)(e) is read narrowly (CJEU C-446/21 Schrems v Meta). For anything you have flagged secret, Art 9(2)(e) is plainly unavailable: the flag is evidence that you did not make it public.
3.4 Location — proximity discovery, including in the background when the app is closed — see also Section 9 (ePrivacy)
Read this section carefully. It is the most intrusive processing Flybi does.
-
When we read your location. There are two cases. Today they are covered by a single choice: if you turn location on, both happen. We are separating them so you can accept the first and refuse the second, but that is not built yet, and until it is you should read the second case as part of what you are agreeing to. 1. Foreground — when you open a proximity feature (discovery, the optional soulmate scan), the app reads your device GPS at that moment. 2. Background — while the app is closed or otherwise not in use. If you have turned location on at all, Flybi continues to read and send your location when you are not using the app at all, including when it is fully closed. Three separate mechanisms do this: a 500 metre geo-fence around your last known position, which sends a new reading each time you leave it and then re-arms around wherever you now are; the operating system's own background location service (on iOS, Significant Location Change, which reports after roughly 500 metres of movement rather than on a clock; on Android, background location updates); and a refresh each time you bring the app back to the foreground. So readings follow your movement, not a timer. To avoid pointless writes we discard a new reading if you have not moved out of a roughly 5 km cell and your last stored point is under 20 minutes old.
-
What is transmitted, and what is stored. What leaves your device is a precise latitude/longitude fix. What we store on your profile is both (a) coarse-area geohash indexes —
geohash4(~39 km cell) andgeohash6(~1.2 km cell) — used to find people in your ring, and (b) the precise latitude/longitude point (location.latitude/location.longitude), used to post-filter candidates by exact distance. So: precise in transit, and precise at rest. We are telling you this plainly rather than describing the storage as "approximate". -
⚠️ Who can currently read that precise point — the position today. The precise point is stored twice: once on a private record only you can read, and once on your profile document, which every signed-in Flybi user can currently read — along with your e-mail address. That is not the design we want and it is not how we describe discovery elsewhere in this notice: the intention is that other users see only a coarse area and a distance. The work to remove the duplicate copies from the profile document has not shipped yet, so until it does, treat your last-known coordinates and your e-mail address as visible to any other signed-in user who queries for them. [planned] Once that lands we will update this bullet rather than quietly drop it.
-
Purpose: proximity discovery only — to show you people within your selected radius, to compute distances, and (where you have enabled it) to keep those distances fresh while you move. Not advertising. Not profiling for third parties. Your location is not sold and not shared with anyone except the processor that stores it for us (Google/Firebase — Section 6.2, EU storage region — Section 7). What other users are shown is a coarse area and a distance. What they can currently read, if they go looking, is more than that — see the bullet above, and the live Hot/Cold game in Section 3.5, which you opt into each time.
- ⚠️ Why this is special-category data, and our Art 9 condition. Flybi is a bi/queer-oriented service. Knowing that a particular person uses Flybi is itself information about their sexual orientation, and a location trail attached to that account is therefore data revealing sexual orientation — special-category data under Art 9(1). A pattern of locations over time can reveal more still (where you sleep, which venues and clinics you visit). We therefore process location on Art 9(2)(a) — your explicit consent, on top of Art 6(1)(a) consent and the separate ePrivacy device-access consent in Section 9. Contract necessity under Art 6(1)(b) and legitimate interests under Art 6(1)(f) are not available for this, and we do not claim them.
-
Background location is separately optional and separately withdrawable. Foreground and background location are two different permissions with two different consents. Declining background location, or turning it off later, leaves the whole of the rest of Flybi working — you keep your account, your chats, your connections and proximity discovery whenever you open the app. We will never require background location as a condition of using Flybi, and we will never re-ask after you have refused. Turning it off is one tap in Profile → Location, at the same depth as turning it on.
-
Retention — one point, no trail. We keep one location point for you: each new reading overwrites the previous one, so your profile holds your latest position and not a history. There is no location-history collection in our database. Your stored point is deleted immediately when you turn location off, when you use "Erase my stored location", and when you delete your account. A 30-day automatic expiry for points nobody has refreshed is [planned] and is not running yet — today, if you simply stop using the app without turning location off, your last point stays until you delete it or delete your account. We do not put your coordinates into analytics events, crash reports or server logs; a coarse ~39 km area cell can, however, still appear as a diagnostic key on a crash report, which we are removing.
-
Minimisation (Art 5(1)(c)). Storing a precise coordinate where a coarse cell would do is more than the feature needs. The intended direction is to store only a geohash (or a deliberately rounded coordinate) and compute exact distance transiently.
-
Erasure and withdrawal (Art 7(3) / Art 17(1)(b)): because consent is the only basis here, withdrawing it leaves no basis to keep what was already stored. Profile → Location therefore does both: turning the switch off withdraws consent, stops every location read — foreground and background — and deletes the stored
location/latitude/longitude/geohash4/geohash6fields from your profile and from the owner-onlyprivate/selfrecord they are mirrored into. The same screen also carries a standalone "Erase my stored location" control you can use at any time, including while location is still switched on (in that case the app will store a new point the next time it reads your location). If the deletion cannot be written — you are offline, say — the app tells you so rather than reporting success (#1034). -
Re-confirmation. We re-present this disclosure and ask you to confirm your location consent again at least once every 12 months, and again whenever the frequency, precision, retention, recipients or purpose changes.
-
Provision: location is optional. Declining it disables nearby discovery but you can otherwise use the app; declining background location leaves nearby discovery working whenever the app is open. We will not gate unrelated functionality on granting location.
3.5 Location — live "Hot/Cold" game (real-time precise distance)
- What happens: the Hot/Cold game is a real-time, two-player game that runs only inside an active, mutually-accepted game between you and one other user in your direct chat. While the game is active:
- your device GPS is polled about every 5 seconds on your device to keep the warmer/colder tint responsive;
- the other player's current precise position is read live from their
profile
locationfield (via a real-time listener) and the distance between you is computed on-device (haversine); - the only things posted into the chat as visible messages are distance labels and the colour tint (e.g. "Getting warmer", "🔥 Burning!") — not coordinates;
-
but — and this is the part we want you to know before you accept a game — while the game runs, each player's precise position is written to a live record attached to the chat room. In a private one-to-one chat that record is readable by the two of you. In a group or open room, it is readable by everyone in that room, not only the two players. That record is also not cleared when the game ends, and it is not yet cleaned up on a schedule. Fixing both — restricting the record to the two players, and wiping it when the game stops — is the highest-priority change on our list. Until it ships, do not start a Hot/Cold game in a room with people you would not want to know exactly where you are.
-
the game auto-quits if you drift more than ~5 km apart, and either player can quit at any time.
- Purpose: to play the consensual real-time proximity game.
-
Lawful basis: Art 6(1)(a) consent, and Art 9(2)(a) explicit consent for the special-category dimension described in Section 3.4 — both players must actively invite and accept the game, which is a specific, freely-given, withdrawable consent to share live precise distance for that session. The game is foreground-only: it runs while the chat is open, not in the background.
-
Retention of game data. The live position record described above persists on the chat room after the game ends until it is overwritten by a later game or deleted with your account. It is not ephemeral today, whatever an earlier version of this notice implied.
3.6 Chat messages
- Data: the text and images you send in direct and group chats
(
chat_rooms/*/messages→text,imageUrl,senderEmail,sentAt); room membership and metadata; in-chat system messages. - Purpose: to deliver the messaging feature.
- Lawful basis: Art 6(1)(b) contract for message delivery; safety screening of message content (the disallowed-language filter, Section 5) rests on Art 6(1)(f) legitimate interests (keeping users safe) and, where applicable, Art 6(1)(c) legal obligation. Message content is not processed on consent, so there is no consent to withdraw for it; you exercise control over it through erasure and account deletion instead (Section 10).
- Note: a message you send is also received by the other participant(s). Their copy may persist in their conversation even after you delete your account (see Sections 6 and 8). The image files you sent are not retained this way: account deletion removes them from Storage, so the delivered message survives without its photo (#1021).
- ⚠️ "Clear chat history" is not deletion. The control in the app is still labelled "Clear chat history" — we are renaming it, because the label promises more than the feature does. What it actually does is record a point in time against your e-mail address on that conversation, and then hide everything before that point from your view only. No message is deleted. The other participants continue to see every message exactly as before, and if you were ever to be shown that conversation again the hidden messages are still in our database. It is best understood as a restriction of processing for you (Art 18), not an erasure (Art 17). If you want data actually deleted, use account deletion (Section 10) or ask us — Section 10 explains what each one really does.
3.7 Safety: reports, blocks & moderation
- Data: user reports you submit or that concern you (
user_reports: reporter/reported identity, reason, free-text details, and a snapshot of the shared chat context); your block lists (blockedUserIds,blockedEmails); and the moderation audit trail (actionTaken,actionedBy,actionedAt,statementOfReasons,slaDeadline). - Purpose: to keep users safe, to action abuse, to meet our content- moderation obligations, and to defend against or bring legal claims.
- Lawful basis: Art 6(1)(f) legitimate interests (the safety of our users and the integrity of the platform — the specific legitimate interest required by Art 13(1)(d)), and Art 6(1)(c) legal obligation where the EU Digital Services Act notice-and-action duties (DSA Art 16–18) apply.
- Reports are handled under our internal notice-and-action procedure: each report is reviewed (target: within ~24 hours), an action is taken or declined, and a statement of reasons is recorded against the report.
3.8 Date of birth / 18+ age gate
- Data: your self-declared date of birth (
dateOfBirth). - Purpose: to operate the 18+ age gate and keep minors off an adults' service.
-
How it is checked, plainly: the date you type during onboarding is checked in the app, on your device. We do not verify it against any document, and we do not use any age-estimation or ID service. It is a declaration we take at face value, backed by the reporting and moderation process in Section 5 — not a proof of age. [planned] a server-side check as well.
-
Lawful basis: Art 6(1)(c) legal obligation and/or Art 6(1)(f) legitimate interests (age assurance / child protection).
- Minimisation note (Art 5(1)(c)): we store the full date of birth. [LEGAL REVIEW: consider storing only a verified "over-18" flag plus the verified date rather than the full DOB where the feature allows, to minimise the data held.]
3.9 Push notifications & device tokens
- Data: Firebase Cloud Messaging (FCM) device tokens (
fcmTokens) and your notification preferences (notificationPreferences). - Purpose: to send the in-app notifications you have enabled (chat messages, requests, game invites, strong-fit alerts, etc.).
- Lawful basis: Art 6(1)(b) contract — delivering the notifications you have asked for is part of the service. You control which ones you get in the app; the operating-system notification permission is a separate technical control over whether your device displays them at all.
- Retention: a device token is deleted when you turn that device's notifications off, when the token is refused by the messaging service as stale, and when you delete your account.
3.10 Technical, security & abuse-prevention data
- Data: rate-limit markers (
rate_limits), App Check attestation signals, and server-side logs (which may include technical identifiers such as IP address). - Purpose: to operate and secure the service and to prevent abuse.
- Lawful basis: Art 6(1)(f) legitimate interests (security, fraud and abuse prevention, service reliability). This covers server-side records only. Anything that writes to or reads an identifier from your device — crash reporting, performance monitoring, analytics — is dealt with separately in Section 3.11, which also explains that those three are currently running without the consent step they need, and what we are doing about it.
App Check. Firebase App Check is integrated, but its enforcement is currently switched off on our server functions, including account deletion — the device-attestation providers it depends on are not yet registered with Apple and Google. So while it is listed here and in Section 6.2 as something we use, it is not protecting those paths today. Section 13 says the same.
3.11 Crash diagnostics, performance monitoring and analytics
⚠️ Read this first — what happens today, 7 August 2026
The consent design described in the rest of this section is not yet built. In the app as it ships right now:
- crash reporting, performance monitoring and usage analytics all start automatically when you open Flybi — before you are asked anything, and whether or not you would have agreed;
- usage analytics records an "app opened" event at launch, ahead of any consent screen;
- there is no in-app switch that turns any of them off. The two switches described below do not exist yet;
- your Flybi user ID is attached to crash reports as the identifier for that device, and it is not cleared when you sign out — so on a shared device, later crashes can still carry the previous account's ID;
- a fault in one chat feature can additionally attach your e-mail address to a crash report, and a coarse (~39 km) area cell can be attached too.
We are not describing that as a design. It is a defect, it is the top of our engineering list, and until it is fixed the legal bases set out below are not being properly obtained. Everything marked [planned] below is where we are going, not what the app does now. If you want us to delete diagnostics data already collected about you, e-mail us (Section 1) — note that account deletion does not currently reach these systems (Section 10).
[planned] These will be off by default, with nothing running unless you switch it on, and the app working identically either way.
- The services: Firebase Crashlytics (crash reporting), Firebase Performance Monitoring (app and network performance), and Google Analytics for Firebase (usage analytics).
- Data — Crashlytics: a crash-dedup UUID, the Crashlytics Installation UUID, the Firebase Installation ID, a Firebase session ID, crash timestamp, bundle ID and app version, OS name and version, jailbreak/root status, device model, CPU architecture, RAM and disk, instruction pointers, method and function names, exception classes and messages, fatal signal names and codes, binary image names/UUIDs/sizes/base addresses, app foreground or background state, screen rotation, proximity-sensor trigger status, and version-control information.
- Data — Performance Monitoring: the Firebase Installation ID, device model, OS, orientation, RAM and disk, CPU usage, mobile carrier (MCC/MNC), radio and network type, country derived from your IP address, locale, app state, network URLs (without query parameters), response codes, payload sizes and response times, and IP addresses. Unlike crash reporting this collects from every session, not only when something fails.
-
What of your identity currently reaches these reports. Your Flybi user ID is set as the identifier on crash reports and stays set after you sign out; your e-mail address can be attached when one particular chat operation fails; a coarse ~39 km area cell and a chat-room ID can be attached the same way; and every log line the app records at "info" level or above is sent along as a breadcrumb. Your precise coordinates, name, bio, tags and connections are not — those are actively stripped. [planned] none of it should be there: the intended position is that no Flybi identifier or profile field is passed into a crash report at all, which is what the rewrite of this pipeline (to an explicit allow-list) is for.
-
Lawful basis: Art 6(1)(a) consent, and — logically first — your consent under Art 5(3) ePrivacy / cookiebekendtgørelsen § 3 to write and read a persistent installation identifier on your device. There is no legitimate-interest route for that device access, and none of the ePrivacy exemptions covers crash reporting, performance monitoring or analytics: the test is what is strictly necessary from your point of view, and Flybi works the same whether or not a crash report is ever sent. We therefore do not rely on Art 6(1)(f) for any of this. As the box at the top of this section says, that consent is not currently being asked for, so the collection happening today does not have the basis it needs. We would rather say that than dress it up.
-
Separate controls. [planned] "Crash & performance diagnostics" and "Usage analytics" will be two independent switches, both off by default, both refusable without any loss of functionality, and both re-accessible at any time in Settings. Neither switch is in the app today.
-
Withdrawal. [planned] When the switches ship, turning either off will stop collection, call
deleteUnsentReports()so anything queued on your device is discarded, and delete the Firebase installation where that is technically possible. Google documents that opting out "will apply the next time the user launches the app", so we will also hold our own local flag that our code honours immediately. Today there is no in-app way to switch this off. If you want it stopped, or want diagnostics data already collected about you deleted, e-mail us (Section 1) and we will do it by hand. -
Retention. Google retains Crashlytics data for 90 days; Performance Monitoring data for 30 days where it is associated with an IP address and 60 days where it is associated with an installation. These periods are enforced by Google, not by us.
-
Recipient and role: Google LLC acts as our processor for Crashlytics, Performance Monitoring and the Analytics measurement service, under the Firebase Data Processing and Security Terms. We keep Firebase Service Data sharing and the Analytics data-sharing settings off, so Google's controller-to-controller measurement terms — under which Google would be an independent controller of shared data — do not engage.
-
Transfers: this data goes to Google LLC in the United States. The transfer relies on the EU–US Data Privacy Framework, under which Google LLC is certified, with the EU Standard Contractual Clauses in Google's terms as the fallback safeguard. See Section 7.
- If you say no, we are not blind. Apple collects crash logs from TestFlight testers under Apple's own terms and shares them with us, and Google Play's Android vitals reports crashes from users who opted in to sharing diagnostics at the OS level. Neither of those requires anything from us on your device, and neither depends on your answer here.
3.12 Best-fit / ML signals
- Data: server-computed best-fit embedding vector (
embeddingVector), connection-outcome rows used to improve who we surface (connection_outcomes), encounter records and streak stats (flybi_encounters,flybi_user_stats). - Purpose: to compute and improve who we surface to you.
- Lawful basis: Art 6(1)(b) contract (surfacing best-fit people) and Art 6(1)(f) legitimate interests (improving how well we surface people).
3.13 Advertising — not active at launch
At launch Flybi shows no advertising. The Google AdMob SDK is integrated but ships disabled ("dark"), and we do not use your data for advertising, behavioural targeting, or ad measurement. There is therefore no Art 6 basis claimed for advertising at this time. If advertising is later enabled, we will update this notice first and, for any behavioural/targeted advertising or device-storage access for ads, obtain your Art 6(1)(a) consent (and the separate ePrivacy device-access consent — Section 9) and, on iOS, your App Tracking Transparency permission before any tracking occurs.
4. No automated decisions with legal effect — GDPR Art 13(2)(f) / Art 22
Flybi uses automated processing to rank and surface profiles (best-fit and soulmate/strong-fit scans) and an automated text filter to screen names, bios and chat for disallowed language. These help us run the service and keep it safe.
We do not make decisions producing legal effects concerning you or similarly significantly affecting you solely by automated means within the meaning of Art 22(1). Moderation actions that restrict an account or content (warn / hide / suspend) are taken by a human moderator, who issues a statement of reasons (DSA Art 17).
5. How we keep the service safe
We operate: an in-app report flow and block capability; a human moderation process with a ~24-hour review target, statements of reasons, and warn/hide/suspend actions; a disallowed-language filter on names, bios and chat; an 18+ age gate; and Terms/EULA acceptance at registration. These underpin the safety processing described in Sections 3.6–3.8.
6. Who receives your data — GDPR Art 13(1)(e)
6.1 Other users
By design, your profile (name, photo, bio, public tags, approximate area, badges and — if you make it visible — your personality profile) is shown to other signed-in users so they can discover and connect with you. Chat content is shared with the people in that conversation. Secret tags are shared only via a mutual reveal.
More than that is currently readable, and you should know it. Your profile record as stored today also carries your e-mail address and your precise last-known coordinates, and it is readable by any signed-in Flybi user, not only by the people we choose to show you to. Nothing in the app displays those fields — but "not displayed" is not the same as "not shared", and we are not going to describe it as if it were. Removing them from the readable copy is [planned]; see Section 3.4.
Open rooms. If you create or join an open ("Stop Bi") room, that room is listed to other signed-in users so they can find and join it. The listing shows its title and image, its join tags, and its approximate area — a geohash cell of roughly 1.2 km × 0.6 km, the same coarse grid used for profile discovery. Your precise coordinates are not in the room record: it holds only the cell, so the point you were standing on when you opened the room is not recoverable from it (#1033). Rooms you keep private are visible only to their participants and to anyone you invite.
⚠️ What an open-room listing actually carries. Everything in the room's record travels to the device of every signed-in user who lists open rooms — not just the parts the app puts on screen. That includes the e-mail addresses of the room's participants, of anyone invited to it, and of whoever created it (room membership is keyed by e-mail throughout Flybi), and the text of the last message sent in the room. The app does not display the last message or the addresses in the discovery card, but they are delivered all the same, and a determined person can read them. If you would not want your e-mail address known to strangers, do not join open rooms until we have fixed this. Re-keying membership from e-mail to an opaque ID is tracked as #696 / #600.
What a new joiner can see. When someone joins an open room, they are shown messages sent before they arrived — currently up to the most recent 200 messages of that conversation. There is no server-side limit behind that number: it is a cap the app applies, and one we can change remotely, so it is a product setting rather than a guarantee. People who were not present when you wrote something can therefore read it. A real cap — post-join only, or a short window — is [planned].
6.2 Processors (sub-processors) acting on our instructions
We use Google Firebase as our backend processor (the contracting Google entity — e.g. Google Ireland Limited and/or Google LLC, as applicable under Google's Cloud/Firebase terms). The specific services are:
- Cloud Firestore — profile, tags, chat, reports and related documents;
- Firebase Authentication — sign-in (email/Google/Apple);
- Firebase Storage — profile and tag images;
- Cloud Functions (region europe-west1, Belgium) — server-side logic including the account-erasure cascade and moderation triggers;
- Firebase Cloud Messaging (FCM) — push notifications;
- Firebase Remote Config — configuration;
- Firebase App Check — anti-abuse attestation. Integrated, but its enforcement is currently switched off on our server functions, including account deletion and chat-history clearing (Section 3.10). Treat it as present but not yet doing its job.
- Google BigQuery — some Firestore collections are exported to a Google BigQuery dataset for aggregate product analysis. Account deletion does not currently reach that dataset (Section 10).
And, for crash, performance and usage data (Section 3.11) — which, as that section explains, are currently running by default rather than on your switch:
- Firebase Crashlytics — crash reports;
- Firebase Performance Monitoring — app and network performance data;
- Google Analytics for Firebase — usage analytics.
Google processes this data on our behalf as a processor under the Google Cloud / Firebase Data Processing and Security Terms (an Art 28 Data Processing Agreement is in place via acceptance of Google's DPA). For the three diagnostic and analytics services above, the contracting entity is Google LLC and the data reaches the United States — see Section 7. We keep Google's data-sharing settings off so that Google does not become an independent controller of that data. No other processors (for example a third-party e-mail provider) are shipped in the current build; this list will be updated if any are added. (Current position; to be confirmed in a professional review as the project grows.)
- Google AdMob: integrated but disabled at launch (Section 3.13); no ad data is shared while it is dark.
6.3 Authorities and legal claims
We may disclose data to public authorities (e.g. Danish Police) where required by law or to address a serious risk to life or safety, and to our advisers to establish, exercise or defend legal claims.
7. International transfers — GDPR Art 13(1)(f) / Arts 44–49
Our processing is configured for the EU/EEA: Cloud Functions run in
europe-west1 (Belgium) and Firestore/Storage are provisioned in an EU
region (e.g. eur3 / europe-west1). (Current configuration; to be confirmed
in a professional review as the project grows.)
Two things nonetheless leave the EEA:
- Crash diagnostics, performance monitoring and analytics (Section 3.11) are processed by Google LLC in the United States. Note that these are currently running for everyone rather than only for people who switched them on — see the box at the top of Section 3.11.
- Some Google support, security or operational functions for the EU-hosted services may involve access from outside the EEA.
The mechanism is the same in both cases. Google LLC is certified under the EU–US Data Privacy Framework, which the European Commission has found to provide an adequate level of protection (Art 45), and the EU Standard Contractual Clauses are incorporated into Google's Data Processing Terms as an Art 46 safeguard that stands behind it. We keep the SCCs in the contract chain deliberately, so that the transfer remains covered if the Framework is ever suspended or annulled — a legal challenge to it is pending before the Court of Justice. You can request a copy of the relevant safeguard using the contact details in Section 1.
8. How long we keep your data (retention) — GDPR Art 13(2)(a)
We keep personal data only as long as needed for the purposes above. Every period below is anchored to an event we actually record — the date you deleted your account, the timestamp of the last message in a conversation, the date a report was closed — so that you can work out the period that applies to your data rather than reading a general promise.
⚠️ How these periods are enforced today, 7 August 2026. Deletion you ask for — account deletion, erasing your location — runs immediately, as a real server-side job, and you can rely on it. The time-based periods in the table below are a different matter: the scheduled clean-up job that is meant to enforce them has not been built yet. Rows marked [not yet automatic] describe the limits we hold ourselves to and will delete to on request, not a sweep that runs on its own. We are telling you this instead of quietly loosening the wording, and building the job is the fix.
| Data | Retention |
|---|---|
| Account, profile, tags, photos, personality, stats | Kept while your account exists. Erased when you delete your account (Section 10) — see the erasure timing note below. |
| Location (Section 3.4) | One point only. Each reading overwrites the previous one, so no trail is built. The stored point is deleted when you turn location off, when you use "Erase my stored location", and when you delete your account. The 30-day expiry for un-refreshed points is [not yet automatic]. |
| Live Hot/Cold game session data | The live position record written during a game stays on the chat room after the game ends until a later game overwrites it or your account is deleted (Section 3.5). Clearing it when the game stops, and sweeping old records, are [planned]. |
| Chat messages | Kept for the life of the conversation. The 12 months after the last message limit is [not yet automatic] — no job currently deletes dormant conversations. On account deletion your profile is erased, but messages you sent stay in the conversations they were delivered to, on our legitimate interest in the other participants' own record of their conversation (Art 6(1)(f)); you can object to that under Art 21 and we will weigh it. The images you sent are an exception: they are deleted from Storage by the erasure cascade, so a retained message shows the text but no longer the photo (#1021). |
| User reports / safety & moderation records | Our limit is 24 months from the date the report is closed (actionedAt), and these are kept beyond your account deletion, because they are needed to keep other users safe and to establish, exercise or defend legal claims (Art 17(3)(e), and our legitimate interest under Art 6(1)(f) in the safety of the people who reported). [not yet automatic] — deletion at 24 months is done on request or by hand until the scheduled job ships. Reports that led to a ban, or that concern serious harm, may be kept longer where a specific matter is live — we will tell you the period if you ask. |
| Date of birth / age-gate record | Kept while your account exists (age-assurance evidence); erased with the account. |
| Encounter & ML/connection-outcome rows about other users | On your deletion these are stripped of your name and photo and your identifier is replaced with a placeholder, rather than the rows being deleted, so other users' history and counts survive. Be aware that one of those placeholders is currently built from your account's internal ID rather than being a fresh, unlinkable token — so it is not the dead end we would like it to be. Fixing that is [planned]; see Section 10. |
| Blocks placed on you by other users | Kept as long as the blocking user's account exists, so that their block continues to work — and removed when you delete your account, since the erasure cascade scrubs you from other people's block lists. |
| Technical logs, rate-limit and security data | Our limit is 30 days from the date of the log entry, and up to 6 months for logs retained for a specific abuse or security investigation. [not yet automatic]. |
| Crash, performance and analytics data (Section 3.11) | Retained by Google: Crashlytics 90 days; Performance Monitoring 30 days where associated with an IP address and 60 days where associated with an installation. These are enforced by Google, not by us. |
| Backups | Our backup rotation is 30 days. A deleted record may survive in a backup until that backup is overwritten in the ordinary cycle; it is not used for any other purpose in the meantime, and if a backup is ever restored the deletions are replayed against it. |
Timing of erasure. When you ask us to erase data, or delete your account, we act on it promptly — the deletion runs when you confirm it, not on a clean-up schedule, and well inside the one month Art 12(3) gives us to respond. That is deliberately a different clock from the periods in the table above, which is why the box above tells you which of those periods are not yet enforced by a job.
Where a period above depends on something we cannot predict — an open safety investigation, a legal claim — we keep the data for as long as that specific matter requires and no longer, and we will tell you the expected period if you ask (Art 13(2)(a)).
9. Access to your device (ePrivacy) — Art 5(3) ePrivacy Directive / cookiebekendtgørelsen § 3
Two things Flybi does count as storing information on, or gaining access to information stored in, your terminal equipment under Art 5(3) of the ePrivacy Directive 2002/58/EC, transposed in Denmark as BEK nr 1148 of 9 December 2011 § 3:
- Reading your device's location and sending it to our servers — for discovery and background updates (Section 3.4) and the live game (Section 3.5). Sensor readings are outside Art 5(3) only while they stay on the device; once the reading, or any derivation of it such as a geohash, leaves the device, Art 5(3) applies (EDPB Guidelines 2/2023 v2.0, §44).
- Writing and reading the installation identifiers used by Crashlytics, Performance Monitoring and Analytics (Section 3.11). ⚠️ Those identifiers are currently being written at launch without asking you first — see the box at the top of Section 3.11. The rule below is the rule; we are not yet meeting it for this second item, and the consent prompt that will fix it is being built.
Both require your prior consent, and this is a separate legal hook that sits in front of our GDPR Art 6 basis — if we do not clear Art 5(3), no Art 6 basis can rescue the processing, and Art 5(3) has no legitimate-interest option. We do not rely on the "strictly necessary for a service you explicitly requested" exemption for any of it. In particular, that exemption cannot cover collection that continues while the app is closed, and it cannot cover crash reporting or analytics, because the test is what is strictly necessary from your point of view — Flybi works the same without them.
The operating-system permission dialog is not this consent. An OS permission prompt is a technical control over a resource; it does not name a purpose, a retention period, a recipient or a withdrawal right, and it cannot be a valid consent on its own. Our own in-app consent screen is what asks you, and the OS prompt is only triggered after you have said yes there. If you decline in Flybi, we do not show you the OS prompt at all.
Withdrawal. Turn location off in Profile → Location — one tap, at the same depth as switching it on. You can additionally revoke the permission in your device settings. Turning location off in-app stops every location read, foreground and background, and also erases the location already stored for you, both the copy on your profile and the private copy (Section 3.4). Withdrawing leaves the rest of Flybi working. For diagnostics and analytics there is no in-app switch yet (Section 3.11); until there is, e-mail us and we will stop it for you.
Supervision. GDPR matters are supervised by Datatilsynet; Digitaliseringsstyrelsen supervises the Danish cookiebekendtgørelse — the rules in this section — and can impose penalties under it. See Section 11.
10. Your rights — GDPR Art 13(2)(b)–(d)
You have the following rights over your personal data. To exercise them, use the in-app controls described below or contact us (Section 1).
- Access (Art 15) — a copy of your data.
- Rectification (Art 16) — correct inaccurate data; you can edit most of your profile in-app.
- Erasure / "right to be forgotten" (Art 17) — delete your account from
within the app (Settings → Delete account). This triggers a server-side
cascade (
deleteAccountCloud Function) that erases your profile and everything filed under it — tags and tag images, personality, badges and preferences, date of birth, location (both the profile copy and the private one), your stats and streaks, your soulmate connections and secret-tag overlaps, your encounters, reveal requests in both directions, rate-limit records, waitlist entry and your notification tokens — plus every file you uploaded to our storage (including the images you sent in chats, #1021), and finally your Firebase Authentication record, deleted last so the process can never leave you half-deleted. It also strips your name and photo from records that live on other users, and removes you from other people's block lists. What it does not reach — plainly: - Your e-mail address stays on every chat room you took part in, and on every message you sent that remains in someone else's conversation. The cascade uses those e-mail fields to find your rooms but does not currently clear them. Where the room is an open room, that address is readable by other signed-in users (Section 6.1). This is the biggest gap in our deletion today and it is being fixed.
- The placeholder that replaces you in shared history is built from your account's internal ID, so it is not the unlinkable token we would like it to be. Fixing that is [planned].
- Crash reports, performance data and usage analytics are not touched by the cascade (Section 3.11), nor is the BigQuery dataset those Firestore collections are exported to (Section 6.2). If you want those deleted too, e-mail us and we will do it by hand.
- Messages you sent that were already delivered to other people stay in their conversations (Section 8), and safety and moderation records are kept for the period in Section 8 under Art 17(3)(e).
A separate deactivation option lets you hide your account without deleting it.
- A web-based deletion request is also available for users who have uninstalled the app, at https://flybi.app/delete-account (which names the app/developer, as required by Google Play's account-deletion policy) (live and published — #725).
What "delete your account" does, and what "clear chat history" does — they are not the same. Deleting your account really deletes data, as described above. The control still labelled "Clear chat history" deletes nothing: it records a point in time against your e-mail address on that conversation and hides everything before it from your own view. Everyone else in the room still sees every message, and the messages remain in our database. We are renaming the control, because the current name promises deletion and delivers hiding. If you want data gone rather than hidden, delete your account or ask us. - Restriction (Art 18) — ask us to stop using your data while a dispute about its accuracy or our legal basis is resolved, instead of deleting it. Hiding a conversation from your own view is a form of restriction, not erasure — see above. - Objection (Art 21) — object to processing based on legitimate interests (Sections 3.7, 3.10 and 3.12); we will stop unless we have overriding legitimate grounds (e.g. ongoing safety/abuse handling). - Data portability (Art 20) — receive data you provided, based on consent or contract, in a structured, commonly used, machine-readable format. - Withdraw consent (Art 13(2)(c); Art 7(3)) — where we rely on consent, you can withdraw at any time, as easily as you gave it, without affecting the lawfulness of processing before withdrawal. We rely on consent for: - Foreground location and, separately, background location (Sections 3.4 / 3.5) — withdraw either in Profile → Location, or in your device settings. Withdrawing also erases the location already stored for you, and the same screen has a standalone "Erase my stored location" control. - Crash & performance diagnostics and, separately, usage analytics (Section 3.11) — the in-app switches are [planned] and not there yet, so for now withdraw by e-mailing us and we will switch it off for your account and delete what has been collected. - Your tags, where they reveal special-category data (Section 3.3), and optional profile fields — withdraw by removing them or editing your profile. - Any future advertising (Section 3.13).
Withdrawing any one of these leaves the rest of Flybi working. We do not make access to the app conditional on background location, diagnostics or analytics, and we will not re-ask after you have refused.
Access and data-portability requests are handled via the contact e-mail in
Section 1 (ngts91@gmail.com), with a response target of within one month as
required by Art 12(3). (Current process; to be confirmed in a professional
review as the project grows.)
11. Right to complain — GDPR Art 13(2)(d)
If you believe we have processed your data unlawfully, you may lodge a complaint with the Danish supervisory authority. You do not need to raise it with us first, though we would rather you did.
Datatilsynet (Danish Data Protection Agency) — https://www.datatilsynet.dk — supervises our compliance with the GDPR. Its current postal address and complaint channel are published on datatilsynet.dk; refer to the site for the authoritative details.
Digitaliseringsstyrelsen (Danish Agency for Digital Government) — https://digst.dk — supervises the Danish cookiebekendtgørelse (BEK nr 1148 of 9 December 2011), which is the rule that governs access to information on your device: our reading of your location, and the installation identifiers used by crash reporting, performance monitoring and analytics (Section 9). Complaints about those go to Digitaliseringsstyrelsen rather than Datatilsynet. Digitaliseringsstyrelsen is also Denmark's Digital Services Coordinator under the Digital Services Act.
You may also complain to the supervisory authority in your EU/EEA country of residence.
12. Accountability records we maintain (informational)
For transparency, and because the Art 30(5) "<250 employees" exemption does not apply to us (our location processing is not occasional and is likely to result in a risk to data subjects — these are alternative triggers, any one of which removes the exemption), we maintain a Record of Processing Activities (ROPA) under Art 30(1).
A Data Protection Impact Assessment (DPIA) under Art 35 is mandatory for our location processing. The route is not "large scale" — at our current size we do not meet the Art 35(3)(b)/(c) scale triggers — but Datatilsynet's own Art 35(4) list, item 3: processing of location data in combination with at least one further criterion. We process location data and meet at least two further WP248 rev.01 criteria (systematic monitoring, and sensitive or highly personal data). That list item carries no size threshold, so a closed beta of 26 users does not escape it. The DPIA covers the foreground/background split and why background collection is necessary, the Art 9 analysis, the sampling frequency and stored precision, retention, the outing / stalking / physical-safety risk model, processors and transfers, and withdrawal and deletion mechanics. If a high residual risk remains after mitigation we will undertake Art 36 prior consultation with Datatilsynet. The ROPA and DPIA are maintained on file.
13. Security & data breaches
We protect your data with measures including encryption in transit, Firebase
Authentication, server-side security rules (firestore.rules) and rate limiting.
App Check is integrated but its enforcement is currently off on our
server functions (Section 3.10), so it is not adding protection today. No system
is perfectly secure, and Sections 3.4, 3.5, 6.1 and 10 name the specific places
where our current rules are looser than we intend them to stay.
If a personal data breach occurs, we will notify Datatilsynet without undue delay and, where feasible, within 72 hours of becoming aware of it, unless the breach is unlikely to result in a risk to your rights and freedoms (GDPR Art 33), and we maintain an internal breach register (Art 33(5)). Where a breach is likely to result in a high risk to you, we will inform affected users without undue delay (Art 34). Because a breach affecting precise location, chat and identity could be high-risk (per EDPB Guidelines 01/2021 breach-severity factors: nature/sensitivity/volume of data, ease of identification, and severity of consequences), we treat such incidents accordingly.
14. Future features (not active)
The following are not part of the live service and are listed only so this notice stays accurate as the app evolves:
- Biometric / face-comparison identity verification — deferred. If introduced, biometric data used to uniquely identify you is special-category data (Art 9) and will require Art 9(2)(a) explicit consent, a strengthened DPIA, and an update to this notice before any processing begins. We do not process biometric data today. (A non-biometric "verified" trust badge exists, decided by a human moderator; any verification artifacts are kept in a private collection not exposed in discovery.)
- Advertising (Section 3.13) and payments/in-app purchases — not active; this notice will be updated before either launches.
15. Changes to this policy
We may update this notice. We will post the new version at https://flybi.app/privacy and, for material changes (e.g. a new processing purpose or legal basis), notify you in-app or by e-mail and, where required, seek fresh consent.
*Drafting note for counsel: every legal requirement above is grounded in the
research brief and in the external legal research memo of 7 August 2026
(MEMO.md) — GDPR Arts 3, 5, 6, 7, 8, 9, 12, 13, 17, 18, 21, 22, 25, 27, 30, 33,
34, 35; ePrivacy Art 5(3) + EDPB Guidelines 2/2023 v2.0 §44, transposed as BEK nr
1148 § 3; Danish Data Protection Act § 6(2); e-handelsloven § 7. Data-flow
descriptions are taken from the live code (firestore_fields.dart,
firestore.rules, discovery_repository_impl.dart, chat_room_game_wrapper.dart,
the deleteAccount Cloud Function, and the moderation runbook). The first
revision of 7 August 2026 brought the notice into line with the memo on:
background location and the Art 9 condition (§3.4, §3.5, §9),
Crashlytics/Performance/Analytics as consent-gated device access (§3.11),
event-anchored retention (§8), the honest account of chat clearing versus
deletion (§3.6, §10), and controller contact details (§1).
The second revision of the same day reconciled the notice against a
line-by-line source-code audit (code-audit-2026-08-07.md), and the code won
every disagreement. Corrected: the reach and the gaps of the deletion cascade
(§10, §8); the App Check claim (§3.10, §6.2, §13); world-readable profile e-mail
and coordinates (§3.4, §6.1); what an open-room listing actually delivers and how
much backlog a new joiner sees (§6.1); telemetry running by default rather than
on consent, with the Flybi user ID and, in one path, an e-mail address attached
(§3.11, §7, §9, §10); published retention periods that no scheduled job enforces
(§8); the live-position record left behind by the Hot/Cold game (§3.5); the
"clear chat history" watermark (§3.6, §10); and the client-side-only age gate
(§3.8). Passages describing a design that is not yet shipped are marked
[planned]; that marker is load-bearing and must not be removed ahead of the
code.
The open questions behind those markers — founder decisions, and points the audit
listed as not determined — are tracked internally in
docs/legal/open-items-2026-08-07.md and in
#1167. They are deliberately
kept out of this file: tool/build_site.py renders this document to
https://flybi.app/privacy, and markdown passes HTML comments through to the
published page.*