5 Commits
Author SHA1 Message Date
duffyduckandClaude Opus 5 e76b4ace88 status.txt zeigt die Zusammenfassung, nicht die erste beliebige Zeile
Die Grund-Zeile nahm bei fehlendem Alarm schlicht die erste Ausgabezeile.
Beim ersten Prod-Lauf nach dem Versiegeln stand dort deshalb die
einmalige Notiz "Grundlage fuer die Rehash-Ueberwachung wird gesetzt"
statt des Ergebnisses "OK: Checkpoint N erstellt" - eine Randnotiz
verdeckte die Zusammenfassung.

Jetzt: bei Alarm die ALARM-Zeile, sonst die OK-Zeile, und erst wenn
beides fehlt die erste Zeile ueberhaupt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 19:25:45 +02:00
duffyduckandClaude Opus 5 31c4c209e4 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) <noreply@anthropic.com>
2026-08-26 17:23:24 +02:00
duffyduckandClaude Opus 5 601fb03b22 Gegenbuch-Container: Rechte am Bind-Mount selbst geraderuecken
Fehlerbild aus dem echten Betrieb: "mkdir: cannot create directory
'/gegenbuch/schluessel': Permission denied", Container in der
Neustart-Schleife. Ursache: Das Datenverzeichnis kommt als Bind-Mount vom Host;
der Betreiber hatte das Projekt als root geklont, der Container lief aber
direkt als UID 1000 und durfte dort nichts anlegen. Der .gitkeep-Ansatz hatte
stillschweigend angenommen, dass als normaler Benutzer geklont wird - auf einem
Server ist root der Normalfall.

Fix: Der Container startet als root, setzt /gegenbuch per chown auf den
Arbeitsbenutzer (PUID/PGID, Standard 1000) und startet sich per setpriv als
dieser neu. Die eigentliche Arbeit laeuft weiterhin unprivilegiert. Schlaegt
das chown fehl (rootless Docker), gibt es einen Hinweis mit dem passenden
Host-Befehl statt eines stummen Abbruchs.

Verifiziert mit exakt der Ausgangslage: Datenverzeichnis auf root:root gesetzt,
Container gestartet -> laeuft durch, erzeugte Dateien gehoeren 1000:1000, der
private Schluessel liegt mit 0600.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 19:51:10 +02:00
duffyduckandClaude Opus 5 1eb65809ec Gegenbuch: Dienstkonto statt Token, .env mit gueltigen Werten
Blocker behoben: Ich hatte ein dauerhaftes API-Token vorausgesetzt - das gibt
es in OpenCRM nicht. Zugangstoken leben 15 Minuten, der Gegenbuch-Container
waere nach dem ersten Durchlauf gestorben. Aufgefallen erst durch die Frage des
Betreibers, woher er den Token nimmt.

Loesung: Das Gegenbuch meldet sich bei jedem Lauf selbst an, mit einem eigenen
Benutzerkonto, dessen Rolle ausschliesslich audit:read traegt. Damit kann es
nur Pruefwerte lesen - keine Kundendaten, keine Aenderungen. CRM_TOKEN bleibt
fuer Tests moeglich, ist aber nicht mehr der Normalweg. Fehlerfaelle (falsches
Passwort, Anmelde-Bremse, CRM nicht erreichbar) werden unterschieden und im
Klartext gemeldet.

.env.example nennt jetzt zu jedem Schalter die gueltigen Werte - bisher liess
sich nur raten, ob es prod oder production heisst. Einschliesslich des Falls
"erst nur Staging testen, Prod spaeter dazunehmen".

Beide READMEs um "Zugang einrichten" ergaenzt: Rolle mit nur audit:read,
Benutzer damit, Zugangsdaten in die .env. Mit dem Hinweis, dass jede Anmeldung
im Audit-Log erscheint - gewollt, denn so faellt auch auf, wenn das Gegenbuch
aufhoert zu arbeiten.

Verifiziert gegen eine Attrappe, die wie das echte CRM eine Anmeldung verlangt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 19:31:46 +02:00
duffyduckandClaude Opus 5 a62c51b7c7 Gegenbuch als Docker-Setup, lokales Buch auf eigener Maschine
Betreiber-Entscheidung: Das Gegenbuch laeuft auf einer eigenen Maschine fuer
Prod und Staging; ein externes Git-Repository entfaellt, das Buch liegt lokal.
Die Trennung, auf die es ankommt, ist damit gegeben - wer OpenCRM uebernimmt,
kommt nicht ans Buch.

Richtung bewusst so herum: Das Gegenbuch holt ueber HTTPS mit einem Token, das
nur audit:read kann. OpenCRM kennt weder Adresse noch Schluessel des
Gegenbuchs. Kein SSH-Zugang zum CRM noetig.

tools/audit-notary/ enthaelt jetzt Dockerfile, entrypoint.sh,
docker-compose.yml und .env.example. Zwei Dienste (prod, staging) mit
getrennten Verzeichnissen und Schluesseln, gesteuert ueber COMPOSE_PROFILES -
dasselbe Muster wie beim Caddy-Profil im Hauptstack. Der Signaturschluessel
wird beim ersten Start auf der Gegenbuch-Maschine erzeugt.

Lokaler Betrieb ist jetzt ein vollwertiger Modus statt eines Testschalters. Die
Erfolgsmeldung benennt bei jedem Lauf, was abgedeckt ist und was nicht - statt
der frueheren pauschalen Formulierung "kein Manipulationsschutz", die im
Einsatz auf eigener Maschine schlicht falsch war.

Verifiziert mit echtem Docker-Build gegen eine CRM-Attrappe: Genesis ohne
Bestaetigung -> Code 4; mit Bestaetigung Normalbetrieb exit 0; Eintrag
veraendert -> Alarm exit 2; Eintraege geloescht -> Alarm exit 2; Siegel
verschwunden -> Alarm.

Behoben beim Bauen: useradd -u 1000 || true verschluckte, dass UID 1000 im
Node-Image vergeben ist - der Container startete gar nicht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 18:51:45 +02:00