Neuer Router /admin/tls (SUPER_ADMIN only, AuditLog, Rate-Limit 5/hour):
- GET /admin/tls/status – erkennt proxy/certbot/internal-Modus,
liest Ablaufdatum via openssl x509 -enddate
- POST /admin/tls/renew/certbot – ruft setup-tls.sh <domain> auf
- POST /admin/tls/renew/internal – ruft setup-tls-internal.sh <hostname> [ip]
auf, reloaded nginx danach
Läuft mit den Root-Rechten des bestehenden timemaster.service (User=root,
unverändert) - Angriffsfläche dadurch begrenzt auf SUPER_ADMIN-Auth +
Domain/Hostname-Validierung (Regex, kein Shell-Interpolieren, subprocess
mit Argument-Liste statt shell=True).
Frontend: neuer Tab "Server / TLS" in TenantsPage – Status-Anzeige +
zwei Formulare (öffentlich/intern).
3 neue Tests in test_tls_admin.py (Rollen-Gate, Status im Testcontext,
Input-Validierung).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LTxkZEUdfgMxZvHPiZJ8bV
Geplante Erinnerungen (Feature-Parität mit Urlaubsverwaltung):
- APScheduler (AsyncIOScheduler) in der FastAPI-Lifespan; tägliche Jobs ab
settings.reminder_hour. Redis-Tageslock gegen Doppelversand bei mehreren
Prozessen; jeder Job mit eigener Session + RLS-Bypass.
- Drei Jobs (auch einzeln aufrufbar): offene Anträge an Genehmiger,
Resturlaub-Verfall-Vorwarnung an Mitarbeiter, fehlende AU an HR.
- Pro-User notification_prefs (JSONB, opt-out); GET/PATCH /users/me/notification-prefs
+ ProfilePage-UI; Vertreter-Mail respektiert die Prefs.
- Manueller Trigger POST /companies/me/run-reminders (Admin) – gleiche Logik,
firmen-scoped (testbar ohne Warten).
- Bugfix: GET-/PATCH-Urlaubskonto (update_balance) nutzte nicht existente
Felder (base_days/carried_over_days/ip_address) → korrigiert auf
entitled_days/carried_over/ip + company_id; available_days ergänzt.
Migration 0037 (users.notification_prefs). 188/188 Tests grün. Deployed 137 + 164.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mandantenfähigkeit ausgebaut:
- Neue Rolle RESELLER (company_id NULL); companies.reseller_id + is_active
- RLS-Erweiterung (Migration 0034): companies/users zusätzlich auf app.reseller_id
gefenced → Reseller sieht/verwaltet DB-seitig nur eigene Firmen, keine
personenbezogenen Zeit-/Abwesenheitsdaten (DSGVO: nur Verwaltung)
- get_current_user setzt app.reseller_id + Bypass aus für RESELLER
- tenant_service: Firma + Erst-Admin (Einladung), Übersicht mit Kennzahlen
- Router /reseller/* (Self-Service) und /admin/* (SUPER_ADMIN: Mandanten + Reseller)
- Login-Sperre bei deaktiviertem Mandanten
- Frontend: TenantsPage (/admin/tenants), eigene ResellerCompaniesPage (/reseller),
rollenbasierte Login-Weiterleitung, Nav "Mandanten" für SUPER_ADMIN
- 4 neue Tests inkl. Cross-Reseller-RLS-Isolation; 172/172 grün
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mitarbeiter scannen einen am Eingang ausgehängten QR-Code mit dem Privat-Handy
(/stamp?t=<token>), melden sich per Personalnummer + PIN an und stempeln ein/aus.
Eigener öffentlicher Endpunkt-Pfad, da der Kiosk-PIN-Login Ed25519-Geräte-
Signaturen verlangt, die ein Privat-Handy nicht hat.
Backend:
- Company.public_stamp_enabled (opt-in, default OFF) + rotierbares
public_stamp_token_hash (SHA-256) + created_at; Migration 0033
- Router /time/public: company/auth/action (slowapi-Limits, AuditLog)
- kiosk_auth_service.login_pin_public() reused PIN-Lockout, keyed auf
(public:company_id, personnel_number)
- public_stamp_session_service: 120s Redis-Kurz-Session
- Admin-Token-Endpunkte in companies.py (GET/rotate/DELETE)
Frontend:
- Public-Route /stamp (PublicStampPage)
- Stempel-PIN-Verwaltung in ProfilePage (reused POST /users/{id}/kiosk-pin)
- QR-Generierung/Druck/Toggle in CompanySettingsPage
Sicherheit: schwächer als Kiosk (keine Geräte-Signatur/Nonce/IP-Whitelist),
bewusster BYOD-Komfort-Tradeoff; Schutz über PIN + Lockout + opt-in.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Backend: Model HoursPayout, Schema, Router GET/POST/DELETE
- GET /hr/payouts: HR/Admin sehen alle, Employee/Manager nur eigene
- POST /hr/payouts: reduziert OvertimeBalance.taken_hours sofort
- DELETE /hr/payouts/{id}: storniert und bucht Stunden zurück
- AuditLog-Einträge bei Anlegen und Stornieren
- Migration 0030: hours_payouts Tabelle
- Frontend: /hr/payouts Seite (lila, 💸) mit Filter, Tabelle, Modal
- Modal zeigt verfügbares Überstundenguthaben + Warnung bei Überziehung
- Navigation: Stunden-Auszahlung (HR/COMPANY_ADMIN/SUPER_ADMIN)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>