fix: resolve 13 findings from March 23 triage#29
Conversation
Install Vitest + happy-dom + v8 coverage and add 77 unit tests across 5 test files covering lib/streaks, lib/gamification, lib/activity, lib/accentColors, and lib/streaks-advanced. Includes reusable Supabase mock helper (tests/setup/supabase-mock.js) and npm scripts: test, test:watch, test:coverage. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two-step pact creation flow: template picker grid with 8 preset templates, then customizable form. Templates pre-fill title, description, recurrence, and suggested deadline time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace unlimited weekly free freezes with pool-based system: - Users start with 2 freezes, earn more at streak milestones (7/14/30d) - Max pool: 5 freezes, 3-day cooldown between uses - UI shows freeze count badge, cooldown timer, tier-based streak icons - SQL migration adds streak_freezes_remaining + streak_freeze_last_used Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5-agent parallel review (security, performance, architecture, testing, accessibility) identified 26 issues. All 26 now resolved: Accessibility (critical): dialog ARIA semantics, focus trap, Escape key Accessibility (high): aria-labels, role="alert", aria-pressed states Accessibility (medium/low): focus-visible outlines, reduced-motion CSS, decorative SVG aria-hidden, recurrence button states Security: maxLength on inputs, generic error messages (no DB leak) Architecture: extracted resetFormState(), useModalScrollLock hook (shared across 5 modals), removed dead code (recurrenceLabel fn, unused CSS) Performance: memoized filteredTemplates/today, fixed AnimatePresence exit animations, replaced transition:all with specific properties Testing: 25 new unit tests for pactTemplates.js data integrity Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: lib/pactTemplates.js (20 templates, 5 categories) was not included in the previous commit, causing CI test failures and empty template grid on GitHub-deployed version. Additional fixes from Claude's PR review: - Error icon SVG now has aria-hidden in CreatePactModal - resetFormState wrapped in useCallback for exhaustive-deps compliance - useStreakFreeze returns generic error message (no DB detail leak) - FREEZE_COOLDOWN_DAYS constant imported in DailySummaryCard (was hardcoded) - Exported FREEZE_COOLDOWN_DAYS from streaks-advanced.js Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-tests # Conflicts: # components/DailySummaryCard.js
- PactCard: add isCompletingRef guard to handleMiss (prevents double-submit) - CreatePactModal: add Monthly recurrence button + hint text - pactTemplates.test.js: add 'monthly' to valid recurrence types - streaks-advanced: export useStreakFreeze alias for applyStreakFreeze - DB: cleaned 15 abandoned focus sessions, reset stale streak, updated CHECK constraint to allow 'monthly' recurrence Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Overlay now blurs dashboard behind modal (backdrop-filter: blur(8px)) - Guard createPortal with typeof document check to prevent SSR crash Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6-agent parallel execution addressing frontend audit (6.3→target 8+) and morning report bugs. DESIGN REFRESH: - Kill gradient monoculture: solid accent on 19 non-CTA elements, gradient reserved for primary buttons + hero only - Replace glass with solid backgrounds on 19 content card selectors, glass kept on sidebar/nav/modals only - Tighten spacing: card padding 20px→16px, vary border-radius by context (cards 14px, inputs 10px, modals 22px, pills full) NEW FEATURES: - Skeleton loading states: new Skeleton component with shimmer animation, replaces spinners on 4 dashboard pages - Groups page redesign: member avatar stacks, task progress bars, deterministic color icons, refined hover effects BUG FIXES: - FocusContext: proper async cleanup on unmount, localStorage try/catch for corrupted data - PactCard: isolated streak/XP chain (no cascade failures), 15s safety timeout on isCompletingRef - GroupDetailClient: N+1 query → single join (21 calls → 1) - DailySummaryCard: 4 sequential queries → Promise.all (~300ms saved) - ActivityItem: wrapped in React.memo (prevents O(n) re-renders) 35 files changed, ~880 insertions, ~400 deletions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8-agent parallel execution addressing all remaining frontend audit findings. GRADIENT: 4-stop rainbow → subtle 2-stop indigo (#4338CA → #5B5EF5) on all gradient vars including celebration and subtle variants. DARK MODE: Warmer backgrounds (#08090D → #0C0C0E, #0E1117 → #111113) shifting from cold blue to warm neutral. TEXTURE: Added SVG noise overlay at 3% opacity on body::after for organic depth (Linear/Craft.do pattern). LANDING PAGE: Removed template icon boxes (52px → 32px inline), simplified step circles, reduced hero padding, added browser mockup product showcase section with perspective tilt. EMPTY STATES: Personality copy — "Suspiciously empty" for pacts, "No stats yet" for stats, contextual filter-aware messages. PACTCARD: Deadline urgency colors (green >24h, yellow <24h, red <12h, pulsing <6h). Refined hover (border-color shift, no translateY). DASHBOARD: Stat cards with colored left borders by type (streak=indigo, pacts=green, focus=blue, XP=amber). Animated count-up numbers with ease-out cubic via requestAnimationFrame. Shadow-only hover. SOUND: New lib/sounds.js — Web Audio API generated sounds for completion pop, timer chime, streak milestone, miss tone. Toggleable via localStorage. No external audio files needed. FRAMER MOTION: Replaced whileHover spring with CSS transitions on mundane elements (Sidebar nav items, logo, buttons; Navbar CTA; FocusTimer buttons). Kept Framer for layoutId, entrance animations, AnimatePresence, and whileTap. Tuned navPillSpring to smoother values. ACTIVITY FEED: Added missing activity type icons (streak, freeze, challenge). Restructured layout with inline timestamps, stronger actor/action hierarchy, hover backgrounds, and neutral timeline line. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PactCard: playCompletionSound() on complete, playMissSound() on miss - FocusTimer: replaced inline sound with richer playTimerChime() from lib/sounds.js (3-note C-E-G chime) - Removed old inline audio code from FocusContext (duplicated by sounds.js) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… cleanup, urgency colors, stat cards, empty states, Cmd+K palette Addresses remaining items from the March 21 Frontend Audit (6.3→8+ target): DESIGN: - Warmer dark mode: shift all blue-tinted grays to warm neutral zinc - SVG noise texture on body::after at 3% opacity (Linear/Raycast style) - Landing page: remove floating cards, bold step numbers, asymmetric grid - Stat cards: streak card with flame glow, colored left borders on others - Empty states: personality copy + custom SVG illustrations on Pacts/Groups - PactCard: deadline urgency colors (green >24h, yellow 12-24h, red <12h, pulse <6h) FEATURES: - Command Palette (Cmd+K): search, keyboard nav, theme toggle, navigation - Timezone detection: auto-persist user IANA timezone for streak calculations - Konami code easter egg with confetti - Timezone-aware streak risk detection and freeze system FIXES: - Streak test dates: add Z suffix for proper UTC interpretation - Modal UI refreshes (CreateGroup, CreateTask, Onboarding) - DailySummaryCard enhancements 28 files changed, ~840 insertions, ~390 deletions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…imezone, parallel queries Addresses remaining items from the March 21 Morning Report: BUGS: - ActivityFeed: fix stale closure in loadMore by using refs for hasMore/isLoadingMore inside IntersectionObserver callback - StatsPageClient: pass user timezone to calculateStreak (was defaulting to UTC, mismatching local completions) SECURITY: - GroupDetailClient: UUID validation on route param — returns 404 for malformed IDs before any DB query - CreatePactModal: deadline capped at 1 year from today (max attr) - Cron routes: verified case-insensitive (Web Headers API) — no fix needed PERFORMANCE: - gamification.js: 6 sequential unlockAchievement calls → Promise.all() (~5-6x latency improvement on pact completion path) 104 tests pass, build clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CreatePactModal: fix template grid clipping — modal uses flex column with scrollable body sections, header stays pinned - CommandPalette: "Create New Pact" now opens modal directly via onCreatePact callback instead of navigating to /dashboard/pacts - DashboardLayout: wire CommandPalette → CreatePactModal with state Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CommandPalette: overlay changed from motion.div to plain div — Framer Motion's transform breaks backdrop-filter compositing. Added CSS fade-in animation instead. Blur now works correctly. - CreatePactModal: category pills changed from overflow-x scroll to flex-wrap so all 5 pills are visible without clipping Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removed AnimatePresence wrapper and backdrop-filter from overlay. Uses same approach as working modals: plain div, rgba(0,0,0,0.4) background, conditional render with early return. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The blur mechanism uses html[data-modal-open] #dashboard-layout
{ filter: blur(12px) } — all other modals trigger this via the
useModalScrollLock hook. Added the same hook to CommandPalette.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
P0 CRITICAL: - FocusContext: fix stale closure in timer interval (ref sync in render body + optional chaining guard) - FocusContext: fix race condition in session creation (null check on data.id before ref assignment) - Cron: batch N+1 queries — check-streak-risk 2N→2 queries, cleanup N→1 upsert P1 HIGH: - Auth callback: fix open redirect with URL origin validation (blocks //evil.com, javascript:, data: schemes) - DashboardClient: throttle mark_overdue_pacts to once per day - GroupDetailClient: remove duplicate userIds variable - FocusContext: clarify useFocusSafe contract (JSDoc) P2 MEDIUM: - email.js: complete HTML escaping (quot, apos, backtick, null guard) - next.config.mjs: lock image remote to specific Supabase project - activity.js: null guard on getBatchReactions return value DESIGN: - globals.css: restore styled thin scrollbars (a11y fix) - globals.css: neutral shadows/borders in light theme (remove AI tint) - Landing page: particle background → CSS mesh gradient - FocusTimer: document.title shows countdown during sessions 104 tests pass, build clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Restore ParticleBackground component (removed by mistake in mesh gradient change — user wants particles) - Fix scroll: remove min-height: 100dvh from .hero — was making hero fill entire viewport, hiding all content below the fold Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Restore 3 floating notification cards (Pact completed, 2 hours left, Alex joined) with staggered entrance + ambient bob animations - Increase hero padding-top to 128px (desktop) / 96px (mobile) to clear fixed navbar with breathing room Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The asymmetric first-card span 2 left Streaks & Stats alone on the last row with a gap. Reverted to equal 3-column grid. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ActivityFeed: replace useEffect+deps with callback ref pattern for IntersectionObserver — observer created once on mount, not recreated on every isLoading toggle - Toast: type-aware progress bar colors, error duration sync (6s), info type uses var(--info) instead of accent, 4px left borders Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MERGE: - Resolve 8 conflicts (CreatePactModal, DailySummaryCard, streaks-advanced, package-lock, 2 test files) — keep branch versions with all improvements REVIEW FIXES (from 7-agent parallel review): - DashboardClient: remove unused useCountUp (~48 wasted re-renders), fix user object in deps (use user?.id), remove dead handleSignOut, add timezone to calculateStreak - Deduplicate CreatePactModal: single instance in DashboardLayout, DashboardClient uses custom events to trigger it - Consolidate sound settings: merge two localStorage keys (lockin-sound-enabled + lockin_sounds) into one (lockin_sounds) - Heatmap bug: output loop now uses formatDateInTimezone (was formatLocalDate) - Timezone DB write: cached in localStorage, only writes when changed 104 tests pass, build clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses 3 bugs from Claude's GitHub PR review: - PactCard: monthly recurrence toast now shows "month" instead of falling through to "weekday" - SQL: add migration for monthly constraint on pacts table - mark_overdue_pacts: monthly pacts now advance by 1 month instead of falling through to 1 day Both SQL changes applied to production Supabase. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CommandPalette: move setState out of effects into event handlers (setActiveIndex in onChange, setQuery/reset in Cmd+K handler) - useCountUp: remove early-return setState, use safeTarget fallback - DailySummaryCard: rename useStreakFreeze → applyStreakFreeze import (was triggering react-hooks/rules-of-hooks) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Security: remove open redirect via x-forwarded-host in auth callback, add crypto.timingSafeEqual for all 4 cron routes via shared cronAuth.js. Performance: memoize FocusContext value (useMemo), batch N+1 notification inserts in streak-breaks cron, cap orphaned session duration correctly. Design: remove noise texture overlay, desaturate bg gradients + accent, vary gradient angles, tighten border-radius, soften dark borders, reduce button glow, neutralize background colors. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@claude review |
|
Claude finished @vayungodara's task in 2m 16s —— View job PR Review — fix: resolve 13 findings from March 23 triage
OverallSolid batch of targeted fixes. The security work is particularly clean. A few issues are worth addressing before merge — one functional bug, one undisclosed scope expansion, and some minor items. Security ✅
Performance ✅
Bug: Missing
|
| Area | Status | Notes |
|---|---|---|
| Security (open redirect + timing-safe cron) | ✅ Clean | Well-implemented |
| Performance (FocusContext memoization) | ✅ Clean | Minor ref-deps note, benign |
| Performance (batch notifications) | ✅ Clean | |
| Data integrity (orphaned session cap) | ✅ Clean | |
| Skeleton animation | Missing @keyframes shimmer |
|
| CommandPalette | ✅ Clean | Undisclosed in PR description; ⌘N badge may be misleading |
| Design tokens (globals.css) | ✅ Clean | |
| iOS scaffolding | ✅ Clean |
One functional fix needed: Add @keyframes shimmer to Skeleton.module.css. Everything else is green or advisory.
The skeleton pulse animation was silently failing because only shimmerSlide was defined. Also added reduced-motion override for the base element animations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ion type whitelist Activity log batch insert in streak-breaks cron now logs errors instead of silently swallowing them. DB create_notification function whitelist updated to include all 19 notification types from NOTIFICATION_TYPES. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@claude review |
|
Claude finished @vayungodara's task in 2m 8s —— View job PR Review — fix: resolve 13 findings from March 23 triage
OverallClean batch of targeted fixes. The previously identified Security ✅
One observation: the redirect uses Bug Fixed ✅
Performance ✅
|
| Area | Status | Notes |
|---|---|---|
| Security (open redirect + timing-safe cron) | ✅ Clean | |
| Performance (FocusContext memoization) | ✅ Clean | Ref-deps update pattern is fine |
| Performance (batch notifications) | ✅ Clean | |
| Data integrity (orphaned session cap) | ✅ Clean | |
Skeleton @keyframes shimmer |
✅ Fixed | Was bug in previous review |
| CommandPalette | ✅ Clean | Confirm ⌘N global shortcut exists |
send-reminders reminder_logs |
✅ OK | In-loop is correct here (email-gated) |
lib/sounds.js |
✅ Clean | |
| iOS scaffolding | ✅ Clean |
No blocking issues. PR is ready to merge once you've verified the auth callback flow and visual checks pass.
|
Replacing with a clean branch from main (no inherited commits). See new PR. |
Summary
Cross-references findings from 3 email sources:
Resolves 13 of 15 open findings from PR #28 triage. Remaining: DST streak edge case (needs integration tests), Kanban drag-and-drop (feature addition).
Changes
auth/callback/route.js//guardlib/cronAuth.js+ 4 cron routescrypto.timingSafeEqualvia shared utilitylib/FocusContext.jsuseMemoon context value,useCallbackon formatTimecron/check-streak-breaks/route.js.insert()instead of N callscron/cleanup/route.jsMath.min(now, expectedEnd)for orphaned sessionsglobals.cssTest plan
npm run buildpasses clean🤖 Generated with Claude Code