# AUTH.3C — C5 EXECUTOR RUNTIME ISOLATION DESIGN **Status:** DESIGN + VERIFIED DEPLOYMENT PLAN (STRICT READ-ONLY, KEIN produktiver Umbau) **Datum:** 2026-08-27 **Mission Type:** STRICT READ-ONLY DISCOVERY + ARCHITECTURE DESIGN + ISOLATED VALIDATION **Baseline:** AUTH.1 (40bbc40) + AUTH.2 (edcb4902) + AUTH.3A (a11c1bb) + AUTH.3B = COMPLETE > ⚠️ Dies ist ein **Design-Dokument**. Es wird KEIN produktiver Umbau ausgeführt, > kein Container erstellt, keine Compose/Network/Volume/DB geändert, kein echtes > Credential erzeugt, keine ENV geändert, kein Deployment, keine produktive > Tolaria-Mutationsprobe. Bei Zweifel: FAIL CLOSED + HARD STOP. --- ## 1. CURRENT EXECUTION FLOW (Phase 1) — rekonstruiert ### 1a. SAVE-Pfad: RQ/Hermes → C5 CLI → C5CPropagator → TolariaClient.write() ``` RQ/Hermes (Container 06a4a73573d0, User hermes uid 10010) │ ├─ [Entry Point] rq_c5_cli.py (argparse CLI, manuell aufgerufen) │ KEIN CLI-Command führt C5CPropagator mit save_token aus (verifiziert) │ ├─ [Library] rq_c5c.py C5CPropagator (Z.497) │ __init__(store, reader, client=None, ...) → client = client or TolariaClient() │ Default: credential-frei (kein save_token) │ write() → self.client.write(vault_path, after_content) (Z.638) │ └─ [Library] rq_c5c.py TolariaClient.write() (Z.322) token = self._require_token(self.save_token, "SAVE") # fail-closed → POST /api/vault/save (Bearer save_token) ``` **Boundary-Fakten (SAVE):** - **Process Boundary:** C5CPropagator läuft im RQ/Hermes-Prozess (kein separater Prozess). - **Container Boundary:** RQ-Container `06a4a73573d0` (User `hermes`, uid 10010, gid 10000). - **Filesystem Boundary:** `/opt/data` (RQ-Container-Dateisystem); C5-DB `/opt/data/c5c_live/c5a.db`. - **ENV Boundary:** `TOLARIA_SAVE_TOKEN` ABSENT im RQ-Container (verifiziert). `C5A_DB` steuert DB-Pfad. - **Network Boundary:** Tolaria `187.124.31.123:5173` (auch 10.0.4.1/10.0.9.1); Forgejo 10.0.4.1:3000/10.0.9.1:3000. - **DB-Zugriff:** C5AStore → SQLite `c5a.db` (Commit-State, ObjectChanges, Approvals, Ledger). - **Forgejo-Zugriff:** GitReader liest Repo `nexo312/trading-system-docs` (Forgejo-Git-Push-Key). - **Tolaria-Zugriff:** `write()` (SAVE) via `TolariaClient`. - **Approval-DB-Zugriff:** C5AStore (delete_approvals-Tabelle) — SAVE-Pfad liest/schreibt sie nicht aktiv. - **Benötigte Inputs:** Commit-SHA, ObjectChanges, Source-/Provenance-Daten aus Forgejo. - **Erzeugte Outputs:** Tolaria-SAVE, C5-State-Update (PROPAGATING→VERIFYING→UPDATING_SEARCH). ### 1b. DELETE-Pfad: RQ/Hermes → C5 CLI → DeleteExecutor → Approval Validation → TolariaClient.delete() ``` RQ/Hermes (Container 06a4a73573d0) │ ├─ [Entry Point] rq_c5_cli.py cmd_c5_delete_approve (Z.355) → persistiert Human-Approval ├─ [Entry Point] rq_c5_cli.py cmd_c5_delete_execute (Z.424) → führt DELETE aus ├─ [Entry Point] rq_c5_cli.py cmd_c5_delete_replay (Z.458) → idempotenter Replay │ ├─ [Helper] rq_c5_cli.py _delete_executor (Z.344) │ TolariaClient(base_url, delete_token=os.environ.get(ENV_TOLARIA_DELETE_TOKEN)) │ → liest NUR DELETE-Token (kein SAVE-Token) │ ├─ [Library] rq_c5_delete.py DeleteExecutor (Z.83) │ __init__(store, client=None) → client = client or TolariaClient() (Default credential-frei) │ execute(commit_sha) (Z.192): │ Gate 1: ObjectChange existiert, operation == DELETE │ Gate 2: Commit-Status == ST_DELETE_APPROVED │ Gate 3: Approval existiert, APPROVED, passt exakt (Commit/Objekt/Pfad) │ Gate 4: Pre-Delete-Drift-Check (Ziel existiert noch) │ → _do_delete() → self.client.delete() (DELETE) │ └─ [Library] rq_c5c.py TolariaClient.delete() (Z.~352) token = self._require_token(self.delete_token, "DELETE") # fail-closed → POST /api/vault/delete (Bearer delete_token) ``` **Boundary-Fakten (DELETE):** - **Process Boundary:** DeleteExecutor läuft im RQ/Hermes-Prozess (kein separater Prozess). - **Container Boundary:** RQ-Container `06a4a73573d0` — **SELBER Container wie SAVE**. - **Filesystem Boundary:** `/opt/data`; C5-DB `/opt/data/c5c_live/c5a.db`. - **ENV Boundary:** `TOLARIA_DELETE_TOKEN` ABSENT im RQ-Container (verifiziert). - **Network Boundary:** Tolaria `187.124.31.123:5173`. - **DB-Zugriff:** C5AStore → SQLite `c5a.db` (Approvals, Ledger, Commit-State). - **Forgejo-Zugriff:** GitReader (Provenance-/Object-Daten). - **Tolaria-Zugriff:** `delete()` (DELETE) via `TolariaClient`. - **Approval-DB-Zugriff:** C5AStore delete_approvals-Tabelle (lesen + USED markieren). - **Benötigte Inputs:** Commit-SHA, persistierte Approval, ObjectChange, Nonce. - **Erzeugte Outputs:** Tolaria-DELETE, Approval→USED, Commit→ST_UPDATING_SEARCH. ### 1c. Kernbefund (bestätigt AUTH.3B) **SAVE- und DELETE-Caller laufen im SELBEN Prozess/Container** (`rq_c5_cli.py`, RQ-Container `06a4a73573d0`). **CREDENTIAL_SEPARATION_STATUS = LOGICAL_ONLY.** Sobald Credentials produktiv in denselben Container injiziert würden, wäre RQ_SAVE_ACCESS/DELETE_ACCESS technisch NICHT mehr NO. → AUTH.4 BLOCKED. --- ## 2. MINIMUM EXECUTOR CAPABILITIES (Phase 2) — Least Privilege ### SAVE EXECUTOR (maximal benötigt) | Capability | Klassifikation | |---|---| | C5 Work Package/Input lesen | REQUIRED | | Source-/Provenance-Daten lesen (Forgejo) | REQUIRED | | Tolaria READ (falls erforderlich) | REQUIRED (Verifikation) | | Tolaria SAVE | REQUIRED | | C5 State Updates (c5a.db) | REQUIRED | | Tolaria DELETE | NOT_REQUIRED | | Forgejo Admin | NOT_REQUIRED | | Docker | NOT_REQUIRED | | SSH | NOT_REQUIRED | | Host Root | NOT_REQUIRED | | DELETE Credential | NOT_REQUIRED | | Search-Rebuild Credential | NOT_REQUIRED (sofern nicht zwingend) | ### DELETE EXECUTOR (maximal benötigt) | Capability | Klassifikation | |---|---| | Konkreten Delete-Auftrag lesen | REQUIRED | | Persistierte Approval lesen/verifizieren | REQUIRED | | Object/Commit/Nonce prüfen | REQUIRED | | Tolaria DELETE | REQUIRED | | Delete Ledger aktualisieren | REQUIRED | | Tolaria SAVE | NOT_REQUIRED | | Forgejo Admin | NOT_REQUIRED | | Docker | NOT_REQUIRED | | SSH | NOT_REQUIRED | | Host Root | NOT_REQUIRED | | SAVE Credential | NOT_REQUIRED | > **UNKNOWN darf nicht als REQUIRED angenommen werden.** Alle oben als REQUIRED > markierten Capabilities sind aus dem Code verifiziert (nicht angenommen). --- ## 3. ISOLATION OPTIONS (Phase 3) — Bewertung > ⚠️ NUR BEWERTUNG. KEINE Container/Networks/Volumes erstellen. ### OPTION A — Ein separater C5-Executor-Container mit SAVE+DELETE - **SECURITY_BOUNDARY:** RQ↔Executor getrennt; aber SAVE+DELETE im selben Executor. - **RQ_SECRET_VISIBILITY:** RQ kann Executor-Secrets nicht lesen (Container-Boundary). - **SAVE_DELETE_ISOLATION:** **NEIN** — SAVE und DELETE im selben Container. - **FILESYSTEM_ISOLATION:** RQ↔Executor getrennt; SAVE/DELETE gemeinsam. - **ENV_ISOLATION:** RQ↔Executor getrennt; SAVE/DELETE-ENV gemeinsam. - **NETWORK_ISOLATION:** Executor-Netzwerk getrennt von RQ. - **PROCESS_ISOLATION:** Executor-Prozess getrennt von RQ. - **CREDENTIAL_BLAST_RADIUS:** Ein Kompromiss des Executors = SAVE+DELETE beide offen. - **DB_ACCESS:** Executor braucht c5a.db (Schreibzugriff). - **QUEUE_REQUIREMENT:** Nein (CLI/Inbox möglich). - **OPERATIONAL_COMPLEXITY:** Mittel (ein Container mehr). - **FAIL_CLOSED:** Ja. - **RECOVERY:** Einfach (ein Container). - **AUDITABILITY:** Mittel. - **CURRENT_STACK_COMPATIBILITY:** Hoch (Coolify/Compose vorhanden). - **IMPLEMENTATION_EFFORT:** Mittel. - **Fazit:** Verbessert RQ-Isolation, aber **löst SAVE/DELETE-Trennung NICHT** — nur LOGICAL_ONLY→Container-Ebene, nicht Scope-Ebene. ### OPTION B — Zwei getrennte Container: c5-save-executor + c5-delete-executor - **SECURITY_BOUNDARY:** RQ↔SAVE↔DELETE je getrennt. - **RQ_SECRET_VISIBILITY:** RQ kann beide nicht lesen. - **SAVE_DELETE_ISOLATION:** **JA** — SAVE- und DELETE-Credential in getrennten Containern. - **FILESYSTEM_ISOLATION:** SAVE- und DELETE-FS getrennt. - **ENV_ISOLATION:** SAVE- und DELETE-ENV getrennt. - **NETWORK_ISOLATION:** SAVE- und DELETE-Netzwerk getrennt. - **PROCESS_ISOLATION:** SAVE- und DELETE-Prozess getrennt. - **CREDENTIAL_BLAST_RADIUS:** Minimal — SAVE-Kompromiss berührt DELETE nicht und umgekehrt. - **DB_ACCESS:** Beide brauchen c5a.db (Schreibzugriff) — **Konflikt mit DB-Isolation (Phase 7)**. - **QUEUE_REQUIREMENT:** Nein (CLI/Inbox möglich). - **OPERATIONAL_COMPLEXITY:** Höher (zwei Container mehr). - **FAIL_CLOSED:** Ja. - **RECOVERY:** Mittel (zwei Container). - **AUDITABILITY:** Hoch. - **CURRENT_STACK_COMPATIBILITY:** Hoch (Coolify/Compose vorhanden). - **IMPLEMENTATION_EFFORT:** Höher. - **Fazit:** **Erfüllt die Zielarchitektur** (SAVE≠DELETE technisch getrennt). Bevorzugt, sofern DB-Isolation lösbar. ### OPTION C — Separate Unix-Prozesse im selben Container, unterschiedliche Secret-Files/Usern - **SECURITY_BOUNDARY:** Nur Prozess-Ebene; **gleicher Container/FS/ENV**. - **RQ_SECRET_VISIBILITY:** RQ (User hermes) könnte Secret-Files lesen, wenn gleiche Rechte. - **SAVE_DELETE_ISOLATION:** Nur wenn getrennte Unix-User + Dateirechte; **fragil**. - **FILESYSTEM_ISOLATION:** Nur via Dateirechte (kein echtes FS-Isolation). - **ENV_ISOLATION:** **NEIN** — gleiche ENV im Container. - **NETWORK_ISOLATION:** **NEIN** — gleiche Netzwerk-Namespace. - **PROCESS_ISOLATION:** Teilweise (getrennte Prozesse, gleicher Kernel/Container). - **CREDENTIAL_BLAST_RADIUS:** Mittel — Container-Kompromiss = beide offen. - **DB_ACCESS:** Beide c5a.db. - **QUEUE_REQUIREMENT:** Nein. - **OPERATIONAL_COMPLEXITY:** Niedrig. - **FAIL_CLOSED:** Ja. - **RECOVERY:** Einfach. - **AUDITABILITY:** Niedrig. - **CURRENT_STACK_COMPATIBILITY:** Hoch (kein neuer Container). - **IMPLEMENTATION_EFFORT:** Niedrig. - **Fazit:** **NICHT ausreichend** — ENV-Isolation fehlt, RQ (User hermes) könnte Secrets lesen. Verletzt RQ_SECRET_VISIBILITY=NO. ### OPTION D — Sidecar-/Broker-Modell - **SECURITY_BOUNDARY:** Broker vermittelt; Executoren getrennt. - **RQ_SECRET_VISIBILITY:** RQ sieht Secrets nicht (nur Broker). - **SAVE_DELETE_ISOLATION:** Ja, wenn Broker getrennte Executoren ansteuert. - **FILESYSTEM_ISOLATION:** Ja (getrennte Container). - **ENV_ISOLATION:** Ja. - **NETWORK_ISOLATION:** Ja. - **PROCESS_ISOLATION:** Ja. - **CREDENTIAL_BLAST_RADIUS:** Minimal. - **DB_ACCESS:** Broker + Executoren. - **QUEUE_REQUIREMENT:** **Ja** (Broker = Queue) — **neue Infrastruktur, NICHT vorhanden**. - **OPERATIONAL_COMPLEXITY:** Hoch. - **FAIL_CLOSED:** Ja. - **RECOVERY:** Komplex. - **AUDITABILITY:** Hoch. - **CURRENT_STACK_COMPATIBILITY:** **Niedrig** — kein Broker/Queue im Stack. - **IMPLEMENTATION_EFFORT:** Hoch. - **Fazit:** **Abgelehnt** — erfordert neue Infrastruktur (Broker/Queue), die nicht vorhanden ist. Verletzt "KEINE neue Infrastruktur deployen". ### OPTION E — Queue-basierte Executor-Trennung (falls vorhandene Infrastruktur geeignet) - **SECURITY_BOUNDARY:** Queue entkoppelt RQ von Executoren. - **RQ_SECRET_VISIBILITY:** RQ sieht Secrets nicht. - **SAVE_DELETE_ISOLATION:** Ja, wenn getrennte Queues/Executoren. - **FILESYSTEM_ISOLATION:** Ja. - **ENV_ISOLATION:** Ja. - **NETWORK_ISOLATION:** Ja. - **PROCESS_ISOLATION:** Ja. - **CREDENTIAL_BLAST_RADIUS:** Minimal. - **DB_ACCESS:** Executoren. - **QUEUE_REQUIREMENT:** **Ja** — **keine Queue im Stack vorhanden** (verifiziert: kein RabbitMQ, kein Broker). - **OPERATIONAL_COMPLEXITY:** Hoch. - **FAIL_CLOSED:** Ja. - **RECOVERY:** Komplex. - **AUDITABILITY:** Hoch. - **CURRENT_STACK_COMPATIBILITY:** **Niedrig** — keine vorhandene Queue. - **IMPLEMENTATION_EFFORT:** Hoch. - **Fazit:** **Abgelehnt** — keine vorhandene Queue-Infrastruktur; würde neue Infrastruktur erfordern. ### OPTION F — Andere MINIMAL sichere Variante - **Kandidat F1: RQ credential-frei + SAVE/DELETE als getrennte Container (B) mit getrennter DB-View.** Kombiniert B (Container-Trennung) mit minimaler DB-Boundary (Phase 7): SAVE-Executor bekommt nur Commit/ObjectChange-Read + State-Write auf eigene Tabellen; DELETE-Executor nur Approval/Ledger. **Bevorzugt**, da es die Zielarchitektur mit vorhandener Infrastruktur erfüllt. - **Kandidat F2: RQ credential-frei + SAVE/DELETE als getrennte Container (B) mit geteilter c5a.db.** Falls DB-Trennung nicht sauber möglich: geteilte c5a.db, aber SAVE-Executor erhält KEIN DELETE-Credential und umgekehrt. **Akzeptabel**, aber DB-Boundary schwächer. --- ## 4. PREFERRED ARCHITECTURE (Phase 4) **Gewählt: OPTION B (zwei getrennte Container) mit OPTION F1 (minimale DB-Boundary).** ``` RQ/Hermes (Container 06a4a73573d0) — credential-frei │ credential-freier Auftrag (CLI/Inbox, kein Secret) ▼ +---------------------------+ +-----------------------------+ | c5-save-executor (Cont.) | | c5-delete-executor (Cont.) | | SAVE credential | | DELETE credential | | NO DELETE | | NO SAVE | | Tolaria SAVE + READ | | Tolaria DELETE | | c5a.db: Commit/Object-Read| | c5a.db: Approval/Ledger | +---------------------------+ +-----------------------------+ │ SAVE (Bearer save_token) │ DELETE (Bearer delete_token) ▼ ▼ Tolaria Server (187.124.31.123:5173) — erwartet SAVE+DELETE-Verifier ``` **Begründung (Priorität):** 1. **Credential-Isolation:** SAVE- und DELETE-Credential in getrennten Containern → RQ kann keins lesen, SAVE-Executor kann DELETE nicht, DELETE-Executor kann SAVE nicht. 2. **Fail-Closed:** Beide Executoren erben `_require_token` (AUTH.3A) — fehlendes/leeres Token → lokaler Abbruch. 3. **DELETE-Blast-Radius minimieren:** DELETE-Executor isoliert, kein SAVE-Credential, Human Gate bleibt. 4. **Auditierbarkeit:** Getrennte Container → getrennte Logs/Netzwerk. 5. **Wiederherstellbarkeit:** Getrennte Container → getrennter Rollback. 6. **Geringe Komplexität:** Keine neue Infrastruktur (Coolify/Compose vorhanden), kein Broker/Queue. **Gegen reale Infrastruktur geprüft:** - Coolify/Compose vorhanden → Container-Erstellung möglich (in AUTH.4, nicht jetzt). - Kein Broker/Queue → CLI/Inbox-Channel (Phase 5), keine neue Infrastruktur. - c5a.db SQLite → DB-Boundary via getrennte Tabellen/Dateien (Phase 7). --- ## 5. RQ → EXECUTOR COMMAND CHANNEL (Phase 5) > ⚠️ NUR BEWERTUNG. KEINE neue Infrastruktur deployen. ### Optionen | Option | AUTH | AUTHZ | REPLAY_PROT | IDEMPOTENCY | JOB_ID | MISSION_ID | ACTION_HASH | AUDIT | FAIL_CLOSED | RQ_CAN_FORGE | RQ_CAN_ESCALATE | EXEC_CAN_VALIDATE | |---|---|---|---|---|---|---|---|---|---|---|---|---| | **CLI (bestehend)** | OS-User | CLI-Arg | Nein (manuell) | Ja (Commit-SHA) | Commit-SHA | Nein | Nein | Shell-History | Ja | Ja (RQ ruft auf) | Nein (kein Secret) | Ja (Gates) | | **Filesystem Inbox** | FS-Rechte | Datei | Teilweise | Ja | Dateiname | Nein | Nein | Datei-Meta | Ja | Ja | Nein | Ja | | **SQLite Job Queue** | DB-Rechte | Job-Record | Teilweise | Ja | Job-ID | Ja | Ja | DB-Ledger | Ja | Ja | Nein | Ja | | **RabbitMQ** | — | — | — | — | — | — | — | — | — | — | — | — | (nicht vorhanden) | | **HTTP Internal API** | Token | Scope | Nein | Ja | Job-ID | Ja | Ja | Server-Log | Ja | Ja | Nein | Ja | | **Unix Socket** | FS-Rechte | Peer | Nein | Ja | Job-ID | Ja | Ja | Socket-Log | Ja | Ja | Nein | Ja | | **C5 State Machine** | DB-Rechte | State | Teilweise | Ja | Commit-SHA | Ja | Ja | DB-Ledger | Ja | Ja | Nein | Ja | **Bewertung:** - **CLI (bestehend)** ist der **einfachste, vorhandene** Kanal. RQ ruft `c5-save-executor`/`c5-delete-executor` als CLI auf. **RQ_CAN_FORGE_JOB = Ja** (RQ kann jeden Auftrag formulieren), aber **RQ_CAN_ESCALATE_SCOPE = Nein** (RQ hat kein Secret, kann nur beauftragen, nicht selbst schreiben). Der Executor validiert den Auftrag selbst (Gates). - **SQLite Job Queue / C5 State Machine** sind die **robustesten** (JOB_ID, MISSION_ID, ACTION_HASH, DB-Ledger, Replay-Schutz). Nutzt vorhandene c5a.db — **keine neue Infrastruktur**. - **RabbitMQ/HTTP/Socket** erfordern neue Infrastruktur oder neue Endpoints → **abgelehnt** (Scope-Creep). **Empfehlung:** **CLI (bestehend) als primärer Kanal** für SAVE; **C5 State Machine (c5a.db) als primärer Kanal** für DELETE (Approval persistiert, Nonce, Single-Use, Replay-Schutz). Beide nutzen vorhandene Infrastruktur. ### DELETE-spezifisch (RQ darf NICHT durch freien Auftrag einen Delete autorisieren) Der DELETE-Executor muss selbst prüfen (im Code verifiziert, rq_c5_delete.py): - **erlaubte Operation:** ObjectChange.operation == DELETE (Gate 1) - **Objekt:** ObjectChange existiert, genau einer (Gate 1) - **Commit:** Commit-Status == ST_DELETE_APPROVED (Gate 2) - **Approval:** existiert, APPROVED, passt exakt Commit/Objekt/Pfad (Gate 3) - **Nonce:** Approval single-use (→ USED nach DELETE) - **Single Use:** Approval→USED, kein Replay - **State:** Commit→ST_UPDATING_SEARCH nach DELETE - **Scope:** kein freier Pfad-Parameter (nur aus ObjectChange) --- ## 6. SECRET VISIBILITY PROOF (Phase 6) > ⚠️ NUR BEWEISFÜHRUNG. KEINE Secrets erzeugen/lesen. ### Zielarchitektur (OPTION B): Kann RQ SAVE/DELETE lesen? | Prüfpunkt | RQ→SAVE | RQ→DELETE | SAVE-Exec→DELETE | DELETE-Exec→SAVE | Rain→beide | |---|---|---|---|---|---| | **ENV** | Getrennte Container → NEIN | NEIN | NEIN | NEIN | NEIN | | **/proc** | Getrennte Container → NEIN | NEIN | NEIN | NEIN | NEIN | | **mounted files** | Getrennte Volumes → NEIN | NEIN | NEIN | NEIN | NEIN | | **shared volumes** | Keine geteilten Secret-Volumes → NEIN | NEIN | NEIN | NEIN | NEIN | | **Docker inspect** | Nur Host-Admin (nicht RQ) → NEIN | NEIN | NEIN | NEIN | NEIN | | **Compose** | Secret via .env/Coolify, nicht Plain ENV → NEIN | NEIN | NEIN | NEIN | NEIN | | **Logs** | Kein Secret-Logging (AUTH.3A) → NEIN | NEIN | NEIN | NEIN | NEIN | | **crash dumps** | Kein Secret in Dumps → NEIN | NEIN | NEIN | NEIN | NEIN | | **temp files** | Kein Secret in Temp → NEIN | NEIN | NEIN | NEIN | NEIN | | **DB** | c5a.db enthält keine Secrets → NEIN | NEIN | NEIN | NEIN | NEIN | | **IPC** | Getrennte Container → NEIN | NEIN | NEIN | NEIN | NEIN | | **shell history** | RQ ruft CLI ohne Secret-Arg → NEIN | NEIN | NEIN | NEIN | NEIN | **Ergebnis:** Mit OPTION B ist die Isolation **erreichbar** mit der aktuellen Infrastruktur (Coolify/Compose, getrennte Container, .env/Coolify-Secrets). **KEIN HARD STOP.** > ⚠️ **Einschränkung (ehrlich):** Die Isolation ist nur **technisch erreichbar**, wenn > die Secrets in getrennten Containern injiziert werden (nicht in den RQ-Container). > Solange SAVE/DELETE im RQ-Container lägen, wäre RQ_SECRET_VISIBILITY=NO NICHT garantiert. > Das ist genau der AUTH.3B-HARD-STOP, den OPTION B auflöst. --- ## 7. FILESYSTEM / DB SEPARATION (Phase 7) > ⚠️ NUR BEWERTUNG. KEINE DB erzeugen/verändern. ### Welche DBs brauchen die Executoren? | DB | SAVE-Executor | DELETE-Executor | RQ | |---|---|---|---| | **c5a.db (C5 State)** | Schreibzugriff (Commit/ObjectChange-State) | Schreibzugriff (Approval/Ledger) | Schreibzugriff | | **missions.db** | NEIN | NEIN | Ja (RQ) | | **safety.db** | NEIN | NEIN | Ja (RQ) | | **heartbeat.db** | NEIN | NEIN | Ja (RQ) | | **delete approvals** | NEIN (liest nicht) | **Ja** (lesen + USED) | Ja | | **attempt ledger** | NEIN | **Ja** (schreiben) | Ja | ### Muss SAVE-Executor Schreibzugriff auf dieselbe DB wie RQ haben? - **Nein, nicht auf missions/safety/heartbeat.** SAVE-Executor braucht nur c5a.db (Commit/ObjectChange). - **c5a.db geteilt mit RQ:** Ja, aber auf minimale Tabellen begrenzbar. ### Muss DELETE-Executor Schreibzugriff haben? - **Ja, auf c5a.db** (Approval→USED, Ledger, Commit-State). Nicht auf missions/safety/heartbeat. ### Kann Zugriff auf minimale Tabellen/DB-Dateien begrenzt werden? - **Ja, via getrennte SQLite-Dateien** (OPTION F1): SAVE-Executor → `c5a_save.db` (Commit/ObjectChange-Read + State-Write); DELETE-Executor → `c5a_delete.db` (Approval/Ledger). Oder via SQLite-View/Readonly-Connections. - **SQLite-Locking:** Getrennte Dateien vermeiden Lock-Konflikte zwischen SAVE- und DELETE-Executor. Geteilte Datei → WAL-Modus + kurze Transaktionen. **Empfehlung:** **Getrennte SQLite-Dateien** für SAVE- und DELETE-Executor (minimale DB-Boundary), RQ behält c5a.db als Orchestrierungs-State. Keine neue DB-Engine. --- ## 8. NETWORK POLICY DESIGN (Phase 8) > ⚠️ NUR DESIGN. KEINE Firewall-/Docker-Network-Änderung. ### SAVE-Executor (nur notwendige Ziele) | Ziel | Zugriff | |---|---| | Tolaria (187.124.31.123:5173) | **JA** (SAVE + READ) | | Forgejo (10.0.4.1:3000) | **JA** (Source-/Provenance-Read) | | Search | NEIN (kein Rebuild-Credential) | | Internet | NEIN | | Docker | NEIN | | Host SSH | NEIN | | Telegram | NEIN | ### DELETE-Executor (nur notwendige Ziele) | Ziel | Zugriff | |---|---| | Tolaria (187.124.31.123:5173) | **JA** (DELETE) | | Forgejo (10.0.4.1:3000) | **JA** (Object/Commit-Read) | | Search | NEIN | | Internet | NEIN | | Docker | NEIN | | Host SSH | NEIN | | Telegram | NEIN | **Ziel:** Beide Executoren erreichen nur Tolaria + Forgejo (interne State-Quellen). Kein Internet, kein Docker, kein SSH, kein Telegram. --- ## 9. FAILURE MODEL (Phase 9) > ⚠️ NUR ANALYSE. FAIL CLOSED. | Szenario | Verhalten | |---|---| | **SAVE-Executor down** | RQ kann nicht propagieren → Commit bleibt in READY/PROPAGATING. Kein Datenverlust. FAIL CLOSED. | | **DELETE-Executor down** | DELETE nicht ausführbar → Commit bleibt ST_DELETE_APPROVED. **Nichts wird gelöscht.** FAIL CLOSED. | | **RQ down** | Executoren warten auf Auftrag. Kein automatischer Write. FAIL CLOSED. | | **Tolaria down** | Executor → TolariaUnavailableError → Retry/DEAD (C5C-Modell). FAIL CLOSED. | | **DB locked** | SQLite-Lock → Retry/Fehler. Kein Write ohne State. FAIL CLOSED. | | **Queue unavailable** | CLI/Inbox → kein Queue-Abhängigkeit. FAIL CLOSED. | | **Credential missing** | `_require_token` → lokaler Abbruch (RC_AUTH_FAILURE). FAIL CLOSED. | | **Credential revoked** | Server → 401. Executor meldet Fehler. FAIL CLOSED. | | **malformed Job** | Executor-Gates → DeleteApprovalError/ExecutionError. FAIL CLOSED. | | **duplicate Job** | Idempotenz (Commit-SHA) → DELETE_ALREADY_AT_TARGET. Kein zweiter Write. | | **replayed Job** | Approval single-use (→ USED) → Replay denied. FAIL CLOSED. | | **Job stale** | Commit-Status ≠ ST_DELETE_APPROVED → denied. FAIL CLOSED. | | **Approval wrong** | Gate 3 (exakter Match) → denied. FAIL CLOSED. | | **Object wrong** | Gate 1 (genau ein DELETE-ObjectChange) → denied. FAIL CLOSED. | | **Commit wrong** | Gate 2 (Status) → denied. FAIL CLOSED. | | **Executor restart mid-operation** | Replay (idempotent) → Zustand aus c5a.db. Keine Sicherheitsinvariante verloren. | **Erwartung:** **FAIL CLOSED.** DELETE insbesondere: **Unklarheit = NICHT löschen.** --- ## 10. DELETE SPECIAL SECURITY (Phase 10) > ⚠️ NUR DESIGN. HUMAN_APPROVAL_AUTHENTICITY_GAP bleibt OPEN (AUTH.3D). **Zusätzliche Anforderungen für DELETE-Executor:** - **Eigener Container bevorzugt:** Ja (OPTION B, c5-delete-executor). - **Eigenes Credential:** Ja (TOLARIA_DELETE_TOKEN, getrennt von SAVE). - **Kein SAVE:** Ja (kein SAVE-Credential, kein SAVE-Endpoint-Zugriff). - **Human Approval zwingend:** Ja (Gate 3, persistierte Approval). - **Approval single-use:** Ja (→ USED nach DELETE). - **Object-bound:** Ja (Gate 1, genau ein DELETE-ObjectChange). - **Commit-bound:** Ja (Gate 2, ST_DELETE_APPROVED). - **Nonce-bound:** Ja (Approval-ID als Nonce). - **Replay-safe:** Ja (single-use + Idempotenz). - **Vollständiges Audit Ledger:** Ja (c5a.db delete_approvals + attempt ledger). - **Kein LLM kann Approval selbst erzeugen:** **NICHT garantiert** — HUMAN_APPROVAL_AUTHENTICITY_GAP=*** (Provenance nicht kryptographisch an Christian gebunden, `--approved-by` frei wählbar). **ABER:** HUMAN_APPROVAL_AUTHENTICITY_GAP bleibt OPEN. AUTH.3C modelliert ihn nur als Blocker, repariert ihn NICHT (AUTH.3D). --- ## 11. MIGRATION DESIGN (Phase 11) > ⚠️ NUR PLAN. KEINE AUSFÜHRUNG. **HEUTE:** RQ-Container ├ C5C Writer └ DeleteExecutor **ZIEL:** RQ-Container (credential-frei) + c5-save-executor + c5-delete-executor ### Atomare Schritte | Schritt | GOAL | FILES | CONTAINERS | MOUNTS | NETWORKS | DB | CREDENTIALS | TEST | ROLLBACK | HUMAN_GATE | PROD_IMPACT | |---|---|---|---|---|---|---|---|---|---|---|---| | **S1** | Executor-Code extrahieren (SAVE/DELETE als eigenständige CLI) | rq_c5c.py, rq_c5_delete.py → executor-Module | — | — | — | — | — | Unit-Tests | Git-Revert | Nein | Keine | | **S2** | c5-save-executor-Image bauen | Dockerfile | c5-save-executor | /app/vault? (nein) | c5-net | c5a_save.db | SAVE-Token (synthetisch) | Isolierte Tests | Image entfernen | Nein | Keine | | **S3** | c5-delete-executor-Image bauen | Dockerfile | c5-delete-executor | — | c5-net | c5a_delete.db | DELETE-Token (synthetisch) | Isolierte Tests | Image entfernen | Nein | Keine | | **S4** | RQ credential-frei machen (ENV-Tokens entfernen) | — | RQ | — | — | — | — | ENV-Check | ENV wiederherstellen | Nein | Keine (RQ hat keine Tokens) | | **S5** | Command-Channel (CLI/Inbox) verdrahten | rq_c5_cli.py | — | — | — | — | — | Integration | Git-Revert | Nein | Keine | | **S6** | Tolaria-Server-Auth aktivieren (AUTH.2) | — | tolaria | — | — | — | SAVE+DELETE-Verifier | T1-T26 | Rollback (WRITE_DEGRADED) | **Ja** | Write-Downtime-Fenster | | **S7** | SAVE-Aktivierung (produktiv) | — | c5-save-executor | — | — | — | SAVE-Token (echt) | T1-T26 | Executor stoppen | **Ja** | SAVE aktiv | | **S8** | DELETE-Aktivierung (produktiv) | — | c5-delete-executor | — | — | — | DELETE-Token (echt) | T1-T26 | Executor stoppen | **Ja** | DELETE aktiv | **Rollback:** Jeder Schritt einzeln revertierbar (Git-Revert, Image entfernen, ENV wiederherstellen, Executor stoppen). S6-Rollback = WRITE_DEGRADED_MODE (READ available, WRITE DENIED) — öffnet keine unauth Writes. --- ## 12. ISOLATED PROTOTYPE (Phase 12) > ⚠️ NUR falls vollständig ohne Produktion möglich. Sonst DESIGN_ONLY. **Klassifikation: DESIGN_ONLY** — Ein echter Isolation-PoC (getrennte Container) ist **nicht ohne Produktionsänderung** möglich, da Container-Erstellung/Netzwerk-Änderung produktive Infrastruktur berührt (verboten in AUTH.3C). Daher wird der PoC **nicht improvisiert**; die Boundary wird stattdessen durch **isolierte Unit/Integration-Tests** auf Prozess-Ebene validiert (synthetische Secrets, Fake-Tolaria, Temp-DB). **Isolierte Tests (T1–T15) — als Testplan definiert, in AUTH.4 ausführbar:** | Test | Nachweis | |---|---| | T1 | RQ ohne Secret → kein Write möglich | | T2 | SAVE-Executor sieht SAVE | | T3 | SAVE-Executor sieht DELETE nicht | | T4 | DELETE-Executor sieht DELETE | | T5 | DELETE-Executor sieht SAVE nicht | | T6 | SAVE kann Delete nicht | | T7 | DELETE kann Save nicht | | T8 | fehlendes Credential → fail-closed | | T9 | malformed Job → fail-closed | | T10 | duplicate/replay sicher | | T11 | Delete ohne Approval → denied | | T12 | Delete mit gefälschter Approval → denied (soweit heutiger Mechanismus erkennt) | | T13 | Executor restart verliert keine Sicherheitsinvariante | | T14 | keine Secrets in Logs | | T15 | keine Secrets in State DB | **ISOLATED_POC_STATUS: DESIGN_ONLY** (kein echter Container-PoC ohne Produktionsänderung möglich). --- ## 13. AUTH.3D DEPENDENCY (Phase 13) > ⚠️ NICHT vorwegnehmen — verifizieren. **Kann Runtime-Isolation abgeschlossen werden, während HUMAN_APPROVAL_AUTHENTICITY_GAP offen bleibt?** - **SAVE_RUNTIME_ISOLATION:** **READY** — unabhängig von Approval-Gap. SAVE-Executor braucht keine Human-Approval; die Container-Trennung (OPTION B) ist vollständig ohne Gap-Schließung umsetzbar. - **DELETE_RUNTIME_ISOLATION:** **technisch implementierbar** — die Container-Trennung (OPTION B) ist unabhängig vom Gap umsetzbar. Der DELETE-Executor kann isoliert deployed werden. - **DELETE_OPERATION_ACTIVATION:** **BLOCKED bis AUTH.3D** — solange HUMAN_APPROVAL_AUTHENTICITY_GAP=*** offen ist, darf DELETE produktiv nicht aktiviert werden (Provenance nicht kryptographisch an Christian gebunden). **AUTH3D_REQUIRED: JA** (für DELETE_OPERATION_ACTIVATION). --- ## 14. AUTH.4 REASSESSMENT (Phase 14) > ⚠️ NUR BEWERTUNG. KEINE Aktivierung. | Punkt | Status | Blocker | |---|---|---| | **SERVER_AUTH_DEPLOYMENT** | **CONDITIONALLY_READY** | AUTH.2-Code fertig; Deployment in AUTH.4 mit Human-Gate | | **SAVE_EXECUTOR_DEPLOYMENT** | **CONDITIONALLY_READY** | Container-Erstellung in AUTH.4; Code extrahieren (S1) | | **SAVE_ACTIVATION** | **CONDITIONALLY_READY** | Nach SAVE-Executor-Deployment + Server-Auth | | **DELETE_EXECUTOR_DEPLOYMENT** | **CONDITIONALLY_READY** | Container-Erstellung in AUTH.4; Code extrahieren (S1) | | **DELETE_CREDENTIAL_ACTIVATION** | **CONDITIONALLY_READY** | Nach DELETE-Executor-Deployment (Boundary gelöst) | | **DELETE_OPERATION_ACTIVATION** | **BLOCKED** | HUMAN_APPROVAL_AUTHENTICITY_GAP=*** bis AUTH.3D | | **HERMES_READ_ONLY_AUTONOMY** | **CONDITIONALLY_READY** | RQ credential-frei; READ ohne Credential | | **HERMES_BOUNDED_AUTONOMY** | **BLOCKED** | DELETE-Operation blockiert bis AUTH.3D | --- ## 15. FRESH CHECKER (Phase 15) > ⚠️ Wird als unabhängiger Subagent ausgeführt (deleg_60a862ee). --- ## 16. FINAL REPORT (Phase 16) > ⚠️ Wird nach Fresh Checker ausgefüllt.