Field notes / threat modelling
Protected nothing
One guardrail stood between a food-diary repository and going public. Someone traced it through the code a day later and found the field it named had never been in the repository. What did need guarding was in a file nobody was arguing about.
A rule sounded exactly right, protected exactly nothing, and stood as the one thing blocking real work, until someone traced it back to what the code actually does.
This is a proof-of-concept built by one technical person working alongside an NHS dietetic team, not an official NHS product, and no patient data lives anywhere in it.
The rule was simple. Before the food diary's repository could go public, it needed a guardrail against identifiable data leaking through the diary's own free-text fields, chiefly a description a client might type next to a reference photo. Someone could type their own name into it without thinking, to help remember whose entry it was. That risk was real, agreed on at the time in the project's own words as "hard to guard... loose enough to say go public," and it sat there as the one condition standing between the repository and a public GitHub Pages migration everything else was ready for.
The condition held for a day. Then, traced through the actual code rather than argued about again, it didn't survive the first look.
never in the repoWhere the description actually goes
The description a client types is captured in the app, stored as a note on a log entry in IndexedDB on the device, and exported into a spreadsheet the dietitian handles. It is never committed, never pushed, never served. The repository's visibility has no effect on it whatsoever, because it was never in the repository to begin with. A guardrail on that field would have protected data that going public put at no risk at all.
A second, independent reason cut just as deep. The app ships with no build step at all, just straight unminified JavaScript, so its entire source has been downloaded verbatim by every single visitor to the live site since the day it launched. Repo visibility was never protecting the application code either, because the browser was already handing that code to anyone who asked. The "code stays private" preference behind two earlier hosting rejections had, for the part of the project a visitor could reach, never once been true.
~40 files, 1 sensitive stringThe place nobody checked
If the free-text field was never the risk, going public should have been safe from day one. It
wasn't, quite, and the reason was somewhere else entirely: roughly forty tracked files sitting
outside the application folder, never served to a visitor and shielded from view by nothing but the
repository itself being private. A Namecheap migration plan and the spec beside it,
DEPLOY.md, NOTES.md, DECISIONS.md, and a stray
.cpanel.yml. Grepping through all of it for anything infrastructure-shaped turned up
exactly one genuinely sensitive string: a hosting-account username, and not even this project's own
account. It belonged to someone else's.
The thing everyone had been scared of couldn't actually happen. The thing worth being scared of had been sitting in a folder nobody had opened, the whole time the guardrail argument was running.
two repos, not oneA fix that doesn't depend on remembering
The fix that shipped doesn't ask anyone to remember anything. Rather than scrub the sensitive files
out of a single shared repository and trust every future session to keep scrubbing, the project
split in two: one private repository holding everything, full history intact, and one public
repository synced from it that holds only the application directory's own contents. Nothing outside
app/ can leak, because nothing outside app/ is ever in the public repo to
begin with.
Purging the sensitive files from one shared repository's history was considered and turned down on
purpose. NOTES.md gets written every session, which means every future session is a
fresh chance to type an identifier back into a file that's now public, and a miss like that is
silent and unrecoverable the moment the repository is cloned. The split doesn't have that failure
mode. There's nothing to miss, because the sensitive files are never in the repo that goes public in
the first place.
One faster fix was on the table too, and turned down for a completely different kind of reason. GitHub offers private-repo Pages hosting on its paid tier, for around four dollars a month, which would have made the whole question go away without touching a single file. Food diary's own author turned it down outright, on the spot, with two words: "not pro." No technical argument followed it, because none was needed. It was a spending decision, not an engineering one, and the project didn't pretend otherwise.
not a hosting decisionWhat the guardrail actually protects now
The free-text field is still a real concern. It existed before this repository was ever considered for public release, and it will keep existing after, because it's a property of what the app lets someone type, not of who can see the code. It just isn't a hosting decision, and treating it as one is the mistake this piece is about. It has its own design question to answer, on its own schedule, and the fix for it won't be a line in a hosting migration plan.
The pattern generalises past one repository. The project specified a control against a threat that sounded exactly right and had never been traced to the actual place the data flows through. It still held up real work, however briefly. And the thing worth guarding against the whole time was sitting in plain sight, in a directory nobody had thought to check, because the argument had already used up everyone's attention on the door that was never open.