From 31c4c209e4b34f5a2cbbd09efee2b9fd68b4a580 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Wed, 26 Aug 2026 17:23:24 +0200 Subject: [PATCH] status.txt nennt den Grund, nicht nur das Etikett In der Statusdatei des Gegenbuchs stand fuer JEDEN Exit-2 derselbe Satz: "BEFUND - Widerspruch zwischen CRM und Gegenbuch". Ein echter Widerspruch sah damit genauso aus wie eine quittierpflichtige Erstsiegelung. Aufgefallen im Betrieb: Der Betreiber las "BEFUND" auf Staging und konnte nicht entscheiden, ob er handeln muss - obwohl die Kette dort valid:true meldet und der Alarm nur den erwarteten Siegelwechsel betraf. Wer ausschliesslich die Statusdatei liest, und genau dafuer ist sie da ("damit eine Ueberwachung sie abgreifen kann, ohne Logs zu durchsuchen"), bekam ein Etikett ohne Inhalt. Der Lauf wird jetzt mitgeschnitten; die erste ALARM-Zeile landet als "Grund:" in status.txt, ohne Alarm die erste Ausgabezeile. Co-Authored-By: Claude Opus 5 (1M context) --- docs/todo.md | 13 +++++++++++++ tools/audit-notary/entrypoint.sh | 21 +++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/todo.md b/docs/todo.md index 0cd12dd0..50a6f87c 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -97,6 +97,19 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung ## ✅ Erledigt +- [x] **📄 `status.txt` nennt jetzt den Grund, nicht nur das Etikett** (2026-08-26) + - In der Statusdatei des Gegenbuchs stand für **jeden** Exit-2 derselbe Satz: + „BEFUND – Widerspruch zwischen CRM und Gegenbuch". Ein echter Widerspruch + sah damit genauso aus wie eine quittierpflichtige Erstsiegelung. + - Aufgefallen im Betrieb: Der Betreiber las „BEFUND" auf Staging und konnte + nicht entscheiden, ob er handeln muss – obwohl die Kette dort `valid:true` + meldet und der Alarm nur den erwarteten Siegelwechsel betraf. Wer nur die + Statusdatei liest (und dafür ist sie da – „damit eine Überwachung sie + abgreifen kann, ohne Logs zu durchsuchen"), bekam ein Etikett ohne Inhalt. + - Der Lauf wird jetzt mitgeschnitten; die erste `ALARM:`-Zeile landet als + `Grund:` in `status.txt`. Ohne Alarm die erste Ausgabezeile. + - Datei: `tools/audit-notary/entrypoint.sh` + - [x] **⚖️ Aufsicht und Eingriff getrennt: neuer Haken „Audit-Betrieb"** (2026-08-26) - Die DSGVO-Rolle trug `audit:*` **komplett**, also auch `audit:admin`. Ein DSGVO-Beauftragter konnte damit `seal-backlog`, `rehash` und `cleanup` – diff --git a/tools/audit-notary/entrypoint.sh b/tools/audit-notary/entrypoint.sh index 6f53c0d7..b973a25f 100755 --- a/tools/audit-notary/entrypoint.sh +++ b/tools/audit-notary/entrypoint.sh @@ -70,8 +70,16 @@ fi # Logs zu durchsuchen. while true; do ZEIT=$(date -Iseconds) - node /opt/notary/notary.mjs + # Ausgabe mitschneiden, um den GRUND in die Statusdatei zu bekommen. + # + # Vorher stand dort nur das Etikett ("BEFUND"), und das ist fuer jeden + # Exit-2 dasselbe - ein echter Widerspruch sieht darin aus wie eine + # quittierpflichtige Erstsiegelung. Wer nur die Statusdatei liest, kann + # nicht entscheiden, ob er handeln muss. Genau die Sorte Signal, gegen die + # dieses Werkzeug gebaut ist. + node /opt/notary/notary.mjs > /tmp/lauf.log 2>&1 CODE=$? + cat /tmp/lauf.log case $CODE in 0) LAGE="in Ordnung" ;; 1) LAGE="Betriebsfehler (Konfiguration, CRM nicht erreichbar, Commit)" ;; @@ -82,6 +90,15 @@ while true; do *) LAGE="unbekannter Code" ;; esac echo "[$INSTANZ] $ZEIT exit=$CODE ($LAGE)" - printf '%s exit=%s %s\n' "$ZEIT" "$CODE" "$LAGE" > /gegenbuch/status.txt + # Erste erklaerende Zeile mitnehmen: bei Alarm die ALARM-Zeile, sonst die + # erste Ausgabezeile ueberhaupt. + GRUND=$(grep -m1 '^ALARM: ' /tmp/lauf.log | sed 's/^ALARM: //') + if [ -z "$GRUND" ]; then + GRUND=$(grep -m1 -v '^[[:space:]]*$' /tmp/lauf.log) + fi + { + printf '%s exit=%s %s\n' "$ZEIT" "$CODE" "$LAGE" + [ -n "$GRUND" ] && printf 'Grund: %s\n' "$GRUND" + } > /gegenbuch/status.txt sleep "$INTERVALL" done