Adds the two passwordless-auth endpoints behind /api/v1/auth/:
POST /magic-link/request — body {email}; always 200 (no enumeration leak)
GET /magic-link/consume — ?token=...; signs in (signup-on-first-link)
Sign-up flow: first consume for an unknown email creates the user with a
random unguessable bcrypt-hashed password — keeps the schema NOT NULL
constraint while permanently locking the password endpoints out.
Failure modes (missing/expired/already-consumed) collapse to a single
401 to prevent attackers distinguishing them. DB persist failures on
request silently degrade to the generic 200 to avoid leaking internal
state.
Config:
auth.magic_link.ttl (default 15m, env DLC_AUTH_MAGIC_LINK_TTL)
auth.magic_link.base_url (default http://localhost:8080)
Tests: 11 unit tests against fakes (repo, user service, sender) cover
happy path (new + existing user), normalization, bad JSON, persist
failure, missing/unknown/expired/consumed token, URL builder.