Files
SlipItIn/Agents/Architecture.md
2026-07-22 20:33:06 +02:00

4.8 KiB
Raw Blame History

Slip It In Architektur-Updates (Phase 2b & 3b)

Dieses Dokument fasst die Sicherheits- und Stabilitäts-Erweiterungen zusammen, die dem ProjectPlan.md hinzugefügt wurden.

🔒 Backend-Sicherheit (Phase 2b)

1. JWT-Claims Validation im GameHub

  • Problem: Clients könnten falsche PlayerId-Claims senden (Spoofing)
  • Lösung: GetAuthenticatedUserId() extrahiert User-ID aus JWT-Claims
  • Implementierung: Jede Hub-Methode validiert Context.User?.FindFirst(ClaimTypes.NameIdentifier)

2. IDbContextFactory statt Scoped DbContext

  • Problem: Bei parallelen SignalR-Aufrufen kann es zu Race Conditions kommen
  • Lösung: IDbContextFactory<SlipItInDbContext> erzeugt isolierte Sessions pro Aufruf
  • Vorteil: Phrase-Transfer ist thread-safe, keine Conflicts bei 2 gleichzeitigen Challenges

3. Serverseitige Validierung

  • Regel: Clients senden nur "Ich möchte X machen", Server prüft ALLES
  • Beispiel: SubmitSlipAsync() prüft auf dem Server:
    • Gehört die Phrase dem Spieler?
    • Ist die Runde aktiv?
    • Ist der Spieler noch im Spiel?

4. Daten-Isolation (GameStateDto vs. PlayerHandDto)

  • GameStateDto: Öffentliche Daten (Username, Score, CardCount) → für ALLE sichtbar
  • PlayerHandDto: Private Daten (Text der eigenen Karten) → nur für den Spieler selbst
  • Ergebnis: Gegner sehen nicht, welche Phrasen ich habe!

📱 Client-Stabilität (Phase 3b)

1. WeakReferenceMessenger für Event-Entkopplung

  • Problem: Services rufen ViewModels direkt auf → Memory Leaks wenn VM disposed
  • Lösung: Services senden Messages via WeakReferenceMessenger.Default.Send()
  • Vorteil: ViewModels können sich abmelden ohne zirkuläre Abhängigkeiten

Beispiel:

// Service sendet Event
WeakReferenceMessenger.Default.Send(new GameStateChangedMessage(newState));

// ViewModel empfängt (mit auto-cleanup beim Dispose)
WeakReferenceMessenger.Default.Register<GameStateChangedMessage>(this, (r, m) =>
{
	CurrentGameState = m.Value;
});

2. Automatischer Reconnect

  • Strategie: Exponential Backoff (0s → 2s → 10s → 30s)
  • Pufferung: Offline-Aktionen werden in lokale Queue geschrieben
  • Resync: Nach Reconnect wird ResyncAsync() aufgerufen

Flow:

  1. SignalR-Verbindung getrennt
  2. Client speichert "Slip zu Phrase X" in lokale Queue
  3. Nach 2s Automatischer Reconnect-Versuch
  4. Nach erfolgreichem Reconnect: Queued Actions werden abgesendet

3. State Restoration

  • App-Pause: GameStateService speichert aktuellen State in SecureStorage
  • App-Resume: ResyncAsync() wird aufgerufen
    • Holt aktuellen GameState vom Server
    • Sendet gepufferte Offline-Aktionen erneut
    • UI zeigt "Syncing..." bis fertig

4. Dual-Layer Storage

  • In-Memory Layer: GameStateService halten aktuellen State
  • Persistent Layer: SecureStorage/Preferences speichern Backup
  • Fehler-Handling: Nach App-Crash kann State aus Persistent Layer wiederhergestellt werden

📊 Schnellreferenz: Neue Components

Backend

GameHub
├─ GetAuthenticatedUserId()          → JWT-Validierung
├─ ValidatePlayerAccessAsync()        → Authorization Check
└─ Alle Methoden nutzen IDbContextFactory

Program.cs
├─ AddDbContextFactory<SlipItInDbContext>()
├─ AddAuthentication(JwtBearerDefaults)
└─ AddSignalR() mit JWT-Filter

DTOs
├─ GameStateDto (öffentlich)
├─ PlayerHandDto (privat)
└─ Keine CardText in GameStateDto!

Client

GameStateService
├─ CurrentGameState (in-memory)
├─ CurrentPlayerHand (in-memory)
├─ UpdateGameStateAsync() → speichert + sendet Message
└─ ResyncAsync() → bei App-Resume

SignalRService
├─ ConnectAsync(token) mit Auto-Reconnect
├─ RequestGameStateAsync()
└─ On<> Handler senden Messages

Messages (WeakReferenceMessenger)
├─ GameStateChangedMessage
├─ PlayerHandChangedMessage
└─ ChallengeReceivedMessage

🧪 Wichtigste Tests

Test Ziel
JWT-Auth Hub lehnt Requests ohne gültiges Token ab
Player-Access User A kann nicht auf Players von User B zugreifen
Race Condition Phrase-Transfer ist thread-safe bei 2 gleichzeitigen Challenges
Offline-Queue Aktionen während Netzwerk-Ausfall werden gepuffert und später gesendet
Memory Leaks Keine Leaks wenn ViewModels disposed werden (WeakReference)
State-Sync App-Resume synct korrekt mit Server-State

🚀 Implementierungs-Reihenfolge

  1. Backend zuerst: JWT-Auth + IDbContextFactory konfigurieren
  2. GameService erweitern: Serverseitige Validierung in alle Methoden
  3. Client-Services: GameStateService + SignalRService implementieren
  4. Messaging: WeakReferenceMessenger in ViewModels integrieren
  5. Tests: Integrationstest-Suite schreiben
  6. UI: Views an neue Message-Events binden