chore(analytics): Umami-Kern entfernen — Injection, Client-Lib, Auth-Hook, Container, DB

Erster Schritt der Umami-Komplett-Entfernung (Entscheidung: kein Web-Analytics):
- hooks.server.ts: injectUmamiAnalytics-Injection raus (stoppt Script-Load in der Unified-App)
- packages/shared-utils/analytics-server.ts: GELÖSCHT (Script-Injection-Util)
- packages/shared-utils/analytics.ts: zu No-op entkernt — window.umami/isUmamiAvailable
  raus, trackEvent no-op; alle 28 *Events-Aufrufer kompilieren weiter (senden nichts)
- packages/shared-auth/authService.ts: inline-Umami-trackAuth-Hook + Aufrufe raus
- infrastructure/docker-compose.gpu-box.yml: umami-Service (mana-mon-umami) raus
- docker/init-db: CREATE DATABASE umami + GRANT raus
- gelöscht: docs/ANALYTICS.md, scripts/mac-mini/setup-umami-db.sh, picture-landing .env.example

VERBLEIBEND (separat, größer): ~60 weitere Dateien — 7 Landing-Layout.astro
(eigene Script-Injection), website-blocks Analytics-Feature, Legal/Datenschutz,
i18n×5, Admin-UI, ~20 Docs. Teils produkt-/rechts-sensibel → in Wellen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-26 14:21:04 +02:00
parent 1d9a19d40f
commit 9720cd9516
9 changed files with 10 additions and 585 deletions

View file

@ -23,20 +23,6 @@ import {
getAppSettings as getAppSettingsFromToken,
} from './jwtUtils';
/**
* Inline analytics helper - tracks auth events via Umami if available.
* No-ops silently in environments without Umami (mobile, SSR, dev).
*/
function trackAuth(event: string, data?: Record<string, string | number | boolean>): void {
if (typeof window !== 'undefined' && (window as any).umami?.track) {
try {
(window as any).umami.track(event, { ...data, module: 'auth' });
} catch {
// Silently ignore tracking errors
}
}
}
/**
* Default storage keys
*/
@ -135,11 +121,9 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
// SSO cookie is nice-to-have, don't fail login if this fails
}
trackAuth('login', { method: 'email' });
return { success: true };
} catch (error) {
console.error('Error signing in:', error);
trackAuth('login_failed', { method: 'email' });
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error during sign in',
@ -175,11 +159,9 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
// If emailVerified is false, the user needs to verify their email before login
const needsVerification = data?.user?.emailVerified === false;
trackAuth('signup', { method: 'email' });
return { success: true, needsVerification };
} catch (error) {
console.error('Error signing up:', error);
trackAuth('signup_failed', { method: 'email' });
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error during sign up',
@ -203,7 +185,6 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
}).catch((err) => console.error('Error logging out on server:', err));
}
trackAuth('logout');
await service.clearAuthStorage();
} catch (error) {
console.error('Error signing out:', error);
@ -228,7 +209,6 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
return service.handleAuthError(response.status, errorData);
}
trackAuth('password_reset_requested');
return { success: true };
} catch (error) {
console.error('Error sending password reset email:', error);
@ -484,7 +464,6 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
return { success: false, error: err.message || 'Passkey registration failed' };
}
trackAuth('passkey_registered');
return { success: true };
} catch (error) {
// User cancelled or WebAuthn error
@ -572,14 +551,12 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
storage.setItem(storageKeys.USER_EMAIL, data.user?.email || ''),
]);
trackAuth('login', { method: 'passkey' });
return { success: true };
} catch (error) {
if (error instanceof Error && error.name === 'NotAllowedError') {
return { success: false, error: 'Passkey authentication was cancelled' };
}
console.error('Passkey authentication error:', error);
trackAuth('login_failed', { method: 'passkey' });
return {
success: false,
error: error instanceof Error ? error.message : 'Passkey authentication failed',
@ -758,7 +735,6 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
}
}
trackAuth('login', { method: '2fa' });
return { success: true };
} catch (error) {
return {
@ -805,7 +781,6 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
}
}
trackAuth('login', { method: 'backup_code' });
return { success: true };
} catch (error) {
return {
@ -892,7 +867,6 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
return { success: false, error: err.message || 'Failed to send magic link' };
}
trackAuth('magic_link_sent');
return { success: true };
} catch (error) {
return {
@ -1297,7 +1271,6 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
]);
console.log('SSO: Successfully authenticated via session cookie');
trackAuth('login', { method: 'sso' });
return { success: true };
} catch (error) {
// SSO failed - this is expected if user hasn't logged in anywhere