Transparency report
Last updated September 18, 2026
This is the first one. It covers Peachy from launch to 16 September 2026, with changes since that date recorded where they change the answer to a question this report exists to answer. The format is the one we intend to keep: what we hold, what we could be made to hand over, what we were asked for, and what changed since last time.
Every claim below about what our code does was re-read against that code on 18 September 2026, and where something is half-built the half that is missing is named beside the half that is not. Two things on this page are of a different kind and cannot be checked that way — the count of government requests and the warrant canary — and each says so where it appears. The canary carries its own date for that reason: the date above is a re-reading of code, the canary’s is a person’s signature, and the two move for different reasons and by different hands. If you are here to serve legal process, the page you want is Law Enforcement Guidelines.
What we hold about a person
Almost all of it is readable by us. The exceptions are named as exceptions, because the point of this list is that you can tell the two apart at a glance.
- Your phone number. Readable. Kept until you delete your account.
- Your profile — name, @handle, photo, and an email address if you gave one. Readable. Kept until you delete your account.
- Contacts you synced. Readable, and this is the largest readable thing we hold about anybody. The phone number is stored as a number, in the clear — not scrambled or hashed into something we cannot read back. The private name you saved is stored only where that number already belongs to a Peachy account; where it belongs to nobody here, we keep the number and no name. Most of the numbers in an address book are of that second kind — people who are not on Peachy and have agreed to nothing with us — which is why this is the part of your account we would most like to be holding less of. Hashing the numbers would not change that: there are few enough phone numbers that anyone can try them all against a hash. What would change it is private contact discovery, which we have not built.
- Private messages — direct messages and private group chats. We hold a ciphertext and no key. Not readable by us. The metadata around them is (see below).
- Messages that could not seal, and messages in public rooms, the commons and your thread with Peachy itself. Readable, in plaintext, by design. Kept until the author deletes them or the account goes.
- Photos, videos and files. One sent inside a sealed conversation is encrypted on the sending device with its own key and we store bytes we cannot open. One on a readable surface — a Slices post, the commons, a public or organisation room, a thread with the assistant — is readable.
- Places you share. Readable, everywhere, including inside a sealed conversation — a place is a database row rather than a file, and it is not encrypted. It is kept at the precision it was picked, which can be street level, until the message carrying it is deleted. The rough position your device sends along with a place search is different: it is used to answer the search and written to no table.
- Slices posts, comments and reactions. Readable.
- Your chats with Peachy itself. Readable, in plaintext, both halves.
- Triage decisions — one line per notification routed, naming the sender, an excerpt of what they wrote and the verdict. Readable, and swept at 30 days: a decision nobody rated is deleted outright, and one somebody rated keeps the row and loses the words, because a correction is worth keeping and a copy of someone else’s message is not. This row said “indefinite — no sweep exists” until that sweep was written, and “rolling” before that, when nothing of the kind existed.
- A record of every assistant run — what was asked, what it did step by step, how it came out. Readable, swept at 30 days.
- Usage counts — which screens were opened, not what was on them. Swept at 180 days, and detached from you the moment you delete your account.
- Push tokens, one per device, until that device signs out.
- Sign-in sessions and registered devices — the platform, the browser’s user-agent string where there is one, and when the session was last used. A session idle for 90 days expires. That last-used stamp is deliberately recorded to the day and not the minute: it used to be written at full resolution on every request, which made this table a minute-by-minute record of when each of a person’s devices was in use.
- Sign-in codes, deleted a day after they expire. Until that sweep was written this table was a standing list of every phone number that had ever asked for a code, including people who never completed sign-up.
- Server logs, for 14 days, in a separate database that holds no product data.
- Meet identity-verification artefacts, for people who use Meet.
What we do not hold: passwords, because there are none; payment details, because there is nothing to pay for; advertising identifiers; third-party analytics. That last one is worth saying precisely rather than letting it do work it has not earned: no analytics company receives anything about you, and the usage counts we keep are our own, kept by us, and listed above with everything else.
We keep no IP addresses
This one is worth stating on its own because it is unusual and because it is checkable. We do not log the IP address a request came from anywhere — not in the application, not in the request log, not against an account or a session. The four places in our code that read a caller’s address feed an in-memory rate-limit counter and nothing else, and no column anywhere in our schema holds one. The log pipeline additionally masks anything IP-shaped before a line is stored, so a value that reached it by accident would not survive the write. When that was checked across the whole retained log corpus on 18 September 2026 — 209,865 rows, every message and every distinct field name — there were no IP-shaped values in it at all. The masking rule matches nothing today, which is the point of having it: the claim stays true because it is enforced at the door rather than re-verified by hand.
Two caveats on that, since a claim this strong should carry its own limits. The masking pattern matches IPv4 and not IPv6, deliberately — a pattern loose enough for IPv6 also matches clock times, and a log pipeline that mangles timestamps gets turned off. And the log database does not delete account identifiers, it replaces them with a one-way fingerprint: that is a pseudonym rather than an erasure, and somebody holding both databases could hash a known identifier and find its lines. Both of those are about the logs, not about addresses; no address reaches either database in the first place.
The consequence is worth spelling out, because it is the part that matters to someone reading this page: an order asking us which addresses an account connected from, or which account connected from an address, cannot be answered. We do not have it to hand over, and we could not reconstruct it.
What we cannot read, and what we learn anyway
Since 17 September 2026, every private conversation — a direct message and a private group chat alike — is end-to-end encrypted by default, on all four apps, with no setting to find. The protocol is MLS (RFC 9420). The keys are on the devices in the conversation. We hold a ciphertext and never hold a key, so the words of those messages are not producible by us: not to a court, not to ourselves.
That is a claim about content and about nothing else. We run the Delivery Service those conversations are carried over, and the standard is explicit about what that lets an operator see (RFC 9750 §8.1). In our case: that a device submitted an encrypted payload to a given group at a given time, the size of every payload, how often a group’s membership changes, which devices published keys and which of those keys were consumed by whom, and which device a group invitation was addressed to. Server fanout, a stable group identifier and the push path together let anybody holding the whole database infer who is talking to whom. There is no sealed-sender equivalent here and there was never going to be one on this rung.
One piece of that did get smaller. Since 18 September 2026 we no longer record which device sent an encrypted message: the cryptography had never told us, and our own database column was the application layer volunteering what the protocol had withheld. The column is no longer written and the rows written before it are blanked. Be exact about the size of that change — it removes the recorded, queryable answer to “who sent this”, not the ability of someone with the whole database to infer a conversation from its shape. Group-management messages keep their sender on purpose, because they travel in a form that carries it in the clear regardless.
Messages written before 17 September 2026
Sealing is not retroactive, and the honest number belongs here rather than in a footnote. As of 18 September 2026 our database holds 918 private message rows written before sealing was switched on, in plaintext, readable by us and producible under an order. Every one of them predates the encryption and none of them can be sealed after the fact — the keys that would have been used never existed. Making them deletable is work in progress at the time of writing; until it lands, deleting the message from the app is what removes it.
Where content goes, and to whom
- Tinfoil, and only Tinfoil, for every AI feature: parts of readable message content, to run the For-you lens, search, notification triage and the assistant. A sealed conversation’s words are not among it, and not by a rule anyone has to remember — every query that builds one of those prompts excludes sealed rows in SQL. Since 17 September 2026 every model call Peachy makes goes to a hardware-attested enclave running open-weight models. Before the first byte our server verifies the enclave’s measurement against the release Tinfoil published to a public transparency log, pins the TLS key that attestation binds, and re-verifies every hour. A failed verification closes the call with an error rather than sending the content somewhere else: there is no second provider to fall back to, by design, and no code path to one. You can run the same check yourself at pchy.app/verify.
- Twilio: your phone number, to send a sign-in code.
- Apple and Google: push notification payloads. See below.
- Google Maps Platform: a place you type, or the rough coordinates that go with a place search, to turn into a real address. It receives the query and the location, not who you are.
- Google Calendar, and only if you connect it.
- Render: hosts the servers and the database.
- Cloudflare R2: media.
We claim that list is exhaustive, which is only worth claiming if it is true, so re-checking it is a standing item before this report is re-dated.
Two honest limits on the enclave. First, which of our processes builds a prompt matters, because a process that concatenates your messages is a process that read them. Notification triage and tagging are assembled inside the attested enclave from message ids with no text attached. The For-you lens, the chat lens, group curation, search and the assistant’s own turns are still assembled by our API process, which reads the plaintext out of Postgres to do it. Second, on the web the verification page is JavaScript our own server delivered to your browser seconds earlier, so a server willing to lie could serve a verifier that agrees with it. “Without trusting us” is literally true on the apps, which ship their verifier in a signed binary, and is not literally true in a browser. Tinfoil say as much about in-browser verification in their own documentation.
For the period this report covers, there is one more thing to say, and it is not flattering: until 17 September 2026 there were two AI providers, Anthropic and Tinfoil, with Anthropic the default and a per-account flag deciding which one served a given account. Content that went to Anthropic in that window went under its commercial terms, which forbid training and permit retention. Anthropic was removed entirely on 17 September 2026 and its key is held by no deployed Peachy process.
What Apple and Google see
A notification carries the message text, the way Signal’s does, except where the message is end-to-end encrypted — then there are no words for us to send, and the reading device fetches and decrypts them itself.
Until recently the notification also carried the conversation identifier, in the clear, in the field the two platforms use to group notifications together. Sealing the words and then labelling the envelope with a stable conversation id is not a partial win; it is the thing sealing exists to prevent. Two devices handed the same identifier milliseconds apart are two people in a room together, and the same identifier arriving on one device every evening for a year is that person’s closest correspondent, with timestamps. That field is now a keyed hash computed over the device and the conversation together, so the same conversation produces a different value on every device it reaches and nothing can be joined across devices, across participants, or across time.
What that does not fix, said here rather than discovered later. Apple and Google still learn that a particular device was sent a notification, at a particular time, at a particular frequency; timing and volume are metadata and a hash does nothing about them. And one field still carries the raw conversation identifier: a custom key in the payload, which the apps already on people’s phones read to open the right conversation when you tap. Apple and Google can see that key. Removing it would break tap-to-open on every phone in the field, so it stays until those builds have turned over. We would rather write that down than let the paragraph above read as more than it is.
The web app is different and better here, for a reason that is nothing to our credit: a browser push payload is encrypted to the browser under a key the push service does not hold, so the same identifier travels where the service cannot read it. That is a property of the Web Push standard, not of anything we did.
What we could be compelled to produce
Everything above marked readable, in plaintext, for any account named in valid legal process: public-room and commons messages, any private message that could not seal, the plaintext messages written before sealing, your chats with Peachy itself, Slices posts, profiles, attachments on any readable surface, every shared place, your synced address book, triage records, and the metadata of every conversation including the sealed ones.
What we could not produce, since 17 September 2026: the words of a sealed private conversation. We hold the ciphertext and no key to it, so an order for those messages can be answered only with bytes. That is a limit on us rather than a policy of ours, which is the only kind worth writing in this section — a policy can be changed by the people who wrote it. Nothing else about that conversation is protected by it: who its members are, when they wrote, how often, when somebody joined or left, and the existence and size of anything they attached are all producible.
We also could not produce IP addresses or connection records, because we do not keep them, and we could not produce anything that a retention sweep has already deleted: server logs older than 14 days, the encrypted delivery envelopes of a conversation older than eight weeks, unrated triage decisions and assistant run records older than 30 days, usage counts older than 180 days, and sign-in codes a day past expiry. Those sweeps run hourly, on a schedule, and are not suspended by a request arriving.
The full procedure, including what a subpoena reaches versus what a warrant reaches, is on the Law Enforcement Guidelines page.
Requests we received
For the period covered by this report, and through the date at the top of this page, we have received nothing in any category — no subpoena, no court order, no warrant, no emergency disclosure request, no national security process, and no government content-removal request. We have produced no user data to any government, anywhere.
Be clear about what kind of statement that is. It is a person saying so, not a system reporting it: no automated test checks it and none could. Peachy is a very small operation: there is no separate legal department such a request could have been routed past, which is why one person can answer the question at all. If a count is ever non-zero we will publish the number. If we are ever legally prevented from stating a count, we will say that instead of saying zero.
User reports acted on inside the product — blocks, spam reports, abuse reports — are moderation rather than government requests and are not counted here.
Warrant canary
Signed by the operator on 18 September 2026. This date is not the verification date at the top of the page. That one says when the claims about our code were last re-read against the code; this one says when a person last affirmed the statement below. Nothing automatic can advance it.
A warrant canary is a statement the operator signs with each edition and which is meant to be removed rather than falsified; its absence from a later edition is the signal. The statement this report carries is that Peachy has received no national security letter, no FISA order and no other classified request for user data, and has not been required to install a backdoor or hand a key to any government.
It is re-affirmed with every edition, and early on any change to the AI provider, to the enclave measurement we pin, or to the list of parties named under “Where content goes” above. It is a dated fact about a person, so no build checks it and none could.
Security reports
Our vulnerability disclosure policy is at pchy.app/security and at /.well-known/security.txt. Since 17 September 2026 it has a paid half: a self-run bug bounty with four published tiers, a three-business-day acknowledgement and ten days to triage, at pchy.app/security/bounty. There is no intermediary platform; reports arrive by email and a person answers them. The programme opened after the close of this period, so it has paid nothing yet, and no vulnerability report has been received as of the date at the top of this page.
Deleting your account
Deletion is self-service, immediate, and needs no contact with us. Nine things survive it, each for a stated reason, and the list of nine is held in step with the code that does the deleting by a test rather than by anybody’s memory — that list used to say six while the real number was nine. It is written out in full on Delete your account.
One residue that list does not cover, named here because it is ours to name: a notification-triage record belongs to the person who received the notification, not to you, so deleting your account does not reach it. Where such a record holds an excerpt of something you wrote, that excerpt survives in someone else’s row until the 30-day sweep above clears it.
And one defect found and fixed on 18 September 2026, recorded here because a report that lists only what we got right is an advertisement. Deleting a message cleared its words, its attachments, any place attached to it and its ciphertext — but not one server-side routing field, never shown in any app, which named where its author was when they wrote. Every message anybody had ever deleted still carried it, readable by us and producible under an order. Its invisibility is what let it survive: a column no app can draw is a column nobody notices has stayed, which is how it outlived a privacy audit reading the delete path. Deleting now clears it, and the rows that accumulated before were emptied.
How this report is kept honest
A design document is allowed to describe what does not exist yet. A transparency report is the opposite kind of document: every sentence is a dated factual claim, and your only reason to believe any of it is that we are the sort of people who keep it true. One that has quietly gone stale is not a small error — it is the single most useful thing anybody could cite to argue that nothing else we publish can be trusted.
It has gone stale twice, on the same day, and the way it happened is why this section exists. Once it said a feature was unimplemented for a day after that feature had shipped; the file was then edited twice more for unrelated reasons and the false sentence survived both passes. “Somebody will notice while they are in there” is therefore a disproved theory rather than a plan. What replaced it: the internal source of this page carries a machine-readable stamp naming the commit and the date it was last verified against; the claims that actually rotted are bound to the repository facts that decide them by a test that runs on every build, in both directions, so the day somebody switches one of them on in production the build goes red until the document is rewritten; and there is a written list of what must be re-read before that stamp can be moved.
The corrections themselves are made above rather than footnoted, because a list that quietly improves is worth no more than one that quietly rots. In summary: the contacts row said “hashed” and nothing is hashed. The triage row said retention was “rolling” when no sweep existed, was corrected to “indefinite”, and then a sweep was written forty minutes later and it was wrong in the other direction — a promise with no code behind it, then code with no promise in front of it, inside one day. The second kind is the one nobody is motivated to report, which is why it is written down. The sub-processor list above claimed to be exhaustive and was missing two entries. And the place where a person was standing survived the deletion of the message that carried it, which is the entry directly above this section.
The next one
Due 16 March 2027, or on the first government request, whichever is sooner. It will be a diff against this one. If the warrant canary is missing from it, read that as the answer.
See also the Privacy Policy, Security and Law Enforcement Guidelines.