Commit Graph
13 Commits
Author SHA1 Message Date
florian.wildeandClaude Opus 5.5 30f271b23a feat(hosts): Schluessel auf dem Host anzeigen und ausrollen (#016)
Die Hostseite listet, welche Public und Private Keys sshkv dort
verwaltet - direkt oder ueber eine Hostgruppe - mit Zustand als Punkt
und Text. Ein Dry-Run je Host zeigt das Diff aller Benutzer dieses
Hosts und rollt nach Bestaetigung aus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 10:19:27 +02:00
florian.wildeandClaude Opus 5.5 4584669962 feat(hosts): Host-Key und Bootstrap in der Oberflaeche (#009, #010)
Auf der Hostseite: Host-Key abrufen, Fingerprint vergleichen und
vertrauen oder ablehnen. Weicht ein Key vom vertrauten ab, erscheint
eine deutliche Warnung, und Annehmen geht nur mit Haekchen und frischer
Bestaetigung. Danach Bootstrap per Einmal-Passwort oder per Befehl und
Verbindungspruefung, jeweils mit Fortschrittsanzeige.

Der sshd-Befund empfiehlt prohibit-password, wenn root sich per
Passwort anmelden darf - nur als Hinweis, geaendert wird nichts.

E2E im gebauten Stand mit Worker gegen ein echtes sshd.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 10:00:43 +02:00
florian.wilde 69f9037e41 Merge branch 'phase/009-host-key-pruefung' 2026-10-12 09:51:59 +02:00
florian.wildeandClaude Opus 5.5 90a41dc55d feat(hosts): Seiten fuer Hosts und Hostgruppen (#008)
Ersetzt die Platzhalter: Hostliste mit Suche und Gruppenfilter per GET
(teilbare Links), Formulare fuer Hosts und Gruppen, Hostdetail als Geruest
und Gruppendetail mit Mitgliederauswahl. Bearbeiten-Knoepfe entscheidet der
Server per darf(); jede Seite prueft die Sitzung selbst.

Die Detailseite rendert HostKeyAktionen (#009) und BootstrapAktionen (#010)
als feste Platzhalter mit fertigen Props, damit die Folge-Issues nur ihre
eigene Datei ersetzen. Formulare senden per onSubmit, weil React ein
<form action> nach jeder Antwort zuruecksetzt und Eingaben bei Feldfehlern
sonst verloren gingen. Unter md zeigt die Hostliste Karten statt Tabelle,
damit Status und Host-Key auf 390 px ohne Wischen sichtbar bleiben.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:50:34 +02:00
florian.wildeandClaude Opus 5.5 353b751df2 feat(ssh): strikte Host-Key-Pruefung und TOFU im Worker (#009)
Jede Verbindung prueft den Host-Key gegen die vertrauten Keys des
Hosts und bietet nur deren Algorithmen an - sonst koennte der Server
einen Key eines anderen Typs zeigen, den nie jemand gesehen hat. Ein
abweichender Key bricht vor dem Senden von Zugangsdaten ab, wird als
ausstehend festgehalten und oeffnet eine Abweichung.

Abrufen bricht die Verbindung im hostVerifier ab: der Mensch
entscheidet, nie der Code. Einen vertrauten Key zu ersetzen verlangt
ein ausdrueckliches ersetzen und eine frische Bestaetigung.

Integrationstest gegen ein echtes sshd inklusive Host-Key-Wechsel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:37:09 +02:00
florian.wildeandClaude Opus 5.5 d1ba822a4a feat(auth): Anmeldeseiten, TOTP-Einrichtung und Bestaetigung (#004)
Anmeldung, Einrichtung des zweiten Faktors fuer den Notfall-Admin,
erneute Bestaetigung vor kritischen Aktionen und die Seite fuer
fehlende Rechte. Die Huelle zeigt jetzt den echten Benutzer, und jede
Seite prueft die Sitzung selbst; ein struktureller Test haelt das fest.

Die Ablaeufe sind im gebauten Stand gegen den Mock-OIDC geprueft
(pnpm test:e2e): Admin, Konto ohne Gruppe, Notfall-Admin mit TOTP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:28:51 +02:00
florian.wilde 4d0044b380 Merge branch 'phase/002-design-layout' 2026-10-12 09:21:46 +02:00
florian.wildeandClaude Opus 5.5 445f5c5ebd feat(ui): Prototyp Uebersicht und Schluesseldetail (#002)
Klickbarer Prototyp mit Beispieldaten aus src/beispiel/, sichtbar als
Beispiel gekennzeichnet. Er zeigt das verbindliche Design an echten
Bildschirmen, bevor die Lesemodelle (#012, #021, #026) existieren; die
Seiten tauschen spaeter nur die Datenquelle. Die bisherige Startseite
entfaellt zugunsten der Route-Gruppe (app).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:20:34 +02:00
florian.wildeandClaude Opus 5.5 419e8ff8bd feat(ui): Huelle mit Seitenleiste und Platzhalterseiten (#002)
Die Huelle bekommt Benutzer und optional den aktiven Pfad als Props und
kennt weder Sitzung noch Datenbank; ohne Pfad ermittelt die Navigation
ihn per usePathname(), weil ein Layout den Pfad nicht kennt. Die
Benutzerermittlung steckt in huellenBenutzerErmitteln(), damit #004 nur
diese Funktion ersetzen muss.

Unter 1024 px klappt die Leiste ein; geschlossen ist sie invisible und
damit auch nicht per Tab erreichbar. Alle Navigationsziele haben eine
Platzhalterseite, damit nichts auf eine 404 fuehrt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:20:30 +02:00
florian.wildeandClaude Opus 5.5 88b5697cc9 feat(ui): Design-Tokens, Schriften und Datumsformate (#002)
Die Farben des Tresor-Designs stehen als CSS-Variablen in :root und
werden per @theme inline an Tailwind gereicht, damit Inline-SVGs und
Utility-Klassen dieselbe Quelle nutzen. Schriften kommen selbst gehostet
aus @fontsource, nur in den benutzten Gewichten und im Latin-Ausschnitt.

src/lib/format.ts rechnet fest in Europe/Berlin: der Server laeuft im
Container auf UTC, die Anzeige soll aber ueberall dieselbe Ortszeit
zeigen. relativ() nimmt den Bezugspunkt als Parameter, damit statische
Seiten und Tests deterministisch bleiben.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:20:22 +02:00
florian.wildeandClaude Opus 5.5 5ef90310e1 feat(auth): Anmeldung per OIDC und Notfall-Admin mit TOTP (#004)
Sitzung, OIDC-Fluss und Rueckruf aus Laufzettel uebernommen und auf
sshkv angepasst. Abweichungen mit Absicht:

- Ohne passende sshkv-Gruppe gibt es keinen Zugang, auch keinen
  Lesezugriff: schon die Hostliste verraet, wer wohin darf.
- Notfall-Admin nur mit TOTP (Freigabe Frage 5). Ein richtiges
  Passwort fuehrt beim ersten Mal nur zur Einrichtung. Jeder Code gilt
  einmal, fuenf Fehlversuche sperren 15 Minuten.
- Kritische Rechte verlangen eine Bestaetigung, die hoechstens fuenf
  Minuten alt ist. Bei OIDC mit prompt=login, max_age=0 und Pruefung
  von auth_time, sonst zaehlte eine laufende SSO-Sitzung als Beweis.
- Sitzungen laufen acht statt zwoelf Stunden.

Die Seiten folgen, sobald das Design-System (#002) steht.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:17:44 +02:00
florian.wildeandClaude Opus 5.5 a11ae7eef3 feat(marke): Logo, Favicon und PWA-Icons per Skript (#002)
Die Bildmarke liegt als SVG in drei Varianten (dunkel, hell, mono) vor.
Rasterdateien erzeugt scripts/icons.mjs mit sharp und sie werden
eingecheckt, damit Build und Laufzeitabbild kein sharp brauchen. Unter
32 px dient eine reduzierte Marke ohne Zahlenring und Bolzen, weil die
Details dort zu Rauschen verschwimmen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:09:07 +02:00
florian.wildeandClaude Opus 5.5 cef9510f18 chore: Projektgeruest mit Next.js 16, Prisma 7 und pnpm (#001)
Konfiguration aus Laufzettel uebernommen, damit alle Projekte gleich
gebaut und geprueft werden. Entwicklungsdatenbank auf 5436, weil 5433
und 5434 von ProxLedger und Laufzettel belegt sind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:05:15 +02:00