patrick
de35eaa3ea
feat: QR-Stempeln als eigener Menüpunkt + Tablet-Link
...
Security Audit / Python Dependency Audit (push) Has been cancelled
Security Audit / Node.js Dependency Audit (push) Has been cancelled
QR-Stempeln aus CompanySettingsPage in eigene Seite /settings/qr-stamp
ausgelagert, eigener Nav-Eintrag 'QR-Stempeln' (COMPANY_ADMIN/SUPER_ADMIN).
Toggle speichert jetzt eigenständig (PATCH public_stamp_enabled). Neuer
Tablet-Link-Bereich: Direkt-URL kopieren + 'Auf diesem Gerät öffnen' zum
dauerhaften Einrichten eines Tablets am Eingang (gleicher Token wie Handy-QR).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-02 22:10:48 +02:00
patrick
06bb1c1664
feat: FZA Einzelstunden + Security-Fixes (K-1–K-5, H-2–H-4, M-1/M-3/M-6)
...
FZA Einzelstunden:
- Absence.fza_hours (Numeric 5,2) — FZA in Stunden statt Tagen
- Migration 0032: fza_hours Spalte in absences
- AbsenceCreate/AbsenceOut Schema um fza_hours erweitert
- absence_service: _deduct/_refund_overtime nutzt fza_hours direkt wenn gesetzt
- Frontend: Tage/Stunden-Toggle im FZA-Antrag-Modal
Security K-1: Privilege Escalation via PATCH /users/{id}.role
- user_service: Whitelist für Rollenänderungen, SUPER_ADMIN nur durch SUPER_ADMIN
- Letzter COMPANY_ADMIN gegen Selbst-Demotion gesichert
Security K-2: Kiosk-IP-Whitelist hinter nginx
- kiosk_security: _get_client_ip() liest X-Real-IP statt request.client.host
Security K-3: Kiosk-PIN Brute-Force-Schutz
- kiosk_auth_service: Redis-Lockout nach 5 Fehlversuchen (15 min)
Security K-4: TOTP-Setup-Hijacking
- auth router: /totp/setup abgelehnt wenn TOTP bereits aktiv
Security K-5: Separater Fernet-Key
- config: SECRET_KEY_DATA Feld (optional, Fallback auf SECRET_KEY)
- crypto: get_fernet_key() mit Warning bei fehlendem SECRET_KEY_DATA
Security H-2: Vacation Balance nur HR/Admin
- absences router: PATCH /balance nur noch HR/COMPANY_ADMIN/SUPER_ADMIN + AuditLog
Security H-3: Rate-Limits auf /auth/refresh + /auth/logout
- auth router: 30/min auf refresh, 60/min auf logout
Security H-4: Login-Failure-Logging + Lockout
- auth_service: Redis-Counter, Lockout nach 10 Versuchen (15 min)
- AuditLog für login_success und login_failed
Security M-1: Nginx Security-Header
- nginx.conf: X-Frame-Options, X-Content-Type-Options, CSP, Referrer-Policy, X-XSS-Protection, Permissions-Policy
Security M-3: AuditLog bei Rollenänderungen
- user_service: action=role_changed mit old/new role
Security M-6: create_all nur in Development
- main.py: Base.metadata.create_all nur wenn not settings.is_production
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-26 11:13:42 +02:00
patrick
094863f94b
feat: agent-02-kiosk Phase 1 - NFC UID migration + session service
...
- Migration 0025: kiosk_nfc_uid column on users table with partial unique index per company
- User model: kiosk_nfc_uid field after personnel_number
- New service: kiosk_session_service.py (Redis-based 15min sessions)
- New core module: app/core/redis.py (sync Redis client with ping-test)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-24 12:45:47 +02:00
patrick
35fcea90f4
feat(kiosk): Stufe 3 – ServiceWorker, WebCrypto Setup-Flow, Kiosk-UI, 15 Security-Tests
...
3A – Frontend Kiosk-Modus:
- public/kiosk-sw.js (NEU, 187 Zeilen): ServiceWorker signiert alle /api/v1/kiosk/
Requests automatisch mit Ed25519. Keypair-Generierung intern (non-extractable),
Speicherung in IndexedDB. BroadcastChannel-Leader-Election für Heartbeat.
- KioskSetupPage.tsx (NEU, 307 Zeilen): Enrollment-Flow unter /kiosk/setup.
Keypair-Generierung via WebCrypto im ServiceWorker, Public Key als PEM anzeigen.
Browser-Kompatibilitäts-Check (Ed25519 ab Chrome 113+).
- KioskStampPage.tsx (NEU, 348 Zeilen): Kiosk-UI unter /kiosk.
Live-Uhr mit Server-Zeit-Offset, Heartbeat-Loop 30s, Online/Offline-Indikator.
- App.tsx: /kiosk und /kiosk/setup Routen außerhalb ProtectedRoute
3B – Tests:
- tests/test_kiosk_security.py (NEU, 387 Zeilen): 15/15 Tests grün
Abgedeckt: gültige Signatur, falscher Key, Replay-Schutz, Timestamp-Drift,
Future-Timestamp, pending/revoked Device, unbekanntes Gerät, fehlende Header,
Lifecycle-Tests, heartbeat_status nach Heartbeat
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-24 12:23:03 +02:00
patrick
0f83d13c0c
feat(kiosk): Stufe 2 – Ed25519-Auth, CLI-Tool, neue KioskDevicesPage
...
2A – Backend Ed25519-Verifizierung:
- app/core/kiosk_security.py (NEU): verify_kiosk_request() Dependency
- Timestamp-Check (30s Drift), Nonce-Cache (Redis/In-Memory), IP-Whitelist
- Ed25519-Signatur über METHOD+PATH+TIMESTAMP+NONCE+sha256(BODY)
- PEM + OpenSSH Key-Format unterstützt
- app/routers/kiosk.py: approve/revoke Endpunkte, POST /heartbeat (Ed25519-signiert)
- app/services/kiosk_service.py: token-basierte Methoden entfernt, approve/revoke/heartbeat
- app/schemas/kiosk.py: KioskDeviceOut mit heartbeat_status, HeartbeatRequest/Response
2B – CLI-Tool:
- cli.py (NEU, 529 Zeilen): Typer-CLI mit kiosk add/list/approve/revoke/info
- Public-Key-Fingerprint (SHA256), Rich-Tabellen, CIDR-Validierung
- Direkter DB-Zugriff mit RLS-Bypass
2C – Frontend:
- KioskDevicesPage.tsx: Zwei-Tab-Layout (Wartet/Aktiv), Status-Ampel,
Auto-Refresh 30s, Ed25519-Workflow (kein Token mehr)
- Layout.tsx: KioskHealthBadge (online/total, 30s Refresh, nur COMPANY_ADMIN)
requirements.txt: typer>=0.12.0, rich>=13.7.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-24 12:13:46 +02:00
patrick
ada1b51f33
docs: vollständige Projektdokumentation hinzugefügt
...
- docs/api.md: komplette API-Referenz (1375 Zeilen, alle Endpunkte)
- docs/architecture.md: Tech-Stack, DB-Schema, RLS-Architektur, Auth-Flow
- docs/deployment.md: Setup, nginx, systemd, update.sh, Backup/Rollback
- docs/development.md: Dev-Setup, Test-Workflow, Code-Konventionen, Fallstricke
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-24 11:29:44 +02:00
sysops
1fedd683e0
Initial commit – TimeMaster Zeiterfassung & HR-Tool
...
Stand: agent-06 (Audit-Log), agent-05 (Krankmeldung), agent-07 Phase 1 (Personalnummer),
Busylight-Pull-Integration, TOTP/2FA, Abwesenheiten, Zeiterfassung, Kiosk-Grundgerüst.
Migrations 0001–0023 deployed auf 192.168.1.137 + .164.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-23 20:03:27 +02:00