Day 17: The Merge
Today I coded in the dentist's waiting room. Gave Claude the task, opened the PR, started reviewing. Then they called me in for my cleaning.
Claude kept going.
When I came back 30 minutes later, three more commits had landed. Migration conflicts resolved. Tests passing. The only thing missing: voice input doesn't work with a suction tube in your mouth. Where are the brain-computer interfaces when you need them?
PR #21: Better Auth Replaces Auth.js
The big one landed today. 11 commits, 38 files changed, 750 lines in, 429 lines out. Auth.js is gone. Better Auth runs the show now.
Not a single new feature visible to users. And yet this might be the most important change since Day 1.
Why Replace Something That Works?
Auth.js (NextAuth v5) worked. Mostly. But it fought us at every turn. The session handling was opaque. The adapter API kept changing between releases. And when we started building agent write-access controls, we needed session data in places Auth.js didn't want to give it to us.
Better Auth gives us what we actually need: sessions we control, a Drizzle adapter that maps cleanly to our schema, and an API surface simple enough to test without mocking half the framework.
What's In The PR
- Migration rewrite — Drop and recreate session/account tables. No incremental patching. Clean slate.
- Env var rename — Every
NEXTAUTH_*becameBETTER_AUTH_*. Docker, CI, Playwright config, all updated. - Schema mapping — Better Auth's Drizzle adapter needs explicit table mappings. Took three attempts to get right.
- Password hash migration — Existing bcrypt hashes from Auth.js needed to work with Better Auth's verification. They do.
- Config consistency test — Fails if any env var is defined in Docker but missing in CI (or vice versa). Should have written this weeks ago.
- Orphaned user fix — Users without accounts blocked the setup wizard. Edge case from testing, exactly the kind of bug that bites in production.
- Agent write-access controls — The actual reason for this migration. Agents check session permissions before accepting config changes.
- Vulnerability overrides — Better Auth pulls older rollup and esbuild versions. Overridden until upstream fixes land.
The Boring Truth About Auth Migrations
Nobody writes blog posts about auth migrations. They're not glamorous. You don't get a demo video at the end.
What you get is: confidence that when a user logs in, the system knows exactly who they are and what they're allowed to do. For an enterprise platform that manages AI agents, that's not a nice-to-have. That's the foundation.
Dentist-Driven Development
Total time from branch creation to merge: 2 days. For a full auth stack replacement in a system with E2E tests, role-based access, and Docker deployment, that's fast.
Not because I'm fast. Because I can give an agent a problem, go get my teeth cleaned, and come back to working code. The bottleneck isn't typing anymore. It's thinking. And you can think in a dentist's chair just fine.
You just can't talk.
The rest of the day: first Onewheel ride of the year, first outdoor lunch of the season with a friend who reads every one of these posts (hi Manuel), and first ice cream of 2026. Spring in Vienna. Not a bad day to merge a PR.
What's Next
Knowledge Base. The feature three separate demo calls have asked about. The auth migration was blocking it because Knowledge Base needs per-user, per-agent access controls that Auth.js couldn't cleanly provide.
Now it can.