The Note on the Lid
How I decided whether to encrypt a readable summary field before a beta, by measuring the premise I had written down a few hours earlier.
Tonight I locked a change I had logged only a few hours earlier: the one-line summary on each journal card gets encrypted on the phone, the same way the entry already is. The change itself is small. What I want to write down is the question I asked before letting the design session start, and the measurements that answered it, because they also overturned a sentence in my own notes and a number I had assumed without measuring.
A note on the lid
Picture each journal entry as a page inside a locked box. Your phone holds the key, with a copy in your own Google Drive. What is stored on the server is the box, closed.
On the lid of each box there is a sticky note. Luna writes it when you save: one warm line about the night, the kind of thing a journal card can show without opening anything. There is a second, longer note too, the one Luna reads to remember your recent days across nights, and that one is written under a rule. No names, no employers, no diagnoses, no amounts. I wrote about earning that readable field back in June, and the filter was the price of keeping it readable.
The short note never got the rule. It predates the long one and it was only ever meant for the card, and when the long note got its filter nobody carried the name rule back. So it could say "dinner with Sarah after Dad's oncologist visit" while the box next to it stays sealed. Both notes are disclosed in the Privacy Policy as readable. That is the state I found when a claims audit of my own posts made me reread what each field actually holds.
A derived field inherits the weakest reader it was ever designed for. The long note had a reader with rules. The short note had a card.
Is it necessary?
Before I let the design session start, I asked for the plain version, with the impact, and whether this was needed at all. I want that question answered before the effort goes in.
The honest answer was no, on the narrow reading. No law I know of requires it. The policy discloses the field as readable, so there is no accuracy problem to fix. The gain is real but bounded, because the conversation still passes through the server on its way to the model while you chat, and the long note stays readable on purpose.
The first recommendation on the table was the cheap version. Add the leave-out rule to the short note's prompt now, encrypt the field after the beta. One prompt change, no migration, no change to the save path two weeks before a frozen build.
I still think a disclosed weakness is a weakness I chose. Disclosed is not done. But I would have taken the stopgap if the numbers had stayed where I assumed they were.
The note I wrote a few hours earlier was wrong
My own handoff note said the server no longer reads the short summary anywhere, only the app's screens do. That sentence was load-bearing for the cheap option and for the expensive one. So before the loop I searched the code for every reader.
Two things on the server read it. Luna's memory falls back to the short note whenever an entry has no long one, and the admin dashboard fetches it to decide whether an account has saved an entry. Neither was in my notes. The dashboard turned out not to matter (it uses the field as a yes or no). The memory fallback was the real question, because dropping it changes what Luna remembers.
Then I measured instead of arguing. Every entry saved since September has a long note, so none of them needs the fallback. Four older entries do. The longest short note in the database is under three hundred characters, and the column has room for the encrypted form's extra length, so the database does not change at all.
I notice, writing this, that I had almost argued from a number I had not measured. "The fallback is live for half the corpus" was true across all time and false for everything recent. The all-time number pointed at the stopgap. The recent number pointed at the full fix. Same database, different question.
With the fallback nearly dormant and no schema change needed, the two technical reasons for the stopgap were gone. What remained was calendar risk, and that is a decision about what I value, not about what is correct. I chose the full fix, with a build date two weeks before the beta window so it soaks on my own nights first.
What the fix borrows
Nothing in the mechanism is new. The phone encrypts the short note with the key it already uses for the entry, and the screens decrypt it when they draw a card. The reflection feature already works this way: the server writes it, the phone seals it, the server stores the sealed form. The short note joins that pattern instead of inventing one.
Three ordering choices came out of the loop, and I think they generalize.
First, the server change. Luna's memory stops reading the short note before any phone starts encrypting it, because the other order would hand the model an encrypted blob for the four entries that still lean on the fallback. Whichever side can be wrong on its own without harm ships first.
Then the read side, before the write side. The screens learn to read both the readable form and the encrypted form in a release of their own, before any phone writes the new form. If I have to revert the writing, the reading still works and no card goes blank. I had first planned both halves in one release, and a review of this post caught the hole: a reverted app would have shown the encrypted text on every card. The reversibility comes from the sequence, and only from the sequence.
And the existing notes convert quietly. Each account's old lines get encrypted the next time it opens the app, with no screen and no backup prompt. When I encrypted the entries themselves in June, I built a blocking upgrade flow with a download first, because a lost key would have destroyed words the person wrote. A summary is not the person's words and can be rewritten from the page. The ceremony should match what is at stake, and here almost nothing is.
One more decision was mine rather than the design's. The onboarding screen says short summaries are stored readable. After this ships that sentence is false, so the screen gets a new version and every account reads it once more, the second time this month after a rewrite earlier in October, and the Privacy Policy's sentence changes with it. I would rather show a screen twice than leave an untrue sentence on it.
The calendar is the risk
The code risk here is small. It is the same mechanism as June and the same gate, and a smoke on my own phone before the merge. What is not small is that a two-week beta read starts in late October on a frozen build, and a save-path change in the week before it is exactly the kind of thing that clouds the read.
So the plan has a hard stop. If it is not merged by October 19, it waits until the window closes in November. The field stays readable through the beta, which is the state it has been in since April, and the policy already says so. Slipping leaves things exactly as they are today. Writing that down in advance is what lets me start the build without bargaining with myself on the Sunday.
Mental Models
A derived field inherits its weakest reader. When a system generates a second copy of something sensitive, the copy's privacy posture is set by its least demanding reader, which is usually the one it was first built for. Audit the derived fields, not just the source.
Disclosed is not done. A weakness you state honestly in a policy is still a weakness you chose. The disclosure buys accuracy, not absolution.
Measure the premise you were handed, especially your own. The sentence in my own handoff was the one I was least likely to check, and it was the one that was wrong. Numbers measured over all time and numbers measured over the recent window can point in opposite directions.
Order changes by what can be wrong alone. Ship the side that is safe on its own first, make the read side tolerant before the write side changes, and match the ceremony of a migration to what is actually at stake.