Files
claude-regelwerk/.vault-tools/trading-plattform-pruefung/start_probe_zugang.py
T
Pascal MichelandClaude Opus 5 d7ffc9a5b5 Automatischer Push: 6 Datei(en) geändert
- .vault-tools/plan-kopie/LIESMICH.md
- .vault-tools/plan-kopie/rot_nachweis.py
- .vault-tools/trading-plattform-pruefung/LIESMICH.md
- .vault-tools/trading-plattform-pruefung/browser_r.py
- .vault-tools/trading-plattform-pruefung/start_probe_w.py
- .vault-tools/trading-plattform-pruefung/start_probe_zugang.py

Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-23 04:00:01 +02:00

136 lines
5.6 KiB
Python

"""Probe-Backend mit Anmeldung: die echte App mit Attrappe, Wegwerf-Register und Wegwerf-Zugang.
Koordinator-Werkzeug zu Teil 10, nicht fuers Repo. Kein Broker-Aufruf, kein Ereignis im echten
Register, keine echte Zugangsdatei. Der Wegwerf-Zugang traegt ein bekanntes Passwort und das
Beispielgeheimnis der TOTP-Literatur; beides steht in zugang.json im Ausgabeordner, damit
angriffe.py und der Browser-Lauf sich anmelden koennen.
Aufruf aus dem Projektordner (oder einer Kopie davon):
python start_probe_zugang.py <port> <ausgabeordner> [mit-paperstatus] [zwei-benutzer]
Mit zwei-benutzer kommt ein zweiter Wegwerf-Benutzer "zweiter" dazu (eigenes TOTP-Geheimnis, in zugang2.json),
damit sich pruefen laesst, dass das Entfernen des einen den anderen nicht trifft.
"""
import dataclasses
import json
import os
import sys
from datetime import UTC
from datetime import datetime
from pathlib import Path
import uvicorn
from trading.broker.attrappe import BrokerAttrappe
from trading.dashboard.app import erzeuge_app
from trading.dashboard.config import lade_dashboard_config
from trading.dashboard.zugang import Benutzer
from trading.dashboard.zugang import schreibe_benutzer
from trading.dashboard.zugang import setze_passwort
from trading.killswitch.killswitch import lade_killswitch_config
from trading.registry.registry import Registry
BENUTZER = "probe"
PASSWORT = "nur-fuer-die-probe-2026"
GEHEIMNIS = "JBSWY3DPEHPK3PXP"
port = int(sys.argv[1])
ordner = Path(sys.argv[2])
# Befund der Sicherheitspruefung vom 2026-09-20: erzeuge_app startete (bis Paket S5) immer den echten
# Stille-Waechter und las dafuer config/paper.toml und config/secrets.toml aus dem Arbeitsordner. Eine
# Probe-Instanz im echten Projektordner haette nach 180 s auf das Telefon geklingelt. Deshalb nur aus
# einer Kopie oder einem Arbeitsbaum ohne Geheimnisdatei.
# Seit Paket E2 (2026-09-22) findet die Plattform die Geheimnisdatei auch ueber TRADING_GEHEIMNISSE
# bzw. CREDENTIALS_DIRECTORY -- nach dem Umzug steht die erste in jeder Login-Shell, und die Wache
# unten liefe ins Leere. Die Probe nimmt beide aus ihrer Umgebung, bevor die App gebaut wird
# (Befund der Abschlusspruefung E2).
for name in ("TRADING_GEHEIMNISSE", "CREDENTIALS_DIRECTORY"):
os.environ.pop(name, None)
if Path("config/secrets.toml").exists():
sys.exit(
"Abbruch: Im Arbeitsordner liegt config/secrets.toml. Die Probe startet nur aus einer Kopie "
"ohne Geheimnisdatei, sonst spraeche sie mit dem echten ntfy und dem echten Home Assistant."
)
ordner.mkdir(parents=True, exist_ok=True)
mit_status = "mit-paperstatus" in sys.argv[3:]
zwei_benutzer = "zwei-benutzer" in sys.argv[3:]
ZWEITER = "zweiter"
GEHEIMNIS_ZWEITER = "KRUGS4ZANFZSAYJA"
zugang_datei = ordner / "zugang.toml"
benutzer = {BENUTZER: Benutzer(name=BENUTZER, passwort=setze_passwort(PASSWORT), totp_geheimnis=GEHEIMNIS)}
if zwei_benutzer:
benutzer[ZWEITER] = Benutzer(name=ZWEITER, passwort=setze_passwort(PASSWORT), totp_geheimnis=GEHEIMNIS_ZWEITER)
(ordner / "zugang2.json").write_text(
json.dumps({"benutzer": ZWEITER, "passwort": PASSWORT, "geheimnis": GEHEIMNIS_ZWEITER}),
encoding="utf-8",
)
schreibe_benutzer(zugang_datei, benutzer)
(ordner / "zugang.json").write_text(
json.dumps({"benutzer": BENUTZER, "passwort": PASSWORT, "geheimnis": GEHEIMNIS}),
encoding="utf-8",
)
paper_ordner = ordner / "paper"
paper_ordner.mkdir(exist_ok=True)
status_datei = ordner / "status.json"
if mit_status:
protokoll = paper_ordner / "2026-09-18T131502-paper.jsonl"
zeilen = [
{"art": "kopf", "modus": "paper"},
{"art": "takt", "schritt": 1, "phase": "handelt", "position": 10, "zielposition": 10},
]
protokoll.write_text("\n".join(json.dumps(z) for z in zeilen) + "\n", encoding="utf-8")
status_datei.write_text(
json.dumps(
{
"zeit": datetime.now(UTC).isoformat(),
"modus": "paper",
"phase": "handelt",
"agent": {
"quelle": "register",
"name": "aapl-minute-ppo",
"version": "v20260907-074410",
"status": "paper",
},
"instrument": "AAPL.XNAS",
"killswitch": "aktiv",
"position": 10,
"zielposition": 10,
"letzte_aktion": {"zeit": datetime.now(UTC).isoformat(), "aktion": 3, "stufe": 1},
"letzte_kerze": datetime.now(UTC).replace(second=0, microsecond=0).isoformat(),
"orders": 1,
"kontowert": 100012.5,
"startkapital": 100000.0,
"hinweis": None,
"protokoll": str(protokoll),
"pid": 1,
}
),
encoding="utf-8",
)
config = dataclasses.replace(
lade_dashboard_config("config/dashboard.toml"),
port=port,
broker_wahl="attrappe",
sendeintervall_s=2.0,
erlaubte_hosts=(f"127.0.0.1:{port}", f"localhost:{port}"),
anmeldung_pflicht=True,
mfa_pflicht=True,
zugang_datei=str(zugang_datei),
zugang_protokoll=str(ordner / "anmeldungen.jsonl"),
paper_status_datei=str(status_datei),
paper_protokoll_ordner=str(paper_ordner),
)
app = erzeuge_app(
broker=BrokerAttrappe(),
registry=Registry(db_pfad=ordner / "registry.db", artefakt_wurzel=ordner / "artifacts"),
config=config,
killswitch_config=lade_killswitch_config("config/killswitch.toml"),
dist=Path("dashboard/dist"),
)
print(f"Probe-Backend mit Anmeldung auf 127.0.0.1:{port}, Ablage {ordner}", flush=True)
uvicorn.run(app, host="127.0.0.1", port=port, log_level="warning", server_header=False, proxy_headers=False)