trading-system-docs/modul-15-m09-anbindung-implementierung.md
Red Queen 022c30e537 feat(tolaria): migrate C3H HR wave 1 — 16 safe root↔canonical pairs to schema v1
C3H HUMAN REVIEW WAVE 1: migriert 16 freigegebene HR-A PAIR_MIGRATION_SAFE Paare.
Pro Pair: Root (representation=source) + Canonical (representation=canonical,
derived_from=Root-ID) atomar. Body byte-genau unveraendert. IDs stabil aus
C3 Mapping Preview v2. modul-12/18/19/vps.md NICHT angefasst.
Knowledge schema v1. (Red Queen)
2026-08-25 19:19:02 +00:00

6.1 KiB

knowledge_schema id type role representation state
1 object/a3cffdc1-41fd-ab84-c211-7b586f153e8d arch implementation source current

Modul-15 → Modul-09 Control-Anbindung — Implementierung & Live-E2E

Status: FREIGEGEBEN / PRODUKTIV VERIFIZIERT (20.08.2026, Nutzer-Bestätigung). Datum: 20.08.2026 · Autor: Rain Ocampo (Hermes) Gilt für: Modul-09-Execution-Service ↔ Modul-15-Monitoring-Control

Freigabe-Hinweis: Diese Doku dokumentiert den Implementierungs- und E2E-Stand. Die finale Freigabe (M15/M09 als FREIGEGEBEN markieren) erfolgte am 20.08.2026 durch Nutzer-Bestätigung. M16 wird nicht begonnen.


1. Umgesetzte Architektur (Variante C)

Event-Cache als nicht-kritischer Vorfilter + synchroner HTTP-Final-Check als Autorität.

  • M15 = autoritative Safety-/Trading-Control-Instanz.
  • M09 sendet neue Orders (OPEN/INCREASE) nur, wenn M15 eindeutig ENABLED + frisch bestätigt.
  • REDUCE/CLOSE/CANCEL (Risikoabbau) sind immer erlaubt — unabhängig vom M15-Status.

Kernregel

State OPEN/INCREASE REDUCE/CLOSE/CANCEL
ENABLED ERLAUBT erlaubt
PAUSED VERBOTEN erlaubt
HALTED VERBOTEN erlaubt
UNKNOWN / M15-down / stale VERBOTEN (FAIL-CLOSED) erlaubt

2. API-Vertrag M15 → M09 (additiv, kein Breaking Change)

GET /control/trading-state

{
  "trading_status": "ENABLED",        // ENABLED|PAUSED|HALTED|UNKNOWN
  "system_status": "HEALTHY",
  "state_version": 3,                 // monoton, je Status-Änderung inkrementiert
  "timestamp": "2026-08-20T15:30:00Z",
  "expires_at": "2026-08-20T15:30:00.5Z",  // TTL-Horizont (now + 500ms)
  "ttl_seconds": 0.5,
  "audit_id": "ctl-..."               // M15-interne Audit-Kennung
}

Nur trading_status=ENABLED und expires_at in der Zukunft = eindeutige Erlaubnis. Timeout/5xx/503 → FAIL-CLOSED (als UNKNOWN behandeln).

Event-Kanal (Event-Cache)

  • Exchange market.control, Routing-Key trading.state (nur bei Status-Änderung).
  • M09-Consumer ControlCacheConsumer speist den Event-Cache-Vorfilter.
  • Cache-TTL: 5 s. Stale-Cache → als UNKNOWN behandeln → OPEN/INCREASE blockiert.

3. M09-Implementierung

Neue Dateien

  • app/control/client.pyControlClient (Event-Cache-Vorfilter + HTTP-Final-Check, FAIL-CLOSED)
  • app/control/__init__.py
  • app/consumer/control_consumer.pyControlCacheConsumer (market.control/trading.state)

Geänderte Dateien

  • app/core/service.py — Control-Check zwischen Schritt 4 (Order anlegen) und Schritt 5 (_submit_and_track); _apply_control_audit; action_type-Ableitung; Consumer-Start/Stop
  • app/core/models.pyExecutionOrder + Audit-Felder
  • app/config.py — M15-URL/Timeout/TTL/Cache-TTL + Control-Exchange/Routing-Key
  • app/storage/storage.py — INSERT/UPDATE um control_*-Felder; update_control_audit
  • migrations/001_execution.sql — Audit-Spalten (idempotent via ADD COLUMN IF NOT EXISTS)

Audit-Felder je Order

action_type, control_status, control_state_version, control_expires_at, control_audit_id, control_check_source (http|cache|bypass|none).

Parameter

  • Final-Check-HTTP-Timeout: 500 ms, Retry: max 1 sofort.
  • expires_at-TTL (M15): 500 ms.
  • Cache-TTL (M09): 5 s.
  • Kein Auto-Resume; kein "Senden ohne Check".

4. Live-E2E-Ergebnisse (VPS, 20.08.2026)

Alle Szenarien auf dem VPS (187.124.31.123) live ausgeführt. Alle grün.

# Szenario Ergebnis
S1 ENABLED-Pfad: OPEN-Order durch, Auditfelder in DB 9/9 PASS
S2 HALTED-Pfad: M03 gestoppt → OPEN blockiert, kein Broker-Send, reason CONTROL_HALTED 9/9 PASS
S3 PAUSED-Pfad: nicht-krit. Service down → OPEN blockiert, reason CONTROL_PAUSED 4/4 PASS
S4 Risikoabbau bei HALTED: REDUCE/CLOSE/CANCEL erlaubt (bypass) 4/4 PASS
S5 M15-down: OPEN FAIL-CLOSED (CONTROL_UNREACHABLE), REDUCE/CLOSE/CANCEL erlaubt 7/7 PASS
S6 Cache-vs-Final-Check: HTTP HALTED gewinnt über Cache 2/2 PASS
S7 Race/TTL: Doppel-Publish → keine Doppelorder (Idempotenz) 2/2 PASS
S8 Event-Cache: 1 Consumer, 0 Backlog, Reconnect nach RabbitMQ-Restart verifiziert
S9 Recovery: nach Behebung wieder ENABLED, OPEN erlaubt 3/3 PASS
S10 Health/Security: health/ready 200, keine öffentl. Ports, keine Secrets, keine echten Tracebacks verifiziert
S11 Regression: bestehender M09-Paper-E2E (Kette 03→09) ALLE CHECKS BESTANDEN

S1-Detail (ENABLED)

control_status=ENABLED
control_state_version=1
control_expires_at=1787241066.98
control_audit_id=ctl-2073194e651040db
control_check_source=http
action_type=OPEN
broker_order_id=PAPER-EXEC-...   (Broker-Send erfolgt)
status=FILLED

S2-Detail (HALTED)

control_status=HALTED
control_state_version=2
control_audit_id=ctl-b2cd6303f8754328
control_check_source=http
action_type=OPEN
broker_order_id=None             (KEIN Broker-Send)
reason_codes=['CONTROL_HALTED']
status=FAILED

S5-Detail (M15-down)

reason_codes=['CONTROL_UNREACHABLE']
broker_order_id=None             (FAIL-CLOSED, kein Broker-Send)
REDUCE/CLOSE/CANCEL → control_check_source=bypass (erlaubt)

5. Verifikation Health/Security

  • M09 + M15 health und health/ready200.
  • Keine öffentlichen Ports (nur Docker-intern via expose:).
  • Keine Secrets in Logs/API/DB.
  • Tracebacks in Logs: ausschließlich pika AMQPConnectionError während des kontrollierten RabbitMQ-Restarts (erwartete Reconnect-Logs, keine echten Fehler).

6. Freigabe-Status

  • FREIGEGEBEN / PRODUKTIV VERIFIZIERT (20.08.2026, Nutzer-Bestätigung).
  • M15/M09-Control-Anbindung ist final freigegeben — keine weiteren technischen Änderungen an M09/M15.
  • M16: nicht beginnen.
  • Credential-Cleanup: temporäre Forgejo-Tokens/Deploy-Keys → count=0 (siehe Git-Commit).

Implementierung + Live-E2E abgeschlossen. Finale Freigabe erteilt (20.08.2026).