This document describes the technical implementation of platform admin functionality, including access controls, scope-aware operations, billing/reconciliation tooling, and operational safeguards.

Scope

This document focuses on platform admin implementation in:

  1. Views, forms, and templates used by superusers.
  2. Account provisioning and account-management operations.
  3. Promotion and billing actions exposed through platform admin.
  4. Security, rate limiting, and auditability requirements.

Entry Points and Structure

Primary implementation files:

  1. checktick_app/core/views_platform_admin.py
  2. checktick_app/core/urls.py
  3. checktick_app/core/templates/core/platform_admin/*.html

Primary navigation surfaces include:

  1. Dashboard
  2. Organisations
  3. Statistics
  4. Logs
  5. Pricing
  6. Billing
  7. Promotions

Access Control Model

Platform admin endpoints are superuser-only and protected by explicit controls:

  1. superuser_required decorator for route protection.
  2. require_http_methods for endpoint method constraints.
  3. django-ratelimit on sensitive actions.
  4. CSRF protection for state-changing form posts.

Design intent: administrative workflows are explicit, auditable, and fail-closed when authorization fails.

Data access boundary: Platform Admins are deliberately excluded from survey response data. They cannot view, download, or export survey data, and can_export_survey_data returns False for platform admin status alone. Platform Admin capabilities are limited to account/billing/promotions operations and platform-level log review. A Platform Admin may only access survey data if they independently hold an in-survey role (survey owner, organisation owner/admin, or active data custodian). This boundary is enforced by the permission helpers in checktick_app/surveys/permissions.py and locked down by automated tests in checktick_app/surveys/tests/test_data_governance_views.py.

Encryption at rest: Survey responses are encrypted at submission time using a per-survey X25519 keypair (hybrid encryption: random per-response 32-byte DEK, AES-256-GCM payload, DEK wrapped via ephemeral X25519 ECDH + HKDF-SHA256). Only the survey's public key is stored server-side in plaintext form; the private key is stored wrapped and is only unwrapped into the owner's session via owner unlock (password / recovery phrase / OIDC auto-unlock / organisation key). The server can encrypt responses but cryptographically cannot decrypt them, so platform admins (and anyone with database access) cannot read response content โ€” including demographics, which are encrypted inside the same response payload โ€” without recovering the survey private key. Recovery flows (see Recovery Dashboard) use the same Vault escrow mechanisms and audit trails to recover the survey private key; recovering it grants the ability to decrypt all responses encrypted with the survey's public key, and is restricted to organisation owners and platform admins via the recovery dashboard's dual-authorization workflow.

Account and Billing Operations

Platform admin supports operational workflows across account types and tiers:

  1. Organization administration and status management.
  2. Pricing override management for supported tiers.
  3. Billing timeline/reconciliation views.
  4. Controlled refund actions linked to payment records.
  5. Manual tier upgrades with configurable renewal dates (see below).

Manual Tier Upgrades

Platform admins can create or update a tier-scoped account (Pro, Team, Organisation, Enterprise) via the organization_create view when create_target == 'account'. The form includes:

  • Tier dropdown: overrides the scope query param, allowing any tier.
  • Renewal date: preset buttons (1 year, 2 years, 5 years) or a custom date picker. Sanity cap: max 5 years, must be in the future.
  • Tier-specific rules: Free ignores expiry; Pro/Team require a renewal date; Organisation/Enterprise default to no expiry but allow optional renewal.

The view sets subscription_current_period_end on the profile so the existing process_expired_subscriptions cron auto-downgrades the account when the date passes. Pre-expiry warning tracking fields (last_expiry_warning_sent_at, last_expiry_warning_stage) are reset on each save so warnings restart for the new expiry date.

Manually upgraded accounts (no payment_subscription_id) receive a 7-day grace period before downgrade, matching the GoCardless past-due grace period. GoCardless subscriptions are downgraded immediately (the provider has already notified the user).

Manual tier changes are logged via AuditLog (recording the admin actor, target user, old/new tier, and valid_until date). A notification email is sent to the user via send_manual_upgrade_email when upgraded to a paid tier. The expiry date is shown on the profile page and in the subscription portal.

Downgrading to free via the form closes excess surveys immediately (via force_downgrade_tier). Upgrading re-opens surveys auto-closed by a previous downgrade (via reopen_surveys_on_upgrade).

The tier selected determines which survey layouts the user can access (see tier_limits.py allowed_layouts). Free tier: linear only. All paid tiers: all 7 layouts (section menu, RCT, guided, staged, matrix, Delphi).

See docs/billing-and-subscriptions.md ยง Manual Tier Upgrades and Expiry for the user-facing behaviour.

Refund action constraints (hosted reference flow):

  1. Full refund automation only.
  2. Mandatory reason code.
  3. Required free-text explanation for other reason.
  4. Idempotent handling for repeated operator attempts.

Promotions Operations

Platform admin promotions implementation supports:

  1. Promotion creation and edit workflows.
  2. Activate/deactivate/toggle operations.
  3. Duplicate/revoke workflows for reuse and controlled shutdown.
  4. Post-start immutability of billing-impacting terms.
  5. Lifecycle processing and reconciliation alignment.

Audit and Observability

Administrative actions and lifecycle outcomes are auditable using structured metadata.

Coverage includes:

  1. Promotion lifecycle events.
  2. Refund request and webhook-reconciled state transitions.
  3. Operator attribution and references required for finance/audit traceability.
  4. Manual tier changes (actor, target user, old/new tier, valid_until date).

See also: Audit Logging and Notifications.

Security and Abuse Controls

Relevant protections include:

  1. Role-constrained admin actions.
  2. Endpoint rate limiting on refund/billing operations.
  3. Strict webhook signature verification and required webhook secret.
  4. Defensive validation on refund amount/policy paths.

See also: Security Overview.

Testing Strategy (Platform Admin Slice)

Primary coverage areas:

  1. Permissions and authorization boundaries.
  2. Method restrictions and malformed request handling.
  3. Promotion operation regressions.
  4. Billing/refund policy enforcement and idempotency.
  5. Webhook-reconciled billing state transitions.

Representative suites:

  1. tests/test_platform_admin_permissions.py
  2. tests/test_platform_admin_regressions.py
  3. tests/test_platform_admin_tier_validity.py
  4. tests/test_manual_upgrade_lifecycle.py
  5. tests/test_billing.py
  6. tests/test_layout_gating.py
  7. tests/test_organisation_checkout.py

Self-Hosted Considerations

For SELF_HOSTED=true environments:

  1. Billing is disabled by default.
  2. Platform admin billing/refund flows depend on optional external provider integration.
  3. Operators must configure webhook signing and provider-specific credentials before enabling billing actions.
  1. Billing, Refunds, and Promotions Technical Overview
  2. Account Tiers Implementation
  3. Billing and Subscriptions
  4. Refund Policy