No description
Find a file
Alec Perkins 604c2bbf91
Some checks failed
ci / test (push) Failing after 1m6s
ci / deploy (push) Failing after 0s
Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5)
- Rate limits in the shared cache for comments, issues, uploads and
  invites; a limited HTMX reply keeps the draft.
- Content-Security-Policy (self only, no inline script or style, bucket
  origin for images and frames) and Permissions-Policy on every page.
  htmx configured not to inject styles or eval.
- Moderation: deactivating a user ends their sessions and keeps their
  content; deleted accounts show as "ghost"; reserved usernames; the
  admin won't delete an org's last owner.
- Admin requires a TOTP code (django-otp), with add_admin_totp to enrol.
- Email provider chosen by environment through django-anymail.
- Playwright browser tests: axe WCAG 2.1 AA on every page in light and
  dark, no CSP violations, keyboard walkthrough, theme toggle. Explicit
  Canvas/CanvasText on :root fixes dark-mode contrast detection.
- bin/start creates the data dir if missing; docs/operations.md runbook.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:51:06 -04:00
.forgejo/workflows Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
bin Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
config Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
docs Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
intent Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
static Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
templates Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
tests Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
.dockerignore Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
.env.example Scaffold Phase 0: Django project, deploy config, base layout 2026-10-27 06:59:34 -04:00
.gitignore Scaffold Phase 0: Django project, deploy config, base layout 2026-10-27 06:59:34 -04:00
.python-version Scaffold Phase 0: Django project, deploy config, base layout 2026-10-27 06:59:34 -04:00
compose.yaml Scaffold Phase 0: Django project, deploy config, base layout 2026-10-27 06:59:34 -04:00
Dockerfile Harden auth, invites and deployment after security review 2026-10-27 08:42:19 -04:00
fly.toml Scaffold Phase 0: Django project, deploy config, base layout 2026-10-27 06:59:34 -04:00
litestream.yml Scaffold Phase 0: Django project, deploy config, base layout 2026-10-27 06:59:34 -04:00
manage.py Scaffold Phase 0: Django project, deploy config, base layout 2026-10-27 06:59:34 -04:00
pyproject.toml Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
README.md Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00
uv.lock Harden for launch: limits, CSP, moderation, admin 2FA (Phase 5) 2026-10-27 10:51:06 -04:00

Intent

Track the why behind features, across implementations. See docs/concept.md and docs/plan.md.

Local development

With uv:

uv sync
uv run python manage.py migrate
uv run python manage.py runserver

Or with Docker:

docker compose up --build

Then open http://localhost:8000. Data lives in data/ (uv) or the data volume (Docker).

Checks:

uv run playwright install chromium   # once, for the real-browser tests
uv run ruff check . && uv run ruff format --check . && uv run pytest

uv run pytest -m "not browser" skips the browser tests for a quicker run.

Production

Fly.io, one machine with a volume at /data; Litestream backs the database up to B2 and uploads go to Tigris. Deploying, secrets, administrators, email, moderation and the restore drill are in docs/operations.md.