CRUD-Endpoints für den Admin-Bereich "Verwaltung -> Technik/Datenbank":
Merkmale (inkl. Kategorie-Zuordnung, im_auftragskatalog-Flag),
Kategorien, Workspaces samt Zusammensetzung aus Merkmalen
(workspace_merkmale hinzufügen/entfernen - Kernbaustein des später
geplanten Workspace-Creators). Backends/Blueprints nur lesend, da deren
Änderung echten Ansible-Rollen-Code voraussetzt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Neuer Endpoint GET /api/v1/devices (alle Geräte, Organisationsname
gejoint) für den Admin-Bereich "Verwaltung -> Geräte".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Neue Endpoints GET/POST /api/v1/organizations und GET/POST
/api/v1/organizations/{id}/activation-codes für den neuen Kunden-
Management-Bereich der Kundenplattform. Aktivierungscodes werden
serverseitig generiert (kein manuelles Ausdenken nötig).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
Neue Env-Var TUXFLOTTE_KUNDENPLATTFORM_TOKEN, require_admin_token zu
require_service_token verallgemeinert (akzeptiert Admin- oder
Kundenplattform-Token). Neuer GET /api/v1/organizations/{id}/devices
Endpoint für Kundenplattforms Geräteliste + Besitz-Validierung (ADR-0011).
Bestehende Auftragskatalog-Endpoints akzeptieren jetzt beide Tokens.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
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>
data/ ist Laufzeit-Gerätespeicher (z.B. Hardware-Snapshots), keine
Quelldatei. *.bak-* ist die etablierte Namenskonvention der bisherigen
scp-Backups vor jedem Deploy - beides soll git status auf anode sauber
halten, jetzt wo dort direkt gepullt statt gescpt wird.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ohne das Flag interpretiert Kickstart --password als bereits gehashten
Wert - das Klartext-Passwort würde fehlinterpretiert und der Login
schlägt fehl. War bereits live auf anode direkt gefixt, aber nie
committed (Fund beim Aufräumen des dortigen Checkouts).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
fetch_auftragskatalog_state() hardcoded absent as the default when no
device_merkmale row exists (COALESCE(dm.aktiv, FALSE)), regardless of
whether the Merkmal is part of the device's workspace. Since the
catalog is meant to be the same pool of Merkmale that workspaces are
composed from (see ADR-0010's clarification), that default was wrong:
flagging an already workspace-composed, actively-in-use Merkmal as
catalog-eligible would silently remove it from every device using
that workspace on their next check-in, without anyone ever deselecting
it.
Now joins workspace_merkmale for the device's assigned workspace and
defaults to present when the Merkmal is a member, absent otherwise;
an explicit device_merkmale row always overrides that default in
either direction. Verified against anode: catalog-eligible + already
workspace-composed Merkmal now defaults to present with no
device_merkmale row, explicit aktiv=false overrides to absent,
explicit aktiv=true overrides back to present.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
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>
runtime_blueprint.backend_id/workspace_id must be the stable, distro-neutral
key (e.g. "fedora") as documented in 08-provisioning-api.md, not the
internal database UUID - the installer's backend dispatch
(backends/${backend_id}/backend.sh) depends on it being a directory-safe
key.
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.