# Requirements: Dimension47 — Milestone "PWA-Companion"

**Defined:** 2026-04-27
**Core Value:** Am Tisch funktioniert alles in Echtzeit und regelkonform: Spieler lesen ihren Charakterbogen am Handy, der GM steuert vom Laptop aus den Battle-Screen, der eingelassene Tisch-Display zeigt die Spielsicht — ohne Reibung, ohne falsche Werte, ohne Reload.

## v1 Requirements

### Level-Up (PF2e regelkonform)

- [ ] **LVL-01**: User startet Level-Up auf einem Charakter und sieht einen Wizard mit allen für das neue Level relevanten Wahlpunkten
- [ ] **LVL-02**: Attribute Boosts auf Level 5/10/15/20 werden angeboten (4 Boosts pro Boost-Level, +2 unter 18, +1 ab 18; HP-/Skill-Recompute folgt)
- [ ] **LVL-03**: Klassentalent-Wahl an jedem geraden Level mit Filter nach Klasse + Level + Voraussetzungen
- [ ] **LVL-04**: Fertigkeitstalent-Wahl an jedem geraden Level mit Voraussetzungs-Filter (Übungsstufe, benannte Fertigkeit)
- [ ] **LVL-05**: Allgemein-Talent-Wahl an Level 3/7/11/15/19 (Fertigkeitstalente sind optional als Allgemein-Talent wählbar)
- [ ] **LVL-06**: Skill-Increase an Level 3 und jedem 2. Level danach mit Cap-Regel (Trained→Expert ab L3, Expert→Master ab L7, Master→Legendary ab L15)
- [ ] **LVL-07**: Ancestry-Talent-Wahl an Level 5/9/13/17 mit Filter nach Abstammung + Heritage + Voraussetzungen
- [ ] **LVL-08**: Klassenmerkmale werden automatisch aus Class-Progression-Tabelle pro Klasse + Level angewendet (neue DB-Tabelle, gefüttert aus PF2e-Quelldaten)
- [ ] **LVL-09**: Voraussetzungen werden über einen DSL-Evaluator geprüft; nicht-evaluierbare Voraussetzungen erscheinen als Warnung, kein Hard-Block
- [ ] **LVL-10**: Abgeleitete Werte werden automatisch neu berechnet (HP-Max, Save-Proficiency, AC-Proficiency, Klassen-DC, Wahrnehmung)
- [ ] **LVL-11**: User kann den Level-Up-Wizard jederzeit abbrechen oder bisherige Wahlen rückgängig machen, bevor er bestätigt (Draft-Session)
- [ ] **LVL-12**: Bestätigtes Level-Up wird atomar persistiert (Transaction) und erzeugt einen nachvollziehbaren Historieneintrag (Snapshot-Before in JSON)
- [ ] **LVL-13**: Free-Archetype-Variante kann pro Charakter aktiviert werden; aktiviert zweiten Talent-Slot, der bis zur Dedication frei wählbar und danach archetype-restricted ist
- [ ] **LVL-14**: Spellcaster bekommen Slot- und Cantrip-Progression nach Klasse/Tradition; spontane Caster zusätzlich Repertoire-Increment
- [ ] **LVL-15**: Deutsche Übersetzungen für neue Talent-Voraussetzungs-Texte und Klassenmerkmal-Beschreibungen werden via bestehender Translation-Pipeline (Claude API + DB-Cache) bereitgestellt

### PWA Foundation

- [ ] **PWA-01**: App ist als PWA installierbar (Web App Manifest, Pflicht-Icon-Größen inkl. maskable, Splash, `display: standalone`)
- [ ] **PWA-02**: Service Worker via `vite-plugin-pwa` mit `injectManifest`-Strategie; user-scoped Cache-Keys verhindern Cross-User-Cache-Leak
- [ ] **PWA-03**: Add-to-Home-Screen-Flow auf Android nutzt `beforeinstallprompt`
- [ ] **PWA-04**: Add-to-Home-Screen-Flow auf iOS zeigt geführte Anleitung (Overlay mit Safari-Schritten), da kein programmatischer Prompt verfügbar
- [ ] **PWA-05**: Charakterbogen ist offline lesbar (Cache-First für GET `/characters/:id` + abgeleitete Endpunkte)
- [ ] **PWA-06**: Inventar, Talente, Aktionen, Alchemie eines bereits geladenen Charakters sind offline lesbar
- [ ] **PWA-07**: Service Worker zeigt "Neue Version verfügbar"-Hinweis mit manueller User-Bestätigung; **kein** automatisches `skipWaiting()`
- [ ] **PWA-08**: Service-Worker-Update wird während aktiver Battle-Session unterdrückt (kein Mid-Fight-Reload)
- [ ] **PWA-09**: TanStack Query persistiert Cache via `idb-keyval` für Offline-Reads über bestehende Hooks
- [ ] **PWA-10**: SW-Cache-Einträge werden bei Live-Update-Events via `postMessage` aus Socket-Hooks invalidiert

### Web Push

- [ ] **PUSH-01**: Server hat persistente VAPID-Keys (env-konfiguriert, dokumentiertes Rotations-Verfahren)
- [ ] **PUSH-02**: User opt-in für Push erfolgt nach expliziter Aktion (Settings-Schalter o.ä.), nicht beim ersten Load
- [ ] **PUSH-03**: Push-Subscription wird pro User + Device persistiert (`PushSubscription`-Tabelle, mehrere Devices pro User möglich)
- [ ] **PUSH-04**: Service Worker verarbeitet `push`-Events und zeigt Notification mit Titel, Body, Icon, Action-Link
- [ ] **PUSH-05**: Server entfernt abgelaufene/ungültige Subscriptions (410 Gone Handling beim Send)
- [ ] **PUSH-06**: GM kann gezielten Push an einen einzelnen Spieler oder an alle Spieler einer Kampagne senden
- [ ] **PUSH-07**: System sendet Battle-Turn-Alert per Push automatisch, wenn Initiative auf den Charakter eines Spielers wechselt
- [ ] **PUSH-08**: Push-Payload enthält Deep-Link in die App (Battle / Charakter / Chat öffnet sich beim Tap)

### Battle Multi-Screen Ausbau

- [ ] **BAT-01**: Eigene Display-Route `/battle/:id/display` rendert read-only Spielsicht (keine GM-Controls, keine Drag-Handles, kein GM-Sidebar-Panel)
- [ ] **BAT-02**: Server hält separate Sub-Rooms `battle:<id>:gm` und `battle:<id>:display`; GM-only-Daten werden serverseitig gefiltert, **nicht** clientseitig per Prop ausgeblendet
- [ ] **BAT-03**: Display-Mode hat eigenes Auth-Modell (kurzlebiger Display-Token oder dedizierter Display-Pseudo-User), URL-Share leakt keine Daten
- [ ] **BAT-04**: Display-Layout ist für querformatigen, eingelassenen Tisch-Bildschirm optimiert (große Schrift, keine Touch-Steuerung nötig)
- [ ] **BAT-05**: Initiative-Tracker erscheint als sortierte Liste mit "Wer ist dran"-Highlight, sichtbar in GM- und Display-Mode
- [ ] **BAT-06**: GM-"Nächster Zug"-Button rückt Initiative weiter; Event broadcastet an alle Clients (GM + Display + Spieler)
- [ ] **BAT-07**: Token-Effekte/-Auren/-Buffs/-Debuffs als Datenmodell (`BattleEffect`-Tabelle mit FK auf Token, Name, optionaler Dauer in Runden)
- [ ] **BAT-08**: GM kann Effekte pro Token hinzufügen, entfernen und aktualisieren über Battle-Sidebar
- [ ] **BAT-09**: Token-Effekte sind auf Display-Mode sichtbar (Icon/Badge am Token + Liste in der Initiative-Karte)
- [ ] **BAT-10**: Token-Add und Token-Remove laufen als WebSocket-Events (`token:added`, `token:removed`); keine Query-Invalidation als Workaround
- [ ] **BAT-11**: GM-Control-Layout läuft auf Touch-Tablets benutzbar (Targets ≥ 44 px, kein Pflicht-Mobile-Layout, aber funktional)

### Würfeln

- [ ] **DICE-01**: User kann PF2e-Notation eingeben und werfen (z.B. `1d20+7`, `2d6+3`, `4d6kh3`); Parser via `@dice-roller/rpg-dice-roller`
- [ ] **DICE-02**: Würfeln ist server-authoritativ (Server würfelt mit `crypto.randomInt`, broadcastet Ergebnis; kein Client-Tampering möglich)
- [ ] **DICE-03**: System berechnet PF2e Degree of Success (Crit Success, Success, Failure, Crit Failure) gegen optionale DC mit ±10-Regel
- [ ] **DICE-04**: Schaden-Rolls verdoppeln auf Crit die Würfel-Anzahl, **nicht** die Modifikatoren (PF2e-Regel)
- [ ] **DICE-05**: Würfe werden in `DiceRoll`-Tabelle persistiert, scoped pro Kampagne und (optional) Battle-Session
- [ ] **DICE-06**: Roll-Log ist live für alle Teilnehmer einer Kampagne/Battle (WebSocket-Broadcast über Dice-Gateway)
- [ ] **DICE-07**: Jeder Roll trägt Zuordnung: User + Charakter + Label (z.B. "Athletik-Probe") + Zeitstempel + optionale DC

### Chat

- [ ] **CHAT-01**: User kann Textnachrichten in einer Kampagne posten (live für alle Mitglieder)
- [ ] **CHAT-02**: User kann Textnachrichten in einer Battle-Session posten (live für alle Teilnehmer)
- [ ] **CHAT-03**: Chat-Nachrichten werden in `ChatMessage`-Tabelle persistiert (scoped pro Kampagne und/oder Battle)
- [ ] **CHAT-04**: Chat-Markdown wird mit `react-markdown` + `rehype-sanitize` gerendert; **kein** `dangerouslySetInnerHTML` ohne Sanitizer
- [ ] **CHAT-05**: Würfelergebnisse werden inline im Chat eingebettet (FK `embedRollId` von ChatMessage auf DiceRoll)
- [ ] **CHAT-06**: Chat-Verlauf lädt paginiert (Initial + Scroll-Back via Cursor)

### GM Live-Tools

- [ ] **GM-01**: GM-Live-Tools-Panel ist als eigene UI-Surface zugänglich (für eingeloggten GM einer Kampagne)
- [ ] **GM-02**: GM kann HP eines Spieler-Charakters live setzen (Schaden, Heilung, Direktwert) — nutzt bestehende Char-Events
- [ ] **GM-03**: GM kann Conditions auf Spieler-Charakter live hinzufügen, entfernen, aktualisieren
- [ ] **GM-04**: GM kann Items aus Equipment-DB an Spieler-Charakter geben (Suche → Auswahl → Übergabe live)
- [ ] **GM-05**: GM kann Geld (Credits) eines Spieler-Charakters live anpassen
- [ ] **GM-06**: Server-seitige Authorisierung prüft auf allen GM-Live-Tool-Events "Aktor ist GM dieser Kampagne"; bestehende Char-WebSocket-Events werden auditiert und ggf. abgesichert
- [ ] **GM-07**: Destruktive Aktionen (z.B. HP auf 0 setzen, Item löschen) erfordern zweistufige Bestätigung
- [ ] **GM-08**: GM kann gezielte Push-/Chat-Nachricht an einen Spieler oder alle Spieler senden (kombiniert PUSH-06 + CHAT-01)

### Obsidian Vault (Read-only)

- [ ] **VAULT-01**: System verbindet zu einem selbst-gehosteten Vault-Endpoint; konkretes Transport-Protokoll wird in der Vault-Discuss-Phase entschieden (Default-Empfehlung: WebDAV-Proxy via NestJS)
- [ ] **VAULT-02**: Vault-Browser zeigt Ordner-Tree-Navigation aus server-seitiger Listing-API
- [ ] **VAULT-03**: User kann eine Markdown-Datei aus dem Vault öffnen und gerendert lesen (CommonMark + GFM Tabellen/Codeblöcke/Bilder)
- [ ] **VAULT-04**: Wikilinks `[[Note]]` und `[[Note|Alias]]` werden als klickbare Links gerendert (Obsidian-Shortest-Path-Auflösung via `@portaljs/remark-wiki-link`)
- [ ] **VAULT-05**: Bild-Embeds `![[image.png]]` werden gerendert; Bilder via Vault-Endpoint geladen (kein direkter Browser-Zugriff auf Vault-Server)
- [ ] **VAULT-06**: Vault-Volltextsuche durchsucht Markdown-Inhalte (server-seitig, Postgres FTS oder vergleichbar)
- [ ] **VAULT-07**: Server validiert alle Pfade gegen Path-Traversal (kein Escape via `../` aus Vault-Root)
- [ ] **VAULT-08**: Zuletzt gelesene Notes (LRU) werden im Service Worker gecacht für Offline-Read
- [ ] **VAULT-09**: Markdown-Renderer nutzt Sanitizer durchgehend (DOMPurify oder rehype-sanitize); kein `rehype-raw` ohne Sanitization
- [ ] **VAULT-10**: Vault-Endpoint-Authentifizierung läuft serverseitig über bestehende JWT-Auth; Vault-Credentials werden nie an den Browser ausgeliefert

## v2 Requirements

Verschoben — anerkannt, aber nicht in dieser Roadmap.

### Level-Up Erweiterungen

- **LVL-V2-01**: Level-Up-Historie-Ansicht im Charakterbogen (Was wurde an welchem Level gewählt?)
- **LVL-V2-02**: Reverse-Level-Up — bestätigtes Level rückgängig machen

### Battle Polish

- **BAT-V2-01**: Cinematic Display-Theme (off-turn dim, large active-turn-card)
- **BAT-V2-02**: Animierte Push-Ping-Ankunft mit Vibration + In-App-Initiative-Card-Overlay

### Würfeln Polish

- **DICE-V2-01**: GM "Würfelaufforderung anfragen" (kombinierter Push + vorbefüllter Würfel-Button beim Spieler)
- **DICE-V2-02**: Roll-History-Export als HTML/PDF (analog Charakterbogen-Export)
- **DICE-V2-03**: Auto-Anwendung von Conditions aus Zaubern/Angriffen bei kritischem Erfolg

### Vault Erweiterungen

- **VAULT-V2-01**: Frontmatter-NPC-Chips (`npc: true` Notes erscheinen als Hover-Chips in Chat/Battle)
- **VAULT-V2-02**: Vault-Offline-FlexSearch-Index für vollständige Offline-Suche

## Out of Scope

| Feature | Grund |
|---------|-------|
| Bidirektionales Vault-Sync | Read-only deckt aktuellen Bedarf; Write-Konflikte sind eigenes Produkt |
| Offline-Edit + Sync-Queue | Last-write-wins-Korruption; Spielsessions sind online; Komplexität ohne Mehrwert |
| Native iOS/Android-App (Capacitor) | Web Push reicht; PWA-Install ersetzt Native-Bedürfnis; doppelte Codebases |
| In-App-Charakter-Erstellung von null | Pathbuilder-Import bleibt der Erstellungspfad; Doppelarbeit gegen 5 Jahre Pathbuilder-Reife |
| Andere TTRPG-Systeme als PF2e | Datenmodell und UI sind PF2e-spezifisch; Generalisierung kostet Schärfe |
| Öffentlicher Multi-Tenant-Betrieb | Self-hosted für eigene Gruppe; kein Onboarding-Flow nötig |
| Presence/Awareness-Indikatoren | Wert klein vs WebSocket-Komplexität, besonders bei Mobile-Lockscreen |
| Fog of War / Dynamic Lighting / Token Vision | Spiel passiert in Person mit 3D-Minis auf Tisch-Display; obsolet |
| Voice/Video-Chat | Discord existiert und funktioniert |
| 3D-Würfel-Physik mit Animation | Burns CPU, lenkt vom Tisch ab; echte Würfel liegen daneben |
| Real-time kollaboratives Vault-Editing | Read-only ist explizit Scope-Grenze |
| AI-NPCs / AI-Encounter-Generierung | Vault liefert die GM-Vorbereitung |
| Auto-Apply Attack-Rolls auf Enemy-HP | Hohe Datenmodell-Kosten; GM macht das via Live-Tools manuell |
| Marketplace für Maps/NPCs | Single-Tenant, keine Sharing-Anforderung |

## Traceability

| Requirement | Phase | Status |
|-------------|-------|--------|
| LVL-01 | Phase 1 | Pending |
| LVL-02 | Phase 1 | Pending |
| LVL-03 | Phase 1 | Pending |
| LVL-04 | Phase 1 | Pending |
| LVL-05 | Phase 1 | Pending |
| LVL-06 | Phase 1 | Pending |
| LVL-07 | Phase 1 | Pending |
| LVL-08 | Phase 1 | Pending |
| LVL-09 | Phase 1 | Pending |
| LVL-10 | Phase 1 | Pending |
| LVL-11 | Phase 1 | Pending |
| LVL-12 | Phase 1 | Pending |
| LVL-13 | Phase 1 | Pending |
| LVL-14 | Phase 1 | Pending |
| LVL-15 | Phase 1 | Pending |
| PWA-01 | Phase 2 | Pending |
| PWA-02 | Phase 2 | Pending |
| PWA-03 | Phase 2 | Pending |
| PWA-04 | Phase 2 | Pending |
| PWA-05 | Phase 2 | Pending |
| PWA-06 | Phase 2 | Pending |
| PWA-07 | Phase 2 | Pending |
| PWA-08 | Phase 2 | Pending |
| PWA-09 | Phase 2 | Pending |
| PWA-10 | Phase 2 | Pending |
| PUSH-01 | Phase 3 | Pending |
| PUSH-02 | Phase 3 | Pending |
| PUSH-03 | Phase 3 | Pending |
| PUSH-04 | Phase 3 | Pending |
| PUSH-05 | Phase 3 | Pending |
| PUSH-06 | Phase 3 | Pending |
| PUSH-07 | Phase 3 | Pending |
| PUSH-08 | Phase 3 | Pending |
| DICE-01 | Phase 4 | Pending |
| DICE-02 | Phase 4 | Pending |
| DICE-03 | Phase 4 | Pending |
| DICE-04 | Phase 4 | Pending |
| DICE-05 | Phase 4 | Pending |
| DICE-06 | Phase 4 | Pending |
| DICE-07 | Phase 4 | Pending |
| CHAT-01 | Phase 4 | Pending |
| CHAT-02 | Phase 4 | Pending |
| CHAT-03 | Phase 4 | Pending |
| CHAT-04 | Phase 4 | Pending |
| CHAT-05 | Phase 4 | Pending |
| CHAT-06 | Phase 4 | Pending |
| BAT-01 | Phase 5 | Pending |
| BAT-02 | Phase 5 | Pending |
| BAT-03 | Phase 5 | Pending |
| BAT-04 | Phase 5 | Pending |
| BAT-05 | Phase 5 | Pending |
| BAT-06 | Phase 5 | Pending |
| BAT-07 | Phase 5 | Pending |
| BAT-08 | Phase 5 | Pending |
| BAT-09 | Phase 5 | Pending |
| BAT-10 | Phase 5 | Pending |
| BAT-11 | Phase 5 | Pending |
| GM-01 | Phase 6 | Pending |
| GM-02 | Phase 6 | Pending |
| GM-03 | Phase 6 | Pending |
| GM-04 | Phase 6 | Pending |
| GM-05 | Phase 6 | Pending |
| GM-06 | Phase 6 | Pending |
| GM-07 | Phase 6 | Pending |
| GM-08 | Phase 6 | Pending |
| VAULT-01 | Phase 7 | Pending |
| VAULT-02 | Phase 7 | Pending |
| VAULT-03 | Phase 7 | Pending |
| VAULT-04 | Phase 7 | Pending |
| VAULT-05 | Phase 7 | Pending |
| VAULT-06 | Phase 7 | Pending |
| VAULT-07 | Phase 7 | Pending |
| VAULT-08 | Phase 7 | Pending |
| VAULT-09 | Phase 7 | Pending |
| VAULT-10 | Phase 7 | Pending |

**Coverage:**
- v1 requirements: 75 total
- Mapped to phases: 75 (Phase 1: 15, Phase 2: 10, Phase 3: 8, Phase 4: 13, Phase 5: 11, Phase 6: 8, Phase 7: 10)
- Unmapped: 0 ✓

---
*Requirements defined: 2026-04-27*
*Last updated: 2026-04-27 after roadmap mapping*
