Acht Meilensteine lagen ohne fremden Blick auf main. Ein Review mit eigener
Datenbank, Gegenproben und vollem Suitenlauf hat sie gegen die
Akzeptanzkriterien und gegen CLAUDE.md geprueft.
Die Kernregeln halten: fuenf von fuenf Gegenproben gegen Versionierung,
Mandantengrenze, Abschlussregel und Selbstauskunft wurden rot. Alle Befunde
lagen am Rand — und die drei wertvollsten waren Gegenproben, die gruen blieben.
Schwer:
- Der Link in der Mail "Verzeichnis-Abgleich fehlgeschlagen" war ein 404
(/verwaltung/verzeichnis statt /admin/verzeichnis). Die eine Meldung, die an
alle Administratoren geht, im Moment eines Ausfalls. Ein Test prueft jetzt
jeden Meldungspfad gegen die vorhandenen Routen.
- Der Export eines Entwurfs mit Baustein lieferte einen leeren Abschnitt unter
dem Platzhalter "wird ersetzt" — der Zweck des Formats ist, eine Vorlage in
eine zweite Installation zu bringen. Bausteine werden jetzt aufgeloest.
Mittel:
- Der Anhang-Handler hatte keinen Test; die ganze Rechtepruefung liess sich
durch einen hartcodierten ADMIN ersetzen, Suite gruen. Es ist die einzige
Stelle, die rohe Dateibytes ausliefert. tests/anhang-route.test.ts faehrt ihn
jetzt echt, acht Pruefungen.
- /api/scim in der Proxy-Allowlist stand in keinem Test. OEFFENTLICH ist
exportiert, der Test vergleicht beide Richtungen: eine Liste, die nur in einer
Richtung geprueft wird, laeuft dem Code hinterher.
- Ein offener Ereignisstrom ueberlebte Abmelden, Deaktivieren und
Sitzungswiderruf. Der Herzschlag prueft die Sitzung jetzt nach. Dass es kein
Test zeigte, lag an einer Attrappe `sitzung: {}` — eine Attrappe ohne die Form
der Wirklichkeit prueft etwas anderes als die Wirklichkeit.
- README kannte MITARBEITER nicht und behauptete, unbekannte Benutzer wuerden
angelegt. Wer auf v0.2.0 hebt und nur das README liest, haette genau diese
Leute ausgesperrt.
- sicherung.md nannte einen Anhaenge-Pfad, den es nirgends gibt — als
Rueckfallwert in einem Skript mit rm -rf. Jetzt bricht es ab statt zu raten.
- Attributnamen wurden nur in der Server Action geprueft, waehrend der
Graph-Leser sich im Kommentar darauf berief.
Dazu #027: die Ende-zu-Ende-Ablaeufe raeumen jetzt zentral auf, vor und nach
dem Lauf, und ein struktureller Test bewacht es. Beim ersten echten Lauf seit
dem 26. September waren sieben Ablaeufe rot, vier Ursachen, keine ein
Produktfehler — unbemerkt, weil pnpm test:e2e in keinem Tor steht. Das ist jetzt
#038 und keine Fussnote.
Ein Befund des Reviews war falsch (der Zustands-Handler habe keinen Test; er hat
acht direkte Aufrufe). Nachgeprueft, bevor etwas geaendert wurde.
1454 Vitest-Tests (vorher 1432), 113 E2E-Ablaeufe gruen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Laufzettel betreiben
Diese Sammlung richtet sich an den, der Laufzettel betreibt, aber nicht gebaut hat. Sie führt von einem leeren Server bis zur ersten Anmeldung, und danach durch Aktualisierung, Sicherung und Fehlersuche. Wer die Anwendung benutzen will, liest stattdessen die Anleitung.
Es gibt zwei Wege in den Betrieb. Beide sind gleichwertig und führen zum selben Stand.
| Weg | Für wen | Was du mitbringen musst |
|---|---|---|
| Docker Compose | Es gibt schon einen Docker-Host, und weitere Dienste laufen dort ebenso. Aktualisieren heißt neu bauen. | Docker mit Compose-Plugin |
| Nativ im Proxmox-LXC | Es gibt einen Proxmox-Host und keinen Docker. Ein Skript legt den Container an und installiert darin alles — PostgreSQL, Node, die Anwendung, einen systemd-Dienst. | Proxmox VE 8 oder 9, oder ein leeres Debian 13 |
Nimm den Compose-Weg, wenn du schwankst: er ist der Weg, gegen den hier entwickelt und getestet
wird. Der pct-Teil des Proxmox-Skripts ist ungetestet — das steht so, und warum, in
proxmox.md.
Was auf beiden Wegen gilt
Vier Dinge sind keine Empfehlung, sondern Teil des Aufbaus. Sie zu übergehen heißt, einen anderen Stand zu betreiben als den beschriebenen.
Die Datenbank ist von außen nicht erreichbar. Im Compose-Stand hat postgres kein
ports:-Mapping und hängt nur im Netz intern, das internal: true ist — ein Netz ohne Gateway.
Nativ läuft PostgreSQL mit listen_addresses = '', also nur am Unix-Socket. Dieselbe Regel, zwei
Mittel. Daraus folgt, dass jede Sicherung und jeder Blick in die Daten über den Dienstnamen
beziehungsweise den Socket läuft, nie über psql -h localhost. tests/betriebsstand.test.ts hält
das für den Compose-Stand fest, damit ein ports:-Mapping nicht versehentlich zurückkommt.
Die Anwendung bindet auf 127.0.0.1 und spricht kein HTTPS. Davor gehört ein Reverse Proxy, der
das Zertifikat hält — siehe reverse-proxy.md. Ohne Proxy erreicht die
Anwendung niemand außer dem Host selbst, und das ist die richtige Voreinstellung: ein Dienst, der
aus Versehen im LAN steht, fällt keinem auf.
APP_URL ist die öffentliche Adresse und wird nicht geraten. Aus ihr entstehen die QR-Adressen
auf den gedruckten Aufklebern und die OIDC-Rücksprungadresse. Sie später zu ändern ist möglich, aber
teuer — der Grund steht am Anfang von reverse-proxy.md. Leg die Adresse fest,
bevor der erste Aufkleber gedruckt wird.
Geheimnisse entstehen im Zielsystem. APP_SECRET, das Datenbank-Passwort und das erste
Admin-Passwort werden dort erzeugt, wo sie gelten, und stehen in keinem Repository und in keiner
Vorlage. APP_SECRET gehört mit in die Sicherung: ohne ihn sind nach dem Zurückspielen alle
Sitzungen ungültig und die verschlüsselt gespeicherten LDAP-Bind-Passwörter unlesbar. Siehe
sicherung.md.
Die Kapitel
- Inbetriebnahme mit Docker Compose — von null bis zur ersten Anmeldung, mit der vollständigen Tabelle der Umgebungsvariablen, dem Seed und der Aktualisierung
- Der native Weg im Proxmox-LXC —
deploy/proxmox/laufzettel.shunddeploy/install.sh, was sie anlegen, wie ein zweiter Aufruf aktualisiert, und die Prüfliste für den ersten echten Lauf - Reverse Proxy — Caddy und nginx als vollständiges Beispiel, TLS, Weiterleitungen, welche Kopfzeilen nötig sind und welche schaden
- Anmeldung über authentik — OIDC-Provider, Gruppen auf Rollen, Notfallzugang
- Sichern und Zurückspielen — auf beiden Wegen, was in die Sicherung gehört und was nicht, und wie du prüfst, dass das Zurückspielen wirklich funktioniert
- Entra ID als Verzeichnisquelle — App-Registrierung,
User.Read.All, Administratoreinwilligung, und was anders ist als bei einem lokalen AD - Benachrichtigungen — SMTP einrichten, den Webhook prüfen, die Signatur nachrechnen, und wo man nachsieht, wenn keine Mail mehr ankommt
- SCIM-Endpunkt — die einzige Stelle, an der ein fremder Dienst von außen schreibend zugreift: das Token, was nicht unterstützt wird, und was der Reverse Proxy durchlassen muss
Wo sonst noch etwas steht
../../README.md— Kurzfassung für Entwickler, Betriebsmodi, Seed-Inhalt../../.env.example— jede Umgebungsvariable mit Kommentar, zum Kopieren../architektur.md— warum es so gebaut ist; Abschnitt 6 fasst die Betriebsregel zusammen../anleitung/08-fehlerbehebung.md— Fehlermeldungen der Oberfläche. Wer eine Meldung im Browser sieht, ist dort besser bedient als hier