fetchCalendarEvents holte serverseitig immer nur currentWeekStart -7/+14 Tage, egal
wie breit die Ansicht (bis zu 31 Tage) tatsächlich war. Spalten jenseits von Tag 14
blieben leer, der "all day"-Zaehler zaehlte nur die geladenen Termine. timeMax
skaliert jetzt mit viewDays (max(14, viewDays + 7) Tage vorwaerts), 7-Tage-Standard
unveraendert.
v1.129.2
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
export-fields.ts importierte prisma auf Modulebene fuer fetchExportData, wurde aber
von der Client-Komponente SettingsSidebar wegen EXPORT_FIELDS mitgezogen -- Oeffnen
der Einstellungen warf "PrismaClient is unable to run in this browser environment".
fetchExportData liegt jetzt in export-data-server.ts, export-fields.ts bleibt frei
von Server-only-Importen.
v1.129.1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Aufgaben, die in der Vergangenheit geplant und nicht erledigt wurden, waren bislang
praktisch unsichtbar: nur Aufgaben mit aktiviertem Rolling-Schalter (oder bei global
aktiviertem Auto-Rolling) wandern automatisch auf heute (rollOverdueTasks in
WeeklyView.tsx) -- alles andere blieb fuer immer auf seinem urspruenglichen Datum
stehen, sobald man in der Wochenansicht weitergeklickt hat.
- src/lib/weekly/overdue.ts: reine Funktionen getOverdueTasks/groupOverdueByDate
(unerledigt, kein Someday, scheduledDate vor heute -- Datumsvergleich als String,
damit Uhrzeit/Zeitzone keine Rolle spielen). 10 Unit-Tests.
- src/components/OverdueTasksManager.tsx: Dialog, gruppiert nach dem urspruenglich
geplanten Tag (aelteste zuerst), Checkbox zum Erledigen, Knopf zum Verschieben auf
heute pro Aufgabe, "Alle auf heute verschieben". Nutzt LinkifiedText (v1.128.0) --
Titel mit URLs bleiben auch hier anklickbar. Verschieben/Erledigen laeuft ueber die
bestehenden moveTaskToSlot/toggleTask-Pfade, keine neue API.
- Neuer Menuepunkt "Ueberfaellig" mit Anzahl-Badge neben "Wiederkehrend" in allen
bestehenden Menue-Varianten (linke/obere Randleiste, mobile Leiste, Kopfzeile).
Verifiziert nicht nur mit Unit-Tests: lokale Instanz mit Wegwerf-Postgres (Docker)
aufgesetzt, drei ueberfaellige Aufgaben geseedet (eine mit URL im Titel), per Playwright
eingeloggt -- Badge, Gruppierung und Link-Rendering per Screenshot geprueft. Danach real
geklickt: eine Aufgabe per Checkbox erledigt, eine per Knopf auf heute verschoben, die
restlichen zwei per Sammelknopf -- alle drei Aenderungen per Datenbankabfrage bestaetigt.
Ausserdem: Typecheck, Lint (0 Fehler), 118 Unit-Tests (10 neu), Produktions-Build.
v1.129.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Eine im Titel getippte URL war bisher reiner Text innerhalb des klickbaren Bereichs
der Aufgabe -- ein Klick darauf hat je nach Ansicht die Aufgabe durchgestrichen
(Tagesraster, GridTaskBlock) oder den Bearbeiten-Modus geoeffnet (Kanban/Someday/
Liste/Prioritaet, weekly/TaskItem.tsx und PriorityView.tsx), statt den Link zu oeffnen.
- src/lib/weekly/format.ts: neue reine Funktion splitTextAndUrls zerlegt einen Titel
in Text- und URL-Abschnitte (http(s)://, www.-Adressen). Abschliessende Satzzeichen
(".", ",", ")", ...) bleiben Text, nicht Teil des Links.
- src/components/weekly/LinkifiedText.tsx: rendert diese Abschnitte, URL-Abschnitte als
echtes <a target="_blank" rel="noopener noreferrer"> mit stopPropagation, damit ein
Klick ausschliesslich den Link oeffnet und nicht an den umgebenden Klick-Handler
durchgereicht wird. Kein Titel ohne URL bekommt ein zusaetzliches Wrapper-Element.
- Eingebaut ueberall dort, wo ein Aufgabentitel bislang als reiner Text stand:
GridTaskBlock.tsx, weekly/TaskItem.tsx, PriorityView.tsx.
Keine Aenderung an Daten, API oder dem separaten task.url-Feld (der eigene "Termin-
Link"-Button in TaskItem.tsx) -- reine Darstellungsaenderung.
8 neue Unit-Tests fuer splitTextAndUrls (Titel ohne URL, nur URL, URL mit Text davor/
danach, www.-Form, Satzzeichen am Ende, Klammern, zwei URLs im selben Titel).
Verifiziert: Typecheck, Lint (0 Fehler), 108 Unit-Tests (8 neu), Produktions-Build.
v1.128.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
M3 aus TODO.md, nach v1.126.0 als gemeldete Luecke aufgenommen und jetzt geschlossen:
Aufgaben liessen sich bislang nur am Desktop per Maus verschieben, weil WeeklyView.tsx
ausschliesslich natives HTML5-Drag nutzte (draggable/onDragStart/onDrop), das auf
Touch-Geraeten grundsaetzlich nicht feuert.
Neuer Long-Press-Mechanismus, keine neue Dependency:
- GridTaskBlock bekommt onTouchStart/onTouchMove (handleTaskTouchStart/
handleTaskTouchMovePending) -- 200ms Halten ohne wesentliche Fingerbewegung
aktiviert den Drag (Vibration als Feedback, wie beim bestehenden Muster)
- Zwei-Phasen-Architektur identisch zum bereits vorhandenen Touch-Long-Press fuer
"Termin per Ziehen anlegen" (upgradeToDragListeners/handleTouchStart weiter oben in
derselben Datei): passiver Timer zum Aktivieren, danach ein document-weiter,
nicht-passiver touchmove-Listener nur waehrend des aktiven Drags (blockiert Scrollen
nur dann, nicht davor)
- handleDrop akzeptiert jetzt e: DragEvent | null -- der Touch-Pfad ruft dieselbe
Funktion direkt auf (kein natives DragEvent vorhanden), decideTaskDrop (v1.126.0)
unveraendert wiederverwendet, keine eigene Entscheidungslogik, keine geaenderte
API-Payload
Echt verifiziert, nicht nur angenommen: lokale Instanz mit Wegwerf-Postgres (Docker)
aufgesetzt, Testnutzer + Task geseedet, per Playwright ein echter Touch-Drag simuliert
(dispatchte TouchEvent-Objekte, 200ms Halten, schrittweise Bewegung, Loslassen) --
Task landete nachweislich per DB-Abfrage auf dem neuen Zeitslot. Derselbe Aufbau mit
dragTo() bestaetigt: der Desktop-Pfad (Maus) funktioniert unveraendert weiter.
Ausserdem: Typecheck, Lint (0 Fehler), 100 Unit-Tests, Produktions-Build -- alle gruen.
v1.127.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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>
L4 aus dem TODO-Block Sicherheitsdurchgang. Bewusst vorsichtig: die Policy laeuft
zunaechst nur als "Content-Security-Policy-Report-Only" und blockiert nichts, meldet
aber ueber den neuen Endpunkt POST /api/csp-report jeden Verstoss (console.error/PM2).
Whitelist aus dem tatsaechlichen Code abgeleitet, nicht geraten:
- fonts.googleapis.com/fonts.gstatic.com: FontPicker.tsx/WeeklyView.tsx laden
Nutzer-Schriftarten zur Laufzeit per <link> nach
- 'unsafe-inline' fuer script-src/style-src: Next.js' App-Router-Hydration und der
eine dangerouslySetInnerHTML-Block in WeeklyView.tsx (View-Transition-Styles)
brauchen das ohne Nonce-Infrastruktur (eigener, groesserer Umbau)
- Kein <iframe>, keine Drittanbieter-Bilder, keine clientseitigen fetch()-Aufrufe zu
fremden Domains gefunden. FontAwesome laeuft als React-Komponente im eigenen
Bundle. OAuth-Redirects sind Top-Level-Navigation, von CSP nicht betroffen.
src/middleware.ts: /api/csp-report von der Login-Pflicht ausgenommen -- der Browser
schickt Reports automatisch, auch von der nicht angemeldeten Login-Seite.
Scharf schalten (Report-Only aus dem Header-Namen entfernen) erst, nachdem ein paar
Tage Reports durchgesehen wurden -- die OAuth-Flows (Google/Microsoft/Apple/Notion)
liessen sich hier nicht interaktiv durchklicken.
Verifiziert: Typecheck, Lint, 85 Unit-Tests, Produktions-Build, Header und
Report-Endpunkt manuell im gebauten Standalone-Server geprueft.
v1.125.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>
Erste drei Punkte aus dem TODO-Block L (Sicherheitsdurchgang vom 12.09.):
- scripts/update-app.sh: kein automatischer "prisma db push --accept-data-loss"-
Fallback mehr, wenn "migrate deploy" fehlschlaegt. Das lief am 11.09. beim
Boot-Lauf tatsaechlich unbeaufsichtigt durch. Ein fehlgeschlagenes Migrate
bricht das Deployment jetzt sauber ab, exakt wie ein fehlgeschlagener Build.
- 14 API-Routen gaben error.message direkt an den Client zurueck (Kalender-
Connect/-Sync, Task-Import/-Sync, Someday-Listen, Datenimport). Neuer Helper
src/lib/api-error.ts (safeErrorMessage): generische Meldung in Produktion,
echte Meldung nur noch lokal. Logging unveraendert in console.error.
- src/lib/email.ts: tls.rejectUnauthorized: false entfernt -- stand seit dem
allerersten Commit unbegruendet drin, produktiver SMTP-Host (Kasserver) hat
ein gueltiges Zertifikat.
Verifiziert: Typecheck, Lint, 79 Unit-Tests, Produktions-Build alle gruen.
v1.123.2
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Letzter offener Punkt aus dem Sicherheitsdurchgang vor dem Beta-Test: npm audit
meldete 24 Schwachstellen, davon mehrere kritisch in next und next-auth.
- next 14.2.35 -> 15.5.24 (patcht alles, was next@16 sonst erfordert haette --
ein Major-Sprung statt zwei; next 15 unterstuetzt weiterhin React 18)
- next-auth 4.24.13 -> 4.24.15, @auth/core per overrides auf 0.41.3 erzwungen
(next-auth pinnt es sonst exakt auf die verwundbare 0.34.3, als ungenutzten
optionalen Peer)
- nodemailer 7 -> 10 per overrides (next-auth haelt einen ungenutzten optionalen
Peer auf 7.x)
- postcss auf 8.5.28, auch next's eigene interne Kopie per overrides
- ungenutztes @auth/prisma-adapter entfernt (Projekt nutzt @next-auth/prisma-adapter)
npm audit: 24 -> 0.
Zwei echte Codeaenderungen dafuer noetig:
- Next.js 15: { params } in Routen-Handlern ist jetzt ein Promise. Einzige
betroffene Route: cross-sync/rules/[id].
- nodemailer.Transporter gibt es seit @types/nodemailer 8 nicht mehr als
Namespace-Property, nur noch als benannter Type-Export. Einzige Stelle:
src/lib/email.ts.
Ausserdem google-auth-library als direkte Abhaengigkeit deklariert (vorher nur
ueber googleapis transitiv gehofft) und per overrides auf eine Version gepinnt --
der frische package-lock.json aus den obigen Fixes hob sie sonst nicht mehr
passend, wodurch zwei inkompatible Kopien nebeneinander existierten und der
Typecheck brach.
Verifiziert: Typecheck, Lint, 79 Unit-Tests, Produktions-Build alle gruen.
Login-Seite, Sicherheitsheader und Auth-Middleware manuell im gebauten
Standalone-Server geprueft. Kein Playwright-E2E-Lauf (braucht echte DB/OAuth).
v1.123.0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sicherheitsdurchgang vor dem geplanten Beta-Test mit Security-Scannern:
- Login (authorize() in src/lib/auth.ts) hatte als einziger Auth-Endpunkt kein
Rate-Limit, obwohl signup/reset-password/verify-email/resend-verification es
bereits nutzen. Jetzt max. 8 Versuche pro E-Mail in 15 Minuten.
- Fehlende Standardheader ergaenzt (X-Content-Type-Options, X-Frame-Options,
Referrer-Policy, Permissions-Policy), X-Powered-By abgeschaltet. Bewusst
ohne CSP -- braucht eine eigene, getestete Whitelist fuer OAuth/Fonts/CDN.
- npm audit fix (ohne --force): 24 -> 10 gemeldete Schwachstellen, keine
Breaking Changes. Die verbleibenden 10 haengen an next@14 und next-auth@4
(siehe CHANGELOG "Known issues") und brauchen ein eigenes Major-Upgrade.
Ausserdem zwei Betriebsfixes, die beim heutigen Deploy live auffielen:
- scripts/update-app.sh setzt jetzt selbst PATH=/usr/local/bin:$PATH. Ohne
Login-Shell fand es pm2 nicht und brach nach erfolgreichem Build beim
Neustart ab -- die Instanz blieb dabei auf dem alten Stand, kein Datenverlust,
aber ein unnoetiger manueller Eingriff.
- tsconfig.json nimmt .next-build/types/**/*.ts mit auf; Next.js traegt das
beim Bauen mit NEXT_DIST_DIR=.next-build sonst als nie eingecheckte
Abweichung auf dem Produktionshost ein.
v1.122.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>
Zwei Befunde aus dem Sicherheitsdurchgang zum CodeScene-Auftrag:
- /api/calendar/apple/sync war ohne Anmeldung erreichbar und hat beliebige
Apple-Zugangsdaten aus dem Request gegen Apple CalDAV geschickt. Damit liess
sich die Instanz als Relay zum Durchprobieren fremder Zugangsdaten nutzen.
Die Route verlangt jetzt dieselbe Session-Pruefung wie /connect.
- AuthForm.tsx hat E-Mail und Passwort im Klartext in die Browser-Konsole
geschrieben. Die Debug-Ausgaben sind entfernt.
Keine Aenderung an Payloads oder Antwortformaten.
v1.121.1
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>
TaskInput, SomedayAddTask, TaskItem (ueber 900 Zeilen), ListVisualsPopover
und TabVisualsPopover liegen jetzt unter src/components/weekly/. Dazu die
Prioritaets-Abzeichen: GridTaskBlock importierte getPriorityBadge aus
WeeklyView.tsx und zog sich damit die gesamte Wochenansicht in seinen
Abhaengigkeitsgraphen.
WeeklyView.tsx: 11.148 -> 9.711 Zeilen, erstmals unter 10.000. Gegenueber
dem Stand vor dem Audit (11.906) sind das 2.195 Zeilen oder 18 Prozent.
Der Typecheck hat den Schnitt in mehreren 19-Sekunden-Runden gefuehrt und
dabei zwei Dinge gefunden, die sonst erst im Browser aufgeschlagen waeren:
ein doppeltes export-Schluesselwort und -- feiner -- dass DragEvent in
WeeklyView aus React stammt, in den neuen Dateien ohne Import aber das
globale DOM-DragEvent gewesen waere.
Verifiziert: Typecheck 0 Fehler, npm run build Exit 0, 63 Unit-Tests gruen.
v1.119.2
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beim Vermessen der Struktur zeigte sich: In WeeklyView.tsx stecken acht
eigenstaendige Komponenten mit zusammen rund 1.870 Zeilen, die gar nichts
mit der Wochenansicht zu tun haben. Sie haben bereits eigene Props -- der
Schnitt braucht also kein Props-Design, nur die richtigen Importe.
Drei davon sind jetzt heraus, unter src/components/weekly/. Die Symbolliste
projectIconsGlobal ist zu ProjectIcon gewandert, wo sie als einzige
gebraucht wird.
11.556 -> 11.148 Zeilen.
Der scharfe Typecheck aus v1.118.1 hat sich hier zum ersten Mal richtig
ausgezahlt: Er nannte in 19 Sekunden praezise jeden fehlenden Import, in
mehreren schnellen Runden. Vor C1 haette der Build all das stumm
durchgewunken -- und die Fehler waeren erst im Browser aufgeschlagen.
Verifiziert: Typecheck 0 Fehler, npm run build Exit 0, 63 Unit-Tests gruen.
v1.119.1
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zwei UI-Wuensche aus der Wochenansicht (TODO.md Block I).
Der Spaltenkopf ist position: sticky und deckte mit --weekly-bg ab -- die
Hervorhebung des heutigen Tages begann daher erst unterhalb von Wochentag
und Datum. Jetzt faerbt sich der Kopf mit.
Die Symbole sitzen statt unten rechts oben rechts. Damit Titel und Uhrzeit
nicht darunter laufen, bekommen sie rechts Freiraum -- ueber
:has(.event-icons-row) nur dort, wo ueberhaupt Symbole erscheinen. Fuer
beide Darstellungen umgesetzt: Zeitraster und Liste.
Verifiziert: npm run build Exit 0. Das Ergebnis ist rein visuell und daher
nur im Browser wirklich pruefbar.
v1.119.0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Dateien schalteten die Typpruefung komplett ab und blieben deshalb auch
von ignoreBuildErrors: false unberuehrt -- eine Luecke im gerade erst
geschlossenen Netz.
- calendar-cache.ts brauchte die Ausnahme gar nicht: ohne sie null Fehler.
- microsoft-todo.ts hatte vier Faelle zirkulaerer Typinferenz
(url -> data -> response -> url), aufgeloest durch explizite Annotationen.
- outlook-calendar.ts verbarg einen moeglichen Laufzeitfehler: Der Code
streute response!-Assertions, eine Stelle war vergessen. Statt noch einer
Assertion prueft er jetzt echt, ob nach drei Wiederholversuchen ueberhaupt
eine Antwort vorliegt.
Ausserdem Block I in TODO.md: Hervorhebung des aktuellen Tages im
Spaltenkopf und die Symbole in Kalenderterminen nach oben rechts, beide mit
Fundstelle in globals.css.
Verifiziert: Typecheck 0 Fehler, npm run build Exit 0.
v1.118.2
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
typescript.ignoreBuildErrors steht jetzt auf false. Ein erfolgreicher Build
ist damit wieder ein Beleg dafuer, dass der Code uebersetzbar ist.
Die Ursache der 30-Minuten-Laufzeit war nicht die Groesse von WeeklyView.tsx,
wie ich vermutet hatte, sondern das include-Muster **/* in tsconfig.json. Auf
src/**/* eingegrenzt laeuft der volle Typecheck in 19 Sekunden.
Die sieben gefundenen Fehler:
- notion-calendar.ts rief notion.databases.query() auf. Die Methode gibt es
in @notionhq/client v5 nicht mehr -- die Notion-Anbindung war zur Laufzeit
schlicht kaputt und niemandem aufgefallen. Migriert auf dataSources.query(),
aber mangels Notion-Zugang ungetestet. Gespeicherte Verbindungen enthalten
alte database_ids und muessen neu eingerichtet werden.
- WeeklyView.tsx importierte isAllDayEvent noch aus format statt date-utils
-- mein eigener Fehler aus v1.118.0, der ohne scharfen Typecheck
durchgerutscht war.
- Export-Helfer lagen in einer route.ts, wo Next.js nur Route-Handler
erlaubt; SettingsSidebar importierte sie von dort und zog einen
Server-Handler in den Client-Graphen. Jetzt in src/lib/export-fields.ts.
- push-notifications.ts: BufferSource-Cast fuer applicationServerKey.
- web-push hat keine Typen; lokale Deklaration statt neuer Abhaengigkeit.
Verifiziert: npm run build Exit 0 mit scharfem Typecheck, 63 Unit-Tests gruen.
v1.118.1
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>
Dritter Schnitt an WeeklyView.tsx (D1):
- src/lib/weekly/device-settings.ts: Cookie-Helfer plus die vier
Schluessellisten, die bewusst nur im Cookie und nicht in der Datenbank
gehalten werden
- src/lib/weekly/format.ts: stripHtml, invertColor, isAllDayEvent,
getSomedaySlotCount
11.655 -> 11.556 Zeilen. Mit npm run build verifiziert (Exit 0).
Damit sind die reinen Funktionen ohne Komponenten-State heraus, insgesamt
11.906 -> 11.556 (rund 3 %). Der Rest ist die Komponente selbst: JSX und
Handler auf gemeinsamem State. Jeder weitere Schnitt braucht echtes
Props-Design statt Verschieben.
v1.117.7
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Zweiter Schnitt an WeeklyView.tsx (D1). 13 reine Funktionen ohne
Komponenten-State: getStartOfWeek, getDayName, getTimeSlots, formatHour,
getWeekNumber, formatCustomHeader und weitere.
11.830 -> 11.655 Zeilen. Mit npm run build verifiziert (Exit 0).
Nebenbefund: getWeekNumber existiert im Projekt dreimal -- hier, in
WeekPrintModal.tsx und in api/user/export-week-view/route.ts. Das Ersetzen
der Duplikate steht in TODO.md; vorher gehoeren die drei Implementierungen
auf Gleichheit geprueft.
v1.117.6
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Erster Schritt der Aufteilung von WeeklyView.tsx (D1). Die sieben gemeinsamen
Typen lagen in der Komponentendatei; SettingsSidebar und GridTaskBlock
importierten sie von dort und zogen sich damit die gesamte
11.900-Zeilen-Komponente in ihren Abhaengigkeitsgraphen.
WeeklyView.tsx re-exportiert die Typen weiterhin, bestehende Importe bleiben
also unveraendert -- kein Anfassen der beiden Importeure noetig.
11.906 -> 11.830 Zeilen. Mit npm run build verifiziert: Exit 0, 36 Seiten
generiert, /tasks unveraendert bei 265 kB.
v1.117.5
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
eslint.ignoreDuringBuilds stand auf true, der Build verschluckte also jede
Lint-Meldung. Im gesamten Projekt gab es genau zwei echte Errors -- beide
"let json" statt "const json" in SettingsSidebar.tsx. Behoben, Schalter aus,
next lint endet mit Exit 0.
Die 695 Warnungen (470 no-explicit-any, 209 ungenutzte Variablen, 11
unvollstaendige Hook-Abhaengigkeiten) blockieren den Build nicht. Die
Hook-Warnungen sind davon die interessantesten, weil daraus echte Bugs
entstehen -- stehen als eigener Punkt in TODO.md.
Naechster Schritt ist typescript.ignoreBuildErrors; der volle tsc-Lauf
dauert wegen WeeklyView.tsx ueber 15 Minuten und laeuft noch.
v1.117.4
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>
Event titles were coloured with color-mix(... 78%, black), which stayed so
close to the event's own colour that it barely separated from the tinted
background. Mixing 30% of the colour into a dark slate keeps the calendar
colour recognisable while making the text properly legible.
v1.116.4
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The drop preview and the empty-slot input were keyed by date.getDay(), which
is only unique inside a 7-day window. At 21 days every column sharing the
hovered column's weekday lit up — the mirrored drop targets, one per Tuesday.
The invisible half was worse: handleDrop resolved its target with
visibleDays.find(d => d.getDay() === dayOfWeek), so dropping on the second or
third Tuesday scheduled the task on the first one. Both now use the column's
own date; handleDragOver/handleDrop take a Date instead of a weekday number.
Task rendering was already date-based, so only drag state was affected.
v1.115.3
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add a "Custom" option next to the 1/2/3/5/7 presets where any number of
days from 1 to 31 can be typed. The seven duplicated preset button rows
are replaced by a shared DaysSelector component with panel/header/menu
variants.
The day grid and all-day grid only had CSS for cols-1/2/3/5/7, so any
other count silently fell back to five columns; both now derive
grid-template-columns from the actual day count.
v1.115.0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Focus Mode now shows a SKIP button that moves to the next task of the day
without completing the current one. Skipped task ids are tracked in
WeeklyView and filtered out of the focus queue, so completing a task still
picks the correct next one; the list is cleared when Focus Mode closes.
The timer resets on each new task, and the button is disabled when no other
task is left for today.
Also drops the standalone "Element Colors" and "Weekend Colors" sections from
Styling settings (those controls live in the CSS Variables panel since
1.113.1) and enlarges the CSS variable swatches.
v1.114.0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Today Highlight, Past Days, Saturday and Sunday now also appear as their
own groups in the CSS Variables panel, bound to the same profile fields
as the existing Element/Weekend Colors controls so both stay in sync.
Every row now shows the color swatch before its label.
v1.113.1
Adds a "CSS Variables" panel to the Styling tab with a color picker and
description for every color token in globals.css (base, sidebar, design
token aliases, event colors, all-day chips), plus a "Custom CSS" textarea
that loads after the default stylesheet and can override any rule.
Overrides are stored per-user (customCssVars, customCss) and applied on
the root container's inline style, so they take precedence over themes
and per-field settings.
v1.113.0
After dragging a calendar event to a new time or date, trigger
fetchCalendarEvents on both the old and new date context so the
move is reflected instantly without waiting for the next poll cycle.
Applies to both non-recurring and recurring drag confirms.
v1.112.2
- Calendar icon is now a standalone button to the left of the << < Today > >> cluster
- Uses its own ref (navDatePickerBtnRef) so SimpleDatePicker anchors and
opens directly below the icon instead of at the center date display
- Removed separator inside nav pill (no longer needed)
v1.112.1
- Location field shows dropdown suggestions from previously saved locations
as the user types; selected/submitted locations are persisted to
profile.viewSettings.savedLocations (max 20, most recent first)
- Reminder dropdown gains a "Custom…" option that opens an inline editor
for entering X minutes / hours / days before the event; confirmed custom
values are persisted to profile.viewSettings.customReminderMinutes
(max 10) and appear in future reminder dropdowns
v1.112.0
Changed alignItems from flex-start to center on outer div and span.
Removed manual top/left offsets on checkbox (no longer needed with
center alignment). Icon column uses justifyContent: center.
v1.111.4
- borderLeft now always 4px (transparent when no project/kanban color)
so all tasks have the same left padding (8px) and checkboxes align
- Rolling and provider icons moved from inline text flow to a right-
aligned sibling span in the outer flex row (always at line end)
- paddingRight: 30px when weatherEnabled to prevent temperature overlay
from overlapping task text
v1.111.3
Icon column (14px fixed width) is now always rendered when priority or
project icon settings are enabled, even when a task has no icons.
Each icon slot is a 12×12px centered container so icons are the same
size and horizontally aligned. Increased gap to 2px for breathing room.
v1.111.2
The project assign button and dropdown list now show the project's
actual icon (or faFolder as fallback) instead of a plain circle,
matching the icon rendering used in the task row stacked column.
v1.111.1
Priority icon (top) + project icon (bottom) now rendered in a fixed
leading column before the checkbox, matching the AnyDay area layout.
Provider/sync icon always inline at end (removed absolute fallback).
v1.111.0