Protokoll im Adminbereich, ein Knopf für das ganze Blatt
Die restlichen zwei Änderungswünsche. **Protokoll.** „Wer was wo macht" stand seit dem ersten Tag in AuditLog — harte Regel 3 sorgt dafür. Was fehlte, war die Ansicht darauf. /admin/protokoll ist genau das und keine zweite Aufzeichnung: filterbar nach Person, Aktion, Art und Zeitraum, rückwärts blätternd. Nur für die Leitung. Eine Zeile nennt Aktenzeichen und Namen, und schon die Existenz einer Zeile verrät, dass es einen Vorgang gibt; ein gefiltertes Protokoll für alle wäre ein Weg, die Sichtbarkeitsregeln von hinten aufzurollen. Aus demselben Grund werden Kennungen ohne Sichtbarkeitsfilter zu Aktenzeichen aufgelöst — ein Protokoll aus UUIDs liest niemand, und eines, das niemand liest, ist keine Kontrolle. **Speichern.** Jedes Feld trug seinen eigenen Knopf: ein Arbeitsvertrag mit zwölf Feldern hiess zwölfmal speichern. Der Knopf steht jetzt am Blatt. Geschrieben wird trotzdem je Feld und nicht als Transaktion, und das folgt aus dem Datenmodell: Abschnitte sind einzeln versioniert, weil mehrere Leute gleichzeitig an einer Akte arbeiten. Als Transaktion blockierte ein einziges zwischenzeitlich geändertes Feld das ganze Blatt — elf gute Änderungen verloren, weil jemand das zwölfte angefasst hat. So geht durch, was durchgeht, und die Rückmeldung sagt, was offen blieb und wo. Lichtbilder bleiben ausgenommen: ein Upload mit Prüfkette ist keine Feldänderung. lib/audit.ts liegt jetzt als lib/audit/write.ts neben lib/audit/query.ts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ef377f0123
commit
5f9f5d99fb
@@ -20,6 +20,8 @@ Wo eine Entscheidung fachlich anders ausfallen kann, steht das ausdrücklich dab
|
||||
| `04-datenmodell.md` nennt zugleich `CREATE SEQUENCE case_number_2026` und die Tabelle `CaseCounter(year, lastNumber)` mit `SELECT … FOR UPDATE` | `CaseCounter`. Eine Sequenz pro Jahr müsste jedes Jahr von Hand angelegt werden, und der Abteilungsleiter ist ausdrücklich nicht technisch |
|
||||
| Das rohe SQL benutzt `search_vector` und `updated_at` in Schlangenschrift, die Prisma-Modelle Höckerschrift | Prisma-Voreinstellung behalten: Tabellen in Höckerschrift-Pascal, Spalten in Höckerschrift. Das SQL quotet entsprechend (`"searchVector"`, `"updatedAt"`) |
|
||||
| Kein Modell für Kanäle, obwohl `ChatMessage.channelId` existiert und `06-chat-und-realtime.md` Kanäle mit eigener Mindeststufe verlangt | Modell `Channel` ergänzt, dazu `ChatReaction` für den festen Reaktionssatz |
|
||||
|
||||
> Nachtrag: `Channel` ist inzwischen wieder entfernt, siehe „Freie Kanäle sind entfallen" weiter unten.
|
||||
| `/api/health` soll den Discord-Gateway prüfen, aber die Web-App fragt nie live bei Discord an | Modell `ServiceHeartbeat`. Der Worker schreibt alle 30 Sekunden seinen Zustand, `web` liest ihn |
|
||||
|
||||
## Der wichtigste Widerspruch
|
||||
@@ -1003,3 +1005,43 @@ Profilbild. Das Bild kommt von Discord — dort liegt es ohnehin, die Anmeldung
|
||||
dieselbe Stelle, und ein eigener Zwischenspeicher wäre ein Dienst mehr im Stack für ein Bild
|
||||
von 64 Pixeln. Dafür steht `cdn.discordapp.com` in der Inhaltsrichtlinie. Wer kein Bild hat,
|
||||
bekommt seine Initialen; ein Platzhaltergesicht lädt nichts nach und sagt nichts.
|
||||
|
||||
### Das Protokoll ist eine Ansicht, keine neue Spur
|
||||
|
||||
„Wer was wo macht" stand vom ersten Tag an in `AuditLog` — harte Regel 3 aus CLAUDE.md sorgt
|
||||
dafür, dass jede schreibende Aktion und jeder Lesezugriff ab Stufe 3 eine Zeile erzeugt. Was
|
||||
fehlte, war die Ansicht darauf. `/admin/protokoll` ist genau das und **nicht** eine zweite
|
||||
Aufzeichnung.
|
||||
|
||||
Zwei Festlegungen:
|
||||
|
||||
**Nur die Leitung.** Eine Protokollzeile nennt Aktenzeichen und Namen, und schon die Existenz
|
||||
einer Zeile verrät, dass es einen Vorgang gibt. Ein „gefiltertes Protokoll für alle" wäre ein
|
||||
Weg, die Sichtbarkeitsregeln von hinten aufzurollen: aus den Lücken liesse sich lesen, was man
|
||||
nicht sehen darf. Deshalb `requirePermission('admin')` und sonst nichts.
|
||||
|
||||
**Kennungen werden aufgelöst, ohne Sichtbarkeitsfilter.** Aus `Case:0192…` wird
|
||||
`AfiS-2026-0042`. Ohne das wäre die Ansicht eine Spalte UUIDs, die niemand liest — und ein
|
||||
Protokoll, das niemand liest, ist keine Kontrolle. Das ist die Ausnahme, die es geben muss,
|
||||
damit die Leitung prüfen kann, ob die Regeln eingehalten wurden. Sie ist genau deshalb auf die
|
||||
Leitung beschränkt.
|
||||
|
||||
Zeilen, deren Ziel sich nicht auflösen lässt — ein Exportauftrag etwa —, bleiben mit ihrer
|
||||
rohen Kennung stehen. Ein Protokoll mit Lücken wäre keins.
|
||||
|
||||
### Ein Knopf für das ganze Blatt
|
||||
|
||||
Jedes Feld trug seinen eigenen Speichern-Knopf. Einen Arbeitsvertrag mit zwölf Feldern
|
||||
auszufüllen hiess zwölfmal speichern, und wer eines vergass, merkte es erst beim Nachlesen.
|
||||
Der Knopf steht jetzt am Blatt.
|
||||
|
||||
Gespeichert wird trotzdem **je Feld und nicht als Transaktion**. Das ist kein halber Umbau,
|
||||
sondern folgt aus dem Datenmodell: Abschnitte sind einzeln versioniert, weil an einer Akte
|
||||
mehrere Leute gleichzeitig arbeiten. Wäre das Speichern eine Transaktion, blockierte ein
|
||||
einziges zwischenzeitlich geändertes Feld das ganze Blatt — elf gute Änderungen gingen
|
||||
verloren, weil jemand anderes das zwölfte angefasst hat. Stattdessen geht durch, was durchgeht,
|
||||
und die Rückmeldung sagt, was offen blieb und wo. Der Fassungsvergleich steht weiterhin am
|
||||
betroffenen Feld.
|
||||
|
||||
Lichtbilder bleiben ausgenommen: ein Bild wird hochgeladen und geprüft, das ist ein eigener
|
||||
Vorgang mit eigener Prüfkette und keine Feldänderung.
|
||||
|
||||
Reference in New Issue
Block a user