Admin-Dashboard (Modell / Budget / Usage)
Steuer- & Sichtfläche für die LLM-Kostengovernance aus
ADR-0017.
Entscheidung:
ADR-0024.
Gleichwertig als UI + API + MCP (AI-Parität, ADR-0018) — die
Logik liegt einmalig in lib/llm/* (Single Source).
Frage: siehst Du das?
Was man kann
- Modell je Aufgabe wählen (
classification,embedding,standardReport,premiumReport,pdfExtraction,toolUse,bulkParse) — Override schlägt ENV/Default, sofort wirksam (Cache-Invalidierung). - Budget-Cap (USD Tag/Monat) setzen — die Engine bremst fail-open bei Überschreitung (ADR-0017).
- Ist-Kosten sehen: heute / Monat + je Task+Modell (Calls/Tokens/$).
Benutzerverwaltung & Impersonation
Eigener Admin-Bereich (ab Dashboard-Nav verlinkt), proxy.ts-gated
(platform_admin + 2FA) und zusätzlich server-seitig geprüft.
/admin/users— Nutzerliste mit Suche (E-Mail/Name) + Rollen-Filter; pro Zeile Auge-Button (Session-Takeover, ADR-0026 v2 — wechselt in die Sicht des Nutzers mit dessen Rolle/Rechten; orange Leiste oben zeigt den Modus, dort auch „Beenden"), Kontext (read-only Inspektion via?inspect=, auditiert) und Detail. Unten: Admin-Audit + Impersonation-Audit./admin/users/[id]— Plattform-Rolle ändern (user/support/platform_admin) und Konto DSGVO-konform löschen (gleiche Erasure-Kaskade wie die Selbst-Löschung)./admin/impersonate— nur noch Redirect auf/admin/users(Konsole dort integriert); die Headless-APIGET/POST /api/v1/admin/impersonatebleibt unverändert.
Sicherheit (fail-closed): nur verifizierte platform_admin, nicht aus
einer Impersonation heraus; kein Self-Target; kein Degradieren des letzten
Admins (Lockout-Schutz); kein Löschen eines anderen Admins; Org-Owner-Guard
vor der Löschung; striktes Audit vor der Löschung. Rollen-/Lösch-Eingriffe
landen in admin_audit_log, Impersonation weiter in impersonation_log.
Rollen-Änderungen wirken für den Ziel-Nutzer erst ab dessen nächstem
Login/Token-Refresh (JWT-Sessions).
Zugänge
| Zugang | Auth | Für |
|---|---|---|
UI /admin | Auth.js platform_admin + 2FA (ADR-0006, Gate in proxy.ts) | Menschen |
API /api/v1/admin/* | API-Key mit admin-Scope | Skripte/KI |
MCP get_usage/set_model/set_budget | dito (LANDNUTZEN_API_KEY) | KI-Ops |
Kein/ungültiger Key → 401, gültiger Key ohne Scope → 403.
Datenquellen und Drift-Überwachung
/admin/data-sources trennt weiterhin den letzten technischen Lauf vom
Betriebsnachweis des tatsächlich aktiven Releases. Zusätzlich zeigt die Seite
für jeden qualifizierten Active Pointer den Zustand fresh, due, stale,
failed oder unknown, seine individuellen Fristen, Coverage-/Quality-Befunde,
den letzten Zustandswechsel und die Alarmzustellung.
Der stündliche Cron monitor-data-source-drift verwendet das bestehende
CRON_SECRET, das cron_runs-Ledger sowie die bereits eingerichtete Resend-
Zustellung an POC_ADMIN_ALLOWLIST. Alarmiert werden nur neue, geänderte,
verschärfte oder behobene Zustände; unveränderter Drift verursacht keine
wiederholten E-Mails. Fehlgeschlagene oder nicht konfigurierte Zustellung bleibt
im Dashboard sichtbar und wird beim nächsten gültigen Lauf wiederholt.
Bekannte Teilabdeckung und bereits freigegebene Qualitätswarnungen sind keine
neuen Vorfälle. Der Monitor verändert keinen Release und keinen Active Pointer.
/admin/cron/monitor-data-source-drift zeigt die Laufhistorie mit
Beobachtungen, Übergängen, Zustellstatus und dedupliziertem Fingerprint. Die
bestehende Resend-Testmodusgrenze bleibt unverändert: Vor Verifikation der
Versanddomain kann nur die hinterlegte Resend-Konto-Adresse erreichbar sein.
Werkzeug-KPIs
/admin/metrics zeigt die kennungsfreien First-Party-Aggregate aus ADR-0042:
- Aktivierungsfunnel vom ersten bewussten Formularkontakt bis zum ersten Ergebnis oder ehrlichen technischen Endzustand;
- qualifizierte Serverläufe, Erfolgs- und Fehlerquoten;
- p50/p95 als obere Grenzen fester Laufzeitklassen sowie die ausdrücklich als Näherung markierte Erstlauf-/Wiederverwendungs-Sicht je Serverinstanz;
- Providerstatus, grobes Bundesland und direkt zurechenbare Providerkosten;
- Stichprobe, erster Messtag und Reife der festen 14-Tage-Baseline einschließlich Funnel-Integrität und vollständiger Kostenzuordnung;
- den separat ausgewiesenen, während D+1 bis D+14 fortgeschriebenen und ab D+15 eingefrorenen Ausgangswert mit denselben Funnel-, Fehler-, Provider-, Runtime-, Laufzeit- und Kostendimensionen wie die laufende Auswertung.
Es existieren keine Rohereignisse. Adresse, Koordinate, Eingabe, Ergebnis,
URL, Referrer und Besucherkennungen sind weder in der Tabelle noch in der
Admin-Antwort enthalten. Der tägliche Cleanup behält regulär den aktuellen und
die 29 vorhergehenden Kalendertage; sein Laufstatus ist im Cron-Dashboard
sichtbar. Davon getrennt bleiben der Baseline-Anker aus Tool-ID und ersten
Funnel-/Server-Messtagen sowie die während D+1 bis D+14 fortgeschriebenen
Dimensionsaggregate dauerhaft als Vergleichsreferenz erhalten. Mit Ablauf von
D+14 ist der Snapshot vollständig und bleibt ab D+15 unverändert. Er enthält
keinen Kalendertag und keine Region. Die UI nutzt Auth.js mit
platform_admin und dem bestehenden 2FA-Gate.
Endpunkte
| Methode | Pfad | Zweck |
|---|---|---|
GET | /api/v1/admin/usage | Usage je Task+Modell + Spend + Budget |
GET | /api/v1/admin/model | effektives Modell je Task |
PUT | /api/v1/admin/model | { task, model } setzen |
GET | /api/v1/admin/budget | Budget + Ist |
PUT | /api/v1/admin/budget | { dailyUsd, monthlyUsd } (null = kein Limit) |
GET | /api/v1/admin/metrics?days=14&tool=pv-yield | aggregierte Werkzeug-KPIs; Fenster 1/7/14/30 Tage |
GET | /api/v1/admin/data-sources | Quellenkatalog, aktiver Release, pointergebundene Drift-Policy, Befunde und Alarmzustellung |
MET-01-Baseline abschließen
Der revisionsfähige Abschlussprüfer liest ausschließlich die bestehenden Aggregate und gibt weder Tageswerte noch Regionen oder Besucherkennungen aus:
npm run qa:metrics:baseline -- --markdown
Vor Ablauf von D+14 endet der Befehl bewusst mit einem Fehlerstatus. Für einen reinen Zwischenstands-Readback während der laufenden Messung muss dieser Zustand ausdrücklich zugelassen werden:
npm run qa:metrics:baseline -- --markdown --allow-pending
Das Tag-30-Gate darf erst geschlossen werden, wenn der Prüfer
abschlussbereit, 14/14 vollständig abgeschlossene Messtage, vorhandene
Funnel- und Serverdaten, Funnel-Integrität und vollständige Kostenzuordnung
meldet. Der ausgegebene SHA-256 bindet den tag- und regionsfreien Snapshot an
den Nachweis.
Admin-Key erzeugen
node scripts/create-admin-key.mjs "Label"
Speichert nur den Hash (SHA-256(key+secret)); der Klartext wird
einmalig ausgegeben (nicht wiederherstellbar). Scope
{report, admin}. Verwendung:
curl -H "Authorization: Bearer ln_…" \
https://www.landnutzen.at/api/v1/admin/usage
Sicherheit
Admin-Key ist mächtig: nur Hash gespeichert, Scope-getrennt,
Rate-Limit/Audit wie jeder Key (ADR-0019/0023), Rotation manuell
(neuen Key erzeugen, alten via revoked_at sperren). UI zusätzlich
durch 2FA-Gate geschützt.