feat(laeufe): Vier-Augen-Freigabe (#040)
Prüfung / pruefung (push) Waiting to run
Prüfung / e2e (push) Blocked by required conditions

Verlangt eine Vorlagen-Version eine Freigabe, laesst sich ein Lauf erst
abschliessen, wenn ein Zweiter ihn freigegeben hat. Das braucht zweierlei, und
beides zusammen: das neue Recht `freigeben` (ADMIN und REDAKTEUR, nicht
TECHNIKER) und dass man nicht an dem Lauf gearbeitet hat.

Als gearbeitet zaehlt: angelegt, einen Schritt gesetzt oder abgeschlossen. Eine
Zuweisung allein nicht — waere die Regel hier strenger, blockierte sie kleine
Teams ohne Gewinn.

Auch ein Administrator kann sich nicht selbst freigeben, und das ist der ganze
Sinn. Die Pruefung sitzt in `hatDaranGearbeitet` an einer Stelle, wie
`laufMussVeraenderbarSein`; die wichtigste Haelfte — der Ersteller — haelt
zusaetzlich ein CHECK in der Datenbank.

Zurueckweisen verlangt eine Begruendung, setzt den Lauf auf IN_ARBEIT und nimmt
eine erteilte Freigabe zurueck. Kein fuenfter LaufStatus: ein neuer Enum-Wert
haette jeden Codepfad betroffen, der heute vier Faelle kennt.

Sobald jemand abzuschliessen versucht und die Freigabe fehlt, bekommen die
Freigabeberechtigten eine Mail — ein anderer Empfaengerkreis als bei jeder
anderen Meldung, und ohne die, die gearbeitet haben. Die Aufforderung entsteht
ausserhalb der Transaktion: innerhalb wuerde sie mit dem Fehler zurueckgerollt,
und dann wartet ein Lauf auf etwas, von dem niemand weiss. Ein partieller
Unique-Index haelt sie bei mehreren Versuchen auf einmal.

Die Pflicht haengt an der Version, nicht an der Vorlage: eine veroeffentlichte
Version ist unveraenderlich, ein laufender Lauf behaelt also seine Regel. Beim
Bearbeiten und Duplizieren wandert sie mit — das war die unmittelbare Lehre aus
#039, wo die tiefe Kopie zwei Felder stillschweigend verworfen hatte.

1526 Vitest-Tests (vorher 1496), 115 E2E-Ablaeufe gruen. Klickprobe am gebauten
Stand mit elf Pruefungen; drei rote Punkte darin waren meine eigenen
Testfehler, einer davon lehrreich: ein reload() direkt nach einer Server Action
trifft den Router-Cache von Next und zeigt kurz den alten Stand.

Closes #40

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-10-24 01:14:04 +02:00
co-authored by Claude Opus 5
parent a2330ef682
commit d30bb6d235
27 changed files with 1373 additions and 44 deletions
+52
View File
@@ -242,6 +242,58 @@ Knopf gesperrt und darunter steht, was fehlt.
Wird danach eine Änderung nachgetragen, die einen Pflichtschritt wieder offen lässt, nimmt sich der
Abschluss selbst zurück. Damit lügt „abgeschlossen“ nie.
## Vier-Augen-Freigabe
Manche Arbeiten soll nicht derselbe abschließen, der sie gemacht hat: ein Firewall-Rollout, ein
Restore-Test, das Löschen eines Kontos. Verlangt die Vorlage eine Freigabe, steht das oben am Lauf —
und **Lauf abschließen** wartet, bis jemand sie erteilt hat.
### Wer freigeben darf
Es braucht zweierlei, und beides zusammen:
1. das Recht **freigeben** — das haben `ADMIN` und `REDAKTEUR`, **nicht** `TECHNIKER`;
2. und man darf **nicht an dem Lauf gearbeitet** haben.
Als „gearbeitet“ zählt: ihn angelegt, einen Schritt gesetzt oder ihn abgeschlossen zu haben. Nur
**zugewiesen** zu sein zählt nicht — wer zugewiesen wurde und nichts getan hat, darf freigeben.
**Auch ein Administrator kann sich nicht selbst freigeben.** Das ist der ganze Sinn, und es ist eine
bewusste Härte: wer allein im Haus ist, kommt damit nicht weiter und braucht einen Zweiten mit dem
Recht. Dieselbe Regel hält auch die Datenbank fest, nicht nur die Anwendung.
### Freigeben oder zurückweisen
Oben am Lauf steht eine Karte mit einem Feld für die **Begründung** und zwei Knöpfen:
- **Freigeben** — die Begründung ist freiwillig. Danach lässt sich der Lauf abschließen.
- **Zurückweisen** — die Begründung ist **Pflicht**. Der Lauf geht zurück auf *in Arbeit*, ein
bereits erteilter Abschluss wird aufgehoben, und der Bearbeiter sieht die Begründung an derselben
Stelle. Ohne Begründung steht er vor derselben Frage wie vorher.
Eine Zurückweisung nimmt auch eine **erteilte** Freigabe zurück. Damit lässt sich ein Lauf, der
schon abgeschlossen war, in die Arbeit zurückholen — ohne `archivVerwalten`, solange er nicht
archiviert ist.
### Wer erfährt davon
Sobald jemand den Lauf abzuschließen versucht und die Freigabe fehlt, bekommen die
**Freigabeberechtigten** eine Mail — nicht der Zuständige, wie bei allen anderen Meldungen. Wer an
dem Lauf gearbeitet hat, bekommt sie nicht: er dürfte ohnehin nicht freigeben.
Das geht **einmal** hinaus, auch wenn jemand es mehrmals versucht. Nach einer Zurückweisung wird
nicht erneut gemahnt — der Zurückweisende weiß, dass er wartet.
### Einschalten
Das Häkchen steht im Editor beim **Veröffentlichen**: „Läufe dieser Version brauchen eine Freigabe
durch einen Zweiten“. Es gehört zur **Version**, nicht zur Vorlage — ein laufender Lauf kann seine
Regel also nicht unter den Füßen verlieren, und in der Versionsliste steht an jeder Fassung, ob sie
eine Freigabe verlangt.
Beim Bearbeiten wandert das Häkchen in den neuen Entwurf mit. Eine Vorlage, die eine Freigabe
verlangt, verliert sie also nicht durch eine Textkorrektur.
## Archivieren — das ist endgültig
**archivieren** fragt nach: „Nach dem Archivieren ändert sich an diesem Lauf nichts mehr — kein
+34
View File
@@ -423,6 +423,40 @@ dieselbe Stelle. Dass eine Schritt-Bedingung auf **dieselbe Version** zeigt,
haelt ein Trigger: nach dem Veroeffentlichen waere ein fremder Verweis nicht mehr
entscheidbar, und der Abschnitt erschiene stillschweigend immer.
## 5f-3. Die Vier-Augen-Freigabe: eine Stelle, zwei Netze
Verlangt eine Version eine Freigabe, haengt der Abschluss daran — und die Regel
dahinter ist **eine Funktion**: `hatDaranGearbeitet` in
`src/server/services/laeufe.ts`. Sie wird vor jeder Freigabe und vor jeder
Zurueckweisung gerufen, genau wie `laufMussVeraenderbarSein` vor jeder Aenderung
an einem Lauf. Zwei Stellen liefen auseinander, und die erste, die es vergisst,
hebt die Regel auf.
Gezaehlt wird dreierlei: wer den Lauf **angelegt** hat, wer ein
**Schrittergebnis** gesetzt hat, und wer ihn **abgeschlossen** hat. Der
Zustaendige gilt bewusst **nicht** als Bearbeiter — eine Zuweisung ist noch keine
Arbeit, und waere die Regel hier strenger, blockierte sie kleine Teams ohne
Gewinn.
**Zwei Netze, nicht eines.** Die wichtigste Haelfte steht als CHECK in der
Datenbank (`Lauf_freigabe_nicht_selbst`): der Ersteller gibt nicht frei, auch
dann nicht, wenn jemand an der Dienstschicht vorbei schreibt. Der Dienst prueft
strenger, weil er in zwei weitere Tabellen sehen kann; ein CHECK braeuchte dafuer
eine Unterabfrage.
**Das Recht `freigeben` hat nicht `TECHNIKER`**, und das ist eine Entscheidung
gegen Bequemlichkeit: sonst haengt die Vier-Augen-Regel daran, dass zufaellig ein
zweiter Techniker greifbar ist. Wer sie umgehen will, braucht ein Konto mit mehr
Rechten — und das steht im Protokoll.
**Die Aufforderung entsteht ausserhalb der Transaktion.** Der Abschlussversuch
scheitert mit `FreigabeFehlt`; `laufAbschliessen` faengt genau diesen Typ,
reiht die Meldung an die Freigabeberechtigten ein und wirft weiter. Innerhalb
der Transaktion wuerde sie mitsamt dem Fehler zurueckgerollt — und dann wartet
ein Lauf auf etwas, von dem niemand weiss. Ein partieller Unique-Index
(`Zustellung_freigabe_einmal`) sorgt dafuer, dass mehrere Versuche nicht mehrere
Mails ergeben.
## 5g. Der Verzeichnis-Abgleich: vier Schichten und eine Notbremse
Eine Verzeichnisquelle hat seit #028 eine **Art** — `LDAP`, `GRAPH` oder `SCIM` —,
+58 -2
View File
@@ -41,13 +41,14 @@ als Unterpunkte mit Aufgabe und Dauer.
| #038 | Die E2E-Abläufe laufen in keinem Tor | 1 h 35 min |
| #037 | Zwei Nachzügler aus der Durchsicht von Phase 2 | 1 h 50 min |
| #039 | M23 – Bedingte Schritte und Abschnitte | 5 h 20 min |
| | **Summe** | **79 h 15 min** |
| #040 | M24 – Vier-Augen-Freigabe | 3 h 30 min |
| | **Summe** | **82 h 45 min** |
| Meilenstein | Tatsächlich | Status |
|---|---|---|
| v0.1.0 | 35 h 20 min | veröffentlicht |
| v0.2.0 | 38 h 35 min | veröffentlicht |
| v0.3.0 | 5 h 20 min | in Arbeit |
| v0.3.0 | 8 h 50 min | in Arbeit |
---
@@ -1839,3 +1840,58 @@ Wirklichkeit nicht — die Prüflisten stehen in `docs/betrieb/entra-id.md` und
- **M24 (#040)** Vier-Augen-Freigabe. Der Abschluss wird dort ohnehin angefasst, und M25 braucht den
Freigeber für das Blatt.
---
## 2026-10-24 · Sitzung 26 · 22:30–01:40
**Issue:** #040 (M24)
**Version:** 0.3.0 (unveröffentlicht)
### Erledigt
- **Vier-Augen-Freigabe.** Neues Recht `freigeben`, Pflicht an der Version, Freigeben und
Zurückweisen samt Begründung, Aufforderung an die Berechtigten, Häkchen im Editor, Anzeige an der
Versionsliste.
- 1526 Vitest-Tests (vorher 1496), davon 22 neue in `tests/freigabe.test.ts`.
- Klickprobe am gebauten Stand: elf Prüfungen, alle grün.
### Entscheidungen
- **Das Recht `freigeben` hat nicht `TECHNIKER`.** Sonst hängt die Vier-Augen-Regel daran, dass
zufällig ein zweiter Techniker greifbar ist. Wer sie umgehen will, braucht ein Konto mit mehr
Rechten — und das steht im Protokoll.
- **Das Recht allein genügt nicht.** Wer an dem Lauf gearbeitet hat, gibt ihn nicht frei, auch nicht
als Administrator. Die Prüfung sitzt in `hatDaranGearbeitet`, an **einer** Stelle, wie
`laufMussVeraenderbarSein`; die wichtigste Hälfte (der Ersteller) hält zusätzlich ein CHECK.
- **Eine Zuweisung ist noch keine Arbeit.** Wer zugewiesen wurde und nichts getan hat, darf
freigeben — wäre die Regel hier strenger, blockierte sie kleine Teams ohne Gewinn.
- **Kein fünfter `LaufStatus`** für „zurückgewiesen“: der Lauf geht auf `IN_ARBEIT`, die Begründung
steht in einem Feld und im Protokoll. Ein neuer Enum-Wert hätte jeden Codepfad betroffen, der
heute vier Fälle kennt.
- **Die Pflicht hängt an der Version**, nicht an der Vorlage: eine veröffentlichte Version ist
unveränderlich, ein laufender Lauf behält also seine Regel.
### Probleme
- **Die Aufforderung muss außerhalb der Transaktion entstehen.** Innerhalb würde sie mit dem Fehler
zurückgerollt — und dann wartet ein Lauf auf etwas, von dem niemand weiß. Gelöst mit einem eigenen
Fehlertyp `FreigabeFehlt`, den `laufAbschliessen` außen fängt; dafür musste die Transaktion in
eine eigene Funktion. Ein Zeichenkettenvergleich auf die Meldung wäre eine Zusage über ihren
Wortlaut gewesen.
- **Drei rote Punkte in der Klickprobe waren meine eigenen Testfehler**, und einer ist lehrreich:
ein `reload()` direkt nach einer Server Action zeigt kurz den alten Stand, weil es den
Router-Cache von Next trifft. Die Action revalidiert den Pfad; ein Benutzer sieht das Ergebnis
**ohne** Neuladen. Nachgewiesen, bevor ich etwas geändert habe: in einem frischen Browser-Kontext
stand alles richtig da, und die Datenbank trug Freigeber, Zeitpunkt und Notiz.
Die beiden anderen: ein Selektor traf versteckten Protokolltext, und ein Suchmuster `/freigeb/`
traf nichts — in „Freigabe“ und „freigegeben“ kommt diese Zeichenfolge gar nicht vor. Dreimal
gesucht, bis es auffiel.
- **Die Freigabepflicht wäre bei „Bearbeiten“ verloren gegangen**, hätte #039 es mir nicht gerade
gezeigt: dort verwarf die tiefe Kopie `nurFuerAbteilungen` und `bedingung`. Diesmal von Anfang an
mitgenommen — und das ist der ganze Wert eines Befundes, der verstanden statt nur behoben wurde.
### Nächster Schritt
- **M25 (#041)** PDF-Übergabeprotokoll. Der Freigeber steht jetzt am Lauf und gehört auf das Blatt.
+83 -24
View File
@@ -1,10 +1,10 @@
# #040 M24 – Vier-Augen-Freigabe
**Status:** offen
**Status:** erledigt
**Im Tracker:** –
**Meilenstein:** v0.3.0
**Labels:** phase-3, backend, frontend
**Geschätzt:** 8 h **Tatsächlich:** –
**Geschätzt:** 8 h **Tatsächlich:** 3 h 30 min
## Ziel
@@ -17,52 +17,111 @@ ein **Zweiter** ab — nachweisbar im Protokoll.
## Zu entscheiden
- [ ] **Freigabe am Lauf oder am Schritt?** Empfehlung: **am Lauf**, gesetzt von der Vorlage.
- [x] **Freigabe am Lauf oder am Schritt?** Empfehlung: **am Lauf**, gesetzt von der Vorlage.
Am Schritt wäre feiner und verführt zu Checklisten, in denen an fünf Stellen jemand warten
muss; am Lauf ist es eine Aussage über die Arbeit als Ganzes und erklärt sich von selbst.
Schritt-Freigaben bleiben möglich, wenn sich der Bedarf zeigt — `VorlagenSchritt.konfig` ist
ein Json.
- [ ] **Wer darf freigeben?** Empfehlung: ein eigenes Recht `freigeben`, standardmäßig bei `ADMIN`
- [x] **Wer darf freigeben?** Empfehlung: ein eigenes Recht `freigeben`, standardmäßig bei `ADMIN`
und `REDAKTEUR` — **nicht** bei `TECHNIKER`. Begründung: die Vier-Augen-Regel soll nicht
davon abhängen, dass zufällig ein zweiter Techniker greifbar ist; und wer sie umgehen will,
braucht dann ein zweites Konto mit mehr Rechten, was im Protokoll steht.
- [ ] **Darf der Bearbeiter sich selbst freigeben?** **Nein**, und das ist der ganze Sinn. Geprüft
- [x] **Darf der Bearbeiter sich selbst freigeben?** **Nein**, und das ist der ganze Sinn. Geprüft
wird gegen `Schrittergebnis.aktualisiertVonId` **und** `Lauf.erstelltVonId`: wer irgendetwas
daran getan hat, gibt nicht frei. Ein `ADMIN`, der allein im Haus ist, kommt damit nicht
weiter — das ist eine bewusste Härte, und die Anleitung sagt es.
- [ ] **Was, wenn die Freigabe verweigert wird?** Empfehlung: ein Zustand „zurückgewiesen“ mit
- [x] **Was, wenn die Freigabe verweigert wird?** Empfehlung: ein Zustand „zurückgewiesen“ mit
Pflichtnotiz. Der Lauf geht zurück auf `IN_ARBEIT`, die Notiz steht im Protokoll und an der
Abarbeitungsansicht. Kein eigener `LaufStatus` — das wäre eine Änderung an einem Enum, das
vier Jahre halten soll; es genügt ein Feld plus Protokolleintrag.
## Aufgaben
- [ ] Migration: `freigabePflicht Boolean` an `VorlagenVersion`, dazu `freigegebenVonId`,
- [x] Migration: `freigabePflicht Boolean` an `VorlagenVersion`, dazu `freigegebenVonId`,
`freigegebenAm` und `freigabeNotiz` am `Lauf`; CHECK, dass `freigegebenVonId` und
`freigegebenAm` zusammen gesetzt sind (wie bei `abgeschlossenAm`)
- [ ] CHECK: `freigegebenVonId` ist **nicht** `erstelltVonId` — die Regel gehört in die Datenbank,
- [x] CHECK: `freigegebenVonId` ist **nicht** `erstelltVonId` — die Regel gehört in die Datenbank,
nicht nur in den Dienst (CLAUDE.md)
- [ ] Recht `freigeben` in `RECHTE`, Rollenmatrix-Test erweitern
- [ ] Dienst: `laufFreigeben(laufId, benutzer, notiz?)` und `laufZurueckweisen(laufId, benutzer,
- [x] Recht `freigeben` in `RECHTE`, Rollenmatrix-Test erweitern
- [x] Dienst: `laufFreigeben(laufId, benutzer, notiz?)` und `laufZurueckweisen(laufId, benutzer,
notiz)`; Abschluss verlangt die Freigabe, wenn die Version sie fordert
- [ ] Die Prüfung „wer hat daran gearbeitet“ an **einer** Stelle, wie `laufMussVeraenderbarSein`
- [ ] Benachrichtigung: ein neuer `Meldeanlass` `LAUF_FREIGABE_OFFEN` an die Rollen mit dem Recht —
- [x] Die Prüfung „wer hat daran gearbeitet“ an **einer** Stelle, wie `laufMussVeraenderbarSein`
- [x] Benachrichtigung: ein neuer `Meldeanlass` `LAUF_FREIGABE_OFFEN` an die Rollen mit dem Recht —
sonst wartet ein Lauf, von dem niemand weiß
- [ ] Oberfläche: Hinweis am Lauf („wartet auf Freigabe durch einen Zweiten“), Knöpfe für Freigeben
- [x] Oberfläche: Hinweis am Lauf („wartet auf Freigabe durch einen Zweiten“), Knöpfe für Freigeben
und Zurückweisen, Notizfeld; die Übersicht bekommt einen Filter „wartet auf meine Freigabe“
- [ ] Editor: Häkchen „dieser Lauf braucht eine Freigabe“ an der Version
- [ ] Druckansicht und PDF nennen Freigeber und Zeitpunkt
- [ ] Anleitung: Kapitel 02 (Läufe abarbeiten) und 04 (Vorlagen), mit dem Hinweis, dass ein
- [x] Editor: Häkchen „dieser Lauf braucht eine Freigabe“ an der Version
- [x] Druckansicht und PDF nennen Freigeber und Zeitpunkt
- [x] Anleitung: Kapitel 02 (Läufe abarbeiten) und 04 (Vorlagen), mit dem Hinweis, dass ein
Einzelkämpfer sich nicht selbst freigeben kann
## Akzeptanzkriterien
- [ ] Test: ein Lauf mit Freigabepflicht lässt sich nicht abschließen, solange keine Freigabe steht
- [ ] Test: der Bearbeiter kann **nicht** freigeben — auch nicht als `ADMIN`
- [ ] Test: die Datenbank weist es ebenfalls ab (CHECK), nicht nur der Dienst
- [ ] Test: eine Rolle ohne `freigeben` wird abgewiesen, über jede Server Action
- [ ] Test: Zurückweisen verlangt eine Notiz und setzt den Lauf auf `IN_ARBEIT`
- [ ] Test: die Meldung geht an die Rollen mit dem Recht und nicht an alle
- [ ] Test: ein Lauf **ohne** Freigabepflicht verhält sich unverändert — bestehende Läufe und
- [x] Test: ein Lauf mit Freigabepflicht lässt sich nicht abschließen, solange keine Freigabe steht
- [x] Test: der Bearbeiter kann **nicht** freigeben — auch nicht als `ADMIN`
- [x] Test: die Datenbank weist es ebenfalls ab (CHECK), nicht nur der Dienst
- [x] Test: eine Rolle ohne `freigeben` wird abgewiesen, über jede Server Action
- [x] Test: Zurückweisen verlangt eine Notiz und setzt den Lauf auf `IN_ARBEIT`
- [x] Test: die Meldung geht an die Rollen mit dem Recht und nicht an alle
- [x] Test: ein Lauf **ohne** Freigabepflicht verhält sich unverändert — bestehende Läufe und
Vorlagen merken nichts
- [ ] Am Handy kein horizontales Scrollen
- [x] Am Handy kein horizontales Scrollen
## Beim Umsetzen dazugekommen
- **Die vier Entscheidungen sind so gefallen wie empfohlen.** Zwei haben sich im Code als besonders
tragend erwiesen:
- **Die Freigabe hängt an der Version, nicht an der Vorlage.** Eine veröffentlichte Version ist
unveränderlich — ein laufender Lauf kann seine Regel damit nicht unter den Füßen verlieren. In
der Versionsliste steht an jeder Fassung, ob sie eine Freigabe verlangt.
- **Kein fünfter `LaufStatus` für „zurückgewiesen“.** Der Lauf geht auf `IN_ARBEIT`, die
Begründung steht in `freigabeNotiz` und im Protokoll. Ein neuer Enum-Wert hätte jeden Codepfad
betroffen, der heute vier Fälle kennt.
- **Als „gearbeitet“ zählt dreierlei** — angelegt, ein Schrittergebnis gesetzt, abgeschlossen.
Der **Zuständige** gilt bewusst nicht als Bearbeiter: eine Zuweisung ist noch keine Arbeit, und
wäre die Regel hier strenger, blockierte sie kleine Teams ohne Gewinn. Die Prüfung sitzt in
`hatDaranGearbeitet`, an einer Stelle — wie `laufMussVeraenderbarSein`.
- **Die Aufforderung entsteht außerhalb der Transaktion**, und das war die einzige knifflige Stelle:
der Abschlussversuch scheitert mit einem eigenen Fehlertyp `FreigabeFehlt`, den
`laufAbschliessen` außen fängt, um die Meldung einzureihen und dann weiterzuwerfen. Innerhalb
würde sie mit dem Fehler zurückgerollt — und dann wartet ein Lauf auf etwas, von dem niemand
weiß. Dafür musste die Transaktion in eine eigene Funktion (`abschlussVersuchen`).
- **Ein anderer Empfängerkreis als bei jeder anderen Meldung**: nicht der Zuständige, sondern jeder
mit dem Recht `freigeben` — ohne die, die gearbeitet haben. Eine Aufforderung zu etwas, das der
Dienst abweist, ist schlimmer als keine.
- **Ein partieller Unique-Index** (`Zustellung_freigabe_einmal`) hält die Mahnung bei einem Lauf
und Empfänger auf einmal. Ein Techniker versucht es mehrmals; ohne den Index wäre jede Mail für
sich korrekt und in Summe eine Belästigung — derselbe Fall wie „überfällig“ in #034, nur
schneller erreicht.
- **Die Freigabepflicht wandert bei „Bearbeiten“ und „Duplizieren“ mit.** Das war kein Zufall,
sondern die unmittelbare Lehre aus #039: dort hatte die tiefe Kopie `nurFuerAbteilungen` und
`bedingung` stillschweigend verworfen. Eine Vorlage soll ihre Freigabepflicht nicht durch eine
Textkorrektur verlieren.
## Was die Klickprobe gezeigt hat
Elf Prüfungen am gebauten Stand, alle grün — von „Freigabe-Karte sichtbar“ über „Zurückweisen
verlangt eine Begründung“ bis „Häkchen aus der Vorversion übernommen“ und 390 px.
**Drei rote Punkte waren meine eigenen Testfehler**, und der dritte ist festzuhalten:
1. Ein Selektor traf den **versteckten** Protokolltext „Lauf abgeschlossen“ statt der Erfolgsmeldung.
2. Ein Suchmuster `/freigeb/` traf nichts: in „Freigabe“ und „freigegeben“ kommt diese Zeichenfolge
gar nicht vor. Dreimal gesucht, bis es auffiel.
3. **Ein `reload()` direkt nach einer Server Action zeigt kurz den alten Stand.** Die Action
revalidiert den Pfad, und der Benutzer sieht das Ergebnis ohne Neuladen — ein Reload im selben
Kontext trifft dagegen den Router-Cache von Next. Das ist Next und kein Fehler dieser Anwendung,
aber es ist auch nicht, was ein Mensch tut. Die Probe prüft jetzt das echte Verhalten.
Nachgewiesen, bevor etwas geändert wurde: in einem frischen Browser-Kontext stand alles richtig
da, und die Datenbank trug Freigeber, Zeitpunkt und Notiz.
## Was offen bleibt
- **Freigaben an einzelnen Schritten** gibt es nicht, bewusst. Am Lauf ist es eine Aussage über die
Arbeit als Ganzes und erklärt sich von selbst; am Schritt verführte es zu Checklisten, in denen an
fünf Stellen jemand warten muss. `VorlagenSchritt.konfig` ist ein Json — wenn sich der Bedarf
zeigt, ist der Platz da.
- **Ein Einzelkämpfer kommt nicht weiter**: wer allein ist und an dem Lauf gearbeitet hat, kann ihn
nicht freigeben, auch nicht als Administrator. Das ist die Härte, die die Regel ausmacht, und die
Anleitung sagt es ausdrücklich.
+2 -2
View File
@@ -44,7 +44,7 @@ Diese Dateien sind die Quelle; `pnpm issues:sync` spiegelt sie in den Gitea-Trac
| #037 | [Zwei Nachzügler aus der Durchsicht von Phase 2](037-anhaenge-lesemodell.md) | erledigt | v0.2.0 | 2 h | 1 h 50 min |
| #038 | [Die E2E-Abläufe laufen in keinem Tor und waren monatelang rot](038-e2e-im-tor.md) | erledigt | v0.2.0 | 3 h | 1 h 35 min |
| #039 | [M23 – Bedingte Schritte und Abschnitte](039-bedingte-schritte.md) | erledigt | v0.3.0 | 12 h | 5 h 20 min |
| #040 | [M24 – Vier-Augen-Freigabe](040-vier-augen-freigabe.md) | offen | v0.3.0 | 8 h | – |
| #040 | [M24 – Vier-Augen-Freigabe](040-vier-augen-freigabe.md) | erledigt | v0.3.0 | 8 h | 3 h 30 min |
| #041 | [M25 – PDF-Übergabeprotokoll mit Unterschrift](041-pdf-uebergabeprotokoll.md) | offen | v0.3.0 | 8 h | – |
| #042 | [M26 – Weitere Schritt-Typen](042-weitere-schritt-typen.md) | offen | v0.3.0 | 6 h | – |
| | **Summe** | | | **272 h** | **79 h 15 min** |
| | **Summe** | | | **272 h** | **82 h 45 min** |