Case study
Velve Auth
We wrote the operating system. The login was not going to be someone else's.
Context
The European authentication library for TypeScript and PostgreSQL, built for Velve, a deployment platform for Europe that is written from the ground up — down to its own kernel. It runs in your own process with your users in your own database, answers who is signed in, and nothing else: no roles, no organisations, no third-party service in the loop.
Why I built it
Velve is built from scratch. Not the framework, not the runtime — the operating system underneath is ours, and the platform on top is shaped differently from anything a general-purpose auth library expects. Sign-in sits in the core of that platform, and the things the platform will need from it later are things no off-the-shelf library has a place for. Borrowing was never really on the table, and the one candidate settled the question on its own: Better Auth stores password hashes as salt and hash with no algorithm marker, a grep for rehash across its whole repository returns nothing, it invents email addresses at nine call sites when a provider returns none — and since July 2026 it belongs to Vercel.
I wanted a library that verifies whatever hash you already have and quietly replaces it with Argon2id on the next sign-in.
Verifying a hash and creating one are separate decisions. The library reads six prefix families — Argon2, bcrypt, scrypt, PBKDF2 and Firebase's modified scrypt — and writes exactly one.
Auth libraries don't fail on cryptography. Of Better Auth's 33 published advisories, ten are the same missing line: and user_id equals actor. So every repository method on a user-bound table takes an actor in its signature. You can pass the wrong one; you can't forget it.
The optional WASM accelerator broke the one guarantee it was meant to speed up. hash-wasm settles in a microtask, so 800 concurrent sign-ins against a five-second wait limit ran 14.7 seconds with zero refusals. The fix yields between derivations, and the wrong explanation I first wrote for it is still in the decision log above the correction — a log you tidy is a log you can't trust.
What should've been a library is currently a 290-entry decision log, 4,300 lines of documentation and sixteen tables, with the sign-in route still ahead of it. The reasons are the product; the code is the receipt.
Stack
Links
Next