Commit Graph
100 Commits
Author SHA1 Message Date
adminandClaude Opus 5.5 536fb47e66 Prüfroutine Secure Boot: Firmware-Stand aus Installer und Agent, Einstufung secure_boot_stufe()
Migration 0079: Setup Mode und Drittanbieter-CA im Hardware-Snapshot,
firmware_* an devices aus dem Agent-Check-in. Gerätelisten und
Hardware-Endpunkt liefern firmware + secure_boot_stufe.
platform-docs roadmap/secure-boot-verschluesselung.md Schritt 3

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 18:47:04 +01:00
adminandClaude Opus 5.5 8c9c2ce040 Migration 0078: Merkmal Kiosk (Mint, Debian)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 13:52:14 +01:00
adminandClaude Opus 5.5 ec0ea8a777 Migration 0077: elf neue App-Merkmale, Teams als Webapp-Vorlage
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 09:25:03 +01:00
adminandClaude Opus 5.5 2e855f3572 Neue Organisationen: Gerätenamen-Präfix aus dem Namen, zwei Stellen
Erstkontakt-Probelauf 25.10.2026: neue Organisationen hatten kein Präfix,
Geräte hießen tuxflotte-0001. Jetzt beim Anlegen hostname_praefix aus dem
Namen (Kleinbuchstaben, Umlaute ausgeschrieben, a-z0-9-, höchstens 20
Zeichen) und hostname_stellen 2 (Nutzerwunsch, vorerst). Bestehende
Organisationen unverändert. Neuinstallation erkennt jetzt auch Namen mit
mehr Ziffern als "stellen" (ab dem 100. Gerät), statt umzubenennen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 17:33:11 +01:00
adminandClaude Opus 5.5 917054bf00 Organisation archivieren (Entscheidung A, 25.10.2026)
Bisher ließen sich Organisationen gar nicht entfernen. Jetzt archivieren:
nur ohne aktive Geräte; Medien (enrollment_sessions) widerrufen,
Aktivierungscodes deaktiviert, laufende Einladungen zur Personalisierung
zurückgezogen; die Organisation fehlt danach in der Liste und im
Admin-Dashboard. Daten bleiben erhalten (Migration 0076, archived_at).
Endgültiges Löschen später als eigener Punkt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 17:28:33 +01:00
adminandClaude Opus 5.5 d76fdad01a Personalisierung: Sperre durch eine Neu-Einladung endet mit der Einladung
Befund Erstkontakt 25.10.2026: Eine neue Einladung ohne "Bestehenden
Zugang behalten" sperrte das Konto sofort (auch am Bildschirmschoner einer
laufenden Sitzung); Zurückziehen hob die Sperre nicht auf. Jetzt merkt sich
das Konto die sperrende Einladung (Migration 0075, gesperrt_durch). Wird
sie zurückgezogen, ersetzt, läuft ab oder scheitert am Gerät, ist das
Konto wieder frei; eine ersetzende Einladung übernimmt die Sperre. Von
Hand gesperrte Konten bleiben gesperrt. Die Liste meldet
gesperrt_durch_einladung.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:31:41 +01:00
adminandClaude Opus 5.5 a6f5021d40 Spiegel: Schlüssel stabil/vorab statt der Ausrollstufen testing/vorab
Seit 5210186 (Ausrollstufe stabil heißt testing) prüften Spiegel-Bau und
stand.json-Laden gegen AUSROLLSTUFEN. Der Spiegel heißt aber weiter
"stabil", sein Archiv wurde nicht mehr gebaut und Geräte von
Testing-Organisationen fielen auf den Git-Weg (ansible-content-stabil über
Gitea) zurück. Gefunden am frisch installierten Gerät im
Erstkontakt-Probelauf (ansible_weg=git).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:46:01 +01:00
adminandClaude Opus 5.5 a4d9d7e2fe Gelöschtes Gerät einer anderen Organisation gibt den Fingerabdruck frei
Beim Erstkontakt-Probelauf blockierte das in Liebherr archivierte
Liebherr-83 die Neuinstallation derselben Hardware für eine neue
Organisation. Der alte Datensatz bleibt als Verlauf, sein Fingerabdruck
bekommt das Suffix :archiv:<id>. Aktive Geräte anderer Organisationen
bleiben weiterhin gesperrt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:30:37 +01:00
adminandClaude Opus 5.5 9a7b20b6a5 Einstieg Schritt 4: Dashboard-Angaben für Erste Schritte, Meldungen mit Standort/Zweck statt OE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:47:34 +01:00
adminandClaude Opus 5.5 efb2c0b65f Einstieg Schritt 3: Installation (Bereitstellungsvorlage) aus der Ziel-OE wählen, wenn keine angegeben
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:44:19 +01:00
adminandClaude Opus 5.5 dd5c5629f3 Einstieg Schritt 2: WLAN der Organisation als Einstellung, an alle Geräte (Rolle org-wlan)
Migration 0074: organizations.org_wlan (Optionen der Rolle, Passwort
verschlüsselt). GET/PUT /api/v1/organizations/{id}/org-wlan; im
Auftragskatalog gilt es für org-wlan, solange OE/Gruppe nichts festlegt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:41:05 +01:00
adminandClaude Opus 5.5 5210186126 Einstieg Schritt 1: Art der Organisation bringt Standard-Workspace mit, Ausrollstufe stabil heißt testing
Migration 0073: kundengruppen.standard_workspace_id (Schule: Schulcomputer
(Mint)); neue Organisationen bekommen Bereitstellungsvorlage und Workspace an
"Neue Geräte". Ausrollstufe 'stabil' -> 'testing' (Repo/Spiegel bleiben).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:36:55 +01:00
adminandClaude Opus 5.5 2a734497ed Passwort vergessen: Konto aus dem QR-Code (ADR-0041, 25.10.2026)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 10:36:06 +01:00
adminandClaude Opus 5.5 da44fd1c6a Passwort vergessen per Adresse (ADR-0041, 24.10.2026)
Je eingerichtetem Konto mit der Adresse ein Link, auch auf mehreren
Geräten; Begrenzung je Konto mit dem Kiosk-Weg geteilt, Konten an der
Grenze still übergangen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 11:09:56 +02:00
adminandClaude Opus 5.5 bcfe411290 Personalisierung per Einladung statt Aktivierungscode (ADR-0041, 24.10.2026)
Kunden-Admin trägt die Adresse ein (nur mit Merkmal), der Link (7 Tage,
einmalig) führt zu Anmeldename und Passwort; Stand-Seite per abgeleitetem
Token. Migration 0072: Stand eingeladen, Code-Spalten optional, laufende
Codes zurückgezogen. Code-Endpunkte entfernt; Passwort-vergessen-Kiosk
bleibt bis zur Umstellung der Rolle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 10:52:14 +02:00
adminandClaude Opus 5.5 2f6dfd585b Ausgegebene Medien löschen, Gerät löschen deprovisioniert zusätzlich
DELETE /api/v1/organizations/<org>/enrollment-sessions/<id> entfernt nur
nicht mehr nutzbare Medien (widerrufen, abgelaufen, aufgebraucht).
archive_device() entzieht jetzt auch das Agent-Secret: ein gelöschtes Gerät
checkte bisher weiter ein (Liebherr-47, 03.10.2026).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 07:49:53 +02:00
adminandClaude Opus 5.5 5284bb470b README: Deploy über die anode-Wrapper, Plattform-Ereignisse
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 17:32:46 +02:00
adminandClaude Opus 5.5 844faa2aec Dashboard: Ampel je Gerät, Plattform-Ereignisse (Migration 0071)
_geraete_ampel(): rot bei Fehlern im letzten gemeldeten Lauf oder Platte
>= 95 %, gelb bei knappen Ressourcen oder länger/nie nicht gemeldet, mit
Gründen; für Kunden- und Admin-Dashboard. Tabelle plattform_ereignisse:
neue Stände vorab/stabil schreibt der Spiegel-Thread, Deploy/Migration/
Boot-Medium die Wrapper auf anode. Admin-Dashboard liefert die letzten 30.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 17:23:03 +02:00
adminandClaude Opus 5.5 10f5030995 Webapps standardmäßig nur im Menü, Desktop-Symbol per Häkchen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 15:01:53 +02:00
adminandClaude Opus 5.5 fe72c401c4 Migration 0069: Beschreibung des Merkmals Veyon für Kunden
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 11:30:09 +02:00
adminandClaude Opus 5.5 b8f3b25bda Agent-Fassung "freigegeben": die in der Ausrollstufe festgelegte (ADR-0046 Schritt 3)
Für postinstall.sh: liest tuxflotte_agent_commit aus roles/agent/defaults/main.yml
im aktuellen Spiegel-Stand der Stufe des Geräts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 09:52:50 +02:00
adminandClaude Opus 5.5 999b197dd5 Check-in speichert ansible_weg (ADR-0046 Schritt 2), Migration 0068
Der Agent meldet seit 54f76f1, ob er den Ansible-Stand als Archiv von
anode, per Git oder per Git-Rückfall bezogen hat. Nur die drei bekannten
Werte werden gespeichert; Gerätelisten liefern das Feld mit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 09:40:42 +02:00
adminandClaude Opus 5.5 4e1fae12d0 Spiegel: geladenen Stand beim Start melden
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:30:27 +02:00
adminandClaude Opus 5.5 a54c21c7b2 Spiegel-Meldungen sofort ins Journal (stdout ist unter systemd gepuffert)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:30:20 +02:00
adminandClaude Opus 5.5 2fae14cfe0 ADR-0046 Schritt 1: Spiegel auf anode, Archiv je Stand, ansible_stand im Check-in
- Hintergrund-Thread spiegelt ansible-content (vorab), -stabil und
  provisioning-agent alle 60 s nach data/spiegel, Archiv (tar.gz + SHA-256)
  je Stand, die letzten drei je Stufe bleiben abrufbar
- Check-in liefert zusätzlich ansible_stand {commit, sha256}; ansible_repo
  bleibt als Rückfall
- GET /api/v1/agent/ansible/<commit>.tar.gz und
  /api/v1/agent/fassung/<commit>/<datei> nur mit Agent-Secret
  (Authorization + X-Tuxflotte-Geraet), nur zustehende Stände

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:28:15 +02:00
adminandClaude Opus 5.5 d90ce99180 Org-Ressourcen für alle Organisationen freischalten
Rollen sind in ansible-content-stabil (c219e3b) freigegeben.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:19:46 +02:00
adminandClaude Opus 5.5 a7d22412b8 API-Doku (/docs, /redoc, /openapi.json) abschalten, Fedora-Kickstart-Endpunkt entfernen
Beides war über anode.tuxflotte.de ohne Anmeldung erreichbar (Durchsicht
18.10.2026, ADR-0046 Abschnitt 'Unabhängig davon'). Health-Check des
Deploys läuft seit infra 7c7069b über /health.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 18:20:14 +02:00
adminandClaude Opus 5.5 fc4e2c34b2 Merge branch 'passwort-vergessen'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:30:17 +02:00
adminandClaude Opus 5.5 46b875ea7e Personalisierung: Passwort vergessen per Mail-Link, Modus im Check-in, Admin-Reset ohne Änderungszwang (Migration 0067, ADR-0041 18.10.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:26:35 +02:00
adminandClaude Opus 5.5 7d889b9a61 Merge branch 'passwort-reset'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 10:00:22 +02:00
adminandClaude Opus 5.5 6ea1f876e5 Personalisierung: Passwort-Reset durch die Verwaltung (Migration 0066, ADR-0041 18.10.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 09:57:54 +02:00
adminandClaude Opus 5.5 2a8514a1a0 Merge branch 'personalisierung-ausblenden'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 09:35:58 +02:00
adminandClaude Opus 5.5 7d4812b3dc Personalisierung: Option anmeldung_anbieten im Check-in (ADR-0041, 18.10.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 09:32:50 +02:00
adminandClaude Opus 5.5 53b60ad05a Merge branch 'personalisierung-merkmal'
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 17:02:33 +02:00
adminandClaude Opus 5.5 b4c77689fd Personalisierung Schritt 3: Konten im Check-in, Rückmeldung des Agents, Sperren, Neuinstallation
Check-in liefert persoenliche_konten (anlegen mit Hash, aktiv, sperren,
entfernen). /api/v1/agent/persoenliche-konten nimmt die Ergebnisse an:
angelegt löscht den Hash und merkt ohne "Bestehenden Zugang behalten" die
übrigen Konten zum Entfernen vor. Ein Code ohne Kästchen sperrt bestehende
Konten sofort. Sperren/Entsperren je Konto. Eine Neuinstallation beendet
alle Personalisierungen des Geräts. Migration 0065 um gesperrt, entfernen,
geraet_meldung und Status fehlgeschlagen ergänzt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:55:51 +02:00
adminandClaude Opus 5.5 e12f2206a4 Personalisierung: Code prüfen ohne Verbrauch (für das zweistufige Formular)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:32:08 +02:00
adminandClaude Opus 5.5 327bf948df Personalisierung Schritt 2: Aktivierungscode, Einreichen, Bestätigen, E-Mail-Domänen (Migration 0065)
Code je Gerät (7 Tage, nur Hash gespeichert), Einreichen mit Domänen- und
Anmeldenamenprüfung (Passwort kommt nur als SHA-512-crypt), Bestätigung
binnen einer Stunde, verfallene Vorgänge verlieren Hash und Adresse. Die
Platzhalterseite /personalisierung entfällt, das Formular liegt in der
Kundenplattform.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:28:18 +02:00
adminandClaude Opus 5.5 90586094f0 Migration Personalisierung auf 0064 (0062/0063 inzwischen auf main belegt)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:01:27 +02:00
adminandClaude Opus 5.5 e72d9da725 Merkmal personalisierung (Migration 0062) und Hinweisseite /personalisierung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:01:27 +02:00
admin 46ec2f5151 Merge branch 'veyon-schluessel' 2026-10-15 14:06:41 +02:00
adminandClaude Opus 5.5 960c4cb092 Migration 0063: Merkmal fileserver heisst Gemeinsame Ablage (eingebunden)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 13:58:16 +02:00
adminandClaude Opus 5.5 a49252a81a Veyon: Schluesselpaar je OE, Check-in reichert Optionen an (Migration 0063)
Bauplan Schritt 1 (platform-docs roadmap/veyon-schluesselverteilung-
diskussion-2026-10-14.md). Paar beim ersten Bedarf erzeugt (RSA 4096,
PKCS#8/SPKI-PEM wie veyon-cli), privat Fernet-verschluesselt. Optionen:
veyon_schluesselname, veyon_public_pem, veyon_raum, veyon_lehrer; nur
Lehrergeraete zusaetzlich veyon_private_pem und veyon_rechner
(<hostname>.local, ohne sich selbst). Lehrer = Haekchen veyon_lehrer an
irgendeiner aktiven Gruppe. Fehler brechen den Check-in nicht ab.
Getestet gegen eine Wegwerf-Datenbank mit allen Migrationen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 13:55:51 +02:00
adminandClaude Opus 5.5 ed145be3d2 Org-Ressourcen: Tabellen, API und Auftrag org-ressourcen im Check-in (Migration 0062)
Ressourcen (Mail, Nextcloud, ownCloud, WebDAV, SMB, Web-Proxy) gehoeren zur
Organisation und wirken fuer die ganze Org, OEs samt Unter-OEs oder
Geraetegruppen. Keine Zugangsdaten: unbekannte Felder werden verworfen.
Der Check-in schickt die fuer das Geraet geltenden Ressourcen (spezifisch
zuerst) als Auftrag org-ressourcen, vorerst nur fuer Organisationen mit
Ausrollstufe vorab (ORG_RESSOURCEN_NUR_VORAB).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 12:57:38 +02:00
adminandClaude Opus 5.5 413d9a4795 Migration 0061: Merkmal org-wlan (systemweites WLAN fuer alle Benutzer)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:31:24 +02:00
adminandClaude Opus 5.5 4ff3c99bee Agent-Fassung je Gerät: SHA-256 der agent.py beim Check-in speichern (Migration 0060)
Nachtrag zu ADR-0044: Ob ein Gerät die über die Rolle agent freigegebene
Fassung übernommen hat, war aus der Ferne nicht sichtbar. Ältere Agenten
schicken nichts (Wert bleibt stehen), ungültige Werte werden verworfen
statt den Check-in abzulehnen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:46:13 +02:00
adminandClaude Opus 5.5 48ebac7576 Kundengruppe je Organisation beim Anlegen und nachträglich setzen
Neue Organisationen bekamen keine Kundengruppe (nur die Rückfüllung in
Migration 0050 hatte sie gesetzt) und sahen dadurch keine Vorlagen mit
Sichtbarkeit kundengruppe. Liste/Detail liefern die Kundengruppe mit,
POST /organizations nimmt sie an, PUT .../kundengruppe ändert sie.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 08:50:43 +02:00
adminandClaude Opus 5.5 0c268e9088 Gestuftes Ausrollen: Ausrollstufe je Organisation (Migration 0059)
Der Check-in liefert Organisationen mit Stufe "stabil" die Adresse des
freigegebenen Repos (ansible-content-stabil), "vorab" die von main. Neue
Organisationen sind stabil; Default Lab, Liebherr und WLAN-Test vorab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 16:57:20 +02:00
adminandClaude Opus 5.5 26e26e1b3b Standardbrowser je Workspace-Version (Migration 0058)
Vorgabe im Entwurf setzen (Firefox oder ein im Entwurf enthaltener
Browser), wird mit kopiert, faellt beim Entfernen des Browsers zurueck und
steht in der Wirkungsvorschau. Der Check-in liefert sie als eigenen Auftrag
"standardbrowser" (kein Katalog-Merkmal); dessen Rueckmeldung erzeugt keine
Ereigniszeile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 15:10:30 +02:00
adminandClaude Opus 5.5 381e0e55c1 Hostname: Standardpräfix tuxflotte statt des vom Boot-Medium gemeldeten Namens
Ohne eigene Hostnamenkonvention übernahm der Server den vom Client
gemeldeten Namen. Der Client ist das Live-System des Boot-Mediums, also
hieß jedes Gerät "debian" (auch das erste Kundengerät). Jetzt vergibt der
Server immer selbst, ohne eigenen Präfix als tuxflotte-<Nummer>. Bekannte
Geräte mit unpassendem Namen bekommen ihn bei der nächsten Neuinstallation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 13:47:59 +02:00
adminandClaude Opus 5.5 ea00480df1 Bereitstellungsvorlagen: archivierte Geraete/abgelaufene Medien zaehlen nicht als Nutzung
Nutzung und Loeschsperre zaehlen nur aktive Geraete und gueltige
Installationsmedien. Beim Loeschen werden Zuordnungen archivierter
Geraete und abgelaufene/widerrufene Medien mit entfernt (sonst
blockieren die Fremdschluessel). Anlass: Liebherrs
Entwicklungsprofile hingen nur noch an Altlasten vom 08./09.09.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:50:13 +02:00
adminandClaude Opus 5.5 485282664a Migration 0057: Merkmal diagnosezugang-sperre (Haertung, alle drei Backends)
GUI-Runde 10/2026 Punkt 7.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:44:03 +02:00
adminandClaude Opus 5.5 61aa108666 Aktivierung: bei Medium mit Ziel-OE deren Workspace in der Template-Antwort
Die Installer-Uebersicht (25_installation_confirm.sh) zeigte den
Profil-Workspace, wirksam ist aber der der Ziel-OE (Schritt F). Neue
Hilfsfunktion oe_kette_workspace(); gleiche Distro-Regel wie
geraete_basis_herkunft(). Der Installer liest nur den Namen, keine
Installer-Aenderung noetig. GUI-Runde 10/2026 Punkt 8.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:42:12 +02:00
adminandClaude Opus 5.5 465910f700 Dashboards: Verteilungen fuer Ringdiagramme (Zustand, Distro, Workspace, Organisation)
_dashboard_verteilungen(): Geraetezustand ausschliessend (nie gemeldet,
>7 Tage nicht gemeldet, Ressourcen knapp, in Ordnung), Distro und
wirksamer Workspace je Geraet ueber geraete_basis(), Organisationen im
Admin-Dashboard. Hoechstens 5 Teile + 'Weitere', Sonderfaelle (ohne
Installation/Workspace) immer am Ende. GUI-Runde 10/2026 Punkt 6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:40:40 +02:00
adminandClaude Opus 5.5 0561691f20 Bereitstellungsvorlagen: Bearbeiten, Loeschen, Nutzung, Distro aus Workspace
Liste liefert Geraete-/Medien-Anzahl, Verschluesselung, Secure Boot. Neue
Endpunkte PUT/DELETE (Loeschen gesperrt solange Geraete oder
Installationsmedien verweisen). backend_id optional - ohne Angabe gilt
die Distro des Workspace (ADR-0038). Pruefung fuer Anlegen und
Bearbeiten in _bereitstellungsvorlage_pruefen(). GUI-Runde 10/2026 Punkt 5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:34:55 +02:00
adminandClaude Opus 5.5 b038350e72 Aktivitaetenliste: Installationsereignisse + zusammengefasste Agent-Laeufe
fetch_aktivitaeten(): ein Agent-Lauf meldet je Merkmal ein Ereignis (~56,
gleicher Zeitstempel) - hier zu einer Zeile zusammengefasst, Fehler
benannt. Neuer Endpunkt /organizations/{id}/aktivitaeten, beide
Dashboards liefern zusaetzlich 'aktivitaeten'. GUI-Runde 10/2026 Punkt 4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:30:32 +02:00
adminandClaude Opus 5.5 3381b2b13c Aktivierungscodes verwalten: Bezeichnung, Gueltigkeit, Nutzung, Status/Loeschen
Migration 0056: bezeichnung, gueltig_bis, verwendet_anzahl,
zuletzt_verwendet (alle optional, bestehende Codes unbegrenzt gueltig).
Abgelaufene Codes werden bei der Aktivierung abgelehnt, erfolgreiche
Aktivierungen gezaehlt. Neue Endpunkte: Status setzen, Loeschen; Anlegen
nimmt optional bezeichnung/gueltig_tage. GUI-Runde 10/2026 Punkt 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:25:38 +02:00
adminandClaude Opus 5.5 f1435018ec Webapp-Icons: Content-Type auch fuer Vorlagen-Icons nachschlagen
get_webapp_icon kannte nur workspace_webapps/gruppen_webapps, Icons von
webapp_templates kamen als application/octet-stream.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 11:12:11 +02:00
adminandClaude Opus 5.5 41ad31c900 Migration 0055: Merkmal konsolenwechsel-sperre (Haertung, alle drei Backends)
Siehe platform-docs ADR-0039.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:41:06 +02:00
adminandClaude Opus 5.5 f4c306e389 Aufraeumen: Schulcomputer Basis entfernt, Workspace-Liste mit Freigabe-Namen
Testprofile von Default Lab und WLAN-Test zeigen auf die Vorlagen
Schulcomputer (Mint/Debian/Ubuntu) derselben Distro, die Basis-Workspaces
entfallen (Migration 0054). fetch_workspaces() liefert die Namen der
freigegebenen Kundengruppen/Organisationen fuer Anzeigen wie
"Vorlage fuer Schulen".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:06:08 +02:00
adminandClaude Opus 5.5 1288097927 Workspace an der OE, Distro-Konfliktregel, Ziel-OE fuer Installationsmedien
- PUT /api/v1/organisationseinheiten/{id}/workspace: Workspace (sichtbar fuer
  die Organisation, mit Distro) an eine OE haengen, automatisch oder auf eine
  Version gepinnt.
- distro_konflikte(): simuliert OE-Workspace, OE umhaengen und Geraet
  verschieben und blockiert, wenn ein aktives Geraet danach einen Workspace
  mit anderer Distro bekaeme (Meldung nennt Geraete und OE).
- Sicherheitsnetz in geraete_basis_herkunft(): passt der OE-Workspace nicht
  zur Geraete-Distro, gilt der Workspace der Installation.
- Enrollment-Sessions mit Ziel-OE (geprueft gegen die Profil-Distro);
  aktivierte Geraete landen dort, resolve_template liefert die Blueprints der
  wirksamen Grundausstattung.
- Profil anlegen prueft, dass Workspace und Profil dieselbe Distro haben.
- OE-Liste mit eigenem und wirksamem (geerbtem) Workspace, Geraeteliste mit
  wirksamem Workspace und Distro.
Workspace-Creator neu, Schritt F.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:12:33 +02:00
adminandClaude Opus 5.5 5187ad7be7 Migration 0053: Ziel-OE fuer Enrollment-Sessions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:12:18 +02:00
adminandClaude Opus 5.5 421e3edc45 Workspace-Verwaltung: Entwurf/Veroeffentlichen, Wirkung, Vorlage, Kopie, Loeschen
Inhalte aendern sich nur noch im Entwurf (Endpunkte lehnen sonst mit
kein_entwurf ab, Webapps muessen zum Entwurf gehoeren, neue Merkmale zur
Distro passen). Veroeffentlichen prueft die Distro erneut. Neue
Endpunkte: Entwurf anlegen/verwerfen, veroeffentlichen, Versionen,
Nutzung (Profile, OEs, Geraete automatisch vs. gepinnt), Wirkung (Diff
plus Nutzung), Name/Zweck, Vorlage mit Sichtbarkeit, Kopie-Pruefung und
Kopie auf andere Distro (fehlende Merkmale fallen weg und werden
gemeldet), Loeschen nur wenn ungenutzt (raeumt Icons auf),
Kundengruppen. geraete_basis_herkunft() liefert die Herkunft der
Grundausstattung. Workspace-Creator neu, Schritt E.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:34:38 +02:00
adminandClaude Opus 5.5 857461cc44 API: Workspace aus dem Assistenten in einem Rutsch anlegen
POST /api/v1/workspaces/assistent legt Workspace mit Distro, Version 1,
Merkmalen und Webapps aus Vorlagen in einer Transaktion an und lehnt
Merkmale ab, die auf der gewaehlten Distro nicht umgesetzt sind
(Fehlermeldung nennt sie). Key wird aus dem Namen erzeugt und je
Eigentuemer eindeutig gemacht. Workspace-Creator neu, Schritt D.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:12:12 +02:00
adminandClaude Opus 5.5 b361579cc6 Migration 0052: Bestandsmigration, jeder Workspace genau eine Distro
Liebherrs gepflegter Schulcomputer wird Vorlage je Distro (Kundengruppe
Schule), Liebherr- und Gaissach-Profile zeigen auf die Mint-Variante.
Alter globaler Schulcomputer wird Schulcomputer Basis je Distro fuer die
Bestandsprofile. Gast/fjmfm geloescht, Entwickler bleibt als Entwickler
(Mint) bis nach dem 01.11.2026 (gueltiger Aktivierungszugang).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:00:58 +02:00
adminandClaude Opus 5.5 08ecec3c80 Migration 0051: workspace_merkmale und gruppen.workspace_id entfernen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:55:41 +02:00
adminandClaude Opus 5.5 4a7ae27dc7 Server auf Workspace-Versionen und OE-Workspace umgestellt
geraete_basis() ermittelt die Grundausstattung eines Geraets: Distro aus
der Installation, Workspace von der naechsten OE mit Workspace (gepinnte
Version oder neueste veroeffentlichte), sonst wie bisher aus der
Installation. Blueprints, Auftragskatalog, Webapps und Profil-Aufloesung
lesen die Version; Gruppen-Webapps ergaenzen. Gruppen tragen keinen
Workspace mehr, Exklusivregel und Endpunkte entfallen. Admin-Bearbeitung
wirkt bis Schritt E auf die Arbeitsversion. Workspace-Liste/-Detail
liefern Distro, Version, Vorlage, Sichtbarkeit; Sichtbarkeit fuer Kunden
nach Eigentum, global, Kundengruppe oder Organisation.

Lokal gegen eine Kopie der Produktionsdaten geprueft: Soll-Zustand aller
21 Geraete und 12 Profile identisch zum alten Code, 19 Szenarien gruen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:54:35 +02:00
adminandClaude Opus 5.5 3ac7485179 Migration 0050: Workspace-Versionen, Distro am Workspace, OE-Workspace, Kundengruppen
Rein additiv mit Rueckfuellung: jeder Workspace bekommt Version 1 mit
seinem bisherigen Inhalt, alle Organisationen die Kundengruppe Schule.
Neu: Sichtbarkeit/Freigaben fuer Vorlagen, Workspace an der OE mit
gepinnter Version und Auto-Haken, Gruppen-Webapps, Org-Berechtigung
darf_eigene_workspaces. Workspace-Creator neu, Schritt C.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:54:23 +02:00
adminandClaude Opus 5.5 98bd2c57fb Migration 0049: Kategorie App-Store aufloesen, Bayern Cloud Schule einordnen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:44:09 +02:00
adminandClaude Opus 5.5 8363d41dd3 API: Kategorie-Art und Kategorie für Webapp-Vorlagen
fetch_kategorien() liefert art, Kategorien lassen sich als App oder
Richtlinie anlegen. Webapp-Vorlagen tragen optional eine App-Kategorie,
die beim Aktivieren in den Workspace mitkopiert wird.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:28:49 +02:00
adminandClaude Opus 5.5 845533a0a0 Migration 0048: kategorien.art und webapp_templates.kategorie_id
Workspace-Creator neu, Schritt A (platform-docs/roadmap/workspace-creator-neu.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:28:39 +02:00
adminandClaude Opus 5.5 16d2de6c3a ISO-Bau ohne sudo, Unit wieder voll gehaertet
build_customer_iso.sh braucht seit der Squashfs-Schicht kein root mehr:
sudo-Aufruf und sudoers-Datei entfallen, NoNewPrivileges,
CapabilityBoundingSet/AmbientCapabilities und RestrictSUIDSGID wieder an
(Ausnahmen aus ADR-0027 zurueckgenommen).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:19:43 +02:00
adminandClaude Opus 5.5 b8015567f3 Unit: ISO-Build-Arbeitsverzeichnis auf der Datenplatte beschreibbar (ProtectSystem=strict)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 12:27:12 +02:00
adminandClaude Opus 5.5 5ed6d4d478 Boot-Medium neutral benannt (TUXFLOTTE_BOOT_MEDIUM_PATH), Offline-Medium, Neuinstallation ohne Rueckfrage pro Enrollment Session
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 12:17:31 +02:00
adminandClaude Opus 5.5 43d0fce764 Hostnamenkonvention auch bei Neuinstallation bekannter Geraete, Live-System-Name nicht mehr uebernehmen (Kunden-ISO-Test R16)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 10:24:42 +02:00
adminandClaude Opus 5.5 4d5d6090b4 Debug-Modus bei jedem installation_completed, Vorlagenname an build_customer_iso.sh (Kunden-ISO-Test R6/R10)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 09:42:52 +02:00
adminandClaude Opus 5.5 cec4dcb2d6 ISO-Build: root_password_hash fuer Diagnosezugang, Geheimnisse per stdin statt Argument (ADR-0035)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 14:18:26 +02:00
adminandClaude Sonnet 5 e0e60ef828 Fix: Cross-Org-Reaktivierung derselben Hardware crasht mit HTTP 500
Bare-Metal-Fund (21.09.2026): dieselbe physische Testmaschine wurde mit
Aktivierungscodes zweier verschiedener Organisationen aktiviert (device_
fingerprint bleibt hardware-gebunden stabil, anders als bei VM-Testumgebungen
mit Snapshot-Reset zwischen Laeufen). load_or_create_device() wirft dafuer
bewusst einen RuntimeError, der bisher ungefangen bis zu FastAPI durchschlug
(HTTP 500 "Internal Server Error" statt einer klaren Ablehnung) - fuer den
Installer nicht von einem echten Serverfehler unterscheidbar. Jetzt sauber
abgefangen und als strukturierte success:false-Antwort zurueckgegeben, analog
zum bestehenden invalid_activation_code-Fall.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DWKevK2QUK5tsGmqfSD6Yy
2026-09-21 13:25:56 +02:00
adminandClaude Sonnet 5 676e324381 Bereitstellungsvorlage: custom-Partitionierungsschema per API/GUI
CreateBereitstellungsvorlageRequest bekommt scheme + extra_partitions
(Mountpoint/Prozent/Dateisystem je Zusatzpartition), mit serverseitiger
Validierung (Prozentsumme < 100, keine doppelten Mountpoints, nur
ext4/btrfs). Bisher war "custom" laut Code-Kommentar nur per direkter
DB-Pflege erreichbar - jetzt vollstaendig ueber das bestehende Admin-
Formular (Organisationen -> Bereitstellungsvorlagen).

fetch_templates() liefert partitioning jetzt mit aus, damit die Admin-
Tabelle das gewaehlte Schema anzeigen kann.

Migration 0046 dokumentiert die neue JSONB-Form im Spalten-Default und
zieht bestehende Zeilen nach (Muster wie Migration 0026).

Teil der E2E-Testrunde, siehe platform-docs/roadmap/
e2e-testrunde-lokale-adressierung.md Phase 3. Gegenstueck im Install-
Backend (image_deploy_partition_custom() etc.) ist in tuxflotte-installer
bereits umgesetzt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DWKevK2QUK5tsGmqfSD6Yy
2026-09-19 14:52:13 +02:00
adminandClaude Sonnet 5 8140c8cf80 Merkmal-Icon-Dateiendung: .ico statt .svg als Fallback-Default
Live gefunden direkt beim Nachprüfen des vorigen Fixes: "image/x-icon"
fehlt in Pythons mimetypes-Datenbank (guess_extension liefert None), der
Fallback-Default war fälschlich ".svg" statt ".ico" gesetzt (Kopierfehler
gegenüber _write_webapp_icon(), die genau dafür schon .ico als Default
nutzt). Ein Kolibri-Favicon (echtes ICO, von der neuen Magic-Bytes-
Erkennung korrekt als image/x-icon erkannt) landete dadurch weiterhin
mit .svg-Endung auf der Platte.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-11 11:40:42 +02:00
adminandClaude Sonnet 5 a6fecdd818 Icon-Fetch: echten Bildtyp per Magic Bytes erkennen statt Server-Header zu vertrauen
Live gefunden beim Icon-Backfill (Phase 6): learningequality.org liefert
sein Favicon mit Content-Type "image/svg+xml", tatsächlich sind die Bytes
ein PNG-in-ICO-Container - wäre im Browser als kaputtes Bild gelandet
(SVG-Parser auf Binärdaten). _erkanntes_bildformat() sniffed jetzt die
echten Magic Bytes (PNG/JPEG/GIF/ICO/WEBP/SVG-Erkennung), der HTTP-Header
dient nur noch als Fallback. Zentral in _fetch_url_bytes() gefixt, damit
sowohl Webapp- als auch Merkmal-Icons profitieren (gleicher Fetch-Pfad).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-11 11:39:16 +02:00
adminandClaude Sonnet 5 95946bd11c Phase 6: App-Beschreibungen + Icon-Fetch-Mechanismus
Migration 0045: 47 von 56 Merkmalen hatten keine Beschreibung (Datenbank-
Check 11.09.2026) - Kurzbeschreibungen ergänzt, gleicher Ton wie die 9
bestehenden. Neue Spalten homepage_url/icon_source_hint (nur real gegen
die jeweilige URL bzw. https://cdn.simpleicons.org/<slug> geprüft
gesetzt, sonst NULL statt geraten) sowie icon_filename/icon_content_type
(Cache, analog workspace_webapps).

Neuer Icon-Fetch: fetch_merkmal_icon() probiert zuerst den Simple-Icons-
Slug, sonst fetch_favicon() der Homepage (bestehende Funktion aus dem
Webapp-Mechanismus direkt wiederverwendet) - Kombi aus beidem war die
Nutzer-Entscheidung in der Plan-Klärungsrunde. aktualisiere_merkmal_icon()
ist ein eigener, wiederholbar aufrufbarer Schritt (POST /api/v1/merkmale/
{id}/icon/aktualisieren) statt Teil des Anlegens, weil Merkmale per
Migration entstehen, nicht per API-Call mit sofortigem Netzwerk-Kontext.
Auslieferung über GET /merkmal-icons/{filename}, gleiches Muster wie
/webapp-icons.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-11 11:36:55 +02:00
adminandClaude Sonnet 5 2ebecd1426 Admin-Dashboard: archivierte Geräte auch aus "letzte Aktivität" ausschließen
Live gefunden bei der Verifikation: die Geräteanzahl-Spalte filterte
schon archivierte Geräte heraus (FILTER WHERE archived_at IS NULL), die
"letzte Aktivität"-Spalte (MAX) nicht - eine Organisation mit 0 aktiven
Geräten konnte dadurch trotzdem ein Aktivitätsdatum zeigen (von einem
längst archivierten Gerät). Jetzt konsistent beide gefiltert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-11 11:23:17 +02:00
adminandClaude Sonnet 5 2aae6348a6 Phase 5: Dashboard-Datengrundlage (Kunde + Admin)
Neue fetch_customer_dashboard()/fetch_admin_dashboard() + Endpunkte
GET /api/v1/organizations/{id}/dashboard und GET /api/v1/dashboard/admin.
V1 bewusst nur aus bereits vorhandenen Daten (siehe Plan-Klärungsrunde
11.09.2026) - der Agent meldet Platten-/RAM-Auslastung schon länger bei
jedem Check-in (health_disk_used_percent/health_ram_used_percent), das
wird hier erstmals aggregiert statt nur pro Gerät angezeigt:
- "Nächste Schritte": eigener Workspace vorhanden, Installationsmedium
  erstellt (das eigentliche iso_build_id lebt in kundenplattforms eigener
  DB, dort ergänzt), erstes Gerät aktiv, Hostnamenkonvention eingerichtet.
- Flotten-Gesundheit: Geräte ohne Check-in seit 7 Tagen, Platten-/RAM-
  Auslastung ab 85% - gemeinsame Auswertung _dashboard_flotten_gesundheit()
  für Kunde (org-gefiltert) und Admin (alle Organisationen, mit Namens-
  Präfix je Zeile).
- Letzte Aktionen: jüngste device_merkmal_events (applied/apply_failed).
- Admin zusätzlich: Organisationstabelle mit Geräteanzahl/letzter Aktivität.

Festplattenfehler-/SMART-Daten bleiben bewusst außen vor - der Agent
erfasst das aktuell nicht, wäre ein eigener Erfassungsmechanismus (siehe
Rückfrage-Runde im Plan).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-11 11:21:33 +02:00
adminandClaude Sonnet 5 4706870774 Phase 4: Webapp-Kategorie-Menü-Einordnung + Kiosk-Modus, Chromium+Edge-Merkmale
Webapps bekommen zwei neue, optionale Eigenschaften (Migration 0043):
kategorie_id (FK auf kategorien, nullable) und kiosk_modus (Boolean).
Kein eigener "Webapps"-Menüpunkt (per Nutzer-Feedback in der Plan-Runde
verworfen) - stattdessen ordnet sich eine Webapp optional einer der
bestehenden App-Kategorien zu, KATEGORIE_ZU_XDG_CATEGORIES übersetzt das
in eine echte Freedesktop-Categories=-Zeile fürs .desktop-Menü (Default
unverändert Network;WebBrowser; ohne gewählte Kategorie).

Kiosk-Modus: bei aktiviertem kiosk_modus löst der Server (nicht das
Gerät) anhand der Workspace-Merkmal-Zuordnung auf, welcher Browser das
Kiosk-Fenster öffnet (Chrome bevorzugt, Chromium Fallback, sonst normaler
Tab) - _resolve_kiosk_browser() in fetch_workspace_webapps().

Migration 0044: Chromium + Microsoft Edge als neue Browser-Merkmale
(Google Chrome existiert bereits aus Migration 0031). Chromium bewusst
NUR für debian-image/mint-image blueprint-verknüpft, nicht ubuntu-image -
recherchiert: Ubuntus "chromium"-Paket ist seit 19.10 nur ein
transitionelles Paket, das im Hintergrund Snap nachzieht (passt nicht zu
unserem Modell), während Debian und Mint ein echtes .deb bauen. Microsoft
Edge über das offizielle, distributionsunabhängige Microsoft-Repo auf
allen drei Backends.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-11 11:10:33 +02:00
adminandClaude Sonnet 5 b686d87c4b Workspace-Klon-Endpunkt für "Diesen Standard übernehmen"
Live gefundene Lücke (11.09.2026): das neue Besitz-Modell von
routers/workspace.py bindet Webapps strikt an Eigentum - ein globaler,
schreibgeschützter Standard-Workspace hat nie eigene Webapps, und eine
Organisation ohne einen einzigen eigenen Workspace hatte dadurch gar
keinen Weg mehr zu Webapps (Regression gegenüber dem alten, aber
unsicheren Verhalten, das jede nutzende Organisation an geteilten
Workspaces mitschreiben liess und damit ein Cross-Org-Leck riskierte).

clone_workspace() kopiert die Merkmal-Zusammensetzung eines sichtbaren
Workspace in einen neuen, garantiert der aufrufenden Organisation
gehörenden Workspace - der Standard selbst bleibt für alle unangetastet.
Neuer Service-Endpunkt POST /api/v1/workspaces/{id}/clone (Service-Token
wie die übrigen Workspace-Endpunkte).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-11 10:36:05 +02:00
adminandClaude Sonnet 5 965db2b541 fetch_available_workspaces_for_organization(): ist_global-Feld ergänzen
Fürs neue Kunden-Workspace-Creator-UI (Phase 3) - damit die
Kundenplattform zwischen eigenen (bearbeitbar) und globalen
(schreibgeschützt) Workspaces unterscheiden kann.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-11 09:02:49 +02:00
adminandClaude Sonnet 5 aa9072ef91 Admin-Geräteliste: Workspace-Name mitliefern (GUI-Umbau Phase 2)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-11 08:59:02 +02:00
adminandClaude Sonnet 5 ed217032d8 Umlaut-Fix Kategorie + fedora-Backend vollständig entfernt
- Migration 0041: "Buero & Produktivitaet" -> "Büro & Produktivität"
  (ASCII-Ersatzschreibweise, key unveraendert - Fremdschluessel laufen
  ueber kategorie_id, nicht ueber key).
- Migration 0042: fedora-Backend nach Nutzer-Bestaetigung komplett
  entfernt (siehe Rueckfrage bei Migration 0040) - dazu erst die eine
  darauf verweisende Bereitstellungsvorlage ("Schulcomputer (Fedora)")
  und ihre 4 historischen Zuweisungen an bereits archivierte Testgeraete
  geloescht (sonst ON DELETE RESTRICT), dann das Backend selbst
  (Blueprints kaskadieren automatisch mit).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-10 16:14:50 +02:00
adminandClaude Sonnet 5 af6af03b43 Zwei echte Anzeige-Bugs gefixt, Backend-Namen bereinigt
- debug_mode_until wurde beim Ablaufen nie geloescht - Auftragskatalog-
  Seite und Geraeteliste zeigten den Debug-Modus dadurch dauerhaft als
  aktiv an, auch Tage nach Ablauf (live an zwei echten Geraeten gefunden,
  abgelaufen am 02./09.09., trotzdem noch "aktiv" angezeigt).
  _health_felder_aus_row() liefert das Feld jetzt nur noch, wenn es
  tatsaechlich noch in der Zukunft liegt.
- fetch_unassigned_devices() (Flows "Unbestaetigte Geraete") hatte den
  archived_at-Filter nie bekommen, den fetch_devices_for_organization()/
  fetch_all_devices() schon hatten - bereits geloeschte Geraete ohne
  Zuweisung erschienen dadurch dauerhaft als offene Aufgabe.
- Migration 0040: Backend-Namen gekuerzt (Debian/Mint/Ubuntu statt
  "... (Golden Image) ..."), altes "mint"-Backend (vor dem Golden-Image-
  Pivot, keine Bereitstellungsvorlage nutzt es mehr) geloescht. "fedora"
  bewusst NICHT angefasst - echte Bereitstellungsvorlage+Zuweisungen
  haengen dran, siehe Rueckfrage an den Nutzer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-10 15:41:14 +02:00
adminandClaude Sonnet 5 f337718ec6 Geräteliste: Workspace-Name mitliefern (GUI-Umbau)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-10 14:51:54 +02:00
adminandClaude Sonnet 5 bfbd8f7b17 Hostnamenkonvention: serverseitige Vergabe für neue Geräte
- Migration 0039: organizations.hostname_praefix/-stellen/-nummer_modus/
  -naechste_sequenz. Leerer Präfix = keine Konvention (unverändertes
  Verhalten, Client bestimmt den Hostnamen selbst).
- generate_hostname_for_organization(): erzeugt "<praefix>-<nummer>",
  sequenziell (Zeilen-Lock via FOR UPDATE) oder zufällig (freie Nummer
  per secrets.randbelow(), Kollisionsprüfung gegen vorhandene Hostnamen,
  Fallback auf nächste freie sequenzielle Nummer nach 20 Versuchen).
- resolve_hostname_for_activation(): greift nur bei einem GENUIN NEUEN
  Gerät (device_fingerprint noch unbekannt) - eine Re-Aktivierung eines
  bekannten Geräts behält immer den vom Client gemeldeten Hostnamen,
  überschreibt also keine manuelle Umbenennung.
- agent_checkin(): liefert jetzt auch "hostname" (devices.hostname) an
  den Agenten.
- Neue Endpunkte GET/PUT /api/v1/organizations/{id}/hostname-konvention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-10 12:06:35 +02:00
adminandClaude Sonnet 5 10d31f8cf3 Gerätegruppen mit alternativem Workspace, device_merkmale abgelöst
- Migration 0038: gruppen.workspace_id (nullable FK), device_merkmale
  Tabelle entfernt (keine Datenzeilen auf anode, geprüft vor Drop).
- set_gruppe_workspace()/clear_gruppe_workspace(): weist einer
  Gerätegruppe einen alternativen Workspace zu, ersetzt die komplette
  Baseline für Mitgliedsgeräte statt nur einzelner Merkmale. Prüft
  Organisationszugehörigkeit des Workspace (global oder eigene Org) und
  die Exklusivitätsregel (ein Gerät nur in einer workspace-tragenden
  Gruppe gleichzeitig) - sowohl beim Zuweisen als auch beim Hinzufügen
  eines Geräts zu einer bereits workspace-tragenden Gruppe.
- resolve_effective_workspace_id(): neue Auflösungsstufe zwischen
  Bereitstellungsvorlage und OE-/Gruppen-Merkmal-Overrides.
- fetch_auftragskatalog_state()/_listing(): device_merkmale-Override-Ebene
  entfernt (gewann bisher immer), select_auftrag/deselect_auftrag-
  Endpunkte + set_auftrag_selection() entfernt. get_device_auftragskatalog
  bleibt als reine Ist-Zustand-Anzeige.
- Neuer Endpunkt GET /api/v1/organizations/{id}/workspaces (global +
  eigene, org-gefiltert - fetch_workspaces() bleibt admin-only, würde
  sonst fremde private Workspaces preisgeben).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-10 10:43:34 +02:00
adminandClaude Sonnet 5 b270103eab Fix: optionen-Update überschrieb bisherige Werte statt sie zu ergänzen + OE-/Gruppen-Select-Endpunkte akzeptieren jetzt optionen-Payload
Zwei zusammenhängende Fixes, beide Voraussetzung für die neue
optionen-Eingabe-UI in kundenplattform (struktur.py/gruppen.py):

1. set_auftrag_selection()/set_oe_auswahl()/set_gruppe_auswahl()
   ersetzten optionen bisher komplett (kein natives JSONB-Merge im
   UPSERT) - ein im Formular leer gelassenes Passwort-Feld
   (parse_optionen_form() lässt solche Keys bewusst weg, siehe
   optionen_felder.py) hätte ein zuvor gesetztes Passwort beim nächsten
   Bearbeiten stillschweigend gelöscht. Neue merge_optionen()-Funktion:
   bestehenden Wert holen, mit den neu eingegebenen Feldern
   zusammenführen, erst dann verschlüsseln (encrypt_sensitive_optionen()
   dafür idempotent gemacht - erkennt bereits "enc:"-präfigierte Werte
   und verschlüsselt nicht doppelt).

2. /api/v1/organisationseinheiten/{oe_id}/merkmale/{merkmal_key}/select
   und die Gruppen-Entsprechung nahmen bisher gar keinen Payload-Body
   entgegen (hartcodiert leeres optionen-Dict) - jetzt wie der
   geräteweise Endpunkt mit AuftragSelectRequest. Ohne diesen Fix hätte
   die neue OE-/Gruppen-UI (Kundenplattform) eingegebene AD-Domäne o.ä.
   nie beim Server ankommen können.

Zusätzlich: fetch_oe_merkmale_listing()/fetch_gruppe_merkmale_listing()
liefern jetzt auch optionen (maskiert, siehe mask_sensitive_optionen())
für die "bereits gesetzt"-Anzeige im Formular.

ECHT gegen die Produktions-DB getestet (nicht nur Code-Review): OE-Ebene
erst mit Domain+Passwort setzen, dann NUR die Domain erneut setzen ohne
Passwort-Feld - Passwort blieb korrekt erhalten, Domain wurde aktualisiert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-10 09:38:41 +02:00
adminandClaude Sonnet 5 d970936b7c Migration: AD-Anbindung/Fileserver/Update-Proxy-Merkmale
Siehe admin/ansible-content fuer die zugehoerigen Rollen und
admin/kundenplattform fuer die optionen-Eingabe-UI.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-10 09:38:02 +02:00
adminandClaude Sonnet 5 d61071335d Fix: OE-/Gruppen-Optionen erreichten nie das Gerät + At-Rest-Verschlüsselung für sensible Merkmal-Optionen
Fund beim Vorbereiten der AD/OIDC/Fileserver-Merkmale (10.09.2026):
resolve_katalog_overrides() selektierte nie die optionen-Spalte aus
oe_merkmale/gruppen_merkmale, obwohl set_oe_auswahl()/set_gruppe_auswahl()
sie langst speichern konnten - nur device_merkmale.optionen erreichte je
ein Geraet. Da die Geraete-Einzel-Ebene laut Entscheidung vom 09.09.2026
nicht der vorgesehene Ort fuer Merkmal-Konfiguration ist (siehe
project_phase2_app_store_merkmale-Memory), waere OE-/Gruppen-seitig
gesetzte Konfiguration (z.B. eine AD-Domaene) nie beim Geraet angekommen.

resolve_katalog_overrides() liefert jetzt (aktiv, quelle, quelle_id,
optionen) statt nur (aktiv, quelle, quelle_id) - beide Aufrufer
(fetch_auftragskatalog_state fuer den Agenten,
fetch_auftragskatalog_listing fuer die Kundenportal-Anzeige) angepasst.

Zusaetzlich neue At-Rest-Verschluesselung fuer optionen-Werte, deren Key
auf _passwort/_password/_secret/_token endet (Namenskonvention statt
Allowlist - neue Merkmale mit einem Zugangsdaten-Feld brauchen nur den
passenden Key-Namen, keine Codeaenderung). Gleiches Fernet-Muster wie
kundenplattform/encryption.py fuer den WLAN-PSK, aber eigenes Modul/eigener
Schluessel (TUXFLOTTE_ENCRYPTION_KEY) - provisioning-server muss bei jedem
Agent-Checkin entschluesseln koennen, anders als der einmalige ISO-Build-
Transfer dort. Kundenportal-Katalog-Listing zeigt sensible Werte nur als
maskierten Boolean (mask_sensitive_optionen()), nie im Klartext oder auch
nur verschluesselt im Browser.

Neue Abhaengigkeit: cryptography==50.0.0 (gleiche Version wie
kundenplattform), TUXFLOTTE_ENCRYPTION_KEY live auf anode gesetzt.

ECHT gegen die laufende Produktions-Datenbank getestet (nicht nur
Syntax-Check): OE-Ebene (verschluesselter Roh-DB-Wert, korrekter
Klartext im Agent-Checkin-Pfad, korrekt maskiert im Listing-Pfad) UND
Geraete-Ebene als Regressionstest (bestehender, meistgenutzter Pfad
funktioniert unveraendert weiter) - beide bestanden, Testdaten wieder
entfernt.

Voraussetzung fuer die anstehenden AD/OIDC/Fileserver-Merkmale (siehe
project_phase2_app_store_merkmale-Memory), die auf OE-/Gruppen-Ebene mit
echten Zugangsdaten konfiguriert werden sollen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-10 09:21:51 +02:00
adminandClaude Sonnet 5 8c8894b942 Migration: Konfiguration/Härtung-Kategorien + erste 10 Merkmale
Siehe admin/ansible-content für die zugehörigen Rollen und
Test-/Verifikationsdetails.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-10 09:07:46 +02:00
adminandClaude Sonnet 5 d7f14c9feb Webapp-Vorlagen (Zwei-Ebenen-Modell, Nutzer-Entscheidung 09.09.2026)
Ergaenzung zum bisherigen rein kundeneigenen workspace_webapps: Admin
kann jetzt zusaetzlich global wiederverwendbare Vorlagen anlegen
('bereitstellen und zur Auswahl stellen'), Kunden aktivieren sie pro
Workspace zusaetzlich zu weiterhin frei erstellbaren eigenen
Eintraegen ('Kunden koennen selbst welche erstellen').

Neue Tabelle webapp_templates (Migration 0033, diesmal korrekt ueber
TUXFLOTTE_DATABASE_URL statt sudo-postgres angewendet - siehe Lehre aus
dem vorherigen Owner-Bug). workspace_webapps bekommt ein nullable
template_id (ON DELETE SET NULL) zur Aktivierungs-Nachverfolgung.

activate_webapp_template() kopiert Name/URL/Icon-Datei PHYSISCH unter
einem neuen, vom eigenen Eintrag abgeleiteten Dateinamen - keine
laufende Referenz auf die Vorlagen-Icon-Datei, sonst wuerde ein
spaeteres Loeschen/Aktualisieren der Vorlage die schon aktivierte Kopie
mit betreffen.

Neue Endpunkte: /api/v1/webapp-templates (CRUD),
/api/v1/workspaces/{id}/webapp-templates/available (noch nicht
aktivierte Vorlagen fuer einen Workspace), .../activate.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-09 17:42:30 +02:00
adminandClaude Sonnet 5 4b229a992b Webapp-Mechanismus (Phase 2): Server-seitige DB+API+Favicon-Fetch
Nachtrag: Migration 0030 (App-Store-Batch-1-Merkmale) war im letzten
Commit versehentlich nicht mit dabei - jetzt nachgeholt (git status hat
es aufgedeckt).

Neue Tabelle workspace_webapps (Migration 0032): kundeneigene
{name, url}-Eintraege pro Workspace, kein fester Katalog wie bei
Merkmalen - jede Organisation/jeder Workspace hat ihre/seine eigene
Liste (Nutzer-Anforderung 09.09.2026: 'der Kunde hat diverse URLs').

app.py-Aenderungen:
- fetch_favicon(): bestes-Effort-Ermittlung des Website-Favicons
  (erst <link rel=icon> per Regex aus dem HTML, sonst /favicon.ico an
  der Domain-Wurzel) - bewusst ohne neue pip-Abhaengigkeit (nur
  urllib, passt zum bisher sehr schlanken requirements.txt).
- CRUD-Endpunkte /api/v1/workspaces/{id}/webapps[/​{webapp_id}]
  (GET/POST/PUT/DELETE), Icon-Serving unter /webapp-icons/{filename}
  (unauthentifiziert wie /golden-images/, gleicher
  Path-Traversal-Schutz).
- Checkin-Response um 'webapps' erweitert (fetch_workspace_webapps(),
  gleiches assignments->bereitstellungsvorlagen-Join-Muster wie
  fetch_assigned_blueprints()).
- WICHTIG: Server komponiert nie eine eigene oeffentliche URL (ANODE_URL
  ist nur client-seitig bekannt, siehe agent.py/backend.sh) - Checkin
  liefert nur den relativen icon_path, der Agent haengt ANODE_URL davor.

Gehört zusammen mit admin/ansible-content (neue Rolle
webapp-shortcuts, echt end-to-end getestet) und admin/kundenplattform
(Admin-UI unter /admin/technik/workspaces/{id}, Icon-Proxy analog zum
bestehenden ISO-Download-Proxy-Muster).

Live auf anode angewendet: Migration 0032 (workspace_webapps-Tabelle).
app.py-Deployment (git pull + Neustart) folgt separat.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-09 14:58:51 +02:00
adminandClaude Sonnet 5 ead3535e72 Migration: 6 Sonderfall-App-Store-Merkmale (google-chrome, anydesk, kolibri, veyon, gdevelop, turbowarp)
Siehe admin/ansible-content für die zugehörigen Rollen und die
Recherche-/Verifikationsdetails pro App.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-09 14:44:40 +02:00
adminandClaude Sonnet 5 e7202585e9 Migration: App-Store-Unterkategorien + Backfill fehlender Golden-Image-Blueprints
Fund beim Start von Phase 2 (Merkmal-Ausbau): bestehende App-Store-
Merkmale (brave, google-earth, guest-session, libreoffice, onlyoffice)
waren nur fuer die alten Backends mint/fedora verdrahtet, nicht fuer
die inzwischen tatsaechlich genutzten Golden-Image-Backends
(mint-image/debian-image/ubuntu-image) - der Auftragskatalog lieferte
diese Merkmale fuer jedes real provisionierte Geraet nicht aus. Per
INSERT...SELECT nachgezogen (gleicher Ansible-Rollenname, alle Rollen
sind bereits distributionsunabhaengig).

Zusaetzlich acht neue App-Store-Unterkategorien fuer die anstehende
App-Auswahl (siehe Plan-Datei/Memory project_phase2_app_store_merkmale).
Bestehende vier Merkmale bleiben vorerst bei der groben 'app-store'-
Kategorie, Umsortierung ist ein separater Schritt.

Live auf anode angewendet + verifiziert (15 Blueprint-Zeilen, 8 neue
Kategorien).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
2026-09-09 13:20:58 +02:00