3.4 KiB
Auth and Settings Migration Notes (Feb 21, 2026)
This document captures the auth/settings stabilization work completed during the SQLite -> Supabase migration cleanup.
Why this was needed
The app had overlapping auth models:
- Supabase Auth tables (
auth.users) - App tables (
public.users,public.sessions,public.password_reset_tokens)
The app was still expecting public.users.password_hash, but that column was not present in the migrated schema, which caused:
- login failures
- reset password failures (
Could not find the 'password_hash' column...) - settings profile/session issues
Environment key mapping that must be correct
Use different values for these:
NEXT_PUBLIC_SUPABASE_ANON_KEY-> anon/publishable keySUPABASE_SERVICE_ROLE_KEY-> service_role/secret key
If these are the same value, auth/session/profile flows break.
Database work completed (Phase 1)
Phase 1 schema alignment was completed in Supabase:
- created
public.profileswithidreferencingauth.users(id) - enabled RLS policies for own profile access
- backfilled profile rows from existing data
- optional trigger created to auto-create profile rows for new auth users
public.users was retained for compatibility during transition.
Code changes made
1) src/lib/server/auth.ts
registerUsernow creates credentials in Supabase Auth (auth.users) via admin API.authenticateUsernow verifies credentials usingsignInWithPasswordinstead ofpublic.users.password_hash.updateUserAccountnow updates password/email in Supabase Auth admin API.- Profile fields are mirrored to:
public.userspublic.profiles
- Existing custom
gantt_sessionflow remains in place for compatibility.
2) src/app/api/auth/reset-password/route.ts
- Removed dependency on
public.users.password_hash. - Password reset now updates Supabase Auth user password through admin API.
- Added fallback for legacy records: if auth user is missing, create it with the same UUID, then set password.
3) src/app/settings/page.tsx
- Hardened response parsing for session/profile/password requests to avoid client runtime errors on malformed responses.
- Fixed avatar preset rendering key collisions:
- deduped generated preset URLs
- switched to stable numeric keys (not data URL strings)
Current state (important)
Auth is currently hybrid but stable:
- credentials/passwords: Supabase Auth (
auth.users) - app profile fields:
public.profiles(and mirroredpublic.users) - app session guard cookie: custom
gantt_sessionis still used by this codebase
This is intentional as an intermediate compatibility stage.
Known behavior
Forgot password route currently generates reset links for dev/testing flow and does not send production email by itself unless an email provider flow is added.
Validation checklist used
- login works after env fix
- reset password no longer fails on missing
password_hash - settings screen loads name/email/avatar
- avatar save no longer returns auth/session-related errors
- duplicate React key warning in avatar presets resolved
Next cleanup (recommended)
To fully finish migration and remove duplication:
- Move API auth/session checks to Supabase JWT/session directly.
- Remove custom session table/cookie flow (
public.sessions,gantt_session) after cutover. - Keep
public.profilesas the only app profile table and retire compatibility mirrors.