Our Auth Library's Last Release Was July 2022. We Noticed in June 2026.

A dead library ran our dashboard's authentication for four years without a single alert, because dependency bots only report new versions and known CVEs.
I was reviewing a teammate’s PR against our dashboard’s authentication code when I hit an import I’d never seen: imia. I got curious and opened the upstream repo. It was archived, and its last release dated back to July 2022.
imia ran session authentication for the Mergify dashboard: every login and every staff impersonation. We adopted it in June 2022, when it looked alive; its final release shipped a few weeks later. It held that job for four years while upstream sat still, and nothing in our tooling ever said a word.
Nothing warned us
Our bots watch dependencies all day, but everything they show us is one of two things: a new version to bump to, or a published vulnerability to patch. An archived project rarely produces either. There’s no release to bump to, and if a vulnerability turns up, there’s no maintainer to write the fix. Your bot never gets a patched version to offer you. The pin keeps resolving and CI stays green, so the silence reads as health.
When I asked myself how long we would have kept shipping on top of it without that lucky code review, the honest answer was months, maybe years.
The impact analysis I wrote that morning wasn’t dramatic, which is what makes this failure mode nasty. The pinned wheel still installs. Nothing breaks tomorrow. The costs are all deferred: a security issue in our auth layer would go unreported and unfixed, and imia 0.5.3 only keeps working with current Starlette because it sticks to Starlette APIs that have stayed stable so far, so a Starlette release would eventually pick the migration deadline, not us.
There’s a fair objection that a small library over stable APIs might be finished rather than abandoned, and for a string-padding helper I’d accept it. The layer that decides who is logged in doesn’t get that benefit of the doubt.
The fix I refused
The first version of our migration ticket proposed vendoring imia. It’s small (about 680 lines) and MIT-licensed, so copying it into our tree was the path of least resistance.
I killed that plan. Authentication is one of the most common building blocks in software, and the community maintains good libraries for it; owning a private copy of auth code that nobody else reads or patches felt like the worst of both worlds. Forking it publicly would have been the same commitment with extra ceremony. Vendoring can make sense for a leaf utility. For the code that decides who is logged in, I want as much shared, maintained code under it as possible.
So we listed the real options:
| Option | Why we passed |
|---|---|
| fastapi-users | Wants to own the user model and ships password machinery we’d never use (our login is GitHub OAuth only). Our Redis-backed session flow would end up as custom strategies anyway. |
| AuthX | JWT-based. Instant revocation means bolting a token blocklist back on, which is the server-side state our Redis sessions already give us. |
| Starlette-Login | 15 stars, one maintainer. That’s how we got into this situation. |
| Pin and monitor | Keeps every risk and hands the migration date to a future Starlette release. |
We picked starlette.authentication, the auth layer Starlette itself ships, plus our own adapters on top.
Which, if you squint, is exactly what imia was: thin glue over Starlette primitives. The custom code just moved down a level, onto the framework we already pin and track. It shrank to a couple hundred typed, tested lines that we own.
Swapping auth middleware without logging anyone out
A middleware-stack swap doesn’t realistically fit behind a feature flag: the middleware is either in the stack handling every request or it isn’t. Safety had to come from how we designed the change.
The decision that mattered most: keep the session storage exactly as it was. Sessions live in Redis via starsessions (same author as imia, but still maintained), and the new backend reads the same session keys imia wrote. That bought us what a feature flag or a dual-stack dispatcher would have: every session opened before the deploy stayed valid after it, and rolling back would have been an ordinary redeploy against the same sessions. Nobody got logged out, and nobody even noticed.
The swap turned out to be a simplification too. imia needed two middlewares chained together, one for authentication and one for impersonation. Starlette’s built-in AuthenticationMiddleware takes a backend, and ours resolves both in one pass: load the user from the session, then swap in the impersonated user when a staff member is driving.
Before: two imia middlewares chained
flowchart LR
A1[Request] --> B1[imia AuthenticationMiddleware]
B1 --> C1[imia ImpersonationMiddleware]
C1 --> D1[Dashboard app]
After: one Starlette middleware, our backend
flowchart LR
A2[Request] --> B2[starlette AuthenticationMiddleware]
B2 --> C2["Mergify backend<br/>session user + impersonation in one pass"]
C2 --> D2[Dashboard app]
The rest was mechanical: port the existing auth tests to the new backend, then walk through login, logout, and entering and exiting impersonation on staging. Our own PR-risk bot flagged the change as HIGH (about 1,200 lines across 17 files, touching the API layer), which felt fair for an auth swap. It merged three days after I first saw the archive banner.
Making luck less necessary
Finding this through idle curiosity in a code review is not a process. The frustrating part is that the data to catch it was sitting in public APIs: the registries have exposed the stale release dates since 2022, GitHub exposes an archived flag, and OpenSSF Scorecard even scores maintenance health from signals like these. None of that was wired into anything we actually look at.
So the same morning, I opened a second ticket: an auditor that walks our direct dependencies and pulls those signals into a ranked report. Archived or deprecated projects come first, then stale-but-alive ones. A single-maintainer project sitting on a sensitive path like auth or session handling gets extra weight.
That rule cuts both ways: starsessions, the same author’s session library we kept, sits on that watchlist. It isn’t abandoned, and this time something is watching instead of waiting for luck.
The first run flagged a handful of other dependencies that need care. We now have a ranked list instead of an accident.
What it can’t measure is the thing I actually want to know. Registries record versions and vulnerabilities, and GitHub records activity, but there’s nowhere a maintainer can say how much time they still have for a project. Every check we run (release recency, commit dates, archived flags, deprecation banners) is a proxy for one person’s available attention. imia’s author did the responsible thing by archiving the repo, loudly and unambiguously. Plenty of dying projects never get that. They go quiet, and your bots keep telling you everything is fine.
Go check yours. It takes five minutes to grep your lockfile for the libraries sitting under your login flow and open their repos. I found four years of silence under ours.


