docs: map existing codebase

This commit is contained in:
2026-03-16 11:19:29 +01:00
parent 65d9842831
commit 45e0f779a4
7 changed files with 1609 additions and 0 deletions

View File

@@ -0,0 +1,224 @@
# Codebase Concerns
**Analysis Date:** 2026-03-16
## Tech Debt
**Unsafe Type Assertions:**
- Issue: Environment variables are cast with `as string` without runtime validation
- Files: `src/lib/supabase.ts`
- Impact: If environment variables are missing or undefined, the application will fail at runtime with cryptic errors instead of clear validation
- Fix approach: Implement proper environment variable validation at startup with descriptive error messages. Use a validation function or schema validator (e.g., Zod) to ensure all required env vars are present and properly typed before using them.
**Unvalidated Supabase Query Results:**
- Issue: Database query results are cast to types with `as Type` without validation (e.g., `data as Budget[]`, `data as Category[]`)
- Files: `src/hooks/useBudgets.ts`, `src/hooks/useTemplate.ts`, `src/hooks/useCategories.ts`, `src/hooks/useQuickAdd.ts`
- Impact: If database schema changes or returns unexpected data structure, application could crash silently or display incorrect data. Type casting bypasses TypeScript safety.
- Fix approach: Add runtime validation using Zod or similar schema validation library. Define schemas for all database types and validate responses before casting.
**Hardcoded Date Logic Without Timezone Handling:**
- Issue: Date calculations in `monthBounds()` and budget queries use local timezone without explicit handling
- Files: `src/hooks/useBudgets.ts` (line 27-42), `src/pages/DashboardPage.tsx` (line 37-39)
- Impact: Users in different timezones may see incorrect month boundaries. Budget dates could be off by one day depending on user timezone.
- Fix approach: Use a date library like `date-fns` or `Day.js` with explicit timezone support. Store all dates in UTC and format for display based on user locale.
**No Error Boundary Component:**
- Issue: Application has no React Error Boundary to catch and handle rendering errors gracefully
- Files: `src/App.tsx`, `src/components/AppLayout.tsx`
- Impact: A single component error can crash the entire application without user feedback. No recovery mechanism.
- Fix approach: Implement an Error Boundary wrapper at the root level and key sections to gracefully display fallback UI and log errors.
## Known Bugs
**Query Invalidation Race Conditions:**
- Symptoms: When mutations complete, related queries are invalidated but may not refetch before components re-render
- Files: `src/hooks/useBudgets.ts`, `src/hooks/useTemplate.ts`, `src/hooks/useCategories.ts`
- Trigger: Rapid mutations on related data (e.g., updating template items then immediately viewing budget detail)
- Workaround: Manually refetch or await invalidation before navigation
**Logout Doesn't Clear Cache:**
- Symptoms: After logout, if user logs back in as different user, old data may still be visible momentarily
- Files: `src/hooks/useAuth.ts`, `src/components/AppLayout.tsx`
- Trigger: User logs out, then logs in as different account
- Workaround: Clear QueryClient cache on logout
**Missing Bounds Check on Inline Edits:**
- Symptoms: User can enter negative numbers or extremely large numbers in inline edit cells
- Files: `src/pages/BudgetDetailPage.tsx` (InlineEditCell component)
- Trigger: User enters invalid amount in inline editor
- Workaround: Client-side validation only; no server-side constraints shown
## Security Considerations
**Unauthenticated Supabase Client Exposed:**
- Risk: Application uses public anon key for Supabase, all clients share same authentication
- Files: `src/lib/supabase.ts`
- Current mitigation: Supabase RLS policies on database tables
- Recommendations: Verify RLS policies are correctly set on ALL tables. Test that users cannot access other users' data through direct API calls. Consider using service role key for sensitive operations and server-side validation.
**No Input Validation on User-Provided Data:**
- Risk: Category names, template names, quick-add names accepted without validation or sanitization
- Files: `src/pages/CategoriesPage.tsx`, `src/pages/TemplatePage.tsx`, `src/pages/QuickAddPage.tsx`, `src/components/QuickAddPicker.tsx`
- Current mitigation: Input length limited by UI
- Recommendations: Add server-side validation for text length, character restrictions, and XSS prevention. Sanitize data before display.
**No Rate Limiting on Mutations:**
- Risk: User can spam API with unlimited mutations (create, update, delete operations)
- Files: All hook files with mutations
- Current mitigation: None
- Recommendations: Implement client-side debouncing and server-side rate limiting per user. Add confirmation dialogs for destructive operations.
**Cleartext Storage of Sensitive Data:**
- Risk: Notes field on budget items can contain sensitive information but has no encryption
- Files: `src/pages/BudgetDetailPage.tsx` (notes field)
- Current mitigation: None
- Recommendations: Add encryption for notes field or implement field-level access control via RLS.
## Performance Bottlenecks
**Inefficient Pie Chart Rendering on Large Budgets:**
- Problem: PieChart component recalculates and re-renders on every data change without memoization
- Files: `src/pages/DashboardPage.tsx` (lines 104-109, Pie chart rendering)
- Cause: Pie chart data transformation happens during render, component not memoized
- Improvement path: Memoize chart data calculations with `useMemo()`. Consider moving heavy computations outside render.
**Category Lookup O(n) on Every Item:**
- Problem: Every budget item with category data requires iterating through categories array in filters
- Files: `src/pages/DashboardPage.tsx`, `src/pages/BudgetDetailPage.tsx`
- Cause: Using `filter()` and `reduce()` in render logic without memoization or indexing
- Improvement path: Create a category index Map in a custom hook. Memoize grouped/filtered results.
**No Pagination on Long Lists:**
- Problem: All budgets, categories, and quick-add items load at once. No pagination or virtualization.
- Files: `src/pages/BudgetListPage.tsx`, `src/pages/CategoriesPage.tsx`, `src/pages/QuickAddPage.tsx`
- Cause: Supabase queries fetch all rows without limit
- Improvement path: Implement pagination with `.range()` in queries. For very large lists, use virtual scrolling.
**Sidebar Component Overcomplicated:**
- Problem: Sidebar UI component is 724 lines with extensive state and conditional logic
- Files: `src/components/ui/sidebar.tsx`
- Cause: Radix UI base component with full feature set
- Improvement path: Extract mobile/desktop logic into separate custom hooks. Consider if full sidebar complexity is needed.
## Fragile Areas
**Budget Month Lookup Logic:**
- Files: `src/pages/DashboardPage.tsx` (lines 285-289), `src/hooks/useBudgets.ts` (line 28-32)
- Why fragile: String prefix matching on dates to find current month budget. If date format changes, breaks silently.
- Safe modification: Create dedicated date utility functions with tests. Use date library comparison instead of string prefixes.
- Test coverage: No unit tests for monthBounds or month lookup logic
**QuickAddPicker Multi-Dialog State:**
- Files: `src/components/QuickAddPicker.tsx`
- Why fragile: Manages two modal states (popover + dialog) with multiple interdependent state variables. Easy to get out of sync.
- Safe modification: Refactor into a state machine pattern or context provider. Create helper function to reset all state.
- Test coverage: No tests for state transitions or edge cases (e.g., closing popover while dialog open)
**Inline Edit Cell Implementation:**
- Files: `src/pages/BudgetDetailPage.tsx` (lines 68-133)
- Why fragile: `useRef` with imperative focus, async commit logic could leave cell in inconsistent state on error
- Safe modification: Add error handling in commit() to reset editing state. Use useCallback to memoize handlers.
- Test coverage: No tests for edit flow, cancellation, or blur behavior
**Template Item Reordering:**
- Files: `src/hooks/useTemplate.ts` (lines 174-189)
- Why fragile: Uses Promise.all for batch updates, first error stops entire operation but leaves partial state
- Safe modification: Implement transaction-like behavior or rollback on error. Show partial success/failure feedback.
- Test coverage: No tests for concurrent updates or error scenarios
**Date Parsing in Budget Heading:**
- Files: `src/pages/BudgetDetailPage.tsx` (lines 275-280)
- Why fragile: Splits date string and uses `map(Number)` which could silently fail if date format changes
- Safe modification: Use date parsing library. Add validation for date format.
- Test coverage: No tests for date format parsing
## Scaling Limits
**QueryClient Cache Without Limits:**
- Current capacity: Unbounded cache growth with every mutation
- Limit: Long sessions could consume significant memory with stale cached data
- Scaling path: Implement QueryClient cache configuration with GC time, stale time, and maximum cache size
**No Database Indexing Strategy Documented:**
- Current capacity: Unknown if queries will scale beyond thousands of items
- Limit: Performance degradation as user data grows
- Scaling path: Add database indexes on user_id, category_id, budget_id fields. Document query patterns.
**Sidebar Component Renders Full Navigation on Every App Load:**
- Current capacity: Works fine with <10 navigation items
- Limit: Could become slow if navigation items scale to hundreds
- Scaling path: Implement menu virtualization or lazy loading for navigation items
## Dependencies at Risk
**React Query (TanStack Query) Version Lock:**
- Risk: Fixed to v5.90.21, major version bumps require API migration
- Impact: Security fixes in newer versions require full refactor
- Migration plan: Create abstraction layer for React Query hooks to isolate API. Plan quarterly dependency updates.
**Supabase SDK Not Version-Locked:**
- Risk: Using ^2.99.1 allows minor/patch updates that could introduce breaking changes
- Impact: Unexpected behavior in authentication or database operations
- Migration plan: Pin to exact version during development, test thoroughly before minor version upgrades
**Recharts for Charts:**
- Risk: Limited customization without ejecting to custom D3
- Impact: Cannot easily implement complex financial chart types needed in future
- Migration plan: Consider migrating to Chart.js or Visx if advanced charting requirements emerge
## Missing Critical Features
**No Data Export:**
- Problem: Users cannot export budgets or transaction data
- Blocks: Users cannot do external analysis, tax reporting, or data portability
**No Recurring Transactions:**
- Problem: Each month requires manual budget recreation or template generation
- Blocks: Can't model monthly recurring expenses that auto-populate
**No Budget Archival:**
- Problem: Old budgets accumulate in database, no way to hide or delete safely
- Blocks: UI becomes cluttered, performance degrades
**No Audit Trail:**
- Problem: No tracking of who changed what and when
- Blocks: Cannot debug data inconsistencies or provide accountability
**No Multi-Device Sync:**
- Problem: Offline support or sync conflicts not handled
- Blocks: Mobile app development would be difficult
## Test Coverage Gaps
**No Unit Tests:**
- What's not tested: All business logic, date calculations, budget math, filter/reduce operations
- Files: `src/hooks/`, `src/lib/`
- Risk: Regression in calculation logic could go unnoticed (e.g., budget overage math, currency rounding)
- Priority: High - calculation errors directly impact financial data
**No Integration Tests:**
- What's not tested: Mutation sequences, error recovery, cache invalidation, query dependencies
- Files: All pages that use multiple mutations
- Risk: Race conditions and inconsistent state when multiple operations happen quickly
- Priority: High - production data corruption risk
**No Component Tests:**
- What's not tested: Inline edit cells, modal state management, form validation, error states
- Files: `src/pages/BudgetDetailPage.tsx`, `src/components/QuickAddPicker.tsx`
- Risk: UI behavior breaks silently (e.g., edit not saving, delete confirmation not working)
- Priority: Medium - affects user experience
**No E2E Tests:**
- What's not tested: Complete user workflows (login → create budget → add items → view dashboard)
- Risk: Critical paths fail only in production
- Priority: Medium - would catch integration failures early
**No Error Path Testing:**
- What's not tested: Network errors, auth failures, database errors, invalid data
- Files: All mutation handlers use generic toast.error() without specific handling
- Risk: Users see unhelpful error messages, cannot recover gracefully
- Priority: Medium - impacts user experience and debugging
---
*Concerns audit: 2026-03-16*