Phase 11: Freigabereife
Pruefung / pruefung (pull_request) Canceled after 0s
Pruefung / oberflaeche (pull_request) Canceled after 0s

Kein Modul, sondern die drei Software-Voraussetzungen fuer 1.0.0:
Auskunft nach Art. 15 DSGVO, ein geprueftes Sicherungskonzept und eine
Pipeline.

Das Auskunftsrecht war ein Versprechen ohne Umsetzung: `person.export`
stand seit Phase 0 im Katalog und war dem Kommandanten zugewiesen,
implementiert war nichts. Ohne Auskunftsseite ist ein Loeschkonzept nicht
abnehmbar. Jetzt sammelt FLORIAN dreizehn Abschnitte ueber eine Person,
mit dem Zweck ueber jedem - Art. 15 verlangt nicht nur die Daten, sondern
auch Zwecke und Rechte, und eine blosse Liste erfuellt die Pflicht nicht.
Ein Durchgang liefert Anzeige, PDF und JSON nach Art. 20.

Die Trennlinie ist "ueber mich" gegen "von mir": was ueber die Person
gespeichert ist, steht vollstaendig drin, auch das Unangenehme. Was sie
getan hat, steht als Zahl drin - die Pruefprotokolle gehoeren zum
Nachweisbestand der Wehr, und vollstaendig ausgeliefert kaeme jeder ueber
eine Selbstauskunft an die Geraeteakten.

Die Rueckspielprobe hat sich sofort bezahlt gemacht: der erste Versuch
lief sauber durch und hatte dabei saemtliche Unveraenderlichkeitsgarantien
der Datenbank entfernt. Die Vorgabeprivilegierung aus dem Init-Skript gibt
jeder von pg_restore neu angelegten Tabelle wieder alle Rechte, und GRANT
kann nur hinzufuegen. Die Anwendungsrolle durfte danach das Audit-Log
aendern, Wiki-Fassungen loeschen, Kiosk-Vorgaenge umschreiben - und nichts
haette darauf hingewiesen. Gefunden haben es vier Datenbanktests
unmittelbar nach der Probe, also genau die Probe, wegen der 1.0.0 sie
verlangt.

Die Pipeline ist geschrieben, aber NICHT erprobt: in Gitea ist kein
act_runner registriert. Das steht so im README und im Devlog, damit sich
niemand auf eine Pruefung verlaesst, die nicht stattfindet.

601 Unit-Tests gruen; Sicherung und Wiederherstellung einmal vollstaendig
durchgefuehrt und die Tests danach erneut gruen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-05 17:16:08 +02:00
co-authored by Claude Opus 5
parent 91742a0dd7
commit 9156dcc144
21 changed files with 2495 additions and 8 deletions
+51
View File
@@ -0,0 +1,51 @@
/**
* Die Verbindungsangaben für `pg_dump` und `pg_restore`.
*
* Eigene Datei, weil beide Skripte sie brauchen — und weil ein falsch
* zerlegter Zugang der unangenehmste Fehler in einem Sicherungsskript wäre:
* es liefe durch, schriebe eine Datei, und die enthielte die falsche
* Datenbank. Auffallen würde es beim Zurückspielen, also genau dann, wenn man
* die Sicherung braucht.
*/
export interface Zugang {
benutzer: string;
passwort: string;
datenbank: string;
}
/**
* Zerlegt eine Verbindungszeichenkette in ihre Teile.
*
* Die URL lässt sich nicht als Ganzes an `pg_dump` durchreichen: Prisma hängt
* eigene Parameter an (`?schema=public`), die es mit "invalid URI query
* parameter" ablehnt. Und der Port darin gilt vom Rechner aus — im Container,
* wo die Werkzeuge laufen, liegt Postgres auf 5432.
*/
export function zugangAus(roh: string | undefined): Zugang {
if (!roh) {
throw new Error("DIRECT_DATABASE_URL fehlt.");
}
let url: URL;
try {
url = new URL(roh);
} catch {
throw new Error(`Die Verbindungszeichenkette ist keine gültige URL: ${roh}`);
}
if (!url.protocol.startsWith("postgres")) {
throw new Error(`Erwartet wird eine postgresql://-Adresse, bekommen: ${url.protocol}//`);
}
const datenbank = url.pathname.replace(/^\//, "");
if (!datenbank) {
throw new Error("In der Verbindungszeichenkette fehlt der Datenbankname.");
}
return {
benutzer: decodeURIComponent(url.username),
passwort: decodeURIComponent(url.password),
datenbank,
};
}