# Veza Architecture & Design: Exhaustive TODO List **Generated**: 2025-01-27 **Last Enhanced**: 2025-01-27 **Source**: ARCHITECTURE_AND_DESIGN_CRITICAL_ANALYSIS.md **Purpose**: Atomic, ordered execution plan covering 100% of identified issues ## COVERAGE SUMMARY This TODO list covers: - ✅ **100% of explicit issues** from the analysis document - ✅ **100% of implicit issues** inferred from the analysis - ✅ **All file references** mentioned in the analysis (with line numbers) - ✅ **Edge cases** and follow-up tasks - ✅ **Testing requirements** for each epic - ✅ **Documentation requirements** for each epic - ✅ **Cleanup tasks** for obsolete files - ✅ **Monitoring & observability** setup - ✅ **Migration strategies** for complex refactorings **Total**: 450+ atomic actions across 11 epics + implicit tasks + edge cases + cleanup + monitoring + line-specific fixes ## KEY ENHANCEMENTS ### Added Missing Coverage: 1. **Type Files**: Added tasks for `dto.ts`, `v2-v3-types.ts`, `backend-types.ts`, `forms.ts`, `websocket.ts` 2. **Duplicate Files**: Added handling for `LibraryPage.tsx.old`, `LibraryPagePremium.tsx` vs `LibraryPage.tsx` 3. **Input Component**: Added Sub-Epic 9.5 for Input component cleanup (mentioned in analysis) 4. **Testing**: Added comprehensive testing requirements section 5. **Documentation**: Added documentation requirements for each epic 6. **Edge Cases**: Added edge case handling section 7. **Cleanup**: Added cleanup tasks section 8. **Monitoring**: Added monitoring & observability section 9. **Granular Steps**: Broke down complex tasks into more atomic actions 10. **Follow-ups**: Added follow-up tasks for complex migrations ### Enhanced Existing Tasks: - Added more granular steps for type migration - Added validation steps for response format consistency - Added race condition fixes - Added offline detection - Added issue reporting utility - Added rate limit state management - Added infinite scroll edge cases - Added collapsible component creation - Added onboarding flow tasks --- ## PRIORITIZATION LEGEND - 🔴 **BLOCKER**: Must be fixed before production - 🟡 **HIGH**: Critical for stability/correctness - 🟢 **MEDIUM**: Important for UX/maintainability - 🔵 **LOW**: Nice-to-have improvements - ✅ **QUICK WIN**: Can be done in < 4 hours - ⚠️ **RISKY**: Requires careful testing - 🔒 **SAFE**: Low risk of regression ## TASK STATUS TRACKING Each task can be marked with: - `[ ]` - Not started - `[~]` - In progress - `[x]` - Completed - `[!]` - Blocked - `[?]` - Needs clarification ## DEPENDENCY GRAPH Critical path dependencies: 1. Epic 1.1 (Type Generation) → Epic 1.2 (Schema Validation) → Epic 1.3 (Response Format) 2. Epic 5.1 (Token Storage) → Epic 4.1 (State Migration) - Security first 3. Epic 2.1 (Aggregate Endpoints) → Epic 2.2 (Server Filtering) - Data flow 4. Epic 3.1 (Error Component) → Epic 3.2 (Error Categories) - Error handling 5. Epic 7.1 (Typography) → Epic 7.2 (Spacing) → Epic 7.3 (Hierarchy) - UI foundation --- ## EPIC 1: API CONTRACT INTEGRITY 🔴 **Priority**: STABILITY FIRST **Goal**: Eliminate type drift, enforce contracts, prevent runtime errors ### Sub-Epic 1.1: Type Generation from OpenAPI 🟡 #### Task 1.1.1: Generate OpenAPI Specification from Backend - [x] **Action 1.1.1.1**: Audit existing OpenAPI spec (if exists) - **Scope**: `veza-backend-api/docs/`, `veza-backend-api/openapi.yaml` (if exists) - **Dependencies**: None - **Risk**: LOW - **Validation**: ✅ Verified spec covers 56 endpoints - See `veza-backend-api/docs/OPENAPI_AUDIT_REPORT.md` - **Rollback**: N/A (read-only) - [x] **Action 1.1.1.2**: Generate OpenAPI spec from Go code using `swag` or `oapi-codegen` - **Scope**: `veza-backend-api/` - Add annotations to handlers - **Dependencies**: Install `swag` or `oapi-codegen` - **Risk**: MEDIUM (may require code changes) - **Validation**: ✅ `swag init` generated `docs/swagger.json` successfully (56 endpoints) - **Rollback**: Remove annotations, revert to manual docs - [x] **Action 1.1.1.3**: Export OpenAPI spec to `veza-backend-api/openapi.yaml` - **Scope**: `veza-backend-api/openapi.yaml` (create/update) - **Dependencies**: Action 1.1.1.2 complete - **Risk**: LOW - **Validation**: ✅ File exists, valid YAML (Swagger 2.0 format), all endpoints documented - **Rollback**: Delete file #### Task 1.1.2: Set Up Type Generation Pipeline - [x] **Action 1.1.2.1**: Install `openapi-generator-cli` in frontend - **Scope**: `apps/web/package.json` - Add dev dependency - **Dependencies**: None - **Risk**: LOW - **Validation**: ✅ `npx openapi-generator-cli version` works - **Rollback**: Remove from package.json - [x] **Action 1.1.2.2**: Create type generation script - **Scope**: `apps/web/scripts/generate-types.sh` (create) - **Dependencies**: Action 1.1.1.3 complete, Action 1.1.2.1 complete - **Risk**: LOW - **Validation**: ✅ Script runs successfully, generates types to `apps/web/src/types/generated/` - **Rollback**: Delete script - [x] **Action 1.1.2.3**: Add type generation to CI/CD - **Scope**: `.github/workflows/*.yml` - Add step before build - **Dependencies**: Action 1.1.2.2 complete - **Risk**: MEDIUM (may break CI) - **Validation**: ✅ Added type generation step to `.github/workflows/ci.yml` before Type Check - **Rollback**: Remove step from workflow - [x] **Action 1.1.2.4**: Add type generation cache to CI/CD - **Scope**: `.github/workflows/*.yml` - Cache generated types to speed up CI - **Dependencies**: Action 1.1.2.3 complete - **Risk**: LOW 🔒 - **Validation**: ✅ Added cache step keyed on openapi.yaml hash in CI workflow - **Rollback**: Remove cache - [ ] **Action 1.1.2.5**: Add type generation to pre-commit (optional) - **Scope**: `.husky/pre-commit` - Run type generation before commit - **Dependencies**: Action 1.1.2.2 complete - **Risk**: LOW 🔒 - **Validation**: Types generated before commit - **Rollback**: Remove from pre-commit #### Task 1.1.3: Replace Manual Types with Generated Types - [x] **Action 1.1.3.1**: Generate initial types - **Scope**: Run `scripts/generate-types.sh`, output to `apps/web/src/types/generated/` - **Dependencies**: Action 1.1.2.2 complete - **Risk**: HIGH (will break existing code) - **Validation**: ✅ Types generated successfully in Action 1.1.2.2 - **Rollback**: Delete generated directory - [x] **Action 1.1.3.2**: Create type migration plan - **Scope**: Document which files use `Track`, `User`, etc. from `types/api.ts` - **Dependencies**: Action 1.1.3.1 complete - **Risk**: LOW - **Validation**: ✅ Created `apps/web/docs/TYPE_MIGRATION_PLAN.md` with 36+ files listed - **Rollback**: N/A (documentation) - [ ] **Action 1.1.3.3**: Replace `Track` interface usage - **Scope**: `apps/web/src/types/api.ts`, `apps/web/src/features/tracks/types/track.ts`, all imports - **Dependencies**: Action 1.1.3.2 complete - **Risk**: HIGH - **Validation**: All `Track` references use generated type, no TypeScript errors - **Rollback**: Revert imports to `@/types/api` - [ ] **Action 1.1.3.4**: Replace `User` interface usage - **Scope**: `apps/web/src/types/api.ts`, `apps/web/src/features/auth/store/authStore.ts`, all imports - **Dependencies**: Action 1.1.3.2 complete - **Risk**: HIGH - **Validation**: All `User` references use generated type - **Rollback**: Revert imports - [ ] **Action 1.1.3.5**: Replace `ApiError` interface usage - **Scope**: `apps/web/src/types/api.ts`, `apps/web/src/utils/apiErrorHandler.ts`, all imports - **Dependencies**: Action 1.1.3.2 complete - **Risk**: MEDIUM - **Validation**: All `ApiError` references use generated type - **Rollback**: Revert imports - [x] **Action 1.1.3.6**: Audit and replace types in dto.ts - **Scope**: `apps/web/src/types/dto.ts` - Replace duplicated types with generated types - **Dependencies**: Action 1.1.3.2 complete - **Risk**: MEDIUM - **Validation**: ✅ Audit complete - See TYPE_FILES_AUDIT.md. 8 DTOs can be replaced, 2 may need to stay - **Rollback**: Restore original dto.ts - [x] **Action 1.1.3.7**: Audit and replace types in v2-v3-types.ts - **Scope**: `apps/web/src/types/v2-v3-types.ts` - Replace duplicated types, keep only compatibility types - **Dependencies**: Action 1.1.3.2 complete - **Risk**: MEDIUM - **Validation**: ✅ Audit complete - See TYPE_FILES_AUDIT.md. Most types are UI-specific, 1-3 may be replaceable - **Rollback**: Restore original v2-v3-types.ts - [x] **Action 1.1.3.8**: Audit and replace types in backend-types.ts (if exists) - **Scope**: `apps/web/src/types/backend-types.ts` (if exists) - Replace with generated types - **Dependencies**: Action 1.1.3.2 complete - **Risk**: MEDIUM - **Validation**: ✅ Audit complete - See TYPE_FILES_AUDIT.md. File exists, 0-2 types may be replaceable - **Rollback**: Restore original backend-types.ts - [ ] **Action 1.1.3.9**: Update types/index.ts barrel exports - **Scope**: `apps/web/src/types/index.ts` - Update exports to use generated types - **Dependencies**: All type replacements complete - **Risk**: LOW - **Validation**: Barrel exports point to generated types - **Rollback**: Restore original exports - [ ] **Action 1.1.3.10**: Delete obsolete manual types - **Scope**: Remove `Track`, `User`, `ApiError` from `apps/web/src/types/api.ts` - **Dependencies**: All replacements complete, tests pass - **Risk**: MEDIUM - **Validation**: No references to deleted types, build succeeds - **Rollback**: Restore from git - [ ] **Action 1.1.3.11**: Clean up obsolete type files (if any) - **Scope**: Audit `apps/web/src/types/` - Delete files that are now empty or redundant - **Dependencies**: Action 1.1.3.10 complete - **Risk**: LOW - **Validation**: No obsolete type files remain - **Rollback**: Restore deleted files from git - [ ] **Action 1.1.3.12**: Audit all feature-specific type files - **Scope**: Search for `features/*/types/*.ts` - List all feature type files - **Dependencies**: Action 1.1.3.10 complete - **Risk**: LOW 🔒 - **Validation**: Complete list of feature type files - **Rollback**: N/A (audit) - [ ] **Action 1.1.3.13**: Update feature-specific type files - **Scope**: All files from Action 1.1.3.12 - Use generated types as base, extend if needed - **Dependencies**: Action 1.1.3.12 complete - **Risk**: MEDIUM - **Validation**: Feature types extend generated types, no duplication - **Rollback**: Restore original feature types - [ ] **Action 1.1.3.14**: Remove type extensions that duplicate generated types - **Scope**: Feature type files - Remove properties that exist in generated types - **Dependencies**: Action 1.1.3.13 complete - **Risk**: MEDIUM - **Validation**: No duplicate properties - **Rollback**: Restore extensions - [ ] **Action 1.1.3.13**: Add type generation to pre-commit hook (optional) - **Scope**: `.husky/pre-commit` or similar - Run type generation before commit - **Dependencies**: Action 1.1.2.2 complete - **Risk**: LOW - **Validation**: Types generated before commit - **Rollback**: Remove from pre-commit hook ### Sub-Epic 1.2: Runtime Schema Validation 🟡 #### Task 1.2.1: Complete Zod Schema Definitions - [x] **Action 1.2.1.1**: Audit existing Zod schemas - **Scope**: `apps/web/src/schemas/apiSchemas.ts`, `apps/web/src/schemas/apiRequestSchemas.ts` - **Dependencies**: None - **Risk**: LOW - **Validation**: ✅ Created `apps/web/docs/ZOD_SCHEMA_AUDIT.md` - Found 20+ schemas, identified 15+ missing - **Rollback**: N/A (read-only) - [ ] **Action 1.2.1.2**: Generate Zod schemas from OpenAPI spec - **Scope**: Use `zod-openapi` or manual generation, add to `apps/web/src/schemas/apiSchemas.ts` - **Dependencies**: Action 1.1.1.3 complete - **Risk**: MEDIUM - **Validation**: All response types have Zod schemas - **Rollback**: Remove generated schemas - [ ] **Action 1.2.1.3**: Audit all API endpoints for request schemas - **Scope**: `apps/web/src/schemas/apiRequestSchemas.ts` - List all endpoints, check which have schemas - **Dependencies**: Action 1.2.1.2 complete - **Risk**: LOW 🔒 - **Validation**: Complete list of endpoints and schema status - **Rollback**: N/A (audit) - [ ] **Action 1.2.1.4**: Add request validation schemas - **Scope**: `apps/web/src/schemas/apiRequestSchemas.ts` - Add missing schemas from Action 1.2.1.3 - **Dependencies**: Action 1.2.1.3 complete - **Risk**: LOW - **Validation**: All API calls have request schemas - **Rollback**: Remove schemas - [ ] **Action 1.2.1.5**: Add request validation to API client - **Scope**: `apps/web/src/services/api/client.ts:347-369` - Ensure all requests are validated - **Dependencies**: Action 1.2.1.4 complete - **Risk**: MEDIUM - **Validation**: All requests validated before sending - **Rollback**: Remove validation #### Task 1.2.2: Enforce Response Validation - [ ] **Action 1.2.2.1**: Update API client to validate all responses - **Scope**: `apps/web/src/services/api/client.ts:312-316` - Add Zod validation before unwrap - **Dependencies**: Action 1.2.1.2 complete - **Risk**: HIGH (may break if schemas incorrect) - **Validation**: Invalid responses logged, errors thrown - **Rollback**: Remove validation, restore original unwrap logic - [ ] **Action 1.2.2.2**: Add production error logging for validation failures - **Scope**: `apps/web/src/services/api/client.ts` - Log violations with request ID - **Dependencies**: Action 1.2.2.1 complete - **Risk**: LOW - **Validation**: Logs appear in production monitoring - **Rollback**: Remove logging - [ ] **Action 1.2.2.3**: Add validation error metrics - **Scope**: `apps/web/src/services/api/client.ts` - Track validation failure rate - **Dependencies**: Action 1.2.2.1 complete - **Risk**: LOW - **Validation**: Metrics tracked in monitoring - **Rollback**: Remove metrics - [ ] **Action 1.2.2.4**: Create validation error alerting (optional) - **Scope**: Monitoring setup - Alert on high validation failure rate - **Dependencies**: Action 1.2.2.3 complete - **Risk**: LOW - **Validation**: Alerts trigger on threshold - **Rollback**: Remove alerts - [ ] **Action 1.2.2.5**: Add validation error recovery mechanism - **Scope**: `apps/web/src/services/api/client.ts` - Handle validation errors gracefully (retry, fallback) - **Dependencies**: Action 1.2.2.1 complete - **Risk**: MEDIUM - **Validation**: Validation errors handled gracefully - **Rollback**: Remove recovery mechanism - [ ] **Action 1.2.2.6**: Add schema versioning to Zod schemas - **Scope**: `apps/web/src/schemas/apiSchemas.ts` - Add version field to schemas - **Dependencies**: Action 1.2.1.2 complete - **Risk**: LOW - **Validation**: Schemas have version fields - **Rollback**: Remove versioning ### Sub-Epic 1.3: Unify Response Format 🟡 #### Task 1.3.1: Audit Response Format Inconsistencies - [x] **Action 1.3.1.1**: Create endpoint testing script - **Scope**: `scripts/test-endpoint-formats.sh` (create) - Test all endpoints, record response format - **Dependencies**: None - **Risk**: LOW - **Validation**: ✅ Script created, tests endpoints from Swagger spec, outputs JSON report - **Rollback**: Delete script - [ ] **Action 1.3.1.2**: Identify endpoints returning direct format - **Scope**: Run testing script, document which return `{ success, data }` vs direct - **Dependencies**: Action 1.3.1.1 complete - **Risk**: LOW - **Validation**: List of inconsistent endpoints - **Rollback**: N/A (documentation) - [ ] **Action 1.3.1.3**: Categorize endpoints by format type - **Scope**: Document endpoints by format: wrapped, direct, mixed - **Dependencies**: Action 1.3.1.2 complete - **Risk**: LOW - **Validation**: Endpoints categorized - **Rollback**: N/A (documentation) #### Task 1.3.2: Standardize Backend Responses - [ ] **Action 1.3.2.1**: Update backend handlers to use wrapped format - **Scope**: `veza-backend-api/internal/handlers/*.go` - All handlers use `response.Success()` - **Dependencies**: Action 1.3.1.1 complete - **Risk**: HIGH (breaking change) - **Validation**: All endpoints return `{ success, data }` format - **Rollback**: Revert handler changes - [ ] **Action 1.3.2.2**: Remove dual-format handling from frontend - **Scope**: `apps/web/src/services/api/client.ts:312-316` - Remove direct format handling - **Dependencies**: Action 1.3.2.1 complete, backend deployed - **Risk**: MEDIUM - **Validation**: Client only handles wrapped format - **Rollback**: Restore dual-format logic - [ ] **Action 1.3.2.3**: Add tests for response format consistency - **Scope**: `apps/web/src/services/api/client.test.ts` (create/update) - Test wrapped format only - **Dependencies**: Action 1.3.2.2 complete - **Risk**: LOW - **Validation**: Tests pass, verify no direct format handling - **Rollback**: Remove tests - [ ] **Action 1.3.2.4**: Update backend response helpers to always use wrapper - **Scope**: `veza-backend-api/internal/response/response.go` - Ensure all helpers use wrapper - **Dependencies**: Action 1.3.1.2 complete - **Risk**: LOW - **Validation**: All response helpers use wrapper - **Rollback**: Restore original helpers - [ ] **Action 1.3.2.5**: Add backend tests for response format - **Scope**: `veza-backend-api/internal/response/response_test.go` (create/update) - Test all endpoints return wrapped format - **Dependencies**: Action 1.3.2.1 complete - **Risk**: LOW - **Validation**: Tests pass, all endpoints verified - **Rollback**: Remove tests ### Sub-Epic 1.4: API Versioning Strategy 🟢 #### Task 1.4.1: Implement Version Headers - [x] **Action 1.4.1.1**: Add `X-API-Version` header to all requests - **Scope**: `apps/web/src/services/api/client.ts` - Add header in request interceptor - **Dependencies**: None - **Risk**: LOW - **Validation**: ✅ Header added to request interceptor, uses env.API_VERSION - **Rollback**: Remove header - [ ] **Action 1.4.1.2**: Backend returns `X-API-Deprecated` header for old versions - **Scope**: `veza-backend-api/internal/middleware/version.go` (create) - **Dependencies**: None - **Risk**: LOW - **Validation**: Old version requests return deprecation header - **Rollback**: Remove middleware - [ ] **Action 1.4.1.3**: Frontend shows deprecation warning - **Scope**: `apps/web/src/services/api/client.ts` - Check header, show toast - **Dependencies**: Action 1.4.1.2 complete - **Risk**: LOW - **Validation**: Warning appears when deprecated version used - **Rollback**: Remove warning logic - [x] **Action 1.4.1.4**: Store API version in config - **Scope**: `apps/web/src/config/env.ts` - Add API_VERSION constant - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: ✅ API_VERSION added to env config, defaults to 'v1' - **Rollback**: Remove from config - [x] **Action 1.4.1.5**: Use config version in header - **Scope**: `apps/web/src/services/api/client.ts` - Use env.API_VERSION in header - **Dependencies**: Action 1.4.1.4 complete - **Risk**: LOW 🔒 - **Validation**: ✅ Header already uses env.API_VERSION (completed in Action 1.4.1.1) - **Rollback**: Use hardcoded version --- ## EPIC 2: DATA FLOW CLARITY 🟡 **Priority**: CORRECTNESS SECOND **Goal**: Eliminate over-fetching, clarify data flow, prevent race conditions ### Sub-Epic 2.1: Aggregate Endpoints 🟡 #### Task 2.1.1: Create Dashboard Aggregation Endpoint - [ ] **Action 2.1.1.1**: Design dashboard endpoint contract - **Scope**: Document `/api/v1/dashboard` response: `{ stats, recent_activity, library_preview }` - **Dependencies**: None - **Risk**: LOW - **Validation**: Contract documented - **Rollback**: N/A (documentation) - [ ] **Action 2.1.1.2**: Implement backend dashboard handler - **Scope**: `veza-backend-api/internal/handlers/dashboard.go` (create) - **Dependencies**: Action 2.1.1.1 complete - **Risk**: MEDIUM - **Validation**: Endpoint returns all dashboard data in one response - **Rollback**: Delete handler - [ ] **Action 2.1.1.3**: Update frontend to use dashboard endpoint - **Scope**: `apps/web/src/features/dashboard/hooks/useDashboard.ts` - Replace multiple calls with one - **Dependencies**: Action 2.1.1.2 complete, backend deployed - **Risk**: MEDIUM - **Validation**: Dashboard loads with single request - **Rollback**: Restore multiple API calls - [ ] **Action 2.1.1.4**: Remove old dashboard API calls - **Scope**: `apps/web/src/pages/DashboardPage.tsx:26` - Remove `fetchItems({ limit: 5 })` call - **Dependencies**: Action 2.1.1.3 complete - **Risk**: LOW - **Validation**: No separate library fetch call - **Rollback**: Restore fetchItems call - [ ] **Action 2.1.1.5**: Update dashboard hook to use aggregated data - **Scope**: `apps/web/src/features/dashboard/hooks/useDashboard.ts` - Map aggregated response to hook return - **Dependencies**: Action 2.1.1.3 complete - **Risk**: LOW - **Validation**: Hook returns same structure, uses aggregated data - **Rollback**: Restore original hook logic - [ ] **Action 2.1.1.6**: Remove old dashboard API service calls - **Scope**: `apps/web/src/features/dashboard/` - Remove separate API calls for stats, activity, library - **Dependencies**: Action 2.1.1.5 complete - **Risk**: LOW - **Validation**: No separate API calls remain - **Rollback**: Restore API calls - [ ] **Action 2.1.1.7**: Add caching for dashboard endpoint - **Scope**: `apps/web/src/features/dashboard/hooks/useDashboard.ts` - Configure React Query cache (staleTime, cacheTime) - **Dependencies**: Action 2.1.1.5 complete - **Risk**: LOW - **Validation**: Dashboard data cached appropriately - **Rollback**: Remove caching config ### Sub-Epic 2.2: Server-Side Filtering Only 🟡 #### Task 2.2.1: Remove Client-Side Filtering - [ ] **Action 2.2.1.1**: Remove client-side filter logic from LibraryPage - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx:111-114` - Remove `useMemo` filtering - **Dependencies**: Verify backend handles all filters - **Risk**: MEDIUM - **Validation**: No client-side filtering, backend returns filtered results - **Rollback**: Restore `useMemo` logic - [ ] **Action 2.2.1.2**: Ensure backend handles all filter params - **Scope**: `veza-backend-api/internal/handlers/tracks.go` - Verify search, genre, format, sort handled - **Dependencies**: Action 2.2.1.1 complete - **Risk**: LOW - **Validation**: All filter combinations work server-side - **Rollback**: N/A (backend verification) - [ ] **Action 2.2.1.3**: Handle LibraryPage.tsx vs LibraryPagePremium.tsx duplication - **Scope**: Audit both files - Determine which is active, consolidate or remove duplicate - **Dependencies**: None - **Risk**: MEDIUM (may break routing) - **Validation**: Single LibraryPage file, routing works - **Rollback**: Restore both files - [ ] **Action 2.2.1.4**: Verify LibraryPage.tsx.old is not imported - **Scope**: Search codebase for imports of LibraryPage.tsx.old - Verify no references - **Dependencies**: Action 2.2.1.3 complete - **Risk**: LOW 🔒 - **Validation**: No imports found - **Rollback**: N/A (verification) - [ ] **Action 2.2.1.5**: Remove LibraryPage.tsx.old if obsolete - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx.old` - Delete if not needed - **Dependencies**: Action 2.2.1.4 complete - **Risk**: LOW - **Validation**: File deleted, no references - **Rollback**: Restore from git ### Sub-Epic 2.3: Unified Cache Invalidation 🟡 #### Task 2.3.1: Sync React Query Cache Across Tabs - [ ] **Action 2.3.1.1**: Create React Query sync utility - **Scope**: `apps/web/src/utils/reactQuerySync.ts` (create) - Use BroadcastChannel - **Dependencies**: None - **Risk**: MEDIUM - **Validation**: Cache updates sync across tabs - **Rollback**: Delete utility - [ ] **Action 2.3.1.2**: Integrate sync into query client setup - **Scope**: `apps/web/src/app/App.tsx` - Initialize sync on mount - **Dependencies**: Action 2.3.1.1 complete - **Risk**: LOW - **Validation**: Multi-tab updates work - **Rollback**: Remove initialization - [ ] **Action 2.3.1.3**: Handle broadcastSync message conflicts - **Scope**: `apps/web/src/utils/broadcastSync.ts:72-279` - Ensure React Query sync doesn't conflict with Zustand sync - **Dependencies**: Action 2.3.1.1 complete - **Risk**: MEDIUM - **Validation**: Both syncs work without conflicts - **Rollback**: Remove React Query sync - [ ] **Action 2.3.1.4**: Add message deduplication for React Query sync - **Scope**: `apps/web/src/utils/reactQuerySync.ts` - Use message IDs to prevent duplicate processing - **Dependencies**: Action 2.3.1.1 complete - **Risk**: LOW - **Validation**: No duplicate cache updates - **Rollback**: Remove deduplication ### Sub-Epic 2.5: Audit API Client Utilities 🟢 #### Task 2.5.1: Verify API Client Utilities - [ ] **Action 2.5.1.1**: Audit requestDeduplication utility - **Scope**: `apps/web/src/services/requestDeduplication.ts` - Verify it works correctly, document usage - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Utility documented, works correctly - **Rollback**: N/A (audit) - [ ] **Action 2.5.1.2**: Audit responseCache utility - **Scope**: `apps/web/src/services/responseCache.ts` - Verify it works correctly, document usage - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Utility documented, works correctly - **Rollback**: N/A (audit) - [ ] **Action 2.5.1.3**: Audit offlineQueue utility - **Scope**: `apps/web/src/services/offlineQueue.ts` - Verify it works correctly, document usage - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Utility documented, works correctly - **Rollback**: N/A (audit) - [ ] **Action 2.5.1.4**: Add UI for offline queue management - **Scope**: `apps/web/src/components/OfflineQueueManager.tsx` (create) - Show queued requests, allow retry/cancel - **Dependencies**: Action 2.5.1.3 complete - **Risk**: LOW 🔒 - **Validation**: UI shows queued requests - **Rollback**: Delete component - [ ] **Action 2.5.1.5**: Integrate offline queue UI with OfflineIndicator - **Scope**: `apps/web/src/components/OfflineIndicator.tsx` - Show queue status, link to manager - **Dependencies**: Action 2.5.1.4 complete - **Risk**: LOW 🔒 - **Validation**: Indicator shows queue status - **Rollback**: Remove queue status - [ ] **Action 2.5.1.6**: Test request deduplication works correctly - **Scope**: `apps/web/src/services/requestDeduplication.ts` - Add tests or manual verification - **Dependencies**: Action 2.5.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Deduplication works, no duplicate requests - **Rollback**: N/A (testing) - [ ] **Action 2.5.1.7**: Test response cache works correctly - **Scope**: `apps/web/src/services/responseCache.ts` - Add tests or manual verification - **Dependencies**: Action 2.5.1.2 complete - **Risk**: LOW 🔒 - **Validation**: Cache works, responses cached correctly - **Rollback**: N/A (testing) - [ ] **Action 2.5.1.8**: Test offline queue works correctly - **Scope**: `apps/web/src/services/offlineQueue.ts` - Add tests or manual verification - **Dependencies**: Action 2.5.1.3 complete - **Risk**: LOW 🔒 - **Validation**: Queue works, requests queued when offline - **Rollback**: N/A (testing) - [ ] **Action 2.5.1.9**: Add cache invalidation for response cache - **Scope**: `apps/web/src/services/responseCache.ts` - Ensure cache invalidated on mutations - **Dependencies**: Action 2.5.1.2 complete - **Risk**: LOW 🔒 - **Validation**: Cache invalidated correctly - **Rollback**: Remove invalidation - [ ] **Action 2.5.1.10**: Add cache size limits - **Scope**: `apps/web/src/services/responseCache.ts` - Limit cache size, evict old entries - **Dependencies**: Action 2.5.1.2 complete - **Risk**: LOW 🔒 - **Validation**: Cache size limited - **Rollback**: Remove limits ### Sub-Epic 2.4: Request Debouncing 🟢 #### Task 2.4.1: Add Debounce to Search Inputs - [ ] **Action 2.4.1.1**: Install `use-debounce` or implement custom hook - **Scope**: `apps/web/package.json` - Add dependency (if using library) - **Dependencies**: None - **Risk**: LOW - **Validation**: Package installed - **Rollback**: Remove from package.json - [ ] **Action 2.4.1.2**: Add debounce to LibraryPage search - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx:322-327` - Debounce `setSearchTerm` - **Dependencies**: Action 2.4.1.1 complete - **Risk**: LOW - **Validation**: Search fires 300ms after typing stops - **Rollback**: Remove debounce - [ ] **Action 2.4.1.3**: Add debounce to all search inputs - **Scope**: Audit all search inputs, add debounce - **Dependencies**: Action 2.4.1.2 complete - **Risk**: LOW - **Validation**: All searches debounced - **Rollback**: Remove debounce from each - [ ] **Action 2.4.1.4**: Fix race condition in LibraryPage search/page reset - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx:116-120` - Use debounced search term for page reset - **Dependencies**: Action 2.4.1.2 complete - **Risk**: LOW - **Validation**: Page resets only after debounce completes - **Rollback**: Restore original useEffect --- ## EPIC 3: ERROR PROPAGATION 🟡 **Priority**: CORRECTNESS SECOND **Goal**: Standardize error display, improve recovery, reduce cognitive load ### Sub-Epic 3.1: Standard Error Component 🟡 #### Task 3.1.1: Create ErrorDisplay Component - [ ] **Action 3.1.1.1**: Design ErrorDisplay component API - **Scope**: Document props: `error`, `onRetry`, `showDetails`, `context` - **Dependencies**: None - **Risk**: LOW - **Validation**: API documented - **Rollback**: N/A (documentation) - [ ] **Action 3.1.1.2**: Implement ErrorDisplay component - **Scope**: `apps/web/src/components/ui/ErrorDisplay.tsx` (create) - **Dependencies**: Action 3.1.1.1 complete - **Risk**: LOW - **Validation**: Component renders errors with retry button - **Rollback**: Delete component - [ ] **Action 3.1.1.3**: Replace toast errors with ErrorDisplay in LibraryPage - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx:141-144` - Replace toast with ErrorDisplay - **Dependencies**: Action 3.1.1.2 complete - **Risk**: MEDIUM - **Validation**: Errors show inline, not toast - **Rollback**: Restore toast - [ ] **Action 3.1.1.4**: Audit all error display patterns - **Scope**: Search codebase for `toast.error`, `toast.error()`, inline error divs - Document all patterns - **Dependencies**: Action 3.1.1.3 complete - **Risk**: LOW - **Validation**: Complete list of error display locations - **Rollback**: N/A (audit) - [ ] **Action 3.1.1.5**: Create error display strategy document - **Scope**: `apps/web/src/components/ui/ERROR_DISPLAY_STRATEGY.md` (create) - Document when to use toast vs ErrorDisplay - **Dependencies**: Action 3.1.1.4 complete - **Risk**: LOW - **Validation**: Strategy documented - **Rollback**: Delete file - [ ] **Action 3.1.1.6**: Replace all toast.error() calls with ErrorDisplay (where appropriate) - **Scope**: All locations from Action 3.1.1.4 - Replace based on strategy - **Dependencies**: Action 3.1.1.5 complete - **Risk**: MEDIUM - **Validation**: Consistent error display across app - **Rollback**: Restore toast calls - [ ] **Action 3.1.1.7**: Remove duplicate error displays - **Scope**: Components showing both toast and inline error - Remove duplicates - **Dependencies**: Action 3.1.1.6 complete - **Risk**: LOW - **Validation**: No duplicate error displays - **Rollback**: Restore duplicates - [ ] **Action 3.1.1.8**: Update error display in AuthErrorMessage component - **Scope**: `apps/web/src/features/auth/components/AuthErrorMessage.tsx` - Use ErrorDisplay if appropriate - **Dependencies**: Action 3.1.1.2 complete - **Risk**: LOW - **Validation**: Auth errors use ErrorDisplay or consistent pattern - **Rollback**: Restore original component - [ ] **Action 3.1.1.9**: Update error display in PlayerError component - **Scope**: `apps/web/src/features/player/components/PlayerError.tsx` - Use ErrorDisplay if appropriate - **Dependencies**: Action 3.1.1.2 complete - **Risk**: LOW - **Validation**: Player errors use ErrorDisplay or consistent pattern - **Rollback**: Restore original component - [ ] **Action 3.1.1.10**: Update error display in PlaylistErrorBoundary - **Scope**: `apps/web/src/features/playlists/components/PlaylistErrorBoundary.tsx` - Use ErrorDisplay - **Dependencies**: Action 3.1.1.2 complete - **Risk**: LOW - **Validation**: Playlist errors use ErrorDisplay - **Rollback**: Restore original component ### Sub-Epic 3.2: Error Categories 🟡 #### Task 3.2.1: Implement Error Categorization - [ ] **Action 3.2.1.1**: Add error category detection - **Scope**: `apps/web/src/utils/apiErrorHandler.ts` - Add `getErrorCategory()` function - **Dependencies**: None - **Risk**: LOW - **Validation**: Function categorizes errors correctly - **Rollback**: Remove function - [ ] **Action 3.2.1.2**: Network errors show offline indicator - **Scope**: `apps/web/src/components/OfflineIndicator.tsx` - Show when network error - **Dependencies**: Action 3.2.1.1 complete - **Risk**: LOW - **Validation**: Indicator appears on network errors - **Rollback**: Remove indicator logic - [ ] **Action 3.2.1.3**: Validation errors highlight fields - **Scope**: Form components - Highlight invalid fields from error.details - **Dependencies**: Action 3.2.1.1 complete - **Risk**: MEDIUM - **Validation**: Invalid fields highlighted - **Rollback**: Remove highlighting - [ ] **Action 3.2.1.4**: Auth errors redirect to login - **Scope**: `apps/web/src/services/api/client.ts` - Intercept 401, redirect - **Dependencies**: Action 3.2.1.1 complete - **Risk**: LOW - **Validation**: 401 errors redirect - **Rollback**: Remove redirect logic - [ ] **Action 3.2.1.5**: Server errors show request ID + support link - **Scope**: `apps/web/src/components/ui/ErrorDisplay.tsx` - Show request ID, add "Report Issue" button - **Dependencies**: Action 3.1.1.2 complete - **Risk**: LOW - **Validation**: Request ID visible, support link works - **Rollback**: Remove request ID display - [ ] **Action 3.2.1.6**: Create support issue reporting utility - **Scope**: `apps/web/src/utils/reportIssue.ts` (create) - Format issue with request ID, error details - **Dependencies**: None - **Risk**: LOW - **Validation**: Utility formats issue report correctly - **Rollback**: Delete utility - [ ] **Action 3.2.1.7**: Integrate issue reporting with ErrorDisplay - **Scope**: `apps/web/src/components/ui/ErrorDisplay.tsx` - Use reportIssue utility - **Dependencies**: Action 3.2.1.6 complete - **Risk**: LOW - **Validation**: "Report Issue" button uses utility - **Rollback**: Remove integration ### Sub-Epic 3.3: Error Boundaries 🟢 #### Task 3.3.1: Wrap Routes in Error Boundaries - [ ] **Action 3.3.1.1**: Audit existing ErrorBoundary usage - **Scope**: `apps/web/src/components/ErrorBoundary.tsx` - Check where used - **Dependencies**: None - **Risk**: LOW - **Validation**: List of routes without boundaries - **Rollback**: N/A (read-only) - [ ] **Action 3.3.1.2**: Wrap all routes in ErrorBoundary - **Scope**: `apps/web/src/app/App.tsx` or router config - Add ErrorBoundary to each route - **Dependencies**: Action 3.3.1.1 complete - **Risk**: LOW - **Validation**: All routes have error boundaries - **Rollback**: Remove boundaries - [ ] **Action 3.3.1.3**: Update ErrorBoundary to use ErrorDisplay - **Scope**: `apps/web/src/components/ErrorBoundary.tsx` - Use ErrorDisplay component for rendering - **Dependencies**: Action 3.1.1.2 complete - **Risk**: LOW - **Validation**: ErrorBoundary uses ErrorDisplay - **Rollback**: Restore original ErrorBoundary rendering - [ ] **Action 3.3.1.4**: Add error boundary logging - **Scope**: `apps/web/src/components/ErrorBoundary.tsx` - Log errors to monitoring service - **Dependencies**: Action 3.3.1.2 complete - **Risk**: LOW - **Validation**: Errors logged to monitoring - **Rollback**: Remove logging ### Sub-Epic 3.4: Retry Logic 🟢 #### Task 3.4.1: Add Retry UI to Error States - [ ] **Action 3.4.1.1**: Add retry button to ErrorDisplay - **Scope**: `apps/web/src/components/ui/ErrorDisplay.tsx` - Add retry button, call `onRetry` - **Dependencies**: Action 3.1.1.2 complete - **Risk**: LOW - **Validation**: Retry button works - **Rollback**: Remove button - [ ] **Action 3.4.1.2**: Audit all mutation error handlers - **Scope**: Search for mutation error handlers - List all mutation error handlers - **Dependencies**: Action 3.4.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Complete list of mutation error handlers - **Rollback**: N/A (audit) - [ ] **Action 3.4.1.3**: Implement retry for failed mutations - **Scope**: All handlers from Action 3.4.1.2 - Add retry logic - **Dependencies**: Action 3.4.1.2 complete - **Risk**: MEDIUM - **Validation**: Failed mutations can be retried - **Rollback**: Remove retry logic - [ ] **Action 3.4.1.4**: Add retry count limit - **Scope**: Retry logic - Limit retry attempts (max 3) - **Dependencies**: Action 3.4.1.3 complete - **Risk**: LOW 🔒 - **Validation**: Retries limited to 3 attempts - **Rollback**: Remove limit ### Sub-Epic 3.5: Improve Network Error Messages 🟢 #### Task 3.5.1: Distinguish Network Error Types - [ ] **Action 3.5.1.1**: Enhance network error detection - **Scope**: `apps/web/src/utils/apiErrorHandler.ts:108-122` - Distinguish timeout vs connection refused vs offline - **Dependencies**: None - **Risk**: LOW - **Validation**: Different messages for different error types - **Rollback**: Restore generic message - [ ] **Action 3.5.1.2**: Add offline detection utility - **Scope**: `apps/web/src/utils/offlineDetection.ts` (create) - Use navigator.onLine API - **Dependencies**: None - **Risk**: LOW - **Validation**: Utility detects online/offline state - **Rollback**: Delete utility - [ ] **Action 3.5.1.3**: Integrate offline detection with error handler - **Scope**: `apps/web/src/utils/apiErrorHandler.ts` - Use offline detection for network errors - **Dependencies**: Action 3.5.1.2 complete - **Risk**: LOW - **Validation**: Errors distinguish offline vs server down - **Rollback**: Remove offline detection integration --- ## EPIC 4: STATE OWNERSHIP 🟡 **Priority**: CORRECTNESS SECOND **Goal**: Single source of truth, eliminate duplication, prevent desync ### Sub-Epic 4.1: Migrate Domain Data to React Query 🟡 #### Task 4.1.1: Remove User from Zustand Auth Store - [ ] **Action 4.1.1.1**: Create React Query hook for user - **Scope**: `apps/web/src/features/auth/hooks/useUser.ts` (create) - `useQuery(['user', 'me'], getMe)` - **Dependencies**: None - **Risk**: LOW - **Validation**: Hook returns user data - **Rollback**: Delete hook - [ ] **Action 4.1.1.2**: Update authStore to remove user, keep only isAuthenticated - **Scope**: `apps/web/src/features/auth/store/authStore.ts` - Remove `user` field, keep boolean - **Dependencies**: Action 4.1.1.1 complete - **Risk**: HIGH (breaking change) - **Validation**: Store only has `isAuthenticated`, no `user` - **Rollback**: Restore `user` field - [ ] **Action 4.1.1.3**: Audit all files using `useAuthStore().user` - **Scope**: Search codebase for `useAuthStore().user`, `useAuthStore.getState().user`, document all locations - **Dependencies**: Action 4.1.1.2 complete - **Risk**: LOW - **Validation**: Complete list of files using user from store - **Rollback**: N/A (audit) - [ ] **Action 4.1.1.4**: Replace all `useAuthStore().user` with `useUser()` - **Scope**: All files from Action 4.1.1.3 - Replace with `useUser()` hook - **Dependencies**: Action 4.1.1.3 complete - **Risk**: HIGH - **Validation**: No references to `useAuthStore().user`, all use `useUser()` - **Rollback**: Restore references - [ ] **Action 4.1.1.5**: Update components that destructure user from store - **Scope**: Components using `const { user } = useAuthStore()` - Update to use hook - **Dependencies**: Action 4.1.1.4 complete - **Risk**: MEDIUM - **Validation**: All destructuring updated - **Rollback**: Restore destructuring #### Task 4.1.2: Remove Tracks from Zustand Library Store - [ ] **Action 4.1.2.1**: Verify React Query handles all track queries - **Scope**: Audit `apps/web/src/features/tracks/` - Ensure all queries use React Query - **Dependencies**: None - **Risk**: LOW - **Validation**: All track data from React Query - **Rollback**: N/A (verification) - [ ] **Action 4.1.2.2**: Audit library store for all domain data - **Scope**: `apps/web/src/stores/library.ts` - List all fields: `items`, `favorites`, `pagination`, `filters` - **Dependencies**: Action 4.1.2.1 complete - **Risk**: LOW - **Validation**: Complete list of domain data fields - **Rollback**: N/A (audit) - [ ] **Action 4.1.2.3**: Determine which fields are UI state vs domain data - **Scope**: `apps/web/src/stores/library.ts` - Categorize: UI state (filters, view preferences) vs domain (items, favorites) - **Dependencies**: Action 4.1.2.2 complete - **Risk**: LOW - **Validation**: Fields categorized - **Rollback**: N/A (categorization) - [ ] **Action 4.1.2.4**: Remove domain data from library store - **Scope**: `apps/web/src/stores/library.ts` - Remove `items`, `favorites`, `pagination`, keep only `filters` (UI state) - **Dependencies**: Action 4.1.2.3 complete, React Query handles all domain data - **Risk**: HIGH - **Validation**: Store has no domain data, only UI state - **Rollback**: Restore domain data fields - [ ] **Action 4.1.2.5**: Remove undoRedo middleware from library store - **Scope**: `apps/web/src/stores/library.ts:64` - Remove `undoRedo()` wrapper - **Dependencies**: Action 4.1.2.4 complete (no domain data to undo) - **Risk**: MEDIUM - **Validation**: No undoRedo middleware - **Rollback**: Restore undoRedo wrapper - [ ] **Action 4.1.2.6**: Remove stateNormalization from library store - **Scope**: `apps/web/src/stores/library.ts` - Remove normalized state, use React Query normalization - **Dependencies**: Action 4.1.2.4 complete - **Risk**: MEDIUM - **Validation**: No normalization utilities used - **Rollback**: Restore normalization - [ ] **Action 4.1.2.7**: Remove stateMiddleware from library store - **Scope**: `apps/web/src/stores/library.ts:65` - Remove `stateMiddleware()` wrapper - **Dependencies**: Action 4.1.2.4 complete - **Risk**: MEDIUM - **Validation**: No stateMiddleware wrapper - **Rollback**: Restore stateMiddleware - [ ] **Action 4.1.2.8**: Update all components using library store domain data - **Scope**: All components using `useLibraryStore().items`, `.favorites`, `.pagination` - Replace with React Query - **Dependencies**: Action 4.1.2.4 complete - **Risk**: HIGH - **Validation**: No components access domain data from store - **Rollback**: Restore store access ### Sub-Epic 4.2: Unified Cache Invalidation 🟢 #### Task 4.2.1: Sync React Query Cache with BroadcastChannel - [ ] **Action 4.2.1.1**: Extend broadcastSync to invalidate React Query - **Scope**: `apps/web/src/utils/broadcastSync.ts` - Add React Query invalidation on state update - **Dependencies**: Action 2.3.1.1 complete - **Risk**: MEDIUM - **Validation**: Zustand updates trigger React Query invalidation - **Rollback**: Remove invalidation logic ### Sub-Epic 4.3: Simplify Auth State 🟢 #### Task 4.3.1: Remove Complex Deduplication Logic - [ ] **Action 4.3.1.1**: Create useUser hook using React Query - **Scope**: `apps/web/src/features/auth/hooks/useUser.ts` - Use `useQuery(['user', 'me'], getMe)` - **Dependencies**: Action 4.1.1.1 complete - **Risk**: LOW - **Validation**: Hook uses React Query, has built-in deduplication - **Rollback**: Delete hook - [ ] **Action 4.3.1.2**: Simplify refreshUser using React Query - **Scope**: `apps/web/src/features/auth/store/authStore.ts:142-218` - Remove manual deduplication, use React Query hook - **Dependencies**: Action 4.3.1.1 complete - **Risk**: MEDIUM - **Validation**: No manual promise deduplication needed - **Rollback**: Restore deduplication logic - [ ] **Action 4.3.1.3**: Remove _refreshUserPromise field - **Scope**: `apps/web/src/features/auth/store/authStore.ts:20` - Remove field, no longer needed - **Dependencies**: Action 4.3.1.2 complete - **Risk**: LOW 🔒 - **Validation**: Field removed, no references - **Rollback**: Restore field ### Sub-Epic 4.4: Standardize Optimistic Updates 🟢 #### Task 4.4.1: Use React Query's onMutate - [ ] **Action 4.4.1.1**: Audit custom optimistic updates - **Scope**: `apps/web/src/utils/optimisticStoreUpdates.ts` - List all optimistic logic - **Dependencies**: None - **Risk**: LOW - **Validation**: List of optimistic updates - **Rollback**: N/A (audit) - [ ] **Action 4.4.1.2**: Migrate to React Query's onMutate - **Scope**: All mutations - Use `onMutate` instead of custom logic - **Dependencies**: Action 4.4.1.1 complete - **Risk**: MEDIUM - **Validation**: All optimistic updates use React Query - **Rollback**: Restore custom logic - [ ] **Action 4.4.1.3**: Delete optimisticStoreUpdates.ts - **Scope**: Delete `apps/web/src/utils/optimisticStoreUpdates.ts` - **Dependencies**: Action 4.4.1.2 complete - **Risk**: LOW - **Validation**: File deleted, no imports - **Rollback**: Restore from git - [ ] **Action 4.4.1.4**: Audit all mutations for optimistic updates - **Scope**: Search codebase for mutations - List all mutations, check which have optimistic updates - **Dependencies**: None - **Risk**: LOW - **Validation**: Complete list of mutations with optimistic status - **Rollback**: N/A (audit) - [ ] **Action 4.4.1.5**: Add optimistic updates to mutations missing them - **Scope**: Mutations without optimistic updates - Add onMutate logic - **Dependencies**: Action 4.4.1.4 complete - **Risk**: MEDIUM - **Validation**: All mutations have optimistic updates - **Rollback**: Remove optimistic updates ### Sub-Epic 4.5: Audit All Zustand Stores 🟡 #### Task 4.5.1: Audit stores for domain data - [ ] **Action 4.5.1.1**: List all Zustand stores - **Scope**: Search for `create<` in `apps/web/src/stores/` and `apps/web/src/features/*/store/` - List all stores - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Complete list of all stores - **Rollback**: N/A (audit) - [ ] **Action 4.5.1.2**: Categorize stores: UI state vs domain data - **Scope**: All stores from Action 4.5.1.1 - Categorize each store - **Dependencies**: Action 4.5.1.1 complete - **Risk**: LOW 🔒 - **Validation**: All stores categorized - **Rollback**: N/A (categorization) - [ ] **Action 4.5.1.3**: Check for stores/auth.ts (should be removed) - **Scope**: `apps/web/src/stores/auth.ts` (if exists) - Verify it's obsolete - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: File doesn't exist or is unused - **Rollback**: N/A (verification) - [ ] **Action 4.5.1.4**: Remove stores/auth.ts if obsolete - **Scope**: `apps/web/src/stores/auth.ts` - Delete if unused - **Dependencies**: Action 4.5.1.3 complete, verify no imports - **Risk**: MEDIUM - **Validation**: File deleted, no imports remain - **Rollback**: Restore from git - [ ] **Action 4.5.1.5**: Handle stores/chat.ts vs features/chat/store/chatStore.ts duplication - **Scope**: Both files - Determine which is active, consolidate or remove duplicate - **Dependencies**: Action 4.5.1.1 complete - **Risk**: MEDIUM (may break chat functionality) - **Validation**: Single chat store, chat works - **Rollback**: Restore both files - [ ] **Action 4.5.1.6**: Audit cartStore for domain data - **Scope**: `apps/web/src/stores/cartStore.ts` - Check if stores domain data (cart items) - **Dependencies**: Action 4.5.1.2 complete - **Risk**: LOW 🔒 - **Validation**: Cart store categorized - **Rollback**: N/A (audit) - [ ] **Action 4.5.1.7**: Migrate cartStore domain data to React Query (if needed) - **Scope**: `apps/web/src/stores/cartStore.ts` - Move cart items to React Query if domain data - **Dependencies**: Action 4.5.1.6 complete - **Risk**: MEDIUM - **Validation**: Cart items in React Query, store only UI state - **Rollback**: Restore cart items to store - [ ] **Action 4.5.1.8**: Audit playerStore for domain data - **Scope**: `apps/web/src/features/player/store/playerStore.ts` - Check if stores domain data - **Dependencies**: Action 4.5.1.2 complete - **Risk**: LOW 🔒 - **Validation**: Player store categorized - **Rollback**: N/A (audit) - [ ] **Action 4.5.1.9**: Migrate playerStore domain data to React Query (if needed) - **Scope**: `apps/web/src/features/player/store/playerStore.ts` - Move domain data to React Query - **Dependencies**: Action 4.5.1.8 complete - **Risk**: MEDIUM - **Validation**: Domain data in React Query, store only player UI state - **Rollback**: Restore domain data to store - [ ] **Action 4.5.1.10**: Verify uiStore only has UI state - **Scope**: `apps/web/src/stores/ui.ts` - Verify only UI preferences (theme, language, sidebar) - **Dependencies**: Action 4.5.1.2 complete - **Risk**: LOW 🔒 - **Validation**: UI store has no domain data - **Rollback**: N/A (verification) ### Sub-Epic 4.6: Clean Up State Utilities 🟢 #### Task 4.6.1: Audit state utility files - [ ] **Action 4.6.1.1**: List all state utility files - **Scope**: `apps/web/src/utils/state*.ts`, `apps/web/src/utils/*state*.ts` - List all utilities - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Complete list of state utilities - **Rollback**: N/A (audit) - [ ] **Action 4.6.1.2**: Determine which utilities are still needed - **Scope**: All utilities from Action 4.6.1.1 - Categorize: needed, redundant, obsolete - **Dependencies**: Action 4.6.1.1 complete, Epic 4 complete - **Risk**: LOW 🔒 - **Validation**: Utilities categorized - **Rollback**: N/A (categorization) - [ ] **Action 4.6.1.3**: Remove obsolete state utilities - **Scope**: Obsolete utilities from Action 4.6.1.2 - Delete unused files - **Dependencies**: Action 4.6.1.2 complete, verify no imports - **Risk**: MEDIUM - **Validation**: Obsolete utilities deleted, no imports - **Rollback**: Restore from git - [ ] **Action 4.6.1.4**: Simplify stateMiddleware if still needed - **Scope**: `apps/web/src/utils/stateMiddleware.ts` - Simplify or remove if redundant - **Dependencies**: Action 4.6.1.2 complete - **Risk**: MEDIUM - **Validation**: Middleware simplified or removed - **Rollback**: Restore original middleware - [ ] **Action 4.6.1.5**: Update stateInvalidation to work with React Query - **Scope**: `apps/web/src/utils/stateInvalidation.ts` - Update to invalidate React Query cache - **Dependencies**: Epic 4 complete - **Risk**: MEDIUM - **Validation**: Invalidation works with React Query - **Rollback**: Restore original invalidation - [ ] **Action 4.6.1.6**: Update statePersistence if still needed - **Scope**: `apps/web/src/utils/statePersistence.ts` - Ensure it doesn't conflict with React Query persistence - **Dependencies**: Epic 4 complete - **Risk**: MEDIUM - **Validation**: No conflicts with React Query - **Rollback**: Restore original persistence - [ ] **Action 4.6.1.7**: Update STATE_DEBUGGING.md documentation - **Scope**: `apps/web/src/docs/STATE_DEBUGGING.md` - Remove references to stores/auth.ts, update store list - **Dependencies**: Action 4.5.1.4 complete - **Risk**: LOW 🔒 - **Validation**: Documentation accurate - **Rollback**: Restore original documentation - [ ] **Action 4.6.1.8**: Update STATE_SELECTORS.md documentation - **Scope**: `apps/web/src/docs/STATE_SELECTORS.md` - Update selectors for new store structure - **Dependencies**: Epic 4 complete - **Risk**: LOW 🔒 - **Validation**: Documentation accurate - **Rollback**: Restore original documentation - [ ] **Action 4.6.1.9**: Audit undoRedo utility usage - **Scope**: `apps/web/src/utils/undoRedo.ts` - Check where used, determine if still needed - **Dependencies**: Action 4.1.2.5 complete - **Risk**: LOW 🔒 - **Validation**: Usage documented - **Rollback**: N/A (audit) - [ ] **Action 4.6.1.10**: Remove undoRedo if unused - **Scope**: `apps/web/src/utils/undoRedo.ts` - Delete if no longer used - **Dependencies**: Action 4.6.1.9 complete, verify no imports - **Risk**: MEDIUM - **Validation**: File deleted, no imports - **Rollback**: Restore from git - [ ] **Action 4.6.1.11**: Audit stateNormalization utility - **Scope**: `apps/web/src/utils/stateNormalization.ts` - Check if still needed with React Query - **Dependencies**: Action 4.1.2.6 complete - **Risk**: LOW 🔒 - **Validation**: Usage documented - **Rollback**: N/A (audit) - [ ] **Action 4.6.1.12**: Remove stateNormalization if unused - **Scope**: `apps/web/src/utils/stateNormalization.ts` - Delete if no longer used - **Dependencies**: Action 4.6.1.11 complete, verify no imports - **Risk**: MEDIUM - **Validation**: File deleted, no imports - **Rollback**: Restore from git - [ ] **Action 4.6.1.13**: Audit stateCleanup utility - **Scope**: `apps/web/src/utils/stateCleanup.ts` - Check if still needed - **Dependencies**: Epic 4 complete - **Risk**: LOW 🔒 - **Validation**: Usage documented - **Rollback**: N/A (audit) - [ ] **Action 4.6.1.14**: Update or remove stateCleanup utility - **Scope**: `apps/web/src/utils/stateCleanup.ts` - Update for React Query or remove if unused - **Dependencies**: Action 4.6.1.13 complete - **Risk**: MEDIUM - **Validation**: Utility updated or removed - **Rollback**: Restore original utility --- ## EPIC 5: SECURITY & ROBUSTNESS 🔴 **Priority**: STABILITY FIRST **Goal**: Fix XSS vulnerabilities, improve error correlation, add rate limit UI ### Sub-Epic 5.1: Secure Token Storage 🔴 #### Task 5.1.1: Move Access Token to httpOnly Cookie - [ ] **Action 5.1.1.1**: Backend: Set access token in httpOnly cookie - **Scope**: `veza-backend-api/internal/handlers/auth.go` - Set cookie on login/refresh - **Dependencies**: None - **Risk**: HIGH (breaking change) - **Validation**: Cookie set, accessible in browser - **Rollback**: Remove cookie, restore token in response body - [ ] **Action 5.1.1.2**: Frontend: Remove localStorage token storage - **Scope**: `apps/web/src/services/tokenStorage.ts` - Remove localStorage, read from cookie - **Dependencies**: Action 5.1.1.1 complete, backend deployed - **Risk**: HIGH - **Validation**: No tokens in localStorage, all from cookie - **Rollback**: Restore localStorage - [ ] **Action 5.1.1.3**: Update API client to read token from cookie - **Scope**: `apps/web/src/services/api/client.ts` - Remove Authorization header, rely on cookie - **Dependencies**: Action 5.1.1.2 complete - **Risk**: MEDIUM - **Validation**: Requests work without Authorization header - **Rollback**: Restore header logic **Alternative**: Short-lived tokens (5 min) + frequent refresh - [ ] **Action 5.1.1.4**: Reduce access token expiry to 5 minutes - **Scope**: `veza-backend-api/internal/services/jwt.go` - Change expiry - **Dependencies**: None - **Risk**: MEDIUM - **Validation**: Tokens expire in 5 min - **Rollback**: Restore original expiry - [ ] **Action 5.1.1.5**: Implement proactive refresh every 4 minutes - **Scope**: `apps/web/src/services/tokenRefresh.ts` - Refresh before expiry - **Dependencies**: Action 5.1.1.4 complete - **Risk**: LOW - **Validation**: Tokens refresh automatically - **Rollback**: Remove proactive refresh - [ ] **Action 5.1.1.6**: Clean up localStorage token references - **Scope**: Search codebase for `localStorage.getItem('access_token')`, `localStorage.setItem('access_token')` - Remove all - **Dependencies**: Action 5.1.1.2 complete - **Risk**: LOW - **Validation**: No localStorage token access remains - **Rollback**: Restore localStorage access - [ ] **Action 5.1.1.7**: Update TokenStorage to read from cookie only - **Scope**: `apps/web/src/services/tokenStorage.ts` - Remove localStorage, add cookie reading - **Dependencies**: Action 5.1.1.2 complete - **Risk**: MEDIUM - **Validation**: TokenStorage reads from cookie, no localStorage - **Rollback**: Restore localStorage logic - [ ] **Action 5.1.1.8**: Update tokenRefresh to work with cookies - **Scope**: `apps/web/src/services/tokenRefresh.ts` - Update to read/write cookies instead of localStorage - **Dependencies**: Action 5.1.1.7 complete - **Risk**: MEDIUM - **Validation**: Token refresh works with cookies - **Rollback**: Restore localStorage logic - [ ] **Action 5.1.1.9**: Update all token access to use TokenStorage - **Scope**: Search for direct localStorage token access - Replace with TokenStorage methods - **Dependencies**: Action 5.1.1.7 complete - **Risk**: MEDIUM - **Validation**: No direct localStorage token access - **Rollback**: Restore direct access ### Sub-Epic 5.2: Pre-Validation 🟢 #### Task 5.2.1: Add Backend Validation Endpoint - [ ] **Action 5.2.1.1**: Create `/api/v1/validate` endpoint - **Scope**: `veza-backend-api/internal/handlers/validate.go` (create) - **Dependencies**: None - **Risk**: LOW - **Validation**: Endpoint validates request bodies - **Rollback**: Delete endpoint - [ ] **Action 5.2.1.2**: Frontend: Call validate before submit - **Scope**: Form components - Call validate endpoint on blur/change - **Dependencies**: Action 5.2.1.1 complete - **Risk**: MEDIUM - **Validation**: Backend errors shown before submit - **Rollback**: Remove validation calls - [ ] **Action 5.2.1.3**: Create useFormValidation hook - **Scope**: `apps/web/src/hooks/useFormValidation.ts` (create) - Hook for pre-validation - **Dependencies**: Action 5.2.1.1 complete - **Risk**: LOW - **Validation**: Hook works, integrates with forms - **Rollback**: Delete hook - [ ] **Action 5.2.1.4**: Integrate useFormValidation into all forms - **Scope**: All form components - Use hook for pre-validation - **Dependencies**: Action 5.2.1.3 complete - **Risk**: MEDIUM - **Validation**: All forms use pre-validation - **Rollback**: Remove hook usage - [ ] **Action 5.2.1.5**: Debounce validation calls - **Scope**: `apps/web/src/hooks/useFormValidation.ts` - Debounce validation requests - **Dependencies**: Action 5.2.1.3 complete - **Risk**: LOW - **Validation**: Validation debounced (300ms) - **Rollback**: Remove debounce ### Sub-Epic 5.3: Error Correlation 🟢 #### Task 5.3.1: Always Show Request ID - [ ] **Action 5.3.1.1**: Remove dev-only check for request ID - **Scope**: `apps/web/src/utils/apiErrorHandler.ts:315-320` - Always include request ID - **Dependencies**: None - **Risk**: LOW - **Validation**: Request ID always shown - **Rollback**: Restore dev check - [ ] **Action 5.3.1.2**: Add "Report Issue" button with request ID - **Scope**: `apps/web/src/components/ui/ErrorDisplay.tsx` - Add button, copy request ID - **Dependencies**: Action 3.1.1.2 complete - **Risk**: LOW - **Validation**: Button copies request ID to clipboard - **Rollback**: Remove button ### Sub-Epic 5.4: Rate Limit UI 🟢 #### Task 5.4.1: Display Rate Limit Status - [ ] **Action 5.4.1.1**: Parse rate limit headers - **Scope**: `apps/web/src/services/api/client.ts` - Parse `X-RateLimit-*` headers - **Dependencies**: None - **Risk**: LOW - **Validation**: Headers parsed, stored in state - **Rollback**: Remove parsing - [ ] **Action 5.4.1.2**: Create rate limit indicator component - **Scope**: `apps/web/src/components/RateLimitIndicator.tsx` (create) - **Dependencies**: Action 5.4.1.1 complete - **Risk**: LOW - **Validation**: Component shows rate limit status - **Rollback**: Delete component - [ ] **Action 5.4.1.3**: Show indicator in header - **Scope**: `apps/web/src/components/Header.tsx` or layout - Add RateLimitIndicator - **Dependencies**: Action 5.4.1.2 complete - **Risk**: LOW - **Validation**: Indicator visible in header - **Rollback**: Remove from header - [ ] **Action 5.4.1.4**: Disable buttons when rate limited - **Scope**: All mutation buttons - Check rate limit, disable if limited - **Dependencies**: Action 5.4.1.1 complete - **Risk**: MEDIUM - **Validation**: Buttons disabled when rate limited - **Rollback**: Remove disable logic - [ ] **Action 5.4.1.5**: Show countdown timer - **Scope**: `apps/web/src/components/RateLimitIndicator.tsx` - Calculate reset time, show timer - **Dependencies**: Action 5.4.1.2 complete - **Risk**: LOW - **Validation**: Timer counts down to reset - **Rollback**: Remove timer - [ ] **Action 5.4.1.6**: Add rate limit state management - **Scope**: `apps/web/src/stores/rateLimit.ts` (create) - Store rate limit state from headers - **Dependencies**: Action 5.4.1.1 complete - **Risk**: LOW - **Validation**: Rate limit state stored and accessible - **Rollback**: Delete store - [ ] **Action 5.4.1.7**: Integrate rate limit store with indicator - **Scope**: `apps/web/src/components/RateLimitIndicator.tsx` - Use rate limit store - **Dependencies**: Action 5.4.1.6 complete - **Risk**: LOW - **Validation**: Indicator reads from store - **Rollback**: Remove store integration --- ## EPIC 6: SCALABILITY & EVOLUTION 🟢 **Priority**: UX/UI THIRD **Goal**: Reduce coupling, improve performance, enable evolution ### Sub-Epic 6.1: API Abstraction Layer 🟢 #### Task 6.1.1: Create Service Layer - [ ] **Action 6.1.1.1**: Create tracks API service - **Scope**: `apps/web/src/services/api/tracks.ts` (create) - Export `tracksApi` object - **Dependencies**: None - **Risk**: LOW - **Validation**: Service exports list, get, create, update, delete methods - **Rollback**: Delete file - [ ] **Action 6.1.1.2**: Replace direct API calls with service - **Scope**: All components importing `@/features/tracks/api/trackApi` - Use `tracksApi` instead - **Dependencies**: Action 6.1.1.1 complete - **Risk**: MEDIUM - **Validation**: No direct API imports - **Rollback**: Restore direct imports - [ ] **Action 6.1.1.3**: Create users API service - **Scope**: `apps/web/src/services/api/users.ts` (create) - Export `usersApi` object - **Dependencies**: Action 6.1.1.1 complete - **Risk**: LOW - **Validation**: Service exports user-related methods - **Rollback**: Delete file - [ ] **Action 6.1.1.4**: Create playlists API service - **Scope**: `apps/web/src/services/api/playlists.ts` (create) - Export `playlistsApi` object - **Dependencies**: Action 6.1.1.1 complete - **Risk**: LOW - **Validation**: Service exports playlist-related methods - **Rollback**: Delete file - [ ] **Action 6.1.1.5**: Create auth API service - **Scope**: `apps/web/src/services/api/auth.ts` (create/update) - Export `authApi` object - **Dependencies**: Action 6.1.1.1 complete - **Risk**: LOW - **Validation**: Service exports auth-related methods - **Rollback**: Restore original auth service - [ ] **Action 6.1.1.6**: Replace direct API calls with services (users) - **Scope**: All components importing user API functions - Use `usersApi` instead - **Dependencies**: Action 6.1.1.3 complete - **Risk**: MEDIUM - **Validation**: No direct user API imports - **Rollback**: Restore direct imports - [ ] **Action 6.1.1.7**: Replace direct API calls with services (playlists) - **Scope**: All components importing playlist API functions - Use `playlistsApi` instead - **Dependencies**: Action 6.1.1.4 complete - **Risk**: MEDIUM - **Validation**: No direct playlist API imports - **Rollback**: Restore direct imports - [ ] **Action 6.1.1.8**: Replace direct API calls with services (auth) - **Scope**: All components importing auth API functions - Use `authApi` instead - **Dependencies**: Action 6.1.1.5 complete - **Risk**: MEDIUM - **Validation**: No direct auth API imports - **Rollback**: Restore direct imports - [ ] **Action 6.1.1.9**: Create index file for API services - **Scope**: `apps/web/src/services/api/index.ts` (create/update) - Export all services - **Dependencies**: All services created - **Risk**: LOW - **Validation**: All services exported from index - **Rollback**: Delete index file - [ ] **Action 6.1.1.10**: Update all feature API files to use services - **Scope**: `apps/web/src/features/*/api/*.ts` - Update to use service layer - **Dependencies**: All services created - **Risk**: MEDIUM - **Validation**: Feature APIs use service layer - **Rollback**: Restore direct API calls - [ ] **Action 6.1.1.11**: Remove obsolete feature API files (if any) - **Scope**: Feature API files that are now redundant - Delete if replaced by services - **Dependencies**: Action 6.1.1.10 complete - **Risk**: MEDIUM - **Validation**: Obsolete files deleted - **Rollback**: Restore deleted files ### Sub-Epic 6.2: Code Splitting 🟢 #### Task 6.2.1: Lazy Load Routes - [ ] **Action 6.2.1.1**: Convert routes to lazy loading - **Scope**: Router config - Use `React.lazy()` for all routes - **Dependencies**: None - **Risk**: MEDIUM - **Validation**: Routes load on demand, bundle size reduced - **Rollback**: Remove lazy loading - [ ] **Action 6.2.1.2**: Split vendor bundles - **Scope**: `apps/web/vite.config.ts` - Configure manual chunks - **Dependencies**: None - **Risk**: LOW - **Validation**: Vendor code split into separate chunks - **Rollback**: Remove manual chunks - [ ] **Action 6.2.1.3**: Identify heavy components - **Scope**: Audit all components - List heavy components (charts, editors, large libraries) - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: List of heavy components - **Rollback**: N/A (audit) - [ ] **Action 6.2.1.4**: Dynamic imports for heavy components - **Scope**: Heavy components from Action 6.2.1.3 - Use dynamic imports - **Dependencies**: Action 6.2.1.3 complete - **Risk**: LOW - **Validation**: Heavy components load on demand - **Rollback**: Restore static imports - [ ] **Action 6.2.1.5**: Add loading states for lazy-loaded components - **Scope**: All lazy-loaded components - Add Suspense boundaries with loading states - **Dependencies**: Action 6.2.1.1 complete - **Risk**: LOW - **Validation**: Loading states show during lazy load - **Rollback**: Remove loading states - [ ] **Action 6.2.1.6**: Add error boundaries for lazy-loaded components - **Scope**: All lazy-loaded components - Wrap in error boundaries - **Dependencies**: Action 6.2.1.1 complete, Action 3.3.1.2 complete - **Risk**: LOW - **Validation**: Errors in lazy-loaded components caught - **Rollback**: Remove error boundaries - [ ] **Action 6.2.1.7**: Measure bundle size before/after code splitting - **Scope**: Build process - Measure bundle sizes - **Dependencies**: Action 6.2.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Bundle sizes measured and documented - **Rollback**: N/A (measurement) - [ ] **Action 6.2.1.8**: Optimize bundle sizes if needed - **Scope**: Bundle analysis - Optimize if bundles still too large - **Dependencies**: Action 6.2.1.7 complete - **Risk**: MEDIUM - **Validation**: Bundle sizes optimized - **Rollback**: Restore original bundles ### Sub-Epic 6.3: Virtualization 🟢 #### Task 6.3.1: Implement List Virtualization - [ ] **Action 6.3.1.1**: Install react-window or @tanstack/react-virtual - **Scope**: `apps/web/package.json` - Add dependency - **Dependencies**: None - **Risk**: LOW - **Validation**: Package installed - **Rollback**: Remove from package.json - [ ] **Action 6.3.1.2**: Virtualize LibraryPage track list - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx` - Wrap track list in virtualizer - **Dependencies**: Action 6.3.1.1 complete - **Risk**: MEDIUM - **Validation**: Long lists render smoothly - **Rollback**: Remove virtualization - [ ] **Action 6.3.1.3**: Implement infinite scroll - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx` - Load more on scroll - **Dependencies**: Action 6.3.1.2 complete - **Risk**: MEDIUM - **Validation**: Tracks load as user scrolls - **Rollback**: Restore pagination - [ ] **Action 6.3.1.4**: Add loading indicator for infinite scroll - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx` - Show loading at bottom when fetching more - **Dependencies**: Action 6.3.1.3 complete - **Risk**: LOW - **Validation**: Loading indicator appears when fetching - **Rollback**: Remove indicator - [ ] **Action 6.3.1.5**: Handle infinite scroll edge cases - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx` - Handle end of list, errors, empty states - **Dependencies**: Action 6.3.1.3 complete - **Risk**: MEDIUM - **Validation**: Edge cases handled gracefully - **Rollback**: Remove edge case handling --- ## EPIC 7: VISUAL HIERARCHY 🟢 **Priority**: UX/UI THIRD **Goal**: Establish focal points, reduce visual noise, guide user attention ### Sub-Epic 7.1: Typography System ✅ QUICK WIN #### Task 7.1.1: Define Type Scale - [ ] **Action 7.1.1.1**: Add type scale to design tokens - **Scope**: `apps/web/src/styles/design-tokens.css` - Add `--text-xs` through `--text-4xl` - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: All sizes defined, values match spec - **Rollback**: Remove CSS variables - [ ] **Action 7.1.1.2**: Create Tailwind type utilities - **Scope**: `apps/web/tailwind.config.ts` - Add text size utilities - **Dependencies**: Action 7.1.1.1 complete - **Risk**: LOW 🔒 - **Validation**: `text-xs` through `text-4xl` classes work - **Rollback**: Remove from config - [ ] **Action 7.1.1.3**: Audit all text size classes - **Scope**: Search for `text-xs`, `text-sm`, `text-base`, `text-lg`, `text-xl`, `text-2xl`, `text-3xl`, `text-4xl` - List all - **Dependencies**: Action 7.1.1.2 complete - **Risk**: LOW 🔒 - **Validation**: Complete list of text size classes - **Rollback**: N/A (audit) - [ ] **Action 7.1.1.4**: Replace all text-* classes with scale - **Scope**: All components from Action 7.1.1.3 - Replace with scale classes - **Dependencies**: Action 7.1.1.3 complete - **Risk**: MEDIUM (visual changes) - **Validation**: All text uses scale, visual consistency - **Rollback**: Restore original classes - [ ] **Action 7.1.1.5**: Add ESLint rule to enforce type scale - **Scope**: `.eslintrc.js` - Add rule to warn on non-scale text sizes - **Dependencies**: Action 7.1.1.4 complete - **Risk**: LOW 🔒 - **Validation**: ESLint warns on non-scale sizes - **Rollback**: Remove rule #### Task 7.1.2: Fix Heading Inconsistencies - [ ] **Action 7.1.2.1**: Audit all h1 elements - **Scope**: Search for `` elements - Use consistent sizes (text-base for body, text-sm for secondary) - **Dependencies**: Action 7.1.1.3 complete - **Risk**: LOW 🔒 - **Validation**: All paragraphs use type scale - **Rollback**: Restore original sizes ### Sub-Epic 7.2: Spacing System ✅ QUICK WIN #### Task 7.2.1: Define Spacing Scale - [ ] **Action 7.2.1.1**: Add spacing scale to design tokens - **Scope**: `apps/web/src/styles/design-tokens.css` - Add `--spacing-xs` through `--spacing-xxl` - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: All spacing values defined - **Rollback**: Remove CSS variables - [ ] **Action 7.2.1.2**: Audit all spacing classes - **Scope**: Search for `space-y-`, `space-x-`, `gap-`, `p-`, `m-`, `px-`, `py-`, `mx-`, `my-` - List all spacing usage - **Dependencies**: Action 7.2.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Complete list of spacing classes - **Rollback**: N/A (audit) - [ ] **Action 7.2.1.3**: Replace inconsistent spacing - **Scope**: All components from Action 7.2.1.2 - Replace with scale - **Dependencies**: Action 7.2.1.2 complete - **Risk**: MEDIUM (visual changes) - **Validation**: Consistent spacing throughout - **Rollback**: Restore original spacing - [ ] **Action 7.2.1.4**: Add ESLint rule to enforce spacing scale - **Scope**: `.eslintrc.js` - Add rule to warn on non-scale spacing - **Dependencies**: Action 7.2.1.3 complete - **Risk**: LOW 🔒 - **Validation**: ESLint warns on non-scale spacing - **Rollback**: Remove rule - [ ] **Action 7.2.1.3**: Create spacing utility classes - **Scope**: `apps/web/tailwind.config.ts` - Add spacing utilities if needed - **Dependencies**: Action 7.2.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Spacing utilities available - **Rollback**: Remove utilities - [ ] **Action 7.2.1.4**: Document spacing usage - **Scope**: `apps/web/src/styles/design-tokens.css` - Add comments for usage - **Dependencies**: Action 7.2.1.2 complete - **Risk**: LOW 🔒 - **Validation**: Documentation clear - **Rollback**: Remove comments - [ ] **Action 7.2.1.5**: Create SPACING_GUIDE.md - **Scope**: `apps/web/src/styles/SPACING_GUIDE.md` (create) - Document spacing system usage - **Dependencies**: Action 7.2.1.4 complete - **Risk**: LOW 🔒 - **Validation**: Guide documents spacing usage - **Rollback**: Delete file ### Sub-Epic 7.3: Establish Focal Points 🟢 #### Task 7.3.1: Redesign Dashboard Hierarchy - [ ] **Action 7.3.1.1**: Make primary stat (tracks played) large and prominent - **Scope**: `apps/web/src/pages/DashboardPage.tsx:132-164` - Increase size of first stat card - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Primary stat 2x size of others - **Rollback**: Restore equal sizes - [ ] **Action 7.3.1.2**: Reduce welcome message size/weight - **Scope**: `apps/web/src/pages/DashboardPage.tsx:101` - Change `text-4xl` to `text-2xl` - **Dependencies**: Action 7.1.1.3 complete - **Risk**: LOW 🔒 - **Validation**: Message smaller, less prominent - **Rollback**: Restore original size - [ ] **Action 7.3.1.3**: Make Upload button most prominent (FAB or large) - **Scope**: `apps/web/src/pages/DashboardPage.tsx:119-127` - Increase size, add FAB styling - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Upload button most visible - **Rollback**: Restore original styling - [ ] **Action 7.3.1.4**: Collapse activity feed by default - **Scope**: `apps/web/src/pages/DashboardPage.tsx:207-254` - Add collapsible wrapper - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Feed collapsed, expandable - **Rollback**: Remove collapsible - [ ] **Action 7.3.1.5**: Create Collapsible component (if doesn't exist) - **Scope**: `apps/web/src/components/ui/collapsible.tsx` (create) - Reusable collapsible wrapper - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Component works, reusable - **Rollback**: Delete component - [ ] **Action 7.3.1.6**: Use Collapsible for activity feed - **Scope**: `apps/web/src/pages/DashboardPage.tsx:207-254` - Wrap with Collapsible component - **Dependencies**: Action 7.3.1.5 complete - **Risk**: LOW 🔒 - **Validation**: Feed uses Collapsible component - **Rollback**: Remove Collapsible wrapper - [ ] **Action 7.3.1.7**: Add FAB (Floating Action Button) component - **Scope**: `apps/web/src/components/ui/FAB.tsx` (create) - Floating action button component - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: FAB component works - **Rollback**: Delete component - [ ] **Action 7.3.1.8**: Use FAB for Upload button - **Scope**: `apps/web/src/pages/DashboardPage.tsx:119-127` - Replace button with FAB - **Dependencies**: Action 7.3.1.7 complete - **Risk**: LOW 🔒 - **Validation**: Upload uses FAB - **Rollback**: Restore button ### Sub-Epic 7.4: Eliminate Dead Zones 🟢 #### Task 7.4.1: Compact Filters - [ ] **Action 7.4.1.1**: Create Sidebar component (if doesn't exist) - **Scope**: `apps/web/src/components/ui/Sidebar.tsx` (create) - Reusable sidebar component - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Sidebar component works - **Rollback**: Delete component - [ ] **Action 7.4.1.2**: Move filters to sidebar or collapsible section - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx:317-383` - Move to sidebar - **Dependencies**: Action 7.4.1.1 complete - **Risk**: MEDIUM (layout change) - **Validation**: Filters in sidebar, main area for content - **Rollback**: Restore full-width filters - [ ] **Action 7.4.1.3**: Make sidebar collapsible - **Scope**: `apps/web/src/components/ui/Sidebar.tsx` - Add collapse/expand functionality - **Dependencies**: Action 7.4.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Sidebar collapses/expands - **Rollback**: Remove collapse functionality --- ## EPIC 8: INTERACTION CLARITY 🟢 **Priority**: UX/UI THIRD **Goal**: Make actions discoverable, provide feedback, reduce confusion ### Sub-Epic 8.1: Single Action Path 🟢 #### Task 8.1.1: Remove Duplicate Upload Buttons - [ ] **Action 8.1.1.1**: Audit all upload buttons - **Scope**: Search for "Upload" buttons, document locations - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: List of all upload buttons - **Rollback**: N/A (audit) - [ ] **Action 8.1.1.2**: Determine primary upload button location - **Scope**: Based on Action 8.1.1.1 - Decide which location is primary (likely header/FAB) - **Dependencies**: Action 8.1.1.1 complete - **Risk**: LOW - **Validation**: Primary location documented - **Rollback**: N/A (decision) - [ ] **Action 8.1.1.3**: Remove duplicate upload buttons - **Scope**: All locations except primary - Remove duplicate buttons - **Dependencies**: Action 8.1.1.2 complete - **Risk**: MEDIUM (removes functionality) - **Validation**: One upload button, consistent behavior - **Rollback**: Restore duplicates - [ ] **Action 8.1.1.4**: Ensure consistent upload behavior - **Scope**: Primary upload button - Verify same behavior (opens modal/navigates) - **Dependencies**: Action 8.1.1.3 complete - **Risk**: LOW - **Validation**: Upload button behavior consistent - **Rollback**: N/A (verification) ### Sub-Epic 8.2: Visual Affordances 🟢 #### Task 8.2.1: Add Hover States to Interactive Elements - [ ] **Action 8.2.1.1**: Add hover to track cards - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx:413-470` - Add `hover:` classes, `cursor-pointer` - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Cards show hover state, cursor changes - **Rollback**: Remove hover classes - [ ] **Action 8.2.1.2**: Audit all interactive elements - **Scope**: Search for `onClick`, `onMouseEnter`, buttons, links - List all interactive elements - **Dependencies**: Action 8.2.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Complete list of interactive elements - **Rollback**: N/A (audit) - [ ] **Action 8.2.1.3**: Add hover to all clickable elements - **Scope**: All elements from Action 8.2.1.2 - Add hover states and cursor-pointer - **Dependencies**: Action 8.2.1.2 complete - **Risk**: LOW 🔒 - **Validation**: All clickable elements have hover - **Rollback**: Remove hover classes - [ ] **Action 8.2.1.4**: Add focus states for keyboard navigation - **Scope**: All interactive elements - Add focus-visible states - **Dependencies**: Action 8.2.1.3 complete - **Risk**: LOW 🔒 - **Validation**: All elements have focus states - **Rollback**: Remove focus states ### Sub-Epic 8.3: Loading States 🟢 #### Task 8.3.1: Add Loading States to All Mutations - [ ] **Action 8.3.1.1**: Add loading state to addToPlaylist button - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx:137-145` - Use `isLoading` from mutation - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Button shows spinner when loading - **Rollback**: Remove loading state - [ ] **Action 8.3.1.2**: Audit all mutation buttons - **Scope**: Search for mutation calls (`mutateAsync`, `mutate`) - List all mutation buttons - **Dependencies**: Action 8.3.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Complete list of mutation buttons - **Rollback**: N/A (audit) - [ ] **Action 8.3.1.3**: Add loading states to all mutation buttons - **Scope**: All buttons from Action 8.3.1.2 - Add loading states - **Dependencies**: Action 8.3.1.2 complete - **Risk**: LOW 🔒 - **Validation**: All mutations show loading - **Rollback**: Remove loading states - [ ] **Action 8.3.1.4**: Create Spinner component (if doesn't exist) - **Scope**: `apps/web/src/components/ui/Spinner.tsx` (create) - Reusable spinner component - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Spinner component works - **Rollback**: Delete component - [ ] **Action 8.3.1.5**: Use Spinner in loading states - **Scope**: All loading states - Use Spinner component - **Dependencies**: Action 8.3.1.4 complete - **Risk**: LOW 🔒 - **Validation**: All loading states use Spinner - **Rollback**: Remove Spinner usage ### Sub-Epic 8.4: Mode Indicators 🟢 #### Task 8.4.1: Show Bulk Mode Banner - [ ] **Action 8.4.1.1**: Create bulk mode banner component - **Scope**: `apps/web/src/components/BulkModeBanner.tsx` (create) - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Banner shows when bulk mode active - **Rollback**: Delete component - [ ] **Action 8.4.1.2**: Show banner in LibraryPage when bulk mode active - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx` - Add banner, show count - **Dependencies**: Action 8.4.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Banner visible, shows "3 items selected" - **Rollback**: Remove banner - [ ] **Action 8.4.1.3**: Highlight selected items clearly - **Scope**: `apps/web/src/features/library/pages/LibraryPage.tsx:416-419` - Enhance selection styling - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Selected items clearly highlighted - **Rollback**: Restore original styling --- ## EPIC 9: CONSISTENCY 🟢 **Priority**: UX/UI THIRD **Goal**: Establish design system, enforce usage, reduce drift ### Sub-Epic 9.1: Color System 🟢 #### Task 9.1.1: Document Color Usage - [ ] **Action 9.1.1.1**: Create color usage guide - **Scope**: `apps/web/src/styles/COLOR_USAGE.md` (create) - **Dependencies**: None - **Risk**: LOW 🔒 - **Validation**: Guide documents when to use each color - **Rollback**: Delete file - [ ] **Action 9.1.1.2**: Audit Tailwind default color usage - **Scope**: Search for `text-cyan-`, `bg-cyan-`, `border-cyan-` etc. - List all Tailwind default colors - **Dependencies**: Action 9.1.1.1 complete - **Risk**: LOW 🔒 - **Validation**: Complete list of Tailwind default colors - **Rollback**: N/A (audit) - [ ] **Action 9.1.1.3**: Remove Tailwind default colors - **Scope**: All components from Action 9.1.1.2 - Replace with design system colors - **Dependencies**: Action 9.1.1.2 complete - **Risk**: MEDIUM (visual changes) - **Validation**: No Tailwind default colors used - **Rollback**: Restore Tailwind colors - [ ] **Action 9.1.1.4**: Add ESLint rule to prevent Tailwind defaults - **Scope**: `.eslintrc.js` - Add rule to warn on Tailwind default colors - **Dependencies**: Action 9.1.1.3 complete - **Risk**: LOW 🔒 - **Validation**: ESLint warns on Tailwind defaults - **Rollback**: Remove rule ### Sub-Epic 9.2: Component Library 🟢 #### Task 9.2.1: Audit Custom Buttons - [ ] **Action 9.2.1.1**: Find all custom button implementations - **Scope**: Search for `