WebUI Redesign and Component 1: category mapper fixes

This commit is contained in:
Richard
2026-07-19 10:51:07 +02:00
parent c3e66d6cca
commit 7045002ca3
40 changed files with 7037 additions and 971 deletions
+144
View File
@@ -0,0 +1,144 @@
# Plan: Drei-Schichten-Architektur (Core / Lokal / Public)
> 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)
- [ ] 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.
- [ ] `MapPredictalyticsEndpoints()` in `MapReadEndpoints()` + `MapControlEndpoints()` splitten
(rein struktureller Refactor, Verhalten unverändert; bestehende Tests bleiben grün).
- [ ] `GET /api/capabilities` einführen.
### Phase 1 — WebUI als sauberes, gemeinsames SPA (parallel zum neuen Design)
- [ ] Neues Design als **ein statisches Artefakt** bauen, reiner API-Client, `API_BASE`
konfigurierbar (heute `''` = gleiche Origin bleibt lokal gültig).
- [ ] Admin-Aktionen an `capabilities.canControl` koppeln.
- [ ] 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)
- [ ] CORS von `AllowAnyOrigin` auf konfigurierte Origin-Whitelist umstellen.
- [ ] 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.