# BetterAuth Migration Checklist

This document covers the manual steps required to complete the Clerk → BetterAuth migration in both development and production.

**What's automated** (runs via `scripts/migrate.mjs` on every deploy, idempotent):
- Schema migrations (sessions, accounts, verifications tables; nullable clerk_id; email_verified column)
- Convert `teams.owner_id` and `commissioners.user_id` from Clerk IDs → `users.id` UUIDs
- Mark all Clerk users as `email_verified = true`
- Create `accounts` records for Google and Discord OAuth users (via Clerk API)

**What's manual** (one-time steps you do by hand):
- Export user CSV from Clerk (for password hash migration)
- Run the password migration script
- Update OAuth redirect URIs in Google/Discord consoles
- Set env vars in production

---

## Development

### Step 1 — Add environment variables

Add these to your `.env` file:

```
BETTER_AUTH_SECRET="<random string — run: openssl rand -base64 32>"
BETTER_AUTH_URL="http://localhost:5173"
GOOGLE_CLIENT_ID="<from Clerk dashboard → Social Connections → Google>"
GOOGLE_CLIENT_SECRET="<from Clerk dashboard → Social Connections → Google>"
DISCORD_CLIENT_ID="<from Clerk dashboard → Social Connections → Discord>"
DISCORD_CLIENT_SECRET="<from Clerk dashboard → Social Connections → Discord>"

# Keep temporarily for the automated OAuth migration (remove after confirmed working)
CLERK_SECRET_KEY="<your existing value>"
```

Remove once confirmed working: `VITE_CLERK_PUBLISHABLE_KEY`, `CLERK_WEBHOOK_SECRET`, `DEV_ADMIN_CLERK_ID`

### Step 2 — Apply the database schema migration

```bash
npm run db:migrate
```

Adds the `sessions`, `accounts`, and `verifications` tables; makes `clerk_id` nullable; adds `email_verified`.

### Step 3 — Add OAuth redirect URIs for localhost

In **Google Cloud Console** (APIs & Services → Credentials → your OAuth client):
- Add `http://localhost:5173/api/auth/callback/google` to Authorized redirect URIs

In **Discord Developer Portal** (your app → OAuth2):
- Add `http://localhost:5173/api/auth/callback/discord` to Redirects

### Step 4 — Run the automated data migration

```bash
node scripts/migrate.mjs
```

This converts owner IDs, creates Google/Discord OAuth accounts, and marks users as email-verified. It reads from the Clerk API using your `CLERK_SECRET_KEY`.

### Step 5 — Migrate email/password users

This requires exporting password hashes from Clerk (they're only in the CSV export, not the API).

1. Go to **Clerk dashboard → Users → Export** and download the CSV
2. Save it as `exported_users.csv` in the project root (it's gitignored)
3. Run:
   ```bash
   node scripts/migrate-clerk-passwords.mjs
   ```
4. **Delete `exported_users.csv` immediately after** — it contains bcrypt password hashes

### Step 6 — Set yourself as admin

`DEV_ADMIN_CLERK_ID` no longer works. Set admin access directly in the database:

```sql
UPDATE users SET is_admin = true WHERE email = 'your@email.com';
```

### Step 7 — Verify sign-in works

- **Google / Discord**: sign in immediately — OAuth accounts were migrated automatically
- **Email/password**: sign in with the same password as before — bcrypt hashes were migrated
- Check that league ownership and commissioner access still works

After verifying, remove `CLERK_SECRET_KEY` from `.env`.

---

## Production

> Do Steps 1–3 before merging to main. The data migration (Step 4) and OAuth account creation run automatically on deploy.

### Step 1 — Add production environment variables

Add to your production environment (server docker-compose / secrets manager):

```
BETTER_AUTH_SECRET="<strong random string — openssl rand -base64 32>"
BETTER_AUTH_URL="https://brackt.com"
GOOGLE_CLIENT_ID="<same as Clerk dashboard>"
GOOGLE_CLIENT_SECRET="<same as Clerk dashboard>"
DISCORD_CLIENT_ID="<same as Clerk dashboard>"
DISCORD_CLIENT_SECRET="<same as Clerk dashboard>"

# Keep temporarily — needed for the automated OAuth migration on first deploy
CLERK_SECRET_KEY="<your existing production value>"
```

### Step 2 — Add OAuth redirect URIs for production

In **Google Cloud Console**:
- Add `https://brackt.com/api/auth/callback/google` to Authorized redirect URIs

In **Discord Developer Portal**:
- Add `https://brackt.com/api/auth/callback/discord` to Redirects

### Step 3 — Migrate email/password users (before deploying)

The password migration runs against the production database directly — it does NOT go through Docker.

1. Go to **Clerk dashboard → Users → Export** and download the CSV for production users
2. Save as `exported_users.csv` in the project root (gitignored)
3. Run against the production database:
   ```bash
   DATABASE_DIRECT_URL="<prod connection string>" CLERK_SECRET_KEY="<prod key>" node scripts/migrate-clerk-passwords.mjs
   ```
4. **Delete `exported_users.csv` immediately**

### Step 4 — Deploy

Merge to `main`. The GitHub Actions deploy will:
1. Build and push the Docker image
2. SSH to the server and run `docker compose up --no-deps migrate`
3. `scripts/migrate.mjs` runs — applies schema migrations, then (because `CLERK_SECRET_KEY` is set):
   - Converts `teams.owner_id` and `commissioners.user_id` to `users.id` UUIDs
   - Marks users as `email_verified`
   - Creates `accounts` records for Google and Discord OAuth users
4. The app container starts with the new BetterAuth code

### Step 5 — Verify production sign-in

- Google and Discord users: sign in immediately
- Email/password users: sign in with the same password as before
- Spot-check that league ownership and commissioner access are intact

### Step 6 — Remove Clerk credentials

Once everything is confirmed, remove from the production environment:
```
CLERK_SECRET_KEY
VITE_CLERK_PUBLISHABLE_KEY
CLERK_WEBHOOK_SECRET
DEV_ADMIN_CLERK_ID
```

Delete the Clerk webhook endpoint from the Clerk dashboard (it no longer exists in the codebase).

On the next deploy, `scripts/migrate.mjs` will log `"CLERK_SECRET_KEY not set — skipping Clerk account migration"` and skip gracefully.

---

## Notes

### Why email/password migration is a separate manual step

Clerk's REST API does not expose password hashes — they're only available in the CSV dashboard export. The automated deploy script (`scripts/migrate.mjs`) handles OAuth accounts via the API, but password hashes must be exported manually and migrated with `scripts/migrate-clerk-passwords.mjs`.

The bcrypt hashes from Clerk are directly compatible with BetterAuth — no re-hashing is needed. Users sign in with the same password as before.

### What if a user signed up with both Google and email/password?

Both an OAuth account and a credential account will be created for them. BetterAuth handles this correctly — the user can sign in with either method.

### Future cleanup

After the migration is stable (a week or two after production deploy), open a follow-up PR to:
1. Remove the `clerk_id` column from `database/schema.ts` and run `npm run db:generate`
2. Remove `CLERK_SECRET_KEY` handling from `scripts/migrate.mjs`
3. Delete `scripts/migrate-clerk-passwords.mjs`
