# Betriebsdokumentation Aria V3

Gilt erst nach dem Produktivwechsel (`docs/MIGRATION.md`). Bis dahin läuft Aria unverändert.

## Bausteine im Betrieb

| Baustein | Ort (Vorschlag, E8) | Rolle |
|---|---|---|
| Plugin-Patch | `…/telegram/0.0.6/server.ts` + `aria-gateway.ts` | einziger Einhängepunkt in `handleInbound()`, nach `gate()` und Permission-Intercept |
| Bridge | `<REPO>/python/bin/aria_bridge.py --config <CFG>` | wird pro Nachricht vom Plugin gestartet (stdin → JSON → stdout), kein Dauerprozess |
| Konfiguration | `gateway.json`; Vorlagen in `python/config/` (`gateway.example.json` = shadow ohne Codex, `gateway.codex-text.example.json`, `gateway.codex-tools.example.json`) | unbekannte Schlüssel werden abgelehnt |
| Zustand | `state_dir` (z. B. `/home/aria/aria-v3-state`) | siehe nächste Tabelle |
| Schlüssel | `state_dir/keys/clearance.key` (≥ 32 Byte, `aria`, 0600) | HMAC der Clearance |

## Zustandsdateien in `state_dir`

| Datei | Inhalt | Pflege |
|---|---|---|
| `decisions.jsonl` | eine Zeile je Entscheidung (Backend, Klasse, Code, echte Telegram-IDs, **kein Nachrichtentext**) | `decision_log_retention_days` (E17, Betrieb: 30): Datensätze älter als die Frist werden höchstens einmal täglich beim Schreiben entfernt (gleiche Datei, unter Sperre; Marker `decisions.jsonl.pruned`); `0` = keine Löschung |
| `budget.json` | Tagesverbrauch je Backend (UTC) | setzt sich täglich selbst zurück |
| `health.json` | Circuit-Breaker je Backend (Fehlerzähler, offen bis) | heilt nach `health.open_seconds` |
| `modes.json` / `shadow-modes.json` | Modus je Chat (`auto`, `codex`, `claude`) | per Befehl im Chat |
| `nonces.json`, `dedupe.json`, `shadow-dedupe.json` | Einmal-Nonces, Duplikatschutz | laufen nach TTL ab |
| `*.lock` | Dateisperren | nicht von Hand löschen, solange Aria läuft |

## Schalter

| Schalter | Werte | Wirkung |
|---|---|---|
| `ARIA_GATEWAY_MODE` | `off` (Default) / `shadow` / `active` | `off` = exakt Prod; `shadow` = nur protokollieren; `active` = Gateway entscheidet |
| `ARIA_GATEWAY_ON_FAILURE` | `claude_status_quo` (Default) / `block` | was in `active` bei Router-Ausfall passiert (E5); erkannte Sperren gelten immer |
| `ARIA_GATEWAY_TIMEOUT_MS` | shadow 3000, active 15000 | in `active` blockiert der Aufruf die Update-Schleife (E27) |
| `allowed_modes` (Config) | `["shadow"]` oder `["shadow","execute"]` | ohne `execute` führt das Gateway nie aus |
| `codex.real_execution` | `false` (Default) / `true` | `false` = MockRunner |
| `codex.profile` | `text` (Default) / `tools` (B+) | `tools` nur mit Käfig; Config lehnt `address_space_bytes` dort ab |
| `codex.tools_protect_startup` | `true` (Default, Owner TG 12861) / `false` | nur `tools`: Startdateien (`~/.bashrc/.profile/.bash_profile/.bash_logout/.zshrc`), `~/.config`, `~/scripts`, `~/.local/bin`, `<repo>/.git/hooks`+`.git/config`, `~/brain`, `/home/aria/aria` und `.gitconfig` read-only. `false` = ausdrückliche Abwahl (Startdatei-Schreibschutz aus). Seit E44 wirkt der Schalter nur noch innerhalb von Allowlist-Ordnern (das übrige Home ist ohnehin nicht schreibbar) |
| `codex.tools_write_allowlist` | `[]` (Default, E44 Option 2, Owner TG 12923) / Liste absoluter Ordner | nur `tools`: die **einzigen** Home-Ordner, in die Codex schreiben darf (sonst nur Workspace/Lauf-Verzeichnisse). Jeder Eintrag: kanonisch, existierend, kein Symlink, echt unter `home_root`, keine versteckte Komponente, nicht in Sperr-/Startschutzbereichen, `state_dir`, Repo/`aria-v3-*`, nicht überlappend mit `workspace_root`; sonst Konfigfehler bzw. `WRITE_ALLOWLIST_INVALID`. Keine Ordner freigeben, aus denen Cron oder die Hauptsession Code ausführt |

Chat-Befehle (nur Besitzer, nur in `active` wirksam): `/auto`, `/codex`, `/claude`. Eine manuelle Wahl hebt keine
Datenschutz- oder Sicherheitsregel auf (`routing.manual_fallback: block`).

## Prüfen im laufenden Betrieb

- Gateway-Zustand ohne Plugin: `/usr/bin/python3 -I <REPO>/python/bin/aria_bridge.py --config <CFG> --status`
  (`key_available`, `allowed_modes`, `codex_real_execution`, je Backend `health`, `consecutive_failures`, `last_error`, `budget`).
- Plugin-Log: Zeilen `aria-gateway: {…}` (Ergebnis, `forwarded`, Fehlercode, nie Nachrichtentext).
- Genau ein Poller: `ps -eo pid,args | grep 'bun server.ts'` und `/proc/<pid>/cwd`.
- Codex-Läufe: `systemctl --user list-units 'aria-codex-*'` sollte leer sein, wenn nichts läuft (Scopes werden nach
  jedem Lauf gestoppt und zurückgesetzt).

## Typische Fehlercodes

| Code | Bedeutung | Maßnahme |
|---|---|---|
| `NO_USER_BUS` | systemd-User-Bus nicht erreichbar, Codex startet nicht | `loginctl enable-linger aria` prüfen (Admin) |
| `TIMEOUT` | Codex über `timeout_seconds` / `RuntimeMaxSec` | Scope wurde mit allen Kindprozessen beendet |
| `TOOL_EVENT_SEEN` | Werkzeug-Ereignis im text-Profil | erwartet: text erlaubt keine Werkzeuge |
| `OUTPUT_FILE_MISSING` / `OUTPUT_MISMATCH` | `last.txt` fehlt oder passt nicht zum JSONL | Lauf gilt als fehlgeschlagen |
| `WRITE_ALLOWLIST_INVALID` | ein Eintrag von `codex.tools_write_allowlist` verletzt beim Profilbau eine Sperre (z. B. liegt in einem Cron-Ziel, wurde gegen einen Symlink getauscht, existiert nicht mehr) | Codex startet nicht; Eintrag prüfen (`--status` lädt die Konfig und meldet Konfigfehler) |
| `BUDGET_EXHAUSTED` | Tagesbudget erreicht | gilt bis 00:00 UTC (Tagesgrenze UTC) |
| `--status`: `health` = `open` | Circuit-Breaker nach `failure_threshold` Fehlern | heilt nach `open_seconds` |

## Wartung

- Nach **Codex-Update** und **Plugin-Update**: siehe `docs/ABHAENGIGKEITEN.md`, Abschnitt Update-Risiken.
- Schlüsselwechsel: neue Datei schreiben (0600), alte ersetzen; laufende Clearances (TTL 120 s) verfallen dabei.
- Rückweg jederzeit: `docs/ROLLBACK.md`, Stufe 1 (`off`) braucht keine Dateiänderung am Plugin.
