docs: STATUS.md als Single Source of Truth für Cards-Onboarding
Bisherige Doku war über CLAUDE.md, README.md, SMOKE_TEST.md, LESSONS_FROM_MANA_MONOREPO.md plus mana/docs/playbooks/CARDS_GREENFIELD.md zerstreut — eine fresh-AI-Session musste sich Status zusammenstückeln. STATUS.md zentralisiert: - TL;DR + Architektur-Topologie - Architektur-Entscheidungen (festgenagelt) - Phasen-Status-Tabelle (✅/🚧/⏸ pro Phase mit Verifikations-Hinweis) - Lokal-Lauf-Anleitung (5 Schritte zu cards-api + cards-web im Browser) - Verifizierte Endpoints-Liste - Pre-Flight für Phase 2 + Live-Föderation - Wichtige Pointer: Konventionen, Stack, Files, Cross-Repo-Doks - Git-Historie (6 Commits) - 6 Architektur-Subtilitäten, die nicht offensichtlich sind: Reviews-plaintext, SubIndex-Granularität, Protocol-Mirror-TEMPORARY, Inbox-Auto-Create, Dev-Auth-temporär, mana-monorepo-Decommission - Onboarding-Sequenz (5-Min-Lese-Plan) - Vorschläge für nächste Phasen Cross-References: - CLAUDE.md verweist als erstes auf STATUS.md - README.md ebenso - mana/docs/playbooks/CARDS_GREENFIELD.md (im Plattform-Repo) verweist zurück auf cards/STATUS.md für aktuellen Stand — Playbook ist der Plan, STATUS.md ist die Lage. Konvention: bei Phasen-Wechsel STATUS.md aktualisieren, nicht den Playbook (sonst Doku-Drift). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0328caa333
commit
2bed28212d
3 changed files with 336 additions and 0 deletions
|
|
@ -2,6 +2,12 @@
|
|||
|
||||
Guidance for Claude Code when working in this repository.
|
||||
|
||||
> **Wenn du gerade neu bist:** lies zuerst [`STATUS.md`](STATUS.md) — dort
|
||||
> steht der aktuelle Phasen-Stand, was schon läuft, was offen ist, und
|
||||
> wie du lokal verifizierst. Dieses CLAUDE.md ist nur die Konventions-
|
||||
> und Architektur-Referenz; der Status lebt in STATUS.md, damit er nicht
|
||||
> zwischen mehreren Dateien drifted.
|
||||
|
||||
## Was dieses Repo ist
|
||||
|
||||
**Cards** — eigenständige föderierte Spaced-Repetition-App des
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ Notizen aus Mana, Web-Schnipsel aus dem Browser-Plugin).
|
|||
|
||||
→ Live (geplant): <https://cardecky.mana.how>
|
||||
|
||||
**Aktueller Stand und Pickup-Onboarding: [`STATUS.md`](STATUS.md).**
|
||||
|
||||
## Stack
|
||||
|
||||
- **Frontend:** SvelteKit 2 + Svelte 5 (runes-only)
|
||||
|
|
|
|||
328
STATUS.md
Normal file
328
STATUS.md
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
# Cards — Projekt-Status & Onboarding
|
||||
|
||||
**Letztes Update:** 2026-05-08
|
||||
**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.
|
||||
- **6 saubere Commits** auf `main`. Type-check 4/4 grün, **70 Tests
|
||||
grün**, lokaler E2E-Smoke-Test (Postgres → API → Frontend → Föderations-
|
||||
Endpunkte) durch.
|
||||
- **Phasen 0, 1, 3, 4, 5 sind durch** und verifiziert. Phase 2 (Auth-
|
||||
Föderation) ist auf user-side Pre-Flight blockiert.
|
||||
- Cards läuft lokal, ist im Browser benutzbar, hat alle Föderations-
|
||||
Endpoints aus dem `app-manifest.json` implementiert.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ 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 nur `basic` + `basic-reverse`.** Schema vorbereitet
|
||||
auf full-set (cloze, type-in, image-occlusion, 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) | 🚧 blockiert | siehe „Pre-Flight" unten |
|
||||
| 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 | ⏸ offen | autonom möglich |
|
||||
| 7 | AI/MCP-Integration | ⏸ offen | braucht laufende mana-mcp |
|
||||
| 8 | Anki-Import (.apkg-Parser + mana-media-Upload) | ⏸ offen | autonom möglich, ~5–7 Tage |
|
||||
| 9 | Polish (DSGVO-UI, Settings, Account, Statistik, i18n, A11y) | ⏸ offen | breite Polish-Phase |
|
||||
| 10 | Production-Deploy (Mac Mini, Cloudflare-Tunnel) | ⏸ offen | braucht DNS + Tunnel-Config |
|
||||
| 11 | Decommission Cards-Modul aus mana-monorepo | ⏸ offen | erst nach Phase 10 |
|
||||
|
||||
Legende: ✅ erledigt + verifiziert · 🚧 blockiert · ⏸ noch nicht begonnen
|
||||
|
||||
---
|
||||
|
||||
## Was läuft
|
||||
|
||||
### Lokal voll einsatzbereit
|
||||
|
||||
```bash
|
||||
cd /Users/till/Documents/Code/cards
|
||||
|
||||
# 1. Dependencies (idempotent)
|
||||
pnpm install
|
||||
|
||||
# 2. Postgres-Container (auf :5435, kollidiert nicht mit Mana-Plattform-:5432)
|
||||
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
|
||||
|
||||
```
|
||||
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 Single Source of Truth.
|
||||
|
||||
### 3. Lokales Protocol-Mirror
|
||||
|
||||
`packages/cards-domain/src/protocol/` enthält 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. 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. **Phase 8 (Anki-Import)** — autonom, klar abgegrenzte Funktionalität,
|
||||
~5–7 Tage. Brauchbar als Migrations-Hilfe für künftige User.
|
||||
2. **Card-Edit-Page + Inbox-Banner im Frontend** — 1–2 Tage Polish.
|
||||
3. **Pre-Flight aktiv abräumen** — Mana-Plattform-Stack + mana-auth
|
||||
live, dann Cards als App registrieren (Phase 2).
|
||||
4. **Phase 6 (Subscriptions)** — braucht laufende mana-credits.
|
||||
5. **Phase 9 (Polish)** — Settings, Account, DSGVO-UI, Statistik, i18n.
|
||||
|
||||
Was nicht autonom geht: Phase 2 (Auth-Föderation), Phase 7 (mana-mcp-
|
||||
Live), Phase 10 (Mac-Mini-Deploy) — alle hängen an Pre-Flight-Items.
|
||||
|
||||
---
|
||||
|
||||
**Wenn du dieses Dokument liest und etwas hier nicht stimmt, ist das
|
||||
Dokument schuld, nicht der Code. Update es.**
|
||||
Loading…
Add table
Add a link
Reference in a new issue