Erster Schnitt aus TODO-CODESCENE-FORTSETZUNG-2026-09-12.md, nach Owner-Freigabe.
handleDrop (WeeklyView.tsx) vermischte fachliche Drop-Entscheidung (Zielslot bei
Belegung finden, Subtask-Befoerderung vs. Someday-Verschieben vs. normales
Verschieben) mit React-State-Updates und Netzwerkaufrufen. Die Entscheidung ist
jetzt eine reine Funktion decideTaskDrop in src/lib/weekly/drag-drop.ts:
- kennt weder DOM noch React noch Netzwerk, nur Task/Zieltag/Slot als Daten
- kein Import von date-utils.ts: der Aufrufer liefert dayOfWeek/scheduledDate/
allSlots fertig, damit die Datei nur einen Typ-Import hat (wie date-utils.ts/
format.ts/event-layout.ts in diesem Ordner) und ohne Next.js-Bundler in
node:test laeuft
- 15 Charakterisierungstests: freier/belegter/geschuetzter Slot, Drop ohne Slot
mit/ohne vorhandene Startzeit, Subtask-Befoerderung, Someday-Provider-
Vererbung (eigener vs. geerbter Provider), externe Sync-Bedingung, virtuelle
wiederkehrende Instanzen (Server materialisiert sie weiterhin unveraendert
ueber VIRTUAL_ID_REGEX in api/tasks/route.ts)
handleDrop selbst liest jetzt nur noch Eingaben, ruft decideTaskDrop auf und
fuehrt in einem switch exakt die bisherigen Seiteneffekte aus -- keine
geaenderten fetch-Aufrufe, kein geaendertes optimistisches UI-Update, keine
geaenderte API-Payload.
Wichtiger Nebenbefund, kein Teil dieses Refactorings: Task-Drag-and-Drop
funktioniert nur am Desktop. WeeklyView.tsx nutzt ausschliesslich natives
HTML5-Drag (draggable/onDragStart/onDrop), das auf Touch-Geraeten nicht
feuert. Kein separater Touch-Mechanismus vorhanden; react-dnd/
react-dnd-html5-backend sind installiert, aber nirgends importiert.
decideTaskDrop ist bewusst so geschnitten, dass ein kuenftiger
Touch-Mechanismus sie unveraendert wiederverwenden koennte -- das Bauen dieses
Mechanismus ist ein eigenes Feature-Vorhaben (siehe TODO.md Block M3).
Verifiziert: Typecheck, Lint (0 Fehler), 100 Unit-Tests (85 -> 100, 15 neu),
Produktions-Build -- alle gruen. Kein Playwright-E2E fuer Drag-and-Drop
(existiert im Repo bislang nicht).
v1.126.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
L1 aus dem TODO-Block Sicherheitsdurchgang: Apple-/Synology-Kalenderpasswoerter lagen
im Klartext in CalendarConnection.accessToken ("email:passwort"). Bei einem
Datenbank-Leak waeren das nicht nur App-Daten, sondern die echten Zugangsdaten der
Nutzer bei Apple bzw. auf ihrem NAS.
- src/lib/credential-crypto.ts: AES-256-GCM, Schluessel aus CREDENTIAL_ENCRYPTION_KEY.
enc1:-Praefix unterscheidet neu verschluesselte Werte von Alt-Klartext -- Klartext
bleibt beim Entschluesseln unveraendert lesbar statt zu brechen.
- src/lib/prisma.ts: Prisma-Client-Extension ver-/entschluesselt accessToken/refreshToken
transparent fuer alle rund ein Dutzend Aufrufstellen (Google/Outlook/Notion-Tokens
laufen mit, sind ebenso sensibel). Kein Aenderungsbedarf an den Aufrufstellen selbst.
- src/lib/auth.ts: PrismaAdapter braucht einen expliziten Typ-Cast fuer den erweiterten
Client (kein $on/$use mehr in dessen TS-Form, zur Laufzeit unveraendert).
Bestehende Zeilen brauchen keine Migration: Alt-Klartext bleibt lesbar und wird beim
naechsten Schreiben (Token-Refresh, Neuverbinden) automatisch verschluesselt.
ACHTUNG -- NICHT DEPLOYEN, bevor CREDENTIAL_ENCRYPTION_KEY in der Produktions-.env
steht: ohne den Schluessel wirft jeder Kalender-Request eine Exception. Konnte nicht
selbst gesetzt werden (Remote-Schreibzugriff per SSH von der Sandbox verweigert).
Verifiziert: Typecheck, Lint, 85 Unit-Tests (6 neu), Produktions-Build -- alle gruen,
mit einem Test-Schluessel gebaut.
v1.124.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Erster kleiner Schnitt aus Phase A des CodeScene-Auftrags: die Ueberlappungs-
Berechnung war ein rein funktionaler, aber verschachtelter Block mitten in der
Komponente. Sie liegt jetzt als layoutDaySegments/computeEventOverlapLayout in
src/lib/weekly/event-layout.ts und ist mit node:test abgedeckt (einzelner
Termin, Ueberschneidung, direkte Abfolge, drei gleichzeitige Termine,
Reihenfolgeunabhaengigkeit).
Kein sichtbares Verhalten geaendert; der Algorithmus ist unveraendert
uebernommen. WeeklyView.tsx: 9683 -> 9642 Zeilen.
v1.121.2
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ein Termin von 22:00 bis 02:00 wurde bisher als ein ueberlanger Block in den
Starttag gezeichnet und hat die Tagesspalte verlaengert. Jetzt wird er an der
Tagesgrenze geteilt: 22:00-24:00 am Starttag, 00:00-02:00 am Folgetag -- so,
wie es Kalender-Apps zeigen.
Die Regel liegt als reine Funktion splitEventByDay in src/lib/weekly/date-utils.ts
und ist mit node:test abgedeckt (Teilung, Mehrtagestermine, Ende exakt um
Mitternacht, Ganztagstermine, ungueltige Zeiten). Die Wochenansicht arbeitet in
Raster und Liste nur noch mit diesen Tagesabschnitten; Klick, Drag und Resize
greifen weiterhin auf den ungeteilten Termin zu, damit Payloads unveraendert
bleiben. Die Slot-Sperre (protectEventTimes) erfasst dadurch auch die
Nachtstunden des Folgetags.
v1.121.0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nodes eingebauter Test-Runner mit --experimental-strip-types: keine neue
Abhaengigkeit, keine Browser, keine Datenbank, Laufzeit rund 170 ms.
npm test fuehrt sie aus, npm run test:e2e startet weiterhin Playwright.
Die Tests haben sofort zwei echte Fehler gefunden, die ich beim Auslagern
in v1.117.7 selbst eingebaut hatte:
- isAllDayEvent rief parseCalendarDate ohne Import auf
- resolveViewDays nutzte clampViewDays ohne Import
Beides haette zur Laufzeit einen ReferenceError gegeben. Der Build meldete
nichts, weil typescript.ignoreBuildErrors noch aktiv ist -- genau der Fall,
gegen den C1 laeuft. isAllDayEvent liegt jetzt in date-utils.ts, wo es
thematisch hingehoert; clampViewDays und MAX_VIEW_DAYS in
device-settings.ts, DaysSelector re-exportiert sie.
Geprueft werden ISO-Kalenderwochen gegen bekannte Kalenderdaten, die
Wochenstart-Berechnung inklusive Sonntag-Sonderfall, das Zeitraster, die
12/24-Stunden-Anzeige und der Round-Trip formatDateToISO <-> parseCalendarDate
-- die Bruecke zwischen Datenbank und Anzeige, aus der Ein-Tag-Verschiebungen
entstehen.
Mit npm run build verifiziert (Exit 0).
v1.118.0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Das Audit hatte nur src/ nach Passwoertern durchsucht -- zu eng. Betroffen
sind vier getrackte Dateien, nicht eine:
- INFRASTRUCTURE_REQUIREMENTS.md fuehrt das DB-Passwort unverschleiert als
"**Password**: ..." auf, dazu SMTP und NEXTAUTH_SECRET
- deployment-notes.md enthaelt DATABASE_URL und NEXTAUTH_SECRET
- tests/debug/db-connection-test.spec.ts eine Connection-URL samt echter IP
- .env.production.save, der urspruengliche Fund
Die ersten beiden und .env.production.save sind aus dem Index genommen
(lokal bleiben sie), im Testskript ist das Passwort ersetzt. .gitignore
greift jetzt auf .env* statt auf feste Namen -- genau daran war
.env.production.save vorbeigerutscht.
Im Git liegen zwei verschiedene DB-Passwoerter: eines aus dem alten
Docker-Compose-Setup (@db:5432, vermutlich tot), eines aus dem
Supabase-Zugang. Ob letzteres noch aktiv ist, klaert der Pruefbefehl
in TODO.md Block F.
v1.117.2
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Erste Abarbeitung des Repository-Audits (siehe TODO.md).
Sicherheit:
- Rate-Limiting für alle vier Auth-Endpunkte. Sie waren unbegrenzt aufrufbar,
also beliebig viele Mails über den eigenen SMTP-Zugang und beliebig viele
Rateversuche auf Verifizierungscodes.
- Passwort-Reset-Token nur noch als SHA-256-Hash in der Datenbank. Bisher
Klartext: Lesezugriff auf die DB genuegte zur Kontouebernahme.
- Tote Mock-Login-Route entfernt. Sie verglich gegen ein hartcodiertes
Fake-Passwort und war ueber die Middleware-Ausnahme fuer /api/auth/*
ohne Anmeldung erreichbar.
- Passwort-Reset auf bcrypt-Kosten 12, wie beim Signup.
Reparaturen:
- npm test rief jest auf, obwohl es weder Jest-Config noch Jest-Tests gibt.
Zeigt jetzt auf Playwright; jest/ts-jest/@types/jest entfernt.
- Falscher sonar.projectKey im Workflow.
Verifiziert per tsc gegen die geaenderten Bereiche: keine neuen Typfehler.
v1.117.0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Add dark mode color adjustment helper for category colors
- Support multiple motivational quote source URLs
- Fix text wrapping for tasks/events to prevent horizontal overflow
- Improve someday list item layout for long text
- Add CLAUDE.md with semantic versioning and git workflow rules
- Update test/doc URLs and planning docs
v1.1.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Google Tasks integration and Apple Reminders support
- Add task import/export with list management APIs
- Add goal API for weekly goals
- Add German holidays library
- Add ImportListModal component
- Enhance WeeklyView with major UI improvements
- Enhance CalendarSettings with new connection options
- Add external task fields to database schema
- Add Playwright test suites for auth and tasks
- Add iCloud reminders Python scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>