feat(auth): self-contained QR-pairing login voor Ops-dashboard #90
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/qr-pairing-login"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Doel
QR-login voor het Ops-dashboard (naast email/wachtwoord): scan op
/loginmet een telefoon die in het Ops-dashboard is ingelogd → de desktop krijgt een Ops-sessie. Self-contained binnenops_dashboard.Aanpak
Eigen
LoginPairing-tabel in de Ops-DB;/m/pairis een publieke shell (auth in de same-origininfo/approve-calls viagetCurrentUser— werkt ondanksSameSite=Strictop de eerste cross-site QR-GET);claimconsumeert atomair en mint een Ops-SessionviacreateSession(…, tx)+ops_session-cookie. Geen iron-session, geen scrum4me-DB, geen role/demo-gate (één identiteitsruimte). Alle POST's viaapiFetch(CSRF double-submit).Wat is toegevoegd (additief)
app/api/auth/pair/{start,status,info,approve,claim}lib/pairing.ts,lib/pair-cookie.ts,lib/qr-poll.ts;createSession(…, db=prisma)tx-paramLoginPairingmodel +PairingStatusenum + hand-authored migratieproxy.ts:/m/pairpubliek (slash-aware match)app/login/qr-login.tsx+app/m/pair/{page,pair-confirm}.tsxReviews & gates
createSession(tx),PairingStatusenum,infoals POST, approveexpires_at-guard, proxy slash-aware, fail-fastINSTANCE_BASE_URL).nextPollAction+ unit-test).npm run typecheck && npm testgroen: 121 tests (25 files).Geen
Geen wijziging aan scrum4me-web/workers; geen scrum4me-DB-writes. Geen nieuwe env (
INSTANCE_BASE_URLbestaat al).Deploy
prisma migrate deploy+prisma migrate status(Ops = migrator van zijn eigen DB).https://ops.jp-visser.nl) is een post-deploy check.Spec/plan:
docs/superpowers/{specs,plans}/2026-06-15-ops-dashboard-qr-pairing*.md. Scrum4Me: Sprint S-2026-06-15-1, PBI-7, Story ST-017, taken T-55…T-67.🤖 Generated with Claude Code
- app/login/qr-login.tsx: client component with idle/starting/showing/claiming/error phases, QRCodeSVG display, polling /api/auth/pair/status every 2000ms, claim via apiFetch /api/auth/pair/claim on approved, router.push('/') on success - app/login/page.tsx: add QrLogin after </form> with "of"-divider, inside card - app/m/pair/page.tsx: public server shell, no auth guard, renders PairConfirm in card - app/m/pair/pair-confirm.tsx: client component parsing window.location.hash, apiFetch /api/auth/pair/info, 401→unauthenticated state with /login link, Approve button for pending+!expired, apiFetch /api/auth/pair/approve → confirmed Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>