shinkan-jinkendo/backend/version.py
Lars f36a747efa
All checks were successful
Deploy Development / deploy (push) Successful in 45s
Test Suite / pytest-backend (push) Successful in 43s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m16s
Enhance Progression Path Suggestion with Stage Specification Refinement
- Introduced `auto_refine_stage_spec` to `ProgressionPathSuggestRequest`, enabling optional refinement of stage specifications during the rematch process.
- Updated `_run_roadmap_rematch_loop` to incorporate stage specification refinements, logging changes for better tracking of adjustments made during rematching.
- Enhanced `suggest_progression_path` to include refine logs in the output, providing clearer insights into the refinement process.
- Added utility functions for formatting refine log entries, improving the display of refinement actions in the frontend components.
- Updated frontend components to display refine logs, enhancing user feedback on stage specification adjustments during progression analysis.
- Bumped version to 0.8.227 to reflect the new features and improvements.
2026-06-11 21:43:45 +02:00

1950 lines
94 KiB
Python
Raw 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.

# Shinkan Jinkendo Version Information
APP_VERSION = "0.8.227"
BUILD_DATE = "2026-05-22"
DB_SCHEMA_VERSION = "20260607090"
MODULE_VERSIONS = {
"legal_documents": "1.4.0", # Admin: Live-Vorschau pro Abschnitt + modale Vollvorschau (Editor + Dokumentenliste)
"auth": "1.2.3", # P-05b: reset-password min_length=8 via Pydantic PasswordResetConfirm
"profiles": "1.8.1", # GET /profiles/me: account_state + club_roles
"tenant_context": "1.1.0", # M3: account_state + email_verified im TenantContext
"capabilities": "1.2.0", # Registry-first: module-Spalte; Admin nur registrierte Rechte
"rights_registry": "1.0.0", # register_capability/feature + startup sync
"account_lifecycle": "1.1.0", # Phase A: account_onboarding_gate API-Middleware
"clubs": "0.4.2", # delete_club: Gründungsanträge → superseded
"club_memberships": "1.0.1", # Depends(get_tenant_context)
"club_join_requests": "1.0.1", # Depends(get_tenant_context)
"club_creation_requests": "1.0.1", # superseded wenn freigegebener Verein gelöscht
"admin_users": "1.0.0", # GET /api/admin/users
"club_features": "1.6.0",
"admin_rights": "1.1.0", # Matrix UX, Enforcement-Audit, clear club grants by capability
"capability_enforcement_audit": "1.0.0",
"club_quota_bypass": "1.0.0", # platform.club_quota.bypass* + Admin-Grants-API
"entitlements": "1.2.0", # capability_quota_bypass in Feature-Map für /me/entitlements
"platform_media_storage": "1.0.0", # GET/PUT /api/admin/platform-media-storage (Superadmin-Pfad unter MEDIA_ROOT)
"media_rights": "1.3.1", # acting_profile_id in write_audit_log_entry auf Optional[int] (P-13 anonyme Meldungen)
"media_assets": "1.18.1", # P-13: open_report_count in Listendaten (fuer Admins)
"media_legal_hold": "1.0.0", # P-11: Sofortsperre-Services (set_legal_hold, release_legal_hold)
"media_lifecycle": "1.1.0", # P-11: Retention-Job ueberspringt Legal-Hold-Assets
"admin_ai_skill_retrieval": "1.0.0", # Superadmin CRUD /api/admin/ai-skill-retrieval-profiles (Migration 068)
"exercise_enrichment_admin": "1.1.1", # Preview max 3/Request + parallel LLM (Gateway-504 vermeiden)
"admin_ai_prompts": "1.0.3", # Migration 070: openrouter_model; PUT/Liste/Detail
"ai_prompt_job": "0.2.1", # want_instructions; run_exercise_form_ai_suggestion
"ai_prompt_context": "0.2.0", # preparation/trainer_notes; has_instruction_source_text
"ai_prompt_runtime": "0.2.2", # Slug planning_exercise_expectation_profile
"groups": "0.1.0",
"skills": "0.1.1", # DB 065 karate_relevance + relevance_level; CRUD unterstützt Felder
"skill_profiles": "1.0.0", # Phase 3: gewichtetes Fähigkeiten-Profil + skill-discovery/suggestions
"methods": "0.1.0",
"exercises": "2.37.1", # KI-Endpoints: feature_usage nach ai_calls consume
"planning_exercise_suggest": "0.23.2", # Phase C: refine_stage_spec bei stage_mismatch vor Rematch
"training_units": "0.4.0", # POST .../publish-to-framework: Ablauf aus geplanter Einheit → Rahmen-Slot-Blueprint
"training_programs": "0.1.0",
"planning": "0.15.0", # Vorlagen: Strukturvorschau, Bearbeiten inkl. Split-Sessions + Beschreibung
"dashboard": "1.1.0", # GET /api/dashboard/kpis inkl. training_home (ein Client-Roundtrip für KPIs + nächste Termine)
"training_modules": "1.1.0", # PUT/DELETE: assert_library_content_* (Vereinsadmin löscht Vereins-Inhalt, Trainer bearbeitet club wie Übungen)
"import_wiki": "1.0.3", # Default-Kategorie Fähigkeiten: Fähigkeitsbeschreibung; cmtitle-Normalisierung; UI Preview/Execute Defaults je Typ
"admin": "1.0.0",
"membership": "1.0.0",
"catalogs": "1.5.0", # Updated: Trainer Contexts API (Migration 012)
"maturity_models": "1.4.0", # matrix_stack_bundle: vollständiger Katalog+Modelle+Bindings Export/Import
"content_reports": "1.5.1", # P-13: Fruehzeitige 403 fuer plain Admin in set_legal_hold_from_report (CI-Fix)
}
CHANGELOG = [
{
"version": "0.8.226",
"date": "2026-05-22",
"changes": [
"Progressionsgraph Phase B: Rematch-Schleife (max_rematch_rounds) mit optimization_hints und roadmap_unfilled.",
"Fix: Graph-Bewertung/Match 500 bei off-topic am Rand-Slot (collect_gap_fill_specs IndexError).",
],
},
{
"version": "0.8.225",
"date": "2026-06-07",
"changes": [
"Stufen start_state/target_state (Soll-Verkettung) + kontextualisiertes Matching.",
"Mehrstufige Pfad-QS (tier13) mit optimization_hints; Migration 090 Prompt.",
],
},
{
"version": "0.8.224",
"date": "2026-06-07",
"changes": [
"Technik-Pfad-Scope: Geschwister-Techniken (Mae/Yoko bei Mawashi) als hartes Gate in Match/QS.",
"path_primary_topic in build_stage_match_brief; Intent technique_sibling_excludes.",
],
},
{
"version": "0.8.223",
"date": "2026-06-07",
"changes": [
"planning_intent_context: gemeinsamer Intent für anti_patterns/success_criteria (Phase G-ready).",
"Migration 089: LLM-Prompts Zielanalyse + stage_spec mit Intent-Kontext; finalize nach Pipeline.",
],
},
{
"version": "0.8.222",
"date": "2026-06-07",
"changes": [
"Pfad-Ausschlüsse: athletic→Kumite-Heuristik entfernt — nur explizite Negationen und anti_patterns.",
],
},
{
"version": "0.8.221",
"date": "2026-06-07",
"changes": [
"Pfad-Ausschlüsse (keine Kumite etc.) aus Anfrage in Brief, stage_specs und Matching-Gates.",
"QS entfernt path_exclude-Schritte; partielles Strippen wenn die meisten Slots falsch sind.",
],
},
{
"version": "0.8.220",
"date": "2026-06-07",
"changes": [
"Roadmap-Stufen-Match: build_stage_match_brief + stage_semantic_score über Titel, Summary und Goal.",
"Retriever lädt Übungsziele immer bei Stufen-Match; Ranking nach Stufen-Fit statt Gesamtthema.",
],
},
{
"version": "0.8.219",
"date": "2026-06-07",
"changes": [
"Roadmap-Stufen-Gate: Negationen (ohne Tritttechnik) + Pflicht-Treffer Absprung/Beinhebung.",
"anti_patterns in Stufen-Match; Gesamt-Thema allein reicht bei strict_positive nicht mehr.",
],
},
{
"version": "0.8.218",
"date": "2026-06-07",
"changes": [
"Roadmap-Match: Stufen-Lernziel-Gate (semantic_brief_for_stage, stage_learning_goal).",
"Kein Fallback auf globale goal_query bei roadmap_first — Lücke statt falscher Übung.",
"Retrieval-Strafe/Bonus für Stufen-Passung; QS erkennt stage_mismatch.",
],
},
{
"version": "0.8.217",
"date": "2026-06-07",
"changes": [
"F9: planning_roadmap JSONB am Progressionsgraph (Migration 088).",
"PUT Graph + POST edges/sequence speichern Planungs-Artefakt; Laden beim Graph-Wechsel.",
"Roadmap-Vorschlag: include_llm_intent=true für reicheren Semantic Brief.",
"Doku: docs/architecture/PLANNING_PROGRESSION_GRAPH_KI.md als zentrale Ist-Referenz.",
],
},
{
"version": "0.8.216",
"date": "2026-06-07",
"changes": [
"F8: Editierbare stage_specs in UI (Belastung, Erfolgskriterien) → roadmap_override.",
"Erwartete Fähigkeiten als Tags pro Pfadschritt und auf Pfad-Ebene.",
],
},
{
"version": "0.8.215",
"date": "2026-06-07",
"changes": [
"F7: planning_skill_expectations — pro Stufe Retrieval, path_skill_expectations, Gap-Kontext.",
"Wiederverwendbare Scopes für spätere Trainingsplanung (training_section, framework_slot).",
],
},
{
"version": "0.8.214",
"date": "2026-06-07",
"changes": [
"F6: ExerciseGapFillPrepModal — Trainer-Ergänzungen vor KI-Entwurf.",
"context_preview und reicher goal_for_ai aus Roadmap-Snapshot.",
],
},
{
"version": "0.8.210",
"date": "2026-06-07",
"changes": [
"F5: Strukturierte Start/Ziel-Felder, Prompt 087, Zwei-Schritt-UI (start_target_only).",
"Priorität Trainer-Eingabe > KI > Regex; heuristische Start→Ziel-Roadmap.",
],
},
{
"version": "0.8.209",
"date": "2026-06-07",
"changes": [
"F3-Polish: roadmap_first — keine Brücken zwischen Major Steps, kein LLM-Reorder.",
"Pfad-QS: Lücken nur noch bei Nicht-Roadmap-Übergängen; roadmap_qa_mode in Response.",
],
},
{
"version": "0.8.208",
"date": "2026-06-07",
"changes": [
"Phase D: planning_context an POST /exercises/ai/suggest — Prompts Migration 085.",
"Pfad-Builder + Planungs-Picker senden strukturierten Planungskontext bei KI-Neuanlage.",
"Modul planning_exercise_form_context.py; Platzhalter planning_context_json in Übungs-Prompts.",
],
},
{
"version": "0.8.207",
"date": "2026-06-07",
"changes": [
"Phase F4: Roadmap-Review — roadmap_only, roadmap_override auf progression-path-suggest.",
"UI: Major Steps editierbar (Phase, Lernziel, Reihenfolge) vor Übungs-Match.",
"Zwei-Schritt-Flow: Roadmap vorschlagen → Übungen matchen.",
],
},
{
"version": "0.8.206",
"date": "2026-06-07",
"changes": [
"Phase F3: roadmap_first — Bibliotheks-Match pro stage_spec/Major Step statt iterativem Pfad.",
"Gap-Angebote für unbesetzte Roadmap-Stufen (roadmap_unfilled).",
"UI: Pfad-Builder sendet roadmap_first; Übungen an Roadmap gekoppelt.",
],
},
{
"version": "0.8.205",
"date": "2026-06-07",
"changes": [
"Phase F2: Roadmap-LLM über konfigurierbare ai_prompts (078/079) — nur Slugs im Code.",
"include_llm_roadmap auf progression-path-suggest; Fallback deterministisch.",
"Response: prompt_slugs, prompt_slug_catalog, llm_*_applied.",
],
},
{
"version": "0.8.204",
"date": "2026-06-07",
"changes": [
"Planungs-KI Phase F0: Roadmap-first Architektur — planning_progression_roadmap.py (A→B→C).",
"API progression-path-suggest: include_roadmap_preview, progression_roadmap in Response.",
"Doku: PLANNING_PROGRESSION_ROADMAP_SPEC, PLANNING_KI_ROADMAP; Migration 078 Prompts.",
"UI: Didaktische Roadmap-Box im Pfad-Builder (Übergangsphase parallel zu Retrieval).",
],
},
{
"version": "0.8.203",
"date": "2026-06-07",
"changes": [
"Pfad-Builder E3-Fix: themenfremde Schritte (z. B. One Leg Squat) aus Pfad entfernen.",
"Lücken-Angebote: kein Pre-KI-Call — voller Entwurf beim Klick mit goal_for_ai-Kontext.",
"UI: Skills-Katalog im Preview, maxSteps beim Einfügen einhalten.",
],
},
{
"version": "0.8.190",
"date": "2026-05-23",
"changes": [
"Planungs-KI Phase E3: gap_fill_offers nach LLM-QS — Lücken, Off-Topic, QS-Neuanlage.",
"Pfad-Builder UI: „Fehlende Schritte — mit KI anlegen“ + ExerciseAiQuickCreateModal.",
"Schwache Bibliotheks-Brücken ablehnen; Migration 077 Pfad-QA suggested_new_exercises.",
],
},
{
"version": "0.8.189",
"date": "2026-05-23",
"changes": [
"Fix Pfad-Builder: Semantik-Gate zu strikt — soft penalty statt Hard-Filter, gestufter Fallback.",
"Mae-Geri-Matching: Titel/Summary/Goal, Mae-Geri/Maegeri-Schreibweisen.",
],
},
{
"version": "0.8.188",
"date": "2026-05-23",
"changes": [
"Fix Pfad-Builder: Mae-Geri-Thema — kein Skill-Profil ab Schritt 2, verwässerte must_phrases.",
"Pfad-Retrieval: hartes Semantik-Gate, Geri-Waza/Koordination/Gleichgewicht-Erwartungsprofil, QS-Reorder nur bei ok.",
],
},
{
"version": "0.8.187",
"date": "2026-05-23",
"changes": [
"Planungs-KI Phase E2: LLM-Pfad-QS kann Reihenfolge per ordered_step_indices anpassen.",
"Unüberbrückbare Lücken: KI-Neuanlage-Vorschläge (is_ai_proposal) statt nur Bibliotheks-Brücken.",
],
},
{
"version": "0.8.186",
"date": "2026-05-23",
"changes": [
"Planungs-KI Phase E: Semantic Brief (Technik-Phrasen, Ausschlüsse, Entwicklungsbogen) im Hybrid-Retrieval.",
"Pfad-Builder: semantische Schritte, Lücken-Erkennung, Brücken-Übungen, optional LLM-Pfad-QS.",
],
},
{
"version": "0.8.185",
"date": "2026-05-23",
"changes": [
"Planungs-KI Phase C3: POST /api/planning/progression-path-suggest — Ziel → aufbauender Übungspfad.",
"Progressionsgraph-UI: KI-Pfad-Builder mit Review und Speichern via edges/sequence.",
],
},
{
"version": "0.8.184",
"date": "2026-05-23",
"changes": [
"Planungs-KI Phase C2: Treffer mit Variantenliste + suggested_variant_name; Picker wählt Graph-Variante vor Übernahme.",
"hydrateExercisePlanningRow übernimmt exercise_variant_id / suggested_variant_id in die Planungszeile.",
],
},
{
"version": "0.8.183",
"date": "2026-05-23",
"changes": [
"Planungs-KI Phase C1: Progressionsgraph auto-match vom Anker; variantenbewusste Nachfolger-Kanten (034).",
"Request/Response: anchor_exercise_variant_id, progression_graph_name, suggested_variant_id in Treffern.",
"Frontend Übungsliste: Planungs-KI-Suche im KI-Assistent-Modus; Neuanlage im Dialog statt „+ Neu“.",
],
},
{
"version": "0.8.182",
"date": "2026-05-23",
"changes": [
"Planungs-KI Phase B2: LLM-Rerank bei engem Top-Feld — auch nach Erwartungs-/Intent-LLM (max. 2 Calls).",
"Preset „Nächste aus Kontext“: Rerank wenn Ranking unklar; Frontend sendet include_llm_rank immer.",
],
},
{
"version": "0.8.181",
"date": "2026-05-23",
"changes": [
"Planungs-KI Phase B: guidance_notes + Rahmen-Ziele/Notizen → Text-Signale im Erwartungsprofil (planning_text_signals).",
"requires_partner aus Intent filtert Übungen; retrieval_phase +text_signals; Grund „Passt zu Abschnitts-/Rahmen-Zieltext“.",
],
},
{
"version": "0.8.180",
"date": "2026-05-23",
"changes": [
"Fix: Übungs-Anreicherung Vorschau — max. 3 Übungen/Request, parallel LLM; Frontend-Pakete + Retry bei 504.",
],
},
{
"version": "0.8.179",
"date": "2026-05-23",
"changes": [
"Übungs-Anreicherung: Dialog mit Merge-Modus, Skills/Summary/Anleitung, Kosten-Analyse + Bestätigung.",
"Alle aus Filter auswählen (300+), chunked Preview/Apply; Default Sichtbarkeit privat, replace_all empfohlen.",
],
},
{
"version": "0.8.178",
"date": "2026-05-23",
"changes": [
"Superadmin-Werkzeug Übungs-Anreicherung (KI): Kandidaten filtern, Vorschau, Batch-Apply Skills + Status in_review.",
"API /api/admin/exercise-enrichment/* — wiederverwendet exercise_ai / run_exercise_form_ai_suggestion.",
],
},
{
"version": "0.8.177",
"date": "2026-05-22",
"changes": [
"Planungs-Übungssuche Phase A: gesamte sichtbare Bibliothek deterministisch gegen Erwartungsprofil gerankt.",
"Kein OR-Profil-Pool mehr; Volltext nur noch als Score-Signal; retrieval_phase full_library.",
],
},
{
"version": "0.8.176",
"date": "2026-05-22",
"changes": [
"Fix: Planungs-Übungssuche mit Suchtext — SQL-Parameter für ts_rank/plainto_tsquery korrekt gebunden (500).",
"Preset-Erkennung: „nächste Übung planen“.",
],
},
{
"version": "0.8.175",
"date": "2026-05-22",
"changes": [
"Planungs-KI: „Nächste aus Kontext“ — LLM leitet Erwartungsprofil aus Planungskontext ab (Prompt 074).",
"API: llm_expectation_applied, profile_llm_applied; Retrieval-Phase llm_expectation; max. 1 LLM-Call.",
],
},
{
"version": "0.8.174",
"date": "2026-05-22",
"changes": [
"Planungs-KI: Abschnitts-Kontext (guidance_notes, Übungszahl, letzte Übung), Fähigkeitenprofil Einheit/Abschnitt an LLM.",
"Erwartungsprofil hybrid (Planungsbezug) vs. query_only (nur Suchtext); current_section_plan im Target-Profil.",
],
},
{
"version": "0.8.173",
"date": "2026-05-22",
"changes": [
"Planungs-KI: mehrstufiges Profil-Retrieval (Pool → Profil-Vorselektion → Hybrid); LLM max. 1 Call pro Suche.",
"LLM-Gates: kein Intent bei Kurz-Stichwort/preset; kein Rerank wenn Intent-LLM lief oder Ranking klar.",
],
},
{
"version": "0.8.172",
"date": "2026-05-22",
"changes": [
"Planungs-KI UI: Menüpunkt „Planungs-KI: Übung vorschlagen“ im +-Dialog; Freitext-Suche ohne gespeicherte unit_id (client_free).",
"API exercise-suggest: unit_id optional, group_id für Client-Kontext.",
],
},
{
"version": "0.8.171",
"date": "2026-05-22",
"changes": [
"Planungs-KI P1: Szenario-Pipeline (preset/progression/additive/…) + LLM Intent planning_exercise_search_intent → Erwartungsprofil-Overlay.",
"API: scenario_kind, query_intent_summary, include_llm_intent; Migration 073.",
],
},
{
"version": "0.8.170",
"date": "2026-05-22",
"changes": [
"Planungs-KI P2: optionaler LLM-Rerank (planning_exercise_search_rank) mit Titel/summary/goal; include_llm_rank.",
"Client planned_exercise_ids für ungespeicherten Plan; Migration 072 Prompt.",
],
},
{
"version": "0.8.169",
"date": "2026-05-22",
"changes": [
"Fix: planning_exercise_suggest Import library_content_visibility_sql aus tenant_context (Backend-Start/502).",
],
},
{
"version": "0.8.168",
"date": "2026-05-22",
"changes": [
"Planungs-KI P0.1: ExerciseMatchProfile + PlanningTargetProfile — Profil-Score (Fokus, Stil, Skills, Gap) im Hybrid-Retrieval.",
"API exercise-suggest: retrieval_phase profile_v1, target_profile_summary; Doku §12§14.",
],
},
{
"version": "0.8.167",
"date": "2026-05-22",
"changes": [
"Planungs-KI P0: POST /api/planning/exercise-suggest — Kontext-Pack (Einheit, Plan, Anker, Graph) + Hybrid-Score.",
"ExercisePickerModal: Planungskontext aus TrainingUnitEditPage; Treffer mit Begründungen; Doku PLANNING_EXERCISE_SUGGEST_CONTEXT.md.",
],
},
{
"version": "0.8.166",
"date": "2026-05-22",
"changes": [
"KI Schnellanlage: Suche und Anlage kombiniert (Picker + Übungsliste); Suchstring → Titel/Skizze; Rich-Text-Entwurf bearbeitbar vor Speichern.",
"Übungsliste: Schalter „KI-Anlage“ für direkten Einstieg ohne leere Trefferliste.",
],
},
{
"version": "0.8.165",
"date": "2026-05-31",
"changes": [
"Übungspicker Schnellanlage: KI-Vorschau-Dialog vor Speichern; Live-Bibliothekssuche (Titel+Skizze) mit Übernahme bestehender Übung.",
],
},
{
"version": "0.8.164",
"date": "2026-05-31",
"changes": [
"Planung/Übungspicker: Schnellanlage nutzt suggestExerciseAi (Anleitung, Kurzbeschreibung, Fähigkeiten); Fokusbereich Pflichtfeld.",
],
},
{
"version": "0.8.163",
"date": "2026-05-31",
"changes": [
"KI Anleitung: Migration 071 Prompt exercise_instruction_rewrite (JSON: goal, execution, preparation, trainer_notes);",
"POST /exercises/ai/suggest include_instructions; Sanitize/Plaintext-Limits; Medien-Verweise bleiben erhalten;",
"Ueungsformular Tab Anleitung: Button „KI: Anleitung ueberarbeiten“ mit Vorschau-Dialog pro Feld.",
],
},
{
"version": "0.8.162",
"date": "2026-05-31",
"changes": [
"KI Prompt P1 abgeschlossen: ai_prompt_context (Formular-Kontext), run_exercise_form_ai_suggestion als gemeinsamer Einstieg;",
"POST /exercises/ai/suggest und regenerate bauen ExerciseFormAiPromptContext; Admin-Vorschau nutzt dasselbe Modell.",
],
},
{
"version": "0.8.161",
"date": "2026-05-31",
"changes": [
"Migration 070: ai_prompts.openrouter_model (optional je Prompt; Fallback OPENROUTER_MODEL).",
"exercise_ai: effektives OpenRouter-Modell pro Slug; API-Response models_by_slug + model (Skills bevorzugt).",
"Superadmin „KI Prompts“: OpenRouter-Modell speicherbar.",
],
},
{
"version": "0.8.160",
"date": "2026-05-30",
"changes": [
"KI Prompt P1: ai_prompt_runtime load_and_render_ai_prompt + render_ai_prompt_template_for_row; AiPromptUnavailableError;",
"Neu ai_prompt_job: ExerciseFormAiPromptContext (Pydantic), resolve_exercise_form_variables; Admin-Prompt-Vorschau nutzt gleichen Pfad wie exercise_ai-Logik;",
"Zielarchitektur-Doku: Phasendiagramm P0/P1 angepasst.",
],
},
{
"version": "0.8.159",
"date": "2026-05-30",
"changes": [
"Doku: AI_PROMPT_TARGET_ARCHITECTURE.md (Zielbild Kontext-Arten, Composition, Planung/Rahmen, Phasenplan); HANDOVER & docs/architecture/README verlinkt;",
"Backend ai_prompt_runtime: AiPromptContextKind, load_ai_prompt_row — exercise_ai ohne duplizierte Prompt-SQL;",
],
},
{
"version": "0.8.158",
"date": "2026-05-30",
"changes": [
"KI-Prompts: Backend prompt_resolver ({{platzhalter}} robust), Admin-API /api/admin/ai-prompts* (Liste, Detail, PUT, Preview, Reset), Migration 069 default_template;",
"Superadmin-Web: Admin KI Prompts (/admin/ai-prompts) mit Platzhalter-Katalog und Vorschau ohne OpenRouter.",
],
},
{
"version": "0.8.157",
"date": "2026-05-22",
"changes": [
"Übungsformular-KI: Buttons nur noch bei Busy deaktiviert; Vorschau wird vor neuem Aufruf geschlossen (kein Permanent-Grauschalter durch Modal-Zustand)",
"OpenRouter: verschachtelte Textbloecke/Content-Huellen fuer Anthropic; refusal optional mitgenommen",
"exercise_ai: SHINKAN_AI_DEBUG=1 — detaillierte WARN-Logs (Prompt-Laengen, parse-Fehler, Sanitize-Anzahl)",
],
},
{
"version": "0.8.156",
"date": "2026-05-22",
"changes": [
"OpenRouter Client: Assistant-Content als Liste/Bloecke (Claude über Bedrock/OpenRouter)",
"exercise_ai: leere Modelantwort als 502; Skill-JSON aus Fließtext per balanciertem Array-Zuschnitt robuster parsen",
"Admin Retrieval-Profil: Gewichte/Unterkategorien per Formular ohne JSON-Editor",
],
},
{
"version": "0.8.155",
"date": "2026-05-29",
"changes": [
"exercise_ai: Fix haengender KI-Endpunkt bei sehr langen Skill-Arrays vom Modell (Cap + frueher Abbruch nach 5 gueltigen Zeilen)",
],
},
{
"version": "0.8.154",
"date": "2026-05-29",
"changes": [
"Superadmin-Web: KI Skill-Retrieval-Profile unter /admin/ai-skill-retrieval (Liste, JSON config, CRUD gegen /api/admin/ai-skill-retrieval-profiles*)",
"Backend: Router ai_skill_retrieval_admin registriert; ACCESS_HINTS EXEMPT dokumentiert",
],
},
{
"version": "0.8.153",
"date": "2026-05-29",
"changes": [
"Migration 068: ai_skill_retrieval_profiles — konfigurierbare Gewichte/Quotes fuer Skill-Katalog in exercise_ai",
"POST /api/exercises/ai/suggest: optionales Body-Feld focus_areas_context; regenerate nutzt gespeicherte Fokusbereiche",
"exercise_ai: kontextbezogene Skill-Auswahl (Score, Kategorie-Caps), Keyword-Patches wie Rollenspiel vs. Haltegriff/Befreiung",
],
},
{
"version": "0.8.152",
"date": "2026-05-22",
"changes": [
"KI bei Uebungen: Migration 067 ai_prompts + summary_ai_generated; OpenRouter-Hilfsmodul; POST /api/exercises/ai/suggest und POST /api/exercises/{id}/ai/regenerate",
"Uebungsformular: Buttons KI Kurzfassung / Fähigkeiten; exercise_skills is_primary wird aus Payload gespeichert",
],
},
{
"version": "0.8.151",
"date": "2026-05-20",
"changes": [
"Phase 3 Fähigkeiten-Scoring: skill_scoring.py (Dauer × Vorkommen × Primär/Intensität/Beitrag)",
"GET skill-profile für Rahmenprogramm (gesamt + pro Slot), Trainingsmodul, Progressionsgraph",
"GET /api/skill-discovery/suggestions nach skill_ids",
],
},
{
"version": "0.8.149",
"date": "2026-05-19",
"changes": [
"Trainingsplanung: Einheiten-Editor als Vollseite (/planning/units/new|/:id/edit); Hub ohne Modal; Legacy ?unit= Redirect",
"Drift-Schutz: planningUnitRoutes.js, trainingUnitEditorCore.js, Vitest; Playwright 1415",
],
},
{
"version": "0.8.148",
"date": "2026-05-19",
"changes": [
"Planung Vorlagen: Strukturvorschau (Split-Sessions), Kurzbeschreibung, Bearbeitungsseite; Liste liefert sections[] mit",
],
},
{
"version": "0.8.147",
"date": "2026-05-19",
"changes": [
"Planung: Liste Rahmen-Session & Übungen→Modul; Dialog Modul aus Einheit; klarere Rahmen-Unit-ID aus Liste",
],
},
{
"version": "0.8.146",
"date": "2026-05-19",
"changes": [
"Planung: Trainingseinheit → Rahmenprogramm (Session-Slot) speichern; API POST /api/training-units/{id}/publish-to-framework",
],
},
{
"version": "0.8.145",
"date": "2026-05-16",
"changes": [
"Wiki-Import: Standard-Kategorie Fähigkeiten korrigiert auf „Fähigkeitsbeschreibung“ (korrekter Wiki-Name).",
],
},
{
"version": "0.8.144",
"date": "2026-05-16",
"changes": [
"Wiki-Import: Default-Kategorie Fähigkeiten; SMW-Client entfernt versehentliches „Kategorie:“-Prefix; Vorschau/Ausführung nutzen Default-Kategorie je import_type wenn leer.",
"Admin UI Wiki-Import: Wechsel Import-Typ setzt passende Standard-Kategorie.",
],
},
{
"version": "0.8.143",
"date": "2026-05-16",
"changes": [
"DB 065: skills.karate_relevance + skills.relevance_level (Wiki KarateRelevanz / RelevanzLevel 13); smw_mapper + Wiki-Import upsert.",
],
},
{
"version": "0.8.142",
"date": "2026-05-16",
"changes": [
"Bibliothek Planung: Bearbeiten/Löschen von Vorlagen, Rahmenprogrammen, Trainingsmodulen, Progressionsgraphen nach RBAC wie Übungen (club_tenancy.assert_library_content_* + Governance-Übergänge)",
"Planungs-UI: Sichtbarkeit/Verein beim Speichern neuer Trainingsvorlage",
],
},
{
"version": "0.8.141",
"date": "2026-05-14",
"changes": [
"DB 064: Vorlagen-Sektionen mit phase_kind / phase_order_index / parallel_stream_order_index; Speichern und Anwenden behält Split-Sessions; Server: Vorlage → Einheit über Phasen-Replace.",
],
},
{
"version": "0.8.140",
"date": "2026-05-14",
"changes": [
"Frontend Trainingsplanung: Breakout-Panel (neue Ganzgruppen-/parallele Phase, Stream in letzter parallelen Phase); pro Abschnitt Zuordnung zu Phase/Stream oder klassischer Ein-Ganzgruppen-Ablauf.",
],
},
{
"version": "0.8.139",
"date": "2026-05-14",
"changes": [
"Frontend Trainingsplanung: GET phases → Editor mit planLoc pro Abschnitt; Speichern sendet PUT phases bei Breakout-Einheiten (sonst weiter sections); Modul-Dialog zeigt Phase/Stream in der Abschnittsauswahl.",
],
},
{
"version": "0.8.138",
"date": "2026-05-14",
"changes": [
"Planung Paket 2: POST/PUT training_units mit phases (voller Phasen-/Stream-Plan); höchstens eines von phases, sections, exercises pro Request; Rahmen-Blueprint→Termin kopiert verschachtelten Plan; apply-training-module optional phase_order_index + parallel_stream_order_index.",
"Fix: POST from-framework-slot übergibt role an _copy_blueprint_into_scheduled_unit (Stream-Trainer-Validierung).",
"Integrationstest test_replace_phases_roundtrip_parallel_stream.",
],
},
{
"version": "0.8.137",
"date": "2026-05-14",
"changes": [
"DB 063: training_unit_phases, training_unit_parallel_streams; Sektionen mit phase_id oder parallel_stream_id; Default whole_group für Bestand.",
"Planung: GET training_unit liefert phases (verschachtelt) + sections (flach sortiert); Legacy-PUT sections weiterhin eine whole_group-Phase.",
],
},
{
"version": "0.8.136",
"date": "2026-05-13",
"changes": [
"Fix: api/exercises.js — Mandanten-Header für Raw-fetch (PUT Übung, Medien-Upload, Bulk-Archiv) über lokale withActiveClubHeaders statt mergeActiveClubHeader-Import (ReferenceError beim Speichern).",
],
},
{
"version": "0.8.135",
"date": "2026-05-13",
"changes": [
"Frontend Phase 4 Welle 3: frontend/src/api/exercises.js (Übungen, Medien/Archiv, Progressionsgraphen, KI); client.js exportiert API_URL und mergeActiveClubHeader; utils/api.js re-exportiert Modul, api-Objekt spread exercises.",
],
},
{
"version": "0.8.134",
"date": "2026-05-14",
"changes": [
"Frontend Phase 4 Welle 2: frontend/src/api/planning.js (Trainingsplanung); utils/api.js re-exportiert Modul, api-Objekt spread planning.",
],
},
{
"version": "0.8.133",
"date": "2026-05-14",
"changes": [
"Frontend Phase 4 Welle 1: frontend/src/api/client.js (request, ACTIVE_CLUB_STORAGE_KEY); utils/api.js importiert Client, bleibt Facade. Roadmap Phase 4 gestartet.",
],
},
{
"version": "0.8.132",
"date": "2026-05-14",
"changes": [
"Frontend Phase 3 abgeschlossen: TrainingPlanningPageRoot, ExerciseFormPageRoot, ExercisesListPageRoot unter components/; pages/ nur Re-Export (Soft-Limit). Roadmap UMSETZUNGSPLAN Phase 3 / M3 aktualisiert.",
],
},
{
"version": "0.8.131",
"date": "2026-05-13",
"changes": [
"Frontend Phase 3: TrainingPlanningUnitFormModal (Neu/Bearbeiten-Einheit); frameworkLineageText in trainingPlanningPageHelpers; BASELINE_SNAPSHOT §3.4 k6-Log-Mapping.",
],
},
{
"version": "0.8.130",
"date": "2026-05-13",
"changes": [
"Fix: PUT/POST training_units — assistant_trainer_profile_ids als JSONB mit psycopg2.extras.Json schreiben (rohe Python-Liste → ProgrammingError/500 bei Co-Zuweisung).",
],
},
{
"version": "0.8.129",
"date": "2026-05-13",
"changes": [
"Frontend Phase 3: TrainingPlanningTrainerAssignModal (Trainer zuweisen) aus Trainingsplanungsseite; Handler per useCallback.",
],
},
{
"version": "0.8.128",
"date": "2026-05-13",
"changes": [
"Frontend Phase 3: TrainingPlanningModuleApplyModal (Trainingsmodul einfügen) aus Trainingsplanungsseite; gemeinsamer Callback onModuleApplySectionIndexChange.",
],
},
{
"version": "0.8.126",
"date": "2026-05-13",
"changes": [
"Frontend Phase 3: TrainingPlanningFrameworkImportModal aus Trainingsplanungsseite; Playwright-Test 13 (Rahmen-Dialog, skip ohne Gruppe).",
],
},
{
"version": "0.8.125",
"date": "2026-05-13",
"changes": [
"Tests: Playwright 11 (Übungsliste Bulk-Toolbar), 12 (Trainingsplanung); Dashboard-Test 8 prüft HTTP 200 auf /api/dashboard/kpis; pytest test_dashboard_kpis_200_when_inner_lists_mocked.",
"Frontend Phase 3: trainingPlanningPageHelpers.js aus TrainingPlanningPage; ExerciseListBulkToolbar data-testid.",
],
},
{
"version": "0.8.124",
"date": "2026-05-13",
"changes": [
"Frontend Phase 3 (Teil): ExerciseListBulkToolbar-Komponente; Übungsliste nur Verdrahtung.",
],
},
{
"version": "0.8.123",
"date": "2026-05-13",
"changes": [
"Fix: GET /api/dashboard/kpis — interne Aufrufe von list_exercises / list_training_units erhielten FastAPI-Query-Defaults statt None; .strip() auf Query-Objekt → 500. unwrap_query_default in beiden Handlern (Hilfsmodul fastapi_param_unwrap.py).",
],
},
{
"version": "0.8.122",
"date": "2026-05-13",
"changes": [
"Frontend Phase 3 (Teil): useExerciseListCatalogsAndQuery — Katalog-Fetch und Übungslisten-Laden/Keyset-Pagination aus ExercisesListPage in Hook ausgelagert.",
],
},
{
"version": "0.8.121",
"date": "2026-05-13",
"changes": [
"Frontend Phase 3 (Teil): Übungsliste — Suchleiste/Chips in ExerciseListSearchBar; API-Query-Bau und Filter-Chips in utils/exerciseListQuery.js bzw. exerciseListFilterChips.js.",
],
},
{
"version": "0.8.120",
"date": "2026-05-13",
"changes": [
"Frontend: Übungsliste — Filter- und Massenänderungs-Dialoge in ExerciseListFilterModal / ExerciseListBulkModal ausgelagert; Playwright-Test 10 (Filter-Dialog).",
],
},
{
"version": "0.8.119",
"date": "2026-05-13",
"changes": [
"Frontend Phase 3 (Teil): Übungsliste — ExerciseListCard-Komponente, Progressions-Tab lazy (Suspense); Übungspicker-Modal mit @tanstack/react-virtual; content-visibility auf Karten im Übungs-Gitter; Playwright-Test 9 Übungsliste.",
],
},
{
"version": "0.8.118",
"date": "2026-05-14",
"changes": [
"GET /api/dashboard/kpis liefert training_home (upcoming, planned_with_notes, review_pending) — gleiche Logik wie zuvor zwei listTrainingUnits-Calls; Dashboard-Frontend ein Request.",
"Migration 062: Index exercise_skills(exercise_id, level_rank_expr) für list_exercises Stufenfilter; Ausdruck wie _EXERCISE_SKILL_LEVEL_RANK_SQL.",
"Phase 2: Vorlagen EXPLAIN unter scripts/load/explain-readpaths.sql; Playwright-Test 8 erwartet 0× GET /api/training-units auf dem Dashboard.",
],
},
{
"version": "0.8.117",
"date": "2026-05-14",
"changes": [
"GET /api/training-units: optionale Keyset-Pagination (cursor_planned_date YYYY-MM-DD, cursor_id, optional cursor_planned_time bei gesetzter Startzeit; bei Keyset ist limit erforderlich). Sortierung um stabile Tie-Breaks ergänzt: (planned_time_start IS NULL), id.",
"Migration 061: Teilindizes training_units für ASC/DESC-Keyset inkl. id (ersetzt idx_training_units_scheduled_order).",
"frontend api.listTrainingUnits: Query-Parameter für Cursor durchreichen.",
],
},
{
"version": "0.8.116",
"date": "2026-05-14",
"changes": [
"Frontend: Org-Posteingang lädt beim ersten Mount per requestIdleCallback (Fallback setTimeout), um parallele API-Aufrufe beim Dashboard-Start zu entzerren; refresh/Inbox-Seite unverändert sofort.",
],
},
{
"version": "0.8.115",
"date": "2026-05-14",
"changes": [
"GET /api/exercises: optionale Keyset-Pagination (cursor_updated_at ISO-8601 + cursor_id), stabile Sortierung updated_at DESC, id DESC; „Mehr laden“ in Übungsliste und Picker nutzt Keyset statt OFFSET.",
],
},
{
"version": "0.8.114",
"date": "2026-05-14",
"changes": [
"Migration 060: Skalierung GET /api/exercises — Partial-Indizes official/club (+ updated_at, ohne archiviert); Junction-Indizes (exercise_id, is_primary) für List-Subqueries.",
],
},
{
"version": "0.8.113",
"date": "2026-05-14",
"changes": [
"Migration 059: Teilindex training_units(planned_date, planned_time_start) nur für Zeilen ohne framework_slot_id — list_training_units Sortierung.",
],
},
{
"version": "0.8.112",
"date": "2026-05-14",
"changes": [
"Migration 058: Indizes exercises(updated_at DESC) und (created_by, updated_at DESC) für list_exercises-Sortierung und „meine Übungen“.",
],
},
{
"version": "0.8.111",
"date": "2026-05-13",
"changes": [
"GET /api/dashboard/kpis: Kurzüberblick (meine Entwürfe, meine Übungen, abgeschlossene Einheiten Kalenderjahr) in einem Aufruf; Dashboard-UI nutzt den Endpunkt.",
"Hilfsfunktion list_exercises_like_get in exercises-Router für programmatische Listen ohne Query-Defaults.",
],
},
{
"version": "0.8.110",
"date": "2026-05-12",
"changes": [
"GET /api/training-units/:id: Bei Kombinationsübungen werden `combination_slots` inkl. Kandidaten-Titel mitgeliefert (für Plan & Ablauf / Druck).",
"Hilfsfunktion `load_combination_slots_for_exercise` im exercises-Router; GET Übung nutzt dieselbe Ladelogik.",
],
},
{
"version": "0.8.109",
"date": "2026-05-12",
"changes": [
"Kombination: „Serien“ standardmäßig 1 (Formular/API); Archetyp kann via `ARCHETYPE_DEFAULT_REP_SERIES_COUNT` andere Vorgaben setzen; ProfilEditor zeigt Fallback.",
],
},
{
"version": "0.8.108",
"date": "2026-05-12",
"changes": [
"Kombination rep/manual: Feld „Pause zw. Serien“ nur ab 2 Serien sichtbar und speicherbar; Hinweis unterscheidet Wechsel zur nächsten Station; API verwirft intra_rep_rest_sec bei nur einer Serie.",
],
},
{
"version": "0.8.107",
"date": "2026-05-12",
"changes": [
"Kombination Wiederholungsziel: `rep_series_count` in `slot_profiles_v1` (mehrere Serien à ZielWdh.); Formular und ProfilEditorFelder; Pause als „zwischen Serien“ beschriftet; CoachZusammenfassung angepasst.",
],
},
{
"version": "0.8.106",
"date": "2026-05-12",
"changes": [
"Kombinationsübung: Stationssteuerung `advance_mode` in `slot_profiles_v1` (zeitlich / ZielWiederholungen / Coach ohne Arbeitsuhr); Übungsformular + PlanungsProfilEditor; APIPayload verwirft ArbeitSekunden außer bei Zeitmodus; Coach zeigt verkürzte Planzeile je Station.",
],
},
{
"version": "0.8.105",
"date": "2026-05-12",
"changes": [
"Übungsbearbeitung Kombi: Stationen mit Pool per Modal (nur Einzelübungen), Zeiten pro Station in derselben Karte, Drag&Drop + Pfeile statt Index; API schreibt slot_index aus Reihenfolge; Gesamtdurchläufe bei Zirkel/Sequenz/Parcours/Parallel klar beschriftet.",
],
},
{
"version": "0.8.104",
"date": "2026-05-12",
"changes": [
"KombinationsAblaufprofil UX: Stationszeilen (slot_profiles_v1); Schnellwahlen Arbeit↔Pause (Zirkel + Intervall); PlanungsOverride ohne JSON; Übungsformular: Reihenfolge Stationen dann Ablaufprofil.",
"Arbeitspapier: `.claude/docs/working/COMBINATION_TIMING_PROFILE_PLAN.md`.",
],
},
{
"version": "0.8.103",
"date": "2026-05-12",
"changes": [
"Trainingsplanung: bei Kombinationszeilen optionales `planning_method_profile` (Migration 057); Planungs-Editor mit Ablaufprofil-Details, „wie Katalog“ / „aus Katalog kopieren“; Payload/Coach-PUT übernehmen Snapshot.",
],
},
{
"version": "0.8.102",
"date": "2026-05-12",
"changes": [
"Kombinationsübung beim Anlegen/Bearbeiten: archetypbezogenes Ablaufprofil (geführt) + eingeklappt Roh-JSON (`CombinationMethodProfileEditor`); Schlüsselmanifest `combinationMethodProfileUi.js`. Coach: angelegtes method_profile unter Stationenliste lesbar.",
],
},
{
"version": "0.8.101",
"date": "2026-05-12",
"changes": [
"Training-Coach bei Kombinationsübungen: Stationen/Kandidaten mit geladenem Katalog (Kurzbeschreibung, aufklappbar Ablauf/Trainerhinweise); Archetyp-spezifischer Coach-Hilfstext; Archetyp-Labels aus `combinationArchetypes.js`.",
],
},
{
"version": "0.8.100",
"date": "2026-05-12",
"changes": [
"Planungs-API/UI: Kombinationsübungen in Trainingsseinheiten (exercise_kind in Sektions-Responses; PATCH verbietet exercise_variant_id für combination); ExercisePicker ohne simple-only Filter, Badge Kombination.",
],
},
{
"version": "0.8.99",
"date": "2026-05-12",
"changes": [
"exercises Phase 2 (Kombinationsübungen): Migration 056 (`exercise_kind`, `method_archetype`, `method_profile`; Tabellen Slots/Kandidaten); CRUD über POST/PUT/GET Übung mit `combination_slots`; Liste-Filter `exercise_kind_any`; Varianten-Endpoints verbieten `exercise_kind=combination`.",
],
},
{
"version": "0.8.98",
"date": "2026-05-12",
"changes": [
"profiles: `training_planning_prefs` JSONB (Migration 055), Patch via PUT Profil — z.B. Darstellung kopierter Trainingsmodule in der Planungs-UI (nutzerspezifisch).",
],
},
{
"version": "0.8.97",
"date": "2026-05-12",
"changes": [
"Trainingsmodule (Phase 1): Bibliothek `training_modules` + `training_module_items` (Migration 054); REST `/api/training-modules`; Übernahme in Einheiten per `POST /api/training-units/{id}/apply-training-module`; Herkunft `source_training_module_id` auf kopierten Sektions-Items; UI unter /planning/training-modules und Übernahme-Dialog in der Trainingsplanung.",
"Umsetzungsplan: `.claude/docs/working/TRAINING_MODULES_IMPLEMENTATION_PLAN.md`.",
],
},
{
"version": "0.8.96",
"date": "2026-05-12",
"changes": [
"P-01 Admin Rechtstexte: Live-Vorschau je Abschnitt (Markdown) neben dem Editor; modale „Vollständige Vorschau“ aus dem Formular; Augen-Symbol in der Dokumentenliste für die gerenderte Ansicht (API-Laden).",
],
},
{
"version": "0.8.95",
"date": "2026-05-12",
"changes": [
"P-01 Rechtstexte: Abschnitte in der Ausgabe mit fortlaufender §1, §2, … (nur Darstellung/PDF, nicht in der DB); Fließtext mit Markdown (react-markdown) inkl. PDF-Rendering (fett/kursiv, Listen, Links, Codeblöcke).",
],
},
{
"version": "0.8.94",
"date": "2026-05-11",
"changes": [
"Fix P-13: set_legal_hold_from_report wirft 403 fuer plain Admin vor DB-Zugriff (CI-Testkonsistenz).",
"Fix P-13: Tests test_list_inbox_requires_platform_admin und test_patch_report_under_review repariert.",
],
},
{
"version": "0.8.93",
"date": "2026-05-11",
"changes": [
"Fix P-13: Club-Admins können Inhaltsmeldungen zu Vereinsmedien bearbeiten (PATCH, GET-Detail).",
"Fix P-13: Club-Admins können Legal Hold auf Vereinsmedien (nicht 'official') aus Meldung heraus setzen.",
"Fix P-13: Abgeschlossene Meldungen in der Inbox in kollabierbare Archiv-Sektion verschoben.",
"Fix P-13: isClubAdmin + isPlatformAdmin im OrgInboxContext exponiert.",
],
},
{
"version": "0.8.92",
"date": "2026-05-11",
"changes": [
"Fix P-13: Badge in Medienbibliothek aktualisiert sich sofort nach Einreichen einer Meldung.",
"Fix P-13: Inbox zeigt Fehlermeldung statt leerem Bereich wenn Backend-Fehler auftritt.",
"Fix P-13: Meldungen lassen sich nach Abschluss wieder öffnen (Wieder-öffnen-Button).",
"Fix P-13: Bearbeitungskommentare werden separat im Audit-Log protokolliert.",
"Fix P-13: Reviewer-Felder werden beim Wieder-öffnen einer Meldung zurückgesetzt.",
"Fix P-13: Workflow-Balken im Meldungs-Detail zeigt aktuellen Bearbeitungsstand.",
],
},
{
"version": "0.8.91",
"date": "2026-05-11",
"changes": [
"Fix P-13: Name- und E-Mail-Felder im Melde-Dialog fuer eingeloggte Nutzer nicht mehr bearbeitbar (readOnly).",
"Fix P-13: Journaleintraege fuer content_report_filed leserlich (Meldegrund, Prioritaet, Status auf Deutsch).",
"Fix P-13: Badge auf Medienkacheln zeigt Anzahl offener Meldungen (nur fuer Admins).",
"Fix P-13: Statuswechsel an Meldungen werden im Journal des Mediums protokolliert.",
],
},
{
"version": "0.8.90",
"date": "2026-05-11",
"changes": [
"Fix P-13: Club-Admins sehen jetzt Inhaltsmeldungen ihrer Vereinsmedien in der Inbox (Backend-Filter + Frontend canSeeContentReports).",
"Fix P-13: Journaleintrag (content_report_filed) in media_asset_audit_log beim Einreichen einer Meldung (Migration 053).",
"Fix P-13: E-Mail-Benachrichtigung an alle Plattform-Admins bei neuer Meldung (best-effort).",
"Fix P-13: Bestätigungs-E-Mail an Melder beim Einreichen (best-effort).",
"Fix P-13: Medienname (target_filename/target_exercise_name) korrekt in Inbox-Liste angezeigt.",
],
},
{
"version": "0.8.89",
"date": "2026-05-11",
"changes": [
"Feat P-13: MediaPreviewModal — geteilter Medienvorschau-Dialog für alle Kontexte (Bibliothek, Übungsbearbeitung, angehängte Medien); optionale Melden- und Bearbeiten-Buttons im Header.",
"Feat P-13: Melde-Button im ExerciseFormPage-Viewer (verlinktes Medium → Vorschau → Melden).",
"Refactor: Inline-Vorschau-Blöcke in MediaLibraryPage, ExerciseFormPage und ExerciseAttachmentMediaStrip durch MediaPreviewModal ersetzt.",
],
},
{
"version": "0.8.88",
"date": "2026-05-11",
"changes": [
"Feat P-13: Melde-Button in Medienbibliothek (Grid + Liste) — öffnet ReportContentModal; nur aktive Medien ohne Legal Hold.",
"Feat P-13: Melde-Link an jedem Medium in ExerciseAttachmentMediaStrip (Lesemodus Übung).",
"Feat P-13: ReportContentModal — wiederverwendbares Formular (Grund, Beschreibung, Name, E-Mail, Gutglaubenserklärung); Vorausfüllung für eingeloggte Nutzer.",
],
},
{
"version": "0.8.87",
"date": "2026-05-11",
"changes": [
"Feat P-13: Content-Melde-Backend (DSA/KRIT-03) — Migration 052 content_reports; POST /api/content-reports (optionale Auth, official+aktive Medien ohne Login meldbar); GET /api/me/inbox/content-reports (Plattform-Admin); PATCH /api/content-reports/{id}; POST /api/content-reports/{id}/legal-hold (Superadmin, P-11 Integration).",
"Feat P-13: Automatische Priorisierung high fuer minors/illegal_content/youth_protection.",
"Feat P-13: Inbox-Integration — zweiter Abschnitt 'Inhaltsmeldungen' in InboxPage.jsx; OrgInboxContext liefert contentReports + contentReportCount.",
"Feat P-13: P-11 Legal-Hold via set_legal_hold() aus report heraus (reason_code-Mapping); keine separate Moderations-Queue.",
"Tests: 15 Backend-Unit-Tests test_p13_content_reports.py.",
],
},
{
"version": "0.8.86",
"date": "2026-05-11",
"changes": [
"Fix P-11: download_exercise_media_file gibt 451 zurück für Legal-Hold-Assets (Datei nicht mehr auslieferbar).",
"Fix P-11: enrich_exercise_detail liefert asset_legal_hold_active im Media-Array (Frontend-Komponenten koennen Hold erkennen).",
"Fix P-11: ExerciseMediaEmbed + ExerciseMediaThumbTile zeigen 'Medium nicht verfügbar / Gesperrt' statt Datei laden.",
"Fix P-11: ExerciseFormPage Vorschau-Modal zeigt Hinweis statt Datei bei Legal-Hold.",
"Fix P-11: Media-Bibliothek-Liste (list_media_assets) schliesst Legal-Hold fuer Plattform-Admins aus — nur Superadmin sieht sie.",
],
},
{
"version": "0.8.85",
"date": "2026-05-11",
"changes": [
"Fix P-11: Listquery fehlte legal_hold_active/reason_code/reason_note/set_at — Badge und 'Sperre aufheben' im Modal waren nie sichtbar.",
"Fix P-11: submitLegalHold rief loadMedia() statt loadItems() auf ('loadMedia is not a function').",
"Fix P-11: Journal-Renderpfad verwendete nw.legal_hold_reason_code/note statt nw.reason_code/note (Keys aus dem Audit-Log).",
"Fix P-11: Archiv-Picker (ExerciseFormPage, ExerciseInlineFileMediaModal) filtert Legal-Hold-Assets auch fuer Superadmins heraus.",
],
},
{
"version": "0.8.84",
"date": "2026-05-11",
"changes": [
"Feat P-11: Legal-Hold-Sofortsperre — Migration 051 (legal_hold_active + Metadaten in media_assets; audit_log um legal_hold_set/released erweitert).",
"Feat P-11: media_legal_hold.py — zentrale Services set_legal_hold, release_legal_hold, assert_not_under_legal_hold.",
"Feat P-11: Retention-Job ueberspringt Assets mit legal_hold_active=TRUE (keine automatische Loeschung unter Hold).",
"Feat P-11: Neue Admin-Endpoints POST /api/admin/media-assets/{id}/legal-hold, POST …/legal-hold/release, GET …/legal-hold (nur Superadmin).",
"Feat P-11: Sichtbarkeitsfilter erweitert — normale Nutzer sehen Legal-Hold-Assets nicht; Superadmin/Plattform-Admin sehen sie.",
"Feat P-11: exercises from-asset prueft Legal-Hold (LEGAL_HOLD_ACTIVE 403) vor Verknuepfung.",
"Feat P-11: Frontend MediaLibraryPage — Legal-Hold-Badge, Superadmin-Aktionen, Bestaetigungs-Dialog, Journal-Renderpfad fuer legal_hold_set/released.",
"Tests: 15 Backend-Unit-Tests test_p11_legal_hold.py.",
],
},
{
"version": "0.8.83",
"date": "2026-05-11",
"changes": [
"Fix: Journal + Korrektur-Endpoint: club_admin-Pruefung nutzte falsches Schema (role-Spalte nicht in club_members, sondern in club_member_roles via has_club_role); lieferte immer 500.",
],
},
{
"version": "0.8.82",
"date": "2026-05-11",
"changes": [
"Feat P-06: Volljournal fuer Medien (Migration 050) — media_asset_audit_log protokolliert Sichtbarkeits-, Copyright-, Metadaten- und Lifecycle-Aenderungen automatisch.",
"Feat P-06: Korrektur-Deklaration (action_type='correction') via POST /api/admin/media-rights/assets/{id}/correction — zugaenglich fuer Superadmin, Uploader, Vereinsadmin.",
"Feat P-06: Journal-Endpoint gibt jetzt events[] (Deklarationen + Auditlog chronologisch gemischt) und can_correct zurueck; Zugriff fuer Superadmin + Uploader + Vereinsadmin.",
],
},
{
"version": "0.8.81",
"date": "2026-05-11",
"changes": [
"Fix P-06: check_rights_coverage gibt bei rights_status='declared' immer 'ok' zurueck — Erklaerung gilt sichtbarkeitsunabhaengig (Inhalt aendert sich nicht durch Sichtbarkeits-Promotion). 'insufficient'-Pfad entfernt. Tests angepasst.",
],
},
{
"version": "0.8.80",
"date": "2026-05-11",
"changes": [
"Fix P-06: Bei Sichtbarkeits-Promotion (private→club, club→official) oeffnet das Frontend bei RIGHTS_SCOPE_INSUFFICIENT / LEGACY_REDECLARATION_REQUIRED automatisch den Einwilligungsdialog (promotion/redeclaration-Modus) statt eines alert()-Fehlers; PATCH wird nach Bestaetigung mit P-06-Feldern wiederholt.",
],
},
{
"version": "0.8.79",
"date": "2026-05-11",
"changes": [
"Fix: profiles.username -> profiles.name in Journal-Endpoint (500er behoben); RightsDeclarationDialog: doppelter Abbrechen-Button entfernt (Header-X statt Text); Playwright P-01: Platzhalter-Pruefung optional (echtes Impressum deployed); Playwright P-06c: Selector-Konflikt durch UI-Fix beseitigt.",
],
},
{
"version": "0.8.78",
"date": "2026-05-11",
"changes": [
"P-06 Superadmin Medienjournal: GET /api/admin/media-rights/assets/{id}/journal liefert vollstaendiges Deklarations-Log pro Medium; Frontend: Journal-Button im Bearbeitungs-Modal (nur Superadmin), scrollbare Timeline aller Einwilligungserklaerungen mit Kontext-Feldern.",
],
},
{
"version": "0.8.77",
"date": "2026-05-11",
"changes": [
"P-06 Erweiterung: Migration 049 — 4 optionale Freitext-Kontextfelder in media_asset_rights_declarations (person_consent_context, parental_consent_context, music_rights_context, third_party_rights_context); copyright_notice direkt im Upload-Dialog erfassbar; alle drei Dialoge (RightsDeclarationDialog, ExerciseInlineFileMediaModal, ExerciseInlineEmbedModal) und alle Backend-Endpoints aktualisiert.",
],
},
{
"version": "0.8.76",
"date": "2026-05-11",
"changes": [
"Fix P-06: RightsDeclarationDialog in ExerciseInlineFileMediaModal (Upload-Tab) und ExerciseInlineEmbedModal integriert; vor jedem Exercise-Media-Upload oeffnet sich der vollstaendige Einwilligungsdialog statt eines nicht-benutzbaren alert()",
],
},
{
"version": "0.8.75",
"date": "2026-05-11",
"changes": [
"P-06 (Upload-Einwilligungsdialog) technisch umgesetzt unter konservativen Erstannahmen (p06-v1-conservative): Migration 048 (media_asset_rights_declarations + rights_status/rights_declared_for_visibility/rights_declared_at in media_assets); zentrales Policy-Modul media_rights.py; Bulk-Upload und PATCH/Bulk-Patch mit P-06-Enforcement; Re-Deklarations-Endpoint (POST /api/media-assets/{id}/rights-declarations); Admin-Legacy-Summary (GET /api/admin/media-rights/legacy-summary+/legacy-assets); exercises.py: P-06 bei upload_exercise_media und from-asset; Frontend: RightsDeclarationDialog + Altbestand-Indikator in Medienbibliothek. KRIT-04 bleibt offen bis juristische Validierung.",
],
},
{
"version": "0.8.74",
"date": "2026-05-10",
"changes": [
"Rechtstexte: echtes PDF-Download via jsPDF (pdf.save) statt Browser-Print-Dialog; LegalPage und AdminLegalDocumentsPage",
"Rechtstexte Admin: Abschnitts-Reihenfolge per Pfeil-Buttons aendern; neuen Abschnitt an beliebiger Stelle einfuegen",
],
},
{
"version": "0.8.73",
"date": "2026-05-10",
"changes": [
"Rechtstexte: PDF-Export via Browser-Print (kein neues Paket); Drucker-Button in AdminLegalDocumentsPage (laedt Volldokument) und auf LegalPage (nur bei veroeffentlichtem Inhalt); Dokument enthaelt Versionsnummer und Gueltigkeitsdatum",
],
},
{
"version": "0.8.72",
"date": "2026-05-10",
"changes": [
"Rechtstexte: Als-Entwurf-kopieren — POST /api/admin/legal-documents/{id}/copy-as-draft; Inhalt und Titel werden uebernommen, Versionsnummer inkrementiert",
],
},
{
"version": "0.8.71",
"date": "2026-05-10",
"changes": [
"Compliance P-01c: Admin-konfigurierbare Rechtstexte — DB 047 (legal_documents + legal_document_audit); Superadmin CRUD + Publish/Archive-Workflow; LegalPage laedt aus API mit Platzhalter-Fallback; AdminLegalDocumentsPage unter /admin/legal-documents",
],
},
{
"version": "0.8.70",
"date": "2026-05-10",
"changes": [
"Compliance P-01b: Einstellungen/Rechtliches (/settings/legal) fuer mobile/PWA-Darstellung; Hub mit Links zu Impressum, Datenschutz, Nutzungsbedingungen, Medienrichtlinie",
],
},
{
"version": "0.8.69",
"date": "2026-05-10",
"changes": [
"Compliance P-01 (KRIT-01) technischer Teil: Rechtstextseiten /impressum, /datenschutz, /nutzungsbedingungen, /medienrichtlinie als oeffentliche Routen angelegt (Platzhalter, kein Auth erforderlich)",
"Login-Seite und Desktop-Sidebar enthalten Links zu allen vier Rechtstextseiten",
],
},
{
"version": "0.8.68",
"date": "2026-05-10",
"changes": [
"Sicherheit P-12 (MITT-05): logout() bereinigt alle sj_coach_*-Schlüssel aus sessionStorage; Präfix-gezielte Löschung, keine fremden Schlüssel betroffen",
],
},
{
"version": "0.8.67",
"date": "2026-05-10",
"changes": [
"Sicherheit P-05b: PasswordResetConfirm.new_password min_length=8 (POST /auth/reset-password)",
"Sicherheit P-03b: Retention-Default HIDDEN_TO_PURGE 90->30 Tage (gemaess Loeschkonzept 30+30)",
"Sicherheit P-04: Positive Promotion-Tests haerten (explizit 200 + Payload); Umlaut in Fehlermeldung",
],
},
{
"version": "0.8.66",
"date": "2026-05-09",
"changes": [
"Sicherheit P-03: Papierkorb-Retention-Job (media_retention_job.py) als Docker-Service retention-cron aktiviert (lauft taglich um 03:00 Uhr)",
"Sicherheit P-04: Copyright-Pflicht bei Sichtbarkeits-Promotion auf club/official in PATCH und bulk-patch (media_assets)",
"Sicherheit P-05: Passwort-Mindestlange PUT /auth/pin von 4 auf 8 Zeichen angehoben",
"Sicherheit P-07: Release-Test fur ALLOW_PUBLIC_MEDIA_STATIC in test_security_release.py ergaenzt",
"Sicherheit P-23: LoginPage minLength 6 auf 8 angehoben; hartcodierter Versionsstring entfernt",
"Sicherheit P-24: CORS allow_methods und allow_headers auf benotigte Werte eingeschrankt",
],
},
{
"version": "0.8.65",
"date": "2026-05-08",
"changes": [
"Übung auf Verein: fehlende Copyrights an Datei-Assets wieder per Bestätigung + Eingabe beim Speichern setzbar (PUT default_club_media_copyright; Bulk-PATCH ebenfalls)",
],
},
{
"version": "0.8.64",
"date": "2026-05-08",
"changes": [
"Übung bearbeiten: Auto-Scroll beim Drag von Medien zu Textfeldern; Medien-Kacheln mehrspaltig; Sektion/Ablauf-Zuordnung an Medien entfernt (nur noch Titel bearbeiten); Picker: Video-Vorschau-Frame; Katalogvorschau ohne Anhangs-Medienliste; Ansehen mit Speichern-Hinweis + Zurück zur Bearbeitung von der Ansicht",
],
},
{
"version": "0.8.63",
"date": "2026-05-08",
"changes": [
"RTE/Übung Medien: Picker-Thumbnails; Dateiauswahl-Anzeige; bereits verknüpfte Archive-Medien ins Fließtext einfügen; Platzhalter-Caption data-shinkan-exercise-media-caption + Caret nach ZWSP; Lesemodus: Medienliste nur für nicht eingebettete Anhänge; bearbeiten: kompakte Kacheln mit Drag-and-Drop in Textfelder, Upload unter Medien entfällt",
],
},
{
"version": "0.8.62",
"date": "2026-05-08",
"changes": [
"RTE Inline-Medien: Modals Mediathek+Hochladen + „Embed im Text“; Darstellungsgröße small|medium|full (data-shinkan-exercise-media-size); Lesemodus begrenzt Bild/Video-Breite",
],
},
{
"version": "0.8.61",
"date": "2026-05-08",
"changes": [
"RTE „Bild/Video im Text“: eingebaute Hilfe (Caret + insertHTML/Fallback); sichtbarer 📎-Chip im Editor; Hinweis bei fehlgeschlagener Einfügung/Prompt-ID",
],
},
{
"version": "0.8.60",
"date": "2026-05-08",
"changes": [
"Inline-Medien im Übungs-Fließtext (MEDIA_SPEC §11): {{exerciseMedia:id}} → kanonisches span; nur exercise_media dieser Übung; create ohne Platzhalter",
"Frontend: ExerciseRichTextBlock mit Allowlist-Sanitize + Embed; Toolbar „Bild/Video im Text“ im RichTextEditor wenn Medien an der Übung; Detail/Katalog/Liste konsistent",
],
},
{
"version": "0.8.59",
"date": "2026-05-07",
"changes": [
"Aktiver Verein: Backend resolve_tenant_context für Plattform-Admin ohne X-Active-Club-Id nutzt gespeichertes active_club_id wenn der Verein existiert (kein effective=null nach hartem Reload mehr)",
"Frontend: Nach Vereinswechsel Profil neu laden; Dropdown-Wert aus effective_club_id / active_club_id / LocalStorage abgestimmt (getResolvedActiveClubIdForUi)",
],
},
{
"version": "0.8.58",
"date": "2026-05-07",
"changes": [
"Medienbibliothek offiziell: Ändern/Lifecycle nur Superadmin (nicht Plattform-Admin); Bearbeiten-Dialog für andere nur Lesemodus; Superadmin: Vereinsauswahl beim Archiv-Upload folgt aktiv/gesetzt effective_club_id",
],
},
{
"version": "0.8.57",
"date": "2026-05-07",
"changes": [
"Governance: visibility=official nur noch Superadmin (nicht Plattform-Admin)",
"Medienarchiv: private Uploads als Plattform-Admin erfordern explizites club_id; gleiche Ordnerstruktur wie „Verein“, private Kopien mit .u{Profil} vor Dateiendung",
"Übung visibility=Verein: angebundene Archiv-Dateien müssen aktiv sein und Copyright (≥3 Zeichen) haben; UI- und API-Fehlercodes CLUB_MEDIA_*",
"Frontend: „Offiziell“ nur Superadmin (Bibliothek, Übungsformular, Bulk-Sichtbarkeit, Progressionsgraphen)",
],
},
{
"version": "0.8.56",
"date": "2026-05-07",
"changes": [
"Medienbibliothek: Vereinsmedien unter library/{aus Name abgeleitet}-c{club_id}/ statt festem library/club/c{id}/; Sonderzeichen/Umlaute zu sicheren Ordnernamen; fehlender Name → verein-c{id}; Governance-Umzug liest aktuellen Vereinsnamen aus DB",
],
},
{
"version": "0.8.55",
"date": "2026-05-07",
"changes": [
"Medienbibliothek: Speicherpfad library/* mit Medientyp-Unterordnern (image, video, pdf, other) vor SHA-Dateinamen; Umzug bei Governance-PATCH nutzt mime_type aus DB",
],
},
{
"version": "0.8.54",
"date": "2026-05-08",
"changes": [
"Medienpfade: vereinsgeteilt (club) direkt unter library/club/c{id}/; private unter library/club/c{id}/u{profile}/ (kein Ordner „private“/„shared“); Dedupe private inkl. uploaded_by_profile_id",
],
},
{
"version": "0.8.53",
"date": "2026-05-08",
"changes": [
"Medienablage vereinsbezogen: private → library/club/c{id}/private, Vereinssichtbarkeit → …/shared, official unverändert; private Archiv-Upload: club_id oder X-Active-Club-Id; DB club_id bei private gesetzt; PATCH/Bulk: club_id für private nicht mehr blind auf NULL",
],
},
{
"version": "0.8.52",
"date": "2026-05-08",
"changes": [
"Neue lokale media_assets: hierarchische library/* Pfade; Dedupe nach sha+visibility+club_id; bei PATCH/Bulk-Patch Sichtbarkeit/Verein: Datei umziehen, exercise_media.file_path aktualisieren (Details siehe 0.8.53)",
],
},
{
"version": "0.8.51",
"date": "2026-05-07",
"changes": [
"Medienbibliothek GET: Verknüpfung zu Trainingseinheiten nur wenn Tabelle training_unit_exercises existiert (ältere/kaputte Schemas → keine 500, Einheiten-Liste leer)",
],
},
{
"version": "0.8.50",
"date": "2026-05-07",
"changes": [
"Medienbibliothek: DB 046 media_assets.tags (GIN); GET filter media_kind, club_id (Superadmin), uploaded_by; Suche über Copyright & Tags; Antwort usage exercises + training_units; PATCH/Bulk tags; UI volle Breite, Filterleiste, ©-Symbol auf Kacheln, Links zu Übungen/Planung, gleiche Sichtbarkeits-/Status-Symbole wie Übungsliste",
],
},
{
"version": "0.8.49",
"date": "2026-05-07",
"changes": [
"Medienbibliothek UI: Kacheln/Liste, Modal Bearbeiten, Video-First-Frame-Thumbs, Mobile/Safe-Area, Bulk; API: permissions pro Zeile, Uploader/Verein für Admin, PATCH Sichtbarkeit+Bezeichner, trash_soft nur Trainer-Eigenes-Privat / Vereinsorga / Plattform; purge nur Superadmin; superadmin_force_lifecycle + hard_delete; bulk-lifecycle, bulk-patch",
],
},
{
"version": "0.8.48",
"date": "2026-05-07",
"changes": [
"Medienbibliothek: GET /api/media-assets mit lifecycle (active|trash_soft|trash_hidden|all), copyright_notice in Liste; PATCH /api/media-assets/{id} (Copyright); GET …/file für Papierkorb wenn Lifecycle-Recht; Frontend /media + Admin-Nav + Link Übungsformular",
],
},
{
"version": "0.8.47",
"date": "2026-05-07",
"changes": [
"Übung „offiziell“ (§4.2): angehängte Datei-Assets müssen aktiv sein; Sichtbarkeit/Copyright per Bestätigung anheben; PUT /api/exercises/{id} + PATCH bulk-metadata: Felder promote_attached_media_for_official, default_official_media_copyright; Frontend Bestätigungsdialog",
],
},
{
"version": "0.8.46",
"date": "2026-05-07",
"changes": [
"Übung Medien-Upload: bei 409-Konflikt (Papierkorb-Dedupe) logger.warning mit exercise_id, profile_id, media_asset_id, lifecycle, visibility, club_id, sha256_prefix, Dateinamen",
"ExerciseFormPage: erklärende Medien-Hinweistexte in GUI entfernt (Kurzbeschreibung + Archiv-Dialog)",
],
},
{
"version": "0.8.45",
"date": "2026-05-07",
"changes": [
"Upload Übungsmedien: gleicher Inhalt (SHA-256) wie Papierkorb-Asset → 409 MEDIA_ASSET_IN_TRASH statt DB-Fehler; Lifecycle action reactivate (trash_soft/hidden → active)",
"Frontend: Dialog Reaktivieren + Verknüpfen; uploadExerciseMedia wertet strukturiertes 409 aus",
],
},
{
"version": "0.8.44",
"date": "2026-05-07",
"changes": [
"DELETE /api/exercises/{id}/media/{mid}: entfernt nur exercise_media; keine Datei-/media_assets-Löschung; Response orphan_media_asset_id wenn letzte Referenz",
"Übung bearbeiten: Video-Kachel (Erstframe), Dateiname; Papierkorb-Schalter entfernt; „Aus Übung entfernen“ + optional Papierkorb bei Waise",
],
},
{
"version": "0.8.43",
"date": "2026-05-07",
"changes": [
"Medienarchiv: GET /api/media-assets (Suche, nur aktive Assets, Bibliotheks-Sichtbarkeit); GET /api/media-assets/{id}/file (Thumbnails/Vorschau, ssetoken)",
"Übungen: POST /api/exercises/{id}/media/from-asset — bestehendes Archiv-Medium verknüpfen ohne Upload-Duplikat",
"Frontend Übung bearbeiten: „Aus Archiv verknüpfen…“, Medienvorschau-Modal, Kachel-Thumbnails in der Medienliste",
],
},
{
"version": "0.8.42",
"date": "2026-05-07",
"changes": [
"Medien-Papierkorb: POST /api/media-assets/{id}/lifecycle (trash_soft, trash_hidden, recover, purge); Retention-Job scripts/media_retention_job.py",
"Übungen: GET-Detail inkl. asset_lifecycle_state; Bearbeitungsrechte Erweiterung (Vereinsplanung); Frontend Übung bearbeiten: Reihenfolge, Papierkorb-Actions; Detail/Katalog: trash_hidden ausgeblendet, Hinweis trash_soft",
"Fix: ExerciseDetailPage zeigt „Hinweise für Trainer“ wieder an",
],
},
{
"version": "0.8.41",
"date": "2026-05-07",
"changes": [
"DB 045: media_assets, exercise_media.media_asset_id, platform_media_storage; Migration bestehender Medien; Upload-Dedupe pro sha256+visibility+club_id",
"Effektives Medien-Verzeichnis: MEDIA_ROOT + Superadmin local_relative_root (GET/PUT /api/admin/platform-media-storage)",
"Neue Uploads: storage_key exercises/{sha256}{ext}; Download/Delete nutzen media_assets",
"api.js: getPlatformMediaStorage, putPlatformMediaStorage",
],
},
{
"version": "0.8.40",
"date": "2026-05-06",
"changes": [
"Übungen Liste: Fokusfilter mit UND-+ (must_include) und UND- (must_exclude), nur ohne Fokusbereich (focus_only_without); Frontend Dropdown + Mit / Ohne",
],
},
{
"version": "0.8.39",
"date": "2026-05-06",
"changes": [
"Übungen DELETE: Nur eigene private / Vereinsadmin für Vereins-Übungen / Plattform für globale; keine harte Löschung bei Verwendung in Blöcken, Plan-Abschnitten oder Progressionskanten (409 → archivieren)",
"GET /api/exercises: Negativfilter (visibility_exclude_any, status_exclude_any), exclude_without_focus, include_archived; archivierte standardmäßig ausgeblendet",
"Profile exercise_list_prefs (JSONB, Migration 043): gespeicherte Standardfilter; Frontend Übungsliste Filterdialog + „Als Standard speichern“",
"Übungspicker: gleiche Negativfilter; Planung lädt archivierte Übungen immer mit (bestehende Zuordnungen)",
"pytest: tests/test_exercises_delete_policy.py",
],
},
{
"version": "0.8.38",
"date": "2026-05-06",
"changes": [
"Trainingsplanung: Vereinsadmins sehen alle Einheiten bei club_id-/Gruppenliste; GET/PUT Einheit & Löschen mit can_manage_club_org",
"Planung UI: „Trainer zuweisen“ in Vereins-Ansicht (Liste + Kalender) + eigener Modal; Mitgliederverzeichnis für Vereinsorganisation",
],
},
{
"version": "0.8.37",
"date": "2026-05-05",
"changes": [
"DB 042: training_units.assistant_trainer_profile_ids (Co-Trainer-Zuweisung je Termin; NULL = Gruppen-Standard)",
"Trainingseinheiten: POST/PUT lead_trainer_profile_id & assistant_trainer_profile_ids; Leitung für Vereinsmitglieder (Vertretung); GET-Listen inkl. Zuweisung für Sichtbarkeit/assigned_to_me",
"Frontend Trainingsplanung: Leitung/Co-Trainer pro Einheit; Dashboard-Text",
"pytest: tests/test_training_unit_assignments.py",
],
},
{
"version": "0.8.36",
"date": "2026-05-05",
"changes": [
"POST /api/profiles: nur Plattform-Admin; Anlage schema-konform (SERIAL, E-Mail, temporärer PIN-Hash); ProfileCreate mit Pflichtfeldern name + email",
"pytest: POST-Szenarien in test_profiles_read_access.py",
],
},
{
"version": "0.8.35",
"date": "2026-05-05",
"changes": [
"DELETE /api/profiles/{pid}: nur Plattform-Admin (403 sonst); Unit-Tests mit gemockter DB",
],
},
{
"version": "0.8.34",
"date": "2026-05-05",
"changes": [
"GET /api/profiles/{pid}: Zugriff nur eigenes Profil oder Plattform-Admin (403 sonst); Unit-Tests ohne DB; zwei Integrationstests mit PostgreSQL",
"Integration: zwei zusätzliche Profil-Lese-Tests in test_access_layer_integration",
],
},
{
"version": "0.8.33",
"date": "2026-05-05",
"changes": [
"CI pytest-backend wie Mitai-Jinkendo: docker compose exec backend (deployte Stacks shinkan / shinkan-dev); keine Runner-Python/Postgres-Service",
"pytest.ini: Marker smoke/slow, addopts/-q wie Schwesterprojekt; CI: -m \"not slow\", ACCESS_LAYER_STRICT + Integration im Container",
],
},
{
"version": "0.8.32",
"date": "2026-05-05",
"changes": [
"CI pytest-backend: kein setup-python — venv aus System-python3 (arm64/Debian Self-Host, Raspi)",
],
},
{
"version": "0.8.31",
"date": "2026-05-05",
"changes": [
"CI (Gitea): Job pytest-backend — Checkout, Postgres-Service, run_migrations, pytest (+ ACCESS_LAYER_INTEGRATION), ACCESS_LAYER_STRICT auf Router-Hinweis-Script",
"Workflow test.yml: pull_request auf main/develop zusätzlich zu push",
],
},
{
"version": "0.8.30",
"date": "2026-05-05",
"changes": [
"pytest: optionale PostgreSQL-Integration tests/test_access_layer_integration.py (Cross-Verein Übungen Liste/Detail; ACCESS_LAYER_INTEGRATION=1)",
"pytest.ini: Marker „integration“",
],
},
{
"version": "0.8.29",
"date": "2026-05-05",
"changes": [
"Übungen: PATCH /api/exercises/bulk-metadata (bis 500 IDs) — Sichtbarkeit und/oder Status; Ersteller oder Plattform-Admin; Governance wie Einzel-PUT",
"Übungsliste: Mehrfachauswahl, Alle auf dieser Seite, Dialog Massenänderung (Verein/offiziell nur Admins)",
],
},
{
"version": "0.8.28",
"date": "2026-05-05",
"changes": [
"ACCESS_LAYER: Übungen-, Trainingsplanung-, Rahmenprogramme-Detail nutzen library_content_visible_to_profile (einheitliche Leseprüfung)",
"pytest: backend/requirements-dev.txt, pytest.ini, backend/tests/test_access_layer.py — ohne DB (library_content_visibility_sql, parse_active_club_header)",
],
},
{
"version": "0.8.27",
"date": "2026-05-05",
"changes": [
"ACCESS_LAYER Governance-Disziplin: .cursor/rules/access-layer.mdc; ARCHITECTURE 1.4 + CODING_RULES Tenant-Pfad; CLAUDE Pflichtlektüre Zugriffsschicht",
"backend/scripts/check_access_layer_hints.py — Router ohne get_tenant_context außerhalb EXEMPT melden (optional ACCESS_LAYER_STRICT=1)",
"club_tenancy.library_content_visible_to_profile; Audit-Tabelle um globale Router (EXEMPT) ergänzt",
],
},
{
"version": "0.8.26",
"date": "2026-05-05",
"changes": [
"ACCESS_LAYER: clubs-, club_memberships-, club_join_requests-Router nutzen Depends(get_tenant_context) statt nur require_auth",
"profiles: PUT /profiles/{id} und /profile mit TenantContext; profile_document für /auth/me und intern",
"exercise_progression_graphs: Liste/Detail nach library_content_visibility_sql; Leserechte Vereins-Graphs; POST/PUT mit assert_valid_governance_visibility und club_id wie Übungen",
],
},
{
"version": "0.8.25",
"date": "2026-05-05",
"changes": [
"Übungen PUT: bei visibility club wird club_id aus aktivem Verein oder Body gesetzt (verhindert club ohne club_id für Vereinsnutzer)",
"club_tenancy: governance visibility club für Plattform-Admins ohne Vereinsmitgliedschaft (nur Existenz clubs.id)",
"Login POST /api/auth/login: Rate-Limit 30/minute pro IP (vorher 5/minute)",
],
},
{
"version": "0.8.24",
"date": "2026-05-05",
"changes": [
"Übungen-Router: get/update/delete, Varianten, Medien — Depends(get_tenant_context); Upload-Limits via TenantContext; fehlenden DELETE decorator variants gefixt",
],
},
{
"version": "0.8.23",
"date": "2026-05-05",
"changes": [
"ACCESS_LAYER: library_content_visibility_sql + TenantContext an Übungen-Liste, Rahmenprogramme, Trainingsplanung",
"POST Übung/Vorlage/Rahmenprogramm: visibility club ohne club_id → effective_club_id; POST Übung mit assert_valid_governance_visibility",
],
},
{
"version": "0.8.22",
"date": "2026-05-05",
"changes": [
"ACCESS_LAYER Stufe B: Modul tenant_context (resolve_tenant_context, Depends(get_tenant_context)); GET /profiles/me liefert effective_club_id; veralteter X-Active-Club-Id wird dort verworfen (ignore), strikt auf anderen Endpoints via Depends",
"Arbeitspapier ACCESS_LAYER_ENDPOINT_AUDIT.md für Router-Inventar",
],
},
{
"version": "0.8.21",
"date": "2026-05-05",
"changes": [
"FastAPI: Router club_memberships und club_join_requests registriert (GET /api/clubs/{id}/members, join-requests u. a.) — behoben 404 auf Vereinsseite Tab Mitglieder",
],
},
{
"version": "0.8.20",
"date": "2026-05-05",
"changes": [
"Migration 041: wenn noch kein superadmin existiert, werden ältestes Profil mit role admin zu superadmin hochgestuft",
"Registrierung: erster Nutzer und ADMIN_BOOTSTRAP_EMAILS erhalten superadmin (vorher admin)",
],
},
{
"version": "0.8.19",
"date": "2026-05-05",
"changes": [
"Portal-Admin: GET /api/admin/users (alle Nutzer + Vereine); PUT /profiles/{id} mit role/tier (Super-Admin nur durch Super-Admin); Mitgliedschaft inaktiv in Übersicht",
"GUI Admin → Nutzer: Portal-Rolle/Tier, Verein zuweisen, Vereinsrollen bearbeiten",
],
},
{
"version": "0.8.18",
"date": "2026-05-05",
"changes": [
"DB 040 club_membership_requests; API Antrag/Abrufen/annehmen/ablehnen; öffentliches Vereinsverzeichnis; Mitglieder-Directory für Trainerwahl",
"GUI: Vereinsverwaltung Tab Mitglieder & Anträge; Registrierung/Einstellungen Vereinsantrag; Gruppenformular Haupt- und Co-Trainer",
"GET /profiles nur noch für Plattform-Admins",
],
},
{
"version": "0.8.17",
"date": "2026-05-05",
"changes": [
"Multi-Tenancy Phase 4: training_plan_templates + training_framework_programs Listen und Lesen nach visibility/club wie Übungen; Schreiben nur Ersteller oder Plattform-Admin; club_tenancy.assert_valid_governance_visibility",
],
},
{
"version": "0.8.16",
"date": "2026-05-05",
"changes": [
"API Vereinsmitglieder: GET/POST/GET-one/PUT/DELETE /api/clubs/{id}/members (Plattform- oder Vereinsadmin); Frontend api.js Hooks",
],
},
{
"version": "0.8.15",
"date": "2026-05-05",
"changes": [
"DB 039 Fix: Co-Trainer-Backfill über Subquery + CASE (kein jsonb_array_length/jsonb_array_elements auf Nicht-Arrays durch Planner/LATERAL-Reihenfolge)",
],
},
{
"version": "0.8.14",
"date": "2026-05-05",
"changes": [
"DB 039 Fix: Co-Trainer-Backfill nur wenn co_trainer_ids ein JSON-Array ist (vermeidet jsonb_array_length auf Nicht-Array)",
],
},
{
"version": "0.8.13",
"date": "2026-05-05",
"changes": [
"Fix: Startup unter Windows (cp1252) — Emoji/Sonderzeichen in print durch ASCII ([OK]/[FAIL]/[WARN]) ersetzt (main, run_migrations, db_init)",
],
},
{
"version": "0.8.12",
"date": "2026-05-05",
"changes": [
"DB 039: club_members, club_member_roles, clubs.primary_admin_profile_id, profiles.active_club_id + Backfill",
"Multi-Tenancy: Vereinslisten gefiltert, Vereinsanlage nur Plattform-Admin mit primary_admin_profile_id",
"Übungen: visibility club nur für Mitglieder des zugeordneten Vereins",
"GET /api/profiles/me: clubs[], ohne pin_hash; active_club_id setzen via PUT",
"Frontend: X-Active-Club-Id, Vereins-Umschalter, Vereinsseiten angepasst",
],
},
{
"version": "0.8.11",
"date": "2026-05-05",
"changes": [
"DB 038: training_units.lead_trainer_profile_id (Vertretung / Leitung pro Termin)",
"API GET /api/training-units: club_id, assigned_to_me, sort, limit; Co-Trainer in Sichtbarkeit; lead_trainer_name / effective_lead_trainer_profile_id",
"API PUT /api/training-units/{id}: lead_trainer_profile_id (Validierung über Gruppe)",
],
},
{
"version": "0.8.10",
"date": "2026-05-05",
"changes": [
"DB 037: Rahmen-Slot-Blueprints als training_units (framework_slot_id); migration training_framework_slot_exercises → Sektionen/Items; origin_framework_slot_id für Kopien",
"API: Rahmen-Slots mit sections/exercises aus Blueprint; Kalender list_training_units ohne Blueprints; POST /api/training-units/from-framework-slot",
],
},
{
"version": "0.8.9",
"date": "2026-05-05",
"changes": [
"DB 036: Rahmenprogramm Kontext (Fokusbereich, Stilrichtung, M:N Trainingsarten & Zielgruppen); nur Bibliothek — plan_mode/group_id/Slot-training_unit entfernt.",
"API: /api/training-framework-programs ohne concrete/library; Payload focus_area_id, style_direction_id, training_type_ids, target_group_ids",
],
},
{
"version": "0.8.8",
"date": "2026-05-05",
"changes": [
"DB 035: Trainingsrahmenprogramm (Rahmen, Ziele, Slots, Slot-Übungen); plan_mode concrete|library",
"DB 035: training_plan_templates.visibility + Backfill club (CURR-007/008)",
"API: CRUD /api/training-framework-programs (AuthZ wie Übungs-/Planungsbibliothek)",
],
},
{
"version": "0.8.7",
"date": "2026-04-30",
"changes": [
"DB 034: Progressionskanten mit optionalen Varianten-Endpunkten",
"API: POST …/edges/sequence (Reihe auf einmal); POST …/edges/delete-batch",
"Frontend Progressions-UI: Sequenz-Editor, Ketten-Ansicht, Variantenwahl",
],
},
{
"version": "0.8.6",
"date": "2026-04-30",
"changes": [
"DB 033: exercise_progression_edges.notes (Entwicklungsziel)",
"API: Kanten mit notes; JOIN Übungstitel in Listen; PUT Kanten-Notiz",
"Frontend: Progressionsgraphen-Tab unter Übungen + Bereich in Übung bearbeiten",
],
},
{
"version": "0.8.5",
"date": "2026-04-30",
"changes": [
"DB 032: exercise_progression_graphs + exercise_progression_edges (Übung→Übung, edge_type next_exercise)",
"API: CRUD Progressionsgraphen und Kanten unter /api/exercise-progression-graphs",
],
},
{
"version": "0.8.4",
"date": "2026-04-27",
"changes": [
"run_migrations: Warteschlange nach numerischem Präfix der Dateien (stabile Reihenfolge auch bei ungleich langen Zahlen wie 9 vs 10)",
],
},
{
"version": "0.8.3",
"date": "2026-04-28",
"changes": [
"Migrationen: Warteschlange aller fehlenden *.sql; idempotent über schema_migrations",
"Ausführung vorzugsweise psql -1 -f (eine Transaktion pro Datei); Fallback psycopg2 + sqlparse.split",
"requirements: sqlparse wenn kein psql im PATH",
],
},
{
"version": "0.8.2",
"date": "2026-04-28",
"changes": [
"main: run_migrations — Exit-Code auswerten; bei Fehler kein API-Start (verhindert Prod ohne Skill-Tabellen wie 022)",
"SKIP_DB_MIGRATE=1 optional für lokale Runs ohne Datenbank",
],
},
{
"version": "0.8.1",
"date": "2026-04-28",
"changes": [
"skills: JSONB keywords per psycopg2.extras.Json (verhindert 500 wenn keywords als Objekt/Array gesendet wird)",
"GET /api/health/ready: DB-Verbindung + Kern-Tabellen + schema_migrations_count (ohne Auth, für Prod-Debugging)",
],
},
{
"version": "0.8.0",
"date": "2026-04-28",
"changes": [
"DB 031: Trainingsvorlagen (Sektionen) + Struktur pro Einheit (Sektionen, Übungen/Notizen, Dauer)",
"API: /api/training-plan-templates CRUD; Trainingseinheiten mit sections[] + plan_template_id",
"Trainingsplanung UI: Abschnitte, Zwischen-Anmerkungen, Vorlagen auswählen / speichern",
],
},
{
"version": "0.7.9",
"date": "2026-04-27",
"changes": [
"Übungsvarianten: POST/PUT/DELETE /api/exercises/{id}/variants + reorder",
"Übung bearbeiten: voller Varianten-Editor (Speichern pro Variante, Reihenfolge, Voraussetzung)",
"Übung Ansehen: Varianten-Metadaten (Dauer, Schwierigkeit, Material, Progression)",
"GET /exercises Detail: Varianten-Sortierung sequence_order → progression_level",
],
},
{
"version": "0.7.8",
"date": "2026-04-27",
"changes": [
"DB 030: training_unit_exercises.exercise_variant_id (FK exercise_variants)",
"GET /exercises?include_variants=true liefert Varianten für Trainingsplanung",
"Trainingseinheiten: optional exercise_variant_id beim Anlegen/Aktualisieren",
],
},
{
"version": "0.7.7",
"date": "2026-04-27",
"changes": [
"DB 029: Fähigkeitsstufen Einheit (basisoptimierung), model_levels Namen 15",
"Übungen: GET /exercises Filter Stilrichtung, Trainingsstil, Zielgruppe, Fähigkeits-Stufe min/max, ai_search (Volltext-Platzhalter)",
"API: exercise_skills Level-Normalisierung bei Schreiben/Lesen; Wiki-Import Slugs statt Zahl in DB",
],
},
{
"version": "0.7.6",
"date": "2026-04-27",
"changes": [
"API: GET/POST /api/admin/matrix-stack (shinkan.matrix_stack.v1) Fähigkeitskatalog, Reifegradmodelle, Kontext-Bindings für Test→Prod",
"DB 028: exercise_media (Embed/Metadaten), exercise_skills VARCHAR-Level/Intensität; API: POST/PUT/DELETE Medien, /media Static; Übungen-Listen-Fokus",
],
},
{
"version": "0.7.5",
"date": "2026-04-27",
"changes": [
"Resolve/Export: Legacy M:N nur noch, wenn für den Fokus keine Kontext-Bindings existieren (korrekte Striktheit für Fokus+Trainingsstil / Teil-Kontexte)",
],
},
{
"version": "0.7.4",
"date": "2026-04-27",
"changes": [
"DB 027: Bindings Fokus+Trainingsstil ohne Stilrichtung",
"resolve: alle passenden Bindings nach Spezifität mergen",
"API: Export/Import JSON (Modell + aufgelöste Matrix)",
],
},
{
"version": "0.7.3",
"date": "2026-04-27",
"changes": [
"DB 026: maturity_model_context_bindings (Fokus / Stilrichtung / Trainingsstil)",
"API: resolve merged mehrere Modelle; CRUD Bindings; training_type_id Query",
"Admin-Tab Kontext-Zuordnung",
],
},
{
"version": "0.7.2",
"date": "2026-04-27",
"changes": [
"DB: Migration 025 maturity_model_focus_areas / _style_directions / _target_groups (M:N)",
"Bootstrap-Reifegradmodell für alle importierten Skills (Wiki), Stufen 15",
"API+UI: Kontext als Mehrfachauswahl; Matrix zeigt Haupt-/Untergruppe pro Fähigkeit",
],
},
{
"version": "0.7.1",
"date": "2026-04-27",
"changes": [
"DB: Migration 024 maturity_models, model_levels, model_skills, model_skill_levels",
"API: CRUD Reifegradmodelle, Matrix-Pflege, resolve-Kontext",
"Frontend: Admin Fähigkeitsmatrix (/admin/maturity-models)",
],
},
{
"version": "0.7.0",
"date": "2026-04-24",
"changes": [
"BREAKING: Exercises v2.0 - Clean-Room Rebuild (kein Legacy-Code)",
"DB: Migration 014 - Variant Progression + Search Vector + Legacy DROP (age_groups, focus_area, secondary_areas, training_character)",
"DB: Migration 016 - Saved Exercise Searches",
"DB: Migration 017 - Exercise Blocks + Template Blocks",
"Backend: exercises.py komplett neu nach EXERCISES_API_SPEC.md v1.2",
"Backend: Nur M:N Relations, keine JSONB-Kataloge mehr",
"Backend: enrich_exercise_detail() für vollständige Objekte",
"Backend: assign_exercise_relations() für M:N Management",
"API: GET /exercises - Volltext-Suche via tsvector",
"API: POST/PUT /exercises - M:N Relations (focus_areas_multi, training_styles_multi, etc.)",
"Issue #53 konform: Import = Feld-Zuordnung, keine fachliche Interpretation",
]
},
{
"version": "0.6.0",
"date": "2026-04-24",
"changes": [
"Feature: MediaWiki Import (SMW Direct API)",
"DB: Migration 018 - wiki_import_log + wiki_import_references",
"Backend: SmwClient (login, browse, ask, categorymembers)",
"Backend: SmwMapper (SMW Properties → exercises/skills/methods)",
"Backend: import_wiki Router (preview, execute, status, logs, discover)",
"Config: MEDIAWIKI_API_URL=https://karatetrainer.net/api.php",
]
},
{
"version": "0.5.0",
"date": "2026-04-23",
"changes": [
"Feature: Trainer-Kontext-System für fokussierte Ansichten",
"DB: Migration 012 - exercise_training_characters (M:N)",
"DB: Migration 012 - trainer_contexts (Trainer-Profil-System)",
"Backend: CRUD API für Trainer-Kontexte (/api/trainer-contexts)",
"Frontend: TrainerContextsPage für Verwaltung eigener Arbeitsbereiche",
"Architektur: Flat Catalogs + Smart Filtering für 1000+ Übungen",
"Architektur: NULL = 'für alles geeignet', M:N = spezifische Zuordnung",
]
},
{
"version": "0.4.0",
"date": "2026-04-23",
"changes": [
"BREAKING: Migration 010 - Umbenennung training_styles → style_directions",
"BREAKING: Migration 011 - Neue Dimension training_types (Breitensport/Leistungssport)",
"DB: Konsistente Terminologie - Stilrichtungen vs. Trainingsstile",
"DB: Neue Tabelle training_types mit Seed-Daten (Breitensport, Leistungssport, Wettkampf)",
"DB: Neue Junction-Tabelle exercise_training_types (M:N)",
"Architektur: Fokusbereich → Stilrichtung → Trainingsstil → Zielgruppe (alle M:N)",
"Backend: Alle SQL Queries aktualisiert auf neue Tabellennamen (style_directions, style_direction_target_groups)",
"Backend: API Parameter umbenannt (training_style_id → style_direction_id)",
"Backend: CRUD Endpoints für training_types hinzugefügt",
]
},
{
"version": "0.3.4",
"date": "2026-04-23",
"changes": [
"BREAKING: Migration 009 - Zielgruppen M:N Refactoring",
"DB: target_groups.training_style_id entfernt (jetzt global unabhängig)",
"DB: Neue Junction-Tabelle training_style_target_groups (M:N)",
"API: 5 neue Endpoints für M:N Management (GET/POST/PUT/DELETE + hierarchy)",
"API: GET /training-style-target-groups mit Enrichment (focus_area_name, training_style_name)",
"API: GET /training-styles/hierarchy für Tree-View (verschachtelte Struktur)",
"API: POST /training-style-target-groups mit Upsert-Logik",
"Backward-Compatible: exercise_target_groups weiterhin unterstützt",
"Architecture: Eine Zielgruppe kann mehreren Stilen zugeordnet werden",
]
},
{
"version": "0.3.3",
"date": "2026-04-23",
"changes": [
"Fix: Admin-Navigation - Redirect /admin → /admin/catalogs",
"Fix: Admin-Link funktioniert jetzt (vorher 404)"
]
},
{
"version": "0.3.2",
"date": "2026-04-23",
"changes": [
"Feature: Zielgruppen-Verwaltung komplett (Backend + Frontend)",
"API: GET/POST/PUT/DELETE /target-groups mit hierarchischem Kontext (focus_area → training_style → target_group)",
"Admin UI: Neuer Tab 'Zielgruppen' in Katalogverwaltung",
"UX: Create/Edit-Forms mit Training-Stil-Auswahl, Altersbereich (min/max)",
"UX: Hierarchie-Anzeige in Liste (Fokusbereich → Stil → Zielgruppe)",
"Protection: DELETE mit CASCADE-Schutz (Fehler wenn Übungen zugeordnet)",
]
},
{
"version": "0.3.1",
"date": "2026-04-23",
"changes": [
"Feature: Exercises-Router unterstützt M:N Zuordnungen",
"API: GET /exercises/{id} liefert focus_areas[], training_styles[], target_groups[], age_groups_catalog[]",
"API: POST/PUT /exercises akzeptiert focus_areas_multi[], training_styles_multi[], target_groups_multi[], age_groups_catalog[]",
"Pattern: DELETE+INSERT für M:N Updates (konsistent mit skills)",
"Backward-Compatible: Legacy FK-Felder (focus_area_id, training_style_id) bleiben erhalten",
]
},
{
"version": "0.3.0",
"date": "2026-04-23",
"changes": [
"BREAKING: M:N Beziehungen für Übungen (statt 1:1)",
"Migration 008: M:N Zuordnungstabellen (exercise_focus_areas, exercise_styles, exercise_target_groups, exercise_age_groups)",
"Feature: Hierarchische Katalog-Struktur (Fokusbereich → Stil → Zielgruppe)",
"Feature: Zielgruppen-Verwaltung (training_styles.focus_area_id Hierarchie)",
"Feature: Primary/Secondary Assignments (is_primary Flag)",
"Doku: DATABASE_SCHEMA.md + DOMAIN_MODEL.md kontinuierlich gepflegt",
"Architecture: Smart Cascade-Logik (RESTRICT, Rerouting, Move)",
]
},
{
"version": "0.2.0",
"date": "2026-04-23",
"changes": [
"Feature: Admin-verwaltbare Kataloge (Focus Areas, Training Styles, Training Characters, Skill Categories)",
"Feature: Trainer-Fokusbereich-Zuordnung für rollenbasierte Filterung",
"Migration 007: Katalog-Tabellen + Seed-Daten",
"Frontend: AdminCatalogsPage mit 5 Tabs (CRUD für alle Kataloge)",
"Frontend: ExercisesPage nutzt Katalog-Dropdowns (kein Hard-Coding mehr)",
"Frontend: Trainingsstil-Dropdown hinzugefügt (fehlte komplett)",
"Standardisierung: Alle Formulare mit Labels oben, volle Breite, linksbündig",
]
},
{
"version": "0.1.0",
"date": "2026-04-21",
"changes": [
"Initial MVP Setup",
"Feature: Übungsverwaltung (Kern-Modul)",
"Feature: Fähigkeiten- und Methodenkataloge",
"Feature: Trainingsplanung für Gruppen",
"Feature: Trainingsabschnitte mit Kombinations-Flag",
"Feature: MediaWiki-Import (einseitig)",
"Feature: Freigabelogik (privat/Verein/offiziell)",
"Infrastructure: Auth + Membership von Mitai übernommen",
]
}
]