Add CLAUDE.md documentation for Claude Code

Provides comprehensive guidance for future Claude Code instances including development commands, architecture overview, and common patterns.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Keith Smith
2026-02-03 16:52:04 -07:00
co-authored by Claude Sonnet 4.5
parent 7b4d024334
commit cdcae378b7
+446
View File
@@ -0,0 +1,446 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Development Commands
### Local Development (Non-Docker)
```bash
# Set environment for development
export DJANGO_SETTINGS_MODULE=config.settings.development
# Create and activate virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Database operations
python manage.py migrate
python manage.py makemigrations
python manage.py createsuperuser
# Run development server
python manage.py runserver
# Run tests
python manage.py test
# Django shell
python manage.py shell
# Collect static files (for production)
python manage.py collectstatic --noinput
```
### Docker Development
```bash
# Development with live reload
make dev
make dev-build # Rebuild containers
# Production mode
make prod
make build # Build production containers
make deploy # Full deployment (pull, build, migrate, restart)
# Database operations
make migrate
make makemigrations
make createsuperuser
make dbshell # Access database shell
make backup # Backup database
# Monitoring
make logs # All container logs
make logs-web # Web container logs only
make logs-celery # Celery worker logs
make status # Container status
# Control
make stop
make restart
make clean # Stop and remove all containers/volumes
# Shell access
make shell # Django shell
make test # Run tests in container
```
### Celery (Background Tasks)
```bash
# Local development (non-Docker)
# Terminal 1: Run Celery worker
celery -A config worker -l info
# Terminal 2: Run Celery beat (scheduled tasks)
celery -A config beat -l info
# In Docker, Celery runs automatically as separate services
```
## High-Level Architecture
### Django Apps
**users/** - User authentication and management
- Custom User model with email-based authentication (no username)
- Three-tier verification: email verification → admin approval → login
- JWT token authentication with refresh tokens
- Device token management for push notifications
- Rate-limited registration (5/hour) and login (10/hour)
**tasks/** - Core task management
- Hierarchical tasks with parent/subtask relationships
- Task status (pending, in_progress, completed, cancelled) and priority (low, medium, high, urgent)
- Recurrence patterns (daily, weekly, monthly, yearly, custom RRULE)
- Time tracking with start/stop timer functionality
- Tag system with colors and icons for organization
- Task sharing with permission levels (viewer/editor)
- Soft-delete architecture (is_deleted flag) for sync compatibility
**sync/** - Mobile app synchronization
- Offline-first bidirectional sync protocol
- Timestamp-based conflict detection with three resolution strategies (local, server, merged)
- Multi-device support with independent sync tokens per device
- Incremental sync (delta updates) and full sync support
- Uses sync_id (UUID) separate from Django id for mobile compatibility
- Soft-delete propagation to enable client-side deletion
**notifications/** - Email notifications and reminders
- Daily email digest (overdue + due today tasks)
- Timezone-aware scheduling (6-7 AM in user's local time)
- Deduplication (one email per user per day)
- Celery-based background processing
- Recurring task safety net (creates missed recurrences)
### Key Architectural Patterns
**UUID Primary Keys** - All models use UUID as primary key for distributed system compatibility and security.
**Dual ID System** - Each entity has both `id` (Django PK) and `sync_id` (for mobile sync). Sync protocol uses `sync_id` to maintain consistency across devices.
**Soft Delete Pattern** - All entities have `is_deleted` boolean instead of hard deletes. Dual managers enable filtering:
- `objects` - Default manager (excludes deleted)
- `all_objects` - Includes deleted items (used in sync)
**Multiple Serializers Per Context** - Different serializers for list/detail/sync endpoints to optimize performance:
- `TaskListSerializer` - Lightweight for list views
- `TaskSerializer` - Full details with nested subtasks
- `TaskSyncSerializer` - Uses sync_id, includes is_deleted
**Permission System** - Custom `IsOwnerOrReadOnlyIfShared` permission:
- Read access: Owner OR users with shared access
- Write access: Owner only
- Security filtering in serializers prevents tag/task leakage
**Custom Authentication Backend** - `EmailVerifiedApprovedBackend` enforces:
1. Email verification check
2. Admin approval check
3. Superusers bypass both checks
4. Stores error state in session for web UI
**Timezone-Aware Operations** - All time calculations use user's timezone:
- Daily emails scheduled in user's local 6-7 AM
- Overdue calculation relative to user's local date
- UTC storage, converted for display and logic
**Mobile App Support** - `AllowMobileAppFramingMiddleware` detects mobile app via User-Agent and removes X-Frame-Options to allow WebView embedding while maintaining security for web browsers.
### Sync Protocol Details
The sync endpoint (`POST /api/sync/`) handles offline-first synchronization:
**Request Format:**
```json
{
"device_id": "unique-device-id",
"last_sync_token": "previous-token-or-null",
"changes": {
"tasks": [...],
"tags": [...],
"time_entries": [...]
}
}
```
**Response Format:**
```json
{
"sync_token": "new-sync-token",
"server_time": "2025-01-10T12:00:00Z",
"server_changes": {
"tasks": [...],
"tags": [...],
"time_entries": [...]
},
"conflicts": [...]
}
```
**Conflict Detection:** Compares `updated_at` timestamp between client's last sync and server's current state. If server modified entity since last sync, conflict is flagged.
**Conflict Resolution Strategies:**
- **local** - Apply client changes (overwrite server)
- **server** - Keep server version (discard client)
- **merged** - Accept manually merged data
### Celery Task Schedule
Configured in `config/celery.py`:
**send_daily_task_email** - Runs every hour
- Fetches users with email notifications enabled
- Converts UTC to user's timezone
- Sends email only if user's local time is 6-7 AM
- Checks for existing notification to prevent duplicates
- Groups tasks: overdue + due today (pending/in_progress only)
**process_recurring_tasks** - Runs daily at midnight
- Safety net for recurring task creation
- Processes completions from last 48 hours
- Creates next recurrence if missing
- Prevents duplicate recurrences
### Settings Modules
**config.settings.development** - Local development
- DEBUG=True
- SQLite database
- Console email backend
- Minimal security
**config.settings.production** - Production deployment
- DEBUG=False
- PostgreSQL required
- SMTP email backend
- Full security (HTTPS, CSP, HSTS)
- Gunicorn with multiple workers
**config.settings.selfhosted** - Docker/self-hosted
- Environment-based configuration
- PostgreSQL with health checks
- Redis for Celery
- Configurable workers and timeout
- WhiteNoise for static files
### Database Models Reference
**Task Model Fields:**
- Hierarchy: `parent` (ForeignKey to self)
- Status: pending, in_progress, completed, cancelled
- Priority: low, medium, high, urgent
- Recurrence: `recurrence_type`, `recurrence_interval`, `recurrence_rule` (RRULE)
- Timing: `due_date`, `due_time`, `completed_at`, `created_at`, `updated_at`
- Soft delete: `is_deleted` (filters via `SoftDeleteManager`)
- Sync: `sync_id` (UUID for mobile sync)
- Relationships: `tags` (ManyToMany), `time_entries` (reverse FK)
**User Model Fields:**
- Authentication: `email` (unique), `password`, `first_name`, `last_name`
- Verification: `email_verified`, `is_approved`, `approved_by`
- Preferences: `timezone`, `reminder_minutes_before`, `notifications_enabled`, `email_notifications_enabled`
- UUID primary key for security
**TimeEntry Model:**
- `start_time`, `end_time`, `duration` (auto-calculated)
- Foreign keys: `task`, `user`
- Soft delete: `is_deleted`
**TaskShare Model:**
- `shared_by`, `shared_with` (User FKs)
- `permission_level`: viewer, editor
- Can share tasks or tags
- Generic relation pattern
### API Endpoint Overview
**Authentication:**
- `POST /api/users/register/` - Create account (rate limited 5/hour)
- `POST /api/users/token/` - Login (rate limited 10/hour)
- `POST /api/users/token/refresh/` - Refresh JWT
- `POST /api/users/verify-email/` - Verify email token
- `POST /api/users/resend-verification/` - Resend verification email
**Tasks:**
- `GET/POST /api/tasks/` - List/create tasks (supports filtering by status, priority, tags, search)
- `GET/PUT/DELETE /api/tasks/<id>/` - Task detail operations
- `POST /api/tasks/<id>/start-timer/` - Start time tracking
- `POST /api/tasks/time-entries/<id>/stop/` - Stop timer
- `GET/POST /api/tasks/tags/` - Tag management
- `GET/POST /api/tasks/shares/` - Share management
**Sync:**
- `POST /api/sync/` - Main sync endpoint (rate limited 100/hour)
- `GET /api/sync/conflicts/` - List pending conflicts
- `POST /api/sync/conflicts/<id>/resolve/` - Resolve conflict
**Notifications:**
- `GET /api/notifications/` - List notifications
- `POST /api/notifications/<id>/read/` - Mark as read
- `POST /api/notifications/mark-all-read/` - Mark all read
- `GET /api/notifications/unread-count/` - Get unread count
### Environment Variables
Key variables (see `.env.example` and `stack.env.example`):
**Django Core:**
- `SECRET_KEY` - Django secret (generate with `python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"`)
- `DEBUG` - Debug mode (False in production)
- `ALLOWED_HOSTS` - Comma-separated hosts
- `CSRF_TRUSTED_ORIGINS` - HTTPS origins
- `SITE_DOMAIN` - Domain for email links
**Database:**
- `DATABASE_URL` - Connection string (e.g., `postgresql://user:pass@host:5432/db`)
**Redis & Celery:**
- `REDIS_URL` - Redis connection (e.g., `redis://localhost:6379/0`)
**Email:**
- `EMAIL_HOST`, `EMAIL_PORT`, `EMAIL_USE_TLS`
- `EMAIL_HOST_USER`, `EMAIL_HOST_PASSWORD`
- `DEFAULT_FROM_EMAIL` - Sender address
- `EMAIL_VERIFICATION_TOKEN_EXPIRY_HOURS` - Token validity (default: 24)
**Docker/Gunicorn:**
- `GUNICORN_WORKERS` - Worker processes (default: 3)
- `GUNICORN_TIMEOUT` - Request timeout (default: 60)
- `WEB_PORT` - External port (default: 8000)
### Testing
Tests located in each app's `tests.py`. Run with:
```bash
python manage.py test # All tests
python manage.py test users # Specific app
python manage.py test users.tests.TestUserModel # Specific test
```
Docker:
```bash
make test # Run tests in container
```
### Deployment Notes
**Docker Deployment:**
- Production uses PostgreSQL (postgres:16-alpine)
- Redis for Celery message broker (redis:7-alpine)
- Web service runs Gunicorn with configurable workers
- Celery worker and beat run as separate services
- Health checks on all services
- Named volumes for persistence (db_data, redis_data, static_files)
- Networks: frontend (web-facing), backend (internal services)
**Manual Deployment:**
- Use `config.settings.production` settings module
- Requires PostgreSQL (not SQLite)
- Configure SMTP for email
- Use Gunicorn behind Nginx reverse proxy
- Set up systemd services for Gunicorn, Celery worker, Celery beat
- Configure SSL/TLS certificates (Let's Encrypt recommended)
- Enable firewall (UFW) with SSH, HTTP, HTTPS only
**Production Checklist:**
- Set DEBUG=False
- Use strong SECRET_KEY
- Configure ALLOWED_HOSTS (no wildcards)
- Set CSRF_TRUSTED_ORIGINS for HTTPS
- Use PostgreSQL (not SQLite)
- Configure email backend (SMTP)
- Enable security headers (in settings)
- Set up SSL/TLS certificates
- Configure database backups
- Set up log rotation
- Monitor error logs and uptime
### Common Development Patterns
**Creating Recurring Tasks:** When a recurring task is marked complete, the next recurrence is automatically created in `tasks/models.py` `create_next_recurrence()` method. Celery task `process_recurring_tasks()` runs as safety net.
**Time Entry Workflow:**
1. `POST /api/tasks/<id>/start-timer/` creates TimeEntry with start_time
2. Running timer tracked in UI
3. `POST /api/time-entries/<id>/stop/` sets end_time and calculates duration
**Email Verification Flow:**
1. User registers → `email_verified=False`, `is_approved=False`
2. EmailVerificationToken created with 24-hour expiry
3. User clicks link → `email_verified=True`, token marked used
4. Admins notified via email
5. Admin approves in Django admin → `is_approved=True`
6. User notified and can now login
**Adding New Celery Tasks:**
1. Create task function in app's `tasks.py` with `@shared_task` decorator
2. Add to beat schedule in `config/celery.py` if periodic
3. Import in app's `__init__.py` to ensure task registration
4. Restart Celery worker and beat services
**Extending User Model:** The User model is in `users/models.py`. Add fields there, create migration, update serializers and admin if needed.
**Security Filtering:** When adding new endpoints that query related objects, filter by user in viewset's `get_queryset()`. Example from TaskViewSet:
```python
def get_queryset(self):
return Task.objects.filter(user=self.request.user)
```
### File Structure Reference
```
config/ # Django project configuration
settings/ # Environment-specific settings
base.py # Shared settings
development.py # Local development
production.py # Production deployment
selfhosted.py # Docker/self-hosted
celery.py # Celery configuration
urls.py # Root URL configuration
wsgi.py # WSGI entry point
users/ # User management app
models.py # User, DeviceToken, EmailVerificationToken
views.py # Registration, login, profile
serializers.py # User serializers
backends.py # EmailVerifiedApprovedBackend
utils.py # Email utilities
tasks/ # Task management app
models.py # Task, Tag, TimeEntry, TaskShare
views.py # Task CRUD, filtering, timers
serializers.py # Multiple serializers per context
middleware.py # AllowMobileAppFramingMiddleware
permissions.py # IsOwnerOrReadOnlyIfShared
sync/ # Mobile sync app
models.py # SyncLog, SyncConflict
views.py # Sync endpoint, conflict resolution
serializers.py # SyncSerializer with sync_id
notifications/ # Notifications app
models.py # Notification, ScheduledReminder
views.py # Notification CRUD
tasks.py # Celery tasks (daily email, recurring tasks)
templates/ # Django templates
base.html # Base template with dark mode
tasks/ # Task-related templates
users/ # User-related templates
static/ # Static assets
css/ # Stylesheets
js/ # JavaScript
docker/ # Docker-related files
docker-compose.yml # Production Docker setup
docker-compose.dev.yml # Development overrides
Dockerfile # Production image
Dockerfile.dev # Development image
Makefile # Docker command shortcuts
```