trading-system-docs/tolaria/tolaria-write-auth/AUTH3B_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

40 KiB
Raw Permalink Blame History

AUTH.3B — SECRET / ENV / RUNTIME INJECTION DESIGN + DEPLOYMENT PRE-FLIGHT

Status: DESIGN + VERIFIED DEPLOYMENT PLAN (STRICT READ-ONLY, KEIN produktives Deployment) Datum: 2026-08-27 Mission Type: STRICT DESIGN + READ-ONLY DISCOVERY + ISOLATED TESTS Baseline: AUTH.1 (40bbc40) + AUTH.2 (edcb4902) + AUTH.3A (a11c1bb) = COMPLETE

⚠️ Dies ist ein Design-/Plan-Dokument. Es wird NICHTS produktiv deployt, kein Token erzeugt, keine ENV/Compose/Coolify geändert, kein Container restart/recreate, keine produktive Tolaria-Auth aktiviert.


1. RUNTIME DISCOVERY (Phase 1) — IST-Zustand

A) Tolaria Server

Attribut Wert
Container tolaria
Runtime Node.js 20 / Vite (dev server, vite.config.ts middleware)
Host Source /opt/tolaria/app/tolaria
Container Source /app/tolaria
Vault /opt/data/tolaria-vault/app/vault (Bind-Mount)
Compose /opt/tolaria/docker-compose.yml
Port 5173 (produktiv); Repo-vite.config.ts deklariert 5202 (dev)
Produktiver Source-Basisstand b5a5e4bd (VOR AUTH.2)
AUTH.2 deployed? NEIN — Produktion läuft noch OHNE neue Auth (verifiziert: save ohne Token → 200)
ENV erwartet (Code) TOLARIA_SAVE_TOKEN, TOLARIA_DELETE_TOKEN, TOLARIA_VAULT_ROOT (Default /app/vault)
Fail-closed JA — authorizeVaultWrite Z.120-123: leeres expected → 401 "Write scope not configured"

B) C5C Writer (SAVE)

Attribut Wert
Klasse C5CPropagator (rq_c5c.py Z.497)
Write-Methode TolariaClient.write() (Z.315) → POST /api/vault/save, Bearer mit save_token
Credential-Quelle NUR explizit injizierter Client (client=...); Default TolariaClient() credential-frei → fail-closed
ENV TOLARIA_SAVE_TOKEN (Konstante Z.100); rq_c5c.py liest ENV NICHT selbst
CLI-Entrypoint KEINER — kein CLI-Command ruft C5CPropagator mit save_token auf
Produktiver Aufrufer rq_c5f_resume.py (untracked) — konstruiert TolariaClient() OHNE save_token → mit AUTH.3A fail-closed
Runtime RQ-Container (06a4a73573d0), C5-DB /opt/data/c5c_live/c5a.db

C) C5 DeleteExecutor (DELETE)

Attribut Wert
Klasse DeleteExecutor (rq_c5_delete.py)
Write-Methode TolariaClient.delete() → POST /api/vault/delete, Bearer mit delete_token
Credential-Quelle _delete_executor (rq_c5_cli.py Z.344): delete_token=os.environ.get(ENV_TOLARIA_DELETE_TOKEN)
ENV TOLARIA_DELETE_TOKEN (Konstante Z.101)
CLI-Entrypoint c5-delete-execute, c5-delete-replay (Human-Gated)
Runtime RQ-Container (06a4a73573d0), C5-DB /opt/data/c5c_live/c5a.db

D) Red Queen / Hermes

Attribut Wert
Container 06a4a73573d0 (RQ/Hermes)
C5-Caller laufen IM RQ-Container (C5-DB /opt/data/c5c_live/c5a.db)
Docker-Daemon NICHT verfügbar aus RQ-Container (kein /var/run/docker.sock)
VPS-Host-SSH NICHT verfügbar (Key red_queen_forgejo nur für Forgejo-Git-Push)
Tolaria-API read-only erreichbar (187.124.31.123:5173)

E) Rain / OpenClaw

Attribut Wert
Ports 55163 (Alice), 54524 (Matt Addison)
Zugriff auf C5-DB NICHT verifiziert (separate Container)
Tolaria-Write-Credential KEIN (Architektur-Invariante)

2. KRITISCHER BEFUND (Phase 7-Vorab)

SAVE-Caller (C5CPropagator) und DELETE-Caller (DeleteExecutor) laufen im SELBEN Prozess/Container (RQ-Container 06a4a73573d0). Es existiert KEINE getrennte Runtime-Boundary zwischen SAVE und DELETE. Beide Credentials würden, wenn beide injiziert würden, im selben Container landen.

Konsequenz: Die Credential-Separation (SAVE≠DELETE) ist heute NUR logisch (verschiedene ENV-Namen, verschiedene Klassen), NICHT technisch als getrennte Security Boundaries. Das muss in Phase 7 explizit dokumentiert und in Phase 3/4 bewertet werden.


2b. SECURITY BOUNDARY ANALYSIS (Phase 2) — IST-Zustand

Runtime-Fakten (verifiziert)

  • RQ/Hermes-Container = 06a4a73573d0, User hermes (uid 10010, gid 10000).
  • Kein Docker-Socket im RQ-Container (/var/run/docker.sock fehlt) → RQ kann keine anderen Container inspizieren.
  • Kein VPS-Host-SSH (Key red_queen_forgejo nur für Forgejo-Git-Push) → RQ kann Host-Dateien (/opt/tolaria, Compose) NICHT lesen.
  • Kein /opt/tolaria im RQ-Container-Dateisystem.
  • /proc im RQ-Container zeigt nur eigene Prozesse (24 PIDs) → kein Cross-Container /proc-Zugriff.
  • Netzwerk: RQ erreicht Tolaria intern (10.0.4.1:5173{"ok":true}) und Forgejo (10.0.4.1:3000). Tolaria läuft in SEPARATEM Container auf VPS-Host.
  • C5-Caller: KEIN Daemon, KEIN separater Container. C5CPropagator (SAVE) und DeleteExecutor (DELETE) sind Library/CLI, die manuell im RQ-Container aufgerufen werden (Hermes-Gateway-Prozess). C5-DB /opt/data/c5c_live/c5a.db liegt im RQ-Container.
  • ENV im RQ-Container: TOLARIA_SAVE_TOKEN ABSENT, TOLARIA_DELETE_TOKEN ABSENT (korrekt — RQ credential-free). Vorhandene Secrets: FORGEJO_WRITE_TOKEN, NOTION_API_KEY, TELEGRAM_BOT_TOKEN, HERMES_SESSION_KEY (Namen, keine Werte).

CAN_*_READ_SECRET — SAVE und DELETE (identisch, da gleiche Boundary)

Akteur SAVE DELETE Weg
RQ/Hermes (Container 06a4a73573d0) NEIN (tatsächlich) NEIN (tatsächlich) Kein Docker-Socket, kein Host-SSH, kein /proc-Cross, kein /opt/tolaria. ENV ABSENT.
RQ/Hermes (theoretisch via root) JA (wenn Host-root) JA (wenn Host-root) Host-root kann Container-ENV via docker inspect/docker exec lesen.
Rain/OpenClaw (Alice 55163, Matt 54524) NEIN (tatsächlich) NEIN (tatsächlich) Separate Container, kein Zugriff auf RQ-ENV oder Tolaria-Container.
Anderer Container (Tolaria selbst) JA (eigener ENV) JA (eigener ENV) Tolaria-Container hält seine eigenen erwarteten Tokens.
Docker-Admin (VPS-Host) JA JA docker inspect/docker exec auf Tolaria-Container.
Host-Root (VPS) JA JA Liest Compose, .env, Container-ENV, Mounts.
C5C Writer (SAVE-Prozess) JA (SAVE) NEIN (kein DELETE) Erhält nur SAVE-Token via injiziertem Client.
DeleteExecutor (DELETE-Prozess) NEIN (kein SAVE) JA (DELETE) Erhält nur DELETE-Token via ENV.

Security-Boundary-Befund

  • Tolaria-Server = eigene Boundary (separater Container, VPS-Host).
  • RQ/Hermes = eigene Boundary (Container 06a4a73573d0), aber C5-Caller (SAVE+DELETE) laufen INNERHALB dieser Boundary.
  • CRITICAL: SAVE- und DELETE-Credential würden, wenn beide injiziert würden, im selben Container (06a4a73573d0) landen. Es gibt KEINE getrennte Runtime-Boundary zwischen SAVE-Caller und DELETE-Caller.
  • Konsequenz für Phase 3: Die Zielarchitektur "SAVE≠DELETE als getrennte Boundaries" ist mit dem realen Deployment NICHT vollständig erreichbar, solange beide Caller im selben RQ-Container laufen. Die Separation ist NUR logisch (verschiedene ENV-Namen, verschiedene Klassen, verschiedene CLI-Commands), NICHT technisch als getrennte Container/Prozesse.

3b. CREDENTIAL OWNERSHIP MODEL (Phase 3) — Zielarchitektur vs. Realität

Zielarchitektur (verbindlich aus Freigabe)

  • SAVE credential → Tolaria Server + C5C Writer
  • DELETE credential → Tolaria Server + C5 DeleteExecutor
  • RQ: KEIN SAVE, KEIN DELETE
  • Hermes generisch: KEIN SAVE, KEIN DELETE
  • Rain: KEIN SAVE, KEIN DELETE
  • Kein Master-Token
  • SAVE darf DELETE nicht autorisieren; DELETE darf SAVE nicht autorisieren

Erreichbarkeit mit realem Deployment

1) Server-seitige Auth (AUTH.2) — ERREICHBAR ✓

  • Tolaria-Server hält SAVE+DELETE-Tokens in seiner eigenen ENV (separater Container).
  • RQ/Hermes/Rain haben KEINEN Zugriff auf den Tolaria-Container (kein Docker-Socket, kein Host-SSH, kein /proc-Cross).
  • Server-seitige Scope-Trennung (SAVE≠DELETE) ist im Code verifiziert (AUTH.2).

2) Caller-seitige Credential-Separation — NICHT ERREICHBAR (HARD STOP-Kandidat) ✗

  • Ursache: C5C Writer (SAVE) und DeleteExecutor (DELETE) laufen im selben Container wie RQ/Hermes (06a4a73573d0). Es gibt KEINE getrennte Runtime-Boundary.
  • Wenn SAVE- und DELETE-Tokens in die ENV dieses Containers injiziert würden, hätte RQ/Hermes (das im selben Container läuft, gleicher User hermes) technischen Zugriff auf BEIDE Tokens.
  • Das verletzt die Zielarchitektur "RQ: KEIN SAVE KEIN DELETE" und "Hermes: KEIN SAVE KEIN DELETE" — unabhängig davon, ob RQ den Zugriff tatsächlich nutzt.

HARD STOP — exakte Ursache

Die Zielarchitektur "RQ/Hermes credential-free" ist mit dem realen Deployment NICHT erreichbar, solange die C5-Caller (SAVE+DELETE) im selben Container wie RQ/Hermes laufen und ihre Tokens in dessen ENV liegen.

Notwendige Voraussetzung für AUTH.4 (Architektur-Änderung, NICHT in AUTH.3B):

  • Option A (empfohlen): C5C Writer und DeleteExecutor in einen separaten Container/Prozess mit eigener Boundary verschieben, der NICHT der RQ-Container ist. RQ/Hermes ruft diesen Container nur über eine schmale Schnittstelle auf.
  • Option B: Tokens über einen separaten Secret-Store injizieren, auf den nur der C5-Caller-Prozess (nicht RQ/Hermes) Zugriff hat. Im selben Container mit gleichem User ist das praktisch nicht durchsetzbar (RQ kann dieselbe Datei lesen).

Ohne diese Änderung bleibt die Separation NUR logisch (verschiedene ENV-Namen, verschiedene Klassen, verschiedene CLI-Commands), NICHT technisch als getrennte Security Boundaries. Das wird NICHT stillschweigend abgeschwächt — es wird als HARD STOP für die volle Zielarchitektur dokumentiert.

Was TROTZDEM sicher erreichbar ist (ohne Architektur-Änderung)

  • Server-seitige Auth (AUTH.2) aktivieren: Tolaria-Server fail-closed, SAVE≠DELETE Scope-Trennung. RQ bleibt credential-free (kein Zugriff auf Tolaria-Container).
  • SAVE-Aktivierung: C5C Writer erhält SAVE-Token. ABER: da im RQ-Container, hätte RQ technisch Zugriff → verletzt "RQ credential-free" für SAVE.
  • DELETE-Aktivierung: DeleteExecutor erhält DELETE-Token. ABER: da im RQ-Container, hätte RQ technisch Zugriff → verletzt "RQ credential-free" für DELETE.

Fazit Phase 3

  • SERVER_AUTH_DEPLOYMENT: ERREICHBAR (RQ bleibt credential-free ggü. Tolaria).
  • SAVE_ACTIVATION / DELETE_CREDENTIAL_ACTIVATION: BLOCKED bis C5-Caller in getrennte Boundary verschoben ODER Secret-Injection RQ-undurchdringbar ist.
  • Kein Master-Token: ERREICHBAR (AUTH.2/AUTH.3A verifiziert, kein Master-Key).
  • SAVE≠DELETE Scope-Trennung: Server-seitig ERREICHBAR; Caller-seitig nur logisch.

4b. SECRET STORAGE OPTIONS (Phase 4) — Bewertung

Kontext: Was existiert im realen Stack?

  • Coolify-Suite ist auf dem VPS installiert (infrastructure-handbook Z.52).
  • Exakte Tolaria-Provisionierung (Compose vs Coolify) ist aus RQ-Sicht UNKNOWN (kein Docker-Socket, kein Host-SSH). CURRENT_STATE Z.27: "UNKNOWN: Container-Name/ Image-Konfiguration, Env-Variablen, Mounts, Volumes — nur über Host-/Docker-Zugriff ermittelbar, der nicht verfügbar ist."
  • Kein separater Secret-Store (kein Vault/Consul/SOPS/age) im Stack nachweisbar.
  • Kein Docker-Secrets-Mechanismus im Stack nachweisbar (kein Swarm).
  • Tolaria-Server liest ENV via process.env.TOLARIA_SAVE_TOKEN (vite.config.ts).

Optionen-Bewertung (SAVE und DELETE, identisch)

Kriterium A) Plain Compose ENV B) .env-Datei C) Docker Secrets D) read-only Secret-Datei E) Coolify Secret Mgmt F) separater Secret-Store
SECURITY Schwach (ENV in inspect) Mittel (Datei, chmod) Stark (nur im Container) Mittel (Datei, chmod) Stark (Coolify-UI) Stark
VISIBILITY docker inspect sichtbar Datei, nicht inspect Nicht in inspect Datei, nicht inspect Nicht in inspect Nicht in inspect
DOCKER_INSPECT_EXPOSURE JA NEIN NEIN NEIN NEIN NEIN
HOST_EXPOSURE JA (root liest) JA (root liest) JA (root liest) JA (root liest) JA (root liest) JA (root liest)
RQ_EXPOSURE JA (wenn im RQ-Container) JA (wenn im RQ-Container) NEIN (nur Ziel-Container) JA (wenn im RQ-Container) NEIN NEIN
ROTATION Restart nötig Restart nötig Restart nötig Restart nötig Restart nötig Restart nötig
REVOCATION ENV entfernen + Restart Datei löschen + Restart Secret entfernen + Restart Datei löschen + Restart ENV entfernen + Restart Store-Update + Restart
RESTART_BEHAVIOR ENV bleibt Datei bleibt Secret bleibt Datei bleibt ENV bleibt Store bleibt
BACKUP_BEHAVIOR ENV nicht in Backup Datei evtl. in Backup Secret nicht in Backup Datei evtl. in Backup ENV nicht in Backup Store in Backup
OPERATIONAL_COMPLEXITY Niedrig Niedrig Mittel (Swarm nötig) Niedrig Mittel Hoch
COMPATIBILITY Hoch (Vite liest ENV) Hoch Niedrig (kein Swarm) Hoch (Datei lesen) Mittel (Coolify vorhanden) Niedrig (nicht vorhanden)
BLAST_RADIUS Hoch (inspect) Mittel Niedrig Mittel Niedrig Niedrig

Empfehlung für UNSEREN Stack

Minimal sichere Variante: B) .env-Datei (oder D) read-only Secret-Datei) mit strikten Permissions, injiziert in die Tolaria-Container-ENV.

Begründung:

  • A (Plain Compose ENV) ist abzulehnen: docker inspect würde die Tokenwerte offenlegen (DOCKER_INSPECT_EXPOSURE=JA). Das verletzt die Anforderung "kein Secret in docker inspect".
  • C (Docker Secrets) ist nicht kompatibel: erfordert Docker Swarm, das im Stack nicht nachweisbar ist.
  • F (separater Secret-Store) ist nicht vorhanden: keine neue Infrastruktur erfinden (Freigabe-Anforderung).
  • E (Coolify Secret Mgmt): Coolify ist vorhanden, aber die exakte Tolaria- Provisionierung ist UNKNOWN. Falls Tolaria über Coolify deployed wird, ist Coolify Secret Management die natürliche Wahl (nicht in inspect, Rotation via UI).
  • B/D sind die robuste Default-Empfehlung: .env-Datei mit chmod 600, vom Compose/Coolify in die Container-ENV injiziert. Tokenwerte erscheinen NICHT in docker inspect (nur der ENV-Name, nicht der Wert, wenn via env_file injiziert).

WICHTIG (Phase 3-Kopplung): Unabhängig von der Storage-Option bleibt der HARD STOP bestehen: Solange die C5-Caller im RQ-Container laufen, würde jede Injektion in dessen ENV RQ technischen Zugriff geben. Die Storage-Empfehlung gilt daher primär für den Tolaria-Server-Container (eigene Boundary, RQ-fern).


5b. TOKEN GENERATION CONTRACT (Phase 5) — NUR DESIGN, KEINE echten Tokens

⚠️ Dies ist ein Design-Vertrag. Es wird KEIN echtes Token erzeugt, kein Wert angezeigt, nichts in ENV/Compose/Logs/Telegram/Repo geschrieben.

Kryptographische Zufallsquelle

  • /dev/urandom (Linux) oder secrets.token_urlsafe() (Python) — kryptographisch sicher, nicht-deterministisch.
  • NICHT: random-Modul, time-basiert, UUID (nicht krypto-sicher genug für Auth).

Mindestentropie

  • ≥ 256 Bit (32 Bytes) pro Token. Empfehlung: 32 Bytes aus /dev/urandom, base64url-kodiert → 43 Zeichen.

Format / Länge

  • Format: base64url (URL-sicher, kein +///=), 43 Zeichen bei 32 Bytes.
  • Länge: 43 Zeichen (256 Bit Entropie).
  • Keine semantischen Token-Präfixe (kein save-, delete-, tolaria- im Wert) — Präfixe wären unnötige Information und könnten Scope-Leaks erzeugen. Der Scope wird durch die ENV-Variable bestimmt, nicht durch den Tokenwert.

Unabhängigkeit

  • SAVE und DELETE unabhängig generiert (zwei separate /dev/urandom-Ziehungen).
  • Niemals gleicher Wert (bei 256 Bit Entropie kollisionsfrei).
  • Keine Ableitung SAVE→DELETE (kein Hash/Substring/Transformation).
  • Kein Master-Key (kein gemeinsamer Seed, kein hierarchisches Schema).

Nicht-Speicherung / Nicht-Ausgabe

  • Keine Shell-History (kein echo $TOKEN, kein Token in interaktiven Befehlen).
  • Keine Ausgabe in Telegram / Chat / Logs / FINAL REPORT.
  • Token wird NUR in die Ziel-ENV/Secret-Datei geschrieben (Tolaria-Server-Container), nie in Git, nie in Reports, nie in Test-Fixtures.

Wer die Tokens bei AUTH.4 erzeugen darf

  • Nur Christian (Mensch) — manuell auf dem VPS-Host, via /dev/urandom oder openssl rand -base64 32, direkt in die Secret-Datei/Coolify-ENV geschrieben.
  • NICHT RQ/Hermes/Rain — kein Agent erzeugt oder sieht die echten Tokens.
  • Erzeugung erfolgt im Rahmen der AUTH.4-Deployment-Sequenz (Phase 9), nicht in AUTH.3B.

6b. SERVER INJECTION CONTRACT (Phase 6) — AUTH.2 im Code verifiziert

Exakte ENV-Namen (im Code verifiziert, vite.config.ts Z.35-39)

  • TOLARIA_VAULT_ROOT → Default /app/vault
  • TOLARIA_SAVE_TOKENsaveToken (Scope SAVE)
  • TOLARIA_DELETE_TOKENdeleteToken (Scope DELETE)

Verhalten (im Code verifiziert, vault-write-guard.ts Z.112-131)

Feld Wert
SERVER_SAVE_ENV TOLARIA_SAVE_TOKEN
SERVER_DELETE_ENV TOLARIA_DELETE_TOKEN
MISSING_SAVE_BEHAVIOR expected.length === 0 → 401 "Write scope not configured" (fail-closed)
MISSING_DELETE_BEHAVIOR dito (fail-closed)
EMPTY_TOKEN_BEHAVIOR `
WRONG_SCOPE_BEHAVIOR constantTimeEqual(extracted, expected) → falscher Scope → 401 "Invalid credentials"

Fail-closed bestätigt

  • Kein "Auth disabled because ENV missing". Fehlende/leere Token-Konfiguration → mutierende Endpoints bleiben DENIED (401).
  • Scope-Trennung: SAVE-Token autorisiert NUR SAVE; DELETE-Token NUR DELETE.
  • Const-time-Vergleich (constantTimeEqual) gegen Timing-Angriffe.
  • Auth-before-Mutation: bei Auth-Fehler wird Response gesendet, KEINE Mutation.

Fazit Phase 6

  • SERVER_FAIL_CLOSED_STATUS = ENFORCED (im Code verifiziert).
  • Server erwartet exakt TOLARIA_SAVE_TOKEN + TOLARIA_DELETE_TOKEN.
  • Kein Master-Token, keine Scope-Abschwächung.

7b. CALLER INJECTION CONTRACT (Phase 7) — AUTH.3A im Code verifiziert

ENV-Contract (im Code verifiziert, rq_c5c.py Z.100-101)

  • ENV_TOLARIA_SAVE_TOKEN = "TOLARIA_SAVE_TOKEN"
  • ENV_TOLARIA_DELETE_TOKEN = "TOLARIA_DELETE_TOKEN"

Credential-Verwendung (im Code verifiziert)

Caller ENV Verwendung Scope
C5C Writer (C5CPropagator) TOLARIA_SAVE_TOKEN write() Z.322: self._require_token(self.save_token, "SAVE") SAVE
DeleteExecutor TOLARIA_DELETE_TOKEN delete() Z.352: self._require_token(self.delete_token, "DELETE") DELETE
read/list KEIN Credential READ

Verifizierte Invarianten

  • SAVE-Prozess bekommt DELETE nicht: write() nutzt NUR self.save_token.
  • DELETE-Prozess bekommt SAVE nicht: delete() nutzt NUR self.delete_token.
  • read/list brauchen nichts: read()/list() senden kein Bearer.
  • fehlendes Token => kein HTTP Write: _require_token (Z.300-313) bricht lokal ab (RC_AUTH_FAILURE), HTTP wird NICHT aufgerufen (fail-closed, AUTH.1 §4).
  • Retry behält Credential: Client-Instanz hält Token über Retries hinweg.
  • Replay behält Credential: c5-delete-replay nutzt denselben _delete_executor.
  • Token wird nicht persistiert: kein Token in DB/Logs/Reports (AUTH.3A verifiziert).

KRITISCHER BEFUND (Runtime-Separation)

  • Sind C5C Writer und DeleteExecutor heute getrennte Runtime-Prozesse/Boundaries? NEIN.
  • Beide laufen im selben Container (06a4a73573d0, RQ/Hermes) und werden als Library/CLI im selben Hermes-Gateway-Prozess aufgerufen.
  • Konsequenz: Die Credential-Separation ist NUR logisch (verschiedene ENV-Namen, verschiedene Klassen, verschiedene CLI-Commands). Wenn beide Tokens in die ENV dieses Containers injiziert würden, hätte RQ/Hermes technischen Zugriff auf BEIDE.
  • Das wird NICHT als technische Separation behauptet. Es ist explizit dokumentiert: CREDENTIAL_SEPARATION_STATUS = LOGICAL_ONLY (nicht technisch).

Fazit Phase 7

  • CALLER_FAIL_CLOSED_STATUS = ENFORCED (im Code verifiziert).
  • CREDENTIAL_SEPARATION_STATUS = LOGICAL_ONLY (nicht technisch, da gleiche Boundary).
  • Least Privilege im Code korrekt; Runtime-Separation fehlt (HARD STOP aus Phase 3).

8b. HUMAN APPROVAL INTERACTION (Phase 8) — AUTH4_WITH_OPEN_APPROVAL_GAP

Kontext

  • HUMAN_APPROVAL_AUTHENTICITY_GAP = OPEN (aus AUTH.3A, NICHT repariert). Die DELETE-Approval erfüllt Invarianten AN, aber die Provenance ist nicht kryptographisch an Christian gebunden (frei wählbares CLI-Argument --approved-by, rq_c5_cli.py Z.576).
  • DELETE-Execution (AUTH.3A, rq_c5_delete.py Z.192-251): 4 Pre-Gates:
    1. ObjectChange existiert + operation == DELETE
    2. Commit-Status == ST_DELETE_APPROVED
    3. Approval existiert, APPROVED, passt exakt (Commit/Objekt/Pfad) ← Human Gate
    4. Pre-Delete-Drift-Check (Ziel existiert noch)

Wie interagiert das DELETE-Token mit dem Human Gate?

  • Das DELETE-Token (AUTH.2/AUTH.3A) ist eine zusätzliche, unabhängige Bedingung auf Transport-Ebene: delete() sendet Bearer DELETE-Token; Server verweigert ohne gültiges Token (401).
  • Das Human Approval Gate (Gate 3) ist eine separate Bedingung auf Anwendungs-Ebene: execute() verweigert ohne persistierte, exakt passende Approval.
  • DELETE ist nur möglich, wenn BEIDES erfüllt ist: A) gültiges DELETE-Credential (Server-Auth) UND B) bestehendes C5 Human Approval Gate (Gate 3).

Verschärft AUTH.4 das Authenticity-Gap?

  • NEIN. AUTH.4 fügt eine zusätzliche Hürde (DELETE-Token) hinzu, die das bestehende Gap NICHT verschärft, sondern die DELETE-Ausführung zusätzlich absichert.
  • Das Gap (Provenance nicht kryptographisch an Christian gebunden) bleibt bestehen, wird aber durch das DELETE-Token NICHT schwächer. Ein Angreifer, der das Authenticity-Gap ausnutzt (frei wählbares --approved-by), bräuchte ZUSÄTZLICH das DELETE-Token, um tatsächlich zu löschen.
  • Kein Risiko, dass durch das DELETE-Token ein schwächeres Human Gate akzeptiert wird. Das Human Gate (Gate 3) bleibt unverändert ENFORCED.

Klassifikation

AUTH4_WITH_OPEN_APPROVAL_GAP = SAFE_FOR_SERVER_AUTH_ONLY

Begründung:

  • Die Einführung des DELETE-Tokens (Server-Auth) verschärft das Authenticity-Gap NICHT — es fügt eine unabhängige, zusätzliche Hürde hinzu.
  • ABER: DELETE_OPERATION_ACTIVATION (tatsächliches Löschen) sollte erst nach Schließung des Gaps freigegeben werden, um das Risiko eines kombinierten Angriffs (Gap + gestohlenes Token) zu minimieren.
  • SAFE_FOR_SERVER_AUTH_ONLY bedeutet: Server-seitige Auth (AUTH.2) kann sicher aktiviert werden, ohne das Gap zu verschärfen. Die DELETE-Operation selbst bleibt bis zur Gap-Schließung zurückhaltend zu behandeln (siehe Phase 14 GO/NO-GO).

9b. DEPLOYMENT SEQUENCE DESIGN (Phase 9) — AUTH.4 atomar, KEIN Big-Bang

⚠️ NUR DESIGN. KEINE AUSFÜHRUNG in AUTH.3B.

Kernfrage: Caller zuerst vs Server zuerst?

Server zuerst (AUTH.2 aktivieren), dann Caller (AUTH.3A).

Begründung (kein Zeitfenster mit ungeschützten Writes):

  • Wenn der Caller zuerst das SAVE-Token erhält, aber der Server noch ohne Auth läuft, dann sendet der Caller zwar ein Bearer-Token, aber der Server ignoriert es (Produktion läuft aktuell OHNE AUTH.2) → Writes bleiben ungeschützt (ungültiges Zeitfenster).
  • Wenn der Server zuerst AUTH.2 aktiviert (fail-closed), dann verweigert er ALLE Writes ohne gültiges Token. In diesem Moment haben die Caller noch KEIN Token → legitime C5-Writes fallen kurzzeitig aus (kontrolliertes, kurzes Fenster). Das ist akzeptabel, weil es FAIL-CLOSED ist (kein ungeschützter Write).
  • Kein Zeitfenster, in dem Writes ungeschützt bleiben: Server-Auth zuerst schließt das Loch sofort; Caller-Token werden danach injiziert.
  • Kein Zeitfenster, in dem DELETE ohne Human Gate möglich wird: DELETE-Token wird erst injiziert, wenn das Human Gate (Gate 3) bereits ENFORCED ist (AUTH.3A Code ist deployed). DELETE bleibt doppelt abgesichert.

Atomare AUTH.4-Reihenfolge (jeder Schritt einzeln, mit Gate)

# Schritt Aktion Gate/Verifikation
1 PRECHECK Produktiver Source == Forgejo edcb4902; AUTH.2/AUTH.3A Code deployed; kein Token in ENV git diff leer, ENV-Namen ABSENT
2 BACKUP Vault + Compose + aktuelle ENV-Namen sichern (KEINE Tokenwerte) Backup-Datei existiert
3 TOKEN_GENERATION Christian erzeugt SAVE+DELETE-Token (Phase 5 Contract), schreibt in Secret-Datei/Coolify Token in Ziel-ENV, NICHT in Git/Logs
4 SERVER_SECRET_INJECTION TOLARIA_SAVE_TOKEN + TOLARIA_DELETE_TOKEN in Tolaria-Container-ENV (via .env/Coolify) ENV-Namen PRESENT (Werte nicht prüfen)
5 CALLER_SECRET_INJECTION SAVE-Token an C5C Writer, DELETE-Token an DeleteExecutor (NUR nach Boundary-Fix, Phase 3) Getrennte Boundaries ODER HARD STOP
6 CODE_DEPLOY AUTH.2-Source (edcb4902) in Produktion deployen (Container-Restart) Server startet, Read funktioniert
7 SERVER_RESTART Tolaria-Container neu starten (liest neue ENV) Healthcheck OK
8 READ_SMOKE GET /api/vault/ping, /list, /content ohne Token → 200 Read funktioniert
9 UNAUTH_WRITE_NEGATIVE_TEST POST /save ohne Token → 401 (fail-closed) Write DENIED
10 WRONG_SCOPE_NEGATIVE_TEST POST /save mit DELETE-Token → 401; POST /delete mit SAVE-Token → 401 Scope-Trennung
11 AUTHORIZED_SAVE_TEST POST /save mit SAVE-Token → 200 (isolierte Fixture) SAVE funktioniert
12 DELETE_GATE_NEGATIVE_TEST POST /delete mit DELETE-Token aber OHNE Human Approval → DENIED Human Gate ENFORCED
13 AUTHORIZED_DELETE_TEST POST /delete mit DELETE-Token + Human Approval → 200 (NUR falls freigabefähig) DELETE funktioniert
14 POST_DEPLOY_CHECK Read + Write + Scope + kein Token in Logs/inspect Alle Checks grün
15 FRESH_CHECKER Unabhängiger Checker verifiziert alle Gates PASS

Wichtige Design-Entscheidungen

  • Kein Big-Bang: Jeder Schritt hat ein eigenes Gate; bei Fehler → Rollback (Phase 10), nicht weiter.
  • Schritt 5 (CALLER_SECRET_INJECTION) ist BLOCKED bis die Boundary-Frage aus Phase 3 gelöst ist (C5-Caller in getrennten Container ODER RQ-undurchdringbare Injektion). Ohne das bleibt RQ credential-free NICHT erreichbar.
  • Schritt 13 (AUTHORIZED_DELETE_TEST) ist CONDITIONALLY_READY — nur falls DELETE-Operation freigabefähig ist (siehe Phase 14, Gap-Berücksichtigung).
  • Server zuerst minimiert das ungeschützte Write-Fenster auf null.

10b. ROLLBACK DESIGN (Phase 10) — FAIL CLOSED, Write-Degraded-Mode

⚠️ NUR DESIGN. KEINE AUSFÜHRUNG in AUTH.3B.

Grundprinzip

  • FAIL CLOSED bevorzugen. Bei Credential-/Auth-Problem NICHT automatisch auf unauthentifizierte Writes zurückrollen.
  • Ein Rollback darf NICHT bedeuten: "Auth ausschalten und unauthentifizierte Writes wieder erlauben", wenn dadurch die bereits identifizierte CRITICAL Gap (Produktion läuft aktuell OHNE Auth) wieder geöffnet wird.
  • Bevorzugter Security-Rollback = WRITE_DEGRADED_MODE:
    • READ AVAILABLE (Read-Endpunkte funktionieren weiter)
    • WRITE DISABLED (mutierende Endpunkte bleiben DENIED)

Exakte Rollback-Pfade

Fall Symptom Rollback-Aktion Security-Position
A) Server startet nicht Container-Crash nach AUTH.2-Deploy Source auf b5a5e4bd (Basisstand) zurück; ENV-Tokens entfernen; Restart FAIL CLOSED (kein Write ohne Auth)
B) Read-Endpunkte kaputt /ping, /list, /content 500 Source auf b5a5e4bd zurück; ENV-Tokens entfernen; Restart FAIL CLOSED
C) C5C SAVE schlägt fehl SAVE-Writes 401/500 SAVE-Token prüfen/erneuern; NICHT Auth deaktivieren WRITE_DEGRADED (SAVE disabled, READ available)
D) DELETE-Caller schlägt fehl DELETE-Writes 401/500 DELETE-Token prüfen/erneuern; NICHT Human Gate deaktivieren WRITE_DEGRADED (DELETE disabled, READ available)
E) Token falsch injiziert Wrong-Scope 401 Token korrekt injizieren; NICHT Auth deaktivieren FAIL CLOSED
F) Token-Leak vermutet Token in Logs/inspect/Repo Token SOFORT rotieren (Phase 11); NICHT Auth deaktivieren FAIL CLOSED
G) Falscher Scope SAVE-Token autorisiert DELETE (o. umgekehrt) Scope-Trennung prüfen; Token neu generieren FAIL CLOSED
H) Regression nach Restart Read/Write unerwartet Source auf b5a5e4bd zurück; ENV-Tokens entfernen; Restart FAIL CLOSED

WRITE_DEGRADED_MODE (bevorzugter Security-Rollback)

  • READ AVAILABLE: /api/vault/ping, /list, /content, /all-content, /entry, /search funktionieren (kein Token nötig).
  • WRITE DISABLED: /api/vault/save, /rename, /rename-filename, /delete, /command bleiben DENIED (401) — fail-closed, weil Token-Konfiguration entfernt oder ungültig ist.
  • Wie erreicht: ENV-Tokens aus Tolaria-Container entfernen (oder auf ungültig setzen) + Restart. Server bleibt fail-closed (leeres expected → 401).
  • WICHTIG: Das ist KEIN "Auth ausschalten". Es ist "Auth auf DENIED-ALL setzen" — Writes sind blockiert, nicht ungeschützt.

Warum NICHT auf unauthentifizierte Writes zurückrollen

  • Die Produktion läuft aktuell OHNE Auth (CRITICAL Gap, verifiziert in Phase 1).
  • Ein Rollback auf "Auth aus" würde dieses Gap wieder öffnen und Writes ungeschützt lassen.
  • WRITE_DEGRADED_MODE hält Writes geschützt (DENIED), während Read verfügbar bleibt — das ist die sichere Zwischenposition bis zur Fehlerbehebung.

11b. TOKEN ROTATION / REVOCATION (Phase 11) — SAVE/DELETE getrennt

⚠️ NUR DESIGN. KEINE AUSFÜHRUNG in AUTH.3B.

Unterstützt AUTH.2 nur einen Token pro Scope?

  • JA. VaultAuthConfig (vite.config.ts Z.36-39) hält saveToken und deleteToken als einzelne Strings (kein Array, keine Multi-Token-Unterstützung).
  • authorizeVaultWrite (Z.120-126) vergleicht gegen genau EINEN erwarteten Token pro Scope.
  • Konsequenz: Zero-downtime-Rotation (zwei gültige Tokens gleichzeitig) ist mit AUTH.2 NICHT möglich. Rotation erfordert ein kurzes Write-Downtime-Fenster.

SAVE-Rotation (minimales Write-Downtime-Fenster)

  1. Neues SAVE-Token erzeugen (Phase 5 Contract).
  2. Neues Token in Tolaria-Container-ENV schreiben (ersetzt altes).
  3. Tolaria-Container neu starten (liest neues Token).
  4. C5C Writer erhält neues SAVE-Token (nach Boundary-Fix, Phase 3).
  5. Altes SAVE-Token ist sofort ungültig (Server vergleicht nur gegen neues).
  6. Write-Downtime-Fenster: zwischen Schritt 3 und 4 sendet C5C Writer noch altes Token → 401. Fenster = Zeit bis C5C Writer aktualisiert ist.
  7. Verifikation: POST /save mit neuem Token → 200; mit altem → 401.

DELETE-Rotation (analog, getrennt)

  1. Neues DELETE-Token erzeugen.
  2. In Tolaria-Container-ENV schreiben (ersetzt altes).
  3. Tolaria-Container neu starten.
  4. DeleteExecutor erhält neues DELETE-Token.
  5. Altes DELETE-Token sofort ungültig.
  6. Verifikation: POST /delete mit neuem Token + Human Approval → 200; mit altem → 401.

Laufende Retries / queued Jobs

  • Retries: Ein laufender Retry mit altem Token schlägt nach Rotation fehl (401). Der Retry muss das neue Token verwenden (Client-Instanz neu konstruieren).
  • Queued Jobs: C5-Queue-Einträge, die vor Rotation geplant wurden, verwenden beim Ausführen das aktuelle Token (Client wird zur Laufzeit konstruiert). Nach Rotation nutzen sie das neue Token.
  • Empfehlung: Rotation in einem Wartungsfenster durchführen, wenn keine kritischen Writes anstehen.

DELETE-Revocation (unabhängig von SAVE)

  • DELETE-Revocation muss unabhängig von SAVE möglich sein: Ja — DELETE-Token ist eine separate ENV-Variable (TOLARIA_DELETE_TOKEN). Entfernen/ersetzen dieser Variable + Restart widerruft DELETE, ohne SAVE zu beeinflussen.
  • SAVE-Revocation analog: TOLARIA_SAVE_TOKEN entfernen/ersetzen + Restart widerruft SAVE, ohne DELETE zu beeinflussen.
  • Revocation = sofort wirksam nach Container-Restart (Server liest ENV beim Start; kein Cache).

Welche Komponenten müssen restart/reload?

  • Tolaria-Server-Container: Restart nötig (liest ENV beim Start).
  • C5C Writer / DeleteExecutor: Client-Instanz neu konstruieren (neues Token). Kein Container-Restart nötig, wenn Token via ENV/Config injiziert wird und der Prozess neu gestartet wird.

Wie wird Rotation verifiziert?

  • Positiv: Write mit neuem Token → 200.
  • Negativ: Write mit altem Token → 401 (fail-closed).
  • Scope: SAVE-Token autorisiert nicht DELETE und umgekehrt.
  • Kein Token-Leak: neues Token nicht in Logs/inspect/Repo.

12b. BACKUP / RECOVERY (Phase 12) — Secret-Handling

⚠️ NUR DESIGN. KEINE Backup-Konfiguration ändern in AUTH.3B.

Werden Secret-Werte in normalen Backups erfasst?

  • NEIN. Das Tolaria-Backup-Skript (/opt/data/bin/tolaria_backup.py) sichert NUR Vault-Content (.md-Dateien) und App-Source über die read-only API (/api/vault/list, /api/vault/content). Es sichert KEINE ENV-Variablen, KEINE Compose-Datei, KEINE Secret-Dateien.
  • Sollten sie enthalten sein? NEIN. Secrets gehören NICHT in Backups. Sie werden separat (außerhalb des Backup-Pfads) verwaltet und bei Restore neu injiziert.

Wie wird Disaster Recovery durchgeführt?

  1. Vault-Content aus Backup wiederherstellen (via tolaria_backup.py oder Vault-Git-Restore).
  2. App-Source aus Forgejo (edcb4902) neu deployen (rebuildbar, Forgejo=SoT).
  3. Secrets NEU injizieren (nicht aus Backup): Christian erzeugt frische SAVE/DELETE-Tokens (Phase 5 Contract) und schreibt sie in die Container-ENV.

Müssen Tokens nach Restore rotiert werden?

  • JA, zwingend. Nach einem Disaster Recovery werden frische Tokens erzeugt (nicht die alten aus dem Backup). Das verhindert, dass alte, möglicherweise kompromittierte Tokens weiterleben.

Können alte Backups alte gültige Tokens enthalten?

  • NEIN (aktuell): Das Backup-Skript sichert keine Secrets. Aber falls in Zukunft ein Backup die Compose-Datei oder ENV mit aufnimmt, könnten alte Tokens enthalten sein.

Wie verhindern wir Secret-Restore aus veraltetem Backup?

  • Backup-Skript sichert keine Secrets (verifiziert, Z.17 "Keine Secrets im Manifest/Log").
  • Restore-Prozedur injiziert IMMER frische Tokens (nie aus Backup).
  • Empfehlung: Falls ein Backup je Compose/ENV aufnimmt, Secrets vor dem Backup strikt ausschließen (.gitignore-artige Exklusion) und nach Restore rotieren.

Empfehlung (dokumentiert, KEINE Änderung)

  • Secrets NIE in Backups aufnehmen.
  • Nach jedem Restore frische Tokens erzeugen.
  • Backup-Manifest/Logs secret-frei halten (bereits der Fall).

13b. ISOLATED DEPLOYMENT TEST PLAN (Phase 13) — AUTH.4

⚠️ NUR TESTPLAN. KEINE produktiven Mutationsprobes in AUTH.3B. Alle Tests werden in AUTH.4 in isolierter Umgebung (Fixture-Vault, synthetische Tokens) ausgeführt, NICHT gegen Produktion.

ID Test Erwartung Typ
T1 READ ohne Token /ping, /list, /content → 200 Positiv
T2 SAVE ohne Token POST /save → 401 (fail-closed) Negativ
T3 SAVE wrong token POST /save mit falschem Token → 401 Negativ
T4 SAVE DELETE-token POST /save mit DELETE-Token → 401 (Scope) Negativ
T5 SAVE korrektes SAVE-token POST /save mit SAVE-Token → 200 Positiv
T6 DELETE ohne Token POST /delete → 401 (fail-closed) Negativ
T7 DELETE wrong token POST /delete mit falschem Token → 401 Negativ
T8 DELETE SAVE-token POST /delete mit SAVE-Token → 401 (Scope) Negativ
T9 DELETE korrektes Token, ohne Human Approval → DENIED (Gate 3) Negativ
T10 DELETE Approval, aber ohne Token → 401 (fail-closed) Negativ
T11 DELETE Token + Approval → 200 NUR falls ausdrücklich freigegeben Positiv
T12 missing server ENV Server startet, Writes DENIED (fail-closed) Negativ
T13 missing caller ENV Caller bricht vor HTTP ab (fail-closed) Negativ
T14 Restart erhält Security State Nach Restart weiterhin fail-closed Positiv
T15 kein Token in Logs Logs secret-frei Negativ
T16 kein Token in inspect docker inspect secret-frei (soweit Architektur) Negativ
T17 kein Token in Repo Git-History secret-frei Negativ
T18 kein Token im Vault Vault-Content secret-frei Negativ
T19 kein Token in DB C5-DB secret-frei Negativ
T20 Retry sicher Retry behält Credential, kein Leak Positiv
T21 Replay sicher Replay behält Credential, kein Leak Positiv
T22 READ während Write-Degraded-Mode Read 200, Write DENIED Positiv
T23 SAVE/DELETE getrennt widerrufbar Revocation eines Scopes beeinflusst anderen nicht Positiv
T24 Path traversal weiterhin denied ../ → 401/400 Negativ
T25 Symlink escape weiterhin denied Symlink → 401/400 Negativ
T26 /api/vault/command kann Auth nicht umgehen Command ohne Token → 401 Negativ

Test-Ausführungsregeln (AUTH.4)

  • Alle Tests in isolierter Umgebung (Fixture-Vault, synthetische Tokens auth4-...), NICHT gegen Produktion.
  • T11 (DELETE Token + Approval) NUR wenn DELETE-Operation freigabefähig ist (siehe Phase 14).
  • Keine produktiven Mutationsprobes in AUTH.3B.

14b. AUTH.4 GO/NO-GO MATRIX (Phase 14)

⚠️ NUR BEWERTUNG. KEINE Aktivierung in AUTH.3B.

Punkt Status Konkrete Blocker
SERVER_AUTH_DEPLOYMENT CONDITIONALLY_READY AUTH.2-Code (edcb4902) ist fertig + getestet (70/70, Fresh Checker 17/17). Blocker: produktiver Source muss == Forgejo edcb4902 sein; ENV-Tokens müssen injiziert werden; Container-Restart nötig. Kein Code-Blocker.
SAVE_ACTIVATION CONDITIONALLY_READY AUTH.3A-Code (a11c1bb) fertig + getestet (19/19, 318/318). Blocker: SAVE-Token muss an C5C Writer injiziert werden; Boundary-Frage (Phase 3) muss gelöst sein — sonst hätte RQ Zugriff auf SAVE-Token.
DELETE_CREDENTIAL_ACTIVATION BLOCKED DELETE-Token-Injektion an DeleteExecutor erfordert getrennte Boundary (Phase 3). Aktuell laufen SAVE+DELETE im selben Container → RQ hätte Zugriff auf BEIDE Tokens. HARD STOP bis Boundary-Fix.
DELETE_OPERATION_ACTIVATION BLOCKED Zusätzlich zum Boundary-Fix: HUMAN_APPROVAL_AUTHENTICITY_GAP ist OPEN. DELETE-Operation erst nach Gap-Schließung freigeben (kombinierter Angriff Gap+Token).
HERMES_READ_ONLY_AUTONOMY CONDITIONALLY_READY Read-Endpunkte brauchen kein Token; RQ bleibt credential-free für Read. Blocker: keine (Read ist bereits möglich).
HERMES_BOUNDED_AUTONOMY BLOCKED Erfordert SAVE/DELETE-Aktivierung, die wiederum Boundary-Fix + Gap-Schließung voraussetzt.

Kern-Blocker (zusammenfassend)

  1. CREDENTIAL_SEPARATION (Phase 3): SAVE+DELETE laufen im selben Container (06a4a73573d0). RQ credential-free ist technisch NICHT erreichbar, solange beide Tokens in die ENV dieses Containers injiziert würden. → HARD STOP für DELETE_CREDENTIAL_ACTIVATION.
  2. HUMAN_APPROVAL_AUTHENTICITY_GAP (OPEN): DELETE-Operation erst nach Gap-Schließung. → BLOCKED für DELETE_OPERATION_ACTIVATION.
  3. SERVER_AUTH_DEPLOYMENT und SAVE_ACTIVATION sind CONDITIONALLY_READY (Code fertig), aber SAVE_ACTIVATION hängt an der Boundary-Frage.

Empfohlene Reihenfolge (AUTH.4, nach Freigabe)

  1. SERVER_AUTH_DEPLOYMENT (AUTH.2 aktivieren) — sicher, verschärft Gap nicht.
  2. Boundary-Fix (C5-Caller in getrennten Container ODER RQ-undurchdringbare Injektion) — VORAUSSETZUNG für SAVE/DELETE-Credential-Aktivierung.
  3. SAVE_ACTIVATION (nach Boundary-Fix).
  4. Gap-Schließung (separate Freigabe).
  5. DELETE_CREDENTIAL_ACTIVATION + DELETE_OPERATION_ACTIVATION (nach 2+4).

15. INCIDENT (AUTH.3B, 2026-08-27)

INCIDENT_OCCURRED = TRUE (während Phase 1 Discovery)

  • Versehentlicher mutierender POST POST /api/vault/save gegen Produktion (_auth3b_probe.md, Inhalt "x") — Verstoß gegen die verbindliche Incident-Regel (NO MUTATING HTTP METHOD PROBES).
  • INCIDENT_RECOVERED = TRUE — Datei sofort via POST /api/vault/delete entfernt, Read-Back bestätigt: Datei existiert nicht mehr.
  • PERMANENT_DAMAGE = NONE VERIFIED
  • ROOT_CAUSE = unsafe mutating endpoint probe during read-only discovery
  • BESTÄTIGT: Produktion läuft OHNE AUTH.2 (save ohne Token → 200, kein 401).
  • LEHRE: Keine weiteren mutierenden POSTs. Nur read-only GET/Code-Reading.