Add spec compliance improvements: seed switch alert, calendar emojis, period indicator, IP logging
- NutritionPanel: Display seed switch alert on day 15 per dashboard spec - MonthView: Add phase emojis to legend (🩸🌱🌸🌙🌑) per calendar spec - DayCell: Show period indicator (🩸) for days 1-3 per calendar spec - Auth middleware: Log client IP from x-forwarded-for/x-real-ip per observability spec - Updated NutritionGuidance type to include seedSwitchAlert field - /api/today now returns seedSwitchAlert in nutrition response Test coverage: 1005 tests (15 new tests added) - nutrition-panel.test.tsx: +4 tests - month-view.test.tsx: +1 test - day-cell.test.tsx: +5 tests - auth-middleware.test.ts: +3 tests - today/route.test.ts: +2 tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ This file is maintained by Ralph. Run `./ralph-sandbox.sh plan 3` to generate ta
|
||||
|
||||
## Current State Summary
|
||||
|
||||
### Overall Status: 990 unit tests passing across 50 test files + 64 E2E tests across 6 files
|
||||
### Overall Status: 1005 unit tests passing across 50 test files + 64 E2E tests across 6 files
|
||||
|
||||
### Library Implementation
|
||||
| File | Status | Gap Analysis |
|
||||
@@ -17,7 +17,7 @@ This file is maintained by Ralph. Run `./ralph-sandbox.sh plan 3` to generate ta
|
||||
| `decision-engine.ts` | **COMPLETE** | 8 priority rules + override handling with `getDecisionWithOverrides()`, 24 tests |
|
||||
| `garmin.ts` | **COMPLETE** | 33 tests covering fetchGarminData, fetchHrvStatus, fetchBodyBattery, fetchIntensityMinutes, isTokenExpired, daysUntilExpiry, error handling, token validation |
|
||||
| `pocketbase.ts` | **COMPLETE** | 9 tests covering `createPocketBaseClient()`, `isAuthenticated()`, `getCurrentUser()`, `loadAuthFromCookies()` |
|
||||
| `auth-middleware.ts` | **COMPLETE** | 9 tests covering `withAuth()` wrapper for API route protection, structured logging for auth failures |
|
||||
| `auth-middleware.ts` | **COMPLETE** | 12 tests covering `withAuth()` wrapper for API route protection, structured logging for auth failures, IP address logging |
|
||||
| `middleware.ts` (Next.js) | **COMPLETE** | 12 tests covering page protection, redirects to login |
|
||||
| `logger.ts` | **COMPLETE** | 16 tests covering JSON output, log levels, error stack traces, child loggers |
|
||||
| `metrics.ts` | **COMPLETE** | 33 tests covering metrics collection, counters, gauges, histograms, Prometheus format |
|
||||
@@ -39,7 +39,7 @@ This file is maintained by Ralph. Run `./ralph-sandbox.sh plan 3` to generate ta
|
||||
| PATCH /api/user | **COMPLETE** | Updates cycleLength, notificationTime, timezone (17 tests) |
|
||||
| POST /api/cycle/period | **COMPLETE** | Logs period start, updates user, creates PeriodLog with prediction tracking (13 tests) |
|
||||
| GET /api/cycle/current | **COMPLETE** | Returns cycle day, phase, config, daysUntilNextPhase (10 tests) |
|
||||
| GET /api/today | **COMPLETE** | Returns decision, cycle, biometrics, nutrition (22 tests) |
|
||||
| GET /api/today | **COMPLETE** | Returns decision, cycle, biometrics, nutrition (24 tests) |
|
||||
| POST /api/overrides | **COMPLETE** | Adds override to user.activeOverrides (14 tests) |
|
||||
| DELETE /api/overrides | **COMPLETE** | Removes override from user.activeOverrides (14 tests) |
|
||||
| POST /api/garmin/tokens | **COMPLETE** | Stores encrypted Garmin OAuth tokens (15 tests) |
|
||||
@@ -88,14 +88,14 @@ This file is maintained by Ralph. Run `./ralph-sandbox.sh plan 3` to generate ta
|
||||
| `src/lib/cycle.test.ts` | **EXISTS** - 22 tests |
|
||||
| `src/lib/decision-engine.test.ts` | **EXISTS** - 24 tests (8 algorithmic rules + 16 override scenarios) |
|
||||
| `src/lib/pocketbase.test.ts` | **EXISTS** - 9 tests (auth helpers, cookie loading) |
|
||||
| `src/lib/auth-middleware.test.ts` | **EXISTS** - 9 tests (withAuth wrapper, error handling, structured logging) |
|
||||
| `src/lib/auth-middleware.test.ts` | **EXISTS** - 12 tests (withAuth wrapper, error handling, structured logging, IP address logging) |
|
||||
| `src/lib/logger.test.ts` | **EXISTS** - 16 tests (JSON format, log levels, error serialization, child loggers) |
|
||||
| `src/lib/metrics.test.ts` | **EXISTS** - 18 tests (metrics collection, counters, gauges, histograms, Prometheus format) |
|
||||
| `src/middleware.test.ts` | **EXISTS** - 12 tests (page protection, public routes, static assets) |
|
||||
| `src/app/api/user/route.test.ts` | **EXISTS** - 21 tests (GET/PATCH profile, auth, validation, security) |
|
||||
| `src/app/api/cycle/period/route.test.ts` | **EXISTS** - 13 tests (POST period, auth, validation, date checks, prediction tracking) |
|
||||
| `src/app/api/cycle/current/route.test.ts` | **EXISTS** - 10 tests (GET current cycle, auth, all phases, rollover, custom lengths) |
|
||||
| `src/app/api/today/route.test.ts` | **EXISTS** - 22 tests (daily snapshot, auth, decision, overrides, phases, nutrition, biometrics) |
|
||||
| `src/app/api/today/route.test.ts` | **EXISTS** - 24 tests (daily snapshot, auth, decision, overrides, phases, nutrition, biometrics, seed switch alert) |
|
||||
| `src/app/api/overrides/route.test.ts` | **EXISTS** - 14 tests (POST/DELETE overrides, auth, validation, type checks) |
|
||||
| `src/app/login/page.test.tsx` | **EXISTS** - 32 tests (form rendering, auth flow, error handling, validation, accessibility, rate limiting) |
|
||||
| `src/app/page.test.tsx` | **EXISTS** - 28 tests (data fetching, component rendering, override toggles, error handling) |
|
||||
@@ -117,18 +117,18 @@ This file is maintained by Ralph. Run `./ralph-sandbox.sh plan 3` to generate ta
|
||||
| `src/app/history/page.test.tsx` | **EXISTS** - 26 tests (rendering, data loading, pagination, date filtering, styling) |
|
||||
| `src/app/period-history/page.test.tsx` | **EXISTS** - 27 tests (rendering, edit/delete modals, pagination, prediction accuracy) |
|
||||
| `src/app/api/metrics/route.test.ts` | **EXISTS** - 15 tests (Prometheus format validation, metric types, route handling) |
|
||||
| `src/components/calendar/month-view.test.tsx` | **EXISTS** - 30 tests (calendar grid, phase colors, navigation, legend, keyboard navigation) |
|
||||
| `src/components/calendar/month-view.test.tsx` | **EXISTS** - 31 tests (calendar grid, phase colors, navigation, legend, keyboard navigation, emojis) |
|
||||
| `src/app/calendar/page.test.tsx` | **EXISTS** - 23 tests (rendering, navigation, ICS subscription, token regeneration) |
|
||||
| `src/app/settings/page.test.tsx` | **EXISTS** - 34 tests (form rendering, validation, submission, accessibility, logout functionality) |
|
||||
| `src/app/api/auth/logout/route.test.ts` | **EXISTS** - 5 tests (cookie clearing, success response, error handling) |
|
||||
| `src/app/settings/garmin/page.test.tsx` | **EXISTS** - 27 tests (connection status, token management) |
|
||||
| `src/components/dashboard/decision-card.test.tsx` | **EXISTS** - 19 tests (rendering, status icons, styling, color-coded backgrounds) |
|
||||
| `src/components/dashboard/data-panel.test.tsx` | **EXISTS** - 29 tests (biometrics display, null handling, styling, HRV status color-coding, intensity progress bar) |
|
||||
| `src/components/dashboard/nutrition-panel.test.tsx` | **EXISTS** - 12 tests (seeds, carbs, keto guidance) |
|
||||
| `src/components/dashboard/nutrition-panel.test.tsx` | **EXISTS** - 16 tests (seeds, carbs, keto guidance, seed switch alert) |
|
||||
| `src/components/dashboard/override-toggles.test.tsx` | **EXISTS** - 18 tests (toggle states, callbacks, styling) |
|
||||
| `src/components/dashboard/mini-calendar.test.tsx` | **EXISTS** - 23 tests (calendar grid, phase colors, navigation, legend) |
|
||||
| `src/components/dashboard/onboarding-banner.test.tsx` | **EXISTS** - 16 tests (setup prompts, icons, action buttons, interactions, dismissal) |
|
||||
| `src/components/calendar/day-cell.test.tsx` | **EXISTS** - 27 tests (phase coloring, today highlighting, click handling, accessibility) |
|
||||
| `src/components/calendar/day-cell.test.tsx` | **EXISTS** - 32 tests (phase coloring, today highlighting, click handling, accessibility, period indicator) |
|
||||
| `src/app/plan/page.test.tsx` | **EXISTS** - 16 tests (loading states, error handling, phase display, exercise reference, rebounding techniques) |
|
||||
| `src/app/layout.test.tsx` | **EXISTS** - 4 tests (skip navigation link rendering, accessibility, Toaster rendering) |
|
||||
| `src/components/ui/toaster.test.tsx` | **EXISTS** - 23 tests (toast rendering, types, auto-dismiss, error persistence, accessibility) |
|
||||
@@ -158,10 +158,10 @@ These must be completed first - nothing else works without them.
|
||||
### P0.2: Auth Middleware for API Routes ✅ COMPLETE
|
||||
- [x] Create reusable auth middleware for protected API endpoints
|
||||
- **Files:**
|
||||
- `src/lib/auth-middleware.ts` - Added `withAuth()` wrapper for route handlers
|
||||
- `src/lib/auth-middleware.ts` - Added `withAuth()` wrapper for route handlers with IP address logging
|
||||
- `src/middleware.ts` - Added Next.js middleware for page protection
|
||||
- **Tests:**
|
||||
- `src/lib/auth-middleware.test.ts` - 6 tests covering unauthorized rejection, user context passing, error handling
|
||||
- `src/lib/auth-middleware.test.ts` - 12 tests covering unauthorized rejection, user context passing, error handling, IP address logging
|
||||
- `src/middleware.test.ts` - 12 tests covering protected routes, public routes, API routes, static assets
|
||||
- **Why:** All API routes except `/api/calendar/[userId]/[token].ics` and `/api/cron/*` require auth
|
||||
- **Depends On:** P0.1
|
||||
@@ -239,11 +239,11 @@ Minimum viable product - app can be used for daily decisions.
|
||||
- **Files:**
|
||||
- `src/app/api/today/route.ts` - Implemented GET with `withAuth()` wrapper, aggregates cycle, biometrics, and nutrition
|
||||
- **Tests:**
|
||||
- `src/app/api/today/route.test.ts` - 22 tests covering auth, validation, decision calculation, overrides, phases, nutrition
|
||||
- `src/app/api/today/route.test.ts` - 24 tests covering auth, validation, decision calculation, overrides, phases, nutrition, seed switch alert
|
||||
- **Response Shape:**
|
||||
- `decision` (status, reason, icon), `cycleDay`, `phase`, `phaseConfig`, `daysUntilNextPhase`, `cycleLength`
|
||||
- `biometrics` (hrvStatus, bodyBatteryCurrent, bodyBatteryYesterdayLow, weekIntensityMinutes, phaseLimit)
|
||||
- `nutrition` (seeds, carbRange, ketoGuidance)
|
||||
- `nutrition` (seeds, carbRange, ketoGuidance, seedSwitchAlert)
|
||||
- **Fallback Behavior:** When no DailyLog exists (Garmin not synced), returns defaults: hrvStatus="Unknown", BB=100, weekIntensity=0
|
||||
- **Why:** This is THE core API for the dashboard
|
||||
- **Depends On:** P0.1, P0.2, P0.3, P1.3
|
||||
@@ -447,9 +447,9 @@ Full feature set for production use.
|
||||
- [x] In-app calendar with phase visualization
|
||||
- **Files:**
|
||||
- `src/app/calendar/page.tsx` - Month view with navigation, ICS subscription section with URL display, copy button, token regeneration
|
||||
- `src/components/calendar/month-view.tsx` - Complete calendar grid with DayCell integration, navigation controls, phase legend
|
||||
- `src/components/calendar/month-view.tsx` - Complete calendar grid with DayCell integration, navigation controls, phase legend with emojis
|
||||
- **Tests:**
|
||||
- `src/components/calendar/month-view.test.tsx` - 21 tests covering calendar grid, phase colors, navigation, legend
|
||||
- `src/components/calendar/month-view.test.tsx` - 31 tests covering calendar grid, phase colors, navigation, legend, emojis
|
||||
- `src/app/calendar/page.test.tsx` - 23 tests covering rendering, navigation, ICS subscription, token regeneration
|
||||
- **Why:** Planning ahead is a key user need
|
||||
- **Depends On:** P2.6
|
||||
@@ -646,7 +646,7 @@ Testing, error handling, and refinements.
|
||||
- [x] Replace console.error with structured pino logger
|
||||
- [x] Add logging for key events per observability spec
|
||||
- **Files:**
|
||||
- `src/lib/auth-middleware.ts` - Replaced console.error with structured logger, added auth failure logging
|
||||
- `src/lib/auth-middleware.ts` - Replaced console.error with structured logger, added auth failure logging with IP address
|
||||
- `src/app/api/cycle/period/route.ts` - Added "Period logged" event logging, structured error logging
|
||||
- `src/app/api/calendar/[userId]/[token].ics/route.ts` - Replaced console.error with structured logger
|
||||
- `src/app/api/overrides/route.ts` - Added "Override toggled" event logging
|
||||
@@ -654,9 +654,9 @@ Testing, error handling, and refinements.
|
||||
- `src/app/api/cron/garmin-sync/route.ts` - Added "Garmin sync start", "Garmin sync complete", "Garmin sync failure" logging
|
||||
- `src/app/api/auth/logout/route.ts` - Added "User logged out" logging
|
||||
- **Tests:**
|
||||
- `src/lib/auth-middleware.test.ts` - Added 3 tests for structured logging (9 total)
|
||||
- `src/lib/auth-middleware.test.ts` - Added 6 tests for structured logging and IP address logging (12 total)
|
||||
- **Events Logged (per observability spec):**
|
||||
- Auth failure (warn): reason
|
||||
- Auth failure (warn): reason, ip (from x-forwarded-for or x-real-ip headers)
|
||||
- Period logged (info): userId, date
|
||||
- Override toggled (info): userId, override, enabled
|
||||
- Decision calculated (info): userId, decision, reason
|
||||
@@ -713,16 +713,16 @@ Testing, error handling, and refinements.
|
||||
- **Components Tested (5 total):**
|
||||
- `src/components/dashboard/decision-card.tsx` - 19 tests for rendering decision status, icon, reason, styling, color-coded backgrounds
|
||||
- `src/components/dashboard/data-panel.tsx` - 18 tests for biometrics display (BB, HRV, intensity), null handling, styling
|
||||
- `src/components/dashboard/nutrition-panel.tsx` - 12 tests for seeds, carbs, keto guidance display
|
||||
- `src/components/dashboard/nutrition-panel.tsx` - 16 tests for seeds, carbs, keto guidance display, seed switch alert
|
||||
- `src/components/dashboard/override-toggles.tsx` - 18 tests for toggle states, callbacks, styling
|
||||
- `src/components/calendar/day-cell.tsx` - 23 tests for phase coloring, today highlighting, click handling
|
||||
- `src/components/calendar/day-cell.tsx` - 32 tests for phase coloring, today highlighting, click handling, period indicator
|
||||
- **Test Files Created:**
|
||||
- `src/components/dashboard/decision-card.test.tsx` - 19 tests
|
||||
- `src/components/dashboard/data-panel.test.tsx` - 18 tests
|
||||
- `src/components/dashboard/nutrition-panel.test.tsx` - 12 tests
|
||||
- `src/components/dashboard/nutrition-panel.test.tsx` - 16 tests
|
||||
- `src/components/dashboard/override-toggles.test.tsx` - 18 tests
|
||||
- `src/components/calendar/day-cell.test.tsx` - 23 tests
|
||||
- **Total Tests Added:** 90 tests across 5 files
|
||||
- `src/components/calendar/day-cell.test.tsx` - 32 tests
|
||||
- **Total Tests Added:** 103 tests across 5 files
|
||||
- **Why:** Component isolation ensures UI correctness and prevents regressions
|
||||
|
||||
---
|
||||
@@ -909,7 +909,7 @@ P4.* UX Polish ────────> After core functionality complete
|
||||
- [x] **ics.ts** - Complete with 33 tests (`generateIcsFeed`, ICS format validation, 90-day event generation, period prediction feedback, CATEGORIES for calendar colors) (P3.4, P4.5)
|
||||
- [x] **encryption.ts** - Complete with 14 tests (AES-256-GCM encrypt/decrypt, round-trip validation, error handling) (P3.5)
|
||||
- [x] **garmin.ts** - Complete with 33 tests (`fetchGarminData`, `fetchHrvStatus`, `fetchBodyBattery`, `fetchIntensityMinutes`, `isTokenExpired`, `daysUntilExpiry`, error handling) (P2.1, P3.6)
|
||||
- [x] **auth-middleware.ts** - Complete with 6 tests (`withAuth()` wrapper)
|
||||
- [x] **auth-middleware.ts** - Complete with 12 tests (`withAuth()` wrapper, structured logging, IP address logging)
|
||||
- [x] **middleware.ts** - Complete with 12 tests (Next.js page protection)
|
||||
- [x] **logger.ts** - Complete with 16 tests (JSON output, log levels, error serialization, child loggers) (P2.17)
|
||||
- [x] **metrics.ts** - Complete with 18 tests (metrics collection, counters, gauges, histograms, Prometheus format) (P2.16)
|
||||
@@ -920,7 +920,7 @@ P4.* UX Polish ────────> After core functionality complete
|
||||
- [x] **NutritionPanel** - Shows seeds, carbs, keto guidance
|
||||
- [x] **OverrideToggles** - Toggle buttons for flare/stress/sleep/pms
|
||||
- [x] **DayCell** - Phase-colored calendar day cell with click handler
|
||||
- [x] **MonthView** - Calendar grid with DayCell integration, navigation controls (prev/next month, Today button), phase legend, 21 tests
|
||||
- [x] **MonthView** - Calendar grid with DayCell integration, navigation controls (prev/next month, Today button), phase legend with emojis, 31 tests
|
||||
- [x] **MiniCalendar** - Compact calendar widget with phase colors, navigation, legend, 23 tests (P2.14)
|
||||
|
||||
### API Routes (21 complete)
|
||||
@@ -929,7 +929,7 @@ P4.* UX Polish ────────> After core functionality complete
|
||||
- [x] **PATCH /api/user** - Updates user profile (cycleLength, notificationTime, timezone), 17 tests (P1.1)
|
||||
- [x] **POST /api/cycle/period** - Logs period start date, updates user, creates PeriodLog with prediction tracking, 13 tests (P1.2, P4.5)
|
||||
- [x] **GET /api/cycle/current** - Returns cycle day, phase, phaseConfig, daysUntilNextPhase, cycleLength, 10 tests (P1.3)
|
||||
- [x] **GET /api/today** - Returns complete daily snapshot with decision, biometrics, nutrition, 22 tests (P1.4)
|
||||
- [x] **GET /api/today** - Returns complete daily snapshot with decision, biometrics, nutrition, 24 tests (P1.4)
|
||||
- [x] **POST /api/overrides** - Adds override to user.activeOverrides array, 14 tests (P1.5)
|
||||
- [x] **DELETE /api/overrides** - Removes override from user.activeOverrides array, 14 tests (P1.5)
|
||||
- [x] **POST /api/garmin/tokens** - Stores encrypted Garmin OAuth tokens, 15 tests (P2.2)
|
||||
@@ -966,10 +966,10 @@ P4.* UX Polish ────────> After core functionality complete
|
||||
- [x] **P3.4: ICS Tests** - Complete with 28 tests covering ICS format validation, 90-day event generation, timezone handling, period prediction feedback
|
||||
- [x] **P3.5: Encryption Tests** - Complete with 14 tests covering AES-256-GCM round-trip, error handling, key validation
|
||||
- [x] **P3.6: Garmin Tests** - Complete with 33 tests covering API interactions, token expiry, error handling
|
||||
- [x] **P3.7: Error Handling Improvements** - Replaced console.error with structured pino logger across API routes, added key event logging (Period logged, Override toggled, Decision calculated, Auth failure), 3 new tests in auth-middleware.test.ts
|
||||
- [x] **P3.7: Error Handling Improvements** - Replaced console.error with structured pino logger across API routes, added key event logging (Period logged, Override toggled, Decision calculated, Auth failure with IP address), 6 new tests in auth-middleware.test.ts
|
||||
- [x] **P3.8: Loading States** - Complete with skeleton components (DecisionCardSkeleton, DataPanelSkeleton, NutritionPanelSkeleton, MiniCalendarSkeleton, OverrideTogglesSkeleton, CycleInfoSkeleton, DashboardSkeleton), 29 tests in skeletons.test.tsx; loading.tsx files for all routes (dashboard, calendar, history, plan, settings); shimmer animations matching spec requirements
|
||||
- [x] **P3.9: Token Expiration Warnings** - Complete with 10 new tests in email.test.ts, 10 new tests in garmin-sync/route.test.ts; sends warnings at 14 and 7 days before expiry
|
||||
- [x] **P3.11: Missing Component Tests** - Complete with 90 tests across 5 component test files (DecisionCard: 19, DataPanel: 18, NutritionPanel: 12, OverrideToggles: 18, DayCell: 23)
|
||||
- [x] **P3.11: Missing Component Tests** - Complete with 98 tests across 5 component test files (DecisionCard: 19, DataPanel: 18, NutritionPanel: 16, OverrideToggles: 18, DayCell: 27)
|
||||
|
||||
### P4: UX Polish and Accessibility
|
||||
- [x] **P4.1: Dashboard Onboarding Banners** - Complete with OnboardingBanner component (16 tests), dashboard integration (5 new tests)
|
||||
@@ -1007,6 +1007,10 @@ Additional spec compliance improvements implemented:
|
||||
| Seed switch alert in email | notifications.md | **FIXED** | Daily email now includes seed switch alert on day 15 |
|
||||
| HRV status color-coding | dashboard.md | **FIXED** | Data panel now shows green/red/gray based on HRV status |
|
||||
| Intensity progress bar | dashboard.md | **FIXED** | Data panel now shows visual progress bar with color-coding |
|
||||
| Seed switch alert on day 15 | nutrition.md | **FIXED** | NutritionPanel now displays seedSwitchAlert from API |
|
||||
| Phase emojis in calendar legend | calendar.md | **FIXED** | MonthView now shows emojis per spec (🩸 Menstrual \| 🌱 Follicular \| 🌸 Ovulation \| 🌙 Early Luteal \| 🌑 Late Luteal) |
|
||||
| Period indicator in day cells | calendar.md | **FIXED** | DayCell now shows 🩸 for days 1-3 |
|
||||
| IP address in auth failure logs | observability.md | **FIXED** | Auth middleware now logs client IP from x-forwarded-for or x-real-ip headers |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user