Phase 11: Freigabereife (#16)
Pruefung / pruefung (push) Canceled after 0s
Pruefung / oberflaeche (push) Canceled after 0s

This commit was merged in pull request #16.
This commit is contained in:
2026-09-06 20:05:49 +00:00
parent 91742a0dd7
commit 14cc4de9b8
21 changed files with 2495 additions and 8 deletions
+94
View File
@@ -0,0 +1,94 @@
/**
* Die Sperren der Anwendungsrolle — nach einer Wiederherstellung.
*
* Hintergrund, und er ist unerwartet:
*
* Beim ersten Start richtet `docker/postgres/10-init-app-role.sh` eine
* Vorgabeprivilegierung ein — jede künftig angelegte Tabelle bekommt
* automatisch alle Rechte für `florian_app`. Das ist im Betrieb genau richtig:
* eine neue Migration soll nicht daran scheitern, dass jemand vergessen hat,
* Rechte zu vergeben.
*
* `pg_restore` legt die Tabellen aber ebenfalls neu an. Die Vorgabe greift
* also auch dort — und die `GRANT`-Anweisungen aus dem Dump können nur
* hinzufügen, nie wegnehmen. Nach einer Wiederherstellung stünde die
* Anwendungsrolle damit wieder mit allen Rechten da: sie dürfte das Audit-Log
* ändern, Wiki-Fassungen löschen, Kiosk-Vorgänge umschreiben.
*
* Nichts an der Anwendung würde darauf hinweisen. Die Unveränderlichkeit, auf
* der jeder Nachweis gegenüber der Unfallkasse beruht, wäre stillschweigend
* weg — bis jemand danach fragt.
*
* Gefunden haben das die Datenbanktests nach der ersten Rückspielprobe.
* Deshalb gibt es diese Datei: **eine** Liste, aus der sowohl das
* Wiederherstellen als auch das Prüfen der Sperren entsteht. Zwei Listen
* wären zwei Wahrheiten.
*/
/** Tabelle → Rechte, die `florian_app` NICHT haben darf, mit Begründung. */
export const SPERREN: Array<{ tabelle: string; rechte: string[]; grund: string }> = [
{
tabelle: "berechtigung",
rechte: ["INSERT", "UPDATE", "DELETE"],
grund: "systemweiter Rechtekatalog — nur lesbar",
},
{
tabelle: "audit_log",
rechte: ["UPDATE", "DELETE"],
grund: "append-only; das Löschen geht nur im Aufbewahrungslauf",
},
{
tabelle: "kiosk_vorgang",
rechte: ["UPDATE", "DELETE"],
grund: "übermittelte Terminalvorgänge sind unveränderlich",
},
{
tabelle: "druckmessung",
rechte: ["UPDATE", "DELETE"],
grund: "Atemschutzüberwachung — Druckwerte werden nie korrigiert",
},
{
tabelle: "atemschutz_ereignis",
rechte: ["UPDATE", "DELETE"],
grund: "wie oben: der Verlauf einer Überwachung bleibt, wie er war",
},
{
tabelle: "benachrichtigung",
rechte: ["DELETE"],
grund: "was zugestellt wurde, bleibt nachweisbar",
},
{
tabelle: "ki_vorgang",
rechte: ["DELETE"],
grund: "das KI-Protokoll belegt, was die Maschine getan hat",
},
{
tabelle: "wikiversion",
rechte: ["UPDATE", "DELETE"],
grund: "jede Fassung einer Wiki-Seite bleibt erhalten",
},
{
tabelle: "kassenabschluss",
rechte: ["DELETE"],
grund: "ein festgeschriebener Abschluss lässt sich nicht wegräumen",
},
{
tabelle: "benutzer",
rechte: ["INSERT", "DELETE"],
grund: "Konten entstehen und vergehen über den Systemzugang",
},
];
/** Die SQL-Anweisungen, die die Sperren wiederherstellen. */
export function sperrenSql(): string[] {
return SPERREN.map(
({ tabelle, rechte }) => `REVOKE ${rechte.join(", ")} ON "${tabelle}" FROM florian_app`,
);
}
/** Alle Kombinationen, die nach der Wiederherstellung fehlen müssen. */
export function verboteneRechte(): Array<{ tabelle: string; recht: string }> {
return SPERREN.flatMap(({ tabelle, rechte }) =>
rechte.map((recht) => ({ tabelle, recht })),
);
}