92 lines
3.4 KiB
Markdown
92 lines
3.4 KiB
Markdown
# 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 key
|
|
- `SUPABASE_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.profiles` with `id` referencing `auth.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`
|
|
|
|
- `registerUser` now creates credentials in Supabase Auth (`auth.users`) via admin API.
|
|
- `authenticateUser` now verifies credentials using `signInWithPassword` instead of `public.users.password_hash`.
|
|
- `updateUserAccount` now updates password/email in Supabase Auth admin API.
|
|
- Profile fields are mirrored to:
|
|
- `public.users`
|
|
- `public.profiles`
|
|
- Existing custom `gantt_session` flow 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 mirrored `public.users`)
|
|
- app session guard cookie: custom `gantt_session` is 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:
|
|
|
|
1. Move API auth/session checks to Supabase JWT/session directly.
|
|
2. Remove custom session table/cookie flow (`public.sessions`, `gantt_session`) after cutover.
|
|
3. Keep `public.profiles` as the only app profile table and retire compatibility mirrors.
|