Skip to content

Codebase overview

Architecture

  • Monolith: Django serves both HTML templates (Tailwind + Alpine.js + htmx) and a DRF REST API
  • URL pattern: Most views scoped under /a/<org_slug>/ via OrganizationMiddleware
  • API versioning: AcceptHeaderVersioning with versions 1.0 and 2.0
  • Background tasks: Celery with Redis broker; beat scheduler uses DB
  • Feature flags: django-waffle with a custom Flag model. Flag names in flags/flag_names.py, switch names in flags/switch_names.py — see Terminology below
  • Audit trail: django-pghistory stores username + user_email in context (survives user deletion). Read docs/audit-history.md before tracking a model or reading its events
  • Database: PostgreSQL + PostGIS. ATOMIC_REQUESTS = True (all requests are transactions)
  • Deployment: Kamal (Docker-based) + Ansible on EC2. See deploy/README.md

Key directories

commcare_connect/
  opportunity/     # Core domain: opportunities, visits, payments (largest app)
  organization/    # Org management, membership roles
  program/         # Program management, linking orgs/opportunities
  users/           # Custom User model, ConnectID links
  audit/           # Audit reports: CHC indicators, sampling, review workflow
  commcarehq/      # CommCare HQ server integration
  connect_id_client/  # HTTP client for ConnectID service
  form_receiver/   # Receives xforms from CommCare HQ
  commcarehq_provider/ # OAuth provider: HQ as an identity provider
  ocs_provider/    # Open Chat Studio integration
  data_export/     # CSV/streaming exports over OAuth token scopes
  microplanning/   # Work areas, coverage tracking, maps (Mapbox)
  reports/         # KPI and admin reports
  flags/           # Waffle feature flag/switch name constants
  health/          # /up liveness probe, token-gated /status/ dependency checks (see its README)
  multidb/         # Secondary DB support + logical replication
  deid/            # SQL generator for de-identifying a DB copy; only in INSTALLED_APPS under local.py
  web/             # Context processors, shared template tags
  prelogin/        # Public marketing pages
  utils/           # BaseModel, middleware, caching, permissions
config/
  settings/        # base.py, local.py, test.py; deploy_base.py shared by staging.py + production.py
  api_router.py    # DRF API URL routing
  celery_app.py    # Celery config
  urls.py          # Root URL config

Terminology

Some words mean several unrelated things here. Work out which one you are in before searching.

"flag" — four separate concepts:

  • Waffle flags: per-request/per-user feature toggles. Names in flags/flag_names.py, checked with flag_is_active(request, NAME), backed by the custom Flag model in flags/models.py.
  • Waffle switches: global on/off toggles. Names in flags/switch_names.py, checked with switch_is_active(NAME).
  • Visit validation flags: why a UserVisit was flagged for review (duplicate, gps, …). Defined in utils/flags.py (Flags, FlagDescription, FlagLabels), stored on UserVisit.flagged and UserVisit.flag_reason.
  • Verification flag config: which validation flags an opportunity applies — OpportunityVerificationFlags and DeliverUnitFlagRules in opportunity/models/verification.py.

"worker" — there is no Worker model. A worker is a User reached through an OpportunityAccess, and WorkerPageView, the Worker*Table classes and the worker templates all resolve to that pair. Nothing on User marks someone as a worker: org staff have a UserOrganizationMembership, workers have an OpportunityAccess. Worker-scoped URLs pass ?user=<User.user_id> — the UUID, not the PK.