Phase 9 abgeschlossen: Übersicht, Beobachtungsliste, helles Thema, Messung
Prüfung / Lint, Typen, Tests (push) Canceled after 0s
Prüfung / Images bauen (pdf) (push) Canceled after 0s
Prüfung / Images bauen (web) (push) Canceled after 0s
Prüfung / Images bauen (worker) (push) Canceled after 0s
Images / bauen (pdf, docker/pdf.Dockerfile) (push) Canceled after 0s
Images / bauen (web, docker/web.Dockerfile) (push) Canceled after 0s
Images / bauen (worker, docker/worker.Dockerfile) (push) Canceled after 0s

Die Übersicht beantwortet vier Fragen, die man morgens hat: woran arbeite ich,
was ist fällig, wo hat jemand geschrieben, was hat sich getan. Jede Liste
läuft durch visibleCaseWhere — das ist der Ort, an dem eine unachtsame
Abfrage am ehesten eine Akte verrät. Ein Test prüft jede einzeln gegen eine zu
hoch eingestufte Akte. Der bisherige Inhalt ("Dein Zugang") steht jetzt unter
/zugang.

Beobachten ist eine Merkliste, kein Recht: nur was sichtbar ist, lässt sich
merken, und steigt eine Akte später über die eigene Stufe, verschwindet sie
aus der Liste, ohne dass jemand aufräumt.

Das helle Thema tauscht nur die semantische Ebene; die Grundpalette bleibt.
Die Klassifizierungsfarben sind für hellen Grund eine Spur dunkler, im Farbton
aber dieselben — eine Stufe muss in beiden Themen wiedererkennbar sein. Drei
Zustände, "wie das System" ist der Auslieferungszustand, und ein Skript im
Kopf setzt die Wahl, bevor das erste Mal gemalt wird.

Die Messung misst nicht den Nutzer. web-vitals schickt Zahlen und das
Routenmuster, keine Kennung und keinen konkreten Pfad: wer wann welche Akte
geöffnet hat, steht im Zugriffsprotokoll, und eine zweite Spur daneben wäre
eine Überwachungsfunktion ohne Auftrag. Ausgewertet wird Median und 75.
Perzentil, nicht der Mittelwert.

Mobil: die breiten Tabellen scrollen in sich, statt die Seite breiter zu
machen. Ein e2e-Test hält fest, dass keine Seite waagerecht überläuft.

scripts/restore-test.sh spielt eine Sicherung in eine Wegwerf-Datenbank und
prüft ausdrücklich, dass Regeln und Trigger mitkommen: eine Wiederherstellung
ohne entry_no_delete wäre eine Datenbank ohne die Zusicherung, um derentwillen
das System gebaut wird. Einmal durchgespielt, alles angekommen.

186 Tests im Web-Paket, 17 in der Datenbank, 7 im Worker, 54 e2e.
Grösste Route 116,2 von 120 kB.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Harlekin
2026-09-03 10:28:50 +02:00
co-authored by Claude Opus 5
parent 77b29d68d3
commit 3466215e2c
28 changed files with 1446 additions and 92 deletions
@@ -0,0 +1,19 @@
-- Phase 9: Ladewerte messen.
--
-- Nur Zahlen und das Routenmuster. Keine Kennungen, keine konkreten Pfade —
-- die Messung soll sagen, ob die Anwendung schnell ist, nicht wer wann welche
-- Akte geöffnet hat. Siehe docs/09-performance-und-ux.md.
CREATE TABLE "WebVital" (
"id" BIGSERIAL NOT NULL,
"at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"metric" TEXT NOT NULL,
"value" DOUBLE PRECISION NOT NULL,
"route" TEXT NOT NULL,
"rating" TEXT NOT NULL,
CONSTRAINT "WebVital_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "WebVital_metric_at_idx" ON "WebVital"("metric", "at");
CREATE INDEX "WebVital_route_metric_idx" ON "WebVital"("route", "metric");
+20
View File
@@ -906,6 +906,26 @@ enum ExportStatus {
REJECTED
}
/// Gemessene Ladewerte aus den Browsern der Nutzer.
///
/// Nur Zahlen und der Name der Route, **keine Kennungen und keine Adressen mit
/// Aktenzeichen**: die Messung soll sagen, ob die Anwendung schnell ist, nicht
/// wer wann welche Akte geoeffnet hat. Dafuer gibt es das Zugriffsprotokoll,
/// und das ist der richtige Ort dafuer.
model WebVital {
id BigInt @id @default(autoincrement())
at DateTime @default(now())
/// "LCP", "INP", "CLS", "TTFB", "FCP"
metric String
value Float
/// Das Routenmuster, nicht der konkrete Pfad: "/faelle/[caseNumber]".
route String
rating String // "good" | "needs-improvement" | "poor"
@@index([metric, at])
@@index([route, metric])
}
/// Lebenszeichen der Dienste, die nicht im Web-Container laufen. Der Worker
/// schreibt hier seinen Gateway-Zustand hinein, damit /api/health ihn pruefen
/// kann, ohne Discord zu befragen. Siehe docs/11-betrieb.md.