docs(stack): one way to do auth — federate, or better-auth locally - #54
Merged
Conversation
The fleet had six auth approaches across eleven repos: next-auth v5 beta (7, two of them on different betas), Supabase Auth (3), Better Auth (1), next-auth v4 (1), and two hand-rolled. Five repos have no auth at all, which is the correct amount for a brochure site. The same bug got written twice independently: petvity and surf-your-life both shipped a cron guard that failed OPEN when CRON_SECRET was unset, both comparing against the literal string "Bearer undefined". That is what N implementations guarantees. THE RULE Two populations, and conflating them is the mistake: Our own products federate to OrangeCat. Its OIDC provider shipped 2026-06-17; FleetCrown, Solon and now Heidi consume it. A federated app keeps NO users table, no password, no reset flow, no session table — it reads id_token.sub and stops. The identity-bridge instruction generalises: do not rebuild profiles, payments or presence locally. Client-owned apps never federate — aoz-housing's residents belong to AOZ, not to us. They keep local auth, and the blessed library for new local auth is better-auth 1.x. WHY NOT next-auth Because it could not be enforced, and this file's premise is that unenforced choices drift. blessed-versions.json said so itself — "next-auth is deliberately absent while v5 is beta" — so version-currency.mjs, the audit that turns every other drift into a number, was structurally blind to the one technology where inconsistency costs most. The row said "v5 when stable"; it has been beta ~3 years, npm latest is still 4.x, and six repos shipped the beta regardless. better-auth has a real semver major, so it is now IN blessed-versions.json and the existing audit measures it for free. No new machinery. It also uses the blessed ORM, its magic-link plugin takes our own sender so mail-kit slots in unchanged, and hirnli has run it in production since 2026-09. NO AUTH PACKAGE SHARED.md already lists auth under what must NOT be centralized, and sitekit is the evidence: centralizing nav markup centralized the bug, and it serves 2 of 20. Share the decisions and the checks, never the implementation. Existing apps migrate on contact, never on a schedule — ADR-0002 sat at Proposed for seven months while its count went 2→4. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BUfvtBc4ycbYRRjb9eBmuB
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The fleet had six auth approaches across eleven repos: next-auth v5 beta (7, two of them on different betas), Supabase Auth (3), Better Auth (1), next-auth v4 (1), and two hand-rolled. Five repos have no auth at all, which is the correct amount for a brochure site.
The clearest symptom: petvity and surf-your-life independently shipped the same bug — a cron guard that failed open when
CRON_SECRETwas unset, both comparing against the literal string"Bearer undefined". That is what N implementations guarantees.The rule
Two populations, and conflating them is the mistake:
Our own products federate to OrangeCat. Its OIDC provider shipped 2026-06-17; FleetCrown, Solon and now Heidi consume it. A federated app keeps no users table, no password, no reset flow, no session table — it reads
id_token.suband stops. The identity-bridge instruction generalises: do not rebuild profiles, payments or presence locally.Client-owned apps never federate. aoz-housing's residents belong to AOZ, not to us. They keep local auth, and the blessed library for new local auth is better-auth 1.x.
Why not next-auth
Because it could not be enforced, and this repo's premise is that unenforced choices drift.
blessed-versions.jsonsaid so in its own comment:So
version-currency.mjs— the audit that turns every other drift into a number — was structurally blind to the one technology where inconsistency costs most. The row said "v5 when stable"; it has been beta for about three years, npmlatestis still 4.x, and six repos shipped the beta anyway.better-authhas a real semver major, so it is now inblessed-versions.jsonand the existing audit measures it for free. No new machinery. It also uses the blessed ORM (Drizzle +pg), its magic-link plugin takes our own sender somail-kitslots in unchanged, and hirnli has run it in production since 2026-09.Deliberately not doing
No auth package.
SHARED.mdalready lists auth under "what must NOT be centralized", andsitekitis the evidence — centralising nav markup centralised the bug, and it serves 2 of 20 repos. Share the decisions and the checks, never the implementation.No migration project. Existing apps migrate on contact. ADR-0002 sat at "Proposed" for seven months while its duplicate count went 2 → 4; adoption here has only ever moved as a side effect of repairing something.
Docs + one line of JSON. No code changes.
🤖 Generated with Claude Code
https://claude.ai/code/session_01BUfvtBc4ycbYRRjb9eBmuB