# Änderungen Alle nennenswerten Änderungen an diesem Projekt stehen hier. Das Format folgt [Keep a Changelog](https://keepachangelog.com/de/1.1.0/), die Versionierung [Semantic Versioning](https://semver.org/lang/de/). ## [Unveröffentlicht] ### Hinzugefügt - **Wochenansicht** mit Ziehen und Ablegen: Aufgaben aus der linken Spalte in ein Zeitfenster ziehen legt einen Zeitblock an und schreibt ihn in den Kalender. Die Dauer kommt aus dem geschätzten Aufwand der Aufgabe. - Zeitblöcke verschieben und ausplanen; der Kalendertermin zieht mit. - **Rückweg**: Wird ein Zeitblock im Kalender verschoben, übernimmt der Planer das beim nächsten Abgleich. Wird er dort gelöscht, verschwindet auch der Zeitblock — die Aufgabe bleibt und fällt zurück auf offen. - Kapazität und Belegung je Wochentag über jeder Spalte; überbuchte Tage werden rot, sperren aber nichts. - Eine eingeplante Aufgabe wechselt selbsttätig von _Offen_ auf _Geplant_ und wieder zurück, wenn nichts mehr für sie geplant ist. - Handbuchseite zur Wochenplanung. ### Sicherheit - **Schleifenschutz** über `hash = sha256(startISO|endeISO)`: Der Planer schreibt nur bei eigener Änderung und übernimmt aus dem Kalender nur, wenn der Fingerabdruck abweicht. Ohne das würden App und Kalender einander endlos hinterherschreiben. - Jeder Schreibzugriff auf einen bestehenden Termin geht mit `If-Match` heraus. Bei HTTP 412 **gewinnt der Kalender**: der Planer schreibt nicht, verwirft seinen Fingerabdruck und überlässt dem nächsten Abgleich, den fremden Stand zu holen. - Zeitblöcke gehören dem Benutzer über sein Kalenderkonto; die Kennung geht in jede where-Bedingung, nicht in einen nachträglichen Vergleich. ## [0.3.0] – 2026-09-10 ### Hinzugefügt - Kalenderkonten für Microsoft 365 (Graph) und Google verbinden, umbenennen, von Hand abgleichen und trennen. Google gibt es nur in der Instanz `daheim`; in `firma` liefert die Route 404. - Termine werden örtlich gespiegelt: 7 Tage zurück bis 90 Tage voraus. Gelesen werden nur Beginn, Ende, Betreff, ganztägig und "zeigt an als" — keine Teilnehmer, Beschreibungen, Anhänge oder Orte. - Die Startseite zeigt je Bereich, wie voll der heutige Tag ist: Termine aus allen verbundenen Kalendern gegen die Tageskapazität. - Hintergrundjobs: alle 15 Minuten abgleichen, nachts alte Termine und abgelaufene WebAuthn-Herausforderungen entfernen. - Handbuchseite zu den Kalenderkonten, Einrichtungsanleitung für Entra ID und die Google Cloud Console in der README. ### Sicherheit - Zugangs- und Aktualisierungstoken liegen verschlüsselt in der Datenbank (AES-256-GCM, Schlüssel aus AUTH_SECRET abgeleitet). Wer eine Sicherung in die Hände bekommt, kann damit ohne AUTH_SECRET nichts anfangen. - Der Zustandswert im OAuth-Ablauf ist signiert und trägt die Benutzerkennung; ohne das ließe sich ein fremdes Kalenderkonto an ein beliebiges Konto hängen. Er verfällt nach 30 Minuten. - Fehlermeldungen nennen nie den Antwortkörper des Token-Endpunkts — der enthält das Client-Secret oft im Echo. - Protokolliert werden beim Abgleich nur Zahlen, nie Kontonamen oder Termininhalte. ## [0.2.0] – 2026-09-10 ### Hinzugefügt - Aufgaben mit Typ, Status, Priorität, Aufwand, Fälligkeit und Herkunft; Projekte als Klammer darum. - Schnellerfassung mit einem einzigen Feld auf der Startseite und in der Inbox. - Inbox: alles ohne Bereich sammelt sich dort und wird später einsortiert. Die Zahl im Menü zeigt, wie viel noch liegt. - Aufgabenliste mit Filtern nach Suche, Bereich, Status, Art und Projekt. Die Filter stehen in der Adresse und lassen sich als Lesezeichen ablegen. - Ideen als eigene Ansicht, ohne Termin und ohne Aufwand; per Klick wird daraus eine Aufgabe. - Projekte mit Arbeitspaketen, Meilensteinen und Fortschritt. - Die Startseite zeigt, was überfällig, heute oder morgen fällig ist. - Handbuchseiten zu Aufgaben, Ideen und Projekten. ### Geändert - Die Startseite zählt nicht mehr nur Bereiche auf, sondern stellt voran, was jetzt dran ist. ### Sicherheit - Statuswechsel folgen festen Übergängen: Abgeschlossenes wird erst wieder geöffnet. Ein abweichender Wert im Formular führt zu einer Meldung, nicht zu einem stillen Zustandssprung. - Angegebene Bereiche und Projekte werden vor dem Speichern geprüft; ein erfundener Verweis gibt eine Meldung statt eines Datenbankfehlers. ## [0.1.0] – 2026-09-10 ### Hinzugefügt - Projektgerüst mit Next 16 (App Router, `output: "standalone"`), React 19, TypeScript strict, Tailwind 4 und shadcn-Primitiven. - `npm run pruefen` bündelt Prettier, ESLint, `tsc --noEmit`, Vitest und ShellCheck. ShellCheck läuft über das Docker-Abbild, wenn es lokal fehlt. - Datenmodell für Benutzer mit Rolle, OIDC-Konten, Passkeys, Bereiche und Audit-Einträge; PostgreSQL 16 über Prisma 7 mit pg-Treiberadapter. - Anmeldung über einen generischen OIDC-Anbieter, über Passkeys (SimpleWebAuthn) und wahlweise über E-Mail und Passwort. - Rollen `BENUTZER` und `ADMIN`. Jede schreibende Aktion prüft die Rolle serverseitig in der Seite **und** noch einmal in der Server Action. - Audit-Protokoll für jede schreibende Aktion, mit Protokollseite für die Verwaltung. Details werden vor dem Speichern gesäubert. - Instanzsteuerung über `INSTANZ=firma|daheim`. Was eine Instanz nicht darf, liefert dort 404 und lädt seine Konfiguration gar nicht erst. - Bereiche mit Farbe, Arbeitsfenster und Tageskapazität je Wochentag. - Zeitrechnung durchgehend in Europe/Berlin, mit Tagesgrenzen, Wochenbeginn am Montag und deutschen Anzeigeformaten. - `/api/health` mit Status, Version, Instanz und Erreichbarkeit der Datenbank. - Hell und Dunkel, Navigation mit Rollenfilter, Oberfläche auf Deutsch. - Dockerfile in drei Stufen und Compose-Stapel mit eigenem Migrationsdienst. - `backup.sh` (pg_dump im Custom-Format, `.env` und Uploads), `update.sh` (mit Rückrollpfad), `scripts/release.sh` und `scripts/zeit.sh`. - Tests: Unit mit Vitest, Integrationstest und Migrationstest gegen eine echte Datenbank, E2E-Rauchtest mit Playwright. - `npm run screenshots` nimmt die Handbuchbilder in einer Wegwerf-Instanz mit ausschließlich erfundenen Daten auf. - README, Schnellstart, Handbuch, ROADMAP und DEVLOG. ### Sicherheit - Anmeldung, Passwort und Passkey antworten bei Fehlschlag immer gleich, damit sich nicht abfragen lässt, wer ein Konto hat. - Sitzungen als JWT, aber Rolle und Sperrstatus werden bei jeder Anfrage frisch aus der Datenbank gelesen — eine Sperre wirkt sofort. - Die WebAuthn-Herausforderung wird nach einem Versuch verworfen, gleich ob er geglückt ist. - Der Demo-Seed verweigert den Dienst ohne `DEMO_MODUS=true`. - `allowDangerousEmailAccountLinking` ist bewusst aktiv: je Instanz gibt es genau einen vertrauenswürdigen OIDC-Anbieter, der die Adresse selbst prüft.