Commit Graph
68 Commits
Author SHA1 Message Date
Keith SmithandClaude Sonnet 4.5 f2ca07d05d Fix overdue calculation to use user's timezone
Tasks were incorrectly showing as overdue when they were due today.
The issue was that the overdue check was comparing the due date
against UTC's "today" instead of the user's local "today".

Now uses the user's timezone setting to determine the current date
when checking if a task is overdue. This ensures tasks due "today"
only become overdue when the user's local date advances to tomorrow.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 08:28:59 -07:00
Keith SmithandClaude Sonnet 4.5 c994458e24 Fix priority sorting to use correct order
Previously priority sorting was alphabetical (high < low < medium < urgent)
instead of by importance. Now uses Django Case/When to map priority strings
to numeric values: urgent=4, high=3, medium=2, low=1.

Fixes both queryset sorting and list sorting for overdue filter.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 08:23:07 -07:00
Keith SmithandClaude Sonnet 4.5 5985fd010e Fix Chromium scrollbar styling to match dark theme
Add custom scrollbar styles for Chromium/Webkit browsers to match the
dark theme aesthetic. Firefox already had proper scrollbar styling, but
Chrome was showing default light gray scrollbars.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 08:18:13 -07:00
Keith SmithandClaude Sonnet 4.5 1d6b07bfed Implement recurring tasks functionality
Adds automatic creation of next task instance when recurring tasks are completed.

- Add calculate_next_due_date() and create_next_recurrence() methods to Task model
- Update task completion handlers in views and sync API to create next recurrence
- Add hourly Celery task to process any missed recurring tasks
- Support daily, weekly, biweekly, monthly, yearly recurrence patterns
- Respect recurrence_end_date limits

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-04 10:00:34 -07:00
Keith Smith c51fd846a2 Fix mobile sidebar background - use --surface like desktop 2025-12-27 08:58:36 -07:00
Keith Smith fcb5ab5ca3 Make mobile overlay transparent - sidebar slides over content without darkening 2025-12-27 08:56:57 -07:00
Keith Smith fc1a4844a3 Remove mobile sidebar overlay transparency - make fully opaque 2025-12-27 08:55:37 -07:00
Keith SmithandClaude Sonnet 4.5 7f2096db86 Increase mobile sidebar overlay opacity
Changed mobile overlay from 50% to 75% opacity (25% transparent)
to make the sidebar content more visible when open on mobile devices.

Updated rgba(0, 0, 0, 0.5) to rgba(0, 0, 0, 0.75)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 08:53:18 -07:00
Keith Smith ea40beb408 Update debug endpoint to show User-Agent detection in HTML 2025-12-26 22:31:25 -07:00
Keith SmithandClaude Sonnet 4.5 123d6af430 Update middleware to ADD security headers for browsers
Middleware now:
- Detects mobile app vs browser via User-Agent
- Mobile app: Removes frame-blocking headers (allows iframe)
- Browsers: Adds CSP and X-Frame-Options headers (security)

This ensures:
✓ Browsers get full CSP protection
✓ Mobile app can embed content
✓ No need for django-csp package
✓ All security managed in one place

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 22:29:00 -07:00
Keith SmithandClaude Sonnet 4.5 c686021f96 Fix middleware to also remove CSP frame-ancestors header
The CSP_FRAME_ANCESTORS = ("'none'",) setting in production.py was
blocking iframe embedding even after removing X-Frame-Options.

Updated middleware to:
- Detect Android WebView via 'wv' in User-Agent (more reliable)
- Remove both X-Frame-Options AND Content-Security-Policy headers
- This allows mobile app iframe embedding while keeping browser protection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 22:18:03 -07:00
Keith Smith 41abdf4074 Add debug endpoint to check mobile app User-Agent 2025-12-26 22:13:07 -07:00
Keith SmithandClaude Sonnet 4.5 31a0c3c8c5 Add middleware to allow mobile app iframe embedding
Created Django middleware that detects requests from the KeepItGoing
mobile app (via User-Agent) and removes X-Frame-Options header to
allow iframe embedding.

Changes:
- Created tasks/middleware/mobile_app.py with AllowMobileAppFramingMiddleware
- Added middleware to settings after XFrameOptionsMiddleware
- Detects Capacitor WebView User-Agent patterns
- Removes X-Frame-Options only for mobile app, keeps protection for browsers

This allows the mobile app to embed the website in an iframe while
maintaining clickjacking protection for regular web browsers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 22:08:05 -07:00
Keith SmithandClaude Sonnet 4.5 8db9f99701 CRITICAL FIX: Override .detail-closed specificity at mobile
Root cause: The .app-layout.detail-closed class (2-class specificity)
was overriding .app-layout (1-class specificity) at mobile, creating
a 3-column grid "0 1fr 0" instead of single column "1fr".

The task-pane was placed in column 1 (0 width), making it invisible.

Fix: Explicitly override both .app-layout and .app-layout.detail-closed
with equal specificity in the 768px breakpoint.

Cache bust: v=6

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 21:33:11 -07:00
Keith SmithandClaude Sonnet 4.5 8b71447024 Fix task pane layout at mobile - add explicit grid positioning
The task-pane was not displaying at mobile because it lacked explicit
grid positioning and width constraints. Added:
- grid-row: 2 and grid-column: 1 for explicit placement
- width: 100%, min-width: 0, max-width: 100% to ensure full width
- Moved header grid positioning into mobile breakpoint for clarity

Also updated header to have explicit grid-row: 1 positioning.

Cache bust: v=5

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 21:30:06 -07:00
Keith SmithandClaude Sonnet 4.5 f836769ad7 CRITICAL FIX: Move base CSS before media queries
The sidebar-toggle and mobile-overlay base definitions were placed
AFTER the media queries, causing them to override the responsive
styles. This prevented the hamburger menu from showing and broke
the sidebar drawer functionality.

Fixed by moving base definitions before the Mobile Responsive section.

CSS order is now correct:
1. Base styles (display: none for sidebar-toggle)
2. Media queries (display: flex at 768px)

This allows the media query to properly override the base style.

Updated cache version to v=4.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 21:18:14 -07:00
Keith SmithandClaude Sonnet 4.5 d83b1e3091 Fix mobile header layout - remove vertical stacking
The flex-direction: column on header-user was causing buttons to
overflow outside the header bar. Changed approach to keep buttons
horizontal but make them smaller on very small screens.

Changes:
- Removed flex-direction: column from 480px breakpoint
- Keep buttons horizontal with smaller font size
- Reduced button min-height to 36px on small screens
- Reduced touch targets slightly (40px) for very small screens
- Smaller brand font size (0.9rem)

Updated cache version to v=3 to force reload.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 21:14:30 -07:00
Keith Smith e038e47247 Add cache busting to CSS for mobile updates 2025-12-26 21:07:07 -07:00
Keith SmithandClaude Sonnet 4.5 d5010580a4 Implement mobile responsive design improvements
Fixed critical mobile layout issues on phones (400-600px width):

Header improvements:
- Hide email on mobile to save space
- Compact user menu layout
- Adjust brand font size for mobile
- Better spacing with adjusted padding

Sidebar drawer fixes:
- Properly hide sidebar off-screen (translateX(-100%))
- Increase z-index to 100 for proper layering
- Add background and shadow for drawer effect
- Wider drawer (280px) for better touch targets

Touch target improvements:
- All buttons minimum 44px height (Apple HIG standard)
- Larger touch areas for sidebar toggle and theme toggle
- Improved checkbox sizing (24px)

Task list mobile optimization:
- Smaller fonts for tags and priority badges
- Text ellipsis for long tag names
- Better wrapping for task metadata
- Reduced padding for mobile screens

Modal and form improvements:
- Full-width detail pane on mobile
- Responsive modal sizing (95% width, max 400px)
- Better form field spacing

New 480px breakpoint:
- Ultra-small phone optimization
- Vertical stack for Profile/Logout buttons
- Further reduced font sizes and padding

Mobile utility classes:
- .mobile-only / .desktop-only for conditional display
- .mobile-full-width for full-width elements

All changes are CSS-only, no JavaScript modifications needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 21:01:17 -07:00
Keith SmithandClaude Sonnet 4.5 52277d6687 Add favicon to web application
Added SVG favicon based on KeepItGoing app icon (white checkmark on
blue #3B82F6 background). Favicon displays in browser tabs and bookmarks.

Changes:
- Created static/favicons/favicon.svg with app icon design
- Updated templates/base.html with favicon link tags

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 20:09:41 -07:00
Keith SmithandClaude Sonnet 4.5 f7586f2a93 Fix pip upgrade to install in user directory
Changed pip upgrade to use --user flag so the upgraded pip is
installed to /root/.local and gets copied to the runtime stage.

Previous version upgraded pip globally in builder stage but runtime
stage was still using base image's pip (25.0.1). Now the upgraded
pip is in .local/bin which is in the PATH in the runtime container.

This fixes CVE-2025-8869 in pip.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 18:32:55 -07:00
Keith SmithandClaude Sonnet 4.5 4a6b9a991f Upgrade pip during Docker build to fix CVE-2025-8869
Added pip upgrade step in Dockerfile builder stage to ensure latest
pip version is used. This fixes CVE-2025-8869 vulnerability found in
pip 25.0.1 (fixed in 25.3).

pip-audit output before fix:
  Found 1 known vulnerability in 1 package
  Name Version ID            Fix Versions
  pip  25.0.1  CVE-2025-8869 25.3

After rebuilding, pip will be upgraded to 25.3+ which resolves the
security vulnerability.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 18:20:52 -07:00
Keith SmithandClaude Sonnet 4.5 de57befe3a Restore Django security headers for defense-in-depth
Re-added SECURE_CONTENT_TYPE_NOSNIFF and SECURE_BROWSER_XSS_FILTER
to Django settings. These don't conflict with NPM's "Block Common
Exploits" feature - they provide defense-in-depth by ensuring headers
are set even if the request bypasses NPM.

Security header strategy:
- NPM (primary): CSP, HSTS, Referrer-Policy, Permissions-Policy,
  X-Content-Type-Options, X-XSS-Protection via "Block Common Exploits"
- Django (backup): X-Frame-Options, X-Content-Type-Options,
  X-XSS-Protection for defense-in-depth

This follows security best practice of setting headers at multiple
layers rather than relying on a single point of control.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 18:17:34 -07:00
Keith SmithandClaude Sonnet 4.5 240a4de7ac Remove duplicate security headers - handled by NPM
Removed SECURE_CONTENT_TYPE_NOSNIFF and SECURE_BROWSER_XSS_FILTER
from Django settings to prevent duplicate headers. These headers are
now exclusively managed in Nginx Proxy Manager's Advanced config.

This fixes Mozilla Observatory error: "X-Content-Type-Options header
cannot be recognized" which was caused by the header being sent twice
(once from Django, once from NPM).

Security headers now managed in NPM:
- Content-Security-Policy
- X-Content-Type-Options
- X-XSS-Protection
- Referrer-Policy
- Permissions-Policy

X-Frame-Options kept in Django for defense-in-depth (doesn't conflict).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 18:13:32 -07:00
Keith SmithandClaude Sonnet 4.5 5e2b13afe3 Add pip-audit for security vulnerability scanning
Added pip-audit to scan Python dependencies for known CVEs and
security vulnerabilities. This tool checks installed packages
against vulnerability databases and reports any issues.

Usage after deploying:
  docker exec keepitgoing-web pip-audit

Recommended to run monthly or before major updates to identify
packages that need security patches.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 18:06:52 -07:00
Keith SmithandClaude Sonnet 4.5 ec09baf9a5 Remove django-csp package - CSP now handled by NPM
Since Nginx Proxy Manager is handling Content Security Policy headers
at the reverse proxy level, removed django-csp from Django to avoid
duplication and simplify configuration.

Changes:
- Removed django-csp from requirements.txt
- Removed CSPMiddleware from middleware stack
- Removed CSP_* settings from selfhosted.py
- Added comment noting CSP is configured in NPM

CSP is now exclusively managed in NPM's Advanced configuration with:
- default-src 'self'
- script-src/style-src 'self' 'unsafe-inline' (for Django admin)
- img-src 'self' data: https:
- frame-ancestors 'none'
- And other security directives

This keeps configuration in one place (NPM) and eliminates
dependency on django-csp package.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:59:31 -07:00
Keith SmithandClaude Sonnet 4.5 e95369ffbf Add Content Security Policy (CSP) headers
Implements CSP to prevent XSS attacks and complete Mozilla Observatory
security requirements.

Changes:
- Added django-csp>=3.8 to requirements.txt
- Added CSPMiddleware to middleware stack
- Configured CSP directives in selfhosted.py:
  - default-src 'self' (only load resources from same origin)
  - script-src/style-src allow 'unsafe-inline' (needed for Django admin)
  - img-src allows https: and data: URIs
  - frame-ancestors 'none' (prevent clickjacking)
  - form-action 'self' (prevent form hijacking)

This policy balances security with Django admin functionality.
After deployment, Mozilla Observatory should show all green checks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:40:34 -07:00
Keith SmithandClaude Sonnet 4.5 00fca071bf Silence Django security warnings handled by NPM
Added SILENCED_SYSTEM_CHECKS to suppress warnings for:
- security.W004: HSTS (handled by NPM with HSTS Enabled)
- security.W008: SSL redirect (handled by NPM with Force SSL)

These warnings are intentionally suppressed because the security
features are properly configured at the reverse proxy level.

After redeploying, 'manage.py check --deploy' will show:
"System check identified no issues (0 silenced)."

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:36:13 -07:00
Keith SmithandClaude Sonnet 4.5 19ff672562 Update security settings for NPM SSL/HSTS handling
Since Nginx Proxy Manager handles SSL termination, Force SSL, and HSTS:
- Set SECURE_HSTS_SECONDS = 0 (NPM sends HSTS headers)
- Added SECURE_PROXY_SSL_HEADER to trust X-Forwarded-Proto from NPM
- Added SESSION_COOKIE_HTTPONLY for additional session security
- Documented NPM configuration: Force SSL = On, HSTS Enabled = On

This prevents duplicate HSTS headers and ensures Django correctly
detects HTTPS connections behind the reverse proxy.

Cookie security (SESSION/CSRF_COOKIE_SECURE) remains enabled as these
are application-level settings independent of the reverse proxy.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:34:03 -07:00
Keith SmithandClaude Sonnet 4.5 a06b4365ed Add production security settings for HTTPS/SSL
Fixes all 4 Django security warnings:
-  security.W004: Added SECURE_HSTS_SECONDS (1 year HSTS)
-  security.W008: Documented SECURE_SSL_REDIRECT=False (NPM handles SSL)
-  security.W012: Enabled SESSION_COOKIE_SECURE
-  security.W016: Enabled CSRF_COOKIE_SECURE

Additional security hardening:
- HSTS with subdomains and preload
- HttpOnly CSRF cookies
- XSS filter enabled
- Content type sniffing prevention
- Clickjacking protection (X-Frame-Options: DENY)

Note: SECURE_SSL_REDIRECT is intentionally False because Nginx Proxy
Manager handles SSL termination and HTTP→HTTPS redirects at the
reverse proxy level.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:33:07 -07:00
Keith SmithandClaude Sonnet 4.5 ab06bc4fc9 Add API root endpoint for /api/users/
Added UsersAPIRoot view that returns available user-related
endpoints when accessing /api/users/ directly.

All API endpoint groups now have discoverable root endpoints:
- /api/ - Main API root
- /api/users/ - User endpoints
- /api/tasks/ - Task endpoints (already had TaskListCreateAPIView)
- /api/sync/ - Sync endpoints (already had sync view)
- /api/notifications/ - Notification endpoints (already had NotificationListAPIView)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:26:50 -07:00
Keith SmithandClaude Sonnet 4.5 d1720bebb3 Add API root endpoint at /api/
Created /api/ endpoint that returns JSON with:
- API status
- Available endpoints
- Version information

This fixes the "Not Found" error when accessing /api/ and
provides a useful API discovery endpoint for clients.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:24:16 -07:00
Keith SmithandClaude Sonnet 4.5 6eb277c701 Fix authentication: allow superusers to bypass email verification and approval
The authentication backend was requiring ALL users (including superusers)
to have email_verified=True and is_approved=True. This created a
chicken-and-egg problem where the first superuser couldn't log in to
approve themselves.

Now superusers bypass these checks and can log in immediately after
creation via createsuperuser command. Regular users still require
email verification and admin approval.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:14:46 -07:00
Keith SmithandClaude Sonnet 4.5 0459ab7456 Update docker-compose.yml with all environment variables and PostgreSQL
Major changes:
- Switch from MariaDB to PostgreSQL 16
- Add all required environment variables to web service:
  - SECRET_KEY, DEBUG, ALLOWED_HOSTS
  - CSRF_TRUSTED_ORIGINS, CORS_ALLOWED_ORIGINS
  - Email configuration (HOST, PORT, USER, PASSWORD, TLS)
  - Gunicorn settings (WORKERS, TIMEOUT)
- Add SECRET_KEY to celery services (required for Django)
- Update all services to depend on 'postgres' instead of 'mariadb'
- Update DATABASE_URL to use PostgreSQL format
- Update .env.docker.example to reflect PostgreSQL and add WEB_PORT

All environment variables now properly declared in compose file
with ${VAR} syntax for Portainer/Docker compatibility.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:13:12 -07:00
Keith SmithandClaude Sonnet 4.5 695109e447 Add CSRF_TRUSTED_ORIGINS setting for self-hosted deployments
Django requires CSRF_TRUSTED_ORIGINS to be set for POST requests
(including login) when using HTTPS or non-standard ports. Without
this setting, login attempts fail with "CSRF verification failed".

The setting is now configurable via CSRF_TRUSTED_ORIGINS environment
variable, similar to CORS_ALLOWED_ORIGINS.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:10:14 -07:00
Keith SmithandClaude Sonnet 4.5 0cb1e9508f Fix PostgreSQL compatibility in migrations
- tasks.0002_initial: Remove duplicate user field on Tag model
- tasks.0005_fix_tasks_tags_table: Add PostgreSQL/MySQL/SQLite support
  - Use SERIAL instead of AUTOINCREMENT for PostgreSQL
  - Use UUID type for foreign keys in PostgreSQL
- tasks.0006_fix_task_shares_table: Add PostgreSQL/MySQL/SQLite support
  - Use UUID type and TIMESTAMP in PostgreSQL
  - Use CHAR(32) and DATETIME in MySQL/SQLite

These migrations now detect the database backend and use appropriate
syntax for each database type.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:05:33 -07:00
Keith SmithandClaude Sonnet 4.5 4e903b688d Fix duplicate user field in tasks migration
Remove duplicate AddField operation for tag.user field in
tasks/migrations/0002_initial.py. The migration was attempting
to add the user ForeignKey field twice, causing PostgreSQL to
fail with "column 'user_id' of relation 'tags' already exists".

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:01:59 -07:00
Keith SmithandClaude Sonnet 4.5 5a2585e9bd Remove mysqlclient and add Pillow dependencies
- Remove mysqlclient from requirements.txt (using PostgreSQL only)
- Add libjpeg-dev and zlib1g-dev for Pillow image processing
- Fixes build failure when installing Python packages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 16:56:06 -07:00
Keith SmithandClaude Sonnet 4.5 a52b09463a Update Dockerfile for PostgreSQL support
- Replace MySQL client with PostgreSQL client
- Use libpq-dev instead of libmysqlclient-dev
- Remove mysqlclient installation (using psycopg2-binary from requirements.txt)
- Install postgresql-client for pg_isready health checks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 16:54:14 -07:00
Keith SmithandClaude Sonnet 4.5 2afeec85da Update entrypoint.sh to support PostgreSQL
- Auto-detect database type from DATABASE_URL
- Use pg_isready for PostgreSQL health check
- Use mysqladmin ping for MariaDB/MySQL
- Default to postgres if not specified

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 16:48:43 -07:00
Keith Smith 26fda44d7a Add stack.env to .gitignore to prevent credential exposure 2025-12-26 16:21:12 -07:00
Keith SmithandClaude Sonnet 4.5 fa047adda1 Make web port configurable via WEB_PORT environment variable
- Allows deployment when port 8000 is already in use (e.g., by Portainer)
- Defaults to 8000 if WEB_PORT not specified
- Use WEB_PORT=8001 (or any other port) to override

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 16:08:55 -07:00
Keith SmithandClaude Sonnet 4.5 2b40e70a04 Remove env_file references for Portainer compatibility
- Portainer provides environment variables through UI
- env_file references caused deployment failure when .env.docker not present
- Environment variables now come from Portainer Stack configuration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 16:08:04 -07:00
Keith SmithandClaude Sonnet 4.5 71399e54b8 Add Docker deployment configuration
- Add Dockerfile for production (multi-stage build)
- Add Dockerfile.dev for development with hot reload
- Add docker-compose.yml with 5 services (web, mariadb, redis, celery-worker, celery-beat)
- Add docker-compose.dev.yml for development overrides
- Add .dockerignore for optimized builds
- Add docker/entrypoint.sh startup script
- Add .env.docker.example template
- Add Makefile for common commands
- Add deploy.sh for one-command deployment
- Update config/settings/selfhosted.py to support MariaDB via DATABASE_URL
- Add mysqlclient to requirements.txt for MariaDB support
- Update .gitignore to exclude .env.docker

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 15:59:09 -07:00
Keith SmithandClaude Sonnet 4.5 a2097dcad3 Fix MEDIUM-HIGH Security Issue: Restrict tag queryset to user's own tags
Fixed security vulnerability where users could reference any tag in the system when creating/updating tasks.

Changes:

tasks/serializers.py (TaskSerializer):
- Added __init__() method to override tag_ids queryset
- Filter Tag.objects.all() to Tag.objects.filter(user=request.user)
- Only allows users to assign their own tags to tasks
- Prevents information disclosure via tag enumeration

Security impact:
- Prevents users from accessing other users' tag IDs
- Blocks unauthorized tag association
- Protects tag privacy and prevents enumeration attacks
- Enforces proper authorization on tag-task relationships

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:25:53 -07:00
Keith SmithandClaude Sonnet 4.5 84d9b4704a Fix MEDIUM-HIGH Security Issue: Add input validation for choice fields
Added validation for status, priority, and recurrence fields in web forms to prevent invalid database values.

Changes:

TaskUpdateView.post() (line 419):
- Validate status against Task.STATUS_CHOICES before setting
- Validate priority against Task.PRIORITY_CHOICES before setting
- Validate recurrence against Task.RECURRENCE_CHOICES before setting
- Only update fields if value is in allowed choices
- Default to 'none' for invalid recurrence values

TaskCreateView.post() (line 481):
- Validate status, default to 'pending' if invalid
- Validate priority, default to 'medium' if invalid
- Validate recurrence, default to 'none' if invalid
- Prevents creation with invalid choice values

Allowed Choices:
- Status: pending, in_progress, completed, cancelled
- Priority: low, medium, high, urgent
- Recurrence: none, daily, weekly, biweekly, monthly

Security impact:
- Prevents invalid database values from user input
- Maintains data integrity
- Blocks potential business logic bypasses
- Prevents database constraint violations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:25:22 -07:00
Keith SmithandClaude Sonnet 4.5 a03b9fe79c Fix MEDIUM-HIGH Security Issue: Add rate limiting to sensitive endpoints
Added rate limiting to previously unprotected user-related endpoints.

Protected Endpoints:
- UserProfileAPIView: Profile retrieval and updates (1000 req/hour)
- ChangePasswordAPIView: Password change operations (1000 req/hour)
- DeviceTokenAPIView: Device token registration (1000 req/hour)
- DeviceTokenDeleteAPIView: Device token deletion (1000 req/hour)

Changes:
- Added UserRateThrottle import from rest_framework.throttling
- Applied throttle_classes = [UserRateThrottle] to all 4 endpoints
- Inherits default rate of 1000 requests/hour per user from base settings

Security impact:
- Prevents brute force attacks on password changes
- Mitigates enumeration attacks via profile endpoint
- Protects against DoS via excessive device token registration
- Complements existing login/register rate limiting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:24:35 -07:00
Keith SmithandClaude Sonnet 4.5 e7fbef75e9 Fix HIGH Security Issue: Require ALLOWED_HOSTS in production
Added validation to ensure ALLOWED_HOSTS is explicitly set in production.

Changes:
- Check if ALLOWED_HOSTS environment variable is set
- Raise ValueError with helpful message if not set
- Use os.environ['ALLOWED_HOSTS'] instead of .get() to enforce requirement
- Prevents empty or missing ALLOWED_HOSTS from bypassing host validation

Security impact:
- Prevents host header injection attacks
- Blocks cache poisoning via host header manipulation
- Ensures production deployments have explicit allowed hosts configured
- Fails fast with clear error message if misconfigured

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:23:34 -07:00
Keith SmithandClaude Sonnet 4.5 5d9c901918 Fix HIGH Security Issue: Add file upload validation for avatars
Added comprehensive validation for avatar file uploads to prevent malicious file uploads.

Validation Checks:
- File extension: Only allow jpg, jpeg, png, gif
- File size: Maximum 5MB
- Content type: Verify MIME type matches allowed image types

Changes:

users/serializers.py:
- Added MAX_AVATAR_SIZE constant (5MB)
- Created validate_avatar() method in UserSerializer
- Validates file extension against whitelist
- Checks file size and provides helpful error messages
- Verifies content-type header matches allowed image types

config/settings/base.py:
- Added FILE_UPLOAD_MAX_MEMORY_SIZE = 5MB
- Added DATA_UPLOAD_MAX_MEMORY_SIZE = 5MB
- Enforces global upload limits at Django level

Security impact:
- Prevents upload of executables, malware, or scripts
- Mitigates DoS via large file uploads
- Ensures only valid image files can be uploaded
- Protects against MIME-type confusion attacks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:23:11 -07:00
Keith SmithandClaude Sonnet 4.5 026259b4f4 Fix HIGH Security Issue: Add comprehensive security headers
Added comprehensive security headers to prevent XSS, clickjacking, and other attacks.

Security Headers Added:
- SECURE_BROWSER_XSS_FILTER: Enable XSS filter
- SECURE_CONTENT_TYPE_NOSNIFF: Prevent MIME-type sniffing
- X_FRAME_OPTIONS: DENY to prevent clickjacking
- SECURE_REFERRER_POLICY: Control referrer information

Cookie Security:
- SESSION_COOKIE_HTTPONLY: Prevent JavaScript access to session cookies
- SESSION_COOKIE_SAMESITE: Strict to prevent CSRF
- CSRF_COOKIE_HTTPONLY: Prevent JavaScript access to CSRF tokens
- CSRF_COOKIE_SAMESITE: Strict protection

Content Security Policy (CSP):
- CSP_DEFAULT_SRC: Only allow same-origin resources
- CSP_SCRIPT_SRC: Restrict script execution to same-origin
- CSP_STYLE_SRC: Restrict stylesheets to same-origin
- CSP_IMG_SRC: Allow images from same-origin, data URIs, and HTTPS
- CSP_FRAME_ANCESTORS: Prevent embedding in iframes ('none')
- CSP_FORM_ACTION: Restrict form submissions to same-origin

CSRF Protection:
- Added CSRF_TRUSTED_ORIGINS configuration for cross-origin requests

Security impact:
- Prevents clickjacking attacks
- Mitigates XSS vulnerabilities
- Blocks MIME-type confusion attacks
- Protects cookies from JavaScript theft
- Enforces strict CSP to prevent code injection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:22:14 -07:00
Keith SmithandClaude Sonnet 4.5 e5b15c7193 Fix HIGH Security Issue: Open Redirect Vulnerability
Fixed open redirect vulnerability in 9 locations throughout tasks/views.py.

Changes:
- Added url_has_allowed_host_and_scheme import from django.utils.http
- Created safe_redirect() helper function to validate redirect URLs
- Only allows relative URLs or URLs to the same host
- Prevents attackers from redirecting users to phishing/malicious sites

Fixed locations:
- Line 447: TaskUpdateView - task update redirect
- Line 501: task_quick_add - quick add redirect
- Line 521: subtask_create - subtask creation redirect
- Line 537: task_toggle_status - status toggle redirect
- Line 549: task_delete - task deletion redirect
- Line 601: web_timer_start - timer start redirect
- Line 626: web_timer_stop - timer stop redirect
- Line 672: TagUpdateView - tag update redirect
- Line 684: tag_delete - tag deletion redirect

Security impact:
- Prevents phishing attacks via malicious redirect URLs
- Blocks cache poisoning attacks
- Ensures users stay within the application domain

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:21:44 -07:00
Keith SmithandClaude Sonnet 4.5 0147b8644e Add tasks.firebugit.com to development server configuration
Added tasks.firebugit.com to:
- ALLOWED_HOSTS: Allow Django to serve requests from this domain
- CSRF_TRUSTED_ORIGINS: Allow CSRF-protected requests from https://tasks.firebugit.com

This enables testing the development server via the tasks.firebugit.com domain.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:08:39 -07:00
Keith SmithandClaude Sonnet 4.5 c50aaa2d81 Fix Critical Security Issue: Authorization bypass on shared tasks
Added comprehensive authorization checks to prevent users from:
1. Sharing tasks/tags they don't own
2. Modifying tasks/tags that are only shared with them (read-only access)

Changes:

tasks/serializers.py (TaskShareSerializer):
- Added validation in validate() method to verify task/tag ownership
- Users can only share their own tasks and tags
- Prevents malicious users from sharing other people's resources

tasks/permissions.py (NEW):
- Created IsOwnerOrReadOnlyIfShared permission class
- Owners: full access (read, update, delete)
- Shared users: read-only access
- Prevents privilege escalation via shared access

tasks/views.py:
- Applied IsOwnerOrReadOnlyIfShared to TaskDetailAPIView
- Applied IsOwnerOrReadOnlyIfShared to TagDetailAPIView
- Enforces object-level permissions on all update/delete operations

Security impact:
- Prevents users from modifying or deleting resources they don't own
- Prevents users from sharing resources they don't own
- Maintains proper separation between owner and shared access levels

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:38:43 -07:00
Keith SmithandClaude Sonnet 4.5 deabe6ab3d Fix Critical Security Issue: Implement rate limiting on API endpoints
Added comprehensive rate limiting to prevent abuse and DoS attacks:

Configuration (config/settings/base.py):
- Anon rate: 100 requests/hour for anonymous users
- User rate: 1000 requests/hour for authenticated users
- Login rate: 10 attempts/hour (prevents brute force)
- Register rate: 5 attempts/hour (prevents account spam)
- Sync rate: 100 requests/hour (prevents sync flooding)

Custom throttle classes (users/throttles.py):
- LoginRateThrottle: Strict limit for login endpoint
- RegisterRateThrottle: Strict limit for registration endpoint
- SyncRateThrottle: Moderate limit for sync endpoint

Applied throttling to sensitive endpoints:
- users.views.RegisterAPIView: 5/hour
- users.views.TokenObtainPairView: 10/hour
- sync.views.sync: 100/hour

All other API endpoints use default throttles (anon: 100/hour, user: 1000/hour).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:36:54 -07:00
Keith SmithandClaude Sonnet 4.5 b57321e1e4 Fix Critical Security Issue: Replace print() with proper logging
Replaced all debug print() statements with proper logging framework:
- tasks/views.py: 5 print statements → logger.debug()
- sync/views.py: 15 print statements → logger.debug()
- config/celery.py: 1 print statement → logger.debug()
- notifications/tasks.py: 2 print statements → logger.error()

Retained print() in settings files (development.py, selfhosted.py) as they are appropriate warnings to stderr for configuration issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:34:57 -07:00
Keith SmithandClaude Sonnet 4.5 a22c3eed50 Fix Critical Security Issue: Remove weak default SECRET_KEY
Security improvements:
- selfhosted.py: Require SECRET_KEY environment variable (raises ValueError if not set)
- selfhosted.py: Validate SECRET_KEY length (minimum 50 characters)
- selfhosted.py: Warn if DEBUG=True in self-hosted mode
- development.py: Auto-generate random SECRET_KEY on each startup if not provided
- development.py: Remove production domain from ALLOWED_HOSTS
- development.py: Make CSRF_TRUSTED_ORIGINS environment-only

This prevents weak/default SECRET_KEYs from being used in production.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:31:46 -07:00
Keith SmithandClaude Sonnet 4.5 13b5a3c10c Add generic SMTP server configuration example
Add a basic SMTP example that works with any standard SMTP server,
positioned before the specific provider examples (Gmail, SendGrid, etc.).

Includes:
- Generic SMTP configuration template
- Clear explanation of EMAIL_USE_TLS vs EMAIL_USE_SSL
- Common SMTP port reference (587, 465, 25)
- Notes on which settings to use for each port

This provides a starting point for users with custom mail servers
or SMTP providers not specifically listed in the documentation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:11:37 -07:00
Keith SmithandClaude Sonnet 4.5 a9293d6151 Remove Docker support files and documentation
Remove Docker deployment files and all references from README:
- Deleted Dockerfile
- Deleted docker-compose.yml (production)
- Deleted docker-compose.dev.yml (development)
- Removed Docker from Tech Stack section
- Removed Docker Deployment section from README

Docker support may be revisited and added back in the future.
For now, focus is on manual deployment as documented in the
Production Setup Guide.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:08:36 -07:00
Keith SmithandClaude Sonnet 4.5 6fd86a3682 Make tag text bold for better readability
Add font-weight: 600 to tag labels to improve text readability
on solid colored backgrounds. The bold text provides better
contrast and matches the visual weight of the desktop app.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:06:57 -07:00
Keith SmithandClaude Sonnet 4.5 ccd1fe15c1 Update tag styling to match desktop app
Change tag display from transparent background with colored text
to solid colored background with white text to match the desktop app:
- Background: Solid tag color (was transparent with 20% opacity)
- Text: White (was same color as tag)
- Maintains existing rounded rectangle shape from CSS

Tags now appear as colored pills with white text, matching the
visual style of the desktop application.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:06:10 -07:00
Keith SmithandClaude Sonnet 4.5 1872442016 Fix dark/light mode support on change password page
Replace all hardcoded colors and CSS variable fallbacks with proper
theme CSS variables:
- Removed fallback values from all var() calls
- Replaced --color-* prefixed variables with actual theme variables:
  - --color-bg-secondary → --surface
  - --color-border → --border
  - --color-text → --text-primary
  - --color-text-secondary → --text-secondary
  - --color-primary → --accent (via .btn-primary class)
- Updated success alert to use .alert-success class
- Updated buttons to use .btn-primary and .btn-secondary classes
- Fixed input backgrounds and text colors to use theme variables
- Replaced hardcoded error color with --danger variable

The page now properly respects the dark/light mode toggle.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:03:22 -07:00
Keith SmithandClaude Sonnet 4.5 b86db7e0e4 Remove task sharing references from documentation
Task sharing is not currently implemented and removed:
- Task Sharing feature from User Management section
- Shared Views feature description
- TaskShare database model documentation
- Updated description to remove "real-time collaboration"

The application currently supports multi-user authentication and
user management, but does not include task sharing functionality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 18:23:22 -07:00
Keith SmithandClaude Sonnet 4.5 21f201c552 Enhance database configuration documentation
Add comprehensive instructions for all database backends:

SQLite:
- When to use (development, testing, single-user)
- When NOT to use (production with multiple users)
- DATABASE_URL configuration
- Pros and cons with detailed explanations
- Zero-configuration setup instructions

PostgreSQL:
- When to use (production, multiple users, advanced features)
- Complete installation and setup for Ubuntu/Debian and macOS
- Database and user creation with PostgreSQL 15+ schema permissions
- Connection pooling configuration
- Performance tuning recommendations

MySQL/MariaDB:
- When to use (existing MySQL infrastructure, replication)
- Installation for both MariaDB and MySQL
- Secure installation steps
- Alternative driver (PyMySQL) if mysqlclient fails
- Performance tuning configuration

Production Setup Guide updates:
- All three database options in Step 2
- Database driver installation for each backend
- .env examples for PostgreSQL, MySQL, and SQLite
- Clear warnings about SQLite in production

Each database section now includes installation, configuration,
performance tuning, and clear guidance on appropriate use cases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 18:21:05 -07:00
Keith SmithandClaude Sonnet 4.5 f6dff9c459 Add comprehensive production deployment documentation
Add detailed production setup guide covering:
- Step-by-step deployment instructions for Ubuntu/Debian
- Email provider configuration (Gmail, SendGrid, AWS SES, Mailgun)
- Gunicorn and Celery systemd service configurations
- Nginx reverse proxy setup with SSL
- Complete production checklist
- Email verification and admin approval setup
- Troubleshooting guide
- Maintenance tasks and backup procedures
- Enhanced environment variables documentation
- Updated changelog with v1.1.0 features

The guide provides complete instructions for deploying the application
with the new email verification and admin approval system.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 18:16:56 -07:00
Keith SmithandClaude Sonnet 4.5 21d9d01885 Add email verification, admin approval, and user profile enhancements
Implement comprehensive email verification and admin approval system for user registration. Users must verify their email before logging in, and admins must approve new users before they can access the system.

Major features:
- Email verification with UUID tokens (24hr expiry, one-time use)
- Admin approval workflow via Django admin interface
- Custom authentication backend enforcing verification and approval
- Password change functionality for authenticated users
- Enhanced profile page with proper styling and theme support
- Collect first name, last name, and timezone during registration
- Profile link added to header navigation

Email notifications:
- Verification email sent after registration
- Admin notification when users need approval
- Approval notification sent to users

Security features:
- Cryptographically secure UUID tokens
- Token expiration and one-time use enforcement
- Email enumeration protection
- Custom JWT token validation for API access
- Existing users auto-approved via data migration

Templates added:
- Email templates (verification, approval, admin notification)
- Web templates (password change, verification pages)
- Enhanced profile page with dark/light mode support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 18:13:38 -07:00
Keith SmithandClaude Sonnet 4.5 87afc4e80c Add comprehensive database configuration documentation
Updated README with detailed instructions for:
- SQLite3 (default/development) with pros/cons
- PostgreSQL (recommended for production) with full setup
- MariaDB/MySQL configuration and setup
- Database migration between backends

Each section includes:
- Installation instructions for Ubuntu/Debian and macOS
- Database and user creation commands
- Python driver installation
- Configuration examples (both .env and direct settings)
- Migration steps

Also added data export/import instructions for switching databases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 17:58:29 -07:00
Keith SmithandClaude Sonnet 4.5 7f7ea3fef4 Add comprehensive README.md documentation
Added detailed documentation covering:
- Feature overview and capabilities
- Installation and quick start guide
- Configuration options and environment setup
- API documentation and endpoints
- Project structure explanation
- Docker deployment instructions
- Database model descriptions
- Development guidelines
- Production deployment checklist
- Mobile app integration details

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 17:44:10 -07:00
Keith SmithandClaude Sonnet 4.5 6a0b35c39c Initial commit: KeepItGoing task management server
Features:
- Django-based REST API with web interface
- Task management with tags, priorities, and due dates
- Time tracking with start/stop timers
- Subtasks support
- Task filtering (all, today, upcoming, overdue, completed)
- Tag-based organization with color coding
- Sorting by due date and priority
- Auto-assign tags when filtering
- Responsive 3-pane layout (sidebar, task list, detail panel)
- Task sharing between users
- Mobile-responsive design with dark mode support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 17:41:29 -07:00