- 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.
546 lines
29 KiB
Markdown
546 lines
29 KiB
Markdown
# 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.
|