Repository navigation
This release adds a wave of collaboration and reporting features — task comments with @mentions, task dependencies, a cross-project My Work view, time-tracking reports, and a subscribable iCal calendar feed — on top of a large security and stability hardening pass that resolves ~60 findings from a full-repo code review ahead of going public.
✨ New Features
💬 Task comments with @mentions (#5)
- Per-task discussion thread visible to all project members (viewers can read and post)
@mentionsvalidated as project members, each firing a new mention notification- Realtime via SSE comment events; offline-aware via
offlineFetch - Author or project owner can delete; mention matching is word-boundary/span-masked so a short name won't match inside a longer name or email
🔗 Task dependencies — "blocked by" (#6)
- A task can be blocked by other tasks in the same project and can't be completed while any blocker is open
- Cycle detection (3-colour DFS) on update; completion guard enforced across REST PATCH,
/complete, MCPcomplete_task/update_task, and bulk move-to-done - Blocked badge (open-blocker count) on the card + a cycle-aware "Blocked by" picker in the task sheet
- Deleting a task prunes its id from every other task's
blockedByon all delete paths — no phantom blockers
🗓 iCal (.ics) calendar feed (#9)
- Subscribe to your task due dates from Apple / Google / Outlook Calendar
- Public feed
GET /api/calendar/[token]/feed.icsauthenticated by a high-entropy (256-bit) secret URL token (Google "secret address" model) - Per-user revocable
calendarFeedToken; settings API to enable / regenerate / disable - Exposes only your own non-archived tasks with a due date; RFC-5545 builder with ICS-injection-safe escaping, UTC all-day dates, and 75-octet line folding
🧭 "My Work" cross-project view (#8)
- Open tasks assigned to you across all accessible projects, grouped by project or by due-date bucket (Overdue / Today / This week / Later / No date)
- Reuses the existing access-enforced tasks API (no backend change); deep-links to the task in its project
- Overdue conveyed via text (not color alone); dark-mode-safe
📊 Time-tracking reports (#7)
- Turns captured task time sessions into a summary: total, per-project bars, and a weekly trend over a trailing window of N ISO weeks
GET /api/stats/time-report: access-scoped aggregation counting only your own sessions; range selector (1–52 weeks, default 8)- No chart dependencies — CSS/inline bars with empty/error/loading states and a11y labels
🎯 Per-column WIP limits (#2)
- Optional per-column work-in-progress limit set in the column manager (empty = no limit)
- Header shows count / limit; over-limit columns get a destructive ring + badge and an aria-label
- Soft limit — drag is flagged, not blocked; count uses true column size so board filters can't mask an over-limit column
📅 Quick-select chips in the date picker (#4)
- Today / Tomorrow / Next week / Clear chips in the date picker popover for one-click due dates
- Chips resolve to a local calendar date reusing the same
yyyy-MM-ddformatting as the calendar — no timezone shift; purely additive
🔒 Security Fixes (#1)
- User enumeration:
users/searchreturns exact-email matches only — no directory enumeration - OAuth pre-hijack: refuse silent OAuth linking to an unverified credentials account
- Cross-user data deletion: scope backup-restore task/notification deletion to owned projects only (previously deleted tasks in shared projects the user only viewed)
- Secrets/config: fail-fast on missing
AUTH_SECRET; lock down mongo-express in the dev compose - Token lifetime: access tokens get a bounded expiry (default 90d, max 365d); JWTs voided after password change / account deletion; shorter session
maxAge - Rate limiting & password policy: in-memory rate limiting on register/login/password-change + a stronger password policy
- Error/CSP hardening: map duplicate-key to 409 and stop leaking internal error messages; 400 for malformed ObjectId params; drop
unsafe-evalfrom the production CSP - SSE: re-validate the session on heartbeat + a 1h max stream lifetime
- Account deletion: unset dangling assignee refs and notify affected members
🛠 Bug Fixes (#1)
Data integrity
- Replace a mis-declared sparse compound unique index with a partial index; move overdue dedup to a generation-based key and swallow
E11000on summary/digest - Reset the cached Mongoose connection promise on rejection;
syncIndexes()on worker boot so the dedup index actually replaces the old one on existing deployments - Add an
isRunningoverlap guard to the worker interval; restoreNotificationPreferenceon backup rollback
Recurrence & tasks
- Claim completion atomically (
findOneAndUpdateoncompletedAt:null) to stop duplicate recurring spawns; emit the spawned occurrence's created event to the originating tab - Validate
columnIdagainstproject.columnson REST create/update and per-project on bulk move; remap orphaned tasks on MCP column changes - Unify recurrence math on
date-utilsand anchor monthly recurrence (no drift); schedule a reminder for the spawned occurrence; two-pass DST correction incomputeReminderDate - Exclude archived tasks from stats counts; flag overdue only after the due day passes in the user's timezone
Offline & sync
- Offline PATCH echoes the real id and hooks merge it — no more blank/corrupted entities;
tempId → realIdreplay mapping and stable replay order with an idempotency key - Treat auth redirects as transient (keep the queue), skip caching
/api/events, clear page cache on logout, guardcache.puton redirects - SSE reconnect retries indefinitely and recovers on focus/visibility; guard against duplicate
EventSourceconnections; refetch notes/presets/members/archived on reconnect - Fix the stuck user-search spinner + out-of-order results; roll back
dismissAllon failure - Auth: fail open in the JWT session-revocation check so a transient DB error can't force-log-out every user
UI & accessibility
- Store due dates at UTC midnight from the card popover, bulk bar & calendar drag (timezone fix); clear
?taskId=after first open so a closed sheet stays closed - Don't overwrite an in-progress title/description edit on SSE update
- Confirm bulk delete and list-item delete; block deleting a column that still holds archived tasks
- Surface errors on subtask add, project settings, column save, calendar create, and bulk-create
- Dark-mode chips, keyboard-openable rows, aria-labels, truncation,
Cmd/Ctrl+K, calendar project selector, locale-correct labels - Share dialog falls back to email when a non-collaborator has no name to show
📓 Docs & Internal
- Added interaction coverage for the bulk-actions bar — assign/unassign, add-label, priority, move, and archive now assert the right callbacks fire (#3)
- Added a full-repo code review & bug-hunt report (4 critical / ~14 high / ~20 medium / ~20 low) with a phased remediation plan
- Cleaned up internal development artifacts and fixed docs conventions before going public