1.Who is responsible for your data#
The hosted service at notchr.app is run by an individual trading as “Notchr”. For the account and technical data described below, we are the data controller. For the contents of your ledger, the picture is different and more favourable to you: we determine nothing about it and cannot see it, which is set out properly on the data protection page.
Contact for anything in this document, including requests about your data: [email protected].
2.How the encryption works, in plain terms#
This matters because everything else in this policy follows from it.
- When you create an account, your browser generates one random AES-256-GCM data key. That key encrypts every personal field and every photo in your ledger.
- Each passkey you register holds its own wrapped copy of that data key. The wrapping key is derived — with
HKDF-SHA-256 — from a secret the passkey itself produces (the WebAuthn
prfextension). That secret never leaves your device and is never sent to us. - So the database row for a passkey contains a copy of your data key that only that passkey can unwrap. We store the wrapped bytes and have no way to unwrap them.
- Encryption happens before anything is sent, in addition to the TLS that protects it in transit. The server refuses to store a personal field that arrives as readable text, so a bug in the app cannot leak a name into the database by accident.
- Each ciphertext is bound to the column it belongs to, so a value cannot be quietly moved from one field to another.
The unavoidable consequence: lose every passkey and the ledger is unreadable forever. We cannot reset it. That is clause 4 of the Terms, and it is the price of the rest of this page.
3.What we hold but cannot read#
Every item below is stored as ciphertext produced on your device. To us each one is an opaque string or blob of bytes.
| Where | Encrypted before it reaches us |
|---|---|
| A partner | Name, date of birth, body type, hair colour, eye colour, ethnicity, nationality, occupation, place of birth, current city, current country, and your notes about them |
| A date | Venue name, city, country, notes, highlights, and the map coordinates |
| An activity on a date | Your notes against it |
| Photos | The image bytes themselves, resized and re-encoded in your browser and then encrypted. They are kept as objects in Cloudflare R2 rather than in the database, and what is written there is the same ciphertext — see clause 7 |
| You | The name you gave your ledger, your date of birth, and the label on each passkey |
Nobody at Notchr can tell you who is in your ledger, where you went, what you wrote, or what any photo shows. Neither can anyone who obtains the database, lawfully or otherwise, without also obtaining one of your passkeys and the device it lives on.
4.What we hold and can read#
A ledger has to be sorted, numbered and counted, so its skeleton stays in plain text. This is the honest list — it is not nothing, and you should read it before you decide the encryption is total.
| Category | Readable to us |
|---|---|
| Structure of the ledger | Row identifiers and which account they belong to; when each row was created and last changed; how many partners, dates, activities and photos you have; and whether the ledger is kept by one person or shared — a setting, not a name, and the app reads it to decide which dashboard and headings to draw before a passkey has opened anything |
| A partner, minus their identity | Entry number, shag number, height in centimetres, and whether the entry is active or archived |
| A date, minus its place and prose | Start and end timestamps, whether it spanned days, its number for that partner, the star rating, the age recorded at the time, and which event type and activities were tagged |
| Your catalogues | The names of any event types and activities you create yourself, with their categories — these are stored as plain text (see the warning below) |
| Photo metadata | A randomly generated filename, the image type, the size in bytes, sort order, which photo is primary, and the random key naming its object in storage. Original filenames are discarded on upload, and the key is random too, so neither says anything about the picture |
| Account and passkeys | An account number, an account reference (three random words, shown in Settings, so you can name your account to us without an email address; it is drawn at random, says nothing about what is in the account, and cannot sign in or unlock anything — see clause 7 of the data protection page), an opaque WebAuthn handle, and per passkey: its credential identifier, public key, signature counter, authenticator model identifier, whether it is device-bound or synced, whether it is backed up, its transports, when it was added and when it was last used |
| Sessions | A random session identifier, the account it belongs to, and its creation and expiry times |
| Sign-in challenges | Short-lived random challenges used to complete a passkey ceremony, deleted once used or expired |
| Your subscription | When the account was created, which is what decides whether the trial has run out. If you have ever opened a checkout: a random billing reference we minted for you, and the subscription number, customer number, status, renewal date and end date that Stripe reports back. Not the card, and not the email address you give them |
Custom activity and event-type names are not encrypted. They are shared catalogue rows the server has to match and count, so “Dinner” or “Second date” is stored as readable text. Do not put a person's name, or anything you would not write on a Post-it, into a custom activity or event type.
Structure can still be suggestive. Timestamps, ratings and counts describe the rhythm of your life even without the names attached. We keep them because the ledger cannot work without them, and we tell you rather than imply otherwise.
5.Technical and network data#
Reaching a website means revealing an IP address; there is no way round it. When you use Notchr:
- your IP address, user agent and the requests you make are processed by the network in front of the service (see clause 7) in order to route and protect the traffic;
- the application itself keeps no access log of who fetched what. It writes diagnostic output when something fails, which can contain a failing request path and an error, and is not retained as a record of you;
- we do not build a device fingerprint, a profile, or any record of your visits over time.
6.Why we hold it, and on what legal basis#
| Purpose | Data used | Basis (UK/EU GDPR) |
|---|---|---|
| Give you an account and store your ledger | Passkey records, account row, sessions, all ledger rows (as ciphertext) | Performance of our contract with you — Art. 6(1)(b) |
| Sign you in and keep you signed in securely | Passkey public keys and counters, challenges, session cookie | Contract — Art. 6(1)(b) |
| Keep the service up, and defend it from abuse | IP address and request metadata at the network edge, error output, traffic patterns | Our legitimate interests in a service that stays available — Art. 6(1)(f) |
| Answer your questions and handle your requests | Whatever you send us by email, including your account reference if you quote it | Contract, and our legitimate interest in replying — Art. 6(1)(b), (f) |
| Take payment, and know whether the ledger is writable | The billing reference and the subscription record described in clause 4 | Contract — Art. 6(1)(b) |
| Comply with the law | Whatever a valid legal obligation requires, which cannot include readable content | Legal obligation — Art. 6(1)(c) |
We do not rely on consent for any of this, which means there is no consent for us to withdraw and no cookie banner to click. The contents of your ledger are dealt with separately on the data protection page, because the encryption changes who is responsible for what.
7.Everyone else who touches anything#
The complete list. If a company is not here, it does not receive anything from Notchr.
| Who | What they do | What they see |
|---|---|---|
| Cloudflare | The tunnel and network front door for notchr.app, and the Cloudflare R2 bucket that holds your photos | Your IP address, user agent and request metadata. Request and response bodies pass through in transit; the personal ones are already ciphertext. Your photos also come to rest there rather than merely passing through, as that same ciphertext, under random keys that describe nothing. Cloudflare has no more ability to open a photo than we do |
| Our own infrastructure | A self-managed Kubernetes cluster and PostgreSQL database in the United Kingdom that run the app and store the rows. The photo bytes are the one thing it does not hold: those live in the bucket above | Everything described in clauses 3 and 4 — the encrypted items unreadable, the rest readable |
| Google Fonts | Serves the two typefaces the interface is set in | Your browser requests the fonts directly, so Google sees your IP address and user agent. No account data, no cookie from us, and no page content |
| OpenStreetMap Foundation | Map tiles, and the geocoder that turns a place name into coordinates | See clause 8 — this is the one exception worth its own clause |
| Stripe | Sells the subscription as merchant of record: the checkout page, the card, the invoice and VAT | Only if you subscribe, and only on their own pages: the email address and card you type there, your billing country and IP address, and the random billing reference we pass along so the payment can find your account. They send us the subscription's numbers, plan, status and dates. They never see your ledger, and we never see your card. Their privacy policy covers what they hold |
| Anthropic | The AI model behind “backfill from notes” | Nothing. The feature is disabled on the hosted service because the server cannot read your notes. See the AI policy |
There is no analytics provider, no advertising network, no tag manager, no error-reporting service, no marketing platform, no chat widget, no A/B testing tool and no social media pixel. The pages load nothing from anywhere else. Subscribing takes you to Stripe's own page and back again; nothing of theirs is embedded in ours.
We would rather not send anything to Google. Self-hosting the two typefaces would remove that request altogether, and it is on the list of things to fix; until it is, this policy tells you it happens. A browser extension that blocks the request breaks nothing but the lettering.
8.The one place a plaintext detail leaves your device#
The Map page needs coordinates, and coordinates come from a geocoder. So when you open Map, your browser asks nominatim.openstreetmap.org to look up the places that have
not been looked up before, one at a time, roughly one per second.
What that means precisely:
- the request contains the venue, city and country text you typed, in the clear, because a geocoder cannot resolve ciphertext;
- it goes from your browser, not from our server, and carries no account identifier, no session cookie and nothing about the date, the partner or your notes;
- the coordinates that come back are encrypted and stored on the date, so each place is looked up once for your whole account rather than once per device;
- map tiles are then fetched from
tile.openstreetmap.org, which reveals to that service which parts of the world you are looking at; - if you never open the Map page, no place name ever leaves your device. That is your control, and it is a real one.
The OpenStreetMap Foundation is a not-for-profit and its geocoding service has its own usage and privacy policies. Notchr respects its rate limits and sends nothing beyond the place string.
9.Cookies, local storage, and the key on your device#
One cookie. It is session_id: a random identifier, set when you sign in, marked HttpOnly and
SameSite=Lax, Secure over HTTPS, valid for 30 days. It is strictly necessary to keep you signed in and carries
no information about you. There are no analytics or advertising cookies, which is why you have never seen a
banner here.
Your browser also keeps, on your device only and never transmitted:
- Local storage
- A single
themevalue, remembering whether you chose paper, velvet or “follow the system”. - IndexedDB — the vault
- A non-extractable copy of your data key, so that reloading a page does not ask for your passkey again, plus a short-lived cache of decrypted photos for display. Signing out erases the key and revokes the cached images.
Because the key is cached on the device, anyone who can use your unlocked browser profile can read your ledger without ever touching your passkey. Sign out on shared machines.
10.How long we keep things#
| What | Kept for |
|---|---|
| Your ledger rows and photos | Until you delete them or the account. Deleting a partner deletes their dates and photos with them. A photo's stored object is removed before its row is, so a failure leaves the photo intact and retryable rather than stranding bytes in the bucket |
| Account, passkeys | Until you close the account, and the account reference goes with it. Removing a passkey deletes its row and its wrapped key immediately |
| Sessions | 30 days, then expired; a sign-out removes the session at once |
| Sign-in challenges | Five minutes, then discarded whether they were used or not |
| Infrastructure snapshots | Where snapshots of the database exist for disaster recovery, they contain the same ciphertext and roll over on a short cycle, so a deletion works its way out of them as they age |
| Plan and subscription record | For as long as the account exists. Stripe keeps its own invoice records for as long as tax law requires it to |
| Email you send us | As long as needed to deal with the matter, and up to 12 months afterwards for our own records |
| Network logs at the edge | According to Cloudflare's own retention for the service in front of us — short, and measured in days |
There is an inherent backstop: once the last passkey for an account is gone, whatever remains is a pile of ciphertext that nobody, including us, can ever turn back into personal data.
11.What protects you, and what does not#
On our side:
- end-to-end encryption of every personal field and photo, as described in clause 2;
- passkeys instead of passwords, so there is no shared secret to phish, guess, reuse or spill in someone else's breach;
- every request checks that the row you are asking for belongs to your account;
- the server rejects plaintext in encrypted columns rather than trusting the client to have done its job;
- HTTPS everywhere, an application container that runs as a non-root user, and secrets kept out of the browser.
Where the protection stops, stated plainly rather than buried:
- Your device is the weak point. A shared, stolen or compromised device, a malicious browser extension, or someone standing behind you defeats all of the above.
- Browser-delivered encryption requires trust in each page load. The code that holds your key is JavaScript we serve. If our delivery were compromised or we were compelled to serve a modified page, that code could be changed. This is a genuine limitation of every in-browser end-to-end encrypted product, including this one, and it is why the code that does the encrypting is small and readable.
- We cannot promise perfect security, only that the design puts the sensitive part beyond our reach so that our own mistakes cost you less.
12.Information about other people#
Most of a ledger is information about someone else — often intimate, usually recorded without their knowledge. The design is our answer to that: by making the content unreadable to us, the number of people who can ever see it stays at one.
It does not remove your responsibility for holding it, and it means a request from someone who believes they appear in a ledger is one we are technically unable to act on: we cannot search for a name that exists only as ciphertext, and we cannot tell whether any given person appears in any account. The data protection page explains what we do when such a request arrives, and what your own position is.
13.Your rights#
You have rights over your personal data — access, correction, deletion, restriction, objection, portability, and the right to complain. Because of how this service is built, some of them we can serve completely, one of them we can only serve partially, and one of them your own browser already serves better than we could.
Rather than summarise that badly here, the data protection page takes each right in turn and says exactly what we can do. Requests go to [email protected].
A request has to say which account it concerns, and the way to say it is your account reference — the three random words at the top of Settings. Quoting them names your ledger for support, a data request, a deletion or a refund, and names nothing else. Because we hold no email address for you, whether we ever learn one is your decision alone: write from an address that says nothing about who you are and the request is no weaker for it. Quote the reference to us and to nobody else — clause 7 of the data protection page explains what it can and cannot do.
14.Where the data lives#
The application and database run on our own infrastructure in the United Kingdom. Photos are the exception: they sit in a Cloudflare R2 bucket that carries no jurisdictional restriction, so those objects may rest anywhere on Cloudflare’s global network rather than in one country. Of the third parties in clause 7, Cloudflare, Google and Stripe are US-headquartered with global networks, and the OpenStreetMap Foundation is UK-based with European infrastructure, so some processing takes place outside the UK and the EEA.
Where personal data is transferred outside the UK or the EEA, it is done under the safeguards the law provides — the UK's International Data Transfer Addendum, the EU Standard Contractual Clauses, or an applicable adequacy decision, depending on the recipient. The data actually crossing a border in these cases is network metadata and ciphertext, never readable ledger content.
15.Children#
Notchr is for adults. You must be 18 or over to hold an account, we do not knowingly process the data of anyone under 18, and an account we learn belongs to a minor is closed and deleted. If you believe a child is using the service, tell us at [email protected].
16.Changes, and how you will hear about them#
When this policy changes, the revision number and date at the top of the page change with it. A change that materially affects you — a new recipient of data, a new purpose, a new category of readable field — will be announced in the app and on this page at least 30 days before it takes effect, unless the law requires it sooner.
We have no email address for you, by design, so we cannot write to you. That is the trade: no mailing list to leak, and notices you have to read here.
17.Complaints#
Come to us first at [email protected] and we will try to put it right. You can also complain to the Information Commissioner’s Office (ICO), the UK's supervisory authority, at https://ico.org.uk/make-a-complaint/. If you are in the EU/EEA, you may complain to the supervisory authority where you live or work instead.