feat(laeufe): Service, Abarbeitung, Kommentare und Archivschutz
Prüfung / pruefung (push) Canceled after 0s
Prüfung / pruefung (pull_request) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s
Prüfung / e2e (pull_request) Canceled after 0s

Ein Lauf wird vorbereitet, abgearbeitet, abgeschlossen und archiviert. Der
Archiv-Schreibschutz sitzt in genau einer Funktion und wird vor jeder Aenderung
an Kopfdaten, Schrittergebnis und Kommentar gerufen; abgeschlossen bleibt
aenderbar, archiviert nicht.

Die Abarbeitungsansicht speichert jeden Schritt einzeln, frischt sich alle zehn
Sekunden auf und pausiert im Hintergrund. Sie traegt in der Polling-Antwort
keine Befehle und laedt sich auch nicht von selbst neu, solange ein generiertes
Passwort auf der Seite steht: beides tauschte es dem Techniker zwischen Lesen
und Einfuegen aus.

Der unabhaengige Review fand zwei Blocker: ein Befehl konnte zwei verschiedene
Passwoerter tragen (Konto bekommt A, Benutzer erfaehrt B), und „nicht
zutreffend“ liess sich nicht zuruecknehmen, waehrend die Oberflaeche
behauptete, nichts sei gewaehlt. Beides behoben und in Tests festgehalten.

Closes #13

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-25 18:55:59 +02:00
co-authored by Claude Opus 5
parent eec5de404a
commit ed6e6b81eb
44 changed files with 7440 additions and 61 deletions
+63 -2
View File
@@ -15,11 +15,12 @@ als Unterpunkte mit Aufgabe und Dauer.
| #010 | M5 – Vorlagen-Editor | 2 h 10 min |
| #011 | M6 – Mitarbeiter, Abteilungen, Geräte | 2 h 15 min |
| #012 | M7 – Platzhalter, Namensregeln, Escaping | 2 h 30 min |
| | **Summe** | **13 h 45 min** |
| #013 | M8 – Läufe: Service und Abarbeitung | 3 h 05 min |
| | **Summe** | **16 h 50 min** |
| Meilenstein | Tatsächlich | Status |
|---|---|---|
| v0.1.0 | 13 h 45 min | in Arbeit |
| v0.1.0 | 16 h 50 min | in Arbeit |
---
@@ -505,3 +506,63 @@ als Unterpunkte mit Aufgabe und Dauer.
- #013 Läufe: Service und Abarbeitung — Lauf anlegen, abarbeiten, abschließen, archivieren, mit
der Abarbeitungsansicht am Handy.
---
## 2026-09-25 · Sitzung 9 · 15:40–18:45
**Issue:** #013 (M8)
**Version:** 0.1.0
### Erledigt
- `src/server/services/{laeufe,schrittergebnisse,kommentare}.ts` (Sub-Agent): anlegen, öffnen,
abschließen, archivieren, zurückholen, Schrittergebnisse, Abschnitts-Aktion, Kommentare
- `src/server/queries/laeufe.ts`, die Abarbeitungsansicht, der Start-Dialog, die Laufliste und der
Zustands-Endpunkt für die Aktualisierung alle zehn Sekunden
- Namensvorschläge aus den Regeln im Start-Dialog und „Mit AD-Konto verknüpfen“ am Lauf
- Unabhängiger Review: **zwei Blocker**, zwölf Befunde, acht Anmerkungen — alle abgearbeitet
- **879 Tests** (vorher 810) und **37 Ende-zu-Ende-Tests** grün
### Entscheidungen
- **Ein Lauf, ein Passwort je Seitenaufbau.** Vorher entstand je *Vorkommen* ein neues: ein
`New-ADUser` mit `-AccountPassword` und einer Zeile, die das Passwort mitteilt, trug zwei
verschiedene. Das Konto bekäme A, der Benutzer erführe B, und weil nichts gespeichert wird, wäre
A für immer weg. „Bei jeder Anzeige neu“ heißt jetzt: je Aufbau der Seite neu, innerhalb der
Seite überall dasselbe.
- **Abgeschlossen ist nicht archiviert.** „Abgeschlossen“ ist ein Arbeitszustand; Nachträge
passieren danach, und zwar oft. Würde schon der Abschluss sperren, bräuchte jede Kleinigkeit
einen Administrator — und Läufe würden schlicht nicht mehr abgeschlossen.
- **Das Polling trägt keine Befehle, und es lädt auch nicht von selbst neu**, solange ein Passwort
auf der Seite steht. Die erste Hälfte der Zusage war leicht, die zweite fiel erst beim
Nachdenken über `router.refresh()` auf: ein Neuaufbau tauscht das Passwort genauso aus.
- **`/api/` bekommt ohne Anmeldung 401, keine Weiterleitung.** Ein `fetch` folgt einer
Weiterleitung von sich aus und hält die Anmeldeseite für eine gültige Antwort; die
Aktualisierung hätte stundenlang weitergefragt.
- **Abschnitte klappen zu, wenn sie fertig sind — der Zustand liegt im Browser.** Aus den Daten
gerechnet klappte ein von Hand geöffneter Abschnitt beim nächsten Speichern wieder zu.
### Probleme
- **React baut das Formular erst nach dem erneuten Rendern zusammen.** Mein erster Versuch, den
Zustand am abschickenden Knopf mitzugeben, setzte im selben Klick die Vorauswahl um — und damit
den Wert des Knopfes. Angekommen ist wahlweise „offen“ oder gar kein Feld. Gefunden nicht durch
Lesen, sondern durch Nachstellen im gebauten Stand mit einer Ausgabe der `FormData`.
- **Der Review hat einen Blocker gefunden, den mein eigener Test festgeschrieben hatte:** „zwei
Vorkommen ergeben zwei Passwörter“ stand als Erwartung samt Begründung im Test. Die Begründung
war falsch, der Test hat sie zementiert.
- **Ein `h2` in einem `button` ist keine Überschrift mehr.** In einem Knopf sind alle Nachfahren
nur noch Beschriftung; der Abschnittskopf verlor damit seine Gliederung — aufgefallen, weil ein
Playwright-Test die Überschrift nicht mehr fand.
- **Ein `details` und React geraten vor der Hydrierung aneinander:** der Browser klappt auf, React
klappt gleich darauf zu. Jetzt ein Knopf mit `aria-expanded`, der vor der Hydrierung schlicht
nichts tut — wie jeder andere Knopf auf dieser Seite.
- **Fünfter Meilenstein in Folge mit Kommentaren, die mehr versprechen als der Code hält:** der
Titelvorschlag behauptete, der Start-Dialog zeige ihn; `startAuswahl` behauptete, der Dialog
nenne seine Grenze von 500 Einträgen. Beides stimmte nicht.
### Nächster Schritt
- #014 QR-Tags, Geräteseite, Etiketten und Scanner — der Einstieg, für den die ganze Anwendung
gebaut ist: Code scannen, Geräteseite öffnen, loslegen.