Files
proxui/proxmox-console-entwicklungsplan.md
T
2026-06-09 20:31:08 +02:00

373 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Proxmox Multi-Tenant Console — Entwicklungsplan
Plan zur Übergabe an einen ausführenden AI-Agenten. Jede Aufgabe ist so geschnitten, dass sie eigenständig umsetzbar, testbar und reviewbar ist. Arbeite die Epics in Reihenfolge ab; innerhalb eines Epics geben die `Abhängigkeiten` die Reihenfolge vor.
---
## 0. Stack-Entscheidungen (verbindlich)
Diese Entscheidungen sind getroffen. Nicht abweichen, ohne Rückfrage.
| Bereich | Entscheidung |
|---|---|
| Auth | Supabase Auth (E-Mail/Passwort, OAuth, TOTP/2FA) |
| Datenbank | Supabase Postgres (direkter Postgres-Zugriff, **nicht** über PostgREST) |
| Backend | **Go** (>= 1.22), HTTP-Framework: `chi`; DB-Zugriff: `pgx` + `sqlc` für typsichere Queries |
| Migrations | `golang-migrate` (SQL-Files, versioniert) |
| Worker / Queue | Eigener Go-Worker + `asynq` (Redis-basiert) |
| Konsolen-Proxy | Eigener Go-Dienst (Websocket), `nhooyr.io/websocket` |
| Proxmox-Client | Eigener dünner HTTP-Client (keine fertige Lib zwingend; falls Lib, dann nur als Referenz) |
| Frontend | React + TypeScript, Vite, TanStack Query, Tailwind, shadcn/ui |
| Konsole-Rendering | noVNC (VNC) bzw. xterm.js (Serial) |
| Secrets | Master-Key aus ENV/Secret-Manager; Cluster-Tokens **verschlüsselt** in DB (AES-GCM, Envelope) |
> Falls Python statt Go gewünscht ist: ersetze die Go-spezifischen Schritte sinngemäß (FastAPI + SQLAlchemy/asyncpg + Celery), die Architektur bleibt identisch.
### Architektur-Grundregeln (gelten für ALLE Aufgaben)
1. **Nur das Backend spricht mit Proxmox.** Kein Proxmox-Token, kein Proxmox-Hostname erreicht jemals das Frontend.
2. **Supabase liefert Identität, das Backend macht Autorisierung.** JWT wird gegen Supabase-JWKS validiert; Rollen/Rechte kommen aus eigenen Tabellen.
3. **Source of Truth ist die eigene DB.** Proxmox ist Ausführungsebene. Ein Reconciliation-Job gleicht Drift ab.
4. **Multi-Cluster von Anfang an.** Alle Proxmox-Zugriffe gehen über eine `cluster_id`.
5. **Jede tenant-bezogene Query trägt `WHERE tenant_id = $1`.** RLS bleibt zusätzlich aktiv (Defense in depth).
6. **Sensible Felder (Token, Secrets) niemals in DTOs/API-Responses mappen.**
---
## 1. Konventionen für den Agenten
- **Sprache:** Code-Identifier und Commits auf Englisch; UI-Texte auf Deutsch.
- **Branches:** ein Branch pro Aufgabe, Name = Task-ID (z.B. `E2-T03-schema-tenants`).
- **Commits:** Conventional Commits (`feat:`, `fix:`, `chore:`, `test:`).
- **Definition of Done pro Task:** Code + Tests grün + Lint sauber + kurze Notiz in `CHANGELOG.md`, was umgesetzt wurde und welche Annahmen getroffen wurden.
- **Keine echten Credentials im Repo.** `.env.example` pflegen, echte `.env` in `.gitignore`, Secret-Scanner in CI.
- **Tests:** Unit-Tests für Krypto/Auth/Autorisierung sind Pflicht. Für Proxmox-Calls einen Mock-Server bauen (kein Live-Cluster in CI).
- **Bei Unklarheit:** Annahme dokumentieren und weiterarbeiten, nicht blockieren — außer es betrifft Sicherheit (dann stoppen und nachfragen).
---
## EPIC E0 — Projekt-Setup & Infrastruktur
### E0-T01 — Monorepo-Grundgerüst
- **Ziel:** Repo-Struktur stehen.
- **Schritte:** Ordner `backend/`, `worker/`, `console-proxy/`, `frontend/`, `migrations/`, `deploy/`. Root-`README.md`, `CHANGELOG.md`, `.gitignore`, `.env.example`.
- **Akzeptanz:** Repo klont sich, `README` erklärt Setup in <10 Schritten.
- **Abhängigkeiten:** keine.
### E0-T02 — Lokale Dev-Umgebung
- **Ziel:** Alles lokal startbar.
- **Schritte:** `docker-compose.yml` mit Supabase CLI Stack (Postgres + Auth + Studio) und Redis. Makefile-Targets: `make dev`, `make migrate`, `make test`, `make lint`.
- **Akzeptanz:** `make dev` bringt Postgres, Auth, Redis hoch; Studio erreichbar.
- **Abhängigkeiten:** E0-T01.
### E0-T03 — CI-Pipeline
- **Ziel:** Automatische Qualitätssicherung.
- **Schritte:** GitHub Actions (oder gewähltes CI): Build, Lint (`golangci-lint`, `eslint`), Tests, Secret-Scan (`gitleaks`).
- **Akzeptanz:** PR ohne grüne CI ist nicht mergebar.
- **Abhängigkeiten:** E0-T01.
### E0-T04 — Konfigurations- & Logging-Layer
- **Ziel:** Saubere Config und strukturierte Logs.
- **Schritte:** Config aus ENV (z.B. `envconfig`), validiert beim Start. Strukturiertes Logging (`slog`), Request-IDs, keine Secrets in Logs.
- **Akzeptanz:** Fehlt eine Pflicht-ENV, bricht der Start mit klarer Meldung ab.
- **Abhängigkeiten:** E0-T01.
---
## EPIC E1 — Auth & JWT-Middleware
### E1-T01 — Supabase-Projekt & Auth-Konfiguration
- **Ziel:** Auth nutzbar.
- **Schritte:** Supabase-Projekt anlegen (oder CLI lokal). E-Mail/Passwort aktivieren, mind. einen OAuth-Provider, TOTP/2FA aktivieren. JWKS-URL und Issuer notieren.
- **Akzeptanz:** Test-User kann sich registrieren und JWT erhalten.
- **Abhängigkeiten:** E0-T02.
### E1-T02 — JWT-Validierungs-Middleware (Backend)
- **Ziel:** Eingehende Requests authentifizieren.
- **Schritte:** Middleware, die `Authorization: Bearer <jwt>` liest, Signatur gegen Supabase-JWKS prüft (JWKS cachen + periodisch refreshen), Issuer/Expiry validiert. `sub`-Claim (= Supabase-User-ID) in den Request-Context legen. Bei ungültig: 401.
- **Akzeptanz:** Unit-Test mit gültigem, abgelaufenem und manipuliertem Token (jeweils korrektes Verhalten). Geschützter Endpunkt ohne Token → 401.
- **Abhängigkeiten:** E1-T01.
### E1-T03 — Profil-Sync (auth.users → public.profiles)
- **Ziel:** Eigene Nutzer-Entität verknüpft mit Supabase.
- **Schritte:** Beim ersten authentifizierten Request: falls kein `profiles`-Eintrag zur `sub`-ID existiert, anlegen (lazy provisioning). Alternativ Supabase DB-Trigger auf `auth.users`. Eine Variante wählen und dokumentieren.
- **Akzeptanz:** Nach Erstlogin existiert genau ein `profiles`-Datensatz.
- **Abhängigkeiten:** E1-T02, E2-T02.
---
## EPIC E2 — Datenmodell & Migrations
> Alle Tabellen ins `public`-Schema. `profiles.id` referenziert `auth.users.id`. RLS auf allen tenant-bezogenen Tabellen aktivieren.
### E2-T01 — Migrations-Setup
- **Ziel:** Versionierte Schema-Änderungen.
- **Schritte:** `golang-migrate` einbinden, `make migrate` / `make migrate-down`. Namens-Schema `NNNN_beschreibung.up.sql` / `.down.sql`.
- **Akzeptanz:** Up und Down laufen idempotent durch.
- **Abhängigkeiten:** E0-T02.
### E2-T02 — Kern-Tabellen: profiles, tenants, memberships
- **Ziel:** Mandanten- und Nutzergrundlage.
- **Schritte:**
- `profiles` (id = auth.users.id, email, display_name, created_at)
- `tenants` (id, name, slug, status, created_at)
- `memberships` (profile_id, tenant_id, role enum: owner|admin|member|viewer, UNIQUE(profile_id, tenant_id))
- **Akzeptanz:** Migration läuft; FKs und Indizes gesetzt; ein User kann mehreren Tenants angehören.
- **Abhängigkeiten:** E2-T01.
### E2-T03 — Projekte & Quotas
- **Ziel:** Projektebene wie bei Hetzner.
- **Schritte:**
- `projects` (id, tenant_id FK, name, created_at)
- `project_quotas` (project_id FK, max_vcpu, max_ram_mb, max_disk_gb, max_vms)
- **Akzeptanz:** Projekte gehören eindeutig zu einem Tenant; Quota-Defaults gesetzt.
- **Abhängigkeiten:** E2-T02.
### E2-T04 — Clusters-Tabelle (verschlüsselte Credentials)
- **Ziel:** Multi-Cluster-Zugriff sicher.
- **Schritte:**
- `clusters` (id, name, api_endpoint, tls_fingerprint, `encrypted_token` bytea, token_id text, status, created_at)
- Klartext-Token **nie** speichern. Verschlüsselung kommt aus E3.
- **Akzeptanz:** Spalte `encrypted_token` ist `bytea`; kein Klartext-Feld vorhanden.
- **Abhängigkeiten:** E2-T01.
### E2-T05 — VMs & Ressourcen-Mapping
- **Ziel:** Eigene Sicht auf VMs (Source of Truth).
- **Schritte:**
- `vms` (id, project_id FK, cluster_id FK, proxmox_vmid int, node text, name, status, vcpu, ram_mb, disk_gb, created_at)
- `ssh_keys` (id, tenant_id FK, name, public_key, created_at)
- Index auf (cluster_id, proxmox_vmid) UNIQUE.
- **Akzeptanz:** VM ist eindeutig einem Projekt und einem Cluster zugeordnet.
- **Abhängigkeiten:** E2-T03, E2-T04.
### E2-T06 — VMID-Allokator
- **Ziel:** Race-freie, clusterweit eindeutige VMID-Vergabe.
- **Schritte:** Tabelle oder Sequence pro Cluster; Vergabe in einer Transaktion mit `SELECT ... FOR UPDATE` oder Postgres-Sequence. Vergebene IDs reservieren, bevor Proxmox-Call startet.
- **Akzeptanz:** Concurrency-Test mit 50 parallelen Anfragen erzeugt keine Doppel-VMID.
- **Abhängigkeiten:** E2-T05.
### E2-T07 — Audit-Log-Tabelle
- **Ziel:** Nachvollziehbarkeit.
- **Schritte:** `audit_log` (id, tenant_id, profile_id, action, target_type, target_id, metadata jsonb, created_at). Append-only.
- **Akzeptanz:** Tabelle vorhanden, indiziert auf (tenant_id, created_at).
- **Abhängigkeiten:** E2-T02.
### E2-T08 — RLS-Policies
- **Ziel:** DB-seitige Mandanten-Isolation als zweite Verteidigungslinie.
- **Schritte:** RLS auf tenants/projects/vms/ssh_keys/audit_log aktivieren; Policies auf Basis der Mitgliedschaft. Service-Role des Backends ist dokumentiert ausgenommen (Backend macht eigene Filterung).
- **Akzeptanz:** Direkter Query als Nicht-Mitglied liefert keine fremden Zeilen.
- **Abhängigkeiten:** E2-T02 bis E2-T07.
---
## EPIC E3 — Proxmox-Zugriffsschicht
### E3-T01 — Krypto-Layer (Envelope-Encryption)
- **Ziel:** Cluster-Tokens sicher ver-/entschlüsseln.
- **Schritte:** AES-GCM mit 32-Byte-Master-Key aus ENV/Secret-Manager. Nonce wird dem Ciphertext vorangestellt. Funktionen `Encrypt(plaintext)` / `Decrypt(ciphertext)`. Key-Versionierung vorsehen (Prefix-Byte), um spätere Rotation zu ermöglichen.
- **Akzeptanz:** Roundtrip-Unit-Test; falscher Key → Fehler statt Müll; Master-Key fehlt → Start bricht ab.
- **Abhängigkeiten:** E0-T04.
### E3-T02 — Cluster-Repository
- **Ziel:** Cluster-Credentials laden/speichern.
- **Schritte:** `GetCluster(id)` lädt und entschlüsselt das Token im Speicher; `UpsertCluster` verschlüsselt vor dem Speichern. Token nie loggen, nie in DTO.
- **Akzeptanz:** Test: gespeichertes Token kommt entschlüsselt korrekt zurück; DB enthält nur Ciphertext.
- **Abhängigkeiten:** E3-T01, E2-T04.
### E3-T03 — Proxmox-HTTP-Client mit TLS-Pinning
- **Ziel:** Sichere Verbindung zum Cluster.
- **Schritte:** HTTP-Client, der pro Cluster den `tls_fingerprint` prüft (kein `InsecureSkipVerify`). Auth-Header `PVEAPIToken=<token_id>=<secret>`. Methoden: `Get/Post/Put/Delete` mit Retry + Timeout + Kontext.
- **Akzeptanz:** Verbindung gegen Mock-Server mit korrektem/falschem Fingerprint (akzeptiert/abgelehnt). Kein Klartext-Secret in Logs.
- **Abhängigkeiten:** E3-T02.
### E3-T04 — Admin-Endpunkt: Cluster verwalten
- **Ziel:** Cluster anlegen/Token rotieren ohne Deployment.
- **Schritte:** Interner Endpunkt (nur Operator-Rolle, **nicht** für Kunden): Cluster anlegen, Token aktualisieren, Status setzen. Response enthält nie das Token.
- **Akzeptanz:** Token-Rotation per Request ändert nur `encrypted_token`; alter Wert nicht mehr lesbar.
- **Abhängigkeiten:** E3-T03, E4-T02.
---
## EPIC E4 — Autorisierung (RBAC)
### E4-T01 — Mitgliedschafts-Resolver
- **Ziel:** Vom JWT zur Berechtigung.
- **Schritte:** Aus `sub``profiles``memberships` laden; aktuellen Tenant/Projekt aus Request ableiten; Rolle ermitteln. Im Context bereitstellen.
- **Akzeptanz:** Nicht-Mitglied eines Tenants erhält bei tenant-Zugriff 403.
- **Abhängigkeiten:** E1-T02, E2-T02.
### E4-T02 — Policy-/Permission-Funktion
- **Ziel:** Zentrale `Can(role, action, resource)`-Prüfung.
- **Schritte:** Rollen-Matrix (owner/admin/member/viewer × Aktionen wie vm.read, vm.power, vm.create, vm.delete, project.manage, cluster.manage[nur Operator]). Eine Funktion, überall aufgerufen.
- **Akzeptanz:** Tabellengetriebener Unit-Test deckt alle Rollen×Aktionen ab.
- **Abhängigkeiten:** E4-T01.
### E4-T03 — Autorisierungs-Middleware
- **Ziel:** Deklarativer Schutz pro Route.
- **Schritte:** Middleware/Helper, der vor Handler die nötige Permission prüft. Quota-Check als separater Helper für create-Aktionen.
- **Akzeptanz:** Geschützte Route ohne Recht → 403; mit Recht → durch.
- **Abhängigkeiten:** E4-T02.
---
## EPIC E5 — VM-Lifecycle (synchron lesend + Aktionen)
### E5-T01 — VM-Liste & Detail (read)
- **Ziel:** Kunden sehen ihre VMs.
- **Schritte:** Endpunkte `GET /projects/:id/vms` und `GET /vms/:id`. Daten aus eigener DB; Live-Status optional via Proxmox ergänzen. Immer tenant-/projektgefiltert.
- **Akzeptanz:** Nutzer sieht nur VMs seiner Projekte.
- **Abhängigkeiten:** E3-T03, E4-T03, E2-T05.
### E5-T02 — Power-Aktionen (start/stop/reboot)
- **Ziel:** VM steuern.
- **Schritte:** Endpunkte, die Permission `vm.power` prüfen, Proxmox-Call absetzen, die zurückgegebene UPID an den Worker übergeben (siehe E6), Audit-Log schreiben.
- **Akzeptanz:** Start einer VM erzeugt Task; Status wird nach Abschluss in DB aktualisiert.
- **Abhängigkeiten:** E5-T01, E6-T02, E2-T07.
### E5-T03 — Reconciliation-Job
- **Ziel:** Drift zwischen DB und Proxmox erkennen.
- **Schritte:** Periodischer Job, der pro Cluster den Ist-Zustand abruft und mit der DB abgleicht; Abweichungen markieren/loggen. Vorerst nur Reporting, kein Auto-Fix.
- **Akzeptanz:** Manuell in Proxmox gestoppte VM wird im nächsten Lauf als abweichend erkannt.
- **Abhängigkeiten:** E5-T01.
---
## EPIC E6 — Task-Worker (asynchron)
### E6-T01 — Worker-Grundgerüst
- **Ziel:** Eigener Dienst für lange Jobs.
- **Schritte:** Go-Worker mit `asynq`, Redis-Anbindung, Verbindung zur selben Supabase-DB über den **Connection Pooler (Supavisor)**. Graceful Shutdown.
- **Akzeptanz:** Worker startet, verarbeitet einen Dummy-Job.
- **Abhängigkeiten:** E0-T02, E2-T01.
### E6-T02 — UPID-Polling-Job
- **Ziel:** Proxmox-Tasks zu Ende verfolgen.
- **Schritte:** Job-Typ `proxmox.task.poll` (Input: cluster_id, node, UPID, ziel-Entität). Pollt Status bis Erfolg/Fehler, aktualisiert die betroffene Entität in der DB, schreibt Audit-Log. Timeout + max. Retries; bei Fehler Status `failed` + Fehlertext.
- **Akzeptanz:** Mock-Proxmox liefert „running" dann „stopped/OK" → DB-Status wird final korrekt; bei „error" → `failed`.
- **Abhängigkeiten:** E6-T01, E3-T03.
### E6-T03 — Cleanup bei Fehlschlag
- **Ziel:** Keine Zombie-Ressourcen.
- **Schritte:** Wenn ein Provisioning-Task scheitert, halbfertige VM in Proxmox entfernen oder als `failed` markieren und VMID freigeben.
- **Akzeptanz:** Simulierter Fehlschlag hinterlässt keine reservierte VMID und keine verwaiste VM.
- **Abhängigkeiten:** E6-T02, E2-T06.
---
## EPIC E7 — Provisioning (Clone + cloud-init)
### E7-T01 — SSH-Key-Verwaltung
- **Ziel:** Kunden hinterlegen Keys.
- **Schritte:** CRUD-Endpunkte für `ssh_keys` (tenant-gescoped), Validierung des Public-Key-Formats.
- **Akzeptanz:** Ungültiger Key wird abgelehnt; Keys sind tenant-isoliert.
- **Abhängigkeiten:** E4-T03, E2-T05.
### E7-T02 — Template-Vorbereitung (Doku + Skript)
- **Ziel:** cloud-init-fähige Templates pro Node.
- **Schritte:** Dokumentiertes Vorgehen + optionales Skript, um Cloud-Images (Ubuntu/Debian) als Proxmox-Templates anzulegen. In der DB eine `templates`-Referenz (id, cluster_id, name, proxmox_template_vmid).
- **Akzeptanz:** Mind. ein Template pro Test-Cluster auswählbar.
- **Abhängigkeiten:** E3-T03.
### E7-T03 — VM-Erstellung (Clone + cloud-init)
- **Ziel:** Self-Service-VM wie bei Hetzner.
- **Schritte:** `POST /projects/:id/vms`: Permission + Quota prüfen → VMID allokieren → Proxmox-Clone vom Template → cloud-init setzen (SSH-Key, Hostname, Netzwerk) → Start → UPID an Worker. DB-Eintrag mit Status `provisioning`.
- **Akzeptanz:** End-to-End gegen Mock: VM-Datensatz entsteht, Worker schließt ab, Status `running`. Quota-Überschreitung → 409.
- **Abhängigkeiten:** E7-T01, E7-T02, E6-T02, E2-T06, E4-T03.
### E7-T04 — VM löschen
- **Ziel:** Aufräumen sauber.
- **Schritte:** `DELETE /vms/:id` mit Permission `vm.delete`; Proxmox-Stop+Delete via Worker; DB-Eintrag und VMID freigeben; Audit-Log.
- **Akzeptanz:** Nach Löschung keine VM in DB/Proxmox, VMID wieder vergebbar.
- **Abhängigkeiten:** E7-T03.
---
## EPIC E8 — Konsolen-Proxy (noVNC)
### E8-T01 — Konsolen-Ticket-Endpunkt
- **Ziel:** Kurzlebigen Zugang ausstellen.
- **Schritte:** `POST /vms/:id/console`: Permission `vm.console` prüfen, von Proxmox VNC-Ticket holen, ein eigenes kurzlebiges, signiertes Proxy-Ticket an den Client geben (enthält keine Proxmox-Daten).
- **Akzeptanz:** Nicht-berechtigter Nutzer → 403; Ticket hat kurze Gültigkeit.
- **Abhängigkeiten:** E4-T03, E3-T03.
### E8-T02 — Websocket-Proxy-Dienst
- **Ziel:** Browser ↔ Proxmox-Konsole ohne direkte Verbindung.
- **Schritte:** Eigener Dienst, der das Proxy-Ticket validiert, **bei jedem Verbindungsaufbau** die Berechtigung erneut gegen die DB prüft, dann zur Proxmox-VNC-Websocket durchreicht. Kein Proxmox-Hostname zum Client.
- **Akzeptanz:** Verbindung mit gültigem Ticket funktioniert; abgelaufenes/fremdes Ticket wird abgewiesen.
- **Abhängigkeiten:** E8-T01.
---
## EPIC E9 — Audit-Log (Querschnitt)
### E9-T01 — Audit-Writer
- **Ziel:** Einheitliches Logging sicherheitsrelevanter Aktionen.
- **Schritte:** Helper `Audit(ctx, action, target, metadata)`. In allen state-ändernden Endpunkten aufrufen (power, create, delete, key-changes, cluster-admin).
- **Akzeptanz:** Jede schreibende Aktion erzeugt genau einen Audit-Eintrag.
- **Abhängigkeiten:** E2-T07.
### E9-T02 — Audit-Anzeige (read)
- **Ziel:** Transparenz für Tenant-Admins.
- **Schritte:** `GET /tenants/:id/audit` mit Paginierung, nur für admin/owner.
- **Akzeptanz:** Viewer/Member sehen kein Audit-Log.
- **Abhängigkeiten:** E9-T01, E4-T03.
---
## EPIC E10 — Frontend MVP
### E10-T01 — App-Grundgerüst & Auth
- **Ziel:** Login funktioniert.
- **Schritte:** Vite + React + TS, Supabase JS-Client nur für Auth (Login/Logout/2FA), JWT im Speicher halten, an Backend-Calls per `Authorization`-Header anhängen. API-Layer mit TanStack Query.
- **Akzeptanz:** Nutzer kann sich einloggen, 2FA durchlaufen, Token wird an Backend gesendet.
- **Abhängigkeiten:** E1-T01.
### E10-T02 — Tenant-/Projekt-Umschalter & Mitgliederverwaltung
- **Ziel:** Multi-Tenant-Navigation.
- **Schritte:** Tenant-Switcher, Projektliste, Einladen/Rollen-Zuweisung (admin/owner). Layout im Hetzner-Stil (clean, shadcn/ui).
- **Akzeptanz:** Wechsel zwischen Tenants lädt jeweils nur eigene Projekte.
- **Abhängigkeiten:** E10-T01, E4-T03.
### E10-T03 — VM-Übersicht & Detail
- **Ziel:** Kern-UI.
- **Schritte:** VM-Liste mit Status, Detailseite mit Basis-Metriken, Power-Buttons (start/stop/reboot), Live-Status via Polling/Refetch.
- **Akzeptanz:** Power-Aktion spiegelt sich nach Task-Abschluss in der UI.
- **Abhängigkeiten:** E10-T02, E5-T02.
### E10-T04 — VM-Erstellungs-Wizard
- **Ziel:** Self-Service-Provisioning.
- **Schritte:** Wizard (Template, Größe, SSH-Key, Name), Quota-Anzeige, Fortschritt während `provisioning`.
- **Akzeptanz:** Erstellte VM erscheint und wechselt nach Abschluss auf `running`.
- **Abhängigkeiten:** E10-T03, E7-T03.
### E10-T05 — Web-Konsole
- **Ziel:** noVNC im Browser.
- **Schritte:** noVNC-Komponente, holt Ticket vom Backend, verbindet sich mit dem Konsolen-Proxy.
- **Akzeptanz:** Funktionierende Konsole für berechtigte Nutzer.
- **Abhängigkeiten:** E10-T03, E8-T02.
### E10-T06 — SSH-Keys & Audit-Ansicht
- **Ziel:** Restliche MVP-Verwaltung.
- **Schritte:** Key-Verwaltung-UI; Audit-Log-Ansicht für Admins.
- **Akzeptanz:** Keys verwaltbar; Audit nur für Admins sichtbar.
- **Abhängigkeiten:** E7-T01, E9-T02.
---
## Phase 2 & 3 (Backlog, nach MVP)
Grob umrissen — bei Bedarf nach demselben Schema (Ziel/Schritte/Akzeptanz/Abhängigkeiten) herunterbrechen.
- **Phase 2:** Snapshots & Backups (Proxmox Backup Server), VM-Resize/Rebuild, Firewall-Regeln pro VM (Proxmox-Firewall-API), private Netzwerke via SDN/VNet pro Tenant, Floating IPs (eigener IP-Pool), feinere Quota-Durchsetzung.
- **Phase 3:** Metriken-Dashboards (Proxmox-Metriken nach Prometheus/InfluxDB exportieren), Usage-Tracking als Abrechnungsgrundlage, öffentliche API mit Projekt-Tokens (Terraform-Support), E-Mail-Benachrichtigungen, ISO-Mounts, LXC-Container, Load Balancer.
---
## Empfohlene Bearbeitungsreihenfolge (kritischer Pfad)
```
E0 → E1 → E2 → E3 → E4 → E6 (Grundgerüst) → E5 → E7 → E8 → E9 → E10
```
E9 (Audit) und E10 (Frontend) laufen teils parallel, sobald die jeweiligen Backend-Endpunkte stehen. E6-T01 sollte früh kommen, weil E5/E7 darauf aufbauen.