trading-system-docs/tolaria/tolaria-write-auth/AUTH3C_DESIGN.md
Red Queen 10761f52b2 AUTH.3E: Executor Command Channel + Runtime Boundary Contract
- job_schema: geschlossene Job-Type-Allowlist (C5_SAVE_OBJECT/C5_DELETE_OBJECT), Pfad-/Längen-Validierung
- job_state_machine: deterministische States (CREATED/READY/CLAIMED/EXECUTING/SUCCEEDED/FAILED)
- job_claim: atomare Claim-/Lease-/Recovery-Logik (kein TOCTOU)
- job_store: getrennte SQLite-Inbox-DBs (c5a_save.db/c5a_delete.db), delegiert an job_claim
- save_executor_core: SAVE-only, Content-Rekonstruktion, Provenance-Validierung
- delete_executor_core: DELETE-only, AUTH.3D-Composition, TOCTOU-Defense (Re-Read nach Claim)
- test_job_channel: T1-T40 + adversarial (72 Tests)
- test_job_channel_adversarial: adversarial + Substitution + DB-Manipulation
- sensitivity_proof_auth3e: Mutationen A-L (12/12 Invarianten PRESENT)
- AUTH3B/3C/3D/3E_DESIGN: autoritative Security-Dokumentation (e25 Reconciliation)

COMMAND != AUTHORIZATION. Kein generischer Dispatcher. RQ credential-free.
Keine produktive Mutation. Keine echten Credentials.
2026-08-27 10:03:32 +00:00

546 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 (T1T15) — 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.