Datenschutz: Log-Bereinigung vor Server-Upload (Scrubber + Quelle)

Diagnose-Logs werden zentral bereinigt, bevor sie an logs.baka-net.de gehen.
Lokaler debugPrint bleibt vollständig.

- Freitext-Scrubber (LoggerService.scrubText) für message + stackTrace:
  maskiert user=/pw=/password=/token=/secret=/url= sowie Datei-Pfade,
  nackte URLs, Bearer-Token, JWTs und lange Hex-IDs.
- stackTrace auf 8 Zeilen gekürzt (capFrames).
- deviceModel nur noch grobe Plattform (android/ios) statt Hersteller+Modell;
  device_info_plus im Logger entfernt.
- Quelle entschärft: settings_screen loggte Navidrome-Login mit Klartext
  user=/url= — jetzt nur neutraler Status inkl. pwLeer-Flag.
- Neue Tests: test/logger_service_test.dart (9). 79/79 grün, analyze sauber.

Opt-in/Einwilligung bleibt separater Folgeschritt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tr2UwurtxyJUpWpBSeVmBm
This commit is contained in:
Hermes (Server)
2026-08-20 01:38:56 +02:00
co-authored by Claude Opus 4.8
parent 61e28d128f
commit d83f8c8c54
4 changed files with 142 additions and 19 deletions
+3 -6
View File
@@ -263,23 +263,20 @@ class _SettingsScreenState extends State<SettingsScreen> {
: () async {
setDialogState(() => verbindet = true);
logger.info(
'Login-Versuch: url=${urlCtrl.text} user=$selectedUser '
'pwLeer=${passCtrl.text.isEmpty}');
'Navidrome Login-Versuch (pwLeer=${passCtrl.text.isEmpty})');
_navidrome.setCredentials(
urlCtrl.text, selectedUser, passCtrl.text);
final ok = await _navidrome.ping();
setDialogState(() => verbindet = false);
if (ok && ctx.mounted) {
logger.info(
'Login erfolgreich: url=${urlCtrl.text} user=$selectedUser');
logger.info('Navidrome Login erfolgreich');
await _navidrome.speichereZugangsdaten(
urlCtrl.text, selectedUser, passCtrl.text);
if (ctx.mounted) Navigator.pop(ctx);
if (mounted) setState(() {});
} else if (ctx.mounted) {
await logger.error(
'Login fehlgeschlagen: url=${urlCtrl.text} '
'user=$selectedUser pwLeer=${passCtrl.text.isEmpty}');
'Navidrome Login fehlgeschlagen (pwLeer=${passCtrl.text.isEmpty})');
setDialogState(() =>
fehler = '❌ Login fehlgeschlagen');
}