Schließt die Ops-Lücke „kein versioniertes Schema-Tracking" aus FEATURE_IDEAS.md. * apps/api/src/db/migrations/0000_baseline.sql — Drizzle-generierte Baseline-Migration, 355 Zeilen, 25 Tabellen + 5 Enums (cards- und marketplace-Schema). Eingefrostet auf den Live-Stand 2026-05-12. * apps/api/scripts/bootstrap-drizzle-tracking.ts — neues Script, markiert die Baseline in einer bestehenden DB als „bereits angewandt", ohne SQL erneut auszuführen. Verwendet sha256 wie drizzle-orm/migrator (Hash 312d67ba1aeb…), idempotent. * package.json: drizzle:migrate + drizzle:bootstrap-tracking npm-scripts. * docs/playbooks/DRIZZLE_MIGRATIONS_BOOTSTRAP.md — Hand-Over für Prod (Bootstrap einmalig, dann normaler Workflow: schema → generate → commit → migrate, kein push --force mehr). Lokal verifiziert: 17/104 Tests grün, bootstrap idempotent, drizzle-kit migrate erkennt die Baseline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
18 KiB
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
apps/api/src/middleware/auth.ts:39auf opt-in geflippt:ALLOW_DEV_STUB = process.env.CARDS_AUTH_DEV_STUB === 'true'. Vergessene env-var ⇒ Bypass AUS.infrastructure/docker-compose.production.yml: Default flipped auf:-false, plusNODE_ENV: productionfür cards-api ergänzt (fehlte zuvor — nur cards-web hatte es).infrastructure/.env.production.example:CARDS_AUTH_DEV_STUB=falseals Pflichtzeile mit Kommentar.apps/api/vitest.config.ts+apps/api/tests/setup.tsangelegt, damit die Test-Suiten (5 Files mitX-User-Id-Auth) den Stub automatisch aktivieren. Verifikation:pnpm test→ 16 Files, 100 Tests grün.
Verbleibend bei dir (Mac Mini + Deploy)
git pull/ Rebase auf der Prod-Box, danndocker compose -f infrastructure/docker-compose.production.yml \ up -d --build cards-api.- Verifizieren mit
curl -i -H "X-User-Id: probe" https://cardecky-api.mana.how/api/v1/decks→ erwartet 401 (vorher 200). - Optional:
.env.productionauf dem Mac Mini um die expliziteCARDS_AUTH_DEV_STUB=false-Zeile ergänzen (jetzt nur noch Doku-Konsistenz — der Compose-Default ist schon fail-secure). - Forensik:
cards.decks.user_idundcards.cards.user_idgegenmana_auth.usersjoinen — 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 untercards/[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-156berechnetstreak_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 undpullUpdate(deckId)im Deck-Edit (routes/decks/[id]/edit/+page.svelte:39,113,275). - Lizenz-Feld auf Marketplace-Decks —
marketplace/decks.ts:73hatlicensemit DefaultCardecky-Personal-Use-1.0; Constraint bindet Preis an Lizenz-Typ.
Lern-Erlebnis
Scheduler-Verbesserungen
- FSRS-Parameter pro User optimieren —
ts-fsrsliefertcomputeParameters()aus Review-History; Schema (decks.fsrs_settings) und Per-Deck-Override sind vorbereitet, aber kein Endpoint und kein UI. Größter messbarer Retention-Gewinn pro Aufwand. - Leech-Detection —
reviews.lapseszählt bereits; Auto-Markierung + UI-Vorschlag „aufteilen / suspendieren" für Karten oberhalb eines Schwellwerts. - Undo letzte Bewertung — wichtiger UX-Reflex; aktuell muss man das Review händisch zurückbauen.
- 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 ≤ nowlinear 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 —
{{c1::answer::hint}}wird aktuell beim Rendern fallen gelassen; Hint-Anzeige steht inSTATUS.mdals verbleibender Phase-9-Punkt.
Kartentypen, Schema vorhanden / vorbereitet
- Bild-Front / Bild-Back — als generischer Type mit
media_refinfields. MinIO-Storage +media_files-Pfad ist seit Sprint 9k da, also rein UI-Frage. - Speech-In (Audio-Antwort vom User) — Whisper via
mana-sttist im Plattform-Stack vorhanden; Schema müssteexpected+ Audio- Vergleichs-Strategie definieren.
Gamification & Motivation
- Streak-Freeze-Token — ein Streak-Schutztag pro Woche, optional durch Credits kaufbar.
- Streak im Header — heute nur im Stats-Dashboard sichtbar; Header-Glyph mit Zahl wäre Mikro-Aufwand, sichtbare Wirkung.
- 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 wirdmana-notifyvon Cards noch nicht benutzt (siehemarketplace/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 — pro Deck und Tag, aus FSRS-State ableitbar.
- 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 — kleines „Wieso wurde ich befragt?"-Tooltip mit 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.tsim Schema vorhanden; Report-Funktion auf Decks/Karten im UI fehlt. - Lizenz-Auswahl bei Publish —
decks.licensehat DefaultCardecky-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 inapp.htmlfest 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-motionrespektieren inDeckFan.svelteundDeckStack.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, nichtopt-in— siehe akute Sicherheitslücke oben. Fix-Anweisung dort, dieser Eintrag bleibt als Erinnerung, dass die Middleware-Logik inauth.ts:39auf opt-in geflippt gehört (=== 'true'statt!== 'false'). - JWT in
localStorage—dev-stub.svelte.ts:13speichert das Access-Token untercards.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:13whitelistetimage/- Prefix;image/svg+xmlist 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-Policyimg-srcstrikt halten, oder SVG-Upload separat sanitisieren (svgo + Script-Strip). - Security-Headers — gebaut 2026-05-12, noch nicht deployed.
- API:
secureHeaders()aus Hono vorcors()eingehängt (apps/api/src/index.ts:3,30). - Web:
apps/web/src/hooks.server.tsneu, setzt X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policy strict-origin-when-cross-origin, plus HSTS (180 Tage, includeSubDomains) wennNODE_ENV=production. - CSP läuft Report-Only seit 2026-05-12.
hooks.server.tssetztContent-Security-Policy-Report-Onlymit 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 viaCARDS_CSP_ENFORCE=trueauf Enforce flippen. SVG-Upload- Risiko ist dann gemildert (script-src verbietet inline-JS in SVG-Inlinen).
- API:
- CORS lässt
localhostin Prod durch — gebaut 2026-05-12, noch nicht deployed. Live-Probe hatteAccess-Control-Allow-Origin: http://localhost:9999gezeigt. Patch: localhost-Regex inapps/api/src/index.tsperNODE_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 jetztstorage_ok: true|false- optional
storage_errorim Response. Frontend zeigt im Account-Delete-Flow eine Fehler-Toast wennstorage_ok=false.
- optional
- Service-Key-Rotation-Playbook — gebaut 2026-05-12.
docs/playbooks/SERVICE_KEY_ROTATION.mdmit 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.receive60/min/IP,media.upload30/min/user,decks.generate10/min/user,decks.from-image10/min/user,dsgvo.*10/min/IP. Verifiziert intests/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.tsschreibt strukturierte JSON-Zeilen auf stdout (kind: 'audit'). Aktiv auf/dsgvo/export,/dsgvo/delete,/me/export,/me/delete. Persistierung in eineaudit_log-Tabelle ist additiv möglich, ohne Aufrufer anzupassen. - Health-Endpoint inkl. DB+MinIO-Probe — gebaut 2026-05-12, noch
nicht deployed.
/healthzbleibt simpel (Liveness), neu ist/healthz/detailsmit echtemSELECT 1und 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-honovorhanden, 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 habencontent_hash = NULL, Re-Import-Dedupe ist auf diese Karten blind (sieheSTATUS.mdSubtilitä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 inaccount/. Heute ist es als DSGVO-Export versteckt. - Telemetrie-Audit dokumentieren — verifiziert: 0 Tracker —
apps/web/src/enthält weder PostHog noch Plausible/Matomo/Umami, keingtag, keinetrack()-Aufrufe. Das ist ein hartes Mission-Argument, das man heute kostenlos hergibt. Vorschlag: kleine Surface inaccount/oder im Footer („Cards trackt dich nicht — Code-Beweis"), die auf dengit grep-Befund im Repo verlinkt. - Tier-frei-Modus erhalten — Schema und Plumbing für
mana-creditssind 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.mdspricht von „lokalem E2E-Smoke"; einplaywright.config.tsexistiert 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-trackingmarkiert die Baseline auf der Live-DB als „bereits angewandt", ohne SQL re-auszuführen. Lokal verifiziert: idempotent +drizzle:migrateerkennt die Migration danach als bekannt. Playbook indocs/playbooks/DRIZZLE_MIGRATIONS_BOOTSTRAP.md. Nächster Schritt beim User: einmalig auf der Prod-Box ausführen, danach istpush --forceTabu.
- 5 Enums) festgefrostet.
- 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.ymlnebenci.yml, im.github/workflows/-Ordner liegt aber nurci.yml. Entweder Workflow nachziehen oder Doku korrigieren.
Offene Punkte
- Was nach diesem Hardening-Sprint übrig bleibt:
- CSP setzen — eigener Mini-Sprint mit Browser-Test, weil SVG-XSS-Risiko erst mit CSP wirklich gemildert ist.
- Drizzle-Migrationen versionieren — bevor das erste Prod-
Schema-Diff weh tut. Heute läuft alles via
db:push. - FSRS-Parameter-Optimierung pro User — größter messbarer Lern-Effekt, Schema schon vorbereitet.
- Service-Key-Rotation-Playbook in
docs/playbooks/anlegen, bis diemana-auth.app_service_keys-Anbindung (Phase F-1) fertig ist. - 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-Slotvisibility = '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-notifywird von Cards noch nicht aufgerufen; sobald Streak/Weekly/PR-Notifies reinkommen sollen, ist das ein eigener Sprint.