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
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)
Update module name and all imports from habit-tracker-api to apocapoc-api.
This reflects the project's new branding as part of the apocapoc ecosystem
(apocapoc-api, apocapoc-web, apocapoc-android).
- Add date utilities for habit scheduling logic
- Implement CreateHabitHandler with full validation
- Implement GetTodaysHabitsHandler with carry-over support
- Implement MarkHabitHandler for completing habits
- All components developed following TDD methodology
- Complete test coverage for commands and queries