Add comprehensive offline synchronization support for habits and entries:
## Infrastructure (Phase 1)
- Add UpdatedAt and DeletedAt timestamps to Habit and HabitEntry entities
- Implement soft delete with Delete(), Touch(), and IsDeleted() methods
- Create SQL migration with optimized composite indexes for sync queries
- Add GetChangesSince() and SoftDelete() to both repositories
- Update all Find* methods to exclude soft-deleted records
- 13 comprehensive TDD tests for sync repository methods
## HTTP Endpoints (Phase 2)
- GET /api/v1/sync/changes: retrieve all changes since timestamp
- POST /api/v1/sync/batch: apply client changes with conflict resolution
- Implement Last-Write-Wins strategy using UpdatedAt timestamps
- Add authentication and rate limiting (100 req/min)
- Validate user ownership for all sync operations
- 9 tests for sync handlers (3 queries + 6 commands)
## Technical Details
- Composite indexes: (user_id, updated_at) for optimal query performance
- No pagination: atomic sync operations for data consistency
- Upsert behavior: create resources if not found on server
- DTOs with full entity state including timestamps
- Swagger documentation updated for new endpoints
All 220+ tests passing ✓
Implemented comprehensive filtering capabilities for the habits list endpoint:
- Filter by type (BOOLEAN, COUNTER, VALUE)
- Filter by frequency (DAILY, WEEKLY, MONTHLY)
- Filter by archived status
- Text search in habit name and description
- All filters can be combined
- Filters work with pagination
Technical changes:
- Added FilterParams to GetUserHabitsQuery
- Created HabitFilter struct in repository interface
- Implemented dynamic SQL query building in SQLite repository
- Updated HTTP handler to parse filter query parameters
- Added comprehensive tests for repository and handler filtering
- Updated all test mocks with new filter methods
- Create pagination package with Params and Response structs
- Add FindActiveByUserIDWithPagination and CountActiveByUserID methods to HabitRepository interface
- Implement pagination in SQLite repository using LIMIT and OFFSET
- Update GetUserHabitsHandler to support optional pagination parameters
- Modify HTTP endpoint to parse 'page' and 'page_size' query params (default: page=1, page_size=50, max=100)
- Add GetUserHabitsResponse DTO with pagination metadata
- Maintain backward compatibility - endpoint works with and without pagination params
- Add comprehensive tests for pagination logic in repository, handler, and pagination package
- Update all mock repositories to implement new pagination methods
Add user-based rate limiting middleware (100 req/min) for authenticated endpoints using httprate library. Implement common password validation blocking 50+ weak passwords. Improve test coverage from 38.3% to 44.6% with comprehensive refresh token tests.
Security improvements:
- Rate limiting by user ID for /habits and /stats endpoints
- X-RateLimit-Limit header in responses
- Common password blacklist in password validation
- Refresh token test suite with 5 scenarios (valid, invalid, expired, revoked, empty)
COUNTER type:
- Only accepts integer values (rejects decimals)
- Auto-increment behavior: each mark adds to existing value
- Supports decrement via negative values (e.g., -2)
- Enforces minimum value of 0 (never negative)
- Default increment is 1 if no value provided
VALUE type:
- Accepts decimal values
- Replaces value (no auto-increment)
IsNegative field:
- New boolean field on Habit entity
- Persisted in database (is_negative column)
- Available in all DTOs and HTTP responses
- Marks habits as "negative" (e.g., candy consumption)
Examples:
- COUNTER: 5 + (-2) = 3, 2 + (-3) = 0, 0 + (-1) = 0
- VALUE: 5000 → 12000 = 12000 (replacement)
Clean up obvious and redundant comments that don't add value:
- Remove step-by-step comments in command handlers
- Remove obvious test setup comments
- Keep only meaningful comments that explain why, not what
Remove soft delete from HabitEntry:
- Eliminate DeletedAt field from entity and database
- Change UnmarkHabit from soft delete to hard delete
- Simplify all queries removing deleted_at checks
- Update migration to remove deleted_at column
Add date filtering and smart pagination to GetHabitEntries:
- Support optional from/to date parameters
- Implement intelligent pagination rules:
* No date range: pagination required
* Date range > 1 year: pagination required
* Date range ≤ 1 year: pagination optional
- Pagination defaults (page=1, limit=50) only when required
- Return metadata with total count, page, and limit
Technical improvements:
- Cleaner codebase without soft delete complexity
- Better performance (no filtering in queries)
- More intuitive API with flexible pagination
- Comprehensive test coverage for validation rules
Implement all missing endpoints for full habit management:
- GET /api/v1/habits - List all user habits
- GET /api/v1/habits/{id} - Get specific habit
- PUT /api/v1/habits/{id} - Update habit
- DELETE /api/v1/habits/{id} - Archive habit (soft delete)
- GET /api/v1/habits/{id}/entries - Get habit entry history
- DELETE /api/v1/habits/{id}/entries/{date} - Unmark habit (soft delete entry)
All endpoints include:
- TDD approach with comprehensive test coverage
- JWT authentication and ownership validation
- Proper error handling (404, 403, 400, 500)
- Clean architecture with separated commands/queries