Stories · Season 1 — Meridian · Episode 02
The First Login
In which Ana deletes her proudest two hundred lines, and four thousand users move house without noticing.

The story
The post-mortem ended with a sentence Ana had been rehearsing for a week: “We are not an identity company, and we’ve been pretending to be one for four years.”
The rebuild had one non-negotiable constraint, delivered by the operations lead with feeling: no password resets. Four thousand staff accounts across the clinics, most belonging to people whose relationship with IT was already strained. A forced reset would burn a month of goodwill they no longer had.
Ana’s old system stored SHA-256 hashes with a per-user salt — not a scandal in 2019, not defensible now. Her fear was that adopting a real identity core meant either resetting everyone or writing a fragile bridge that kept two password tables alive indefinitely. She budgeted three weeks for the login migration alone.
It took four days. Sentinel’s import path accepts foreign hash algorithms as first-class citizens: she registered her legacy scheme, imported the user rows hashes-and-all, and let each user’s next successful login verify against the old algorithm and transparently re-hash into argon2id. Every login upgraded one account; a month later, the old algorithm’s column was a fossil record.
The cutover itself happened on a Sunday morning. Reed Callahan, Lakeside’s
receptionist and the closest thing Meridian had to a canary, logged in on
Monday, booked eleven appointments, and filed no ticket. That was the whole
launch. The only person who noticed anything was Ana, watching
login.succeeded events stream past with a mug of coffee and the specific
happiness of someone whose code is no longer load-bearing.
Why this is hard the traditional way
Everyone knows you shouldn’t build your own auth. The industry’s answer — “just use a hosted identity provider” — quietly changes the deal: your users move into someone else’s database, your login page becomes someone else’s domain, your password hashes may not be exportable when you leave, and every authentication is a network hop with someone else’s availability attached. For a healthcare platform, “our patients’ clinicians authenticate against a third party’s multi-tenant cloud” is a sentence with compliance homework attached.
The other road — assembling auth from framework primitives — is how Ana got here. The pieces exist, but the system doesn’t: password hashing is a NuGet package, but hash migration, token rotation, reuse detection, uniform errors, lockout windows and session revocation are a hundred decisions that all have a wrong answer, and hand-rolled stacks reliably pick a few.
How Sentinel changes the ending
Sentinel is a library, not a destination: AddSentinel() in Ana’s own API,
her own Postgres, her own domain on the login page. The users never left
home — they were re-housed in place. The pieces she’d feared writing were the
floor, not the ceiling:
- Foreign hashes are a migration feature, not a bridge she maintains: verify-then-rehash on next login, per algorithm, until the legacy scheme ages out.
- Sessions are token families — every refresh rotates atomically, and a rotated token presented twice detonates its whole family and pages someone. The stolen-laptop scenario she’d never handled now has a documented behavior and a test asserting it.
- The errors are pre-flattened.
invalid_credentialsfor unknown user and wrong password alike, dummy-hash timing on the miss. The enumeration leak from episode one is not a bug she fixed but a bug that can’t be reintroduced by a helpful UI copywriter. - The abuse layers from the post-mortem — the four windows, the stuffing heuristic, the CAPTCHA escalation — were configuration, not a quarter’s roadmap.
Her old login code is still in git history. She looks at it occasionally, the way you look at photos of a haircut you once chose on purpose.
What it costs you to ignore this
- A forced reset is a self-inflicted incident. Help-desk queues, weak replacement passwords on sticky notes, and a workforce primed to distrust the next security email.
- Two password tables never converge on their own. The “temporary” bridge becomes the permanent system with double the attack surface.
- Hosted identity is a dependency you can’t page. When the provider has a bad day, your clinics have a bad day, and your status page just points at theirs.
- Every month on the old stack re-runs episode one’s dice. The stuffing botnets did not stop scanning while you deliberated.