# Cards — Projekt-Status & Onboarding **Letztes Update:** 2026-05-08 (Phase 8 + Phase 9 erweiterte Polish-Welle) **Wenn du gerade neu bist (Mensch oder KI):** dieses Dokument soll dir in 5 Minuten den vollen Kontext geben. Lies es vor allem anderen. --- ## TL;DR - **Cards** ist die föderierte Spaced-Repetition-App des Vereins **mana e.V.** Strategie-B-Greenfield (beschlossen 2026-05-08): kein Code-Übernahme aus dem alten `mana-monorepo`, sauber neu gebaut — mit einer dokumentierten Ausnahme für den Anki-Format-Parser (Phase 8c, standalone Parser-Logik). - **30+ saubere Commits** auf `main`. Type-check 4/4 grün, **129 Tests grün** (66 Domain + 56 API + 7 Web), lokaler E2E-Smoke (Postgres → API → MinIO → Frontend → Cloze + Image-Occlusion + Anki-Import mit Media → /stats → /me/export → /cards/hashes) durch. - **🚀 LIVE seit 2026-05-08** auf `https://cardecky.mana.how` + `https://cardecky-api.mana.how` (Mac Mini, Cloudflare-Tunnel `1435166a-…`). Container `cards-{postgres,minio,api,web}`. Forgejo-Remote `git.mana.how/till/cards`. Public-E2E bestätigt: Deck + Card via API anlegbar, Manifest exposed, `cards.*`/`cards-api.*` redirecten via nginx-301 zu cardecky.*. - **Phasen 0, 1, 3, 4, 5, 8 vollständig durch.** **Phase 9 Polish- Welle teilweise** (Card-Edit, Cloze-Editor, Inbox-Banner, Account- /DSGVO-Self-Service, Statistik-Dashboard) — i18n + Image-Occlusion + Hint-Anzeige bei Cloze stehen noch offen. Phase 2 (Auth- Föderation) ist auf user-side Pre-Flight blockiert. - **Pre-Flight teilweise abgeräumt (Sprint 8d):** Verdaccio-Token produktiv via npm.mana.how, lokaler Protocol-Mirror durch Re-Exports aus `@mana/shared-share-protocol` ersetzt, Spec-Drift `mana/url` → `mana/link` gefixt. Verbleibend Pre-Flight: DNS, GitHub-Repo, mana-auth-App-Reg, mana-share-Manifest-Reg. - Cards läuft lokal, ist im Browser benutzbar, hat alle Föderations- Endpoints aus dem `app-manifest.json` implementiert. Anki-Decks können importiert werden (Cloze first-class), Karten manuell editiert, Statistiken angeschaut, Daten via DSGVO-Self-Service exportiert/gelöscht. ``` ┌─────────────────────────────────┐ │ cards/ (this repo) │ │ │ │ apps/web/ SvelteKit + Svelte 5 ← cardecky.mana.how │ apps/api/ Hono + Bun + Drizzle ← Postgres `cards` │ packages/cards-domain/ Pure-TS ← FSRS, Schemas, Protocol-Mirror │ app-manifest.json Föderations-Vertrag └─────────────────────────────────┘ ▲ │ HTTP, JWT, Manifest ▼ ┌─────────────────────────────────┐ │ mana/ Plattform │ │ mana-auth, mana-share, │ │ mana-links, mana-mcp, │ │ mana-search, mana-credits, … │ └─────────────────────────────────┘ ``` --- ## Architektur-Entscheidungen (festgenagelt) Diese stehen — nicht ohne explizite Diskussion antasten: 1. **Strategie B (Greenfield).** Kein Code aus mana-monorepo. 2. **Server-authoritative MVP.** Keine Dexie, keine eigene Sync-Engine. Local-First später via mana-sync-Federation, nicht durch eigenen Stack. 3. **Eigene Postgres-DB `cards`** mit Schema-Isolation `pgSchema('cards')`. 4. **Föderations-Endpoints als Pflicht** — alle aus `app-manifest.json` implementiert (siehe Phase 5 unten). 5. **Encryption initial AUS.** Nachrüstbar via mana-auth-MK. 6. **MVP-Card-Types `basic` + `basic-reverse` + `cloze` + `image-occlusion`** (Cloze Phase 8, Image-Occlusion Phase 9l). Schema vorbereitet auf type-in, audio, multiple-choice. Vollständiger Plan: [`mana/docs/playbooks/CARDS_GREENFIELD.md`](../mana/docs/playbooks/CARDS_GREENFIELD.md) (im Plattform-Repo, weil er Verein-übergreifend gilt). --- ## Phasen-Status | # | Phase | Status | Verifikation | |---|---|---|---| | 0 | Read-Day mana-monorepo-Cards-Code lesen | ✅ | `docs/LESSONS_FROM_MANA_MONOREPO.md` | | 1 | Repo-Skelett (Turbo, pnpm, Bun, Docker, CI) | ✅ | `pnpm install` durch, 136 packages | | 2 | Auth-Föderation (mana-auth Registrierung, JWT-Verify) | ✅ live 2026-05-08 | App in mana-auth registriert, JWT-Verify additiv mit Dev-Stub-Fallback, E2E gegen `tills95@gmail.com` verifiziert | | 3 | Domain-Modell + Drizzle + CRUD-API | ✅ | 8 Tabellen, FSRS via ts-fsrs, 46 Tests grün, E2E-Smoke durch | | 4 | Frontend-Core (SvelteKit, Tailwind 4, Markdown-Editor, Study-View) | ✅ | type-check + build grün, manuell testbar im Browser | | 5 | Föderations-Endpunkte (share, tools, search, dsgvo) | ✅ | 70 Tests grün, E2E-Smoke (Quote→Inbox→Search→DSGVO-Roundtrip) | | 6 | Subscriptions/Credits via mana-credits | 🟡 plumbing | Tier-Awareness im JWT-Claim, requireTier-Helper, credits-client. Nicht produktiv aktiv (Cards-MVP ist tier-frei) | | 7 | AI/MCP-Integration | 🟡 cards-side ready | cards.create + cards.search via tools-Pfad konvergent zu REST, Manifest deklariert tools, mana-mcp + mana-share auf Mac Mini noch nicht deployed | | 8 | Anki-Import (.apkg-Parser, Cloze-Support) | ✅ | 92 Tests grün, /import-Route benutzbar, Cloze als 3. MVP-Card-Type | | 9 | Polish (DSGVO-UI, Settings, Account, Statistik, i18n, A11y, Media, Image-Occlusion) | 🟡 weit | Card-Edit + Cloze-Editor + Inbox-Banner + Account/DSGVO + Statistik + Pre-Flight-Swap + i18n DE/EN + A11y-Pass + Cloze-Hint-Anzeige + Anki-Re-Import-Dedupe + MinIO-Media-Upload + Image-Occlusion durch (9a–9l). Verbleibend: type-in, audio, multiple-choice (Schema vorbereitet) | | 10 | Production-Deploy (Mac Mini, Cloudflare-Tunnel) | ✅ live 2026-05-08 | cardecky.mana.how + cardecky-api.mana.how, alte cards.* via nginx-301-Redirect | | 11 | Decommission Cards-Modul aus mana-monorepo | ✅ 2026-05-08 | apps/cards, services/cards-server, packages/cards-core, mana-app cards-Modul + cross-refs entfernt (4 Commits, type-check 0 errors) | Legende: ✅ erledigt + verifiziert · 🚧 blockiert · ⏸ noch nicht begonnen --- ## Was läuft ### Lokal voll einsatzbereit ```bash cd /Users/till/Documents/Code/cards # 1. Dependencies (idempotent) NPM_AUTH_TOKEN= pnpm install # 2. Postgres + MinIO-Container (Postgres :5435, MinIO :9100/:9101 — # kollidiert nicht mit Plattform-:5432/:9000/:9001) pnpm docker:up # 3. Drizzle-Schema pushen cd apps/api DATABASE_URL='postgresql://cards:cards@localhost:5435/cards' \ pnpm exec drizzle-kit push --force # 4. API starten (auf :3081) DATABASE_URL='postgresql://cards:cards@localhost:5435/cards' \ CARDS_API_PORT=3081 \ CARDS_DSGVO_SERVICE_KEY='msk_test_dsgvo_42' \ bun run src/index.ts & # 5. Web starten (auf :3082) cd ../web && pnpm dev & # 6. Browser öffnen open http://localhost:3082 ``` Login mit beliebigem User-ID-String (Dev-Stub speichert via `sessionStorage`). Für Föderations-Endpunkte (share/receive) muss die User-ID UUID-formatiert sein, z.B. `00000000-0000-0000-0000-00000000aaaa`. Aufräumen: `kill %1 %2 && pnpm docker:down` (Daten in `infrastructure/.volumes/cards-postgres`). Vollständiger Smoke-Test-Runbook: [`docs/SMOKE_TEST.md`](docs/SMOKE_TEST.md). ### Verifizierte Endpoints ``` GET /healthz → {"status":"ok"} GET /version → {"app":"cards","version":"…","build":"…"} GET /.well-known/mana-app.json → Manifest POST /api/v1/decks User-JWT CRUD GET /api/v1/decks User-JWT GET /api/v1/decks/:id User-JWT PATCH/DELETE /api/v1/decks/:id User-JWT POST /api/v1/cards User-JWT Create + Auto-Reviews GET /api/v1/cards?deck_id=… User-JWT GET/PATCH/DELETE /api/v1/cards/:id User-JWT GET /api/v1/reviews/due User-JWT Hot-Path POST /api/v1/reviews/:cardId/:subIndex/grade User-JWT FSRS-Transition POST /api/v1/share/receive User-JWT Föderations-Inbox POST /api/v1/tools/:name User-JWT cards.create | cards.search GET /api/v1/search?q=… User-JWT SearchResultEnvelope GET /api/v1/dsgvo/export?user_id=… Service-Key POST /api/v1/dsgvo/delete Service-Key ``` --- ## Pre-Flight für Phase 2 + Live-Föderation Diese Items sind **nicht autonom machbar** — du oder ein Mensch musst sie freischalten: | Item | Wer | Status | |---|---|---| | DNS für `cardecky.mana.how` reservieren (Cloudflare) | Mensch | offen | | GitHub-Repo `mana-ev/cards` anlegen + Remote pushen | Mensch | offen | | Cards in `mana-auth.apps` registrieren (Service-Key + Public-Key) | Mensch oder KI gegen laufende mana-auth | offen | | `NPM_AUTH_TOKEN` für Verdaccio in `~/.npmrc` setzen | Mensch | offen | | Cards-Manifest bei mana-share registrieren | KI gegen laufende mana-share | offen | Sobald `NPM_AUTH_TOKEN` da ist, kann der lokale Protocol-Mirror in `packages/cards-domain/src/protocol/` durch Re-Exports aus `@mana/shared-share-protocol` ersetzt werden — das ist eine 1-Liner- Änderung in `cards-domain/src/index.ts` plus Imports. --- ## Wichtige Pointer ### Konventionen + Stack - pnpm 9.15.x, Node 20+, Bun für apps/api - Tabs-Indent, single-quotes, 100-col Prettier (`.prettierrc.json`) - SvelteKit 2 + Svelte 5 (**runes-only** — kein legacy `let count = 0`) - Hono + Bun + Drizzle für API - Drizzle 0.38 / drizzle-kit 0.30 / zod 3 (gleicher Stand wie Mana-Plattform) - Tailwind 4 via `@tailwindcss/vite` (oklch-Theme + Dark-Mode-Auto) - Tests: Vitest + Hono `app.request()`, später Playwright für e2e Volle Konventionen: [`CLAUDE.md`](CLAUDE.md) ### Wichtige Dateien | Pfad | Zweck | |---|---| | [`STATUS.md`](STATUS.md) | dieses Dokument — Single Source of Truth für Status | | [`CLAUDE.md`](CLAUDE.md) | Konventionen + Architektur-Invarianten + Stack-Decisions | | [`README.md`](README.md) | Kurz-Anleitung, ein paar Befehle | | [`docs/SMOKE_TEST.md`](docs/SMOKE_TEST.md) | Reproduzierbarer E2E-Lauf (curl-Sequenz) | | [`docs/LESSONS_FROM_MANA_MONOREPO.md`](docs/LESSONS_FROM_MANA_MONOREPO.md) | 15 Architektur-Lessons aus dem Read-Day, 5 Kern-Entscheidungen | | [`app-manifest.json`](app-manifest.json) | Source of Truth für Föderations-Vertrag (v1.0.0, beta-tier) | | [`packages/cards-domain/src/`](packages/cards-domain/src/) | zod-Schemas SSOT + FSRS-Adapter + Protocol-Mirror | | [`apps/api/src/`](apps/api/src/) | Hono-Routen, Drizzle-Schemas, Share-Handlers | | [`apps/web/src/`](apps/web/src/) | SvelteKit-Routes, $lib/api, $lib/auth-Stub | | [`infrastructure/docker-compose.yml`](infrastructure/docker-compose.yml) | Postgres-Container für lokal-dev | ### Cross-Repo-Dokumente (im Plattform-Repo `mana/`) | Pfad | Zweck | |---|---| | `mana/docs/playbooks/CARDS_GREENFIELD.md` | Master-Playbook (alle Phasen, Pre-Flight, Decommission) | | `mana/docs/FEDERATION.md` | Föderations-Architektur-Grundlagen | | `mana/docs/SHARE_PROTOCOL.md` | Manifest- + Envelope-Schema-Spezifikation | | `mana/docs/MANA_AUTH_FEDERATION.md` | App-Identitäts-Modell (Service-Keys, JWKS) | | `mana/docs/SHARED_PACKAGES.md` | Versions-Disziplin Klasse A/B/C | | `mana/docs/PORTS.md` | Port-Allokation (cards-api: **3081**, cards-web: **3082**) | | `mana/docs/PLAN.md` | Übergreifende mana-e.V.-Roadmap inkl. Phase 6 (Cards-Greenfield) | --- ## Git-Historie ``` 39b1791 Phase 9l: Image-Occlusion als 4. MVP-CardType c9eb0a6 Phase 9k: Media-Upload via MinIO-Container e7ae93d docs: STATUS.md auf Phase-9-Welle-2-Stand 593d447 Phase 9j: Anki-Re-Import-Dedupe via content_hash 4b451f1 Phase 9i: Cloze-Hint-Anzeige fd86d96 Phase 9h: A11y-Pass c25c1d0 Phase 9g: i18n DE/EN über alle Routes a640594 docs: STATUS.md auf Phase-9-Polish-Stand 6db6dc3 Phase 9f: Statistik-Dashboard 03117d5 Phase 9e: Account-Page mit DSGVO-Self-Service aff4d95 Phase 9d: Pre-Flight — Protocol-Mirror durch upstream ersetzt 47419b3 Phase 9c: Inbox-Banner auf /decks und /study 35366ed Phase 9b: Cloze-Editor in /cards/new 0a40367 Phase 9a: Card-Edit-Page für alle 3 CardTypes 9da10b3 Phase 8d: STATUS.md auf Phase-8-Stand aktualisiert 2ca09fe Phase 8c: Anki-Import via portiertem Parser 0b609c4 Phase 8b: Cloze-Render im Study-View 553a78d Phase 8a: Cloze als MVP-Card-Type, Cluster-Counter 2bed282 docs: STATUS.md als Single Source of Truth für Cards-Onboarding 0328caa Phase 5: Föderations-Endpunkte — Cards ist föderierter Peer 89a7a92 Phase 4: Frontend-Core MVP — Decks, Cards, Study mit FSRS-Loop e3b3a2b docs: SMOKE_TEST.md — verifizierter E2E-Lauf gegen lokale Postgres 5f67bd9 Phase 3 follow-up: type-check + tests grün, ts-fsrs v5 API 45a47e0 Phase 3: Domain-Modell + Decks/Cards/Reviews-CRUD 8605b1b Phase 0+1: Repo-Skelett für Cards-Greenfield ``` `git remote -v` ist leer — Repo lebt lokal, GitHub-Remote folgt mit Pre-Flight (`mana-ev/cards`). --- ## Architektur-Subtilitäten, die nicht offensichtlich sind ### 1. Reviews bleiben PLAINTEXT Der FSRS-Scheduler quert täglich `due <= now`. Wenn die Reviews verschlüsselt wären, müsste man jeden Tag N Reviews entschlüsseln nur um zu wissen welche fällig sind. Geht nicht. → Wenn Encryption nachgerüstet wird: nur `cards.fields` (front/back) und `decks.{name,description}` werden encrypted, Reviews bleiben plaintext. Pattern aus mana-monorepo bestätigt (`crypto/registry.ts` hat `cardReviews` plaintext-allowlisted). ### 2. SubIndex-Granularität pro Card-Type Eine `basic-reverse`-Karte hat **2** Reviews (sub_index 0 = front→back, sub_index 1 = back→front). Cloze hat 1 Review pro Cluster-Index. Beim Card-Insert werden alle initialen Reviews in **einer Transaktion** mit angelegt — siehe `apps/api/src/routes/cards.ts` POST-Handler. `subIndexCount(type)` in `@cards/domain` ist die SoT für statische Typen. Für Cloze siehe Subtilität #6 — `subIndexCountForCloze(text)` ist die SoT, weil die Anzahl text-abhängig ist. ### 3. Protocol-Mirror auf upstream umgestellt (Sprint 8d, 2026-05-08) `packages/cards-domain/src/protocol/` war ursprünglich ein lokaler Mirror, ist seit Sprint 8d ein dünner Re-Export von `@mana/shared-share-protocol@0.1.0` aus Verdaccio (npm.mana.how). Die gemeinsamen Schemas (Envelope, Search, Quote/Link/Text-Payloads) kommen direkt aus dem Föderations-Vertrag, nur die Cards-spezifische Akzeptanz-Map (`PAYLOAD_SCHEMAS`, `validatePayloadForType`) bleibt lokal. Drift-Risiko ist damit beseitigt — `pnpm update` zieht automatisch nach. **Repo-`.npmrc` zeigt auf `npm.mana.how`** (nicht `pkg.mana.how` wie zuvor — der Tunnel wurde am 2026-05-07 zurückgerollt). NPM_AUTH_TOKEN muss als env-var oder im Shell-Profile vor `pnpm install` gesetzt sein. ### 3-historisch. Lokales Protocol-Mirror (vor Sprint 8d) `packages/cards-domain/src/protocol/` enthielt eine **TEMPORARY**- Kopie der Schemas aus `@mana/shared-share-protocol`. Solange Verdaccio nicht offen ist (kein `NPM_AUTH_TOKEN`), halten wir sie hier lokal. → Drift-Risiko: bei jedem Update der mana-Spec MUSS diese Datei nachgezogen werden, bis der Swap erfolgt. Marker-Kommentar oben in jeder Mirror-Datei. ### 4. Inbox-Deck wird auto-erstellt Eingehende Shares (über `/share/receive`) landen alle in einem auto-erstellten "Inbox"-Deck pro User. `ensureInboxDeck(db, userId)` prüft auf Existenz oder legt es neu an. User kann Karten später in echte Decks umsortieren. → Naming-Hinweis: Wenn ein User schon ein Deck namens "Inbox" hat, greift unser `ensureInboxDeck` darauf zu. Das ist gewollt (idempotent). ### 5. Dev-Auth via X-User-Id ist EXPLICIT temporär `apps/api/src/middleware/auth.ts` und `apps/web/src/lib/auth/dev-stub.svelte.ts` sind beide klar als „Phase 2 ersetzt durch echtes JWT" markiert. Beim Swap auf mana-auth: - API: `@mana/shared-hono` `authMiddleware()` mit JWKS-Cache - Web: `@mana/shared-auth`-Login-Flow gegen `auth.mana.how` - Beide aus Verdaccio (= NPM_AUTH_TOKEN-blockiert) ### 6. Cloze-Karten haben N Reviews — sub_index pro Cluster `subIndexCount('cloze')` wirft bewusst, weil die Anzahl text-abhängig ist. Caller müssen `subIndexCountForCloze(text)` aus `@cards/domain` nutzen. Cluster werden nach numerischer ID aufsteigend sortiert (`{{c1::…}}` = sub_index 0, `{{c2::…}}` = 1, …). Der Card-POST-Handler lehnt `type=cloze` ohne mindestens ein Cluster mit 422 ab — eine Cloze ohne `{{cN::…}}`-Markup ist sinnlos. Render-Helpers (`renderClozePrompt` / `renderClozeAnswer`) leben in `@cards/domain/src/cloze.ts`, sind 12-fach unit-getestet und werden vom Study-View dünn konsumiert. Hint-Markup (`{{c1::answer::hint}}`) wird MVP-stumm gedroppt — Hint-Anzeige ist Phase-9-Polish. ### 7. Anki-Parser ist eine bewusste Strategie-B-Ausnahme `apps/web/src/lib/anki/parse.ts` und `lib/components/AnkiImport.svelte` sind aus mana-monorepo portiert. Kennzeichnung im Header-Kommentar. Begründung: Anki-Format-Logik ist standalone Parser-Code (jszip + sql.js), kein Architektur-Schmuggel — die Kopie spart 2-3 Tage Re-Implementierung bei null Strategy-Risiko. `import.ts` wurde NICHT portiert: das Original schreibt gegen Dexie- Stores und bricht damit Architektur-Invariante #1 (server-authoritative MVP). Die neue Version ist von Hand geschrieben und nutzt direkt `$lib/api/{decks,cards}` über HTTP. ### 8. Media-Refs werden beim Anki-Import gedroppt (Phase 8 MVP) `sanitizeAnkiHtml` strippt `` und `[sound:…]`-Markup ersatzlos. Späterer Media-Pfad ist additiv — entweder ein lokaler `POST /api/v1/media/upload` in cards-api oder gegen Plattform-`mana-media` nach Phase 2. Die Filename→ZIP-Map liegt im `ParsedAnki.mediaByFilename` weiterhin bereit, sie wird aktuell nur für die Preview-Anzeige ("X Medien werden nicht übernommen") genutzt. ### 9. sql-wasm.wasm liegt unter apps/web/static/ 660kB Build-Asset. Wird vom Browser einmal geladen (initSqlJs cache in parse.ts). Bei Update von `sql.js` muss die Datei neu kopiert werden: `cp apps/web/node_modules/sql.js/dist/sql-wasm.wasm apps/web/static/sql-wasm.wasm`. ### 11. MinIO-Media-Storage (Sprint 9k) `cards-minio`-Container im `infrastructure/docker-compose.yml` auf 9100/9101 (Plattform-MinIO ist 9000/9001 — wir bleiben isoliert). `apps/api/src/services/storage.ts` ist ein dünner Wrapper um den `minio`-Client; `ensureBucket()` ist idempotent. ObjectKey-Format `/.` ermöglicht Bucket-Prefix-Sweep beim DSGVO-Delete (kein S3-Cascade). Konfiguration via `CARDS_S3_*`-env-Vars; Default lokaler Container. Phase-10-Prod kann gegen denselben Container auf dem Mac Mini laufen (eigener Bucket) oder gegen Plattform-MinIO. Keine Code-Änderung, nur env. ### 12. Image-Occlusion (Sprint 9l) Field-Schema: `image_ref` zeigt auf eine `media_files.id` (Sprint 9k Storage), `mask_regions` ist ein JSON-Array mit Schema: `{ id, x, y, w, h, label? }`, alle Coords 0..1 relativ. `subIndexCount('image-occlusion')` wirft analog zu cloze; Card-POST nutzt `maskRegionCount(mask_regions)`. Editor (`ImageOcclusionEditor.svelte`): SVG-Overlay über ``, Drag-to-create für Masken, Mindestgröße 2% damit Klicks gefiltert werden. Touch-tauglich via Pointer-Events. Mask-Liste mit Inline- Label-Edit + Delete. Study-View (`ImageOcclusionView.svelte`): aktive Maske ist im Prompt opake schwarz, im Reveal transparent grün mit Label-Text-Overlay (SVG-Text mit stroke-Outline gegen Bild-Hintergründe). Andere Masken bleiben dezent gelb-durchsichtig als Lern-Hinweis. ### 10. content_hash auf cards (Sprint 9j) Jede neue Karte bekommt einen SHA-256-`content_hash` über `{type, sorted-fields}` — geschrieben automatisch im Card-POST, genutzt vom Anki-Re-Import-Dedupe (`/api/v1/cards/hashes` lädt nur die Hash-Liste, der Importer dedupliziert clientseitig). `cardContentHash()` in `@cards/domain` ist deterministisch und field-order-invariant. Cluster-Markup, Whitespace und Hint- Annotationen zählen mit — bewusst, weil zwei Cards mit dem Text `Paris ist Hauptstadt` und `{{c1::Paris}} ist Hauptstadt` sind inhaltlich verschieden. **Backfill-Lücke:** Pre-Sprint-9j-Karten haben `content_hash = NULL`. Der `/hashes`-Endpoint filtert sie weg, also können sie irrtümlich beim Re-Import erneut entstehen. Backfill-Skript ist Phase-10-Polish. ### 11. Cards-Modul in mana-monorepo wird nach Live-Gang **gelöscht** Strategie-B-Konsequenz: nach `cardecky.mana.how` live + 2 Wochen Test folgt ein Decommission-PR in mana-monorepo, der `apps/mana/.../modules/cards/`, `packages/cards-core/`, `services/cards-server/` (Marketplace-Backend) und alle DB-Schemas in `mana_platform.cards.*` entfernt. Keine zwei Cards-Welten parallel. → Diese Entscheidung ist im Greenfield-Playbook festgehalten und im älteren `CARDS_CUTOVER.md` (jetzt überholt) als Strategie-A-Variante diskutiert worden. --- ## Wenn du gerade neu bist — Onboarding-Sequenz 1. **Lies dieses Dokument zu Ende** (5 Min). 2. **Lies `CLAUDE.md`** (Konventionen + Stack-Decisions, 3 Min). 3. **Lies `mana/docs/playbooks/CARDS_GREENFIELD.md`** (Master-Plan, 10 Min). 4. **Optional:** `docs/LESSONS_FROM_MANA_MONOREPO.md` für Domain-Verständnis. 5. **Verifiziere lokal:** `docs/SMOKE_TEST.md` durchspielen — wenn alle 7 Schritte grün, ist die Umgebung in Ordnung. 6. **Memory-Check (KI):** falls du auto-memory hast, prüfe `memory/project_phasenstand.md` für eventuell neueren Stand. --- ## Was als Nächstes ansteht (Vorschläge) In Reihenfolge meiner Empfehlung: 1. **Pre-Flight Restklemmen abräumen** — DNS, GitHub-Repo `mana-ev/cards`, mana-auth-App-Reg (Service-Key + Public-Key), mana-share-Manifest-Reg. Hängt an User-Aktion + laufender Plattform. 2. **Phase 6 (Subscriptions)** — braucht laufende mana-credits + Phase 2 Auth-Föderation. 3. **Phase 7 (AI/MCP)** — braucht laufende mana-mcp. 4. **Phase 10 (Production-Deploy)** — Mac Mini + Cloudflare-Tunnel (cardecky.mana.how + cards-api.mana.how) + MinIO-Bucket (eigener Container oder Plattform), nach allen Pre-Flight-Items. 5. **content_hash-Backfill** — Pre-Phase-9j-Karten haben null content_hash; ein einmaliges Skript würde sie nachziehen, sodass Re-Import-Dedupe lückenlos funktioniert. Phase 10-Polish, sobald Live-User da sind. 6. **Weitere CardTypes** — type-in, audio, multiple-choice sind im Future-Schema vorbereitet, kommen wenn der User-Wunsch klar ist. 7. **Image-Occlusion-Polish** — Resize/Move existierender Masken (aktuell: nur Draw + Delete), Mask-Reorder, Mehrere Masken in einem Cluster (mehrere als ein Review). Was nicht autonom geht: Phase 2, 6, 7, 10 — alle hängen an Pre-Flight oder Plattform-Diensten. Phase 9 ist sehr breit ausgebaut. --- **Wenn du dieses Dokument liest und etwas hier nicht stimmt, ist das Dokument schuld, nicht der Code. Update es.**