Einen Schlüssel zu tauschen soll keinen Ausfall riskieren: Der Nachfolger übernimmt alle aktiven Zuweisungen, wird ausgerollt und per Verbindungstest geprüft – erst wenn alle Tests seit dem letzten Ausrollen grün sind, entfernt der Widerruf aus #024 den alten Schlüssel, der dann als ROTIERT endet. Private Keys bekommen einen neuen Pfad (-rJJJJMMTT) bei gleichem Alias. Damit ssh den neuen nimmt, schreibt privat.ts je Alias nur noch einen config-Eintrag; die jüngste Zuweisung gewinnt. Der Worker setzt vorgaengerId schon beim Erzeugen, so ist die Kette auch nach einem Abbruch vollständig und die Schrittfolge wiederaufnehmbar. Personen-Keys ohne Private Key in sshkv bekommen nur einen Hinweis: dafür braucht es einen neuen Public Key von der Person. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
38 lines
1.6 KiB
TypeScript
38 lines
1.6 KiB
TypeScript
/**
|
||
* Namens- und Pfadregeln der gefuehrten Rotation (#023). Rein, damit testbar.
|
||
*/
|
||
|
||
const NAME_SUFFIX = /\s*\(rotiert \d{2}\.\d{2}\.\d{4}\)$/;
|
||
const PFAD_SUFFIX = /-r\d{8}(?:-\d+)?$/;
|
||
|
||
/** TT.MM.JJJJ und JJJJMMTT nach dem Kalender in Berlin. */
|
||
export function rotationsDatum(jetzt: Date = new Date()): { anzeige: string; kompakt: string } {
|
||
const [jahr, monat, tag] = new Intl.DateTimeFormat("en-CA", { timeZone: "Europe/Berlin" })
|
||
.format(jetzt)
|
||
.split("-");
|
||
return { anzeige: `${tag}.${monat}.${jahr}`, kompakt: `${jahr}${monat}${tag}` };
|
||
}
|
||
|
||
/**
|
||
* „Backup A → B (rotiert 12.10.2026)“ – ein frueheres Rotations-Suffix wird ersetzt, damit
|
||
* die Namen bei jeder Rotation nicht laenger werden.
|
||
*/
|
||
export function rotationsName(name: string, datum: string, maxLaenge = 200): string {
|
||
const suffix = ` (rotiert ${datum})`;
|
||
const basis = name.replace(NAME_SUFFIX, "").trim();
|
||
return `${basis.slice(0, Math.max(1, maxLaenge - suffix.length))}${suffix}`;
|
||
}
|
||
|
||
/**
|
||
* Neuer Pfad fuer den Private Key des Nachfolgers: gleicher Name mit `-rJJJJMMTT`. Ein alter
|
||
* Suffix wird ersetzt; ist der Pfad (auch durch eine fruehere, entfernte Zuweisung) belegt,
|
||
* kommt eine laufende Nummer dazu. Zwei Dateien nebeneinander sind gewollt: bis der Nachfolger
|
||
* getestet ist, bleibt der alte Schluessel benutzbar.
|
||
*/
|
||
export function rotationsPfad(pfad: string, datumKompakt: string, belegt: ReadonlySet<string>): string {
|
||
const basis = pfad.replace(PFAD_SUFFIX, "");
|
||
let kandidat = `${basis}-r${datumKompakt}`;
|
||
for (let nummer = 2; belegt.has(kandidat); nummer += 1) kandidat = `${basis}-r${datumKompakt}-${nummer}`;
|
||
return kandidat;
|
||
}
|