# TimeMaster Zeiterfassung & HR-Tool (Zeiterfassung, Abwesenheiten, Kiosk-Terminals, Reports) – DSGVO-konform, EU-Server. Multimandantenfähig mit strikter Company-Isolation über PostgreSQL Row-Level-Security. ## Tech-Stack - **Backend**: Python 3.12 · FastAPI · SQLAlchemy (async) · PostgreSQL 16 · Redis 7 · Alembic - **Frontend**: React 18 · TypeScript · Tailwind CSS · Vite - **Deployment**: nativ auf Ubuntu (systemd + nginx), kein Docker - **Tests**: pytest + pytest-asyncio + pytest-cov ## Features (Auszug) - Zeiterfassung mit ArbZG-Prüfung (Pausen, Höchstarbeitszeit, Ruhezeiten) - Abwesenheiten: Urlaub (mit Pro-rata/Teilzeit-Anspruch), Krankmeldung (Bradford-Faktor), Zwei-Stufen-Genehmigung - Kiosk-Terminals: Ed25519-signierte PC-Terminals, NFC+PIN, QR-Code-BYOD-Stempeln - 2FA (TOTP), LDAP-Sync, CalDAV-Export, iCal-Abo-Feed - Reports & Exports: CSV/XLSX/PDF, DATEV-Monatsblatt für Steuerberater - Reseller/Mandantenverwaltung, Audit-Log, DSGVO-Datenexport (Art. 15) + Löschkonzept ## API-Dokumentation Vollständige Endpunkt-Referenz: [`docs/api.md`](docs/api.md). Interaktive Swagger-UI (`/docs`) und ReDoc (`/redoc`) sind nur im Development-Modus aktiv, nicht in Production. ## Setup Migrationen und Tests laufen nicht lokal, sondern auf dem Zielserver (kein lokales Postgres/Redis vorausgesetzt). **Server-Neueinrichtung** (Debian 13, als root): ```bash bash setup_server.sh ``` Installiert Postgres, Redis, nginx, Python-venv, führt Alembic-Migrationen aus und schreibt die nginx-Konfiguration. Danach `.env` mit echten Secrets befüllen. **Frontend deployen** (von einem Rechner mit Node.js, nach dem Server-Setup): ```bash ./push-frontend.sh ``` Baut das Frontend (`npm run build`) und synct `dist/` zum Server. ## Deployment-Workflow (bestehender Server) Server pullen git-basiert aus dem eigenen Remote, kein direktes Hochladen von Code: ```bash git push origin main # lokal ssh root@ 'cd /opt/timemaster && ./server-update.sh' # git pull → alembic → restart → health-check ``` ## Tests ```bash cd backend pytest -q ``` Läuft gegen eine echte PostgreSQL-Testdatenbank (RLS-Policies werden in `conftest.py` repliziert), kein SQLite. Coverage-Gate: `--cov-fail-under=50` in `pytest.ini`.