platform-docs/adr/0012-organisationseinheiten-gruppen-konfigurationsvererbung.md
Thomas Stallinger 502a25e4f6 docs: ADR-0012 Gegenlese-Korrekturen
- Anführungszeichen-Inkonsistenz behoben (gerade statt „..." an einer Stelle)
- Entscheidungs-Absatz zu Gruppen verweist jetzt vorwärts auf den
  Self-Service-Nachtrag, statt für sich allein veraltet zu wirken

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 21:14:38 +02:00

8.2 KiB

ADR-0012: Organisationseinheiten und Gruppen als Konfigurationsvererbung

Status: Beschlossen Datum: 12.08.2026

Kontext

Die Geräteliste im Kundenportal (siehe ADR-0011) kennt bislang nur eine einzige organisatorische Ebene unterhalb der Organisation selbst: gar keine. Jedes Gerät hängt lediglich an organization_id und optional an einer Bereitstellungsvorlage (Install-Rezept, siehe 03-organization-model.md). Für Kund:innen mit mehreren Gebäuden, Jahrgangsstufen oder Klassen fehlt eine Möglichkeit, Geräte organisatorisch zu gruppieren und Konfiguration (Auftragskatalog-Merkmale, siehe ADR-0010) für eine solche Gruppe statt geräteweise vorzugeben — ein aus anderen MDM-Systemen bekanntes Bedürfnis (Organizational Units).

In der Diskussion kristallisierten sich zwei fachlich unterschiedliche Gruppierungsbedürfnisse heraus, die sich nicht in einem einzigen Konzept abbilden lassen:

  1. Organisatorische Verortung (z. B. „Gebäude A" → „Klasse 5a"): jedes Gerät gehört zu genau einem Ort, Orte können ineinander verschachtelt sein, und Konfiguration soll von einem allgemeineren zu einem spezifischeren Ort vererbt werden können — klassische OU-Semantik.
  2. Querschnitts-Zuordnung (z. B. „Lehrer", „Schulleitung"): ein Gerät (bzw. dessen Nutzer:in) kann mehreren solcher Zuordnungen gleichzeitig angehören, die Zuordnungen selbst sind nicht hierarchisch.

Beide Bedürfnisse mit einem einzigen, verschachtelbaren Gruppen-Konzept mit Mehrfachmitgliedschaft abzudecken, hätte bedeutet, dass die „zutreffenden Gruppen" eines Geräts keine einzelne Vorfahrenkette mehr sind, sondern die Vereinigung mehrerer, unabhängiger Vorfahrenpfade — mit entsprechend unklarer Konfliktauflösung selbst für den einfachen, hierarchischen Fall. Die beiden Bedürfnisse wurden deshalb bewusst als zwei getrennte Konzepte modelliert.

Entscheidung

Organisationseinheiten (OEs) bilden pro Organisation einen Baum (parent_id-Selbstreferenz). Ein Gerät gehört zu genau einer OE — exklusive Mitgliedschaft wie bei einem Ordner. Dadurch hat jedes Gerät eine eindeutige, einzelne Vorfahrenkette von seiner eigenen OE bis zur Organisation, und Vererbung ist unzweideutig: eine explizite Einstellung der spezifischsten OE in dieser Kette gewinnt über eine allgemeinere.

Jede Organisation besitzt automatisch eine geschützte Standard-OE „Neue Geräte" (ist_standard = true, parent_id = NULL) — der Landeplatz für neu aktivierte Geräte (load_or_create_device()) sowie für alle Organisationen, die vor dieser Änderung angelegt wurden (per einmaligem Backfill-Script). Damit besitzt devices.oe_id nie einen NULL-Sonderfall im laufenden Betrieb; jedes Gerät zeigt immer auf eine echte OE. Die Standard-OE ist gegen Löschung geschützt, kann aber selbst Konfiguration tragen oder von ihrer (impliziten) Wurzel — der Organisation — nichts weiter erben als den Workspace-Default.

Organisationseinheiten sind Self-Service durch die Kund:in selbst verwaltbar (Kundenportal, /struktur) — anders als bei Bereitstellungsvorlagen (installationszeitlich, technisch) ist die OE-Struktur eine rein organisatorische Entscheidung, die die Kund:in selbst am besten kennt.

Gruppen sind dagegen bewusst flach (keine Verschachtelung) — ein Gerät kann mehreren Gruppen gleichzeitig angehören. Gruppen waren in dieser ersten Ausbaustufe zunächst nur intern verwaltbar (/admin/kunden/{id}), nicht Self-Service (siehe Nachtrag unten, noch am selben Tag revidiert): bei der aktuellen, kleinen Kundenzahl sind die Bedürfnisse dem Betreiber bekannt genug, um sie direkt zu pflegen; künftige, heterogenere Kundschaft (KMUs) wird das wahrscheinlich einmal brauchen. Backend-seitig ist die Gruppen-API identisch zur OE-API aufgebaut (gleiche Endpunkt-Struktur für Merkmal-Overrides), sodass Self-Service später ohne Datenmodell-Umbau nachgezogen werden kann — nur die Kundenportal-Routen fehlten dafür noch.

Konfigurationsvererbung: Sowohl OEs als auch Gruppen können — wie ein Gerät selbst über device_merkmale (ADR-0010) — einzelne katalogfähige Merkmale explizit auf aktiv oder inaktiv setzen (oe_merkmale, gruppen_merkmale; jeweils sparsam, nur bei tatsächlich abweichender Meinung eine Zeile). Die Auflösungsreihenfolge für ein Gerät ist:

  1. Workspace-Default (wie bisher, ADR-0010): Teil des zugewiesenen Workspace → present, sonst absent.
  2. OE-Kette: von der eigenen OE des Geräts zur Wurzel laufend gewinnt die erste explizite Einstellung (spezifischer schlägt allgemeiner — klassische Vererbung).
  3. Gruppen: Das Ergebnis aus Schritt 2 zählt hier als eine weitere, gleichberechtigte Stimme neben den Einstellungen aller Gruppen, denen das Gerät angehört. Bei Widerspruch gewinnt „mehr gewinnt": sobald irgendeine zutreffende Stimme aktiv sagt, ist das Ergebnis aktiv. Diese Regel wurde bewusst einer manuellen Prioritätsordnung zwischen Gruppen vorgezogen — bei Gruppen wie „Lehrer" und „Schulleitung" gibt es keine natürliche, für jedes Merkmal gültige Rangfolge, und „mehr gewinnt" ist ohne zusätzliche Konfiguration deterministisch und einfach erklärbar. Sie passt außerdem zur Art der heutigen Merkmale (Komfort-/Funktionsfeatures wie Browser oder Office-Programme, keine Sicherheits-Schalter) — ein künftiges, tatsächlich sicherheitsrelevantes Merkmal könnte stattdessen am Merkmal selbst eine abweichende Konfliktregel hinterlegt bekommen; das ist hier bewusst nicht vorweggenommen.
  4. Geräte-Override (device_merkmale, ADR-0010, unverändert): gewinnt immer, unabhängig davon, was OE-Kette oder Gruppen sagen — die expliziteste, gerätespezifischste Entscheidung bleibt die letzte Instanz.

Die Herkunft der wirksamen Einstellung (workspace, oe, gruppe, geraet) wird im Kundenportal sichtbar gemacht, statt die Auflösung als reine Blackbox zu präsentieren — Transparenz statt stiller Automatik.

Konsequenzen

devices.oe_id ist eine Pflichtangabe (NOT NULL, ON DELETE RESTRICT); jede Organisation muss vor dem ersten Gerät bereits ihre Standard-OE besitzen. create_organization() legt sie automatisch mit an; für die Bestandsdaten (Organisationen vor dieser Änderung) übernimmt ein einmaliges Backfill-Script (scripts/backfill_organisationseinheiten.py) das nachträglich, bevor die NOT-NULL-Migration angewendet wird.

Das Löschen einer OE mit Kind-OEs oder zugeordneten Geräten sowie das Löschen der Standard-OE selbst wird anwendungsseitig verweigert (freundliche Fehlermeldung statt rohem DB-Fehler) — eine OE muss erst leergeräumt werden, bevor sie verschwinden kann.

Die Auflösungsfunktion für den Auftragskatalog (fetch_auftragskatalog_state()/fetch_auftragskatalog_listing(), siehe ADR-0010) braucht für jedes Gerät zusätzlich die vollständige OE-Kette und Gruppenmitgliedschaft. Das wird bewusst in Python statt per rekursivem SQL gelöst (im gesamten provisioning-server bislang keine CTEs) — ein OE-Baum im Umfang einer Schule passt vollständig in den Speicher, eine einmalige Abfrage aller OEs einer Organisation reicht.

Gruppen sind vorerst ein rein interner Verwaltungsmechanismus. Sollte künftig Self-Service für Gruppen nötig werden, ist das ein reiner Kundenportal-Routing-Zusatz (analog zu routers/struktur.py), keine Backend- oder Datenmodell-Änderung.

Gruppen-Self-Service nachgezogen (12.08.2026, gleicher Tag): Die obige Einschätzung wurde noch am Entscheidungstag bestätigt und umgesetzt — Kund:innen können Gruppen jetzt auch selbst verwalten (Kundenportal, /gruppen: routers/gruppen.py + zugehörige Templates), analog zu /struktur für OEs. Wie vorhergesagt war dafür keine Änderung an provisioning-server nötig — die Gruppen-API war von Anfang an organisationsgebunden und strukturell identisch zur OE-API. Der interne Admin-Zugang (/admin/kunden/{id}) bleibt zusätzlich bestehen, für Support und Onboarding durch den Betreiber; beide Oberflächen greifen auf dieselbe anode-API zu, ohne Konflikt. Die Einschränkung dieses ADRs auf „vorerst nur intern" ist damit überholt — Gruppen sind seither wie OEs Self-Service-fähig.

Details zum Datenmodell: 09-data-model-v1.md. Details zur bestehenden Auftragskatalog-Grundlage: ADR-0010, 12-feature-blueprint-model.md.