Files
planer/CHANGELOG.md
T
2026-09-13 15:19:30 +02:00

271 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Ä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
- **MCP-Server** unter `/api/mcp` mit sechs Werkzeugen: Aufgaben suchen,
Woche ansehen, Kalender auflisten, Aufgabe anlegen, abhaken und einplanen.
Beschreibung in [docs/MCP.md](docs/MCP.md).
- Die Werkzeugliste richtet sich nach den Rechten des Tokens — was ein Token
nicht darf, sieht das Modell gar nicht erst.
### Geändert
- Das Einplanen liegt jetzt an einer Stelle, die sowohl die Oberfläche als
auch der MCP-Server benutzen. Ein über MCP angelegter Zeitblock verhält
sich damit genau wie ein von Hand gezogener.
### Sicherheit
- MCP benutzt dieselben Tokens und dieselben Rechte wie die Schnittstelle.
Ein Sprachmodell bekommt keinen eigenen Zugang.
- Jede schreibende Nutzung steht im Protokoll, mit dem Vermerk, dass sie
über MCP kam.
- Der Server kann weder löschen noch Bereiche, Projekte, Kalenderkonten,
Einstellungen oder Tokens anfassen.
## [0.7.0] – 2026-09-13
### Hinzugefügt
- **Schnellerfassung vom Handy** unter _Erfassen_: ein Feld, ein Knopf. Was
ohne Netz erfasst wird, bleibt im Gerät und geht hinaus, sobald wieder eine
Verbindung da ist — mit einer Kennung je Erfassung, damit eine doppelt
zugestellte Nachricht keine zweite Aufgabe ergibt.
- Der Planer lässt sich als **App auf dem Startbildschirm ablegen**
(Manifest, eigenes Symbol, eigener Startpunkt).
- **Öffentliche Schnittstelle** unter `/api/v1`: Aufgaben lesen, anlegen,
ändern und abhaken. Beschreibung in [docs/API.md](docs/API.md).
- **Tokens je Anwendung** mit Rechten je Token, wahlweise mit Ablauf,
verwaltbar unter _API_.
- Handbuchseite zur Schnellerfassung.
### Sicherheit
- Von einem Token liegt nur der Fingerabdruck in der Datenbank. Der Wert
erscheint genau einmal — beim Anlegen.
- Die drei Rechte schließen einander nicht ein: Ein Dienst, der nur erfasst,
kann den Bestand nicht lesen.
- Jeder Fehlschlag beim Ausweisen sieht gleich aus. Ob ein Token unbekannt,
abgelaufen oder zurückgezogen ist, verrät die Schnittstelle nicht.
- Jede schreibende Nutzung steht im Protokoll, mitsamt dem Token — auch jeder
abgewiesene Zugriff.
- Die Schnittstelle kann weder löschen noch Bereiche, Projekte, Zeitblöcke
oder Kalender anfassen.
## [0.6.0] – 2026-09-12
### Hinzugefügt
- **Zammad** (nur `firma`): Tickets, auf die der Suchausdruck passt, werden zu
Aufgaben — mit Verweis ins Ticket. Wird ein Ticket dort geschlossen, hakt
der Planer die Aufgabe ab.
- **Telegram** (nur `daheim`): Eine Nachricht an den Bot wird zur Aufgabe.
Meldungen gehen denselben Weg zurück, mit einem Knopf zum Abhaken. Ein Chat
meldet sich über einen Einmalcode an, der zehn Minuten gilt.
- **Telegram als dritter Meldeweg** neben Push und E-Mail.
- **Spiegel** zwischen den Instanzen: `firma` schickt Belegungen ohne Titel
und die einzeln dafür markierten Aufgaben, `daheim` empfängt. Gespiegelte
Belegung erscheint in der Wochenansicht als „Dienstlich belegt" und zählt
gegen die Tageskapazität.
- Seite **Integrationen**: je Integration Zustand, letzter Erfolg, letzter
Fehler und ein Knopf, der einen Lauf sofort anstößt.
- Handbuchseite zu den Integrationen.
### Geändert
- Was aus einem Fund wird, entscheidet für alle Integrationen dieselbe
Stelle. Geführt werden nur Titel, Notiz, Verweis und Fälligkeit — Bereich,
Projekt, Priorität und geschätzter Aufwand gehören der Planung und werden
nie von außen überschrieben.
- Eine klemmende Integration meldet sich wie ein klemmender Kalender: erst
nach dem dritten Fehlversuch in Folge.
- Die Demo-Instanz für die Bilder spricht nicht mehr nach außen.
### Sicherheit
- Wer dem Telegram-Bot schreibt, ohne verbunden zu sein, bekommt **keine
Antwort** — auch keine Fehlermeldung. Sonst ließe sich herausfinden, dass
es diesen Planer gibt.
- Jede Sendung des Spiegels trägt eine Signatur über den Rumpf und ist nach
fünf Minuten wertlos. Der Empfänger antwortet auf jeden Fehlschlag gleich:
falsches Geheimnis, verstellte Uhr und Unsinn im Inhalt sind von außen
nicht zu unterscheiden.
- Der Signaturvergleich läuft in gleichbleibender Zeit.
- Aufgaben verlassen die Instanz nur mit ausdrücklicher Freigabe je Aufgabe.
Ein Schalter für einen ganzen Bereich würde zu leicht Kundennamen nach
Hause schicken.
## [0.5.0] – 2026-09-11
### Hinzugefügt
- **Benachrichtigungen** per Web-Push und E-Mail, je Benutzer einstellbar.
Vier Anlässe: Tagesüberblick am Morgen, fällige Aufgaben, Vorlauf vor einem
Zeitblock und ein Kalender, der sich nicht abgleichen lässt.
- **Ruhezeit** von 20:00 bis 07:00 ab Werk, über Mitternacht hinweg; wahlweise
das ganze Wochenende. Der Tagesüberblick kommt trotzdem zu seiner Zeit — er
käme sonst nie, wenn jemand früh aufsteht.
- Anmeldung eines Browsers für Push, Liste der angemeldeten Geräte und ein
Knopf, der eine Probemeldung über alle eingeschalteten Wege schickt.
- Ein Lauf alle zehn Minuten prüft, ob etwas zu melden ist; die nächtliche
Aufräumrunde entfernt Nachweise, die älter als 30 Tage sind.
- Handbuchseite zu Benachrichtigungen.
### Geändert
- Der Kalenderabgleich zählt Fehlversuche in Folge mit und meldet erst ab dem
dritten. Ein Netz hustet, ein Anbieter hat Wartung — das ist noch keine
Nachricht wert.
- Ab Werk meldet der Planer gar nichts: kein Weg ist eingeschaltet. Wer beim
ersten Start mit Meldungen überschüttet wird, schaltet alles ab — und dann
auch das Nützliche.
### Sicherheit
- Die Push-Schlüssel eines Geräts liegen verschlüsselt in der Datenbank.
Weder Endpunkt noch Schlüssel noch Mailinhalte landen im Protokoll.
- Ein Gerät, das der Push-Dienst mit 404 oder 410 ablehnt, wird sofort
entfernt; andere Fehler führen nach fünf Versuchen zum selben Ergebnis.
- Der Nachweis einer Meldung wird **vor** dem Senden geschrieben: lieber eine
verpasste Nachricht als eine, die im Minutentakt erneut versucht wird.
## [0.4.0] – 2026-09-11
### 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.