# 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.
