feat(ausrollen): Public Keys mit Trockenlauf und Backup ausrollen (#016)

Zuweisungen von Public Keys an Hosts oder Hostgruppen, ein Trockenlauf
mit Diff je Ziel und das Ausrollen genau dieses Plans. Hat sich die
Datei oder das Soll seit dem Trockenlauf geaendert, bricht das Ziel
ab: es wird nie etwas anderes geschrieben, als jemand gesehen hat.

Auf dem Host geschieht alles als Zielbenutzer, mit Sicherung, Temp-
Datei, mv und 0700/0600; der Hash wird dort erneut geprueft. Der
Deployment-Key gehoert immer zum Soll des Anmeldebenutzers.

Integrationstests gegen echtes sshd, die Oberflaechenbausteine folgen
mit der Schluesselseite aus #012.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 10:17:35 +02:00
co-authored by Claude Opus 5.5
parent 1358055e40
commit f66d87ad11
13 changed files with 1339 additions and 3 deletions
+22
View File
@@ -0,0 +1,22 @@
import { prisma } from "@/lib/db";
/** Auswahl fuer „Public Key ausrollen auf …“ (#016): Hosts mit Bootstrap und Hostgruppen. */
export async function zielAuswahl() {
const [hosts, gruppen] = await Promise.all([
prisma.host.findMany({
where: { archiviertAm: null },
select: { id: true, name: true, bootstrapAm: true },
orderBy: { name: "asc" },
}),
prisma.hostgruppe.findMany({
select: { id: true, name: true, _count: { select: { mitglieder: true } } },
orderBy: { name: "asc" },
}),
]);
return {
hosts: hosts.map((h) => ({ id: h.id, name: h.name, bereit: h.bootstrapAm !== null })),
gruppen: gruppen.map((g) => ({ id: g.id, name: g.name, mitglieder: g._count.mitglieder })),
};
}
export type ZielAuswahl = Awaited<ReturnType<typeof zielAuswahl>>;