Some checks failed
Deploy Development / deploy (push) Successful in 43s
Test Suite / pytest-backend (push) Failing after 2s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 42s
Test Suite / playwright-tests (push) Successful in 1m19s
- Added support for club feature quota bypass based on portal roles and profile grants in the capabilities check. - Introduced new functions to handle quota bypass logic in club feature access and consumption. - Updated the FeatureUsageBadge component to reflect platform exemptions for features. - Incremented application version to 0.8.195 and database schema version to 20260606083 to reflect these changes. - Enhanced backend routers to include new logic for consuming club features during AI-related actions.
1770 lines
87 KiB
Python
1770 lines
87 KiB
Python
# Shinkan Jinkendo Version Information
|
||
|
||
APP_VERSION = "0.8.195"
|
||
BUILD_DATE = "2026-06-07"
|
||
DB_SCHEMA_VERSION = "20260606083"
|
||
|
||
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.1.0", # quota_bypass-Domain + profile_capability_grants in check_capability
|
||
"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.5.0", # Kontingent-Bypass via Capability-Grants (probe/consume)
|
||
"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.0", # Planungs-KI P1: Szenario-Pipeline + Query-Intent-Overlay
|
||
"planning_exercise_suggest": "0.16.1", # M5: consume_club_feature ai_calls nach KI-Erfolg
|
||
"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.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 14–15",
|
||
],
|
||
},
|
||
{
|
||
"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 1–3); 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; Profil‑Editor 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 à Ziel‑Wdh.); Formular‑ und Profil‑Editor‑Felder; Pause als „zwischen Serien“ beschriftet; Coach‑Zusammenfassung angepasst.",
|
||
],
|
||
},
|
||
{
|
||
"version": "0.8.106",
|
||
"date": "2026-05-12",
|
||
"changes": [
|
||
"Kombinationsübung: Stationssteuerung `advance_mode` in `slot_profiles_v1` (zeitlich / Ziel‑Wiederholungen / Coach ohne Arbeitsuhr); Übungsformular + Planungs‑Profil‑Editor; API‑Payload verwirft Arbeit‑Sekunden 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": [
|
||
"Kombinations‑Ablaufprofil UX: Stationszeilen (slot_profiles_v1); Schnellwahlen Arbeit↔Pause (Zirkel + Intervall); Planungs‑Override 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 (basis–optimierung), model_levels Namen 1–5",
|
||
"Ü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 1–5",
|
||
"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",
|
||
]
|
||
}
|
||
]
|