Privacy Policy
1. Introduction
Cortex ("the App") is a focus-timer and sleep app. This Privacy Policy explains what data the App collects, what leaves your device, who receives it, why, and what you can do about it.
Who is responsible. Cortex is built and published by Dmitry Afanasyev, an individual developer working alone. There is no company, and no legal entity stands behind the App. He is the data controller for the purposes of the EU/UK General Data Protection Regulation (GDPR). Contact: [email protected] — that address reaches him directly and is the address for every request described in section 9. We do not publish a postal address here; if you need one for a formal request or for a complaint to a supervisory authority, ask at that email address.
Scope. This policy describes the iOS version of the App. It does not cover the Apple App Store, Apple Health, or any website you reach by tapping a link inside the App. Where the Android build behaves differently, this policy says so.
One thing to understand up front. The App has no accounts, no login, and no server of its own. We never learn your name, email address, or Apple ID. But "no account" is not the same as "no data leaves your device": the App does send usage events, crash reports and purchase events to third-party services, tied to anonymous identifiers those services generate. Sections 2 and 4 describe exactly what.
2. Information We Collect
2.1 Data stored on your device
The App keeps the following in its local storage on your device. This stored record is never uploaded. We receive no copy of your history, your notes, your goals, or your settings file. Some of the same values are, however, sent separately as analytics events at the moment they happen, unless you have turned analytics off — section 2.2 lists exactly which, and describes the switch. These are two different things: your stored history stays on the device, while individual actions are reported as they occur.
- Focus and sleep sessions: duration, planned duration, start and completion timestamps, mode, whether the session completed or was interrupted and why, your 1–5 quality rating, logged distractions, sleep quality rating, your free-text morning journal note, whether you felt refreshed, wake time, and which sound you used. The App keeps up to 1,000 sessions; older ones are dropped.
- Settings: timer durations, sound and volume preferences, selected sound, all notification settings and reminder times, language, onboarding flags, install date.
- Goals: your daily target and each goal you create, including the title you type.
- Custom timer presets: including the name you type (up to 10 presets).
- Streaks and achievements: badges and when they were unlocked, current challenge, longest streak, streak-freeze state.
- Apple Health readings copied into the App: see section 7.
- Weekly report cache: the computed report (score, peak hours, mode distribution, totals, streaks, recommendations).
- Subscription state: your current tier (free / monthly / annual / lifetime).
- Timer state and download status of premium sounds.
- Downloaded premium sound files (
.mp3) in the App's Documents folder. - A CSV export file, if you use the export feature, written to the App's cache folder and handed to the iOS share sheet. The App does not upload it anywhere; what happens after you choose a destination in the share sheet is up to you and that destination.
What is stored here and genuinely goes nowhere. From the list above, the following never appears in any analytics event, crash report, export or network request:
- the free text you type — goal titles, custom timer names, and your morning journal note;
- whether you felt refreshed, and your wake time;
- the stored session records themselves, including the start-time field they hold;
- the contents of the cached weekly report — its score, peak hours, mode distribution and recommendations. Opening the report is reported as an event; what the report says is not;
- your Apple Health readings, both as numbers and as anything computed from them (section 7.2, including the one residual case it names for installations upgraded from an older version);
- the live state of the timer.
Two files are also never uploaded by the App: the CSV you create with the export feature (it is written to the App's cache folder and handed to the iOS share sheet — after that it is up to you and the destination you choose), and the premium sound files you download.
One thing that list cannot hide, and we would rather say than let you assume otherwise: every event is timestamped by the analytics SDK at the moment it is sent. So even where a stored time field never leaves the device, the time at which you did something is visible to the recipients of the corresponding event.
Everything else in that list has a counterpart in section 2.2. The duration, mode, outcome and rating of a session, the distraction types you log, your sleep quality rating, the sound you used, your language and notification settings, your subscription tier, your goal targets and your badges are all reported as events or as properties at the moment they occur — not as a copy of the stored record, but as the same information.
2.2 Analytics and product usage data
In one sentence: we can see which screens you open, how long your sessions last, what you rated them, which sounds and features you use, and what you bought — and we cannot see a single word you typed.
The App sends usage events to two analytics services at the same time:
- Firebase Analytics (Google) — configured on the iOS build and on the Android build
- PostHog Cloud EU (PostHog)
Both services receive the same events, apart from two differences: Google's standard purchase event — which carries the product identifier, value and currency of a completed purchase — is sent to Firebase Analytics only, and PostHog additionally records each change of a device-level property as its own small event (see below).
You can turn all of this off. Settings → Privacy & Safety → Usage Analytics is a switch that stops everything described in this section. It is on by default — the App does not ask you before the first event is sent — and your choice is stored on your device and survives restarts and app updates.
While the switch is off:
- no event, no screen view and no device property is sent to Firebase Analytics or to PostHog;
- the App additionally turns off the two SDKs' own automatic collection, so Firebase's automatic events and PostHog's app-lifecycle events stop as well;
- if analytics has been off since you first opened the App, the PostHog client is never created at all, so no PostHog person profile exists for your installation;
- the breadcrumb trail written into crash reports (section 2.3) stops too — not only the names of the analytics events, but the App's own markers as well ("App launched", "Timer started: pomodoro 1500s", "Session recorded", which sound could not be played) — and so do the details attached to a handled error, such as which sound or which subscription plan was involved.
What the switch does not stop — we would rather say so here than let you discover it later:
- crash reports and error diagnostics to Firebase Crashlytics (section 2.3) keep running — but with the switch off they carry the crash or the error itself and the name of the code path it happened in, and nothing about what you were doing before it;
- RevenueCat (section 2.4) keeps running. It is how a purchase is recognised at all, and switching it off would take away the premium features you paid for;
- the plain network facts in section 2.5 — the premium-sound download, the over-the-air update check, and the IP address that any request reveals.
Turning analytics off sends nothing at all: there is deliberately no "opted out" event. Turning it back on sends one event recording that you did, and where from — at that moment you have consented again.
What is in an event. Each event has a name and a small set of parameters. Categories of events:
| Group | Examples of what is sent |
|---|---|
| App lifecycle | App opened; number of sessions so far; days since install |
| Onboarding | Which step you viewed, which option you tapped, whether you skipped, which sound you previewed |
| Focus sessions | Mode, progress percentage, whether a custom timer was used, which sound, your 1–5 quality rating, how many distractions and of which of five fixed types (phone, people, noise, thoughts, other), why a session was interrupted, and whether the length was a preset or was computed for you. The planned and actual length in seconds are included only when the length was a preset, a custom timer, or a value you set by hand — see 7.2. Starting a break is reported by the same event, with the break mode and its length; the end of a break is not reported at all |
| Sleep | Sleep session duration and sound, planned vs actual minutes, your 1–5 sleep quality rating |
| Goals, streaks, achievements | Target minutes (not the goal's title), a locally generated goal id, streak milestone reached, badge id, challenge type |
| Paywall and purchases | Which paywall variant, which plan you selected, how long you spent on the paywall, how you dismissed it, and — on a completed purchase — the tier, price and currency (plus the product identifier, to Firebase only; see 2.4) |
| Purchase and paywall failures | Which plan was involved and the error code the store SDK returned when a purchase, a restore or a paywall load failed |
| Premium feature gates | Which premium feature you tapped and on which screen |
| Sounds | Which sound you selected or downloaded, whether it is premium, and the reason a download failed |
| Notifications | Which notification type you tapped; whether you granted notification permission and from where; when reminders were paused after a purchase; and, when reminders had lapsed and you came back, how many days it had been since you last opened the App |
| Reports and prompts | Whether a weekly report was a preview or full, when a review prompt was shown |
| Screens | The name of each screen you open (e.g. Focus_Timer, Sleep_Stats, Settings) |
| Apple Health | Only whether you answered the Health permission sheet, and whether it came back granted or denied. No Health value and nothing computed from one — see section 7.2 |
| Privacy switch | That you turned Usage Analytics back on, and that you did it from Settings. Turning it off sends nothing |
Device-level properties attached to your events. These are attached to events rather than sent once, so they travel with everything above. There are two groups.
Set by the App: subscription status and tier; a bucketed
session count (0, 1-5, 6-20,
21-50, 51+); a bucketed
days-since-install; whether sound is on; your app language setting; whether
notifications are enabled; whether you granted the iOS notification permission;
your selected sound; the app version; which timer mode you use most often; whether
you use goals; whether you use the sleep timer; whether you bought or skipped at
the end of onboarding; and whether Apple Health is connected. Every event is also
tagged with whether it came from a development build or from the released app.
Added by the SDKs themselves: the PostHog SDK attaches, on its own, device type, manufacturer, the device model name as reported by the operating system (for example "iPhone 15 Pro" — not the name you gave your phone), OS name and version, app name, bundle identifier, app version and build number, whether the app is running in a simulator, locale and time zone, and it generates app-lifecycle events (installed / updated / opened / backgrounded). The Firebase SDK likewise attaches its own identifiers and device information; those are produced inside Google's SDK rather than by our code, so we describe them from Google's documentation rather than from ours.
One consequence worth knowing if you ever compare volumes: in PostHog, each change to one of the App-set properties above is recorded as its own small event, so PostHog holds more events than the number of actions you took.
Identifiers. The App never calls the "identify this user" function of either service — there is no user ID to give them. Each service generates its own anonymous, per-installation identifier and attaches it to the events. PostHog is configured to build a person profile around that anonymous identifier, which means your events are grouped together across sessions on that installation. A few event parameters (a session id, a goal id) are millisecond timestamps generated on your device — the moment a session finished, the moment a goal was created — and used as local identifiers. They reveal that timing to the recipient, but they are not linked to you.
2.3 Crash reports and error diagnostics
In one sentence: with Usage Analytics off, Crashlytics still receives crashes and handled errors — the stack trace, the error, and the name of the code path it happened in — and nothing about what you were doing before them.
- Firebase Crashlytics (Google) receives crash reports. While analytics is switched on, it also receives a breadcrumb log: the name of every analytics event listed above, and the App's own markers alongside them ("App launched", "Timer started: pomodoro 1500s", "Session recorded", which sound could not be played), written into that log as they happen — so a crash report then contains a trail of what you were doing. Handled (non-fatal) errors are reported too, with a short context string naming the code path that failed; the attributes attached to such an error — which sound, which subscription plan, which notification type — follow the same switch as the breadcrumbs.
- PostHog receives a copy of the same handled errors through its error-tracking feature.
- What the analytics switch in 2.2 does and does not cover here. It covers the whole breadcrumb log, the attributes of a handled error, and the PostHog copy of the errors — all of which stop with the switch off. It does not cover Crashlytics itself: the crash report and the bare non-fatal error keep going. If you do not want those either, the only way to stop them is to uninstall the App.
- Expo receives one crash-related item as well: if the App crashed fatally the last time you used it, the text of that error is attached to the next update check. See 2.5.
Crash and error reports contain stack traces and technical state, not your notes, goals or Health readings. With Usage Analytics off that is all they contain; with it on, they additionally carry the breadcrumb trail and the error attributes described above.
2.4 Purchase and subscription data
Purchases run through Apple's In-App Purchase system and are managed with RevenueCat.
- On every cold start of the App, and whenever your subscription status changes, the App contacts RevenueCat — even if you have never made a purchase. Opening the paywall also fetches the product catalogue from RevenueCat.
- RevenueCat's SDK creates an anonymous app user ID for the installation. The App does not set, read or store it, and never sends RevenueCat your email address, name, or any custom attribute — there are no such calls in the App.
- When you buy or restore, Apple's StoreKit handles the transaction with your Apple ID and RevenueCat validates it. The App itself only reads back which product identifier is active.
- On iOS, the App turns on Apple Search Ads attribution: Apple's AdServices attribution token is collected and passed to RevenueCat, so a purchase can be attributed to the ad campaign that led to the install. This is Apple's own privacy-preserving attribution. The App does not show the App Tracking Transparency prompt and contains no advertising SDK, so iOS does not give it the advertising identifier (IDFA).
- On Android builds the purchase SDK is not configured, and the App sends nothing to RevenueCat there. Firebase Analytics and Crashlytics, however, are configured on Android — the Android exception applies to RevenueCat only.
What reaches the analytics services. A completed purchase is reported to both Firebase and PostHog with the subscription tier, the price, the currency and the place in the App you bought from; the product identifier additionally goes to Firebase Analytics inside Google's standard purchase event. A cancelled, deferred or failed purchase is reported to both services with the product identifier and, on failure, the store's error code.
2.5 Data your device reveals simply by connecting
Every network request the App makes reveals your device's IP address and its user-agent string to whoever receives it. This is how the internet works; it is not something the App adds or can remove. From an IP address, a recipient can generally infer approximate location — typically country, region or city, not a street address. The recipients are listed in section 4.
Your IP address is not masked before it reaches the analytics services, and it is not stripped there at our request. While analytics is switched on, events go to Firebase and to PostHog over a connection that carries your IP address, and each service can derive an approximate location from it. The App does not ask either service to skip that step: the relevant PostHog setting is left at the SDK's default, which permits IP-based location enrichment. Whether the derived location is then retained, and how coarse it is, is controlled in each service's own console rather than by the App.
Two further requests are worth naming explicitly:
- Premium sounds are downloaded on demand from a Cloudflare R2 bucket. The request is a plain file download with no identifier attached, but the file name reveals which sound you chose, and the request reveals your IP and the time.
- Over-the-air updates. On each cold start the App asks Expo's update service whether a new JavaScript bundle is available. That request carries an installation identifier (
EAS-Client-ID) generated by the update library, your IP address and user agent, and technical fields used to match an update to your build: platform, protocol and API version, runtime version, and build environment. If the App crashed fatally the last time you used it, the text of that error — truncated to 1,024 characters — is sent with this request too, in a header the update library adds so that a broken update can be rolled back. That header is added by Expo's update library rather than by our code; the list above is what the library sends on iOS.
2.6 What the App does not collect
None of the following happens in the App:
- No accounts. No registration, no login, no password, no OAuth, no server of our own. The "Log Out" button in Settings does not log out of anything — see section 9.
- No name, email address, phone number, or postal address. The App never asks for them and has no field to enter them.
- No location APIs. The App does not request or use location permission and contains no location code. (See 2.5 for what an IP address alone reveals — that is a different thing, and it does happen.)
- No advertising SDKs, no ad networks, no IDFA, no App Tracking Transparency prompt.
- No microphone, camera, contacts, photos, or calendar access.
- No push notifications. All notifications are scheduled locally on your device; the App does not register for a push token and there is no push server. See section 6.
- No free text. Goal titles, custom timer names and morning journal notes never appear in any event.
- No Apple Health value leaves the device, and neither does anything computed from one. See section 7.2 for the small amount of Health-related metadata that is sent instead, and for one residual case on installations upgraded from an older version.
- We do not sell your data, and there is no data broker in the chain.
3. How We Use Information, and Our Legal Basis
| What | Why we use it | Legal basis (GDPR Art. 6) |
|---|---|---|
| Data stored on your device (2.1) | To run the timer, show your history, statistics, streaks and reports, and schedule reminders | Processed only on your device and under your control; we have no access to it and receive no copy. Art. 6(1)(b) — performance of the contract to provide the App's features. |
| Usage events and screen views (2.2) | To understand which features are used and where people get stuck, so we can decide what to build and fix | Consent (Art. 6(1)(a)), expressed through the Usage Analytics switch in Settings → Privacy & Safety. The switch is on by default, so consent is presumed until you say otherwise; you can withdraw it at any moment, in one tap, without giving a reason, and withdrawal is as easy as leaving it on. Withdrawal is not retroactive — it stops collection from that moment. |
| Crash reports and error diagnostics (2.3) | To find and fix crashes and bugs | Legitimate interests (Art. 6(1)(f)): keeping the App working. The crash report and the bare error are not covered by the analytics switch. The breadcrumb trail in front of a crash, the attributes attached to a handled error, and the copy of handled errors sent to PostHog are — those describe what you were doing rather than what failed, and they follow your consent above. You have the right to object to the part that remains — see the top of section 9. |
| Purchase and subscription data (2.4) | To unlock premium features you paid for, restore purchases, and measure whether the paywall works | Performance of a contract (Art. 6(1)(b)) for unlocking and restoring — this part runs whatever the analytics switch says, because it is how a purchase is recognised. The purchase events sent to analytics follow your consent above and stop with the switch. |
| Apple Search Ads attribution (2.4) | To learn which ad campaign an install came from | Legitimate interests (Art. 6(1)(f)): measuring our own marketing. |
| Sound downloads and update checks (2.5) | To deliver premium sounds and ship fixes without a full app update | Performance of a contract (Art. 6(1)(b)) / legitimate interests. |
| Apple Health readings (section 7) | To compute a suggested session length, a recovery score and the sleep view, on your device | Consent (Art. 9(2)(a)), given on the HealthKit permission sheet iOS shows you. This processing happens only on your device: no Health value and nothing computed from one is sent to us or to anyone else (section 7.2), so there is no transfer of special-category data to a third party to justify. Revoke it in iOS Settings → Health at any time. |
| Health-related metadata in analytics (section 7.2) | To know how many people connect Apple Health at all | Consent (Art. 6(1)(a)) — the analytics switch, same as every other event. What is sent is the fact that you answered the permission sheet and a flag that Health is connected; neither is a measurement, and neither reveals anything about your health. |
We do not use your data for automated decision-making that produces legal or similarly significant effects. The App's session-length recommendation is a suggestion computed on your device.
4. Who Receives Data, and What They Receive
| Recipient | Why | What it receives | Where it processes data | Its privacy documentation |
|---|---|---|---|---|
| Google (Firebase Analytics) | Product analytics | All usage events and screen views from 2.2, device properties, an SDK-generated installation identifier, purchase value/currency/product id, your IP address and an approximate location Google can derive from it | Google, a US company, with global infrastructure | firebase.google.com/support/privacy |
| Google (Firebase Crashlytics) | Crash and error reporting | Crash reports, stack traces, non-fatal errors and the name of the code path each happened in, your IP address, and — only while analytics is switched on — the breadcrumb trail (the analytics event names plus the App's own markers) and the attributes attached to a handled error | As above | firebase.google.com/support/privacy |
| PostHog | Product analytics and error tracking | The same events, properties and errors as Firebase, plus SDK-generated device properties and an anonymous person profile, your IP address and an approximate location PostHog can derive from it | PostHog Cloud EU — the App is configured to send to PostHog's EU region | posthog.com/privacy |
| RevenueCat | Subscriptions and entitlements | An anonymous app user ID it generates, the public SDK key, purchase and restore transactions validated with Apple, subscription status changes, the Apple Search Ads attribution token, your IP address | RevenueCat, a US company | revenuecat.com/privacy |
| Apple | Payment, receipts, restore, App Store review prompt, HealthKit | The purchase itself, tied to your Apple ID, handled entirely by Apple. Apple Health data never leaves your device via Apple in this App. | Apple | apple.com/legal/privacy |
| Cloudflare (R2) | Hosting premium sound files | The name of the sound file you download, your IP address and user agent, the time | Cloudflare, a US company with a global network | cloudflare.com/privacypolicy |
| Expo (EAS Update) | Over-the-air JavaScript updates | An installation identifier (EAS-Client-ID), your IP address and user agent, update-matching metadata (platform, protocol and API version, runtime version, build environment), and — if the App crashed fatally on its previous run — the truncated text of that error |
Expo, a US company. If an update is available, the App fetches its files from a content delivery network whose address arrives in the update response; that host is chosen by Expo's update service, not set in our code. | expo.dev/privacy |
What the analytics switch changes in this table. With Usage Analytics off (section 2.2), Firebase Analytics and PostHog receive nothing — not a reduced set of events, nothing at all. RevenueCat, Apple, Cloudflare and Expo are unaffected: they receive what their rows say whenever the corresponding thing happens. Crashlytics is affected in part: it keeps receiving crashes and errors, and stops receiving the two items its row marks as conditional — the breadcrumb trail and the attributes of a handled error.
Protection at the recipients. Each recipient listed above is bound by its published data-processing terms to provide protection of your data equivalent to that described in this policy and required by the App Store Review Guidelines. We do not use a processor that does not. Each acts as our processor, or as an independent controller under its own terms, for the data in its row; their privacy documents are linked in the table rather than available only on request. We do not sell data to any of them, and none of them is an advertising network or a data broker.
5. Storage, Security and Retention
5.1 Where the data lives
On-device data is stored in the App's private container using the operating system's standard app storage (a local key-value store plus files in the App's Documents and Caches folders). It is readable only by the App and by anything with access to your unlocked device.
5.2 Security
The App does not apply its own encryption to the data it stores. Its own code does not use the iOS Keychain or a secure enclave (what the third-party SDKs do internally is governed by their own documentation). Your data is protected by the device encryption and file protection that iOS applies to every app's container — that is Apple's protection, not something the App adds. Network requests use HTTPS.
5.3 Backups
The App's key-value store — sessions, settings, goals, achievements, and the copies of your Apple Health readings — is marked as excluded from device backup, so it is not copied into an iCloud or computer backup. Files in the App's Documents folder are not marked as excluded: this covers downloaded premium sound files and the analytics SDK's small local file containing its anonymous identifier and its queue of not-yet-sent events. Those may therefore be included in your device backup, which is managed by Apple under Apple's terms.
5.4 How long data is kept
On your device: indefinitely, until you delete it or uninstall the App. There is no time-based deletion. Two limits exist: session history is capped at the most recent 1,000 sessions, and the Health history arrays keep the most recent 14 daily readings each.
At the third parties in section 4. We keep no separate copy of any of it — we have no server and no database — so these periods are the ones that matter. Some are fixed by the provider and some are a setting we choose in that provider's console; we say which is which rather than guessing:
| Recipient | Retention |
|---|---|
| Firebase Crashlytics (Google) | Fixed by Google: crash stack traces, minidump data and the associated Crashlytics/Firebase installation identifiers are kept for 90 days, after which Google begins removing them from live and backup systems. |
| Firebase Analytics (Google) | A setting on the linked Google Analytics property, not something the App's code controls. Google offers 2 months or 14 months for event and user data on a standard property. Which of the two is set is configured in the Google Analytics console; ask us and we will tell you the value currently in force. |
| PostHog Cloud EU | A setting on our PostHog project, again configured in PostHog's console rather than in the App. Ask us and we will tell you the value currently in force. |
| RevenueCat | RevenueCat publishes no fixed period for data it processes on behalf of an app developer. Its privacy policy states that it retains such data under its own retention policy and only as long as necessary to comply with legal obligations, resolve disputes and enforce its agreements. |
| Cloudflare and Expo | These receive request metadata (IP address, user agent, the file or update requested) as an unavoidable part of serving the request. Neither publishes a fixed retention period for that metadata for a service used the way this App uses it; it is governed by the privacy documents linked in section 4. |
| Apple | Under Apple's own retention practices and Apple's privacy policy, not ours. |
If a period above is described as a console setting and you want the current number, email the address in section 13 — that is a question we can answer precisely, unlike a request to find your individual records (see the end of section 9).
6. Notifications
All notifications the App shows — timer completion, daily reminders, streak reminders, weekly report availability — are scheduled locally on your device from data already on your device. The App does not register for a push token, has no push server, and no notification content travels over the network. You can turn each type off in the App's Settings, or turn all of them off in iOS Settings.
The fact that you tapped a notification, whether you granted notification permission, and how long you had been away when lapsed reminders resumed, are sent as analytics events (see 2.2).
7. Apple Health Data
7.1 What the App reads, and when
If you tap "Connect Apple Health" on the Health screen, iOS shows you its own permission sheet. The App requests read access to exactly three data types:
- Heart rate variability (SDNN)
- Resting heart rate
- Sleep analysis (in bed, awake, core, deep, REM, unspecified)
It reads the most recent HRV and resting heart-rate sample from the last 24 hours, sleep from the last day, sleep stages from last night (yesterday 18:00 to today 12:00, local time), and up to 14 days of HRV and sleep history. Reads only happen when the App is in use and at most once every 30 minutes; there is no background delivery of Health data.
The App never writes anything to Apple Health. The permission request asks for read access and an explicitly empty set of write types, and the App contains no Health-writing code at all. You may still see a "write" purpose string in iOS — the HealthKit framework requires that text to be present in any app that links it, and Apple's build validation rejects the app without it. It does not mean the App writes.
Onboarding does not request Health access; only the button on the Health screen does. The App is fully usable without Apple Health. Without it, the session-length suggestion falls back to a time-of-day model. The recovery score is computed from whatever inputs exist: with no Apple Health data and no in-app sleep-timer session it reads zero, but if you have used the App's own sleep timer, the score is computed from that instead.
A technical caveat worth knowing: for privacy reasons, HealthKit does not tell an app whether read access was denied. When the App shows Health as "connected", that means you answered the permission sheet — not necessarily that you granted access.
7.2 Do your Health data leave the device? — Direct answer
No Apple Health value leaves the device, and, with a single exception this section names in full at the end, neither does anything computed from one. No HRV number, no resting heart rate, no hours slept, no sleep-stage minutes, no sleep score, no recovery score, and no bucket, band or rounded version of any of them is included in any analytics event, crash report, weekly report, CSV export, widget, or network request. We checked every analytics call in the App, the weekly-report generator, the CSV export, the widget bridge and every network destination to confirm this, and the App's test suite contains a check that fails the build if a new analytics call names a Health value or anything computed from one. That check reads the source code, so it cannot see a value that reaches an event through an ordinary variable; the one case where that happens today is described at the end of this section, because we would rather write it down than leave it for you to find.
Session lengths the App computes for you. The App can work out how
long your next session should be. When Apple Health is connected, that number is
computed partly from your heart-rate variability, your resting heart rate and your
sleep — so the number itself is Health-derived, even though it looks like a plain
timer duration. Every event about such a session therefore
omits the length: what is sent is a label saying the length was
computed rather than chosen (adaptive as opposed to
preset), the mode, the outcome, and — for an interrupted session — the
percentage of it you completed. The absolute seconds are dropped from the event and
from the crash-report breadcrumb alike. The "recommendation applied" event now
carries no parameters at all.
That same adaptive label is used when the App computes a length
without Health data, from your own session history or the time of
day. That is deliberate: if only the Health branch dropped the number, the mere
presence of a duration in an event would reveal that you have no Health data, and
the disclosure would simply move from the value to its absence.
What is still sent, and it is all metadata rather than measurement:
- that you answered the Health permission sheet, and whether it came back granted or denied;
- a device property recording that Apple Health is connected;
- the
adaptive/presetlabel described above.
All three follow the analytics switch in section 2.2 and stop entirely when you turn it off.
One residual case, on installations upgraded from an older version. In versions before this one, choosing the "AI" timer mode also wrote the two lengths it had just computed — the focus length and the break length that follows it — into your saved timer settings. The current version no longer writes them there, but values already saved on your device are not erased, and they cannot be told apart from lengths you set by hand.
Where this surfaces: when a focus session ends, the App sets up the next break for you, and when a break ends it sets up the next focus session. If you start that next session, the saved length travels with the "session started" event as an ordinary preset length — the break length after a focus session, the focus length after a break. Nothing else in the App reads those two saved values, and the end of a break is not reported at all.
How it ends: both values are replaced by fixed presets the moment you pick any built-in mode other than AI (Pomodoro, Long Focus, Short Sprint or Flow), "Log Out" in Settings resets them to the App's defaults, and uninstalling clears them. We would rather name this than let the paragraphs above be read more widely than they are true.
7.3 Health data and third parties
No Apple Health data, and nothing computed from it, is sent to any third party by the current version of the App — with the single exception named at the end of 7.2, which affects only installations upgraded from an older version and stops as soon as a built-in mode is chosen. Not to Firebase Analytics, not to PostHog, not to Crashlytics, not to RevenueCat, not to an advertiser, not to anyone. There is nothing here to sell and nothing here to target you with.
The three metadata items listed at the end of 7.2 — that you answered the permission sheet, that Health is connected, and that a length was computed rather than chosen — go to the same two analytics services as everything else in 2.2, are covered by the analytics switch, and are attached inside PostHog to the anonymous person profile for your installation described in 2.2. That profile is not linked to your identity and is not used to target you.
7.4 Deleting Health data
Revoking Health access in iOS Settings → Health → Data Access & Devices stops further reads, but it does not delete the readings the App already copied to your device. Neither does "Log Out" in the App's Settings. Uninstalling the App deletes them. See section 9.
There is a consequence worth being explicit about. Because HealthKit does not tell an app that access was revoked (see 7.1), the App continues to treat Health as connected after you revoke it, and it still holds the readings it copied earlier. It keeps using them on the device — for the recovery score and the suggested session length — until they age out of the 14-day history or you uninstall. Nothing computed from them is sent anywhere (see 7.2); if you would rather the App did not hold them at all, uninstalling is what clears them.
8. Children and Teenagers
The App is not directed to children under 16, and we do not knowingly collect data from them. The App has no age gate and no way to verify anyone's age.
Because the App sends usage analytics, it needs a lawful basis that a young child cannot provide. If you are below the age of digital consent in your country — between 13 and 16 in the EEA depending on the country, 13 in the UK — you should use the App only with the agreement of your parent or guardian.
The App's App Store age rating reflects content suitability, which is a separate question from data-protection consent ages. A parent who wants no analytics collected from a device can turn the switch in Settings → Privacy & Safety off; from that moment nothing is sent. If you believe a child has used the App and you want data already collected removed, contact us — but please read section 9 first, because there are real limits to what we can find.
9. Your Rights and How to Use Them
Withdrawing consent, and your right to object. The analytics described in section 2.2 rest on your consent, and you can withdraw it yourself, immediately, without contacting anyone: Settings → Privacy & Safety → Usage Analytics. Turning it off takes effect at once, needs no reason, and is remembered. Withdrawal is not retroactive: it stops collection from that moment and does not reach events already sent — see "the honest limit" below for why we usually cannot delete those.
Two things the switch does not cover, because we process them on the basis of our legitimate interests rather than your consent: the crash and error reports themselves (2.3 — the stack trace, the error and the code path it happened in; the trail of what you were doing before the crash is covered and stops with the switch), and Apple Search Ads attribution (2.4). You have the right to object to those at any time, on grounds relating to your particular situation, and you never have to give a reason for objecting to processing for direct marketing. This right is stated separately here because the law requires it to be brought to your attention that way. To object, email [email protected]. An objection is recorded and honoured for everything we can act on, and we will tell you plainly what we cannot do.
Under the GDPR (and equivalent UK law) you have the right to access your data, to have it corrected or erased, to restrict or object to processing, to data portability, and to withdraw consent where processing is based on consent. Exercising a right is free and we will answer within one month; if a request is complex we may extend that by two further months and will tell you why.
How to make a request: email [email protected] with a description of what you want.
What you can do yourself, right now:
| Goal | How |
|---|---|
| See your data | It is all visible in the App: history, statistics, goals, settings, weekly report. |
| Export your sessions | Premium users can export session history as a CSV from the Stats screen. Note the export contains six columns only — id, duration, completion time, mode, quality rating and distraction types. It does not include your morning notes, sleep quality, goals, achievements, settings, or any Apple Health data. |
| Delete a single goal or timer preset | Delete it on its own screen. |
| Delete your session history | "Clear history" on the History screen. This removes all focus and sleep sessions, ratings, journal notes and distraction logs. |
| Delete downloaded sounds | "Clear sound cache" in Settings. |
| Delete everything on the device | Uninstall the App. |
| Stop analytics being sent | Turn off Settings → Privacy & Safety → Usage Analytics. Immediate, remembered, and no email needed. Firebase Analytics and PostHog then receive nothing at all. |
| Stop everything being sent, crash reports included | Uninstall the App. The analytics switch stops the breadcrumb trail and the error attributes, but not the crash and error reports themselves (2.3), the purchase service (2.4) or the network facts in 2.5. |
| Stop anything about Apple Health being sent | Nothing computed from your Health data is sent, apart from the residual case on upgraded installations described at the end of 7.2 — picking any built-in timer mode other than AI clears that. The remaining Health-related items (that you answered the permission prompt, that Health is connected) stop with the analytics switch. If you would rather the App never read Health, do not connect it, or revoke access in iOS Settings → Health. |
What "Log Out" actually clears. "Log Out" in Settings does not clear all local data. It resets your settings, clears your session history, and sends you back to onboarding. It leaves behind: achievements and streaks, goals, custom timer presets, all copied Apple Health readings, sleep state, the cached weekly report, subscription state, timer state, downloaded sound files, the analytics SDK's local file, and four settings fields — install date, language, whether you granted the notification permission, and the sleep-onboarding flag. (A fifth field, the main onboarding flag, survives the reset itself and is then cleared immediately, which is why you land back on onboarding.) There is no account to log out of. Uninstalling the App is the only way to remove everything from the device.
The honest limit on analytics deletion. There is no account and no identifier we can match to a person. Your events at Firebase and PostHog are attached to an anonymous per-installation identifier that we cannot see and neither can you. In practice this means we usually cannot locate or delete your specific analytics records if you ask, and we will tell you so rather than pretend otherwise. What we can do: stop future collection at once (the switch in Settings, or uninstalling), honour an objection going forward, and delete anything we can actually identify. Where we cannot identify you from the data we hold, Articles 15 to 20 of the GDPR do not apply unless you give us additional information that enables your identification (Article 11(2)). We will not attempt to single you out inside an anonymous dataset in order to answer a request — doing that would create exactly the link this App is built to avoid.
Complaints. If you are in the EEA or the UK, you can complain to your national data protection authority. The list of EEA authorities is published by the European Data Protection Board at edpb.europa.eu; in the UK it is the Information Commissioner's Office at ico.org.uk. You can also complain to us first — we would prefer that, but you are not required to.
10. International Data Transfers
PostHog receives the App's analytics in its EU region, so the events are stored and processed inside the European Economic Area. PostHog itself is a US-incorporated company, so access from outside the EEA for support and operations is possible under its own terms. Google (Firebase Analytics and Crashlytics), RevenueCat, Cloudflare, Expo and Apple are US-based companies operating global infrastructure, so the data described in section 4 may be processed outside the EEA, including in the United States.
For those transfers we rely on the European Commission's Standard Contractual Clauses (Art. 46(2)(c) GDPR), which each provider incorporates into the terms it publishes:
- Google — firebase.google.com/terms/data-processing-terms
- PostHog — posthog.com/dpa
- RevenueCat — revenuecat.com/dpa
- Cloudflare — cloudflare.com/cloudflare-customer-dpa
- Expo — expo.dev/terms (its terms of service incorporate the Clauses directly)
Where a provider is additionally self-certified under the EU–US Data Privacy Framework, that adequacy decision covers the transfer as well; each provider's own privacy document, linked in section 4, states whether it is certified. Copies of the Clauses are published at the addresses above; you can also ask us and we will send you the link for a specific provider. Apple's handling of your purchase is governed by Apple's own privacy policy and is not a transfer we arrange.
11. California Privacy Rights (CCPA / CPRA)
If you are a California resident, the categories of personal information the App collects are: identifiers (SDK-generated device and installation identifiers, IP address), commercial information (purchase history: product, price, currency, subscription tier), internet or other electronic network activity (in-app usage events, screens viewed, crash and error diagnostics), and approximate geolocation derived by the analytics services from your IP address.
The App does not collect sensitive personal information as the CPRA defines it. It collects no health data and no health inference: no Apple Health value and nothing computed from one is sent anywhere, other than the residual saved timer length described at the end of section 7.2, which is a timer duration rather than a health measurement — no precise geolocation, no account credentials, no government identifier, no racial, religious, biometric or genetic data, and no contents of your communications.
We collect the categories above for the business purposes in section 3: providing the App, unlocking purchases, fixing crashes, and product analytics. Most of it stops entirely when you turn off Usage Analytics in Settings → Privacy & Safety.
We do not sell your personal information, and we do not share it for cross-context behavioral advertising. The App has no advertising SDK. It does receive Apple Search Ads attribution from Apple, which tells us which ad campaign an install came from; we do not use it to build an advertising profile of you.
You have the right to know, to delete, to correct, to opt out of sale or sharing, to limit the use of sensitive personal information, and not to be discriminated against for exercising these rights. We do not sell or share, and there is no sensitive personal information to limit; the practical control is the analytics switch, which is available to everyone and costs you no feature of the App. Use the same contact address in section 13 for the rest. Please read the limit described at the end of section 9 — it applies to California requests too.
12. Changes to This Privacy Policy
We will update this policy when the App's behaviour changes. The "Last Updated" date at the top always reflects the current version. If a change materially expands what we collect, we will say so plainly rather than only bumping the date. This policy and the internal record that backs each of its factual claims are kept in the same repository as the App's source code and are updated together.
13. Contact Us
Data controller: Dmitry Afanasyev, an individual developer. There is no company.
Email: [email protected] — for questions, requests, corrections to this document, and every right described in section 9.
Postal address. None is published here. If you need one for a formal request or for a complaint to a supervisory authority, ask at the email address above.
Data protection officer. We have not appointed one, and are not required to under Article 37 of the GDPR. Data-protection enquiries go to the address above.
If you think a statement in this policy is wrong, please tell us. This document is meant to be checkable against what the App actually does.
This privacy policy is effective as of September 5, 2026.