diff --git a/PORTAL_MIGRATION.md b/PORTAL_MIGRATION.md new file mode 100644 index 0000000..1516b9c --- /dev/null +++ b/PORTAL_MIGRATION.md @@ -0,0 +1,158 @@ +# Portal Migration — APIv1/Pterodactyl → APIv2 + +## Purpose +This document defines the required migration steps for moving the ZeroLagHub portal from APIv1 / Pterodactyl assumptions to APIv2. + +It exists to: +* Prevent silent regressions +* Provide a shared checklist for Codex, Claude, and humans +* Make architectural intent explicit + +This file is authoritative. + +--- + +## Migration Scope + +### In Scope +* Authentication +* Instance listing & detail views +* Removal of legacy abstractions +* Alignment with APIv2 contracts + +### Out of Scope (for now) +* Billing +* RBAC / roles +* Refresh tokens +* xterm / console auth (tracked separately) + +--- + +## Phase 1 — Authentication Alignment ✅ (API-side complete) + +### APIv2 Status +* JWT-based auth implemented +* `POST /api/auth/login` +* `GET /api/auth/me` +* Stateless, header-based auth +* No CSRF +* No cookies + +### Portal Requirements +* Portal must not attempt credential validation +* Portal must not implement CSRF +* Portal must send `Authorization: Bearer ` +* Portal must treat APIv2 as source of truth + +--- + +## Phase 2 — Portal Login Migration (REQUIRED) + +### Required Changes +* Login form must submit: + +```json +{ + "identifier": "", + "password": "" +} +``` + +* Token must be stored in `sessionStorage` +* Token must be attached to all API requests + +### Forbidden Patterns +* Cookies for auth +* CSRF tokens +* Legacy `/api/v1/*` calls +* Pterodactyl login flows + +--- + +## Phase 3 — Instances Migration ✅ (API-side verified) + +### APIv2 Contract +* `GET /api/instances` returns: + +```json +{ + "ok": true, + "rows": [ ... ] +} +``` + +### Portal Expectations +* Portal dashboard must: + * Handle empty arrays gracefully + * Not assume instances always exist + * Render based on API response only + +### Explicit Rule +If the portal cannot render with an empty `rows` array, the portal is incorrect. + +--- + +## Phase 4 — Route Protection (UPCOMING) + +### Planned Behavior +* Read routes will require auth: + * `GET /api/instances` + * `GET /api/instances/:vmid` +* Write routes may remain internal initially + +### Portal Implications +* Portal must handle `401 Unauthorized` +* Portal must redirect to login on auth failure +* No retry loops using legacy logic + +--- + +## Phase 5 — Legacy Removal (MANDATORY) + +### Must Be Removed From Portal +* APIv1 client code +* Pterodactyl references +* CSRF utilities +* Cookie-based session logic +* Any fallback to "old behavior" + +### Review Rule +If a portal file references Pterodactyl or APIv1, it must be deleted or rewritten. + +--- + +## Verification Checklist (Use Before Merge) + +* [ ] Portal login uses `/api/auth/login` +* [ ] Token stored only client-side +* [ ] All API calls include Authorization header +* [ ] Dashboard loads with zero instances +* [ ] No CSRF or cookies present +* [ ] No APIv1 endpoints referenced + +--- + +## Anti-Drift Statement + +Any deviation from this document must: +1. Be explicitly discussed +2. Be documented in `SESSION_LOG.md` +3. Update `CONSTRAINTS.md` and/or `ANTI_DRIFT.md` + +Silent changes are not allowed. + +--- + +## Ownership + +* **Portal Team**: Implementation +* **APIv2**: Contract stability +* **zlh-grind**: Enforcement and truth anchor + +--- + +## Status + +* **Created**: 2025-12-28 +* **State**: Active +* **Next Update**: After route-level auth enforcement