Reasons (full ADR in docs/decisions/0001-auth-provider.md): - KetoPath targets EU users with Art. 9 GDPR data; Clerk on US infra raises Schrems II concerns - Free, self-hostable, stays in our Postgres - TypeScript-first, fits Next.js + Fastify + Prisma stack CLAUDE.md updated: - Tech stack: Better Auth on EU Postgres - "Cosa NON fare mai": no manual password hashing - References: Better Auth docs link Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.8 KiB
5.8 KiB
ADR 0001 — Auth provider
- Status: accepted
- Date: 2026-04-29
- Decision makers: Luciano (PO), Claude
- Supersedes: scelta iniziale Clerk in
CLAUDE.md
Contesto
KetoPath è una web app che tratta dati di salute (peso, misure, foto progress, sintomi) — categoria particolare di dati personali ex art. 9 GDPR. Inoltre l'app, per posizionamento commerciale, è destinata esclusivamente al mercato italiano/europeo.
La scelta iniziale in CLAUDE.md era Clerk, ma:
- Schrems II: Clerk è un SaaS USA. Anche con DPA + SCC, il transfer di dati personali (soprattutto sanitari) verso gli USA è una zona grigia per il Garante italiano. Un eventuale incidente o un'ispezione non avrebbe una difesa pulita.
- Costo: oltre 10k MAU il prezzo scala in modo non banale per un MVP a budget contenuto (PRD §16.3).
- Vendor lock-in: spostarsi da Clerk dopo l'integrazione è oneroso (sessions, password reset, OAuth tutto sul loro storage).
Decisione
Adottare Better Auth come libreria di autenticazione self-hostata, con i seguenti vincoli e configurazione:
- Storage: tabelle
User,Session,Account,Verificationnello stesso Postgres del resto dell'app, gestito da@ketopath/db(Prisma). - Residenza dati: ovunque ospiteremo Postgres, deve essere in regione EU. Per l'MVP: locale (Mac); per la produzione (Render/Fly.io): regione EU obbligatoria.
- Metodi di autenticazione:
- Email + password (hashing scrypt gestito da Better Auth)
- Google OAuth (Schrems II non rilevante perché l'utente sceglie attivamente di delegare a Google)
- Email verification: disattivata per MVP per non bloccare onboarding/test; verrà attivata prima del lancio pubblico (V1) insieme a SendGrid.
- MFA: posticipata a V1.
Conseguenze
Positive
- Tutti i dati personali (incluse credenziali in formato hash) restano nel database controllato da noi. Difendibile in audit GDPR.
- Zero costi ricorrenti su un servizio esterno per auth.
- Nessun vendor lock-in: se Better Auth diventa irraggiungibile, possiamo sostituirla con altra libreria mantenendo lo schema.
- Stack 100% TypeScript, integrazione naturale con Next.js (App Router) e Fastify.
Negative
- Responsabilità di sicurezza più alta: dobbiamo aggiornare la libreria con regolarità, monitorare le advisories, gestire il
BETTER_AUTH_SECRETcome segreto critico. - Funzionalità da costruire: alcune feature che Clerk dava out-of-the-box (UI sign-in pre-fatto, gestione MFA hardware, dashboard utenti) richiedono codice nostro.
- Maturità libreria: Better Auth è progetto giovane (2024+), meno battle-tested rispetto a Auth.js o Clerk. Mitigazione: review delle release, smoke test E2E sul flusso auth, fallback a Auth.js se la libreria viene abbandonata.
Alternative considerate
| Opzione | Motivo del NO |
|---|---|
| Clerk | Transfer USA — Schrems II problematico per dati sanitari italiani |
| Auth0 | Costoso oltre 7k MAU; stesso problema USA di Clerk |
| Supabase Auth (cloud) | EU regions ok ma vendor SaaS aggiuntivo che non serve |
| Supabase Auth (self-hosted, GoTrue) | Overhead operativo (Docker, configurazione separata) non giustificato per MVP |
| Auth.js (NextAuth.js) | Tecnicamente valido, più maturo, ma API meno pulita e integrazione Fastify-side scomoda (è Next.js-first); preferito Better Auth per coerenza tra web e api |
| Lucia | Deprecata a marzo 2025 |
| Keycloak | Overkill — JVM, ops dedicato, target enterprise |
| Ory Kratos | Buona alternativa EU-native (Germania), ma overhead operativo simile a Supabase self-hosted; rivalutabile se Better Auth diventasse insostenibile |
Implementazione
Tracciata in 6 fasi:
- Fase 0 (questo ADR + aggiornamento
CLAUDE.md) - Fase 1: schema Prisma + migrazione
add_auth_tables - Fase 2: pacchetto
@ketopath/authcon istanza Better Auth condivisa - Fase 3: integrazione Next.js (handler, client, pagine sign-in/sign-up)
- Fase 4: integrazione Fastify (plugin di sessione, endpoint
GET /me) - Fase 5: test unit + E2E sign-up/sign-in
- Configurazione OAuth Google: a fine progetto, quando il PO fornirà le credenziali
Vincoli operativi da rispettare
BETTER_AUTH_SECRETdeve essere identico traapps/webeapps/api(è la chiave di firma della session).BETTER_AUTH_SECRETnon va mai committato; va caricato via env in produzione (Vercel + Render secrets).- Lo schema delle tabelle auth segue la convenzione Better Auth — non rinominare colonne arbitrariamente per non rompere la libreria al prossimo upgrade.
- Tutti i test E2E che toccano l'auth devono usare account creati nel test stesso (no fixture utenti reali).