docs: Projektorganisation, Architekturplan und Issues pro Phase (#001)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-17 19:42:04 +02:00
co-authored by Claude Opus 5
commit a54c1b6285
20 changed files with 721 additions and 0 deletions
+53
View File
@@ -0,0 +1,53 @@
# Abhängigkeiten
node_modules/
.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
# Next.js / Build
.next/
out/
build/
dist/
*.tsbuildinfo
next-env.d.ts
# Tests
coverage/
test-results/
playwright-report/
# Umgebungsvariablen
.env
.env.*
!.env.example
# Lokale Datenbanken / Daten
*.db
*.sqlite
*.sqlite3
/data/
/postgres-data/
/uploads/
# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
*.log
# Betriebssystem / Editor
.DS_Store
Thumbs.db
.idea/
.vscode/*
!.vscode/extensions.json
*.swp
# Vercel / Sonstiges
.vercel
*.pem
+20
View File
@@ -0,0 +1,20 @@
# Changelog
Alle nennenswerten Änderungen an ProxLedger werden in dieser Datei dokumentiert.
Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/),
und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).
## [Unveröffentlicht]
### Hinzugefügt
- Projektorganisation: Devlog, Changelog, Issue-Übersicht und Issues pro Phase (#001)
- Architektur- und Umsetzungsplan in `docs/architektur.md` (#001)
### Geändert
### Behoben
### Entfernt
### Sicherheit
+39
View File
@@ -0,0 +1,39 @@
# DEVLOG – ProxLedger
## Zeitübersicht
**Gesamt:** 0 h 00 min (laufende Sitzung nicht eingerechnet)
| Issue | Zeit |
|---|---|
| #001 Projekt-Setup | 0 h 00 min |
| Meilenstein | Zeit |
|---|---|
| v0.1.0 | 0 h 00 min |
---
## 2026-09-17 · Sitzung 1 · 19:36–laufend
**Issue:** #001 Projekt-Setup
**Version:** 0.1.0-dev
### Erledigt
- Auftrag gelesen, Rückfragen gestellt
- Umgebung geprüft: Ubuntu 26.04, Git 2.53; Node/Docker fehlten → Node 24 LTS per nvm installiert
- Repository-Rechte korrigiert (Verzeichnis gehörte root), Branch `master` → `main`, Git-Identität lokal gesetzt
- `.gitignore`, `CHANGELOG.md`, `DEVLOG.md`, Architekturplan und 15 Issues angelegt
### Entscheidungen
- **AdminLTE 4.9.1 nur als CSS:** stabil, Bootstrap 5.3.8, kein jQuery; die JS-Plugins manipulieren das DOM und werden daher als React-Komponenten nachgebaut.
- **Host-Identität über Agent-Token statt Server-ID:** Die Server-ID ändert sich bei Hardwaretausch und soll dann eine Warnung auslösen, statt einen neuen Host zu erzeugen.
- **Rechnungen mit Positionen:** Proxmox-Sammelbestellungen und Sammelrechnungen an Kunden sollen ohne doppelte Rechnungsnummern abbildbar sein.
- **Eigener Worker-Prozess** für zeitgesteuerte Warnregeln und Benachrichtigungen, unabhängig von Seitenaufrufen.
- **Prototyp direkt im Next.js-Projekt**, damit die Komponenten weiterverwendet werden.
### Probleme / offene Fragen
- Docker ist nicht installiert und `sudo` erfordert ein Passwort → Installation muss manuell erfolgen (benötigt ab #003).
- Offen: Rolle „readonly“ zusätzlich zu Admin? (vorläufig vorgesehen)
### Nächster Schritt
- Next.js-Grundgerüst (#001), danach Prototyp (#002)
+184
View File
@@ -0,0 +1,184 @@
# ProxLedger – Architektur- und Umsetzungsplan
Stand: 2026-09-17 · Version 0.1.0-dev
## 1. Überblick
```
Kundennetz A (NAT) Kundennetz B Betreiber
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────────────────┐
│ PVE-Host │ │ PBS-Host │ │ ProxLedger (Docker / LXC) │
│ proxledger-agent│─HTTPS─▶│ proxledger-agent│─────▶│ ┌────────┐ ┌───────────┐ │
│ (systemd-Timer) │ Push │ (systemd-Timer) │ Push │ │ web │ │ worker │ │
└──────────────────┘ └──────────────────┘ │ │Next.js │ │ Cron-Jobs │ │
│ └───┬────┘ └─────┬─────┘ │
│ └──── Postgres ┘ │
└──────────────────────────────┘
│ SMTP (M365) / Webhook
▼
E-Mail, Matrix, Zabbix, HA
```
- **Push-Modell:** Das Dashboard fragt nie aktiv bei Hosts an. Agents melden sich täglich per HTTPS.
- **web:** Next.js (App Router) liefert UI, Agent-API (`/api/agent/v1/*`) und `install.sh`/`proxledger-agent.sh`.
- **worker:** Derselbe Code-Stand, eigener Prozess (`node dist/worker.js`) für zeitgesteuerte Aufgaben:
Warnregeln auswerten, „keine Meldung seit 48 h“, Benachrichtigungen versenden, Zusammenfassungen.
- **PostgreSQL:** einzige Datenhaltung; PDF-Uploads auf einem Volume (`/data/uploads`), Metadaten in der DB.
## 2. Tech-Stack
| Bereich | Wahl | Begründung |
|---|---|---|
| Framework | Next.js (App Router), TypeScript strict | Vorgabe |
| ORM | Prisma + PostgreSQL | Vorgabe, Migrationen versioniert |
| UI | `admin-lte` 4.x **nur CSS** + Bootstrap 5.3 + eigene React-Komponenten | AdminLTE 4.9.1 ist stabil, jQuery-frei; die Vanilla-JS-Plugins (PushMenu, Treeview, CardWidget) manipulieren das DOM direkt und werden als React-Komponenten nachgebaut |
| Icons | Bootstrap Icons | AdminLTE-4-Standard |
| Schrift | Source Sans 3 über `next/font` (selbst gehostet) | kein externer Request zur Laufzeit |
| Validierung | zod (API und Server Actions) | Vorgabe |
| Auth | Auth.js (OIDC authentik + Credentials-Fallback) | ausgereift, App-Router-kompatibel |
| Passwörter/Tokens | argon2id (Passwörter), SHA-256 über 256-Bit-Zufallstoken (API-Tokens) | Token haben volle Entropie, SHA-256 reicht und ist schnell nachschlagbar |
| Scheduler | `croner` im Worker | leichtgewichtig, zeitzonenfähig |
| E-Mail | nodemailer (SMTP, STARTTLS 587, M365-tauglich) | |
| PDF | `@react-pdf/renderer` | kein Chromium im Container |
| Tests | Vitest; Integrationstests gegen Postgres (Docker) | |
| Agent | Bash, `curl`, Bordmittel; systemd-Service + Timer | Vorgabe |
Zeitzone der Anzeige: `Europe/Berlin`, Datenhaltung in UTC. Datumsformat `dd.MM.yyyy`, Währung EUR.
## 3. Datenmodell
Gegenüber dem Vorschlag im Auftrag zwei bewusste Änderungen:
1. **Host-Identität ist nicht die Server-ID.** Die Server-ID ändert sich bei Hardwaretausch/Neuinstallation – genau das soll
eine Warnung auslösen. Ein Host wird daher über seinen Agent-Token bzw. eine beim Enrollment erzeugte `agentId`
(abgeleitet aus `/etc/machine-id`) identifiziert; die Server-ID ist ein Attribut mit Historie. Meldet ein neu
registrierter Agent eine Server-ID, die bereits ein bestehender Host hatte, wird das als Neuinstallation erkannt und
zur Übernahme vorgeschlagen.
2. **Rechnungen sind eigene Entitäten mit Positionen.** Eine Proxmox-Bestellung enthält oft mehrere Keys, eine
Kundenrechnung oft mehrere Hosts. Jede Laufzeit verweist auf höchstens eine Einkaufs- und eine Verkaufsposition.
Marge = Verkauf netto − Einkauf netto der Position(en).
### Entitäten (vereinfacht)
```
Customer 1─n Site
Customer 1─n Host (customerId nullable → „nicht zugeordnet“)
Site 1─n Host
Host 1─n Report
Host 1─n SubscriptionKey (Key-Historie: key, firstSeen, lastSeen)
Host 1─n ServerIdHistory
Host 1─n SubscriptionPeriod (Laufzeit: startDate, endDate, key, status: vorgeschlagen|bestätigt)
SubscriptionPeriod n─1 PurchaseInvoiceItem ─n─1 PurchaseInvoice (Proxmox)
SubscriptionPeriod n─1 SalesInvoiceItem ─n─1 SalesInvoice (Kunde)
Host 1─n AgentToken (Hash, erstellt, zuletzt benutzt, widerrufen)
EnrollmentToken (Hash, gültig bis, max. Nutzungen, optional customerId/siteId)
Alert (type, severity, hostId?, customerId?, periodId?, fingerprint, openedAt, resolvedAt, acknowledgedAt)
Notification (alertId?, channel, sentAt, status) – Deduplizierung über Alert-Fingerprint
AlertRuleSetting (key, enabled, thresholds JSON)
NotificationChannel (type: email|webhook, config JSON, enabled)
User (email, name, role: admin|readonly, passwordHash?, oidcSubject?)
AuditLog (userId?, action, entity, entityId, diff JSON, createdAt)
Tag n─m Host
Attachment (PDF: path, mime, size, sha256) – an PurchaseInvoice / SalesInvoice
```
**PurchaseInvoice (Proxmox):** Rechnungsnummer, Rechnungsdatum, Fälligkeitsdatum, netto, brutto, Rabatt, Zahlungsart,
bezahlt (bool), Bezahldatum, PDF.
**SalesInvoice (Kunde):** erstellt (bool), Rechnungsnummer, Rechnungsdatum, Betrag netto/brutto, vom Kunden bezahlt (bool),
Bezahldatum, PDF.
USt-Satz standardmäßig 19 %, pro Rechnung überschreibbar. Beträge als `Decimal(12,2)`.
Das „Häkchen direkt in der Tabelle“ setzt den Status der verknüpften Rechnung. Existiert noch keine Rechnung, legt das
Häkchen eine Minimal-Rechnung an (Nummer später nachtragbar).
## 4. Agent-API
Basis: `/api/agent/v1`, nur JSON, strikt getrennt vom UI (eigene Route-Group, keine Session-Cookies, eigenes Rate-Limit).
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
| POST | `/enroll` | Enrollment-Token (Bearer) | Host registrieren → liefert `hostId` + host-spezifischen API-Token (einmalig im Klartext) |
| POST | `/report` | Host-Token (Bearer) | Statusbericht; Antwort enthält `latestAgentVersion`, `serverTime` |
| GET | `/ping` | Host-Token | Verbindungstest (`proxledger-agent --test`) |
| GET | `/install.sh`, `/agent.sh` | öffentlich | Installer und Agent-Skript (Version eingebettet) |
- zod-Schemas mit `nullable()` für alle optionalen Felder; unbekannte Felder werden ignoriert und geloggt.
- Rate-Limit: Token-Bucket im Prozess (pro IP und pro Token), z. B. 10 Anfragen/Minute; `429` mit `Retry-After`.
- Report-Verarbeitung in einer Transaktion: Report speichern → Host-Stammdaten aktualisieren → Key-/Server-ID-Historie →
Laufzeitvorschlag bei neuem `nextduedate` → betroffene Warnregeln neu auswerten.
- Nachgesendete (gepufferte) Reports tragen ihren Original-Zeitstempel (`collectedAt`) und werden idempotent über `reportId` (UUID vom Agent) angenommen.
## 5. Agent
- `install.sh`: prüft root/Produkt, lädt `proxledger-agent.sh` vom Dashboard, `enroll`, schreibt `/etc/proxledger/agent.conf` (600),
installiert `proxledger.service` + `proxledger.timer` (`OnCalendar=daily`, `RandomizedDelaySec=4h`, `Persistent=true`), erster Report sofort.
- Optionen: `--token`, `--url`, `--ca-cert`, `--uninstall`, `--update`, `--test`.
- Sammelt: Subscription (PVE/PBS/PMG), Hostname, FQDN, IPs, Cluster/Node, Produktversion, Kernel, Sockets, CPU-Modell, Uptime,
Anzahl Updates, Agent-Version, Zeitstempel. Fehlende Werte → `null`. JSON wird ohne `jq` erzeugt (eigene Escape-Funktion).
- Fehlschlag: 3 Versuche mit Backoff (30 s, 2 min, 8 min), danach Ablage in `/var/lib/proxledger/spool/`, beim nächsten Lauf nachsenden (max. 30 Dateien).
- Logging über `logger -t proxledger` bzw. stdout ins Journal.
- Update: nur wenn `AUTO_UPDATE=yes` in der Config oder manuell via `--update`; Prüfsumme vom Dashboard wird verifiziert.
## 6. Warnregeln
Regeln sind reine Funktionen `(Kontext) → AlertCandidate[]`, getrennt testbar. Der Worker gleicht Kandidaten mit offenen Alerts
ab (Fingerprint = Regel + Objekt-ID [+ Schwelle]): neue öffnen, verschwundene schließen, bestehende unverändert lassen.
Benachrichtigt wird nur beim Öffnen bzw. beim Wechsel auf eine höhere Stufe (30 → 14 → 7 Tage).
| Regel | Standard |
|---|---|
| Subscription läuft ab | 30 / 14 / 7 Tage |
| Status ≠ active | sofort |
| Sockets lizenziert ≠ physisch | sofort |
| Keine Meldung | 48 h |
| Server-ID geändert | sofort |
| Key von mehreren Hosts gemeldet | sofort |
| Host ohne Kunde | sofort (nur Info) |
| Proxmox-Rechnung unbezahlt, Fälligkeit | ≤ 7 Tage |
| Verlängert/bezahlt, Kundenrechnung fehlt | sofort |
| Kundenrechnung unbezahlt | nach 30 Tagen |
## 7. Sicherheit
- UI-Routen per Middleware geschützt (ab #013). **Bis dahin nicht öffentlich betreiben.**
- Tokens: 32 Byte Zufall, Präfix `plx_e_` (Enrollment) / `plx_h_` (Host), in der DB nur SHA-256-Hash; einzeln widerrufbar.
- Audit-Log für alle schreibenden Server Actions (vor #013 mit Akteur „system“).
- Security-Header (CSP, HSTS hinter Reverse Proxy), Upload-Prüfung (nur PDF, max. 10 MB).
## 8. Projektstruktur
```
proxledger/
├─ agent/ Bash-Agent, Installer, systemd-Units
├─ deploy/ docker-compose, LXC-Installer, Beispiel-Proxy-Configs
├─ docs/ Architektur, Issues
├─ prisma/ schema.prisma, migrations, seed.ts
├─ public/ favicon.svg, Icons
├─ src/
│ ├─ app/
│ │ ├─ (dashboard)/ UI-Seiten (AdminLTE-Layout)
│ │ ├─ (auth)/login/
│ │ └─ api/agent/v1/ Agent-API
│ ├─ components/ Layout, Logo, SmallBox, Card, Badge, DataTable …
│ ├─ lib/ db, auth, tokens, validation, format
│ ├─ server/ Services (reports, alerts, invoices, notifications)
│ ├─ worker/ Scheduler-Einstiegspunkt
│ └─ mock/ Beispieldaten für den Prototyp
└─ tests/
```
## 9. Meilensteine
| Version | Inhalt | Issues |
|---|---|---|
| 0.1.0 | Projekt-Setup, Prototyp, Datenmodell, Agent-API | #001–#004 |
| 0.2.0 | Agent-Skript | #005 |
| 0.3.0 | Kunden, Standorte, Hostzuweisung, Enrollment-Tokens | #006 |
| 0.4.0 | Host-Tabelle, Suche, Detailansichten | #007 |
| 0.5.0 | Laufzeiten und Rechnungen | #008 |
| 0.6.0 | Kundenübersicht, Dashboard live, Jahresbahn, Export | #009, #010 |
| 0.7.0 | Warnregeln | #011 |
| 0.8.0 | Benachrichtigungen | #012 |
| 0.9.0 | Authentifizierung, Audit-Log | #013 |
| 0.10.0 | Deployment (Docker, LXC), Doku | #014 |
| 1.0.0 | Feinschliff, Dark-Mode, Mobil, Härtung | #015 |
+31
View File
@@ -0,0 +1,31 @@
# #001 Projekt-Setup
**Status:** in Arbeit
**Meilenstein:** v0.1.0
**Labels:** chore, infrastruktur
**Geschätzt:** 3 h **Tatsächlich:** –
## Ziel
Arbeitsfähiges Repository mit Projektorganisation (Devlog, Changelog, Issues) und einem lauffähigen Next.js-Grundgerüst inklusive AdminLTE-CSS, Linting und Prisma-Grundkonfiguration.
## Aufgaben
- [x] Git-Repository mit Branch `main`, `.gitignore`
- [x] `DEVLOG.md`, `CHANGELOG.md`, `docs/issues/` mit Übersicht
- [x] Architektur- und Umsetzungsplan (`docs/architektur.md`)
- [x] Issues pro Phase anlegen
- [ ] Next.js (App Router, TypeScript strict, `src/`) aufsetzen
- [ ] Abhängigkeiten: `admin-lte`, `bootstrap`, `bootstrap-icons`, zod
- [ ] ESLint + Prettier, `npm run lint`, `npm run typecheck`
- [ ] Version `0.1.0-dev` in `package.json`, Versionsanzeige-Helfer
- [ ] Vitest-Grundkonfiguration
## Akzeptanzkriterien
- [ ] `npm run dev` startet ohne Fehler
- [ ] `npm run lint` und `npm run typecheck` sind grün
- [ ] Keine Remote-URL in Projektdateien
## Abhängigkeiten
–
## Notizen / Entscheidungen
- AdminLTE 4.9.1 (Bootstrap 5.3.8) ist stabil und jQuery-frei. Es wird **nur das CSS** eingebunden; die interaktiven Teile (Sidebar-Toggle, Treeview, Card-Widgets) werden als React-Komponenten nachgebaut, weil die AdminLTE-Plugins das DOM direkt manipulieren.
- Node 24 LTS über nvm (Benutzerinstallation).
+31
View File
@@ -0,0 +1,31 @@
# #002 Klickbarer Prototyp
**Status:** offen
**Meilenstein:** v0.1.0
**Labels:** ui, prototyp
**Geschätzt:** 8 h **Tatsächlich:** –
## Ziel
Klickbarer UI-Prototyp der Seiten „Dashboard“, „Kunden-Detail“ und „Host-Detail“ mit realistischen Beispieldaten und ohne Backend, als Abstimmungsgrundlage für Look & Feel. Die Komponenten werden in den späteren Phasen weiterverwendet.
## Aufgaben
- [ ] Logo-Komponente (Standard, Sidebar-Variante, einfarbig, Favicon 32/16) + `favicon.svg`, `favicon.ico`, PNGs, `apple-touch-icon`
- [ ] Theme: Farb-Tokens (abgedunkelte Info/Erfolg), Source Sans 3 (16 px), Monospace-Klasse mit Kopier-Button
- [ ] Layout: Sidebar (250 px, einklappbar, Overlay mobil), Kopfleiste, Inhaltskopf mit Breadcrumb, Footer mit Version
- [ ] Komponenten: SmallBox, InfoBox, Card, Badge, Callout, TodoList, ProgressBar, Tabs, CopyableCode
- [ ] Beispieldaten (`src/mock/`): 4 Kunden, ~8 Hosts (PVE/PBS/PMG), Laufzeiten, Rechnungen, Alerts
- [ ] Dashboard: 4 Small Boxes, Callout „Nicht zugeordnete Hosts“, Card „Subscriptions nach Ablauf“, Card „Aufgaben“, Card „Rechnungsstatus je Kunde“
- [ ] Kunden-Detail: Info-Boxen (Hosts, Einkauf, Verkauf, Marge), Host-Tabelle, Laufzeiten-Tabelle, Summen pro Jahr, Ansprechpartner, Notizen
- [ ] Host-Detail: Profil-Card + Tabs Übersicht, Subscription-Historie, Reports, Rechnungen, Notizen
- [ ] Warnglocke mit Dropdown, Strg+K-Suchdialog (clientseitig über Mock-Daten)
- [ ] Dark-Mode-Umschalter (Grundfunktion)
## Akzeptanzkriterien
- [ ] Alle drei Seiten sind über Sidebar/Links erreichbar und klickbar
- [ ] Suche nach `pve1c-a6bd21fcb6` findet Host und Kunde
- [ ] Mobil (375 px) benutzbar: Sidebar als Overlay, Tabellen scrollbar
- [ ] Weiße Schrift auf Info/Erfolg erfüllt 4,5:1
## Abhängigkeiten
#001
## Notizen / Entscheidungen
+28
View File
@@ -0,0 +1,28 @@
# #003 Datenmodell und Migrationen
**Status:** offen
**Meilenstein:** v0.1.0
**Labels:** backend, datenbank
**Geschätzt:** 5 h **Tatsächlich:** –
## Ziel
Vollständiges Prisma-Schema gemäß `docs/architektur.md` Abschnitt 3, erste Migration, Seed mit Admin-User und optionalen Demo-Daten.
## Aufgaben
- [ ] Docker-Compose für lokale Entwicklung (nur PostgreSQL)
- [ ] Prisma-Schema: Customer, Site, Host, Tag, Report, SubscriptionKey, ServerIdHistory, SubscriptionPeriod, PurchaseInvoice(+Item), SalesInvoice(+Item), Attachment, AgentToken, EnrollmentToken, Alert, Notification, AlertRuleSetting, NotificationChannel, User, AuditLog, Setting
- [ ] Indizes für Suche (Key, Server-ID, Hostname, IP, Rechnungsnummer)
- [ ] Erste Migration
- [ ] Seed: Admin-User aus Umgebungsvariablen, Standard-Warnregeln, optional Demo-Daten (`SEED_DEMO=1`)
- [ ] DB-Client-Singleton, Test-Datenbank-Setup für Vitest
## Akzeptanzkriterien
- [ ] `npx prisma migrate dev` läuft auf leerer DB durch
- [ ] `npx prisma db seed` legt Admin und Standard-Regeln an, idempotent
- [ ] Beträge als Decimal, Zeitstempel in UTC
## Abhängigkeiten
#001
## Notizen / Entscheidungen
- Host-Identität über Agent-Token/`agentId`, nicht über Server-ID (siehe Architektur).
- Rechnungen als eigene Entitäten mit Positionen, damit Sammelbestellungen und Sammelrechnungen abbildbar sind.
+28
View File
@@ -0,0 +1,28 @@
# #004 Agent-API
**Status:** offen
**Meilenstein:** v0.1.0
**Labels:** backend, api, sicherheit
**Geschätzt:** 6 h **Tatsächlich:** –
## Ziel
Getrennte, abgesicherte API unter `/api/agent/v1`, über die sich Agents registrieren und Reports abliefern.
## Aufgaben
- [ ] Token-Bibliothek: Erzeugung (Präfix `plx_e_`/`plx_h_`), SHA-256-Hash, Prüfung, Widerruf, `lastUsedAt`
- [ ] `POST /enroll`: Enrollment-Token prüfen (Ablauf, Nutzungen), Host anlegen oder Neuinstallation erkennen, Host-Token ausgeben, optionale Kunden-/Standort-Zuordnung
- [ ] `POST /report`: zod-Schema (alle Felder nullable), idempotent über `reportId`, Transaktion (Report, Stammdaten, Key-Historie, Server-ID-Historie, Laufzeitvorschlag)
- [ ] `GET /ping`
- [ ] Rate-Limiting (pro IP und Token), `429` mit `Retry-After`
- [ ] Einheitliche Fehlerantworten (JSON), kein Stacktrace nach außen
- [ ] Tests: Auth (fehlend/falsch/widerrufen/abgelaufen), Validierung, Idempotenz, Key-Wechsel, Server-ID-Wechsel, Laufzeitvorschlag, Rate-Limit
## Akzeptanzkriterien
- [ ] Report mit ausschließlich `null`-Feldern (außer Pflicht-Metadaten) wird angenommen
- [ ] Tokens liegen nur gehasht in der DB
- [ ] UI-Session-Cookies werden von der Agent-API ignoriert
- [ ] Alle Tests grün
## Abhängigkeiten
#003
## Notizen / Entscheidungen
+31
View File
@@ -0,0 +1,31 @@
# #005 Agent-Skript
**Status:** offen
**Meilenstein:** v0.2.0
**Labels:** agent
**Geschätzt:** 8 h **Tatsächlich:** –
## Ziel
Schlanker Bash-Agent (nur `curl` und Proxmox-Bordmittel), der täglich per systemd-Timer seinen Status meldet, mit One-Liner-Installation.
## Aufgaben
- [ ] Produkterkennung PVE / PBS / PMG
- [ ] Datensammlung: Subscription (key, status, level, productname, sockets, serverid, regdate, nextduedate, checktime), Hostname, FQDN, IPs, Cluster/Node, Version, Kernel, Sockets, CPU-Modell, Uptime, Updates, Agent-Version, Zeitstempel
- [ ] JSON-Erzeugung ohne `jq` inkl. Escaping, fehlende Werte als `null`
- [ ] Senden mit Retry/Backoff, Spool-Verzeichnis, Nachsenden
- [ ] TLS-Verifikation, optional eigenes CA-Zertifikat
- [ ] Logging ins Journal
- [ ] `install.sh`: `--token`, `--url`, `--ca-cert`; Config `/etc/proxledger/agent.conf` (600); Service + Timer (`RandomizedDelaySec`); erster Report sofort
- [ ] `--uninstall`, `--update`, `--test`
- [ ] Auslieferung von `install.sh`/Agent über das Dashboard
- [ ] ShellCheck sauber; Tests mit Beispielausgaben der `*subscription get`-Befehle
## Akzeptanzkriterien
- [ ] Installation per One-Liner auf PVE 8/9 und PBS 3/4 erfolgreich
- [ ] Report scheitert nicht an fehlenden Befehlen/Feldern
- [ ] Dashboard offline → Report wird gepuffert und beim nächsten Lauf nachgesendet
- [ ] Uninstall entfernt Units, Config und Spool vollständig
## Abhängigkeiten
#004
## Notizen / Entscheidungen
+27
View File
@@ -0,0 +1,27 @@
# #006 Kunden, Standorte und Hostzuweisung
**Status:** offen
**Meilenstein:** v0.3.0
**Labels:** ui, backend
**Geschätzt:** 6 h **Tatsächlich:** –
## Ziel
Kunden und Standorte pflegen, neu registrierte Hosts schnell Kunden zuweisen und Enrollment-Tokens verwalten.
## Aufgaben
- [ ] Kunden anlegen/bearbeiten/löschen (Name, Kundennummer, Ansprechpartner, E-Mail, Notizen)
- [ ] Standorte je Kunde
- [ ] Seite „Nicht zugeordnete Hosts“ mit Mehrfachauswahl und Schnellzuweisung (Kunde + Standort)
- [ ] Callout auf dem Dashboard, solange nicht zugeordnete Hosts existieren
- [ ] Enrollment-Tokens: erzeugen (Ablauf, max. Nutzungen, optional Kunde/Standort), anzeigen (einmalig), widerrufen; Install-One-Liner zum Kopieren
- [ ] Host-Tokens widerrufen
- [ ] Audit-Log-Einträge für alle Änderungen
## Akzeptanzkriterien
- [ ] Mehrere Hosts lassen sich in einem Schritt zuweisen
- [ ] Mit kundengebundenem Enrollment-Token registrierte Hosts sind sofort zugeordnet
- [ ] Widerrufener Token wird von der Agent-API abgewiesen
## Abhängigkeiten
#002, #004
## Notizen / Entscheidungen
+25
View File
@@ -0,0 +1,25 @@
# #007 Host-Tabelle, Suche und Detailansichten
**Status:** offen
**Meilenstein:** v0.4.0
**Labels:** ui
**Geschätzt:** 8 h **Tatsächlich:** –
## Ziel
Hosts finden, filtern und vollständig einsehen.
## Aufgaben
- [ ] Host-Tabelle (serverseitig): Filter Kunde, Status, Produkt, Ablauf, Rechnungsstatus; Sortierung; Spaltenauswahl; Paginierung; CSV-Export
- [ ] Suche nach Key, Server-ID, Hostname, IP, Proxmox-Rechnungsnummer
- [ ] Globale Suche in der Kopfleiste und Sidebar, `Strg+K`
- [ ] Host-Detail: Profil-Card, Tabs Übersicht, Subscription-Historie, Reports, Rechnungen, Notizen; Tags
- [ ] Kopier-Buttons für Key, Server-ID, Rechnungsnummer
- [ ] Badge „Keine Meldung“
## Akzeptanzkriterien
- [ ] Eingabe `pve1c-a6bd21fcb6` liefert direkt Host und Kunde
- [ ] Filter bleiben in der URL erhalten (teilbar, Zurück-Button funktioniert)
## Abhängigkeiten
#006
## Notizen / Entscheidungen
+28
View File
@@ -0,0 +1,28 @@
# #008 Laufzeiten und Rechnungen
**Status:** offen
**Meilenstein:** v0.5.0
**Labels:** ui, backend, buchhaltung
**Geschätzt:** 10 h **Tatsächlich:** –
## Ziel
Lizenzjahre mit Proxmox-Einkaufsrechnung und Kundenrechnung erfassen und den Status schnell pflegen.
## Aufgaben
- [ ] Laufzeitvorschlag bei neuem `nextduedate` bestätigen/verwerfen
- [ ] Laufzeit manuell anlegen/bearbeiten
- [ ] Proxmox-Rechnung erfassen (auch Sammelrechnung über mehrere Laufzeiten), PDF-Upload
- [ ] Kundenrechnung erfassen (auch Sammelrechnung), PDF-Upload
- [ ] Marge pro Laufzeit, Kunde und Jahr berechnen
- [ ] Rechnungsübersicht: alle Laufzeiten, Umschalter „Proxmox bezahlt“ / „Kundenrechnung erstellt“ direkt in der Zeile, Filter Offen/Erledigt/Alle, Kunde, Zeitraum
- [ ] Sidebar-Badge offene Rechnungspunkte
- [ ] Aufgaben-Card auf dem Dashboard mit echten Aktionen
## Akzeptanzkriterien
- [ ] Umschalten in der Tabelle wirkt sofort und wird im Audit-Log protokolliert
- [ ] Summen Einkauf/Verkauf/Marge stimmen mit Einzelwerten überein (Tests)
- [ ] Nur PDF bis 10 MB wird angenommen
## Abhängigkeiten
#007
## Notizen / Entscheidungen
@@ -0,0 +1,25 @@
# #009 Kundenübersicht, Dashboard und Jahresbahn
**Status:** offen
**Meilenstein:** v0.6.0
**Labels:** ui
**Geschätzt:** 8 h **Tatsächlich:** –
## Ziel
Überblick über Kunden, Kennzahlen und anstehende Abläufe mit Echtdaten.
## Aufgaben
- [ ] Kundenübersicht: Anzahl Hosts, aktive Subscriptions, nächster Ablauf, offene Warnungen, Rechnungs-Ampel
- [ ] Kunden-Detail mit Echtdaten (Info-Boxen, Hosts, Laufzeiten, Summen pro Jahr)
- [ ] Dashboard mit Echtdaten: Small Boxes (inkl. „Mehr Infos“-Links auf gefilterte Listen), Kacheln ohne Subscription, ohne Meldung, ohne Kunde, offene Proxmox-Rechnungen, fehlende Kundenrechnungen
- [ ] Card „Rechnungsstatus je Kunde“
- [ ] Ablauf-Kalender: nächste 90 Tage
- [ ] Jahresbahn: Timeline der nächsten 12 Monate, „Heute“-Linie, gruppiert nach Kunde
## Akzeptanzkriterien
- [ ] Kennzahlen stimmen mit den gefilterten Listen überein
- [ ] Jahresbahn mobil horizontal scrollbar
## Abhängigkeiten
#008
## Notizen / Entscheidungen
+22
View File
@@ -0,0 +1,22 @@
# #010 Export CSV und PDF
**Status:** offen
**Meilenstein:** v0.6.0
**Labels:** export
**Geschätzt:** 5 h **Tatsächlich:** –
## Ziel
Daten für Kundenunterlagen und Buchhaltung exportieren.
## Aufgaben
- [ ] CSV (UTF-8 mit BOM, Semikolon, deutsches Zahlenformat): Host-Liste, Kundenübersicht, Rechnungsliste pro Jahr
- [ ] PDF mit einfarbigem Logo: Host-Liste, Kundenübersicht (Anlage für einen Kunden), Rechnungsliste pro Jahr mit Summen
- [ ] Export berücksichtigt aktive Filter
## Akzeptanzkriterien
- [ ] CSV öffnet sich in Excel ohne Umlautfehler
- [ ] PDF-Summen entsprechen der Rechnungsübersicht
## Abhängigkeiten
#009
## Notizen / Entscheidungen
+26
View File
@@ -0,0 +1,26 @@
# #011 Warnregeln
**Status:** offen
**Meilenstein:** v0.7.0
**Labels:** backend, alerts
**Geschätzt:** 8 h **Tatsächlich:** –
## Ziel
Konfigurierbare Warnregeln, die Alerts öffnen und automatisch schließen.
## Aufgaben
- [ ] Regel-Engine: reine Funktionen, Fingerprint, Abgleich offen/neu/erledigt
- [ ] Regeln: Ablauf 30/14/7, Status ≠ active, Sockets-Abweichung, keine Meldung 48 h, Server-ID geändert, Key mehrfach, Host ohne Kunde, Proxmox-Rechnung fällig, Kundenrechnung fehlt, Kundenrechnung unbezahlt nach X Tagen
- [ ] Worker-Prozess mit Scheduler (stündlich) + Auswertung nach jedem Report
- [ ] Einstellungsseite: Regeln aktivieren, Schwellwerte ändern
- [ ] Warnglocke und Alert-Liste (offen/erledigt, quittieren)
- [ ] Tests für jede Regel inkl. Grenzfälle
## Akzeptanzkriterien
- [ ] Kein doppelter offener Alert für denselben Sachverhalt
- [ ] Alerts schließen sich automatisch, wenn die Ursache behoben ist
- [ ] Alle Regel-Tests grün
## Abhängigkeiten
#008
## Notizen / Entscheidungen
+25
View File
@@ -0,0 +1,25 @@
# #012 Benachrichtigungen
**Status:** offen
**Meilenstein:** v0.8.0
**Labels:** backend, alerts
**Geschätzt:** 6 h **Tatsächlich:** –
## Ziel
Über neue Alerts per E-Mail und Webhook informieren, plus regelmäßige Zusammenfassung.
## Aufgaben
- [ ] SMTP (STARTTLS, M365/Exchange Online getestet), HTML-Mail mit Logo
- [ ] Generischer Webhook (JSON, optional HMAC-Signatur, eigene Header)
- [ ] Deduplizierung: nur bei neuem Alert oder Eskalation
- [ ] Tägliche/wöchentliche Zusammenfassung
- [ ] Einstellungsseite mit „Test senden“
- [ ] Wiederholung bei Versandfehler, Versandprotokoll
## Akzeptanzkriterien
- [ ] Testmail über Exchange Online kommt an
- [ ] Derselbe offene Alert erzeugt keine zweite Benachrichtigung
## Abhängigkeiten
#011
## Notizen / Entscheidungen
+26
View File
@@ -0,0 +1,26 @@
# #013 Authentifizierung und Audit-Log
**Status:** offen
**Meilenstein:** v0.9.0
**Labels:** sicherheit
**Geschätzt:** 6 h **Tatsächlich:** –
## Ziel
Zugriff auf das Dashboard absichern und Änderungen nachvollziehbar machen.
## Aufgaben
- [ ] Auth.js: OIDC (authentik), lokaler Admin als Fallback (argon2id)
- [ ] Middleware schützt alle UI-Routen, nicht die Agent-API
- [ ] Login-Seite im AdminLTE-Stil mit Logo
- [ ] Rollen admin / readonly
- [ ] Audit-Log-Ansicht mit Filter
- [ ] Login-Rate-Limit, Security-Header
## Akzeptanzkriterien
- [ ] Ohne Login ist keine UI-Seite erreichbar
- [ ] Login über authentik funktioniert; lokaler Admin auch bei ausgefallenem OIDC
- [ ] readonly-Benutzer kann nichts ändern
## Abhängigkeiten
#006
## Notizen / Entscheidungen
+26
View File
@@ -0,0 +1,26 @@
# #014 Deployment und Dokumentation
**Status:** offen
**Meilenstein:** v0.10.0
**Labels:** deployment, docs
**Geschätzt:** 8 h **Tatsächlich:** –
## Ziel
ProxLedger einfach per Docker Compose oder als LXC-Container auf Proxmox betreiben.
## Aufgaben
- [ ] Dockerfile (Multi-Stage, Standalone-Output, Non-root)
- [ ] `docker-compose.yml` (web, worker, postgres), `.env.example`
- [ ] Migrationen beim Start, Healthcheck
- [ ] LXC-Installer im Stil der Community-Scripts (Debian, Ressourcenabfrage, systemd-Dienste)
- [ ] Reverse-Proxy-Beispiele (Caddy, nginx, Traefik)
- [ ] README (Deutsch): Dashboard installieren → Enrollment-Token → Agent ausrollen
- [ ] Backup-/Restore-Anleitung für die Datenbank und Uploads
## Akzeptanzkriterien
- [ ] `docker compose up -d` auf frischem System ergibt lauffähiges Dashboard
- [ ] LXC-Installer auf PVE 9 erfolgreich
## Abhängigkeiten
#013
## Notizen / Entscheidungen
+24
View File
@@ -0,0 +1,24 @@
# #015 Feinschliff für 1.0
**Status:** offen
**Meilenstein:** v1.0.0
**Labels:** ui, sicherheit
**Geschätzt:** 6 h **Tatsächlich:** –
## Ziel
Produktionsreife: Dark-Mode, Mobilansicht, Barrierefreiheit und Sicherheitsprüfung.
## Aufgaben
- [ ] Dark-Mode vollständig (alle Seiten, PDF bleibt hell)
- [ ] Mobil: Tabellen als Karten, Touch-Ziele ≥ 44 px
- [ ] Kontrast- und Tastaturprüfung
- [ ] Sicherheits-Review (Abhängigkeiten, Header, Uploads, Tokens)
- [ ] Performance-Check mit 200 Hosts / 5 Jahren Reports
## Akzeptanzkriterien
- [ ] Alle Seiten in Hell und Dunkel lesbar
- [ ] Keine bekannten kritischen Schwachstellen in Abhängigkeiten
## Abhängigkeiten
#014
## Notizen / Entscheidungen
+22
View File
@@ -0,0 +1,22 @@
# Issue-Übersicht
Details und Architektur: [../architektur.md](../architektur.md). Zeiten werden aus dem [DEVLOG](../../DEVLOG.md) übernommen.
| Nr. | Titel | Status | Meilenstein | Geschätzt | Tatsächlich |
|---|---|---|---|---|---|
| [#001](001-projekt-setup.md) | Projekt-Setup | in Arbeit | v0.1.0 | 3 h | – |
| [#002](002-prototyp.md) | Klickbarer Prototyp | offen | v0.1.0 | 8 h | – |
| [#003](003-datenmodell.md) | Datenmodell und Migrationen | offen | v0.1.0 | 5 h | – |
| [#004](004-agent-api.md) | Agent-API | offen | v0.1.0 | 6 h | – |
| [#005](005-agent-skript.md) | Agent-Skript | offen | v0.2.0 | 8 h | – |
| [#006](006-kunden-hostzuweisung.md) | Kunden, Standorte und Hostzuweisung | offen | v0.3.0 | 6 h | – |
| [#007](007-hosts-detailansichten.md) | Host-Tabelle, Suche und Detailansichten | offen | v0.4.0 | 8 h | – |
| [#008](008-laufzeiten-rechnungen.md) | Laufzeiten und Rechnungen | offen | v0.5.0 | 10 h | – |
| [#009](009-kundenuebersicht-dashboard-jahresbahn.md) | Kundenübersicht, Dashboard und Jahresbahn | offen | v0.6.0 | 8 h | – |
| [#010](010-export.md) | Export CSV und PDF | offen | v0.6.0 | 5 h | – |
| [#011](011-warnregeln.md) | Warnregeln | offen | v0.7.0 | 8 h | – |
| [#012](012-benachrichtigungen.md) | Benachrichtigungen | offen | v0.8.0 | 6 h | – |
| [#013](013-authentifizierung.md) | Authentifizierung und Audit-Log | offen | v0.9.0 | 6 h | – |
| [#014](014-deployment.md) | Deployment und Dokumentation | offen | v0.10.0 | 8 h | – |
| [#015](015-feinschliff-v1.md) | Feinschliff für 1.0 | offen | v1.0.0 | 6 h | – |
| | **Summe** | | | **101 h** | **–** |