Fünf Schritte: Neuer Schlüssel → Zuweisungen übernehmen → Dry-Run & Ausrollen → Verbindungstests →
Alten widerrufen. Der aktuelle Schritt wird aus der Datenbank errechnet (rotationsStand), deshalb
lässt sich die Rotation jederzeit neu laden und fortsetzen; jeder Schritt ist idempotent.
Kette sofort: Der Worker setzt vorgaengerId schon beim Erzeugen (neues Feld in der
Vorgangs-Eingabe) – auch ein abgebrochener Browser hinterlässt keinen verwaisten Schlüssel. vorgaengerId ist eindeutig: zwei gleichzeitige Rotationen scheitern verständlich.
Gleicher Alias, zwei Zuweisungen:privat.ts schreibt je Alias genau einen config-Eintrag, die
jüngste Zuweisung gewinnt (an der Position der ersten). So zeigt ssh <alias> nach dem Ausrollen auf
die neue Datei, während die alte bis zum Widerruf daneben liegt.
Neuer Pfad:<alter Pfad ohne -rJJJJMMTT>-rJJJJMMTT, bei Kollision mit laufender Nummer –
auch entfernte Zuweisungen belegen einen Pfad (eindeutiger Index über alle Zustände).
Grün heißt aktuell: Der alte Schlüssel wird nur widerrufen, wenn für jede Private-Zuweisung mit
Alias ein erfolgreicher VERBINDUNGSTEST nach dem letzten Ausrollen vorliegt (Server prüft das).
Ohne Private-Zuweisung mit Alias entfällt der Test.
Abschluss: Widerruf aus #024 ohne Zielkonten (der Nachfolger nutzt sie weiter); ein aktiver
Nachfolger macht aus WIDERRUFEN den Status ROTIERT.
Ablaufdatum: Der Nachfolger erbt es nur, wenn es in der Zukunft liegt. Eine Passphrase wird nicht
übernommen (sshkv erzeugt ohne).
Rechte: schluesselVerwalten + publicKeyAusrollen, bei Private-Zuweisungen privateKeyAusrollen.
Deployment-Key: eigene Rotation (später).
Quelle: docs/issues/023-rotation.md – dort wird dieses Issue gepflegt.
## Ziel
Neuer Schlüssel an allen Verwendungen, Test, alter entfernt.
## Aufgaben
- [x] „Rotieren“ auf der Schlüsselseite, Schrittfolge `/schluessel/[id]/rotieren` (wiederaufnehmbar)
- [x] Neuer Schlüssel gleichen Typs, Name „… (rotiert TT.MM.JJJJ)“, `vorgaengerId` = alter
- [x] Zuweisungen übernehmen: Public gleiche Ziele/Optionen, Private gleicher Host/Benutzer/Alias mit neuem Pfad
- [x] Dry-Run + Ausrollen, Verbindungstests, erst dann den alten widerrufen (#024) → `ROTIERT`
- [x] Personen-Key ohne Private Key: nur Hinweis „neuer Public Key nötig“
- [x] Rotationskette auf der Schlüsselseite (Vorgänger/Nachfolger verlinkt)
## Akzeptanzkriterien
- [x] DB-Tests: Schritte, Reihenfolge, Rechte, Namen/Pfade (`tests/rotation.test.ts`)
- [x] Integrationstest: neuer Schlüssel funktioniert, alter von beiden Hosts weg, `ssh <alias>` geht weiter
- [x] E2E im Browser (`tests/e2e/rotation.spec.ts`), Screenshot `rotation-desktop.png`
## Abhängigkeiten
#020, #024
## Notizen / Entscheidungen
- **Fünf Schritte:** Neuer Schlüssel → Zuweisungen übernehmen → Dry-Run & Ausrollen → Verbindungstests →
Alten widerrufen. Der aktuelle Schritt wird aus der Datenbank errechnet (`rotationsStand`), deshalb
lässt sich die Rotation jederzeit neu laden und fortsetzen; jeder Schritt ist idempotent.
- **Kette sofort:** Der Worker setzt `vorgaengerId` schon beim Erzeugen (neues Feld in der
Vorgangs-Eingabe) – auch ein abgebrochener Browser hinterlässt keinen verwaisten Schlüssel.
`vorgaengerId` ist eindeutig: zwei gleichzeitige Rotationen scheitern verständlich.
- **Gleicher Alias, zwei Zuweisungen:** `privat.ts` schreibt je Alias genau einen config-Eintrag, die
jüngste Zuweisung gewinnt (an der Position der ersten). So zeigt `ssh <alias>` nach dem Ausrollen auf
die neue Datei, während die alte bis zum Widerruf daneben liegt.
- **Neuer Pfad:** `<alter Pfad ohne -rJJJJMMTT>-rJJJJMMTT`, bei Kollision mit laufender Nummer –
auch entfernte Zuweisungen belegen einen Pfad (eindeutiger Index über alle Zustände).
- **Grün heißt aktuell:** Der alte Schlüssel wird nur widerrufen, wenn für jede Private-Zuweisung mit
Alias ein erfolgreicher `VERBINDUNGSTEST` nach dem letzten Ausrollen vorliegt (Server prüft das).
Ohne Private-Zuweisung mit Alias entfällt der Test.
- **Abschluss:** Widerruf aus #024 ohne Zielkonten (der Nachfolger nutzt sie weiter); ein aktiver
Nachfolger macht aus `WIDERRUFEN` den Status `ROTIERT`.
- Ablaufdatum: Der Nachfolger erbt es nur, wenn es in der Zukunft liegt. Eine Passphrase wird nicht
übernommen (sshkv erzeugt ohne).
- Rechte: `schluesselVerwalten` + `publicKeyAusrollen`, bei Private-Zuweisungen `privateKeyAusrollen`.
Deployment-Key: eigene Rotation (später).
---
Quelle: `docs/issues/023-rotation.md` – dort wird dieses Issue gepflegt.
florian.wilde
added this to the v0.4.0 milestone 2026-10-12 15:12:45 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Ziel
Neuer Schlüssel an allen Verwendungen, Test, alter entfernt.
Aufgaben
/schluessel/[id]/rotieren(wiederaufnehmbar)vorgaengerId= alterROTIERTAkzeptanzkriterien
tests/rotation.test.ts)ssh <alias>geht weitertests/e2e/rotation.spec.ts), Screenshotrotation-desktop.pngAbhängigkeiten
#020, #024
Notizen / Entscheidungen
Alten widerrufen. Der aktuelle Schritt wird aus der Datenbank errechnet (
rotationsStand), deshalblässt sich die Rotation jederzeit neu laden und fortsetzen; jeder Schritt ist idempotent.
vorgaengerIdschon beim Erzeugen (neues Feld in derVorgangs-Eingabe) – auch ein abgebrochener Browser hinterlässt keinen verwaisten Schlüssel.
vorgaengerIdist eindeutig: zwei gleichzeitige Rotationen scheitern verständlich.privat.tsschreibt je Alias genau einen config-Eintrag, diejüngste Zuweisung gewinnt (an der Position der ersten). So zeigt
ssh <alias>nach dem Ausrollen aufdie neue Datei, während die alte bis zum Widerruf daneben liegt.
<alter Pfad ohne -rJJJJMMTT>-rJJJJMMTT, bei Kollision mit laufender Nummer –auch entfernte Zuweisungen belegen einen Pfad (eindeutiger Index über alle Zustände).
Alias ein erfolgreicher
VERBINDUNGSTESTnach dem letzten Ausrollen vorliegt (Server prüft das).Ohne Private-Zuweisung mit Alias entfällt der Test.
Nachfolger macht aus
WIDERRUFENden StatusROTIERT.übernommen (sshkv erzeugt ohne).
schluesselVerwalten+publicKeyAusrollen, bei Private-ZuweisungenprivateKeyAusrollen.Deployment-Key: eigene Rotation (später).
Quelle:
docs/issues/023-rotation.md– dort wird dieses Issue gepflegt.