Vertrag: „Portaldaten nicht möglich / nicht benötigt"-Opt-out

Dritter Radio-Button in der Zugangsdaten-Card des Vertragsformulars.
Wenn gesetzt, unterdrückt das Cockpit die Warnung „Portal-Zugangs-
daten fehlen" für diesen Vertrag – für Anbieter ohne Portal oder
Kunden, die bewusst keine Zugangsdaten pflegen. Verstopft das
Cockpit sonst dauerhaft.

Neues Feld Contract.portalCredentialsNotRequired (Boolean, default
false) + idempotente Migration (ADD COLUMN IF NOT EXISTS). Bestand
bleibt auf false, Warnung greift wie bisher.

Beim Umschalten auf Opt-out werden portalUsername,
portalPasswordEncrypted und stressfreiEmailId server-seitig
explizit auf NULL gesetzt – Datenhygiene, damit keine verwaisten
Anmeldedaten in der DB stehen bleiben.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 14:45:32 +02:00
co-authored by Claude Opus 4.7
parent aeecc3327f
commit dcdb3cb057
7 changed files with 132 additions and 35 deletions
+29
View File
@@ -97,6 +97,35 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
## ✅ Erledigt
- [x] **🔕 Vertrag: „Portaldaten nicht möglich / nicht benötigt"-Opt-out**
- Dritter Radio-Button in der `Zugangsdaten`-Card des Vertragsformulars:
„Nicht möglich zu bekommen / nicht benötigt". Wenn gesetzt, unterdrückt
das Cockpit die Warnung „Portal-Zugangsdaten fehlen" für diesen
Vertrag (Anbieter hat kein Portal / Kunde bekommt keine Zugangsdaten).
- Neues Feld `Contract.portalCredentialsNotRequired` (Boolean, default
false) + Migration `20260717100000_contract_portal_credentials_not_required`
(`ADD COLUMN IF NOT EXISTS`). Bestand bleibt unverändert warnend.
- Passwort-Spalte im Formular wird bei Opt-out ausgeblendet; alte
Username-/Passwort-Werte werden beim Umschalten geleert, damit der
Vertrag nach dem Speichern nicht mit Leichen zurückkommt.
- [x] **🔧 Debug-Hilfe: Fehler bei „PIN/PUK anzeigen" sichtbar machen**
- Der stumme `alert('PIN/PUK konnte nicht geladen werden')` maskierte
die eigentliche Ursache. Ersetzt durch Toast mit Backend-Message
(Vertrag nicht gefunden / Kein Zugriff / Decrypt-Fehler),
`console.error` mit Stacktrace und einem Info-Toast, falls die SIM
in der DB gar keine PIN/PUK hinterlegt hat. Kein Verhaltens-Change am
Endpoint nur Diagnose.
- [x] **🔗 Vertrag-Zugangsdaten: Externtab-Link zu Kunden-Adressen**
- Kleines Externtab-Icon neben dem Label „Portal Benutzername", öffnet
`/customers/{id}?tab=stressfrei` in neuem Tab, damit man beim Anlegen
einer Portal-Wechseladresse nicht durch die Vertragsansicht zurück
navigieren muss. Sichtbar in beiden Modi.
- Als R116 vom Pentester geprüft, kein Finding (SPA-Parameter, Backend
wertet `?tab=` nicht aus; Sub-Route-IDOR-Check auf `canAccessCustomer`
steht).
- [x] **🔧 Pentest R111 contract-categories: falscher Permission-String**
- Der Pentester meldete 403 auf `POST/PUT/DELETE /api/contract-categories/*`
für Admin trotz vorhandener `contract-categories:*`-Permissions.