13 Commits

Author SHA1 Message Date
f69ed66267 feat: ISO-Build-Orchestrierung fuer personalisierte Kunden-ISOs (Phase 4)
Neue iso_builds-Tabelle (Migration 0016) + vier Endpunkte, die
tuxflotte-installer/scripts/build_customer_iso.sh als Hintergrund-Thread
anstossen: POST/GET .../iso-builds (Trigger + Liste), GET
/api/v1/iso-builds/{id} (Status-Poll) und .../download (fertige ISO
ausliefern). Aeltere abgeschlossene Builds derselben Organisation werden
nach einem erfolgreichen neuen Build automatisch aufgeraeumt (Datei +
DB-Zeile) - anodes Root-Dateisystem ist mit 28GB knapp bemessen.

WLAN-Zugangsdaten werden bewusst nicht in iso_builds gespeichert, nur
transient an build_customer_iso.sh durchgereicht.

Lokal end-to-end gegen einen Wegwerf-Postgres-Container verifiziert (alle
Migrationen 0001-0016, echter build_customer_iso.sh-Lauf gegen die
gecachte Mint-ISO, Status-Uebergaenge pending->running->completed,
Download-Endpunkt liefert byte-identische Datei, Cleanup-Logik entfernt
den vorherigen Build einer Organisation nach dem naechsten erfolgreichen
Bau). Testorganisation danach wieder geloescht.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-07 00:39:32 +02:00
896c22c537 feat: Enrollment-Session-Verbrauch, Organisations-PATCH, strukturierte Partitionierung (Phase 3)
/api/v1/activate akzeptiert jetzt zusätzlich Enrollment-Session-Codes
(die Session-id selbst dient als Bearer-Credential, kein neues
code-Feld nötig) neben den bestehenden organisationsweiten
Aktivierungscodes - fällt bei Nicht-UUID sofort auf den klassischen
Pfad zurück, kein Konflikt. Prüft Widerruf/Ablauf/Kontingent, zählt
devices_used bei Erfolg hoch. Ungültige Sessions melden denselben
invalid_activation_code-Fehlschlag wie ein ungültiger klassischer
Code - das bricht den Installer schon beim Server-Handshake ab, lange
vor jeder destruktiven Aktion (siehe ADR-0008), kein zusätzlicher
Mechanismus nötig.

Antwort-templates werden bei Enrollment-Session-Aktivierung auf die
eine zur Session gehörende Vorlage gefiltert und mit is_default=true
markiert - der bereits in tuxflotte-installer Phase 2 gebaute
Auto-Modus (wählt automatisch die als is_default markierte Vorlage)
funktioniert dadurch ohne jede Installer-Änderung korrekt.

organizations: neuer PATCH-Endpoint (nur Name, weitere Felder bewusst
noch offen).

bereitstellungsvorlagen.partitioning: von TEXT auf JSONB umgestellt,
bestehende "default"-Werte auf {"scheme": "single", "root_filesystem":
"ext4"} migriert - das ist der Vertrag, den tuxflotte-installers
backend_generate_config() (Phase 2) bereits erwartet.

Lokal gegen eine Wegwerf-Postgres mit allen Migrationen 0001-0015
verifiziert: Enrollment-Session-Aktivierung (Vorlagen-Filterung,
is_default-Erzwingung, devices_used-Zählung), Kontingent-Erschöpfung,
Widerruf, Ablauf, Rückfall auf klassische Aktivierungscodes
(Regression), PATCH organizations (Erfolg + 404), /resolve liefert
partitioning jetzt korrekt als JSON-Objekt statt String.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 16:56:46 +02:00
5237606f49 feat: Google Earth Pro als Katalog-Merkmal
Merkmal + Blueprints (fedora, mint -> ansible_role 'google-earth')
in der app-store-Kategorie, analog zu LibreOffice nicht Teil von
workspace_merkmale (kein Basisbedarf, Kunde wählt aktiv).

Lokal gegen eine Wegwerf-Postgres mit allen Migrationen 0001-0014
verifiziert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 09:21:23 +02:00
bde9e92a80 feat: LibreOffice als Katalog-Merkmal
Merkmal + Blueprints (fedora, mint -> ansible_role 'libreoffice',
siehe ansible-content) in der app-store-Kategorie neben OnlyOffice.
Bewusst nicht Teil von workspace_merkmale - kein Gerät bekommt beide
Suiten automatisch, Kunde wählt aktiv im Auftragskatalog.

Lokal gegen eine Wegwerf-Postgres mit allen Migrationen 0001-0013
verifiziert (Katalog-Query liefert state=absent für beide Backends).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-06 08:45:14 +02:00
1e9020c5ba feat: enrollment_sessions Tabelle (ADR-0008)
Datenmodell für zeitlich begrenzte, organisationsgebundene Vorab-
Freigaben für geplante Massenrollouts. Verwaltung (anlegen/auflisten/
widerrufen) folgt in einem späteren Schritt zusammen mit der
Neugerät-Bestätigung im Kundenplattform-Admin-Bereich. Der eigentliche
Verbrauch (Auto-Modus-Gate im Installer) ist bewusst nicht Teil dieser
Migration - separates, noch nicht begonnenes Folgeprojekt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 08:52:09 +02:00
dc1637de7e feat: Mint als Default-Bereitstellungsvorlage statt Fedora
Fedora-Installer wurde zurückgestellt, Fokus liegt auf Mint (siehe
Rollen-Umbenennung in ansible-content, Migration 0010). Neue Geräte ohne
explizite Vorlagen-Auswahl bekommen jetzt standardmäßig die
Mint-Bereitstellungsvorlage zugewiesen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 16:27:58 +02:00
6fe3b6f81b refactor: blueprints.ansible_role auf distro-unabhängige Rollennamen
Begleitet die Umbenennung in ansible-content (brave-fedora/brave-mint ->
brave, onlyoffice-fedora/onlyoffice-mint -> onlyoffice). Beide Backends
nutzen ab jetzt dieselbe Flatpak-basierte, distro-unabhängige Rolle statt
zweier getrennter (von denen die -mint-Variante nie implementiert war).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 16:20:06 +02:00
05a80f0998 feat: Auftragskatalog-Auswahl-API und optionen-Passthrough
Neue Migrationen 0008 (device_merkmale.optionen JSONB) und 0009 (Kategorien
app-store/individuelle-systemkonfiguration, Katalogfähigkeit für
guest-session-ephemeral/browser-brave/office-onlyoffice). Check-in-Antwort
gibt optionen je Auftrag mit. Neue admin-token-geschützte Endpoints zum
Auflisten/Auswählen/Abwählen von Aufträgen pro Gerät.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 15:28:49 +02:00
eb73f2b6b7 feat: extend agent check-in with Auftragskatalog state, add report endpoint
Check-in now also returns "auftraege": the full present/absent state
of every catalog-eligible Merkmal (im_auftragskatalog = true) for the
device's backend, derived statelessly from device_merkmale rather than
just the workspace-resolved blueprints list, which stays untouched.
This is what lets a deselected Auftrag actually be reverted once the
corresponding Ansible role grows an absent branch (ADR-0010) - the
agent doesn't have that branch yet, so this is additive and inert
until it does.

Adds POST /api/v1/agent/report so the agent can write execution
results (applied/apply_failed/removed/remove_failed) back into
device_merkmal_events; selected/deselected is intentionally rejected
here since those are meant to come from wherever Auftrag selection
ends up being triggered, not from the agent itself.

Migration 0007 adds the backing tables (kategorien, device_merkmale,
device_merkmal_events) and the two new merkmale columns.

Verified against anode: checkin toggles present/absent correctly
after inserting a device_merkmale row, report endpoint accepts valid
entries and rejects unknown merkmale / non-agent event types / bad
secrets, and the written event round-trips through device_merkmal_events
correctly as jsonb.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 09:17:19 +02:00
341ef92a7a feat: add provisioning agent bootstrap and check-in endpoints
Adds POST /api/v1/agent/bootstrap (issues a hashed agent secret for a
device) and POST /api/v1/agent/checkin (Bearer-authenticated, resolves
the device's assigned blueprints via its Bereitstellungsvorlage and
returns them alongside the ansible-content repo URL and poll
interval). Migration 0006 adds the backing columns on devices
(agent_secret_hash, agent_secret_issued_at, agent_last_checkin).

This was implemented and verified end to end (activate -> resolve ->
bootstrap -> checkin, plus a full QEMU agent test) in an earlier
session but never committed to this repo, even though it has been
running in production on anode since. Committing now to close that
gap before building on top of it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 09:16:58 +02:00
11186dfdf9 feat: migrate provisioning API to Merkmal/Blueprint/Bereitstellungsvorlage model
Replaces the config.json-backed flat profile model with the
Postgres-backed Workspace/Merkmal/Backend/Blueprint/Bereitstellungsvorlage
schema (migrations 0003-0005). /api/v1/activate now returns Bereitstellungsvorlage
templates instead of profiles, and a new POST /api/v1/templates/{id}/resolve
endpoint resolves a chosen template to a full Runtime Blueprint (workspace,
backend, resolved Merkmal->Ansible-role blueprints, and installation
directives), recording the resulting device assignment.

Removes the now-unused config.json and file-based device registry
directory in favor of the PostgreSQL-backed activation codes and
device tables.
2026-07-18 10:48:29 +02:00
2683b65ffc feat: migrate device registry to PostgreSQL 2026-07-12 15:22:22 +02:00
8d70236ef5 feat: add PostgreSQL persistence foundation 2026-07-12 14:33:31 +02:00