Dokumentiert nachträglich das Phase-4/5-Ergebnis des Self-Service-ISO- Plans (04.-07.08.2026, laut Memory 'Phasen 1-5 abgeschlossen', bislang komplett undokumentiert): Hintergrund-Thread-Orchestrierung in provisioning-server, iso_builds-Statustabelle, Alt-Build-Aufräumung wegen anodes begrenztem Plattenplatz, PSK-Verschlüsselung in Kundenplattforms eigener DB statt provisioning-server, getrennte Aufladen-/Neubau-Aktionen, gestreamter Download-Proxy. 13-live-provisioning-boot.md um den Mint/Casper-Payload-Mechanismus ergänzt (Pendant zum dort bereits beschriebenen Fedora/Dracut-Weg, inkl. des gefundenen Casper-ORDER-Bugs: neue Hook-Skriptnamen werden nie ausgeführt, nur das Überschreiben eines bereits referenzierten Pfads funktioniert). 09-data-model-v1.md um iso_builds als neues Kernobjekt ergänzt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
959 lines
24 KiB
Markdown
959 lines
24 KiB
Markdown
# Tuxflotte Datenmodell v1
|
|
|
|
## Zweck
|
|
|
|
Das Datenmodell beschreibt die persistenten Kernobjekte der Tuxflotte-Plattform und ihre Beziehungen.
|
|
|
|
Die konkrete SQL-Implementierung und das Migrationssystem werden getrennt von diesem fachlichen Modell behandelt.
|
|
|
|
## Kernobjekte
|
|
|
|
- Organization
|
|
- Organisationseinheit
|
|
- Gruppe
|
|
- Device
|
|
- Hardware Snapshot
|
|
- Network Interface
|
|
- Storage Device
|
|
- Workspace
|
|
- Kategorie
|
|
- Merkmal
|
|
- Backend
|
|
- Blueprint
|
|
- Bereitstellungsvorlage
|
|
- Assignment
|
|
- Auftragszuweisung
|
|
- Auftragsereignis
|
|
- Activation Code
|
|
- ISO Build
|
|
- Network Profile
|
|
- Secret Reference
|
|
|
|
`Network Profile` und `Secret Reference` sind weiterhin nur benannt, aber fachlich noch nicht spezifiziert — das bleibt bewusst außerhalb des aktuellen Arbeitsschritts (Provisioning-Server-Datenmodell für Workspace/Merkmal/Backend/Blueprint/Bereitstellungsvorlage).
|
|
|
|
## Organization
|
|
|
|
Eine Organization beschreibt eine organisatorische Einheit innerhalb der Tuxflotte-Plattform.
|
|
|
|
Eine Organization besitzt eigene Geräte, Workspaces, Netzwerkprofile und Richtlinien.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- name
|
|
- created_at
|
|
- updated_at
|
|
|
|
Beziehungen:
|
|
|
|
- besitzt mehrere Devices
|
|
- besitzt optional eigene Workspaces (zusätzlich zu global bereitgestellten Workspaces, siehe Workspace)
|
|
- besitzt mehrere Bereitstellungsvorlagen
|
|
- besitzt mehrere Activation Codes
|
|
- besitzt mehrere Network Profiles
|
|
- referenziert Secrets
|
|
- besitzt mehrere Organisationseinheiten
|
|
- besitzt mehrere Gruppen
|
|
|
|
## Organisationseinheit
|
|
|
|
Eine Organisationseinheit (OE) beschreibt einen organisatorischen Teilbereich innerhalb einer Organization, in dem Geräte verortet werden (zum Beispiel ein Gebäude oder eine Klasse). Organisationseinheiten bilden pro Organization einen Baum (siehe ADR-0012).
|
|
|
|
Jede Organization besitzt automatisch genau eine besondere Organisationseinheit (`ist_standard = true`), in der neu aktivierte Geräte landen, bevor sie manuell einsortiert werden. Diese Standard-Organisationseinheit ist vor Löschung geschützt.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- organization_id
|
|
- parent_id (optional; NULL bedeutet oberste Ebene direkt unter der Organization)
|
|
- name
|
|
- ist_standard (Standard: false)
|
|
- created_at
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einer Organization
|
|
- besitzt optional eine übergeordnete Organisationseinheit (parent_id)
|
|
- besitzt mehrere untergeordnete Organisationseinheiten
|
|
- besitzt mehrere Devices
|
|
- besitzt optional OE-Merkmal-Overrides
|
|
|
|
Constraints:
|
|
|
|
- (organization_id, parent_id, name) ist eindeutig
|
|
- höchstens eine Zeile je organization_id mit ist_standard = true
|
|
|
|
## Gruppe
|
|
|
|
Eine Gruppe beschreibt eine Querschnitts-Zuordnung von Geräten innerhalb einer Organization (zum Beispiel „Lehrer" oder „Schulleitung"), unabhängig von der Organisationseinheiten-Struktur (siehe ADR-0012). Anders als Organisationseinheiten sind Gruppen nicht verschachtelt, und ein Gerät kann mehreren Gruppen gleichzeitig angehören.
|
|
|
|
Gruppen sind wie Organisationseinheiten über das Kundenportal selbst verwaltbar (`/gruppen`), zusätzlich weiterhin über den internen Admin-Bereich (siehe ADR-0012, dort nachträglich ergänzt — ursprünglich als „vorerst nur intern" entschieden, noch am selben Tag auf Self-Service erweitert).
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- organization_id
|
|
- name
|
|
- created_at
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einer Organization
|
|
- besitzt mehrere Devices (Mitgliedschaft)
|
|
- besitzt optional Gruppen-Merkmal-Overrides
|
|
|
|
Constraints:
|
|
|
|
- (organization_id, name) ist eindeutig
|
|
|
|
## Device
|
|
|
|
Ein Device repräsentiert ein dauerhaft bekanntes physisches oder virtuelles Gerät.
|
|
|
|
Die interne Geräte-ID ist unabhängig von Hardwaremerkmalen.
|
|
|
|
Der Hardware-Fingerprint dient der Wiedererkennung während des Provisioning-Handshakes.
|
|
|
|
Ein Device kann deprovisioniert (Zugriff serverseitig entzogen, aber weiterhin sichtbar) und/oder archiviert (aus der aktiven Geräteliste ausgeblendet, „gelöscht" im Sinne des Kundenportals) sein — beides unabhängig voneinander und ohne den Datensatz oder seine Historie zu entfernen (siehe ADR-0013).
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- organization_id
|
|
- oe_id
|
|
- device_fingerprint
|
|
- hostname
|
|
- created_at
|
|
- last_seen
|
|
- deprovisioned_at (optional; NULL bedeutet aktiv provisioniert)
|
|
- archived_at (optional; NULL bedeutet nicht archiviert/gelöscht)
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einer Organization
|
|
- gehört zu genau einer Organisationseinheit
|
|
- gehört zu mehreren Gruppen
|
|
- besitzt mehrere Hardware Snapshots
|
|
- besitzt optional ein Assignment
|
|
|
|
## Hardware Snapshot
|
|
|
|
Ein Hardware Snapshot beschreibt den zu einem bestimmten Zeitpunkt erfassten Hardwarezustand eines Devices.
|
|
|
|
Hardware Snapshots sind zeitbezogene Inventardaten und nicht Bestandteil der stabilen Geräteidentität.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- device_id
|
|
- collected_at
|
|
- architecture
|
|
- manufacturer
|
|
- product_name
|
|
- product_version
|
|
- system_uuid
|
|
- system_serial
|
|
- board_vendor
|
|
- board_name
|
|
- board_serial
|
|
- bios_vendor
|
|
- bios_version
|
|
- boot_mode
|
|
- secure_boot
|
|
- tpm_version
|
|
- cpu_model
|
|
- cpu_logical_count
|
|
- memory_bytes
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einem Device
|
|
- besitzt mehrere Network Interfaces
|
|
- besitzt mehrere Storage Devices
|
|
|
|
## Network Interface
|
|
|
|
Ein Network Interface beschreibt eine zum Zeitpunkt des Hardware Snapshots vorhandene Netzwerkschnittstelle.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- hardware_snapshot_id
|
|
- name
|
|
- type
|
|
- mac_address
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einem Hardware Snapshot
|
|
|
|
## Storage Device
|
|
|
|
Ein Storage Device beschreibt einen zum Zeitpunkt des Hardware Snapshots vorhandenen Massenspeicher.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- hardware_snapshot_id
|
|
- model
|
|
- serial
|
|
- size_bytes
|
|
- transport
|
|
- name
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einem Hardware Snapshot
|
|
|
|
## Workspace
|
|
|
|
Ein Workspace beschreibt einen distributionsunabhängigen Arbeitsplatz-Zielzustand aus einer Menge von Merkmalen (siehe `02-workspace-model.md`).
|
|
|
|
Ein Workspace steht zunächst global bereit. Eine Organization kann zusätzlich eigene Workspaces definieren.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- organization_id (optional; NULL bedeutet global bereitgestellt)
|
|
- key
|
|
- name
|
|
- description
|
|
- created_at
|
|
- updated_at
|
|
|
|
Beziehungen:
|
|
|
|
- gehört optional zu genau einer Organization
|
|
- besteht aus mehreren Merkmalen
|
|
- wird in mehreren Bereitstellungsvorlagen referenziert
|
|
|
|
**Notiz für später (30.07.2026):** Ein Workspace ist zwar distributionsunabhängig benannt, aber nicht jedes Merkmal hat für jeden Backend ein Blueprint (siehe unten). Für den noch nicht gebauten, selbst-bedienten Workspace-Creator (Kunde stellt sich einen eigenen Workspace aus Merkmalen zusammen) folgt daraus eine UX-Reihenfolge, keine Schema-Änderung: **erst Backend wählen, dann Merkmale** — die Merkmalsauswahl im Creator sollte auf `blueprints`-Zeilen für den bereits gewählten Backend gefiltert sein, damit kein Workspace entsteht, der auf der gewünschten Distribution gar nicht realisierbar ist. Nicht dringend, betrifft nur den noch nicht priorisierten Self-Service-Teil (siehe [[project-tuxflotte-pilot-roadmap]]).
|
|
|
|
## Kategorie
|
|
|
|
Eine Kategorie gruppiert Merkmale, die im Auftragskatalog (siehe ADR-0010) zur geräteweisen Ad-hoc-Auswahl stehen, für die Darstellung in einer Katalog-Übersicht.
|
|
|
|
Eine Kategorie hat keine fachliche Wirkung auf die Anwendung eines Merkmals; sie dient ausschließlich der Organisation im Auftragskatalog.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- key
|
|
- name
|
|
- description
|
|
- sort_order
|
|
|
|
Beziehungen:
|
|
|
|
- wird von mehreren Merkmalen referenziert
|
|
|
|
Constraints:
|
|
|
|
- key ist eindeutig
|
|
|
|
## Merkmal
|
|
|
|
Ein Merkmal ist eine einzelne fachliche Eigenschaft eines Workspace, distributionsunabhängig benannt (siehe `12-feature-blueprint-model.md`).
|
|
|
|
Ein Merkmal kann zusätzlich zur Workspace-Zugehörigkeit für die geräteweise Ad-hoc-Zuweisung über den Auftragskatalog freigegeben sein (`im_auftragskatalog`, siehe ADR-0010, Auftragszuweisung unten). Das ist unabhängig davon, ob das Merkmal auch (oder ausschließlich) über einen Workspace zugewiesen wird.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- key
|
|
- name
|
|
- description
|
|
- kategorie_id (optional; nur relevant, wenn `im_auftragskatalog = true`)
|
|
- im_auftragskatalog (Standard: false)
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu mehreren Workspaces
|
|
- besitzt je Backend höchstens einen Blueprint
|
|
- gehört optional zu genau einer Kategorie
|
|
- wird optional mehreren Devices direkt zugewiesen (Auftragszuweisung)
|
|
|
|
## Backend
|
|
|
|
Ein Backend beschreibt die distributionsspezifische Umsetzung eines Workspace (siehe `04-backend-model.md`).
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- key
|
|
- name
|
|
- installer_type (zum Beispiel kickstart, autoinstall, calamares, preseed)
|
|
|
|
Beziehungen:
|
|
|
|
- besitzt Blueprints für Merkmale
|
|
- wird in mehreren Bereitstellungsvorlagen referenziert
|
|
|
|
## Blueprint
|
|
|
|
Ein Blueprint beschreibt die technische Umsetzung genau eines Merkmals für genau ein Backend (siehe `12-feature-blueprint-model.md`).
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- merkmal_id
|
|
- backend_id
|
|
- ansible_role
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einem Merkmal
|
|
- gehört zu genau einem Backend
|
|
|
|
Constraints:
|
|
|
|
- je Merkmal und Backend existiert höchstens ein Blueprint
|
|
|
|
## Bereitstellungsvorlage
|
|
|
|
Eine Bereitstellungsvorlage beschreibt eine von einer Organization vorkonfigurierte Kombination aus Workspace und Backend, einschließlich der installationszeitlichen Vorgaben, die kein Bestandteil eines Blueprints sind (siehe `03-organization-model.md`, `12-feature-blueprint-model.md`).
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- organization_id
|
|
- workspace_id
|
|
- backend_id
|
|
- label
|
|
- is_default
|
|
- disk_encryption
|
|
- partitioning
|
|
- secure_boot_required
|
|
- created_at
|
|
- updated_at
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einer Organization
|
|
- referenziert genau einen Workspace
|
|
- referenziert genau ein Backend
|
|
|
|
Constraints:
|
|
|
|
- höchstens eine Bereitstellungsvorlage je Organization mit `is_default = true`
|
|
|
|
## Assignment
|
|
|
|
Ein Assignment beschreibt die konkrete Zuordnung eines Device zu der Bereitstellungsvorlage, mit der es provisioniert wurde.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- device_id
|
|
- bereitstellungsvorlage_id
|
|
- created_at
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einem Device
|
|
- referenziert genau eine Bereitstellungsvorlage
|
|
|
|
Constraints:
|
|
|
|
- ein Device besitzt höchstens ein Assignment
|
|
|
|
## OE-Merkmal-Override
|
|
|
|
Ein OE-Merkmal-Override beschreibt, dass eine Organisationseinheit für ein katalogfähiges Merkmal eine explizite Meinung hat (`aktiv` oder `inaktiv`), die an die Geräte in ihr und ihren Unter-OEs weitervererbt wird, sofern dort nichts Spezifischeres gilt (siehe ADR-0012). Sparsam geführt: nur bei tatsächlich abweichender Meinung existiert eine Zeile.
|
|
|
|
Attribute:
|
|
|
|
- oe_id
|
|
- merkmal_id
|
|
- aktiv
|
|
- optionen
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einer Organisationseinheit
|
|
- referenziert genau ein Merkmal
|
|
|
|
Constraints:
|
|
|
|
- (oe_id, merkmal_id) ist Primärschlüssel
|
|
|
|
## Gruppen-Merkmal-Override
|
|
|
|
Ein Gruppen-Merkmal-Override beschreibt, dass eine Gruppe für ein katalogfähiges Merkmal eine explizite Meinung hat — strukturell identisch zum OE-Merkmal-Override, aber ohne Vererbungskette (Gruppen sind flach). Gehört ein Gerät mehreren Gruppen mit widersprüchlicher Einstellung zum selben Merkmal an, gilt „mehr gewinnt" (siehe ADR-0012).
|
|
|
|
Attribute:
|
|
|
|
- gruppe_id
|
|
- merkmal_id
|
|
- aktiv
|
|
- optionen
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einer Gruppe
|
|
- referenziert genau ein Merkmal
|
|
|
|
Constraints:
|
|
|
|
- (gruppe_id, merkmal_id) ist Primärschlüssel
|
|
|
|
## Auftragszuweisung
|
|
|
|
Eine Auftragszuweisung beschreibt, ob ein katalogfähiges Merkmal (`im_auftragskatalog = true`) für ein einzelnes Device aktuell ausgewählt ist — als Zeile unabhängig von der Workspace-Zugehörigkeit über die Bereitstellungsvorlage geführt (eigene Tabelle, siehe ADR-0010), aber nicht unabhängig in der Bedeutung: **fehlt** die Zeile, gilt als Default die Workspace-Zugehörigkeit (`present`, wenn das Merkmal Teil des zugewiesenen Workspace ist, sonst `absent`), durchlaufen von etwaigen OE-/Gruppen-Merkmal-Overrides (siehe ADR-0012) — der Auftragskatalog ist kein zweiter, von Workspaces losgelöster Pool, sondern dieselben Merkmale, aus denen auch Workspaces zusammengesetzt werden. Eine vorhandene Auftragszuweisungs-Zeile überschreibt den so ermittelten Default immer, in beide Richtungen — die geräteweise Entscheidung ist die spezifischste und bleibt in jedem Fall die letzte Instanz.
|
|
|
|
Anders als bei einem Assignment ist das Vorhandensein einer Zeile nicht gleichbedeutend mit „aktiv": Ab- und erneutes Zuwählen ändern das `aktiv`-Flag, statt die Zeile zu löschen und neu anzulegen, damit die Historie über das Ereignisprotokoll (Auftragsereignis) nachvollziehbar bleibt.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- device_id
|
|
- merkmal_id
|
|
- aktiv
|
|
- created_at
|
|
- updated_at
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einem Device
|
|
- referenziert genau ein Merkmal
|
|
|
|
Constraints:
|
|
|
|
- (device_id, merkmal_id) ist eindeutig
|
|
- merkmal_id muss auf ein Merkmal mit `im_auftragskatalog = true` verweisen (anwendungsseitig geprüft)
|
|
|
|
## Auftragsereignis
|
|
|
|
Ein Auftragsereignis ist ein unveränderlicher, anhängender Protokolleintrag zu einem Merkmal auf einem Device — sowohl für Auswahländerungen als auch für vom Provisioning Agent gemeldete Ausführungsergebnisse (siehe ADR-0010).
|
|
|
|
Ein einziges, generisches Ereignisprotokoll deckt beide Fälle über das `event_type`-Feld ab, damit künftige Ereignisarten keine neue Tabelle erfordern.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- device_id
|
|
- merkmal_id
|
|
- event_type (`selected`, `deselected`, `applied`, `apply_failed`, `removed`, `remove_failed`)
|
|
- detail (optional, strukturierte Zusatzinformation)
|
|
- occurred_at
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einem Device
|
|
- referenziert genau ein Merkmal
|
|
|
|
Constraints:
|
|
|
|
- keine (append-only, kein Unique-Constraint über die fachlichen Spalten)
|
|
|
|
## Activation Code
|
|
|
|
Ein Activation Code autorisiert den initialen Provisionierungsvorgang eines Geräts und bestimmt die zugeordnete Organization (siehe `08-provisioning-api.md`, `11-device-enrollment.md`).
|
|
|
|
Der Activation Code ist laut `11-device-enrollment.md` ein Übergangsmechanismus und wird langfristig durch Enrollment Sessions ersetzt.
|
|
|
|
Attribute:
|
|
|
|
- code
|
|
- organization_id
|
|
- active
|
|
- created_at
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einer Organization
|
|
|
|
## ISO Build
|
|
|
|
Ein ISO Build beschreibt einen Bauvorgang einer personalisierten Kunden-Installations-ISO (siehe ADR-0014, `13-live-provisioning-boot.md`). Läuft als Hintergrund-Thread in `provisioning-server`, diese Tabelle ist dessen Status-Speicher.
|
|
|
|
Nach jedem erfolgreichen Bau werden ältere ISO Builds derselben Organisation aufgeräumt (begrenzter Plattenplatz auf anode) — ein ISO Build ist damit kein dauerhaftes Archiv, sondern Status des jeweils aktuellen bzw. zuletzt versuchten Baus.
|
|
|
|
Attribute:
|
|
|
|
- id
|
|
- organization_id
|
|
- status (`pending`, `running`, `completed`, `failed`)
|
|
- output_filename (optional)
|
|
- error_message (optional)
|
|
- created_at
|
|
- started_at (optional)
|
|
- finished_at (optional)
|
|
|
|
Beziehungen:
|
|
|
|
- gehört zu genau einer Organization
|
|
|
|
Constraints:
|
|
|
|
- status ist eine der vier definierten Ausprägungen
|
|
|
|
## Relationales Schema v1
|
|
|
|
### organizations
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- name
|
|
- created_at
|
|
- updated_at
|
|
|
|
### organisationseinheiten
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- organization_id
|
|
- parent_id (nullable)
|
|
- name
|
|
- ist_standard (Standard: false)
|
|
- created_at
|
|
|
|
Beziehungen:
|
|
|
|
- organization_id referenziert organizations.id
|
|
- parent_id referenziert organisationseinheiten.id (optional)
|
|
|
|
Constraints:
|
|
|
|
- (organization_id, parent_id, name) ist eindeutig
|
|
- höchstens eine Zeile je organization_id mit ist_standard = true (partieller Unique-Index)
|
|
|
|
### gruppen
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- organization_id
|
|
- name
|
|
- created_at
|
|
|
|
Beziehungen:
|
|
|
|
- organization_id referenziert organizations.id
|
|
|
|
Constraints:
|
|
|
|
- (organization_id, name) ist eindeutig
|
|
|
|
### device_gruppen
|
|
|
|
Spalten:
|
|
|
|
- device_id
|
|
- gruppe_id
|
|
|
|
Beziehungen:
|
|
|
|
- device_id referenziert devices.id
|
|
- gruppe_id referenziert gruppen.id
|
|
|
|
Constraints:
|
|
|
|
- (device_id, gruppe_id) ist Primärschlüssel
|
|
|
|
### oe_merkmale
|
|
|
|
Spalten:
|
|
|
|
- oe_id
|
|
- merkmal_id
|
|
- aktiv
|
|
- optionen
|
|
|
|
Beziehungen:
|
|
|
|
- oe_id referenziert organisationseinheiten.id
|
|
- merkmal_id referenziert merkmale.id
|
|
|
|
Constraints:
|
|
|
|
- (oe_id, merkmal_id) ist Primärschlüssel
|
|
|
|
### gruppen_merkmale
|
|
|
|
Spalten:
|
|
|
|
- gruppe_id
|
|
- merkmal_id
|
|
- aktiv
|
|
- optionen
|
|
|
|
Beziehungen:
|
|
|
|
- gruppe_id referenziert gruppen.id
|
|
- merkmal_id referenziert merkmale.id
|
|
|
|
Constraints:
|
|
|
|
- (gruppe_id, merkmal_id) ist Primärschlüssel
|
|
|
|
### devices
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- organization_id
|
|
- oe_id
|
|
- device_fingerprint
|
|
- hostname
|
|
- created_at
|
|
- last_seen
|
|
- deprovisioned_at (nullable)
|
|
- archived_at (nullable)
|
|
|
|
Beziehungen:
|
|
|
|
- organization_id referenziert organizations.id
|
|
- oe_id referenziert organisationseinheiten.id
|
|
|
|
Constraints:
|
|
|
|
- device_fingerprint ist eindeutig
|
|
|
|
### hardware_snapshots
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- device_id
|
|
- collected_at
|
|
- architecture
|
|
- manufacturer
|
|
- product_name
|
|
- product_version
|
|
- system_uuid
|
|
- system_serial
|
|
- board_vendor
|
|
- board_name
|
|
- board_serial
|
|
- bios_vendor
|
|
- bios_version
|
|
- boot_mode
|
|
- secure_boot
|
|
- tpm_version
|
|
- cpu_model
|
|
- cpu_logical_count
|
|
- memory_bytes
|
|
|
|
Beziehungen:
|
|
|
|
- device_id referenziert devices.id
|
|
|
|
### network_interfaces
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- hardware_snapshot_id
|
|
- name
|
|
- type
|
|
- mac_address
|
|
|
|
Beziehungen:
|
|
|
|
- hardware_snapshot_id referenziert hardware_snapshots.id
|
|
|
|
### storage_devices
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- hardware_snapshot_id
|
|
- name
|
|
- model
|
|
- serial
|
|
- size_bytes
|
|
- transport
|
|
|
|
Beziehungen:
|
|
|
|
- hardware_snapshot_id referenziert hardware_snapshots.id
|
|
|
|
### workspaces
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- organization_id (nullable)
|
|
- key
|
|
- name
|
|
- description
|
|
- created_at
|
|
- updated_at
|
|
|
|
Beziehungen:
|
|
|
|
- organization_id referenziert organizations.id (optional)
|
|
|
|
Constraints:
|
|
|
|
- (organization_id, key) ist eindeutig
|
|
|
|
### kategorien
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- key
|
|
- name
|
|
- description
|
|
- sort_order
|
|
|
|
Constraints:
|
|
|
|
- key ist eindeutig
|
|
|
|
### merkmale
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- key
|
|
- name
|
|
- description
|
|
- kategorie_id (nullable)
|
|
- im_auftragskatalog (Standard: false)
|
|
|
|
Beziehungen:
|
|
|
|
- kategorie_id referenziert kategorien.id (optional)
|
|
|
|
Constraints:
|
|
|
|
- key ist eindeutig
|
|
|
|
### workspace_merkmale
|
|
|
|
Spalten:
|
|
|
|
- workspace_id
|
|
- merkmal_id
|
|
|
|
Beziehungen:
|
|
|
|
- workspace_id referenziert workspaces.id
|
|
- merkmal_id referenziert merkmale.id
|
|
|
|
Constraints:
|
|
|
|
- (workspace_id, merkmal_id) ist Primärschlüssel
|
|
|
|
### backends
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- key
|
|
- name
|
|
- installer_type
|
|
|
|
Constraints:
|
|
|
|
- key ist eindeutig
|
|
|
|
### blueprints
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- merkmal_id
|
|
- backend_id
|
|
- ansible_role
|
|
|
|
Beziehungen:
|
|
|
|
- merkmal_id referenziert merkmale.id
|
|
- backend_id referenziert backends.id
|
|
|
|
Constraints:
|
|
|
|
- (merkmal_id, backend_id) ist eindeutig
|
|
|
|
### bereitstellungsvorlagen
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- organization_id
|
|
- workspace_id
|
|
- backend_id
|
|
- label
|
|
- is_default
|
|
- disk_encryption
|
|
- partitioning
|
|
- secure_boot_required
|
|
- created_at
|
|
- updated_at
|
|
|
|
Beziehungen:
|
|
|
|
- organization_id referenziert organizations.id
|
|
- workspace_id referenziert workspaces.id
|
|
- backend_id referenziert backends.id
|
|
|
|
Constraints:
|
|
|
|
- höchstens eine Zeile je organization_id mit is_default = true (partieller Unique-Index)
|
|
|
|
### assignments
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- device_id
|
|
- bereitstellungsvorlage_id
|
|
- created_at
|
|
|
|
Beziehungen:
|
|
|
|
- device_id referenziert devices.id
|
|
- bereitstellungsvorlage_id referenziert bereitstellungsvorlagen.id
|
|
|
|
Constraints:
|
|
|
|
- device_id ist eindeutig
|
|
|
|
### device_merkmale
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- device_id
|
|
- merkmal_id
|
|
- aktiv
|
|
- created_at
|
|
- updated_at
|
|
|
|
Beziehungen:
|
|
|
|
- device_id referenziert devices.id
|
|
- merkmal_id referenziert merkmale.id
|
|
|
|
Constraints:
|
|
|
|
- (device_id, merkmal_id) ist eindeutig
|
|
|
|
### device_merkmal_events
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- device_id
|
|
- merkmal_id
|
|
- event_type
|
|
- detail (nullable)
|
|
- occurred_at
|
|
|
|
Beziehungen:
|
|
|
|
- device_id referenziert devices.id
|
|
- merkmal_id referenziert merkmale.id
|
|
|
|
### activation_codes
|
|
|
|
Spalten:
|
|
|
|
- code
|
|
- organization_id
|
|
- active
|
|
- created_at
|
|
|
|
Beziehungen:
|
|
|
|
- organization_id referenziert organizations.id
|
|
|
|
Constraints:
|
|
|
|
- code ist Primärschlüssel
|
|
|
|
### iso_builds
|
|
|
|
Spalten:
|
|
|
|
- id
|
|
- organization_id
|
|
- status (Standard: pending)
|
|
- output_filename (nullable)
|
|
- error_message (nullable)
|
|
- created_at
|
|
- started_at (nullable)
|
|
- finished_at (nullable)
|
|
|
|
Beziehungen:
|
|
|
|
- organization_id referenziert organizations.id
|
|
|
|
Constraints:
|
|
|
|
- status ist eine von pending/running/completed/failed (CHECK-Constraint)
|
|
|
|
## Beziehungskonsequenzen
|
|
|
|
Wird eine Organization gelöscht, dürfen zugehörige Devices nicht implizit mitgelöscht werden.
|
|
|
|
Wird ein Device gelöscht, werden zugehörige Hardware Snapshots mitgelöscht.
|
|
|
|
Wird ein Hardware Snapshot gelöscht, werden zugehörige Network Interfaces und Storage Devices automatisch mitgelöscht.
|
|
|
|
Wird eine Organization gelöscht, dürfen ihre Bereitstellungsvorlagen und Activation Codes nicht implizit erhalten bleiben — sie verlieren mit der Organization ihre Grundlage.
|
|
|
|
Wird ein Workspace, ein Backend oder ein Merkmal gelöscht, das noch von einer Bereitstellungsvorlage beziehungsweise einem Blueprint referenziert wird, muss das gesperrt werden, um Bereitstellungsvorlagen nicht unbemerkt ungültig zu machen.
|
|
|
|
Wird ein Device gelöscht, wird sein Assignment mitgelöscht. Wird eine Bereitstellungsvorlage gelöscht, auf die noch ein Assignment verweist, muss das gesperrt werden.
|
|
|
|
Wird ein Device gelöscht, werden seine Auftragszuweisungen und Auftragsereignisse mitgelöscht (konsistent mit dem Umgang mit Hardware Snapshots). Wird ein Merkmal gelöscht, das noch von einer Auftragszuweisung oder einem Auftragsereignis referenziert wird, muss das gesperrt werden. Wird eine Kategorie gelöscht, verlieren zugehörige Merkmale lediglich ihre Kategoriezuordnung; sie bleiben davon unabhängig im Auftragskatalog bestehen.
|
|
|
|
**Notiz für später (03.08.2026):** Das Kaskadieren des Auftragsereignis-Protokolls bei Device-Löschung folgt bewusst dem bestehenden Muster (siehe Hardware Snapshot), ist aber im Sinne einer lückenlosen Historie eine Abwägung, keine zwingende Konsequenz — ein gelöschtes Device nimmt damit auch seine Ausführungshistorie mit. Sollte künftig eine Anforderung entstehen, Auftragshistorie auch nach Device-Löschung aufzubewahren (zum Beispiel für Audit-Zwecke über die Gerätelebensdauer hinaus), ist das eine Änderung der Löschregel für `device_merkmal_events.device_id` (z. B. auf `ON DELETE SET NULL` mit einer zusätzlichen, vom Device losgelösten Identifikationsspalte), keine Änderung an der Ereignis-Tabellenstruktur selbst.
|
|
|
|
Wird eine Organisationseinheit gelöscht, die noch Unter-OEs oder zugeordnete Devices besitzt, muss das gesperrt werden (anwendungsseitig geprüft, siehe ADR-0012) — anders als bei Hardware Snapshots ist ein implizites Mitlöschen der zugeordneten Geräte hier nie gewollt. Die Standard-OE einer Organisation (`ist_standard = true`) ist zusätzlich unabhängig vom Inhalt gegen Löschung gesperrt.
|
|
|
|
Wird eine Gruppe gelöscht, wird ihre Mitgliedschafts- und Merkmal-Override-Zuordnung mitgelöscht; die zugeordneten Devices selbst bleiben unberührt.
|
|
|
|
De-/Reprovisionierung und Archivierung eines Devices (siehe ADR-0013) sind reine Spaltenänderungen (`deprovisioned_at`, `archived_at`), kein Löschvorgang — sie lösen keine der hier beschriebenen Kaskaden aus, alle Beziehungen und Historie eines Devices bleiben davon unberührt.
|
|
|
|
Für die relationale Umsetzung gilt daher:
|
|
|
|
- devices.organization_id → ON DELETE RESTRICT
|
|
- devices.oe_id → ON DELETE RESTRICT
|
|
- organisationseinheiten.organization_id → ON DELETE CASCADE
|
|
- organisationseinheiten.parent_id → ON DELETE RESTRICT
|
|
- gruppen.organization_id → ON DELETE CASCADE
|
|
- device_gruppen.device_id → ON DELETE CASCADE
|
|
- device_gruppen.gruppe_id → ON DELETE CASCADE
|
|
- oe_merkmale.oe_id → ON DELETE CASCADE
|
|
- oe_merkmale.merkmal_id → ON DELETE RESTRICT
|
|
- gruppen_merkmale.gruppe_id → ON DELETE CASCADE
|
|
- gruppen_merkmale.merkmal_id → ON DELETE RESTRICT
|
|
- hardware_snapshots.device_id → ON DELETE CASCADE
|
|
- network_interfaces.hardware_snapshot_id → ON DELETE CASCADE
|
|
- storage_devices.hardware_snapshot_id → ON DELETE CASCADE
|
|
- workspaces.organization_id → ON DELETE CASCADE
|
|
- workspace_merkmale.workspace_id → ON DELETE CASCADE
|
|
- workspace_merkmale.merkmal_id → ON DELETE RESTRICT
|
|
- merkmale.kategorie_id → ON DELETE SET NULL
|
|
- blueprints.merkmal_id → ON DELETE CASCADE
|
|
- blueprints.backend_id → ON DELETE CASCADE
|
|
- bereitstellungsvorlagen.organization_id → ON DELETE CASCADE
|
|
- bereitstellungsvorlagen.workspace_id → ON DELETE RESTRICT
|
|
- bereitstellungsvorlagen.backend_id → ON DELETE RESTRICT
|
|
- assignments.device_id → ON DELETE CASCADE
|
|
- assignments.bereitstellungsvorlage_id → ON DELETE RESTRICT
|
|
- device_merkmale.device_id → ON DELETE CASCADE
|
|
- device_merkmale.merkmal_id → ON DELETE RESTRICT
|
|
- device_merkmal_events.device_id → ON DELETE CASCADE
|
|
- device_merkmal_events.merkmal_id → ON DELETE RESTRICT
|
|
- activation_codes.organization_id → ON DELETE CASCADE
|
|
- iso_builds.organization_id → ON DELETE CASCADE
|
|
|
|
## ID-Erzeugung
|
|
|
|
Persistente Plattformobjekte verwenden UUIDs als interne IDs.
|
|
|
|
UUIDs werden durch die Anwendung erzeugt.
|
|
|
|
Die Datenbank validiert und speichert die IDs, erzeugt sie jedoch nicht selbst.
|
|
|
|
Dadurch stehen Objekt-IDs bereits vor dem Datenbank-INSERT zur Verfügung und können innerhalb einer Transaktion für abhängige Datensätze verwendet werden.
|