- admin-todo.html: mobile-freundliche ToDo/Review-Liste (Prioritaeten, Haekchen +
Notizfelder je Punkt, localStorage, Notizen-Export), admin-gated, noindex. In
admin-licenses.html Nav + Backend-Werkzeuge verlinkt.
- admin.php: devPin auch bei STAGING=1 (v3, Mail bewusst tot) -> Self-Service-
Admin-Login ohne Mailversand. Prod unveraendert (STAGING dort nie definiert,
2FA-Mail-Pflicht bleibt).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Problem: lokal konnte man sich nicht als Admin anmelden — der 2FA-PIN kam nie
an (kein SMTP), und Mailer::sendAdminPin() warf sogar eine Exception, die den
Login komplett abbrach (leere Antwort → „MFA fehlt").
- admin.php: Mailversand nur auf Prod + in try/catch (Mail-Fehler darf den
Login NIE blocken). Lokal (!IS_PRODUCTION) wird der PIN als `devPin` in der
Login-Antwort zurückgegeben — auf Prod NIEMALS (2FA bleibt Pflicht).
- admin.html: devPin wird lokal automatisch ins PIN-Feld vorausgefüllt + als
Hinweis angezeigt.
Verifiziert (temp Test-Admin): login → devPin → verify → authenticated:true,
admin-weltkueche.html erreichbar. Prod unberührt (IS_PRODUCTION-Gate).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vorbereitung für den JWT+Redis-Umschalter: alle verstreuten
$_SESSION['teacher_id'|admin_id']-Zugriffe laufen jetzt durch Session::-Helper,
damit der Backend-Tausch später EINE Datei (Session.php) ist statt 18 Stellen.
- Session.php: neue Admin-Helper adminId()/loginAdmin()/logoutAdmin()/
requireAdmin() (mirror der Teacher-Helper). teacherId()/adminId() starten
die Session jetzt lazy (Aufrufer müssen Session::start() nicht mehr).
- 18 Fundstellen kanalisiert (admin.php, admin-accounts, admin-modules,
licenses, levels, waypoints, foto-upload, admin_gate, save_map).
- Country.php + app.php cockpit_href: über Session:: mit class_exists-Fallback
(Bootstrap/Lib-Kontext, Session evtl. nicht geladen).
Verhaltensneutral: 14/14 Lint OK, Helper-Round-Trip 6/6 PASS, Live-Smoke
(admin status/modules/accounts/licenses) weist unauth. Requests wie bisher
mit 401/403 ab. AUTH_BACKEND bleibt 'session' — Live unverändert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>