# Volltext-Systemaudit: letzte Prozesse und Reviewer-Evaluationsparameter Datum: 2026-09-03 Rolle: Reviewer Diff-Basis: `802e364e8e4e0a7afe15fa5242d139c1b24ce12f` (`HEAD`) ## Kurzfazit Der kombinierte Stand ist **nicht freigabefähig**. Prozess A (SDLC- Playbook-Prozessergänzungen) ist in Rollenfrontmatter, Katalog und positivem Rollentest konsistent, enthält aber eine widersprüchliche Anforderungsgrundlage und nur schwache Schlüsselworttests für die neuen Prompt-Normen. Prozess B (IMAP-Backend für Orga-Mail-Entwürfe) hat einen Blocker: Das unqualifizierte IMAP-`EXPUNGE` kann außer dem adressierten Orga-Draft auch fremde, bereits als `\Deleted` markierte Nachrichten im ausgewählten Entwürfe-Ordner endgültig löschen. Zwei weitere High-Befunde betreffen fehlende Trust-Markierung und einen nicht über die API behebbaren Duplikatzustand nach Teilfehlern. Es wird ausdrücklich **keine** Aktivierungs-, Deployment-, Commit-, Push- oder Veröffentlichungsfreigabe erteilt. ## Scope und Ausgangszustand Geprüft wurde ausschließlich der tatsächlich vorliegende uncommittete Stand der zwei beauftragten Prozesse gegen `HEAD 802e364`: ### Prozess A: SDLC-Playbook-Prozessergänzungen - `agents/admin.md` - `agents/agent-manager.md` - `agents/planner.md` - `agents/reviewer.md` - `agents/catalog.json` - `agents/tests/roles.sh` - `docs/intent/sdlc-playbook-prozessergaenzungen.md` (untracked, vollständig als Neudatei gegen `/dev/null` geprüft) ### Prozess B: IMAP-Backend für Orga-Mail-Entwürfe - `hosts/blunix/localServices/orga-agent.nix` - `hosts/blunix/localServices/orga-agent/README.md` - `hosts/blunix/localServices/orga-agent/client.py` - `hosts/blunix/localServices/orga-agent/draft_server.py` - `hosts/blunix/localServices/orga-agent/test_orga_agent.py` - `hosts/blunix/localServices/secrets.nix` - `docs/intent/orga-mail-entwuerfe-imap.md` als unveränderte, bereits in `HEAD` enthaltene Anforderungsgrundlage `docs/intent/forgejo-umzug-blunix.md` und `docs/intent/nixostest-vm-tests-pilot-tnix.md` sind ebenfalls untracked, aber ausdrücklich nicht Teil dieses Audits und wurden nicht bewertet. Secrets wurden weder gelesen noch entschlüsselt. Es gab keinen Netzwerkzugriff, keinen Build, keine Aktivierung und keinen Dienstneustart. ## Methode und Eskalationsanlass Die genannten Dateien und ihre Diffs wurden vollständig gelesen und gegen `AGENTS.md`, `agents/reviewer.md`, die beiden Intent-Dokumente, die Katalogmetadaten und die im Scope liegenden Tests abgeglichen. Für kritische IMAP-Pfade wurden zusätzlich rein lokale In-Memory-Fehlerinjektionen gegen den vorhandenen Fake-Server ausgeführt. Dieser Audit läuft bewusst unter `gpt-5.6-sol` mit `high` statt unter dem Routine-Fallback `gpt-5.6-terra`/`medium`. Konkreter Eskalationsanlass ist der kombinierte, sicherheitsrelevante Cross-Scope über Rollenverträge, Rollenkatalog, Secret-Zuordnung und einen neuen realen IMAP-Schreib- und Löschpfad. Das Routineprofil wäre für die notwendige Volltext-Korrelation der Vertrauensgrenzen und die aktive Fehlerpfadprüfung nicht ausreichend gewesen; insbesondere waren globale `EXPUNGE`-Wirkung, externe Trust-Grenze und Teilfehler-Recovery gemeinsam zu bewerten. Der projektlokale Graphify-Skill wurde gemäß Repositoryvorgabe geprüft, aber nicht ausgeführt: `graphify-out/graph.json` fehlt, und ein Neuaufbau würde mehrere zusätzliche Repository-Artefakte erzeugen. Das widerspräche der Reviewer-Grenze, nach der dieser Bericht das einzige Datei-Artefakt sein darf. ## Prozess A: Bewertung der SDLC-Playbook-Prozessergänzungen ### Blocker Keine Befunde. ### High Keine Befunde. ### Medium A1 — Intent und implementierter Rollenvertrag widersprechen sich - **Pfad/Zeile:** `docs/intent/sdlc-playbook-prozessergaenzungen.md:28-35`, `agents/agent-manager.md:112-120` - **Beleg:** Das Intent verlangt, dass `agent-manager` den Eskalationsanlass in seinem bestehenden `docs/*.md`-Artefakt festhält. Der Rollenvertrag stellt dagegen ausdrücklich und sachlich korrekt fest, dass diese Rolle kein solches Artefakt führt, und legt den Anlass in die Chat-Übergabe. Die Implementierung dokumentiert die Abweichung sogar als „anders als im Intent-Dokument angenommen“, ohne die Anforderungsgrundlage zu bereinigen. - **Auswirkung:** Die fachliche Implementierung ist praktikabel, aber die Abnahmekette ist nicht eindeutig. Ein späterer Reviewer kann denselben Stand je nach gewählter Quelle als erfüllt oder nicht erfüllt bewerten; außerdem bleibt eine nachweislich falsche Plattformannahme im Intent erhalten. - **Empfehlung:** Vor dem Commit das Intent nach ausdrücklicher Nutzerbestätigung korrigieren oder die Chat-Übergabe als genehmigte Abweichung vom ursprünglichen Intent dokumentieren. Danach Rollenvertrag und Intent wieder wortsinngleich halten. ### Low A2 — Neue Prompt-Normen werden nur durch schwache Schlüsselworttests abgedeckt - **Pfad/Zeile:** `agents/tests/roles.sh:412-420`, `agents/tests/roles.sh:493-501` - **Beleg:** Der Harness prüft unter anderem nur die überall vorkommenden Fragmente `keine` und `nur bei`. Für die Design-Zwischenstufe werden zwar passende Begriffe gesucht, aber weder die notwendige Nutzerbestätigung noch die Reihenfolge „vor finalem Intent-Schreiben“, die beiden positiven Trigger und der negative Fall „bloße Rollenerwähnung“ als zusammenhängender Vertrag geprüft. `bash agents/tests/roles.sh` bleibt daher auch bei semantisch falsch zusammengesetzten Absätzen leicht grün. - **Auswirkung:** Versionen und das bloße Vorhandensein von Text sind abgesichert, nicht das neue Prozessverhalten. Gerade die praktisch zu erprobenden Reviewer-/Planner-Parameter können unbemerkt semantisch regressieren. - **Empfehlung:** Präzisere Vertragsassertionen für Ausgabeort, Nutzerbestätigung, Trigger und Negativfall ergänzen. Zusätzlich mindestens je ein dokumentiertes Rollen-Evaluationsszenario verwenden: Multi-Host muss triggern; reine Rollenerwähnung bei Single-Host darf nicht triggern; eskalierte und Routine-Ausführung müssen unterschiedliche Berichtspflichten ergeben. ### Positive Beobachtungen zu Prozess A - Alle vier geänderten Rollen haben nachvollziehbare Minor-Version-Bumps; Frontmatter, `agents/catalog.json` und Harness stimmen überein. - Die Planner-Zwischenstufe erzeugt kein zweites Datei-Artefakt und erweitert weder Schreib- noch Aktivierungsrechte. - Die Reviewer-Kennzahlen bleiben ausdrücklich optional, auditgebunden und verpflichten bei fehlender Evidenz zur Unsicherheitsangabe statt zur Erfindung von Zahlen. - Administrator, Agent-Manager und Reviewer legen den Eskalationsanlass an einem für ihren tatsächlichen Ausgabeweg geeigneten Ort ab; nur die Anforderungsgrundlage des Agent-Managers muss dazu konsistent gemacht werden. ## Prozess B: Bewertung des IMAP-Backends ### Blocker B1 — Normales `EXPUNGE` löscht nicht nur den adressierten UID - **Pfad/Zeile:** `hosts/blunix/localServices/orga-agent/draft_server.py:215-221`, `hosts/blunix/localServices/orga-agent/test_orga_agent.py:172-185`, `docs/intent/orga-mail-entwuerfe-imap.md:32-35` und `:80-84` - **Beleg:** `delete_uid()` markiert den Ziel-UID per `UID STORE ... +FLAGS (\Deleted)`, ruft danach aber das nicht UID-begrenzte `connection.expunge()` auf. IMAP-`EXPUNGE` entfernt alle im aktuell ausgewählten Ordner als `\Deleted` markierten Nachrichten. Der Fake markiert nur während des jeweiligen Tests gelöschte UIDs und modelliert deshalb keinen bereits oder parallel gelöschten fremden Draft. Eine lokale In-Memory-Prüfung mit fremdem UID `900` in der vorbestehenden Deleted-Menge ergab nach dem Löschen eines Orga-Drafts: `foreign_survives_plain_expunge=False`. - **Auswirkung:** Ein `delete` oder jedes erfolgreiche `update` kann einen fremden, vom Nutzer oder einem anderen Client gelöschten Entwurf endgültig mitentfernen. Der `X-Orga-Draft`-Marker schützt diese Nachricht nicht. Das verletzt direkt die zugesicherte Eigentums- und Ordnergrenze sowie das Erfolgskriterium, keine anderen Nachrichten zu löschen. - **Empfehlung:** Ausschließlich zielgebunden expungen, etwa über `UID EXPUNGE ` nach verifizierter UIDPLUS-Unterstützung. Wenn der Server das nicht unterstützt, darf es keinen stillen Fallback auf globales `EXPUNGE` geben; der Löschpfad muss sicher fehlschlagen oder über ein anderes isolierendes Verfahren umgesetzt werden. Einen Regressionstest mit einem bereits als `\Deleted` markierten fremden Draft hinzufügen. ### High B2 — IMAP-gelesene Draft-Inhalte fehlen die zugesicherte Trust-Markierung - **Pfad/Zeile:** `hosts/blunix/localServices/orga-agent/draft_server.py:294-316` und `:361-364`, `hosts/blunix/localServices/orga-agent/README.md:3-5`, `hosts/blunix/localServices/orga-agent/test_orga_agent.py:209-255` - **Beleg:** README und bestehender Mail-Read-Vertrag verlangen für zurückgegebene Maildaten `UNTRUSTED_EXTERNAL_DATA`. `show` und `list` lesen nun aus einem externen IMAP-Postfach, geben aber nur `draft` beziehungsweise `drafts` zurück. Eine lokale Prüfung ergab `show_has_trust_marker=False`. Kein neuer Test fordert den Marker. - **Auswirkung:** Ein Draft kann nach seiner Erstellung von einer Mail-App, einem anderen Client oder einem kompromittierten Konto verändert werden. Betreff und Body gelangen dann ohne die vorgesehene Kennzeichnung in den Agentenkontext und können als Instruktion statt als unvertrauenswürdige externe Daten behandelt werden. Der Marker `X-Orga-Draft: 1` ist eine Eigentumsmarke, keine Trust-Garantie. - **Empfehlung:** Mindestens `show` und `list` mit `"trust": "UNTRUSTED_EXTERNAL_DATA"` kennzeichnen und dies analog zu `read_server.py` testen. Agentenseitig muss der Inhalt weiterhin nur als Daten behandelt werden. ### High B3 — Der dokumentierte Duplikat-Fallback ist nicht über die API wiederherstellbar - **Pfad/Zeile:** `hosts/blunix/localServices/orga-agent/draft_server.py:192-201` und `:268-281`, `hosts/blunix/localServices/orga-agent/README.md:26-30` - **Beleg:** `update` hängt zuerst eine neue Nachricht mit derselben Message-ID an und löscht danach die alte. Schlägt die Löschung nach erfolgreichem `APPEND` fehl, existieren zwei Treffer. `find_draft_uid()` verwirft aber jeden Mehrfachtreffer als `draft reference is ambiguous`. Eine lokale Fehlerinjektion erzeugte zwei Nachrichten; der unmittelbar folgende `show` endete mit genau diesem RequestError. Damit ist das laut README „recoverable duplicate“ weder per `show`, `update` noch `delete` recoverbar. - **Auswirkung:** Ein einzelner transienter STORE-/EXPUNGE-Fehler kann einen Draft dauerhaft für alle Helper-Operationen sperren und manuelle Postfachreparatur erzwingen. Das Update-Erfolgskriterium „ersetzen statt Duplikate anhäufen“ ist im Fehlerpfad nicht erfüllt. - **Empfehlung:** Einen expliziten, deterministischen Recovery-Pfad entwerfen, zum Beispiel APPENDUID erfassen und bei mehreren exakt markierten Treffern die höchste valide Revision auswählen sowie ältere UIDs zielgebunden bereinigen. Fehlerpfade nach erfolgreichem APPEND und vor/nach STORE mit Tests abdecken; bis dahin die README-Aussage nicht als gewährleistet darstellen. ### Medium B4 — `\Drafts` wird als Teilstring statt als exaktes Flag erkannt - **Pfad/Zeile:** `hosts/blunix/localServices/orga-agent/draft_server.py:45-50` und `:128-146`, `hosts/blunix/localServices/orga-agent/test_orga_agent.py:274-291` - **Beleg:** `SPECIAL_USE_DRAFTS.search(flags)` akzeptiert jedes Flag, das die Bytefolge `\Drafts` enthält. Eine lokale Prüfung mit einem zuerst gelisteten Ordner `Archive` und Flag `\DraftsArchive` sowie einem späteren echten Fallbackordner `Drafts` wählte fälschlich `"Archive"`. - **Auswirkung:** Nichtstandardisierte oder erweiterte Serverflags können die behauptete Ordnerbindung auf den falschen Ordner lenken. Nachfolgende APPEND-/STORE-/EXPUNGE-Operationen würden dann außerhalb des gewünschten Entwürfe-Ordners stattfinden. - **Empfehlung:** Die Flagliste tokenisieren und `\Drafts` ausschließlich per exaktem, case-insensitivem Tokenvergleich akzeptieren. Einen Decoy-Test mit `\DraftsArchive` ergänzen. ### Medium B5 — „Drafts-only/no SMTP“ ist eine Anwendungs-, keine technisch erzwungene Credential-Grenze - **Pfad/Zeile:** `hosts/blunix/localServices/orga-agent.nix:53` und `:170-187`, `hosts/blunix/localServices/secrets.nix:31-37`, `hosts/blunix/localServices/orga-agent/README.md:19-38` - **Beleg:** Der Dienst erhält eine zweite Runtime-Datei desselben kontoweiten Passworts wie `orga-mail-read` und darf über AF_INET/AF_INET6 ausgehend kommunizieren. Der Python-Requestpfad akzeptiert zwar keinen Ordnernamen und implementiert kein SMTP; die Systemidentität beziehungsweise ein kompromittierter Prozess ist aber nicht durch serverseitige Ordner-ACLs, ein dediziertes Konto oder Egress-Filter auf Drafts beziehungsweise IMAP begrenzt. Dass dasselbe Passwort tatsächlich auch SMTP-Authentifizierung erlaubt, wurde nicht geprüft und wird hier ausdrücklich nur als mögliches Risiko, nicht als Fakt, bewertet. - **Auswirkung:** Die README-Formulierungen können als härtere Sicherheitsgarantie verstanden werden, als die Plattform technisch liefert. Bei einer Prozesskompromittierung reicht die App-Level-Allowlist nicht zum Schutz anderer Ordner oder Protokolle. - **Empfehlung:** Die Grenze analog zur bereits dokumentierten Kalenderidentität ausdrücklich als App-Level-Isolation beschreiben. Falls „strikt“ eine technische statt nur logische Grenze meint, eine dedizierte serverseitig eingeschränkte Identität, einen eng validierenden lokalen IMAP-Proxy oder gleichwertige Credential-/Egress-Isolation vorsehen. ### Low B6 — README bezeichnet den neuen IMAP-Draft weiterhin als lokal - **Pfad/Zeile:** `hosts/blunix/localServices/orga-agent/README.md:93-100` - **Beleg:** Im Abschnitt zum weiterhin ausgeschlossenen Versand heißt es noch „revision-hashed local draft“, obwohl derselbe Diff die lokale JSON-Ablage vollständig durch IMAP ersetzt. - **Auswirkung:** Die zentrale Sicherheitsdokumentation widerspricht ihrem neuen Backend und kann Betrieb und spätere Reviews fehlleiten. - **Empfehlung:** `local draft` durch eine eindeutige Formulierung wie `IMAP draft in the account's Drafts folder` ersetzen. ### Positive Beobachtungen zu Prozess B - Caller können keinen Ordnernamen übergeben; reguläre Operationen wählen den ermittelten Drafts-Ordner selbst. - Der neue Service läuft unter einem eigenen Systemnutzer und erhält eine eigene agenix-Runtime-Datei; der Client erhält weder Secretpfad noch Netzwerkzugriff direkt. - Header-Injection im Subject wird abgewiesen; IDs sind eng formatiert und Marker werden vor Update/Delete geprüft. - Der Update-Normalpfad erhält Message-ID und Revision und schreibt vor dem Löschen, wodurch ein APPEND-Fehler die alte Fassung nicht vorab zerstört. - Es wurde kein SMTP- oder `orga-mail-send`-Requestpfad ergänzt. ## Tatsächlich ausgeführte Prüfungen ### Erfolgreich - `bash agents/tests/roles.sh` — **PASS**, `OK: Rollenkatalog und Sicherheitsgrenzen`. - Direkter Python-3.14-Aufruf aus dem vorhandenen Nix Store: `python3 -m unittest -v test_orga_agent.py` — **PASS**, 28 Tests. - `nix-instantiate --parse` für `orga-agent.nix` und `secrets.nix` — **PASS**. - Reine Modulevaluierung mit Stub-Argumenten über `nix-instantiate --eval --strict --json` — **PASS**. Bestätigt wurden Service-User/-Group `orga-mail-draft`, separater Passwortpfad, `AF_UNIX/AF_INET/AF_INET6`, entfallenes `StateDirectory` und Secret-Owner `orga-mail-draft`; es wurde kein Secretinhalt gelesen. - `git diff --check` für alle getrackten Scope-Dateien und `git diff --no-index --check` für das neue SDLC-Intent — **PASS**. - `bash -n agents/tests/roles.sh` und `jq empty agents/catalog.json` — **PASS**. - Lokale In-Memory-Regression für vorbestehendes fremdes `\Deleted`-Flag — **FAIL wie befundet**: fremder UID wurde mitexpungiert. - Lokale Trust-Marker-Prüfung auf `show` — **FAIL wie befundet**: Marker fehlt. - Lokale Fehlerinjektion „APPEND erfolgreich, Alt-Löschung fehlgeschlagen“ — **FAIL wie befundet**: zwei Nachrichten, anschließendes `show` mehrdeutig. - Lokale Folder-Discovery-Prüfung mit Decoy-Flag `\DraftsArchive` — **FAIL wie befundet**: falscher Ordner `Archive` gewählt. ### Nicht erfolgreich ausführbar oder bewusst offen - Eine vollständige Flake-/NixOS-Modulevaluierung per `nix eval --offline` kam in der Sandbox nicht bis zur Evaluation: zuerst war der Standardcache nicht beschreibbar, mit temporärem Cache war der Nix-Daemon-Socket nicht zugänglich; `NIX_REMOTE=local` scheiterte read-only an der Store-Lockdatei. Parser- und isolierte Modulevaluierung liefen deshalb als sichere Ersatzprüfung. Es wurde weder gebaut noch ein Lockfile verändert. - Live-IMAP-`CAPABILITY`/`LIST`, Zoho-Sonderverhalten, APPENDUID/UIDPLUS, realer iPhone-Sync und serverseitige ACLs wurden wegen des Verbots von Netzwerk- und Secretzugriff nicht geprüft. - Kein `nixos-rebuild`, kein Build, keine Aktivierung, kein Dienststart und kein schreibender Live-Smoke-Test wurden ausgeführt. Der erste direkte Aufruf von `python3` scheiterte lediglich daran, dass kein Interpreter im PATH lag; anschließend wurde der bereits vorhandene Nix-Store-Interpreter verwendet. Dabei erzeugte Python ein lokales `__pycache__`; dieses ausschließlich testgenerierte Cacheverzeichnis wurde vollständig wieder entfernt, sodass es kein zusätzliches Artefakt bleibt. ## Kennzahlen-Momentaufnahme seit dem Systemaudit vom 2026-09-01 Beobachtungsfenster ist der Zeitraum nach dem letzten Audit-Commit `57ee3a9` vom 2026-09-01 23:06:46+02:00 bis zu diesem Audit. Ausgewertet wurden der `git log` von `agents/tests/roles.sh`, `docs/intent/`, `docs/research/` und `docs/review/`, die einschlägigen Dokumenttexte sowie der aktuelle read-only-Herdr-Status. - **Planner:** Ein belastbarer Capability-Blocker ist in der Historie dokumentiert: Commit `e1ccbd8` bezeichnet den `AskUserQuestion`-Grant unter `dontAsk` ausdrücklich als wirkungslos; der damalige Rollenvertrag nennt das Tool strukturell nicht verfügbar. Der Stand in `HEAD` hat den Pilot danach auf `auto` umgestellt. `agents/tests/roles.sh` wurde im Fenster viermal geändert; mehrere Änderungen betreffen diesen Planner-Dialogpfad, sind aber nicht jeweils als eigene Blocker zu zählen. - **Reviewer:** Eine explizite Eskalation ist direkt belegt: dieser kombinierte Cross-Scope-Audit läuft wegen Rollen-/Katalog-/Secret-/IMAP-Schreibrisiko unter `sol/high` statt `terra/medium`. - **Administrator, Agent-Manager, Orga, Researcher, Graphics, Orchestrator, Dialog-Agent und Builder:** In den zulässigen, erhaltenen Quellen ist im Beobachtungsfenster kein weiterer Vorgang eindeutig als rollenbezogener Blocker oder tatsächliche Profil-Eskalation attribuierbar. Das ist **keine Nullmessung**. Eine Rate mit Nenner wird bewusst nicht berechnet: Die Quellen enthalten weder eine vollständige Zahl aller Rollenaufträge noch Laufzeit-/Tokenwerte. `herdr agent list` zeigte nur die aktuell lebenden Orchestrator- und Reviewer-Panes; geschlossene Pane-Transkripte der abgeschlossenen Prozesse sind nicht mehr verfügbar. Deshalb lassen sich weder die Gesamtzahl der Aufträge noch weitere Blocker oder Eskalationen belastbar rekonstruieren. Es werden keine Werte geschätzt oder aus Commitanzahlen als vermeintliche Ereignisrate abgeleitet. ## Empfohlene Übergabe 1. Prozess B nicht aktivieren oder veröffentlichen, bevor Blocker B1 behoben und mit einem fremden vorab gelöschten UID regressionsgetestet ist. 2. Vor Abnahme außerdem B2 und B3 beheben; beide betreffen die Kernverträge Trust-Grenze beziehungsweise verlässliches Update/Recovery. 3. B4 und B5 vor Aktivierung fachlich entscheiden: exakte Flagprüfung ist direkt korrigierbar; die Credential-Grenze muss mindestens ehrlich als App-Level-Isolation dokumentiert werden. 4. In Prozess A die Intent-Abweichung A1 bereinigen und die Rollentests um semantisch aussagekräftigere Szenarien ergänzen. 5. Danach dieselben read-only Tests erneut ausführen und, in einer geeigneten Umgebung, eine vollständige offline Flake-Evaluierung nachholen. Ein schreibender Live-IMAP-Test bleibt eine separate, ausdrücklich zu bestätigende Aktion. ## Schlussbewertung Prozess A erreicht seine Grundabsicht ohne neue Berechtigungen und ist nach kleiner Nacharbeit abnahmefähig. Prozess B erfüllt den normalen Happy Path im Fake-Backend, verletzt aber im Löschpfad eine zentrale Sicherheitsanforderung und unterschätzt externe Trust- sowie Recovery-Grenzen. Der grüne bestehende Testlauf widerlegt diese Befunde nicht, weil genau die kritischen Vorbedingungen und Teilfehler bisher nicht modelliert werden.