Commit Graph
91 Commits
Author SHA1 Message Date
Keith SmithandClaude Sonnet 5 7e905a0566 Add Web Push notifications (PWA)
Wires up the previously-scaffolded VAPID/DeviceToken infrastructure end
to end: browser subscription flow on the Profile page's existing "Push
Notifications" toggle, a service worker push/notificationclick handler,
and server-side sending from the daily task digest. Also broadens that
digest's eligibility query so push-only users (email notifications off)
aren't silently skipped, and adds `generate_vapid_keys` since the pinned
py-vapid's own key generator is broken against current cryptography.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 22:30:56 -06:00
Keith SmithandClaude Sonnet 5 cf37389655 Remove CLAUDE.md from version control
It's local AI-assistant guidance, not project documentation meant for
the repo. Kept on disk (gitignored) so it still works locally.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 22:05:40 -06:00
Keith SmithandClaude Sonnet 5 30c61351de Make the web app installable as a PWA (Tier 1: app shell + offline fallback)
Adds a manifest, service worker, and branded icons so the site can be
installed to a home screen/desktop, plus an offline fallback page so a
dropped connection shows something friendlier than the browser's default
error. Icons are rasterized from the existing favicon.svg mark via
rsvg-convert. The manifest and service worker are served through small
Django views (not raw static files) so their asset URLs pick up
WhiteNoise's content-hashed filenames in prod/selfhosted, and the service
worker is served from the site root so its scope covers the whole app.

Does not include true offline task data or Web Push notifications --
those are tracked separately as larger follow-up projects.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 22:03:12 -06:00
Keith SmithandClaude Sonnet 5 a23600a486 Document custom recurrence RRULE patterns and fix stale field names
API.md now lists the supported custom RRULE patterns (every Wednesday,
every other Wednesday, every second Tuesday, every 15th, etc.) matching
the newly implemented dateutil.rrule evaluation. CLAUDE.md's Task model
reference also gets corrected: it listed recurrence_type/recurrence_interval
fields that never existed on the model.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026.8.31.1
2026-08-31 21:21:50 -06:00
Keith SmithandClaude Sonnet 5 70dcc1f001 Add custom recurrence patterns (day-of-week, nth-weekday, day-of-month)
Recurring tasks were locked to fixed daily/weekly/biweekly/monthly/yearly
intervals. The `custom` recurrence type and `recurrence_rule` field already
existed in the model and API docs, but RRULE evaluation was a TODO stub
that silently fell back to weekly, and no UI exposed the option.

Implements real RRULE parsing via dateutil.rrule, and adds a builder UI
(day-of-week checkboxes for weekly, day-of-month or Nth-weekday for
monthly) so users can express patterns like "every other Wednesday" or
"every second Tuesday" without hand-writing RRULE strings.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-31 18:12:15 -06:00
Keith SmithandClaude Sonnet 5 4d88d10382 Point deployment configs at current git host, strip secrets from docs
Repo moved from git.firebugit.com to git.darksingularity.org; the old
host is gone, which would break both docker-compose's git build
contexts and the Portainer stack setup instructions. Also removes
production secret values (SECRET_KEY, DB passwords, SMTP password)
that were committed in plaintext in the deployment guide.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026.8.31
2026-08-31 17:15:42 -06:00
Keith SmithandClaude Sonnet 5 a2bc5de205 Default task sort to due date instead of raw model order
The "Default" option cleared the sort param and fell back to the
model's Meta.ordering (sort_order, -priority, due_date, created_at),
which read as broken/unsorted to users. Default is now due date
(earliest first), matching the existing due_date sort option.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-31 16:55:17 -06:00
Keith Smith 289b5f3856 Document self-registration toggle 2026-04-15 17:47:49 -06:00
Keith Smith 53180a9469 Disable self-registration by default 2026-04-15 17:42:40 -06:00
Keith Smith 586e98fd95 Ignore local tooling files 2026-04-15 17:36:36 -06:00
Keith SmithandClaude Sonnet 4.5 d7d3e8d072 Add comprehensive API documentation
Complete REST API documentation including authentication, rate limiting, all endpoints (users, tasks, tags, time tracking, sharing, sync, notifications), error handling, and usage examples. Intended for developers building applications that integrate with KeepItGoing via the API.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-03 17:22:32 -07:00
Keith SmithandClaude Sonnet 4.5 c8ffa615f0 Fix recurring task duplication bug
Prevent process_recurring_tasks from creating duplicate tasks for dates that already have completed instances. Previously only checked for pending tasks, causing old completed recurring tasks to reappear as pending when subsequent instances went overdue.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-03 16:52:06 -07:00
Keith SmithandClaude Sonnet 4.5 cdcae378b7 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>
2026-02-03 16:52:04 -07:00
Keith SmithandClaude Sonnet 4.5 7b4d024334 Add SITE_DOMAIN environment variable to all services
Fixes email notification links showing localhost:8000 instead of the
actual domain. The SITE_DOMAIN variable is now passed to web,
celery-worker, and celery-beat containers so emails include the
correct URL.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-10 09:15:33 -07:00
Keith SmithandClaude Sonnet 4.5 aca8abca56 Fix daily email timing to work across all timezones
Critical fix: Task now runs every hour instead of once at 6 AM UTC.
This ensures users in all timezones receive their email at 6 AM local time.

Changes:
- Run task every hour instead of once daily
- Check if it's 6-7 AM in user's timezone (1 hour window)
- Track sent emails in Notification model to prevent duplicates
- Add 'daily_email' notification type

Without this fix, users in timezones where 6 AM UTC is not morning
would never receive their daily email.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 09:34:39 -07:00
Keith SmithandClaude Sonnet 4.5 03cfdea42d Simplify notification system to daily email only
Replace complex notification system with a simple daily email:
- Send ONE email per day between 6-9 AM in user's timezone
- Show tasks due today and overdue tasks
- Only send if user has email_notifications enabled
- Remove all push notification logic
- Keep recurring task processor (runs daily at midnight)

This makes notifications much simpler and less intrusive while
still providing value to users.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 09:30:46 -07:00
Keith SmithandClaude Sonnet 4.5 842b958b43 Configure docker-compose to build from git repository
Update build contexts to pull from git repository URL instead of
local directory. This allows Portainer to build images directly
from the repository without requiring SSH access to the server.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 09:19:45 -07:00
Keith SmithandClaude Sonnet 4.5 ff534301f8 Use ps instead of pgrep for celery healthchecks
Change healthchecks to use 'ps aux | grep' instead of 'pgrep' since
procps may not be available in existing images. This works with the
base Python image without requiring a rebuild.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 09:10:02 -07:00
Keith SmithandClaude Sonnet 4.5 991d4f1eaa Add stack.env.example for Portainer git deployments
This allows deploying from git repository in Portainer by providing
an example environment variables file. Users can copy this and fill
in their actual values in Portainer's environment variables section.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 09:06:40 -07:00
Keith SmithandClaude Sonnet 4.5 6e18baf502 Fix celery-worker healthcheck command
Replace celery inspect ping with pgrep check for reliability.
The inspect command was failing in healthcheck context while
the worker process itself was running fine.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 08:52:42 -07:00
Keith SmithandClaude Sonnet 4.5 e0ee377a20 Fix celery container health issues
- Fix import error in notifications/tasks.py (timezone.datetime -> datetime)
- Add healthchecks to celery-worker and celery-beat containers
- Add procps package to Dockerfile for pgrep command
- Add email environment variables to celery containers

The import error was causing celery workers to crash when loading tasks.
Missing healthchecks prevented proper container health monitoring.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 08:47:58 -07:00
Keith SmithandClaude Sonnet 4.5 9dd5d9c154 Replace pytz with zoneinfo for timezone handling
Fixes ModuleNotFoundError by using Python's built-in zoneinfo module
instead of the external pytz dependency. zoneinfo is the standard
library solution for timezone handling in Python 3.9+.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 08:32:38 -07:00
Keith SmithandClaude Sonnet 4.5 8d5faa8a6e Add error handling for timezone conversion
Fixes 500 error when user timezone is invalid or missing.
Now gracefully falls back to UTC if timezone conversion fails.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 08:30:52 -07:00
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>
v1.2.0
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>
v1.1
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>
v1.0.0
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