# Trainee management — operations (Phase 1)

Roster and copy-paste portal for workshop attendees. Design: [trainee-management-design.md](trainee-management-design.md).

## Cloudflare setup

| Variable | Environment | Purpose |
|----------|-------------|---------|
| `WORKSHOP_TOKEN` | Production | Site login + trainee portal API |
| `TRAINER_API_SECRET` | Production | Trainer roster/settings writes |
| `DB` | D1 binding `mhp-workshop-trainer` | Persistence |

Add `TRAINER_API_SECRET` in **Cloudflare Pages → Settings → Environment variables** (Production). Use a long random string — not the same as `WORKSHOP_TOKEN`.

Schema migration (once, or on deploy via API auto-create):

```bash
cd workshop-2026-v2
npx wrangler d1 execute mhp-workshop-trainer --remote --file=schema/d1/002_trainee_management.sql
```

Tables are also created on first API call via `ensureTraineeSchema`.

## Trainer workflow

1. Set workshop session on [Pre-class checklist](../trainer/pre-class-checklist/index.qmd) (cohort id `YYYYMMDD-slug`).
2. Open [Trainee management](../trainer/trainee-management.qmd) — enter `TRAINER_API_SECRET` when prompted (stored in browser session only).
3. Add trainees with **Add row** (name and email required; edit cells then **Save** per row).
4. Save **cohort settings** (URLs, ADLS key, SAS token, …).
5. **Copy portal link** into pre-class email ([trainee-pre-work](../trainer/trainee-pre-work.qmd)).
6. On training morning: **Unlock delivery credentials** (or wait for auto-unlock on delivery date).

## Trainee workflow

1. Sign in with workshop token on [training site](https://mhp-data-engineer-2026.pages.dev/).
2. Open portal link: `…/trainee-portal.html?cohort=YYYYMMDD-slug`
3. Select name → confirm email (must match roster).
4. Copy `ATTENDEE_ID`, links, `.env` snippet, and delivery secrets when unlocked.

## API smoke tests

```bash
# Trainee roster (requires WORKSHOP_TOKEN)
curl -sS -H "Authorization: Bearer YOUR_WORKSHOP_TOKEN" \
  "https://mhp-data-engineer-2026.pages.dev/api/trainee-portal?cohort=20260615-test&mode=roster"

# Trainer roster (requires TRAINER_API_SECRET)
curl -sS -H "Authorization: Bearer YOUR_TRAINER_SECRET" \
  "https://mhp-data-engineer-2026.pages.dev/api/trainees?cohort=20260615-test"
```

## D1 troubleshooting

Open [https://mhp-data-engineer-2026.pages.dev/api/trainer-db-health](https://mhp-data-engineer-2026.pages.dev/api/trainer-db-health) after deploy.

| Symptom | Fix |
|---------|-----|
| `Database not configured` / binding missing | Cloudflare Pages → **Settings** → **Functions** → **D1 database bindings** → add **DB** → `mhp-workshop-trainer` → **Production** → redeploy |
| `D1 tables missing` | CI step `apply-d1-schemas.mjs` failed or wrong database — re-run deploy |
| `Unauthorized` on roster | Set `TRAINER_API_SECRET` in Pages env vars (Production) |
| Buttons do nothing | Unlock **trainer gate** (today’s `YYYYMMDD` access code) first — it blocks the page |

## Vercel mirror

| Feature | Vercel (`site-lemon-zeta.vercel.app`) | Cloudflare (`mhp-data-engineer-2026.pages.dev`) |
|---------|--------------------------------------|-----------------------------------------------|
| Modules, exercises, setup guides | Yes | Yes |
| Workshop token login (`/api/auth`) | Yes | Yes |
| Checklist progress (D1) | Browser only | D1 sync |
| Trainee roster / My Workshop portal | **No** (no D1) | **Yes** |
| Trainer trainee management | **No** | **Yes** |

Trainees who land on Vercel see a banner on **My Workshop** with a link to the Cloudflare portal. Trainers should send the **Cloudflare** portal link in pre-class email.

## Phase 2 (not implemented)

See [design doc §6](trainee-management-design.md) — encryption, CSV, audit log, email templates.
