Privacy Policy
Last updated: 5 September 2026
This policy describes the personal data processed by the Rennes Bus Metro app — and by the other transit apps published by Applications Brozh Inc. — and by the services behind them. It applies to anyone who installs and uses one of these apps.
Sections 1 to 13 describe the current version of the app. An earlier version remains installed and usable on devices that cannot receive that update; it does not process the same data and is covered by section 14.
The principle of the current version, in one sentence: the app works with no account, no name, no email address and no advertising targeting of any kind — the local information space it may display is chosen according to the place you are looking at, never according to you. If you allow it, it uses your location to show you what is around you and to compute your journeys — without ever keeping it.
1. Publisher and data controller
Applications Brozh Inc., a joint-stock company incorporated under the law of Québec (Canada) and registered in Québec under Québec enterprise number (NEQ) 1174835836.
Registered office: 563 rue de la Congrégation, Montréal, Québec H3K 2J1, Canada.
Contact: contact@brozh.com — +1 438 929 4606.
Publication director: Clément Roulland.
Applications Brozh Inc. determines the purposes and means of the processing described below: it is the data controller under the General Data Protection Regulation (GDPR).
The app is offered to people located in the European Union, so this processing falls under the GDPR by virtue of its Article 3(2)(a). Data is hosted in the European Union (see §10) and accessed from Montréal by the publisher. That transfer to Canada relies on the European Commission’s adequacy decision for Canada (commercial organisations subject to PIPEDA).
2. Personal information protection officer
Under Québec’s Law 25 (Act respecting the protection of personal information in the private sector), the role of person in charge of the protection of personal information is held by the person exercising the highest authority within Applications Brozh Inc.:
Clément Roulland — contact@brozh.com — +1 438 929 4606.
3. What we collect
In the current version of the app: five categories, and nothing else.
a) Installation identifier. On first launch, the app generates a random identifier (UUID) stored on your device. It is not tied to anything that identifies you: no name, no email address, no account. Its job is to attach your favorites to your device; it also feeds, on our servers, the strictly anonymous statistics described in §4 — never an individual profile.
b) Device technical information. Operating system and its version, device model and type, app version, app city. This travels with requests to our servers and serves diagnostics, compatibility and installed-version tracking. It is stored alongside a last-activity timestamp refreshed at most once every 15 minutes: we keep no finer activity log.
c) Your favorites. The stops, lines, directions, bike stations and car parks you mark as favorites. A favorite is a plain reference to the network (stop, line or direction identifier) attached to your installation identifier. No free text, no location, 50 favorites maximum.
If the previous version of the app (see §14) was installed on your device, the current version recovers, on its first launch, the favorites you had saved there: the old app’s local file is read, its stop and line references are sent once to our servers, which translate them to the current network without storing or logging them; the recognised favorites are then re-created as favorites of the current version — covered by this policy from that point on — and the original file is deleted from your device. These references contain no location, no free text and no other data. As with any request to our servers, the call that translates them carries your installation identifier: the re-created favorites are attached to it, on the same terms as the ones you add yourself.
d) Your location, if you allow it. The “Nearby” and “Directions” screens may use your device’s location, accurate to about a hundred metres, at the moment you open them. It is sent to our servers to compute the answer — the stops around you, or your journey — then immediately discarded: we store it in no database, our application logs do not record it, it is never matched against your installation identifier, and the answer sent back to you contains no coordinate at all. It does travel in the request’s address, however: as such it appears in our host’s access log, like your IP address, for the same duration and without being used by us (see §7). The app never tracks your movements: it reads your location as a one-off, only when the screen requires it, and only in the foreground. Declining the permission leaves the rest of the app working.
One qualification applies once the counting described in §4 is in service: on the “Nearby” screen your location is then resolved to the nearest stops — at most two — and it is those stops which enter a count — never the coordinate, never a distance. The coordinate itself is still discarded immediately, as described above. Nothing is stored that is not already stored when you open a stop’s sheet: a stop identifier, per day, with no identifier column.
e) Your recent places — on your device only. The places you pick in the “Directions” screen are kept on your device (ten at most) so they can be offered to you again. They are never transmitted, either to us or to a third party. You can clear them one by one, all at once, or through “Delete my data”.
4. Anonymous audience measurement
The app sends our own servers an anonymous, aggregate usage measurement, so we can understand which features are used and improve the app.
What is measured — four categories, and nothing else:
- Navigation within the app — which tab and which section are opened, and by which path a stop’s page is reached.
- Search — that a search took place, the length bucket of what was typed, and the kind of result opened.
- Journey choice — which of the proposals shown is picked, and its rank in the list.
- First session and technical errors — a summary of the very first session, and the error codes the app runs into.
The guarantees, which hold for all four categories:
- No persistent identifier is sent: no installation identifier, no device identifier, no advertising identifier. The ingestion endpoints are technically separated from the rest of the API and structurally have no access to your installation identifier.
- An ephemeral session identifier is generated in memory each time the app opens and changes with every session. It allows a journey to be reconstructed within a session; two sessions cannot be linked to one another.
- When the network is unavailable, pending submissions — and the ephemeral session identifier they carry — are kept on the device only for the time needed to transmit them, for at most 72 hours, then erased; never read back for any other purpose. Past that point they are deleted without ever having been sent.
- The list of events is closed, exhaustive and published: it appears in Annex A, at the end of this page, dated. No event outside that list is emitted. Each dimension of an event is likewise a closed set of values.
- No free text ever leaves the device. A search is reported as a query-length bucket (
1-2,3-5,6+) and the kind of result opened — never the text you typed. A technical error is reported as a code — never a message or a payload. - Beyond the event itself, each submission carries only the city, the app version, the operating system and a “first session” flag.
Our servers additionally compute aggregate usage statistics from the data described in §3: the number of active installations per day, week and month; the proportion of installations still active by install week; the distribution of daily opens; counts of favorites added and removed per line; and the number of consultations of each stop or interchange, per day. Each of these statistics is a plain count carrying no identifier. The intermediate counters attached to an installation for the duration of the computation are ephemeral by construction: the number of opens in a day is destroyed every night once aggregated, and the marker that avoids counting the same consultation of a stop more than once expires by itself after 60 seconds, without being stored durably or backed up (see §9). They serve to monitor the health of the service and decide its evolution, and can identify no one.
Among these statistics, per-stop attendance — the number of consultations of each stop, per day, with no identifier whatsoever — also serves as an audience measure for selling local information space within the app. This is neither targeted advertising nor profiling: what is measured is the audience of a place — the way a billboard is rented on the footfall that passes it — and never the attention of a person. Only those anonymous counts are concerned: no individual data is sold, shared or transmitted, and an advertiser would never receive anything other than totals.
Display-surface counting
This subsection describes a counting that starts at a specific moment — the activation of a setting on our servers, city by city — and not before. It is published in advance: the text exists before the processing, not the other way round.
Two counts are then added to the ones described above. Both are per stop and per day, with no identifier column whatsoever:
- Slots offered — how many times a local information slot could have been displayed for a given stop, and on which of the four surfaces concerned: a stop’s sheet, your favorites, “Nearby” and a line’s detail. This count is kept as two distinct series — guaranteed slots and candidate slots — which are never added together.
- Exposed sessions — how many distinct sessions saw that stop, across all surfaces.
To avoid counting the same session ten times, our servers create a display session token. This token:
- is created by the server, never declared by the app, never sent to your device;
- lives only in our cache, and is written to no database;
- is never matched against the audience measurement described earlier in this §4 — the two are technically separate, and share no table and no output;
- expires after one hour without activity from your installation;
- has no other use: no rate limiting, no diagnostics, no personalisation.
If our cache is unavailable, nothing is counted and nothing is recovered: these counts are floors, never estimates.
⚠️ The ceiling is two hours, not one. The hour above is the inactivity window that ends a session. The two de-duplication markers derived from the token carry a fixed two-hour lifetime that never extends. The link between your installation and a stop therefore stays reconstructible for at most two hours after a display. Past that point, only totals remain.
Two “sessions” now coexist in this policy, and they are not linked. The ephemeral session identifier of the audience measurement is created by the app, in memory, and carries no installation identifier. The display session token is created by the server and knows your installation. No link exists between the two, and none is possible: they meet in no table.
Finally, the “Nearby” screen is the only one of these four surfaces whose counted fact is derived from your location. What is counted there is neither a coordinate nor a distance, but the nearest stops, at most two — see §3.d.
This data is kept as aggregate counters. None of it is used to profile you, or to target advertising at you, and, in the current version, no ad network and no third-party analytics tool receives it: the measurement is entirely first-party.
5. Crash reports
The app embeds the Sentry SDK, configured for crashes only.
What is sent: the crash stack trace, the device model, the OS version, the app version and build number, and a session start/end marker used to compute the crash-free session rate.
What is explicitly switched off at initialisation: default personal-data collection (sendDefaultPii = false), performance tracing, profiling, session replay, automatic breadcrumbs, network and UI instrumentation, and app-hang tracking.
No installation identifier and no usage event ever reaches Sentry. Crash reports and the audience measurement of §4 are two separate sets, with no common identifier that could bring them together.
As with any network call, your IP address is visible to Sentry’s ingestion endpoint at the transport layer; it is not attached to the report.
Sentry processes this data in its European organisation (Frankfurt, Germany) and retains error reports for 30 days.
6. What we do not collect
In the current version of the app:
- No account, no name, no email address, no password
- No tracking of your movements — your location, if you allow it, is read as a one-off to answer your request, never kept by us, never turned into a history (see §3.d)
- No advertising identifier, and no per-person targeting. Local information space may be displayed (see §4): it is chosen according to the place you are looking at, never according to you, your history or a profile. No advertising network and no third-party analytics tool receives anything
- No cross-app or cross-site tracking — the app therefore never shows a tracking permission prompt (App Tracking Transparency)
- No browsing history on our servers — your recent places stay on your device (see §3.e), and your favorites are the only data we keep for you
- No free text in the audience measurement: neither typed searches nor error messages
- No third-party analytics tool, no data broker
7. IP address
Your IP address is processed, never stored durably:
| Where | In what form | For how long |
|---|---|---|
| Anti-abuse counter (Redis cache) | Counter key only, with no associated content. Depending on the route called, a key carries either your IP address or your installation identifier — never both within one key. A single request may feed two counters with distinct keys, one by IP address, the other by installation | 60 seconds, then automatic expiry |
| Host access logs | Standard HTTP logging: caller address and request address, including coordinates where applicable (see §3.d) | Hosting-platform retention, not queried by us |
| Crash-report ingestion (Sentry, EU) | Network origin of the call, not attached to the report | See §5 |
8. Purposes and legal bases
| Processing | Purpose | Legal basis (GDPR) |
|---|---|---|
| Installation identifier, favorites | Provide the favorites feature and restore it on every launch | Performance of the service you request (art. 6(1)(b)) |
| Recovery of the previous version’s favorites | Restore your favorites when you move to the current version | Performance of the service you request (art. 6(1)(b)) — translated in memory, references never kept |
| Device technical information | Diagnostics, compatibility, installed-version tracking | Legitimate interests (art. 6(1)(f)) |
| Anonymous audience measurement | Understand usage and improve the app | Legitimate interests (art. 6(1)(f)) — strictly first-party, no persistent identifier |
| Derived usage statistics (activity, retention, favorites) | Monitor the health of the service and decide its evolution | Legitimate interests (art. 6(1)(f)) — outputs anonymous by construction, no identifier kept |
| Per-stop attendance (consultations) | Measure the audience of stops, including with a view to the future commercialisation described in §4 | Legitimate interests (art. 6(1)(f)) — ephemeral 60-second deduplication, anonymous output with no identifier |
| Crash reports | Fix defects and measure stability | Legitimate interests (art. 6(1)(f)) |
| Anti-abuse counters (IP address or installation identifier, depending on the route) | Security and availability of the service | Legitimate interests (art. 6(1)(f)) — counter key alone, 60 seconds, with no associated content |
| Display-surface counting (slots offered, exposed sessions) | Measuring the audience of a place with a view to selling local information space (§4) | Legitimate interests (art. 6(1)(f)) — anonymous output per stop and per day, with no identifier column; ephemeral de-duplication capped at two hours |
| Location (Nearby, Directions) | Show you the stops around you and compute your journeys | Performance of the service you request (art. 6(1)(b)) — processed in memory, never kept |
| Place search (typing an address or a place) | Suggest and locate the places you type | Performance of the service you request (art. 6(1)(b)) — queries processed by Apple (see §10) |
None of this processing requires your prior consent. Storing the installation identifier on your device is strictly necessary to deliver the service you request — restoring your favorites — and is therefore covered by the exemption in Article 82 of the French Data Protection Act. The audience measurement of §4 falls under the audience-measurement exemption in that same Article 82: it serves solely to produce anonymous statistics on the use of the app, for our own use only, without cross-matching against other processing and without following your browsing elsewhere. Submissions waiting for a network are kept on the device only for the time needed to transmit them, for at most 72 hours, then erased; never read back for any other purpose.
Keeping your recent places on your device is, like the installation identifier, strictly necessary to the service you request and falls under the same exemption (Article 82 of the French Data Protection Act). Nothing there is accessible to anyone but you.
9. Retention periods
| Data | Period |
|---|---|
| Active installation — identifier, device information, favorites | For as long as the app is used |
| Inactive installation | 18 months after last activity, then the identifier and its favorites are deleted |
| Favorite references from the previous version | Never kept — translated for the duration of the request; the original file is then deleted from your device |
| Audience-measurement submissions pending on the device | 72 hours at most, then deleted — whether or not the network has come back |
| Raw audience-measurement event sequences (ephemeral session identifier) | 14 days — on our servers |
| Aggregate audience-measurement counters — no identifier column | Unlimited: these are anonymous statistics |
| Derived usage statistics — no identifier column | Unlimited: these are anonymous statistics |
| Daily per-installation open counter | Destroyed every night once aggregated into an anonymous histogram |
| Stop-consultation deduplication marker (installation identifier + stop) | 60 sliding seconds, automatic expiry, never backed up |
| Crash reports (Sentry) | 30 days |
| Anti-abuse counter keys (IP address or installation identifier, depending on the route) | 60 seconds |
| Display session token (cache) — see §4 | 1 hour without activity, a window that extends on each request; never written to a database |
| Display de-duplication markers derived from that token | 2 hours, a fixed lifetime that never extends |
| Per-stop counts of slots offered and exposed sessions — no identifier column | No limit: these are anonymous statistics |
| Location (Nearby, Directions) | Never kept by us — used for the duration of the computation, then discarded; for the host’s access log, see §7 |
| Recent places (Directions) | On your device only, until you clear them |
| Database backups | 10 days (see §11) |
Purges are triggered by an operator from our back-office, on a reference cadence of once a month: the real worst-case delay is therefore the stated period plus at most one month.
10. Recipients and hosting
We do not sell, rent or trade any data. The only third parties that process it are our technical sub-processors:
| Sub-processor | Role | Data concerned | Location |
|---|---|---|---|
| Fly.io, Inc. (United States) | Hosting of the server application and the database | All server-side data, access logs included (see §7) | Amsterdam region (Netherlands), European Union |
| Upstash, Inc. (United States) | Technical cache | Transient counter keys (≤ 60 s); no personal data retained | Amsterdam region (Netherlands), European Union |
| Functional Software, Inc. (Sentry) (United States) | Crash reports | See §5 | European region (Frankfurt, Germany) |
All three are established in the United States while hosting the data in the European Union. Any resulting transfer is governed by a data-processing agreement incorporating the European Commission’s standard contractual clauses.
The publisher accesses the data from Montréal; that transfer relies on the adequacy decision for Canada (§1).
Place search: Apple. When you type an address or a place in the “Directions” screen, what you type is sent to Apple Inc. (the Maps/MapKit mapping service), which processes it on its own account, under the terms of its own privacy policy (apple.com/legal/privacy). We attach neither your location nor your installation identifier to it: the search is simply biased towards the city the app covers. What Apple keeps of those queries is a matter for its policy, not ours.
In the current version, no ad network, no data broker and no third-party analytics tool receives anything. The recipients specific to the earlier version are listed in §14.
11. Deleting your data
The app offers a “Delete my data” button in the “About” screen. It immediately and permanently deletes, on our servers, your installation identifier and all of your favorites, then clears the identifier held on the device. A new identifier, unrelated to the previous one, is generated on the next launch. The same button also clears the recent places kept on your device.
You may also write to contact@brozh.com.
Backups. Our database is backed up in encrypted form, for disaster recovery only. Deleted data can therefore survive in those backups for at most 10 days after deletion, after which it expires automatically. Those backups are only ever used to restore the service after an incident.
Because the audience measurement of §4 and the crash reports of §5 carry no identifier, they cannot be attached to you — so they can neither be located nor deleted individually. They disappear on their own when the periods in §9 elapse.
12. Your rights
You have the rights of access, rectification, erasure, restriction, objection and portability over data concerning you, as provided by Articles 15 to 22 of the GDPR.
To exercise them, write to contact@brozh.com; we answer within one month. Since we hold nothing that identifies you, we can only match a request to data if you send us your installation identifier; failing that, the “Delete my data” button remains the most direct and reliable way to obtain erasure.
You may at any time lodge a complaint with a supervisory authority. In France this is the Commission nationale de l’informatique et des libertés (CNIL), 3 place de Fontenoy, TSA 80715, 75334 Paris Cedex 07 — www.cnil.fr. People residing in Québec may contact the Commission d’accès à l’information du Québec — www.cai.gouv.qc.ca.
13. Children
The app is aimed at the general public and does not target children. It asks for neither age nor identity, and knowingly collects no data relating to a child.
14. Earlier versions of the app
An earlier version of the app remains installed and usable on devices that cannot receive the current version. It is published under the same App Store listing and is therefore covered by this policy. It shares no code with the current version: sections 1 to 13 do not apply to it, and what follows describes it in full.
- Audience measurement. This version uses Mixpanel (Mixpanel, Inc., United States), a third-party analytics tool, on its European infrastructure — the data is hosted in the European Union. What is sent to it: app installation and app opening, the screen viewed, the addition and removal of a favorite (with the stop and line it refers to), the creation of a reminder, and crash reports. A device identifier, generated by Mixpanel and stored on the device, is sent alongside them. This version explicitly asks Mixpanel not to derive any location from the IP address, so no location data travels with them either. None of it is attached to a name, an email address or an account.
- Favorites. They are stored on your device only, in a local file. For as long as you use this version, no server of ours holds a copy, and deleting them in the app deletes them permanently. Their addition and removal are, however, counted in the audience measurement above. When you move to the current version, these favorites are recovered as described in §3.c: they are then re-created on our servers and attached to your installation identifier.
- Real-time departures. This version requests them directly from the open-data service of STAR, the operator of the Rennes network. No server of ours is involved: we do not see those requests, and your IP address is visible to that recipient alone.
- Location. If you allow it, this version uses the device location to sort stops and bike stations by proximity. The computation happens on the device: no coordinate is transmitted, either to us or to a third party.
- Invitation to the current version. This version asks our server whether access to the public beta of the current version is open, and then for the link if you take it up. Neither call carries any identifier or any content; only your IP address is visible, on the terms set out in §7.
- Retention, and the end of the measurement. The measurement data is retained until the Mixpanel project is deleted. What was sent before this update did carry an approximate, city-level location that Mixpanel derived from the IP address: it remains in the history already recorded, and in the device profile, whose last value stops being refreshed rather than being cleared. Mixpanel offers no way to remove that one property on its own. That project will be deleted once the current version is fully rolled out: the deletion ends collection for all earlier versions at once, with no action on your part, and erases all of the data already collected, that location included.
The most direct way to end this processing on your device remains to install the current version, when your device can receive it, or to uninstall the app.
Annex A — List of audience-measurement events
Dated annex: 20 August 2026. This list is exhaustive and closed. It is presented as an annex, and dated, because it can change: the body of the policy describes the categories measured and the guarantees around them, which do not change; this annex gives the exact state of the list at a given date. Any change is published here with a new date.
Eight events. Each dimension is a closed set of values; no free value is possible.
| Event | What it records | Dimensions |
|---|---|---|
explore_section_toggled |
A section of the “Explore” screen is opened or collapsed | — |
tab_selected |
A tab is selected | level: root, explore |
search_used |
A search took place | query-length bucket (1-2, 3-5, 6+), kind of result opened |
route_direction_switched |
A line’s direction is flipped | — |
first_session_summary |
Summary of the very first session | — |
client_error |
A technical error occurs in the app | code: decode_lossy, config_fallback, unexpected_empty |
trip_plan_proposal_chosen |
A journey proposal is picked | rank: position in the list; long_wait: long wait, yes or no |
hub_detail_opened |
The page of a stop or interchange is opened | source: nearby, favorites, explore, route_detail, trip_detail, deep_link, other |
hub_detail_opened is emitted once per opening: automatic refreshes of the screen emit none.
Removed events. Three events tied to a tipping feature — tip_card_viewed, tip_tapped, tip_outcome — appeared in previous versions of this page. That feature is not offered: these events are no longer declared and are not emitted.
15. Changes and contact
Any change to this policy is published on this page together with a new update date; the version in force is always the one shown here. The app displays a summary of it and a link to this page.
Applications Brozh Inc.
563 rue de la Congrégation, Montréal, Québec H3K 2J1, Canada
contact@brozh.com — +1 438 929 4606