Bisher war vorgaengerId eindeutig: nach einer abgebrochenen Rotation passte kein zweiter Nachfolger in die Kette, und der Schlüssel ließ sich nur über Neuanlage, Zuweisen und Widerruf ersetzen. Jetzt ist die Relation 1:n. Ein partieller Index erlaubt je Vorgänger nur einen Nachfolger, der weder widerrufen ist noch gerade widerrufen wird. Maßgeblich ist der jüngste. Erst wenn der Abbruch abgeschlossen ist, beginnt die Rotation wieder bei Schritt 1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.5 KiB
3.5 KiB
#032 Nacharbeiten aus Phase 4/5
Status: erledigt Meilenstein: v1.0.0 Labels: test, chore Geschätzt: 2 h Tatsächlich: 0,75 h
Ziel
Kleinere offene Punkte aus den Berichten der Phasen 4 und 5 erledigen.
Aufgaben
- Massenwiderruf im Browser testen (E2E mit frischer Bestätigung über den Mock-OIDC)
- Laufende Rotation abbrechen können (Nachfolger widerrufen, Vorgänger wieder aktiv)
- Protokoll-IDs ohne Zweierschritte (Spalten-Default und Trigger ziehen beide
nextval) - „Zum Dry-Run“ aus der Zuweisungsmatrix direkt zur Dry-Run-Karte springen (Anker)
Akzeptanzkriterien
- Alle Suiten grün
Abhängigkeiten
#023, #024, #025, #027
Notizen / Entscheidungen
- Massenwiderruf: Der neue E2E-Test (
widerruf.spec.ts) fand einen echten Fehler: Die Seite/schluessel/widerruffilterte?id=mit/^[a-z0-9]{1,64}$/. Vom Worker erzeugte Schlüssel tragen eine UUID mit Bindestrichen – jeder erzeugte Schlüssel fiel still heraus („Keine Schlüssel gewählt“). JetztidsAusSuchparameterinsrc/lib/schluessel.ts(mit Test). Außerdem nannte der Hinweis nach verweigerter Bestätigung den falschen Knopf („Widerruf vorbereiten“ statt „2 Schlüssel widerrufen“).datenbank()undoidcBestaetigen()liegen jetzt intests/e2e/hilfen.ts. - Rotation abbrechen: kein neues Feld. Abbrechen = Widerruf des Nachfolgers über den Ablauf aus #024
(Dry-Run, er kann schon ausgerollt sein); ein Nachfolger im Widerruf bzw. widerrufen ist die
abgebrochene Rotation (
rotationAbgebrochen).vorgaengerIdbleibt für die Historie, der Abbruch steht alsschluessel.rotation.abgebrochenim Protokoll – in derselben Transaktion wie das Vormerken (widerrufEinleitennimmt dafür optionalzusaetzlichan). Der alte Schlüssel bleibt unverändert; bei gleichem Alias zeigt die config nach dem Anwenden wieder auf die alte Datei (nur verbleibende Zuweisungen landen im Block). - Abbrechen geht nur, solange der alte Schlüssel noch nicht entfernt wird (Schritt 5) – sonst wären am Ende beide halb entfernt. Auf dem Nachfolger ersetzt „Rotation abbrechen“ den normalen „Widerrufen“-Knopf, damit der Abbruch immer im Protokoll steht.
widerrufAbschliessensetztROTIERTnur noch bei einem aktiven Nachfolger, der nicht selbst im Widerruf ist; die Seite schreibt „Ersetzt durch …“ nur beiROTIERT.- Kein zweiter Nachfolger:
vorgaengerIdist eindeutig (1:1-Relation). Nach einem Abbruch lässt sich derselbe Schlüssel deshalb nicht erneut über sshkv rotieren; Seite und Fehlermeldung sagen das (neuen Schlüssel anlegen, zuweisen, alten widerrufen). Eine erneute Rotation bräuchte eine 1:n-Relation mit eindeutigem Teilindex „ein nicht widerrufener Nachfolger je Vorgänger“. → Behoben in #033 (partieller Index statt 1:1). - Protokoll-IDs: Migration
20261012173000_protokoll_id_lueckenlossetzt den Spalten-Default auf den Platzhalter0(Prisma:@default(0),createohne ID geht weiter); die ID zieht nur noch der Trigger unter der Advisory-Sperre aus der weiterhin zugeordneten Sequenz. Bestehende Zeilen bleiben unverändert (die ID steckt in der Hash-Eingabe), alte Lücken bleiben also stehen. Eine mitgegebene ID überschreibt der Trigger weiterhin. - Anker: Die Dry-Run-Karte trägt
id="dry-run"(Kartenimmt eine optionaleid) undscroll-mt-20wegen der festen Kopfleiste der schmalen Ansicht; „Zum Dry-Run“ zeigt auf/schluessel/<id>#dry-run.