"""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 [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 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. 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)