- 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.
29 KiB
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(Userhermes, uid 10010, gid 10000). - Filesystem Boundary:
/opt/data(RQ-Container-Dateisystem); C5-DB/opt/data/c5c_live/c5a.db. - ENV Boundary:
TOLARIA_SAVE_TOKENABSENT im RQ-Container (verifiziert).C5A_DBsteuert 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) viaTolariaClient. - 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_TOKENABSENT 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) viaTolariaClient. - 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):
- Credential-Isolation: SAVE- und DELETE-Credential in getrennten Containern → RQ kann keins lesen, SAVE-Executor kann DELETE nicht, DELETE-Executor kann SAVE nicht.
- Fail-Closed: Beide Executoren erben
_require_token(AUTH.3A) — fehlendes/leeres Token → lokaler Abbruch. - DELETE-Blast-Radius minimieren: DELETE-Executor isoliert, kein SAVE-Credential, Human Gate bleibt.
- Auditierbarkeit: Getrennte Container → getrennte Logs/Netzwerk.
- Wiederherstellbarkeit: Getrennte Container → getrennter Rollback.
- 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 | — | — | — | — | — | — | — | — | — | — | — | — |
| 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-executorals 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-byfrei 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.