Commit Graph

395 Commits

Author SHA1 Message Date
schalli 79210d7966 feat(quick-261008-w5w): Modul-Changelog Durchstich mit Nextcloud-Status
- Typen, Register, Route GET /modules/changelog/:slug, Waechter-Test
- Seed liest die Version per latestVersion aus dem Changelog
- Marktplatz-Detailseite zeigt den Abschnitt Aenderungen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 23:25:02 +02:00
schalli 8679668cac fix(nextcloud-files): WR-08/IN-06 Auswahl-ZIP per POST, Downloads mit Vorabpruefung
- WR-08: POST download/zip mit den Namen im Koerper (JSON oder unsichtbares Formular mit
  names als JSON-Text) statt im Query-String; hoechstens 1000 Namen; die Weboberflaeche
  laedt per Formular in einen unsichtbaren Rahmen (Strom direkt auf die Platte, Cookie und
  Content-Disposition bleiben); alles ausgewaehlt -> ganzer Ordner als ZIP
- Nextcloud nimmt die Auswahl nur in ihrer Adresse an (gemessen: Apache lehnt ueber 8190
  Zeichen mit 414 ab); Tessera prueft die Laenge und antwortet vorher mit 413
  selectionTooLarge, die Weboberflaeche meldet es schon vor dem Absenden
- IN-06: Vorabpruefung (check=1 bzw. check: true, ein PROPFIND Depth 0) vor jedem Download;
  Fehler stehen in der Statuszeile, connectionExpired fuehrt zum Anmeldebildschirm; auch der
  Klick auf einen Dateinamen geht ueber die Pruefung
- e2e-transfer auf POST umgestellt (JSON, Formular ueber /api-proxy, 300 Namen, Pruefung),
  Anwenderhandbuch

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:50:24 +02:00
schalli 08abfef8e2 fix(nextcloud-files): WR-09/IN-02 ungueltige Pfadzeichen sind 400, Vorschau ohne SVG
- WR-09: ein einzelnes UTF-16-Ersatzzeichen in einem Pfadsegment ist 400 invalidPath (bzw.
  invalidName) statt eines URIError mit 500; die Weboberflaeche wiederholt keine 4xx
- IN-02: Vorschaubilder nur als Rasterbild, image/svg+xml wird wie ein fehlendes
  Vorschaubild behandelt (CSP-Sandbox und nosniff bleiben)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:42:31 +02:00
schalli ee05131add fix(nextcloud-files): WR-04/05/06, IN-01 Ersetzen und Abschluss von Uploads abgesichert
- WR-04: die Entity-Tag-Pruefung beim Ersetzen laeuft im Zusammenbau unmittelbar vor dem
  MOVE (gemessen gegen Nextcloud 34: If-Match auf dem MOVE wird gegen .file geprueft und
  ergibt immer 412, ist also nicht nutzbar); weicht der Tag ab -> changedMeanwhile
- WR-05: completeUpload merkt den Zustand synchron vor dem ersten await; ein zweiter oder
  gleichzeitiger Abschluss liefert das gemerkte Ergebnis (auch denselben Fehler) und baut
  nie zweimal zusammen; nur Fehler vor dem MOVE duerfen erneut versucht werden
- WR-06: 412 mit replaceEtag (PUT oder Zusammenbau) ist changedMeanwhile, nicht nameTaken
- IN-01: replaceEtag muss die Form eines Entity-Tags haben (sonst 400)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:41:20 +02:00
schalli 07474bd162 fix(nextcloud-files): WR-03 hoechstens vier gleichzeitige Nextcloud-Aufrufe je Zugang
- die Aufrufsperre vergibt je Zugangsschluessel vier Plaetze bis zur Antwort (Kopfzeilen);
  weitere Aufrufe warten der Reihe nach und pruefen danach, ob der Zugang inzwischen tot
  oder der Ursprung gesperrt ist; ein widerrufener Zugang erzeugt so hoechstens vier 401
- Hochladen und Zusammenbau (Antwort erst nach dem ganzen Koerper) belegen keinen Platz
- Weboberflaeche: Vorschaubilder laden weiter lazy; schlaegt eines fehl, prueft die Ansicht
  hoechstens alle 10 s die Verbindung und kehrt bei connectionExpired zur Anmeldung zurueck

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:39:05 +02:00
schalli ddae9400a3 fix(nextcloud-files): WR-02/IN-04 Widerrufe auch nach Sperre, Netzfehler und abgebrochener Browser-Anmeldung
- voruebergehend gescheiterte Widerrufe (Aufrufsperre nach 429, Netz, Zeitablauf, Wartung,
  5xx) kommen in eine kleine Warteschlange im Arbeitsspeicher und werden nach dem Ende
  der Sperre bzw. nach einer Minute erneut versucht (hoechstens 200 Eintraege, 6 Versuche,
  nie geloggt)
- abgebrochene, ersetzte oder durch Adresswechsel verworfene Browser-Anmeldungen bleiben
  bis zum Ablauf als "abgebrochen" stehen; der Server fragt sie alle 10 s ab und widerruft
  ein doch noch ausgestelltes App-Passwort sofort; sie zaehlen nicht gegen die 200 offenen
- Specs fuer Sperre, Netzfehler, Aufgeben und den Login-Flow-Abbruch; Betriebshandbuch

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:36:32 +02:00
schalli 74e086f435 fix(nextcloud-files): WR-01 Adresspruefung folgt keiner Weiterleitung und meldet nur grob
- testAddress fragt status.php ueber ncRequest ab (keine Weiterleitung, Aufrufsperre,
  keine Zugangsdaten) statt ueber fetchNextcloudStatus mit bis zu drei Weiterleitungen
- Ergebnis nur noch ok / maintenance / paused / locked / redirect / not-nextcloud /
  unreachable, ohne HTTP-Statuscode, Fehlerkuerzel oder Weiterleitungsziel
- NEXTCLOUD_STATUS_FETCHER entfaellt; Specs mit Attrappen-Transport, Anleitung angepasst

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:32:38 +02:00
schalli e78e059477 fix(nextcloud-files): CR-02 Nextcloud-Adresse aendern nur noch Administratoren
- PUT settings traegt @Roles(ADMIN, SUPER_ADMIN) statt @ModuleManage (Muster wie
  TendersController.getSourceConfig); alle Benutzer schicken ihr Passwort an diese Adresse
- POST settings/test: Verwalter ohne Administratorrolle pruefen nur die gespeicherte Adresse,
  jede andere Adresse ist 403
- Einstellungen fuer Verwalter nur lesbar mit kurzem Hinweis, ohne Speichern-Knopf; Hinweis
  "nicht eingerichtet" verweist Nicht-Administratoren an einen Administrator
- Metadaten-Spec (module-manage-handlers), Controller-Spec, Seitentest, e2e-settings
  (Verwalter: 403 auf PUT und fremde Pruefung), Anleitungen und Changelog angepasst

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:31:06 +02:00
schalli 5c2d327bef fix(nextcloud-files): CR-01 Anmeldebremse reserviert Versuche vor dem Nextcloud-Aufruf
- beginPasswordAttempt zaehlt einen Passwortversuch synchron und vor jedem await in
  Benutzer- und Servergrenze; release gibt den Platz bei Erfolg oder Nicht-Fehlversuch frei
- gleichzeitige Fehlversuche kommen nicht mehr an den Grenzen vorbei (3 je Benutzer, 8 je Server)
- Verbinden und Speichern laufen je Benutzer nacheinander (auch Browser-Anmeldung), damit
  zwei gleichzeitige Erfolge kein ungespeichertes, nie widerrufenes App-Passwort hinterlassen
- Specs mit gleichzeitigen Promise.all-Anmeldungen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:27:40 +02:00
schalli 630398fe93 feat(nextcloud-files): Nextcloud-Kennung auf der Anmeldeseite, Anleitungen und Changelog
- Anmeldebildschirm zeigt Name, Logo und Themenfarbe der Nextcloud (GET server, server/logo)
- Kennung wird 10 Minuten zwischengespeichert, Adresswechsel leert sie, Logo nur nach Bytes erkannt und mit CSP-Sandbox ausgeliefert
- Anmeldekarte neu gestaltet (Kennungskopf, Hinweis zum Passwort am Fuss), Kontoleiste mit kleiner Kachel
- Fokusfang in leeren Ordnern, damit die Rücktaste dort funktioniert
- Changelog, Anwender-, Administrations- und Betriebshandbuch (Brute-Force-Ausnahme, Proxy-Grenzen)
- e2e-Skripte wiederholbar gemacht

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:08:57 +02:00
schalli 4d4a0b31cb feat(nextcloud-files): Hoch- und Herunterladen als Datenstrom, große Dateien in Stücken, ZIP
- Hochladen ohne Pufferung: ganze Datei oder Chunked Upload v2 in 8-MiB-Stücken, Zusammenbau im Hintergrund mit abfragbarem Zustand
- Überschreibschutz (If-None-Match / Entity-Tag-Prüfung), Download mit Range, Content-Disposition und Schutzkopfzeilen von Tessera selbst
- Ordner- und Auswahl-ZIP; jeder Nextcloud-Fehler wird vor dem ersten Byte abgebildet, nie 401/403
- Browser-Hochlader mit Fortschritt, Wiederholung, Abbruch und Aufräumen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 18:30:02 +02:00
schalli 8bee65c306 feat(nextcloud-files): Dateien auflisten, Vorschau, Ordner anlegen, umbenennen, verschieben und löschen
- PROPFIND-Auswertung (mehrere propstat, Kleinbuchstaben-Hex, Speicher -3 = unbegrenzt, nur Zeichenketten)
- WebDAV-Schicht mit Zugangsschluessel und Aufrufsperre, Destination immer aus der Basis, Overwrite: F
- mapNcFailure als einzige Fehlerabbildung (nie 401/403 an den Browser), sendUpstreamStream prueft vor dem ersten Byte
- Dateidienst und Routen files, folders, move, preview im eigenen Konto; zweiter Benutzer bekommt notConnected
- Web-API-Funktionen listFolder, createFolder, moveEntry, deleteEntry, previewUrl
- e2e-files.sh gegen die Test-Nextcloud

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 18:14:54 +02:00
schalli d00b6ff79f feat(nextcloud-files): Anmeldung per Passwort und im Browser (Zwei-Faktor), Abmelden mit Widerruf
- Anmelde-Client (getapppassword, cloud/user, Widerruf, Login Flow v2 mit fester Abfrageadresse,
  Link aus Basis und Token neu gebaut), Anmeldebremse 3/15 min je Benutzer und 8/30 min je Server,
  Ablaufspeicher für Browser-Anmeldungen (20 min, höchstens 200, eine je Benutzer)
- Kontodienst: Verbinden, Trennen mit Widerruf, Sitzung mit Zugangsschlüssel-Sperre,
  frisch ausgestellte oder ersetzte App-Passwörter bleiben nie verwaist; jeder Kontozugriff
  über forTenant mit Mandant UND Benutzer aus dem Token
- Migration 20261008183000: Spalte ncLoginName (App-Passwort gilt nur für den Anmeldenamen der
  Ausstellung, gemessen mit E-Mail-Anmeldung gegen Nextcloud 34)
- Verbindungsbildschirm und Kontoleiste, Texte de/en, RLS-Inventar fortgeschrieben,
  E2E-Skript e2e-connect.sh

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 18:02:45 +02:00
schalli 960696745f feat(nextcloud-files): Modul Dateien mit Nextcloud-Adresse, Verbindungsprüfung und gesicherter Verbindungsschicht
- Migration 20261008180000: NextcloudFilesConfig (Organisation) und NextcloudFilesAccount
  (Mandant UND Benutzer per Zeilenschutz, nur verschlüsseltes App-Passwort)
- Transportschicht ncRequest: feste Pfadanfänge, Segmentcodierung, keine Weiterleitungen,
  keine Cookies, Zeitgrenzen; Aufrufsperre pausiert den Ursprung nach jedem 429 und
  sperrt Zugangsschlüssel nach dem ersten 401
- Einstellungen: Adresse speichern/prüfen, Adresswechsel läuft alle Konten ab (mit Bestätigung)
- Controller mit Verwalten nur auf Einstellungen, Seed, Modul, Registrierung in Web
  (Ladefunktion, Symbol folder, Navigation, Layout) und Reiter Einstellungen
- RLS-Inventar fortgeschrieben, Testaufbau (tessera-nc-test) und E2E-Skripte

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 17:41:46 +02:00
schalli ff4938fa97 fix(domains): geloeschter AutoDNS-Auftrag haengt nicht mehr - Domain entscheidet
AutoDNS loescht abgeschlossene Auftraege; GET /job/{id} liefert dann 404
(EF300101). Gibt es die Domain, ist die Registrierung durch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 14:57:53 +02:00
schalli f24ce735ab fix(domains): Verfuegbarkeit mit vollstaendiger Domain abfragen (gegen AutoDNS-Demo geprueft)
Mit nur dem Namensteil als searchToken liefert /domainstudio data: [].

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 14:54:19 +02:00
schalli 443256164d feat(nextcloud-status): http-Logo-Adresse wird einmalig abgeholt, Formularfehler mit Kennung (j9f)
- gemeinsamer SSRF-Schutz in common/public-url-guard.ts (Favoriten unveraendert)
- fetchLogoImage: Schutz je Sprung, Zeitlimit, 1-MiB-Deckel, Magic Bytes
- alle Formularfehler als { code, message } mit deutschem Text

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 14:06:20 +02:00
schalli 2176f8ecce refactor(domains): Einstellung Standard-Nameserver entfernt, Doku angepasst (h3t)
- Spalte DomainsConfig.defaultNameServers per Migration 20261008160000 entfernt
- Feld in Einstellungen/Status (API, DTO, Typen) und Karte im Web entfernt
- Anleitungen und CHANGELOG: Nameserver kommen aus AutoDNS

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 12:37:21 +02:00
schalli 473738db9e feat(domains): Standard-Nameserver aus dem AutoDNS-Profil lesen (h3t)
- parseProfileNameServers erkennt die Nameserver tolerant ([ASSUMED] Schluesselnamen)
- createOrder liest das Profil serverseitig, Browser-Liste wird ignoriert
- GET modules/domains/name-servers (Verwalten), Submit-Sperre bei weniger als zwei

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 12:32:36 +02:00
schalli cc1c83ab0a fix(domains): HTTP 5xx nie als Ablehnung werten, Verwerfen mit Neupruefung, Entwurfsstand im Anspruch (CR-01, WR-01, WR-02, WR-03, IN-03)
CR-01: 5xx, 408, 425 (auch mit AutoDNS-Huelle) sind kein "abgelehnt" mehr,
Bestellung endet in UNKNOWN und der Abgleich wertet sie nicht als "Domain gibt
es nicht". 429 gilt bei der Bestellung ebenfalls als unklar, weil nicht belegt
ist, dass AutoDNS vor der Verarbeitung abgelehnt hat.
WR-01: Verwerfen eines unklaren Auftrags fragt im Augenblick des Verwerfens
erneut bei AutoDNS nach; nur ein ausdrueckliches "nicht gefunden" verwirft.
WR-02: Die Bestaetigung traegt den Entwurfsstand (updatedAt); der Anspruch
greift nur bei gleichem Stand, sonst 409 orderChanged.
WR-03: Auftraege ohne lesbares Datum/Objekt oder eine volle Trefferliste
machen "nichts gefunden" unklar statt verwerfbar.
IN-03: Scheitert das Speichern nach POST /domain, wird die Auftragsnummer
protokolliert und der Auftrag auf UNKNOWN gebracht (nie DRAFT), ohne 500.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 11:29:01 +02:00
schalli 9eada2e082 fix(domains): Neuabruf ?refresh=1 nur fuer Verwalter (WR-06)
Jeder Neuabruf sind bis zu 20 Aufrufe auf dem geteilten AutoDNS-Takt; Benutzer
ohne Freigabestufe Verwalten koennten damit Bestellung und Abgleich verdraengen.
Der ModuleGuard legt die wirksame Stufe auf den Request, das Flag wird fuer
Nicht-Verwalter ignoriert (Zwischenspeicher bleibt).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 11:27:51 +02:00
schalli 268d6d55a4 fix(domains): null in den Einstellungen ergibt 400 statt 500 (WR-04)
@IsOptional liess null durch; der Dienst scheiterte dann an trim()/map() oder an
einer NOT-NULL-Spalte. Felder duerfen fehlen, aber nicht null sein (Kontext-
nummern bleiben ausdruecklich null-faehig).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 11:27:41 +02:00
schalli 9ecf191fb4 fix(domains): Preis nur anzeigen, wenn er nachweislich fuer ein Jahr gilt (WR-05)
Der Rueckgriff auf den ersten Preiseintrag entfaellt; ohne Ein-Jahres-Eintrag
erscheint "Preis unbekannt" statt eines Preises fuer einen anderen Zeitraum.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 11:27:41 +02:00
schalli d332246bde feat(domains): Domain registrieren mit Schutz vor Doppelbestellung, Aufträge, Changelog und Anleitung
- Verfügbarkeitsprüfung über DomainStudio, Entwurf mit Kontakten und Nameservern, Zusammenfassung mit System und Preis
- Verbindliches Abschicken: atomarer Anspruch DRAFT -> SUBMITTING vor dem Netzaufruf, genau ein POST /domain ohne Wiederholung, unklarer Ausgang als UNKNOWN, Bindung an das System
- Aufträge: Stand aus dem AutoDNS-Auftrag, Abgleich unklarer Aufträge, Verwerfen erst nach Abgleich
- Reiter Registrieren und Aufträge, Changelog, Anwender- und Administrationshandbuch, Mandantenschutz-Inventar

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 11:10:03 +02:00
schalli 450218fe77 feat(domains): Kunden, Kontakte aus AutoDNS mit Zuordnung und Domainliste
- Kunden mit Markierung eigene Firma, Kontakte live aus AutoDNS (seitenweise, 60 s Zwischenspeicher), Zuordnung je System
- Kontakt anlegen (Person/Organisation) und einem oder mehreren Kunden zuordnen, nur mit Verwalten
- Domainliste mit Kunde (ueber den Inhaber-Kontakt), Inhaber, Ablaufdatum, Status; Filter und Gruppierung nach Kunde
- Mandantenschutz-Inventar um die beiden neuen Zugriffspaare ergaenzt

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 10:50:06 +02:00
schalli 1f1c984184 feat(domains): Modul Domains mit AutoDNS-Zugang, Verbindungstest und Einstellungen
- Migration mit vier Tabellen (Einstellungen, Kunden, Kontaktzuordnung, Bestellungen), Zeilenschutz je Organisation
- AutoDNS-Client mit festen Demo-/Live-Adressen, Takt-Begrenzer, 20 s Zeitlimit, ohne Wiederholung
- Zugang je System verschluesselt gespeichert, Live-Wechsel nur mit Bestaetigung, Verbindungstest
- Modulseite mit Systemkennzeichnung und Reiter Einstellungen (nur Verwalten)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 10:35:21 +02:00
schalli 6b0f840c1c docs(dkv): Modulbeschreibung kuerzer
Tessera CI/CD / Lint & Type Check (push) Successful in 55s
Tessera CI/CD / Tests (push) Successful in 1m26s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 19s
Tessera CI/CD / Build & Publish Images (push) Successful in 4m36s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 09:07:01 +02:00
schalli 4782fd5daf docs(dkv): Modulbeschreibung nennt Freigabestufe Verwalten, Version 1.1.0
Mit nur "Benutzen" erscheint DKV-Rechnung in der Seitenleiste, die
Seite zeigt aber "Kein Zugriff" (ganzes Modul verlangt Verwalten seit
261002-icv). Der Hinweis steht jetzt in der Marktplatz-Beschreibung.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-07 16:43:43 +02:00
schalli 831c7b8f52 fix(quick-261005-d5d): Postfach-Abruf ueber EWS mit 60-s-Zeitgrenze
Tessera CI/CD / Lint & Type Check (push) Successful in 52s
Tessera CI/CD / Tests (push) Successful in 1m45s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 20s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m41s
Gleicher eigener Timer wie im Kalender; httpreqs timeout greift
waehrend des Verbindungsaufbaus nicht. 60 s, weil PDF-Anhaenge
geladen werden.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 10:26:10 +02:00
schalli e49d4c7c9d fix(quick-261005-d5d): Kalender-Test bricht bei unerreichbarem Exchange nach 15 s ab
EWS-Aufrufe ueber httpntlm bekommen eine eigene 15-s-Zeitgrenze;
httpreqs timeout greift waehrend des Verbindungsaufbaus nicht
(gemessen 134 s). Netzfehler liefern im Test den Schluessel
'unreachable', das Formular meldet 'nicht erreichbar' statt
'Zugangsdaten pruefen'.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 09:29:25 +02:00
schalli 873d15d25e feat(quick-261005-bt1): Proxmox warnt bei gestopptem Gast mit aktivem Autostart
Fuer jeden nicht laufenden qemu/lxc (ohne Vorlage) liest der PVE-Durchlauf
onboot aus /nodes/{node}/{type}/{vmid}/config (nur GET, Deckel 40).
Befund in den Metriken (autostartStopped, autostartUnchecked); Karte wird
Warnung mit einer Zeile je Gast, Kachel zeigt 'gestoppt trotz Autostart'.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 08:30:20 +02:00
schalli af1878d5ee feat(quick-261003-387): Kategorien-API - Anlegen, Sortieren, Zuordnen, Loeschen mit Verschieben, Ueberlagerung in allen Modullisten
- Verwaltungs-Endpunkte nur fuer Administratoren, statische Routen vor :key
- Loeschen verschiebt alle Eintraege inkl. persoenlicher eigener Module in einer Transaktion, ohne Ziel 409
- /modules, /modules/catalog und /module-grants/matrix liefern wirksame Kategorie und Reihenfolge
- eigene Module pruefen die Kategorie gegen die Organisation (400 bei unbekannter)
- Zugriffsinventar nachgezogen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-03 02:39:36 +02:00
schalli 8ec116c75a feat(quick-261003-387): Modulkategorien je Organisation - Tabellen, Grundbestand, Lese-Endpunkt bis in die Seitenleiste
- Tabellen ModuleCategory und ModuleCategoryPlacement mit Zeilenschutz, Spalte CustomModule.sortOrder
- Dienst legt den Grundbestand beim ersten Lesen an, legt die wirksame Kategorie ueber Modullisten
- GET /module-categories, PATCH :key (nur Administratoren), /modules/active liefert wirksame Kategorie
- Seitenleiste ordnet Gruppen und Eintraege nach Kategorienspeicher, zeigt umbenannte Namen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-03 02:33:59 +02:00
schalli 0afcf237e8 feat(api): Protokollzeile je Anfrage und je Nextcloud-Pruefung im Docker-Log
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 23:42:10 +02:00
schalli 6c4bff6f6c feat(nextcloud-status): Meldung in Tessera, Anleitung und Changelog
- Endpunkt für letzte Übergänge der abonnierten Clouds, globaler Melder im Portalrahmen (Desktop: Windows-Benachrichtigung)
- Anleitung für Anwender und Administration, Changelog

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 15:30:45 +02:00
schalli 11a70c9ee9 feat(nextcloud-status): erneute Prüfung nach Ausfall und Hinweis auf der Kachel
- Wiederholungsauftrag jede Minute für Clouds mit einem Fehlschlag älter als fünf Minuten
- Neue Adresse setzt den Prüfstand zurück, der gemeldete Zustand bleibt
- Kachel: Hinweis Prüfung fehlgeschlagen, Fehlercodes als lesbarer Text mit Tooltip

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 15:26:23 +02:00
schalli faed0d760f feat(nextcloud-status): Benachrichtigung abonnieren und Mail bei Störung
- Glocke je Kachel (persönlich, Benutzen-Ebene), Tabelle NextcloudAlertSubscription mit RLS
- Zwei-Fehlschläge-Regel und gemeldeter Zustand auf der Zeile, Anspruch vor dem Mailversand
- Mail (nur Deutsch) über MailService, bis zu drei Versuche, Zugriff beim Senden erneut geprüft
- Fehlercodes in der Mail als lesbarer Hinweis

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-02 15:23:34 +02:00
schalli 87a7b7cbcd feat(nextcloud-status): Dashboard-Kachel, Anleitung und Changelog
- Kachel mit Zählern und roten/gelben Clouds, nur mit Modulzugriff sichtbar (geteilte Widget-Typen, Modulzuordnung, Katalog)
- Anleitung für Anwender und Administratoren, Eintrag im Changelog

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 15:00:31 +02:00
schalli 6698ef1a92 feat(nextcloud-status): Clouds verwalten, Logos, stündliche Prüfung und Sortierung
- Ändern, Entfernen, Logo-Upload und -Abruf, Sammelprüfung nur mit Verwalten
- Stündlicher Auftrag beim Start registriert, Prüfung je Cloud an ihren Mandanten gebunden
- Sortierung nach Kundenname, Status, Version und Support-Ende, je Benutzer gemerkt
- Formular zum Anlegen und Bearbeiten, Zugriffsinventar angepasst

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 14:54:58 +02:00
schalli 5ef7b0c6cc feat(nextcloud-status): Modul mit Statusabruf, Versionsbewertung und Kachelansicht
- NextcloudInstance mit Zeilenschutz, Migration 20261002150000
- Bewertung (Ampel) als reine Funktion, status.php-Abruf mit Grenzen, endoflife.date-Zwischenspeicher
- API: Liste mit Bewertung, Anlegen und Einzelprüfung nur mit Verwalten
- Modulseite mit Kacheln, Registrierung in Seitenleiste, Marktplatz und Symbolen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 14:49:02 +02:00
schalli eaf2c4574a feat(module-grants): Stufe Verwalten in Freigaben-Matrix und Benutzerdetails, Doku und Changelog
- Matrix und Benutzerdetails liefern und zeigen die Stufe, Auswahlfeld Benutzen/Verwalten
- Gruppen mit Verwalten sind in den Benutzerdetails markiert
- Administrationshandbuch, Anwenderanleitung und Changelog beschreiben die Stufen

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 13:35:00 +02:00
schalli c2ebc8daa0 feat(module-grants): Proxmox, Handelsware und DKV mit Freigabestufe Verwalten
- Proxmox-Schreibwege und Handelsware-Einstellungen auf @ModuleManage umgestellt
- DKV-Fleet: ganze Klasse Verwalten-Stufe, Benutzen allein bleibt ohne Zugriff
- Metadaten-Test belegt umgestellte und bewusst Administratoren vorbehaltene Handler
- Webseiten (Proxmox, Handelsware, Widget) folgen canManage, DKV-Zugriffsseite erklärt die Stufe

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 13:31:08 +02:00
schalli a222711ad9 feat(module-grants): Freigabestufe Verwalten – Datenbank, Zugriffsprüfung und Kantinen-Einstellungen
- Migration: ModuleGrant.level (USE/MANAGE), Bestand bleibt USE
- ModuleAccessService.getModuleAccessLevels als einzige Auflösung, MANAGE gewinnt
- @ModuleManage(slug) am ModuleGuard, GET /modules/active liefert canManage
- Kantinenabrechnung: Einstellungen für Benutzer mit Verwalten, Web-Hook useCanManageModule

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 13:28:24 +02:00
schalli 44c1d4351f feat(handelsware-datev): API, Kontenliste mit Zeilenschutz und DATEV-Export
- Prisma-Modelle HandelswareDatevConfig und HandelswareKonto mit Zeilenschutz (Migration 20261002130000)
- XLSX lesen (B1 Kopf, A/B ab Zeile 2, Zahl oder deutscher Text), Konten zuordnen, TXT erzeugen
- neue Konten werden nur beim Export in einer mandantengebundenen Transaktion gespeichert (409 bei geaenderter Liste)
- Konten-CSV Import (alles ersetzen) und Export mit Schutz vor Formeleinschleusung
- Einstellungen nur fuer Administratoren, statische Routen vor accounts/:id

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 11:38:22 +02:00
schalli 1f85277a3b feat(kantine-datev): Kantinenabrechnung als Modul in neuer Gruppe Finanzbuchhaltung
- neue Seitenleisten-Kategorie accounting (Finanzbuchhaltung / Financial accounting)
- CSV (UTF-8, UTF-8 mit BOM, Windows-1252) pruefen, Vorschau mit Zeilenfehlern, DATEV-Lohn-ASCII-Export
- Beraternummer, Mandantennummer, Lohnart je Mandant als Admin-Einstellung (KantineDatevConfig mit Zeilenschutz), anfangs leer
- hochgeladene Daten werden nicht gespeichert; Download per Blob (auch im Desktop-Client)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 11:32:55 +02:00
schalli c07b0cfaf0 feat(cert-manager): Zertifikatspaket hochladen, erkennen und in jedem Format herunterladen
Neuer erster Reiter Übersicht: mehrere Dateien oder die ZIP vom Aussteller
auf einmal ablegen. Der Server erkennt jedes Teil (Server-, Zwischen-,
Stammzertifikat, privater Schlüssel, CSR, auch aus PFX/P7B), fasst
Duplikate zusammen, ordnet Schlüssel/CSR dem Zertifikat zu und baut die
Kette. Unter jedem Teil stehen Download-Knöpfe für alle passenden Formate
(crt, cer, Fullchain, p7b, pfx mit Schlüssel und Kette; key PKCS#8/PKCS#1/
DER; csr PEM/DER). Geschützte PFX lassen sich mit Passwort entsperren.

Neue Endpunkte POST analyze (Dateien/ZIP, Begrenzung Anzahl und Größe vor
dem Entpacken) und POST export (JSON, zustandslos). Modultexte siezen jetzt
durchgehend; Gültigkeit in UTC wie im Zertifikat.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 15:23:34 +02:00
schalli 2dd11b439d fix(favorites): Logo auch fuer Seiten, die es per JavaScript setzen
Tessera CI/CD / Lint & Type Check (push) Successful in 49s
Tessera CI/CD / Tests (push) Successful in 1m28s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 20s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m18s
hosteurope.de liefert im HTML nur einen leeren data:-Platzhalter, das
echte Symbol setzt erst JavaScript; /favicon.ico antwortet mit HTML. Die
Kachel zeigte deshalb nur den Buchstaben. Scheitert das gespeicherte
Symbol, fragt getIconBytes jetzt einmal den DuckDuckGo-Symboldienst -
nur fuer oeffentlich erreichbare Seiten, interne Hostnamen verlassen das
Haus nicht; kennt der Dienst nichts (404), bleibt es beim Buchstaben.
Wirkt auch fuer bestehende Favoriten.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 12:28:32 +02:00
schalli 714f731ac9 feat(admin): Anmeldehinweise der Willkommensmail in der Vorlage bearbeitbar
Tessera CI/CD / Lint & Type Check (push) Successful in 51s
Tessera CI/CD / Tests (push) Successful in 1m29s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 19s
Tessera CI/CD / Build & Publish Images (push) Successful in 4m14s
Neue Felder loginHintDirectory/loginHintLocal (Platzhalter, Pflicht, max. 1000),
Migration 20260930170000 (nullable, leer = Standard aus @tessera/shared).
Knopf Passwort festlegen und Gueltigkeitshinweis bleiben fest; local-no-link
wird nie erzeugt und bleibt fest. Vorschau springt beim Bearbeiten auf die
passende Kontoart. Lokal im Browser nachgewiesen.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 17:56:05 +02:00
schalli e10da76259 feat(admin): eigene Vorlage fuer die Willkommensmail mit Platzhaltern, Vorschau und Testmail
Tessera CI/CD / Lint & Type Check (push) Successful in 50s
Tessera CI/CD / Tests (push) Successful in 1m22s
Tessera CI/CD / Desktop-Pakete bauen (push) Successful in 19s
Tessera CI/CD / Build & Publish Images (push) Successful in 3m10s
Administrator -> Willkommensmail: Betreff, Ueberschrift, Einleitung, Abschluss je
Mandant (Tabelle WelcomeMailTemplate, RLS je Mandant, Migration 20260930150000);
Platzhalter {{name}} {{vorname}} {{benutzername}} {{email}} {{adresse}} {{firma}},
unbekannte -> 400 bzw. Hinweis beim Tippen; Werte escaped, Vorlage reiner Text.
Live-Vorschau per API gerendert, Testmail an die eigene Adresse ohne Token,
Zuruecksetzen auf Standard. Feste Bausteine (Kopf, Zugangsdaten, Anmeldehinweis,
Knoepfe, Fusszeile) bleiben immer drin.
Kopf: Wellenzelle dunkel statt weiss, Streifen 600x40, Inhalt 24 px naeher –
keine weisse Luecke, wenn OWA das CID-Bild nicht zeigt.
Lokal nachgewiesen: Hinweis/Sperre bei {{xyz}}, Speichern, Testmail (Link nur
/login), echte Mail mit eigener Vorlage und 7-Tage-Link.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:49:17 +02:00
schalli 52f538c432 fix(mail): Willkommensmail-Kopf ohne Bildzwang – Logo als HTML, Welle als Streifen
Rueckmeldung des Nutzers: in Outlook nur ein grosser schwarzer Kasten, kein
Logo (das eingebettete Kopfbild wurde nicht angezeigt; Logo und Schriftzug
steckten nur darin). Jetzt Bildmarke aus Tabellenzellen und Schriftzug als
Text in einer niedrigen dunklen Leiste, darunter die Duenen-Welle als
600x56-Streifen, der ins Weiss auslaeuft; fehlt das Bild, bleibt nur Abstand.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-30 16:29:16 +02:00