- Migration: partiell WHERE IS NOT NULL, dedup vorher, kein silent-catch
- Route: INSERT mit .catch(23505) → UPDATE statt ON CONFLICT (partial index inkompatibel)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- pictures: reviewed-Status (Constraint + ALLOWED_STATUSES + Auto-Trigger beim Object-Linking)
- objects: STATUSES um reviewed erweitert; Auto-Trigger draft→reviewed wenn Pair verlinkt
- pairs/statements/questions: STATUSES um reviewed (Phase-1-Lücke)
- pairs: POST /:id/review kaskadiert Pair+Frage+Statements (verlangt alle 3 Sprachen)
- words: Auto requested→translated wenn alle titel_* gefüllt (POST+PATCH)
- audios computeUnits: nur vertonbar wenn ALLE 3 Sprachen pro Feld gefüllt
- claude: translate-text/translate-row/translate-missing mit Placeholder-Schutz
(⟦PHn:label⟧-Tokenisierung, Label übersetzt, UUID erhalten); translation-coverage
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- reviewed-Status für objects/questions/statements/pairs (Constraints)
- feed: nur fertige Inhalte (published + Bild + Audio-Gate), audio_url
- pairs: Publish-Gating (draft→published = 409)
- audios: source_table/source_id/source_field/language + Unique-Index;
generate-for, generate-batch, GET /coverage; voices.js (Voice je Sprache)
- auth: POST /auth/progress, /auth/me mit total_ep/streak/level;
users_public EP-Spalten + user_pair_progress.earned_points
- claude: POST /generate-words; words POST akzeptiert status
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- pictures.js: move GET/POST/DELETE /:id/words/* BEFORE GET /:id
so /:id/words is not shadowed; add POST /:id/words/:wordId
- words.js: move GET /:id after sub-routes; add GET /:id/pictures
and GET /:id/categories
- objects.js: move GET /:id after sub-routes (/:id/words, /:id/pairs,
/:id/pictures); add GET /:id/pictures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- GET /api/objects?picture_id=X filter via object_pictures join
- GET /api/objects/:id/words — full word details
- GET /api/objects/:id/pairs — pairs with nested question + statements
- GET /api/words?titel_de=X case-insensitive filter
- GET /api/pictures/:id/words — full word details
- DELETE /api/pictures/:id/words/:wordId — convenience unlink
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix broken rename migration array (sed had corrupted from values to _sv)
- Add languages table with status lifecycle and trilingual titles
- Add user_names table with unique lowercase index
- Add users_public table linking to user_names and languages (native/target)
- Wire all three new routes under /api/languages, /api/user-names, /api/users-public
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- words table with trilingual titles, status enum, difficulty level, timestamps
- word_pictures junction table (M2M words <-> pictures)
- categories placeholder table
- word_categories junction table (M2M words <-> categories)
- Auto-timestamps on status change (requested/published/blocked)
- Full CRUD + link/unlink endpoints for pictures and categories
- README updated with schema and endpoints
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>