--- type: ADR id: ADR-0014 status: ACTIVE owner: Lead Architect last_update: 2026-03-28 --- # ADR-0014: Bounded Context Mapping (SCS-Architektur) ## Status Akzeptiert ## Kontext Mit der Entscheidung für Domain-Driven Design (→ ADR-0002) und der modularen Architektur (→ ADR-0001) war es notwendig, die fachlichen Grenzen des Systems explizit zu definieren. Die ursprünglichen Module (`masterdata`, `members`, `horses`, `events`) spiegelten technische Kategorien wider, nicht die tatsächlichen Fachdomänen des österreichischen Turniersports. Folgende Probleme wurden identifiziert: 1. Fehlende Ausrichtung zwischen Code-Struktur und ÖTO-Regelwerk 2. Unklare Verantwortlichkeiten bei domänenübergreifenden Operationen (z.B. Nennungs-Transfer) 3. Keine explizite Trennung zwischen Kern-Domäne (Nennungs-Workflow) und unterstützenden Domänen 4. Fehlende Grundlage für eine skalierbare, offline-fähige Desktop-Architektur ## Entscheidung Das System wird in **6 Bounded Contexts** aufgeteilt, die als **Self-Contained Systems (SCS)** implementiert werden. Jeder Context ist fachlich eigenständig, besitzt seine eigene Ubiquitous Language und kommuniziert über definierte Schnittstellen. ### Übersicht der 6 Bounded Contexts | Context | Verantwortlichkeit | Priorität | Phase | |----------------------------|------------------------------------------------------|-----------|---------| | `registration-context` | Nennungs-Workflow (Herzstück des Systems) | **P1** | Phase 4 | | `master-data-context` | Reiter, Pferde, Vereine, ZNS-Daten, ÖTO-Regelwerk | **P1** | Phase 4 | | `competition-context` | Bewerbe, Startlisten, Ergebnisse, Abteilungs-Logik | **P2** | Phase 5 | | `event-management-context` | Veranstaltung, Turnier, Ausschreibung, Genehmigungen | **P2** | Phase 5 | | `billing-context` | Abrechnung, Kassa, Gebühren, Konten | **P3** | Phase 6 | | `identity-context` | Authentifizierung, Rollen, Berechtigungen (Keycloak) | **P3** | Phase 6 | > **Hinweis `series-context`:** Cups, Serien und Meisterschaften werden in Phase 2+ als eigenständiger Context > implementiert. Die Architektur ist von Anfang an dafür vorbereitet (pluggable Berechnungsmodell, > konfigurierbare Paar-Bindung). Kein Hard-Coding von Serien-Logik in anderen Contexts. --- ### Context-Beschreibungen #### `registration-context` — Kern-Domäne (Core Domain) **Verantwortlichkeit:** Der gesamte Lebenszyklus einer Nennung – von der Erstanmeldung bis zur Stornierung. **Aggregate Roots:** - `DomNennung` – Verbindliche Anmeldung eines Paares (Reiter & Pferd) zu einem Bewerb - `DomNennungsTransfer` – Transfer-Operation (kein Storno + Neu); Guthaben bleibt erhalten - `DomAbteilung` – Kleinste Einheit für Startlisten und Ergebnisse (mit Warn-Logik) **Ubiquitous Language (Auswahl):** - `Nennung`, `Nennschluss`, `Nachnenngebühr`, `Nennungs-Transfer`, `Override-Event`, `Startwunsch` **Kern-Invarianten:** - Eine Nennung ist immer einem Paar (Reiter + Pferd) zugeordnet - Nennungs-Transfer ist eine atomare Operation – kein Zwischenzustand ohne gültiges Paar - Regelwerk-Verstöße erzeugen **Warnungen** (niemals harte Fehler) + `Override-Event` --- #### `master-data-context` — Unterstützende Domäne (Supporting Domain) **Verantwortlichkeit:** Stammdaten aller Akteure, Synchronisation mit dem ZNS (Zentrales Nennungs-System) sowie die " Library of Truth" für das ÖTO/FEI Regelwerk. **Aggregate Roots:** - `DomReiter` – Reiter mit Lizenz, Satznummer, Startkarte - `DomPferd` – Pferd mit Lebensnummer, Kopfnummer, Satznummer - `DomFunktionär` – Person mit Turnier-Rolle und Qualifikation (Richter, Parcoursbauer) - `DomVerein` – OEPS-Mitgliedsverein (Veranstalter) - `DomRegelwerk` – Richtverfahren (§ 204 Springen, § 104 Dressur etc.), Sparten, Klassen - `DomGebührenSatz` – Standard-Sätze für Sportförderbeiträge und Tierwohl-Euros **Ubiquitous Language (Auswahl):** - `Satznummer`, `Lebensnummer`, `Kopfnummer`, `FEI-ID`, `Lizenz`, `Startkarte`, `Gastreiter`, `Richtverfahren`, `Paragraph`, `Sparte`, `Klasse` **Kern-Invarianten:** - `Satznummer` ist der primäre Schlüssel für den ZNS-Datenaustausch - ZNS-Daten sind schreibgeschützt; Erweiterungen erfolgen über Verknüpfungen im `identity-context` - Das Regelwerk dient als Basis für alle fachlichen Validierungen im System - ZNS-Daten werden lokal gecacht (Offline-First) --- #### `competition-context` — Unterstützende Domäne (Supporting Domain) **Verantwortlichkeit:** Strukturierung von Bewerben, Erstellung von Startlisten, Erfassung von Ergebnissen. Die * *Abteilung** ist hierbei die kleinste operative Einheit. **Aggregate Roots:** - `DomAbteilung` – Atomare Einheit für Startlisten und Ergebnisse (ÖTO § 39). Ein Bewerb ist der organisatorische Container. - `DomBewerb` – Klammer um eine oder mehrere Abteilungen mit gemeinsamer Bewerbsnummer, Sparte, Klasse. - `DomStartliste` – Geordnete Liste der Starter einer Abteilung. - `DomErgebnis` – Ergebnis eines Starts (Platzierung, Punkte, Zeit) innerhalb einer Abteilung. **Ubiquitous Language (Auswahl):** - `Abteilung`, `Abteilungsnummer`, `Bewerb`, `Prüfung`, `Startliste`, `Richtverfahren`, `Klasse/Höhe` **Kern-Invarianten:** - Startlisten und Ergebnislisten werden auf **Abteilungsebene** verwaltet - Abteilungs-Schwellenwerte gemäß ÖTO § 39 lösen **Warnungen** aus (→ `Override-Event`) - Ein Bewerb kann mehrere Abteilungen haben (z.B. Trennung nach R1/R2 Lizenzen) --- #### `event-management-context` — Unterstützende Domäne (Supporting Domain) **Verantwortlichkeit:** Verwaltung von Veranstaltungen und Turnieren, Ausschreibungs-Generierung, Genehmigungsprozesse. **Aggregate Roots:** - `DomVeranstaltung` – Interne Organisationseinheit des Veranstalters (selbst vergebene ID) - `DomTurnier` – Offizielles Turnier mit OEPS-vergebener Turniernummer - `DomAusschreibung` – Offizielles Dokument mit Pflichtfeldern gemäß ÖTO (A-Satz ZNS) **Ubiquitous Language (Auswahl):** - `Veranstaltung`, `Turnier`, `Turniernummer`, `Turnierkategorie`, `Ausschreibung`, `Kombination`, `TBA` **Kern-Invarianten:** - `Veranstaltung` ≠ `Turnier` (→ ADR-0002, ÖTO § 2 Abs. 1): Eine Veranstaltung kann mehrere Turniere umfassen - Turniernummern werden von der OEPS vergeben, nicht selbst generiert - Kombinations-Turniere behalten je eigene Turniernummer --- #### `billing-context` — Generische Domäne (Generic Domain) **Verantwortlichkeit:** Gebührenberechnung, Kassenführung, Abrechnung mit Reitern und dem Verband. **Aggregate Roots:** - `DomKonto` – Kontobasierte Abrechnung pro Zahler (Basis für „Hansi-Szenario") - `DomGebühr` – Einzelgebühr (Nenngeld, Nachnenngebühr, Sportförderbeitrag, Tierwohl-Euro) - `DomAbrechnung` – Zusammenfassung aller Gebühren einer Veranstaltung **Ubiquitous Language (Auswahl):** - `Konto`, `Nenngeld`, `Nachnenngebühr`, `Sportförderbeitrag`, `Tierwohl-Euro`, `Gebühren-Verzicht` **Kern-Invarianten:** - Sportförderbeitrag und Tierwohl-Euro fallen **pro Start** an (nicht pro Nennung) - Gebühren-Verzicht wird als explizites Event gespeichert (Audit-Trail) --- #### `identity-context` — Generische Domäne (Generic Domain) **Verantwortlichkeit:** Authentifizierung, Rollen-Management, Berechtigungsprüfung (via Keycloak) sowie die Verwaltung von erweiterten Profilen. **Aggregate Roots:** - `DomBenutzer` – Systembenutzer mit Rollen (TBA, Veranstalter, Meldestelle, Richter) - `DomProfil` – Erweiterte Daten (Logo, Bio, Kontakt) verknüpft mit einer `Satznummer` aus dem `master-data-context` - `DomRolle` – Definierte Rolle mit Berechtigungen **Ubiquitous Language (Auswahl):** - `TBA`, `Veranstalter`, `Meldestelle`, `Richter`, `Profil-Link`, `Rolle`, `Berechtigung` **Kern-Invarianten:** - Keycloak ist der einzige Identity Provider (→ ADR-0006) - Ein System-Benutzer kann über eine Link-Tabelle mit amtlichen ZNS-Daten verknüpft werden - Rollen sind turnierbezogen (ein Benutzer kann bei Turnier A TBA und bei Turnier B Richter sein) --- ## Konsequenzen ### Positive - **Fachliche Klarheit:** Jeder Context hat eine klar definierte Verantwortlichkeit und eigene Ubiquitous Language. Die Umbenennung in `master-data-context` schärft das Verständnis als zentrale Library of Truth. - **Abteilungs-Fokus:** Die Anerkennung der Abteilung als kleinste Einheit im `competition-context` löst Inkonsistenzen bei Start- und Ergebnislisten. - **Unabhängige Entwicklung:** P1-Contexts (`registration-context`, `master-data-context`) können ohne P2/P3 entwickelt werden - **Offline-First:** Jeder Context kann seinen eigenen lokalen Cache verwalten (SQLDelight) - **ÖTO-Konformität:** Die Context-Grenzen spiegeln die Struktur des ÖTO-Regelwerks wider - **Erweiterbarkeit:** `series-context` kann in Phase 2+ ohne Änderungen an bestehenden Contexts hinzugefügt werden ### Negative - **Koordinationsaufwand:** Domänenübergreifende Use-Cases (z.B. Nennungs-Workflow) erfordern explizite Integration - **Datenkonsistenz:** Eventual Consistency zwischen Contexts muss bewusst gehandhabt werden - **Initialer Aufwand:** Vollständige Context-Implementierung erfordert mehr Vorabdesign ### Neutral - Die Context-Grenzen können sich mit wachsendem Domänenwissen verschieben (Living Architecture) ## Betrachtete Alternativen ### Technische Modulaufteilung (abgelehnt) Die ursprüngliche Aufteilung in `masterdata`, `members`, `horses`, `events` wurde verworfen, da sie technische Kategorien statt fachliche Domänen widerspiegelt und keine klare Heimat für den Nennungs-Workflow bietet. ### Monolithische Domäne (abgelehnt) Ein einzelner großer Domänen-Context würde die Komplexität des ÖTO-Regelwerks nicht beherrschbar machen und die Offline-First-Strategie erschweren. ## Referenzen - [ADR-0001: Modulare Architektur](0001-modular-architecture-de.md) - [ADR-0002: Domain-Driven Design](0002-domain-driven-design-de.md) - [ADR-0015: Context Map](0015-context-map-de.md) - [Ubiquitous Language](../../03_Domain/01_Glossary/Ubiquitous_Language.md) - [Abteilungs-Trennungs-Schwellenwerte](../../03_Domain/02_Reference/OETO_Regelwerk/Abteilungs-Trennungs-Schwellenwerte.md) - [MASTER_ROADMAP](../MASTER_ROADMAP.md) - ÖTO 2026, § 2 Abs. 1, § 2 Abs. 7, § 2 Abs. 8, § 39