cards/docs/FEATURE_IDEAS.md
Till JS abf493aeec
Some checks are pending
CI / validate (push) Waiting to run
feat(cards): recovery mode, undo, FSRS slider, streak header, stats charts, blog
Study-View:
- Graceful Backlog Recovery: Banner bei >30 fälligen Karten, Recovery-Queue
  sortiert nach Stability aufsteigend (25er-Batch, ?recovery=true)
- Undo letzte Bewertung: 5s-Toast mit RAF-Fortschrittsbalken, Ctrl/Cmd+Z,
  prevSnapshot-Spalte in reviews (Migration 0001, Prod deployed)
- FSRS-Tooltip nach Reveal: State / Stability / Difficulty als Popover

Deck-Edit:
- Neuer Abschnitt „Lern-Algorithmus" mit request_retention-Slider (50–99 %)

Header:
- Streak-Pill (🔥 N) + fällige-Karten-Pill via GET /api/v1/me/summary

Stats-Page:
- Difficulty-Distribution (5 Buckets, Farb-Bars)
- Deck-Fortschritt (Mastery % = stability>21, max 6 Decks)

API:
- GET /me/summary: streak_days + due_now (leichtgewichtiger Header-Endpoint)
- GET /reviews/due: ?recovery=true → stability-sort, Limit 25
- POST /reviews/:cardId/:subIndex/undo: prevSnapshot-Restore, 409 wenn leer
- /me/stats: difficulty_distribution + deck_mastery

Landing:
- 5 Blog-Artikel (Quizlet-Paywall, FSRS, Datenschutz, Anki, Lernkarten-Tipps)
- BlogTeaser-Komponente auf Startseite, Footer-Spalte „Artikel"

i18n: 11 neue Schlüssel in DE/EN/FR/IT/ES

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 13:37:03 +02:00

427 lines
19 KiB
Markdown
Raw Permalink 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.

# Feature Ideas
Stand: 2026-05-12. Korrektur-Pass nach Code-Review gegen den
aktuellen Cardecky-Stand. Items, die zwischen Erst-Erstellung
(2026-05-11) und heute bereits implementiert wurden, sind unten in
**„Seit letzter Liste gebaut"** geführt, damit der Diff nachvollziehbar
bleibt, und aus den Themen-Sektionen entfernt.
---
## 🔴 Akute Sicherheitslücke — Live verifiziert 2026-05-12
**Dev-Stub-Auth-Bypass ist auf Production aktiv.**
`curl -H "X-User-Id: <beliebig>" https://cardecky-api.mana.how/api/v1/decks`
liefert **200 OK** (ohne Header: 401), und Dev-Stub-User bekommen
`founder`-Tier (`auth.ts:90`).
### Repo-Patch — gebaut 2026-05-12, noch nicht deployed
1. `apps/api/src/middleware/auth.ts:39` auf **opt-in** geflippt:
`ALLOW_DEV_STUB = process.env.CARDS_AUTH_DEV_STUB === 'true'`.
Vergessene env-var ⇒ Bypass AUS.
2. `infrastructure/docker-compose.production.yml`: Default flipped
auf `:-false`, plus `NODE_ENV: production` für cards-api ergänzt
(fehlte zuvor — nur cards-web hatte es).
3. `infrastructure/.env.production.example`: `CARDS_AUTH_DEV_STUB=false`
als Pflichtzeile mit Kommentar.
4. `apps/api/vitest.config.ts` + `apps/api/tests/setup.ts` angelegt,
damit die Test-Suiten (5 Files mit `X-User-Id`-Auth) den Stub
automatisch aktivieren. **Verifikation:** `pnpm test`
16 Files, 100 Tests grün.
### Verbleibend bei dir (Mac Mini + Deploy)
1. `git pull` / Rebase auf der Prod-Box, dann
`docker compose -f infrastructure/docker-compose.production.yml \
up -d --build cards-api`.
2. Verifizieren mit
`curl -i -H "X-User-Id: probe" https://cardecky-api.mana.how/api/v1/decks`
→ erwartet **401** (vorher 200).
3. Optional: `.env.production` auf dem Mac Mini um die explizite
`CARDS_AUTH_DEV_STUB=false`-Zeile ergänzen (jetzt nur noch
Doku-Konsistenz — der Compose-Default ist schon fail-secure).
4. Forensik: `cards.decks.user_id` und `cards.cards.user_id` gegen
`mana_auth.users` joinen — IDs ohne Match wären Indizien für
ausgenutzten Bypass.
---
## Seit letzter Liste gebaut (Stand-Korrektur)
Diese Punkte standen in der 2026-05-11-Fassung noch als Ideen, sind
aber im Code längst gelandet:
- **`audio-front` / `typing` / `multiple-choice`** — komplette
Renderer + Editor-Forms + Integration im Study-Flow
(`AudioFrontView.svelte`, `TypingView.svelte`, `MultipleChoiceView.svelte`,
Edit-Routen unter `cards/[id]/edit/+page.svelte`).
- **Keyboard Shortcuts im Study-Mode** — `1/2/3/4` = Rating,
`Space`/`Enter` = Reveal bzw. `good` (`routes/study/[deckId]/+page.svelte:170-180`).
- **Daily Streaks (Backend + Anzeige)** — `me.ts:106-156` berechnet
`streak_days`, Stats-Dashboard zeigt es an. Streak-Freeze, Streak im
Header und Streak-Push fehlen noch (siehe Gamification unten).
- **CSV-Import + CSV-Export** — `lib/csv/{parse,import,export}.ts` +
`CsvImport.svelte`.
- **Quizlet-Import** — `lib/quizlet/parse.ts` + `QuizletImport.svelte`.
- **Marketplace-Smart-Merge-Pull-UI** — `updateAvailable`-Banner und
`pullUpdate(deckId)` im Deck-Edit
(`routes/decks/[id]/edit/+page.svelte:39,113,275`).
- **Lizenz-Feld auf Marketplace-Decks** — `marketplace/decks.ts:73`
hat `license` mit Default `Cardecky-Personal-Use-1.0`; Constraint
bindet Preis an Lizenz-Typ.
---
## Lern-Erlebnis
### Scheduler-Verbesserungen
- **FSRS-Parameter pro User optimieren** — `ts-fsrs@5.3.2` hat
**kein** `computeParameters()` aus Review-History (das erfordert den
Python `fsrs-optimizer`). Der praktisch nutzbare Hebel ist
`request_retention` (0.50.99): höherer Wert → mehr Wiederholungen,
besser für prüfungsrelevantes Lernen; niedrigerer Wert → lockerer,
gut für Allgemeinwissen. Schema (`decks.fsrs_settings`) und
Per-Deck-PATCH-Endpoint sind da; **Retention-Slider im Deck-Edit
gebaut 2026-05-13.** w-Gewichte-Optimierung (Offline-Python-Skript
→ JSON-Upload) bleibt offen.
- **Leech-Detection — gebaut 2026-05-12.** `me/stats` liefert
`leech_cards` (Threshold 4 Lapses, Limit 20, sortiert nach
Lapses desc, mit Front-Snippet + Deck-Name). Stats-Page hat eine
rote Leech-Sektion mit Link in den Card-Editor. i18n in DE/EN/
FR/IT/ES. Suspension/Aufteilen-Vorschläge sind nächste Welle.
- **Undo letzte Bewertung — gebaut 2026-05-13.** `prevSnapshot`-
Spalte in `reviews`, API `POST /:cardId/:subIndex/undo`, 5-s-Toast
mit Fortschrittsbalken im Study-View, Ctrl/Cmd+Z-Shortcut.
- **Card Burial / Suspension** — Karten temporär deaktivieren ohne
Löschen; häufig angefragtes Anki-Feature.
- **Geschwister-Burial** — Cloze-Cluster und basic-reverse-Seiten
nicht am selben Tag wiederholen.
- **Custom Study Sessions** — gefilterte Sitzungen: nur neue Karten,
nur Fehler der letzten Woche, nach Tag filtern. Tag-Filter im
`reviews`-Endpoint fehlt aktuell ganz.
- **Session-Mix-Algorithmus** — heute wird `due ≤ now` linear
abgearbeitet; Optionen „Neue Karten zuerst", „durchmischt", „nur
Fehler" als saubere Filter im Queue-Loader.
- **Subdeck-Unterstützung** — hierarchische Deck-Struktur
(z. B. Vokabeln → Nomen / Verben).
- **Cloze-Hint-Anzeige — bereits implementiert.** `renderClozePrompt`
in `packages/cards-domain/src/cloze.ts` rendert `{{c1::answer::hint}}`
bereits als `[hint]`. `STATUS.md`-Eintrag ist veraltet.
### Kartentypen, Schema vorhanden / vorbereitet
- **Bild-Front / Bild-Back** — als generischer Type mit `media_ref`
in `fields`. MinIO-Storage + `media_files`-Pfad ist seit Sprint 9k
da, also rein UI-Frage.
- **Speech-In** (Audio-Antwort vom User) — Whisper via `mana-stt`
ist im Plattform-Stack vorhanden; Schema müsste `expected` + Audio-
Vergleichs-Strategie definieren.
---
## Gamification & Motivation
- **Streak-Freeze-Token** — ein Streak-Schutztag pro Woche, optional
durch Credits kaufbar.
- **Streak im Header — gebaut 2026-05-13.** `GET /api/v1/me/summary`
liefert `streak_days` + `due_now`; Header zeigt Flammen-Pill und
fällige-Karten-Pill via `onMount`.
- **XP + Badges** — Meilensteine (erstes Deck, 100 Karten, 30-Tage-
Streak).
- **Tages-Ziele** — „Heute: 20 Karten" mit Progress-Bar im Dashboard.
- **Push/Email-Reminders** — „Du hast heute noch 15 fällige Karten"
via `mana-notify`. Aktuell wird `mana-notify` von Cards noch nicht
benutzt (siehe `marketplace/pull-requests.ts:41` — „Notify-Calls
ausgelassen — eigene Welle").
- **Estimated Mastery Date** — „Dieses Deck beherrschst du
voraussichtlich in 3 Wochen" (aus FSRS-Stability ableitbar).
---
## KI-Features
- **Auto-Cloze-Generator** — Text markieren → `{{c1::...}}`
automatisch einfügen.
- **Card-Split-Vorschlag** — KI erkennt informationsreiche Karten
und schlägt Aufteilung vor.
- **Erklär-Modus** — Nach falscher Antwort: KI erklärt den
Zusammenhang (opt-in).
- **Auto-Tagging** — Karten beim Erstellen / Importieren semantisch
taggen.
- **Duplicate Detection** — semantische Ähnlichkeit über Decks
hinweg erkennen.
- **Card Quality Score** — Hinweis „Diese Karte hat zu viel Text" +
Verbesserungsvorschlag.
---
## Analytics & Insights
- **Vergessenskurven-Visualisierung / Graceful Backlog Recovery —
gebaut 2026-05-13.** Stats-Page zeigt Difficulty-Distribution
(5 Buckets, Farb-Bars) + Deck-Fortschritt (Mastery %, Stability>21).
Study-View zeigt Recovery-Banner wenn total>30 fällige Karten,
startet Queue nach Stability sortiert (25er-Batch).
- **Retention-Rate** — aufgeschlüsselt nach Kategorie und Sprache.
- **Lernzeit-Tracking** — Minuten pro Session, Wochentrend.
- **Karten-Schwierigkeits-Heatmap** — welche Karten kosten die
meiste Review-Zeit.
- **Wöchentliche Zusammenfassung** — In-App oder per Email via
`mana-notify`.
- **Algorithmus-Transparenz pro Karte — gebaut 2026-05-13.**
FSRS-Tooltip im Study-View: ⓘ-Button nach Reveal öffnet Popover
mit State, Stability, Difficulty, letztem Rating. Macht FSRS
sichtbar (Mission-Wert „Souveränität").
---
## Import / Export
- **PDF-Export** — druckbare Karteikarten (A6-Format,
vorder-/rückseitig). Print-Route existiert schon
(`decks/[id]/print/`), aber als HTML-Print, nicht generiert-PDF.
- **`.apkg`-Export** — Round-Trip mit dem Anki-Parser (Parser ist
schon da). Stärkste „du kannst jederzeit weggehen"-Geste,
Mission-Argument.
- **Web Clipper** (Browser-Extension) — markierter Text → sofort
neue Karte; eigenes Projekt, eigener Scope.
- **SuperMemo XML** — für Power-User aus dem SM-Ecosystem.
- **FSRS-State-Export** — Lernstand als JSON exportieren für Backup
und Migration (über DSGVO-Export hinaus, in interop-tauglichem
Format).
---
## Zusammenarbeit & Community
- **Study Spaces** — gemeinsame Decks für Schulklassen und
Lerngruppen (braucht Gruppen-Konzept in `mana-auth`, das noch nicht
existiert; `decks.visibility = 'space'` ist im Schema vorgesehen,
aber ohne Spaces-Backend wirkungslos).
- **Deck-Ratings & Kommentare** — Qualitätssicherung im Marketplace
durch Community. `marketplace/discussions.ts`-Schema existiert,
UI-Anbindung müsste geprüft werden.
- **Study Challenges** — mit Freunden auf demselben Deck messen.
- **Kreator-Analytics** — für Marketplace-Publisher: Views, Forks,
Abonnenten-Retention.
- **Collaborative Decks** — Team-Editing mit Rollen
(Maintainer / Contributor).
---
## Marketplace (eigener Themenblock)
Marketplace-Schema + Pull-Update-UI sind da, aber drumherum klafft
einiges:
- **Pull-Request-UI** — Backend (`marketplace/pull-requests.ts`) und
API-Client (`lib/api/marketplace.ts`) existieren; eine Surface, wo
ein Fork-Maintainer Änderungen *an* das Original *vorschlagen*
kann, fehlt im Web.
- **Versions-Diff zwischen Fork und Upstream** — Voraussetzung,
damit Smart-Merge-Pull nicht „trust me"-Klick ist.
- **Moderations-Queue-Surface** — `marketplace/moderation.ts` im
Schema vorhanden; Report-Funktion auf Decks/Karten im UI fehlt.
- **Lizenz-Auswahl bei Publish** — `decks.license` hat Default
`Cardecky-Personal-Use-1.0`; Standard-Lizenzen
(CC-BY-SA, CC-0, CC-BY-NC) als Optionen im Publish-Flow.
- **Lizenz-Anzeige beim Studieren** geforkter Decks — wer das Deck
veröffentlicht hat, welche Lizenz greift; transparent unten in der
Study-View.
---
## UX / Plattform
- **PWA Offline-Read-Only** als Zwischenschritt zur vollen PWA:
Service-Worker cached die letzte Queue, Bewertungen werden
gepuffert. Bricht die Server-authoritative-Invariante nicht
(Puffer ist transient).
- **Dark Mode / Theme-Switcher** — `data-theme="forest"` ist in
`app.html` fest verdrahtet; In-App-Auswahl fehlt. Bei der
laufenden 12-Token-Theming-Strategie ohnehin geplant.
- **Bulk-Operationen** — mehrere Karten auswählen, verschieben,
taggen, löschen.
- **Dynamic Decks / Smart Playlists** — automatisch gefiltert:
z. B. „alle Karten mit Tag 'Grammatik' aus 3 Decks".
- **Card History** — Lernverlauf pro Karte: wann wie bewertet.
---
## A11y (konkret aufs UI bezogen)
- **`prefers-reduced-motion` respektieren** in `DeckFan.svelte` und
`DeckStack.svelte` (animationslastige Komponenten).
- **Screen-Reader-Live-Region** im Study-View für das Reveal-Event
(„Antwort eingeblendet").
- **Touch-Targets ≥ 44 px** für die Rating-Buttons; Mobile-Review
ist der Haupt-Use-Case und Code zeigt keine explizite Min-Höhe.
- **Fokus-Reihenfolge nach Reveal** — Cursor sollte auf den Rating-
Buttons landen, nicht am Body-Anfang.
- **Tastatur-Hilfe-Overlay** im Study-Mode (`?`-Taste): zeigt die
bestehenden Shortcuts an. Heute sind sie undokumentiert in der UI.
---
## Security (eigener Block, weil Live-App)
- **Dev-Stub-Default ist `opt-out`, nicht `opt-in`** — siehe akute
Sicherheitslücke oben. Fix-Anweisung dort, dieser Eintrag bleibt
als Erinnerung, dass die Middleware-Logik in `auth.ts:39` auf
opt-in geflippt gehört (`=== 'true'` statt `!== 'false'`).
- **JWT in `localStorage`** — `dev-stub.svelte.ts:13` speichert das
Access-Token unter `cards.auth.accessToken`. Anfällig für XSS-
Token-Diebstahl. Mitigation: DOMPurify sanitisiert Markdown (gut),
aber HttpOnly-Cookie wäre der robustere Ansatz, sobald der SSO-
Cookie-Pfad ohnehin schon da ist.
- **SVG-Upload erlaubt** — `media.ts:13` whitelistet `image/`-
Prefix; `image/svg+xml` ist im Extension-Map (`media.ts:28`).
SVG kann eingebettetes JavaScript enthalten. Wenn SVG-Medien per
`<img>` gerendert werden, ist es harmlos; bei `<object>`/`<iframe>`
oder direkter Einbettung gibt es ein XSS-Loch. Mindestens
Content-Security-Policy `img-src` strikt halten, oder SVG-Upload
separat sanitisieren (svgo + Script-Strip).
- **Security-Headers — gebaut 2026-05-12, noch nicht deployed.**
- API: `secureHeaders()` aus Hono vor `cors()` eingehängt
(`apps/api/src/index.ts:3,30`).
- Web: `apps/web/src/hooks.server.ts` neu, setzt X-Frame-Options
DENY, X-Content-Type-Options nosniff, Referrer-Policy
strict-origin-when-cross-origin, plus HSTS (180 Tage,
includeSubDomains) wenn `NODE_ENV=production`.
- **CSP läuft Report-Only seit 2026-05-12.** `hooks.server.ts`
setzt `Content-Security-Policy-Report-Only` mit restriktiver
Policy (default-src 'self', script-src 'self', img-src
'self' data: blob:, connect-src whitelist auf
cardecky-api/auth.mana.how/share/mcp). Violations laufen in
die Browser-DevTools-Console. Nach 1-2 Tagen Live-Beobachtung
via `CARDS_CSP_ENFORCE=true` auf Enforce flippen. SVG-Upload-
Risiko ist dann gemildert (script-src verbietet inline-JS in
SVG-Inlinen).
- **CORS lässt `localhost` in Prod durch — gebaut 2026-05-12,
noch nicht deployed.** Live-Probe hatte
`Access-Control-Allow-Origin: http://localhost:9999` gezeigt.
Patch: localhost-Regex in `apps/api/src/index.ts` per
`NODE_ENV === 'production'`-Check disabled.
- **DSGVO-Delete-Honesty — gebaut 2026-05-12, noch nicht deployed.**
Sowohl `/api/v1/dsgvo/delete` (Service-Key) als auch
`/api/v1/me/delete` (Self-Service) liefern jetzt `storage_ok: true|false`
+ optional `storage_error` im Response. Frontend zeigt im
Account-Delete-Flow eine Fehler-Toast wenn `storage_ok=false`.
- **Service-Key-Rotation-Playbook — gebaut 2026-05-12.**
`docs/playbooks/SERVICE_KEY_ROTATION.md` mit 5-Schritt-Rotation,
Tabus, Phase-F-1-Übergang. Bis die mana-auth-managed Variante
fertig ist, ist das die SoT.
---
## Operations & Resilienz
Bisher gar nicht in dieser Liste behandelt, aber Cards ist live:
- **Rate-Limiting — gebaut 2026-05-12, noch nicht deployed.**
In-Memory Sliding-Window-Middleware in
`apps/api/src/middleware/rate-limit.ts`, dependency-frei. Aktive
Limits: `share.receive` 60/min/IP, `media.upload` 30/min/user,
`decks.generate` 10/min/user, `decks.from-image` 10/min/user,
`dsgvo.*` 10/min/IP. Verifiziert in `tests/rate-limit.test.ts`
(4 Tests). Bei Multi-Container-Setup später auf Redis oder
Cloudflare-Rate-Limit umsteigen.
- **Audit-Log für DSGVO-Aktionen — gebaut 2026-05-12, noch nicht
deployed.** `apps/api/src/lib/audit.ts` schreibt strukturierte
JSON-Zeilen auf stdout (`kind: 'audit'`). Aktiv auf
`/dsgvo/export`, `/dsgvo/delete`, `/me/export`, `/me/delete`.
Persistierung in eine `audit_log`-Tabelle ist additiv möglich,
ohne Aufrufer anzupassen.
- **Health-Endpoint inkl. DB+MinIO-Probe — gebaut 2026-05-12, noch
nicht deployed.** `/healthz` bleibt simpel (Liveness), neu ist
`/healthz/details` mit echtem `SELECT 1` und MinIO-`bucketExists`-
Probe, Status 200 bei beidem grün, sonst 503 mit Latency+Error
je Probe.
- **Strukturiertes Logging + Request-IDs** end-to-end — vermutlich
via `@mana/shared-hono` vorhanden, aber im Frontend-Fehler-Toast
bisher keine sichtbare Correlation-ID.
- **Backup-Strategie für `cards`-DB + MinIO-Bucket** — hängt am
globalen Backup-Cron-TODO, ist aber jetzt mit Prod-Daten dringend.
- **`content_hash`-Backfill-Skript** — Pre-Sprint-9j-Karten haben
`content_hash = NULL`, Re-Import-Dedupe ist auf diese Karten
blind (siehe `STATUS.md` Subtilität #10).
---
## Mission-Fit (Vereins-Werte aufs Produkt anwenden)
- **Anti-Lock-In als Feature, nicht als Disclaimer** — `.apkg`-
Export plus FSRS-State-Export plus eine sichtbare „Daten
mitnehmen"-Surface in `account/`. Heute ist es als
DSGVO-Export versteckt.
- **Telemetrie-Audit dokumentieren — verifiziert: 0 Tracker** —
`apps/web/src/` enthält weder PostHog noch Plausible/Matomo/Umami,
kein `gtag`, keine `track()`-Aufrufe. Das ist ein hartes
Mission-Argument, das man heute kostenlos hergibt. Vorschlag:
kleine Surface in `account/` oder im Footer („Cards trackt dich
nicht — Code-Beweis"), die auf den `git grep`-Befund im Repo
verlinkt.
- **Tier-frei-Modus erhalten** — Schema und Plumbing für
`mana-credits` sind da (`credits-client.ts`, `requireTier`), aber
MVP ist tier-frei. Bei jeder neuen Feature-Idee bewusst markieren,
ob sie tier-pflichtig wird oder nicht; default frei.
---
## DevX & Code-Hygiene
- **Playwright-E2E in CI** — `STATUS.md` spricht von „lokalem
E2E-Smoke"; ein `playwright.config.ts` existiert im Repo nicht.
Bei Live-App mit Marketplace-Forks die schmerzhafteste
Regressions-Quelle.
- **Drizzle-Migrationen versionieren — Repo-Setup gebaut 2026-05-12,
Prod-Bootstrap offen.** `0000_baseline.sql` (355 Zeilen, 25 Tabellen
+ 5 Enums) festgefrostet. `apps/api/scripts/bootstrap-drizzle-tracking.ts`
+ `pnpm drizzle:bootstrap-tracking` markiert die Baseline auf der
Live-DB als „bereits angewandt", ohne SQL re-auszuführen. Lokal
verifiziert: idempotent + `drizzle:migrate` erkennt die Migration
danach als bekannt. Playbook in
`docs/playbooks/DRIZZLE_MIGRATIONS_BOOTSTRAP.md`. Nächster Schritt
beim User: einmalig auf der Prod-Box ausführen, danach ist `push
--force` Tabu.
- **Storybook / Histoire für `lib/components/`** — 20+ Svelte-
Komponenten ohne isolierte Vorschau; Lost-Pixel-Theming-Strategie
würde davon doppelt profitieren.
- **CLAUDE.md ↔ Realität synchen** — CLAUDE.md erwähnt
`deploy.yml` neben `ci.yml`, im `.github/workflows/`-Ordner liegt
aber nur `ci.yml`. Entweder Workflow nachziehen oder Doku
korrigieren.
---
## Offene Punkte
- **Was nach diesem Hardening-Sprint übrig bleibt:**
1. **CSP setzen** — eigener Mini-Sprint mit Browser-Test, weil
SVG-XSS-Risiko erst mit CSP wirklich gemildert ist.
2. **Drizzle-Migrationen versionieren** — bevor das erste Prod-
Schema-Diff weh tut. Heute läuft alles via `db:push`.
3. **FSRS-Parameter-Optimierung pro User** — größter messbarer
Lern-Effekt, Schema schon vorbereitet.
4. **Service-Key-Rotation-Playbook** in `docs/playbooks/`
anlegen, bis die `mana-auth.app_service_keys`-Anbindung
(Phase F-1) fertig ist.
5. **JWT-Storage von `localStorage` → HttpOnly-Cookie**
XSS-Token-Diebstahl-Härtung. Größerer Umbau weil der
SSO-Callback-Flow das mitziehen muss.
- **PWA-Offline-Read-Only** ist der Architektur-Trade-off mit dem
größten Risiko: der saubere server-authoritative Pfad würde um
einen Sync-Puffer erweitert. Lieber spät als verfrüht.
- **Study Spaces** bleibt blockiert durch fehlendes Gruppen-Konzept
in `mana-auth`; Schema-Slot `visibility = 'space'` ist
vorbereitet, aber ohne Backend wirkungslos.
- **Marketplace-Reifegrad transparent in STATUS.md führen** —
aktuell taucht „Marketplace" in STATUS.md nur in der „Strategie-
B-Ausnahme"-Notiz auf; ob Marketplace im UI freigeschaltet ist
oder hinter einer Feature-Flag steckt, ist von außen nicht
ablesbar.
- **Notify-Anbindung ist offen** — `mana-notify` wird von Cards
noch nicht aufgerufen; sobald Streak/Weekly/PR-Notifies
reinkommen sollen, ist das ein eigener Sprint.