Files
Predictalytics/docs/archiv/PLAN-Architektur-WebUI-Backend.md
T
RichardandClaude Opus 5 6975720dc6 Eine Roadmap statt neun Plandokumente; alte Plaene ins Archiv
Die offenen Punkte lagen ueber neun Dokumente verstreut, teils widersprechend,
teils mit Punkten, die laengst umgesetzt waren. ROADMAP.md fuehrt sie zusammen:
sechs Stufen, jeder Punkt gegen den Code geprueft.

Markierung ueber eine Legende, damit Konzepte nicht mit Aufgaben verwechselt
werden: dringend, eingeplant, Backlog, Konzept (durchdacht, aber bewusst nicht
eingeplant), liegt beim Nutzer, verworfen.

Stufen: 0 Sofort (OpenRouter-Key) - 1 Aufraeumen abschliessen (Merge nach main,
Nullable-Warnungen, Startup-Backfill) - 2 Portierung abschliessen (Linux-Erstlauf
und Verifikation, dann Deployment/CI) - 3 Analytik schaerfen (Strategie-
Klassifikation, Backtest-Harness, Track-Record im Score, Ranking) - 4 Daten-
haushalt (SQL des Nutzers) - 5 Ingest skalieren - 6 Monetarisierung vorbereiten.

Ein Anhang haelt fest, was geprueft und bewusst NICHT auf die Roadmap kam, damit
es nicht versehentlich wieder als Aufgabe auftaucht (Azuro/Limitless, die
Marketing-Seiten, Kaltarchiv, EF Core 10).

Archiv: FIXPLAN-DONE, FIXPLAN-G-Speicher, FIXPLAN-TODO, FIXPLAN-UI-Ranglisten,
UMSETZUNGSPLAN sowie ANALYSE-Linux-Portierung, PLAN-Linux-Portierung,
PLAN-Architektur-WebUI-Backend und PLAN-DatenIngest-Skalierung liegen jetzt
unter docs/archiv/ mit einer README, die jedes Dokument einordnet. Sie bleiben
als Begruendungs- und Detailquelle - die Roadmap nennt jeden Punkt knapp, die
Herleitung steht dort.

Dabei aufgefallen: die beiden nie gepflegten Plaene (Architektur, DatenIngest)
zeigten 40 offene Punkte, von denen die Haelfte umgesetzt war - Read/Control-
Split, /api/capabilities, CORS-Whitelist, Egress-Kanaele mit Cooldown und
Per-Kanal-Limiter, Ingest-Tiering. Nachgeprueft, abgehakt und mit Statusblock
eingeordnet, sonst waere das Archiv selbst eine Fehlerquelle.

Was dabei nur teilweise umgesetzt war, ist als Roadmap 5.3 aufgenommen
(Health-Statistik je Kanal, multi-homed pruefen, DB-Guard, Plausibilitaets-
pruefung), ebenso der nie durchgefuehrte Audit auf versteckte Writes in
Read-Endpunkten (6.1). Header-Rotation ist als verworfen markiert statt offen
zu bleiben: Verschleierung gegenueber Polymarket riskiert genau den Zugang, auf
dem das Projekt aufsetzt.

STATUS.md beschreibt jetzt nur noch den Ist-Stand und verweist fuer die offenen
Punkte auf die Roadmap, damit nichts doppelt gepflegt wird. CLAUDE.md nennt
beide Einstiege.

Build gruen, 126 Tests gruen, keine toten Links.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 18:46:00 +02:00

167 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Plan: Drei-Schichten-Architektur (Core / Lokal / Public)
> **Archiviert am 2026-08-23** — offene Punkte siehe [`ROADMAP.md`](../../ROADMAP.md),
> Stufe 6. Dieses Dokument wird nicht mehr gepflegt.
>
> **Phase 0 bis 2 sind erledigt**, überwiegend als Nebenprodukt der Linux-Portierung, und
> hier nachträglich abgehakt:
> * Read/Control-Split (`ApiConfiguration.MapPredictalyticsReadEndpoints()` bzw.
> `MapPredictalyticsControlEndpoints()`), `/api/dev/*` und die Job-Trigger liegen auf der
> Control-Seite.
> * `GET /api/capabilities` existiert und meldet den tatsächlichen Zustand; die WebUI
> koppelt ihre Admin-Aktionen daran (`app.js:880,1132`).
> * `API_BASE` ist im SPA konfigurierbar (`app.js:2`), Trait-Chips sind da.
> * CORS läuft über eine Origin-Whitelist, die Bind-Adresse ist explizit
> (`PredictalyticsHost.cs:177,198-201`) — kein `0.0.0.0`.
>
> **Nicht abgehakt** ist der Deep-Dive-Audit auf versteckte Writes in Read-Endpunkten
> (Phase 0, dritter Punkt): die Trennung steht, ob jeder Read-Endpunkt einzeln daraufhin
> geprüft wurde, lässt sich im Nachhinein nicht belegen. Vor einem öffentlichen Host
> nachholen.
>
> **Phase 3 und 4 sind offen** und bilden Roadmap-Stufe 6 — dort als Konzept markiert,
> weil über eine Monetarisierung nicht entschieden ist.
> Stand: 2026-07-12 · Status: **Architektur bestätigt** (Nutzer-Entscheidung), Implementierung
> schrittweise. Kein Code in diesem Schritt.
> Kontext: Neues WebUI-Design (mit Claude Design vorbereitet) wird nach der Schicht-Trennung
> schrittweise implementiert. Public-Release ist noch fern, aber alles wird dafür vorbereitet.
## 0. Bestätigte Architektur
Drei Schichten mit **genau einer** Integrationsschnittstelle zwischen intern und öffentlich:
**der Datenbank**.
```
┌─────────────────────────── LOKAL (eigener Rechner/LAN) ───────────────────────────┐
│ │
│ Schicht 1: CORE Schicht 2: LOKALE API + WebUI │
│ ───────────────── ─────────────────────────── │
│ Crawler, Worker, PnL-Engine, volle API (Read + Control), │
│ Analyse, Ingest keine Auth (localhost), │
│ │ schreibt serviert WebUI-SPA, │
│ ▼ zum Testen von Analysen & Design │
│ ┌──────────────────┐ liest/schreibt ▲ │
│ │ Analyse-DB │◄────────────────────────┘ │
│ └────────┬─────────┘ │
│ │ (nur SELECT-Grant) │
└────────────┼──────────────────────────────────────────────────────────────────────┘
│ ← EINZIGE Verbindung nach außen: read-only DB-Zugriff
┌────────────┼──────────────────────── EXTERNER WEBSERVER ───────────────────────────┐
│ ▼ │
│ Schicht 3: PUBLIC API + WebUI │
│ ──────────────────────────── │
│ nur Read-Endpunkte (identisch zur lokalen Read-Seite), │
│ Auth + Accounts, öffentliches Rate-Limiting, TLS, │
│ serviert dasselbe WebUI-SPA │
│ │ read-only │ read/write │
│ ▼ ▼ │
│ [Analyse-DB, RO] [User-DB (Accounts), separat] │
└────────────────────────────────────────────────────────────────────────────────────┘
```
**Kernprinzipien (aus der Nutzer-Entscheidung):**
- **Core ist rein lokal** und die einzige Instanz, die in die Analyse-DB **schreibt**.
- **Public spricht ausschließlich mit der Datenbank** — nie mit dem Core-Prozess, nie mit der
lokalen API. Public bekommt einen **read-only** DB-User auf die Analyse-DB und eine
**separate User-DB** für Accounts.
- **Lokale und Public WebUI sind optisch UND funktional gleich** (auf der Analyse-/Ansichtsseite),
damit neue Analysen und Designs lokal getestet werden und 1:1 öffentlich aussehen.
## 1. Wie „identisch" technisch erreicht wird
Damit beide WebUIs garantiert gleich sind, wird die **Read-/Analyse-Seite genau einmal** gebaut
und von beiden Hosts wiederverwendet — kein Duplizieren:
1. **Geteilte Read-API-Library.** `Predictalytics.Api` ist bereits eine Library. Die
Endpoint-Registrierung wird in zwei Gruppen gespalten:
- `MapReadEndpoints()`**die Analyse-/Ansichts-Endpunkte** (Trader-Liste/-Detail/-Profil/
-Positionen, Markets, Dashboard, Search, Watchlist-Ansicht, Traits). Wird von **beiden**
Hosts registriert.
- `MapControlEndpoints()`**schreibende/steuernde** Endpunkte (Jobs-Trigger, `/api/dev`,
Trader-Anlage, Watchlist-Mutation, Priority, AI-Analyse-Trigger). Wird **nur lokal**
registriert.
2. **Ein einziges WebUI-SPA-Artefakt.** Dasselbe Build wird von der lokalen und der öffentlichen
Schicht ausgeliefert. Es ist reiner API-Client (kein Server-Code, keine DB-Kenntnis).
3. **Capability-gesteuerte Admin-Bedienelemente.** Da die Control-Endpunkte öffentlich fehlen,
fragt das SPA beim Start eine `GET /api/capabilities` ab (`{ canControl: bool, authRequired: bool }`)
und blendet Admin-Aktionen (Sync/Analyze/Deep-Resync/Trader-Anlegen) nur ein, wenn vorhanden.
→ Analyse-Ansichten sind überall identisch; nur die lokalen Steuer-Buttons fehlen öffentlich.
> **Wichtiger Audit-Punkt vor dem Teilen:** Manche „Read"-Endpunkte haben heute versteckte
> Nebenwirkungen. Beispiel: `GET /api/traders/{id}/deep-dive` **holt Preis-Historie vom Provider
> und speichert Snapshots** — also ein Schreibzugriff **und** ein externer API-Call. Solche
> Endpunkte sind **nicht** public-tauglich (read-only DB verbietet den Write, und Public darf
> Polymarket nicht anrufen). Vor dem Aufnehmen in `MapReadEndpoints()` jeden Endpunkt auf
> versteckte Writes/Provider-Calls prüfen; die Public-Read-Seite muss **rein aus persistierten
> Daten** bedienbar sein (das `/profile`-Design aus FIXPLAN E ist genau deshalb „persisted-only").
## 2. Was heute wo läuft (Ist → Ziel)
- **Heute:** Core + Lokale API + WebUI sind **ein** Prozess (WinFormsHost/EmbeddedWebServer:
Worker + volle API + `wwwroot`-SPA, localhost, keine Auth, CORS `*`). Public existiert nicht.
- **Ziel Lokal:** bleibt bequem **ein** Prozess (Core-Worker + Lokale API + WebUI zusammen ist
zum Testen praktisch). Wichtig ist nur die **Code-Schichtung** (Read-Library getrennt von
Control/Core), damit Public die Read-Library **ohne** Core/Worker/Control referenzieren kann.
- **Ziel Public:** eigener schlanker Host (neues Projekt `Predictalytics.PublicApi`), der
`MapReadEndpoints()` + Auth registriert, das SPA ausliefert, und **nur** die read-only
Analyse-DB + die User-DB kennt.
## 3. Implementierungsplan (schrittweise)
### Phase 0 — Endpunkte klassifizieren & Read/Control trennen (Fundament, klein)
- [x] Jeden Endpunkt in `docs/API.md` als **Read** (public-tauglich) oder **Control** (nur lokal)
markieren. Kandidaten Control: alle `POST/PUT/DELETE`, `/api/dev/*`, Job-Trigger.
- [ ] Auf **versteckte Writes/Provider-Calls** in Read-Endpunkten prüfen (Deep-Dive!) und
bereinigen oder als Control einstufen.
- [x] `MapPredictalyticsEndpoints()` in `MapReadEndpoints()` + `MapControlEndpoints()` splitten
(rein struktureller Refactor, Verhalten unverändert; bestehende Tests bleiben grün).
- [x] `GET /api/capabilities` einführen.
### Phase 1 — WebUI als sauberes, gemeinsames SPA (parallel zum neuen Design)
- [x] Neues Design als **ein statisches Artefakt** bauen, reiner API-Client, `API_BASE`
konfigurierbar (heute `''` = gleiche Origin bleibt lokal gültig).
- [x] Admin-Aktionen an `capabilities.canControl` koppeln.
- [x] Trait-Chips/-Filter im Design vorsehen — **erscheinen erst, wenn Backend-D2 steht**
(kein UI-Bug, das Backend liefert Traits noch nicht).
### Phase 2 — Lokale Grenze härten (klein, jetzt schon sinnvoll)
- [x] CORS von `AllowAnyOrigin` auf konfigurierte Origin-Whitelist umstellen.
- [x] Bind-Adresse explizit (localhost/LAN), nie `0.0.0.0` ohne Firewall; Konfig-Kommentar
„NIEMALS ins Internet — das ist die interne Schicht".
### Phase 3 — DB für Public vorbereiten (mittel, kann früh passieren)
- [ ] **Read-only DB-User** auf der Analyse-DB anlegen (nur `SELECT`). Der Nutzer führt das SQL
selbst aus (Grant-Statements liefern wir).
- [ ] `AppDbContext` public-seitig read-only konfigurieren (read-only Connection; keine
Migrations, kein SaveChanges). Sicherstellen, dass die Read-Endpunkte ohne Writes auskommen.
- [ ] **Schema-Kopplung dokumentieren:** Weil Public direkt auf der Analyse-DB liest, ist das
DB-Schema jetzt eine **Vertragsfläche**. Schema-Änderungen im Core müssen die Public-Read-
Views berücksichtigen (Views/stabile Spalten als Puffer erwägen, damit interne
Refactorings die öffentliche Sicht nicht brechen).
### Phase 4 — Public-Host bauen (groß, wenn Release näher rückt)
- [ ] Neues Projekt `Predictalytics.PublicApi` (eigener Host, TLS, öffentliche Bind-Adresse).
- [ ] `MapReadEndpoints()` + **Auth/Accounts** (separate **User-DB**; Passwörter/Sessions nach
Stand der Technik — Secret-Handling lebt **nur hier**, nie im Core).
- [ ] Öffentliches **Rate-Limiting & Quotas pro Account** (getrennt vom internen Polymarket-Limiter).
- [ ] Mandanten-Sicht: Kunde sieht seine Watchlist/kopierten Master, nicht das gesamte Universum.
- [ ] Dasselbe WebUI-SPA ausliefern.
## 4. Explizite Nicht-Ziele / Fallen
- ❌ Public bekommt **keinen** Zugriff auf Core-Prozess, lokale API oder Control-Endpunkte.
- ❌ Public bekommt **keinen** Schreibzugriff auf die Analyse-DB (nur `SELECT`).
-**Kein** Nachrüsten von Kunden-Auth auf die lokale Vollschicht — Auth lebt nur im Public-Host.
- ❌ Read-Endpunkte machen **keine** Provider-Calls und **keine** Writes (sonst public-untauglich).
- ❌ WebUI kennt die DB nicht — immer nur über die API.
## 5. Reihenfolge / Aufwand
1. **Phase 0** (klein): Read/Control-Split + Capabilities + Deep-Dive-Audit. **Jetzt** — es ist
die Voraussetzung dafür, dass das neue Design von Anfang an sauber sitzt.
2. **Phase 1+2** (klein, parallel): neues SPA als gemeinsames Artefakt, lokale Grenze härten.
3. **Phase 3** (mittel): read-only DB-User + Schema-als-Vertrag dokumentieren.
4. **Phase 4** (groß, später): Public-Host mit Auth/User-DB.
Phase 02 begleiten das neue Design sofort. Phase 3 kann jederzeit vorgezogen werden (billig).
Phase 4 erst zum Release — aber durch 03 ist dann nichts mehr umzubauen, nur zu ergänzen.