djangoplay-web / Architecture / DjangoPlay — Security Architecture
DocsDjangoPlay WebArchitectureDjangoPlay — Security Architecture

DjangoPlay — Security Architecture

DjangoPlay treats security as a cross-cutting concern enforced across the request lifecycle, identity boundary, authorization policies, application services, data protection, and audit infrastructure.

13 min readApplies to v1.2.2
On this page ▾
  1. Architecture
  2. Security Flow
  3. Security Boundaries
  4. Authentication
  5. AuthX JWT Authority
  6. Authentication Boundary
  7. Authorization
  8. RBAC and Policy Enforcement
  9. Request Boundary
  10. Input and Request Protection
  11. CSRF and CORS
  12. CSRF
  13. CORS
  14. Bot Protection
  15. Abuse Protection
  16. Flow Throttling
  17. Application Validation
  18. Service-Layer Security
  19. Secret Protection
  20. Credential Separation
  21. AuthX Service Authentication
  22. Data Protection
  23. Auditability
  24. Security and Background Tasks
  25. Security Across Web and API Interfaces
  26. Security and GenericIssueTracker
  27. Fail-Closed Authorization
  28. Security Configuration
  29. Security Responsibility Matrix
  30. Security Layers
  31. Architectural Principles
  32. Architectural Principle

The security architecture separates:

  • Authentication and identity
  • Authorization and RBAC
  • Request and input protection
  • Abuse prevention and throttling
  • Secret and credential protection
  • Data and database protection
  • Auditability and security logging

Security controls are applied at the appropriate boundary rather than being implemented independently inside individual views or applications.

Architecture

Security Flow

text
                                CLIENT
                                  │
                                  ▼
                         DJANGOPLAY SECURITY
                                  │
             ┌────────────────────┼────────────────────┐
             │                    │                    │
             ▼                    ▼                    ▼
       Authentication       Authorization         Input / Request
          (AuthX)            RBAC / Policies       Protection
             │                    │                    │
             └────────────────────┼────────────────────┘
                                  │
                                  ▼
                    ┌────────────────────────┐
                    │    DjangoPlay Request  │
                    │        Boundary        │
                    └───────────┬────────────┘
                                │
                 ┌──────────────┼──────────────┐
                 ▼              ▼              ▼
             Web Views       DRF APIs       Background
                 |                           Tasks
                 │              │              │
                 └──────────────┼──────────────┘
                                ▼
                    ┌────────────────────────┐
                    │    Policy Enforcement  │
                    │                        │
                    │ • Access Control       │
                    │ • Validation           │
                    │ • Throttling           │
                    │ • CSRF / CORS          │
                    │ • Security Headers     │
                    └───────────┬────────────┘
                                │
                                ▼
                    ┌────────────────────────┐
                    │ Data Protection        │
                    │                        │
                    │ • Encrypted Secrets    │
                    │ • Protected Credentials│
                    │ • Database Security    │
                    └───────────┬────────────┘
                                │
                                ▼
                         Audit / Logging

Security Boundaries

DjangoPlay uses several distinct security boundaries.

Boundary Responsibility
Identity Boundary Establishes authenticated identity through AuthX
Request Boundary Applies middleware, request context, and request-level protection
Authorization Boundary Applies permissions, RBAC, and resource visibility policies
Application Boundary Validates and executes business workflows through services
Data Boundary Controls access to persistent application data
Secret Boundary Protects encryption keys, passwords, API credentials, and service credentials
Audit Boundary Records meaningful security and application state changes

These boundaries are complementary rather than interchangeable.

Authentication establishes who the caller is.

Authorization determines what that identity may do.

Validation and request protection determine whether the request is acceptable to process.

Authentication

AuthX is the external identity authority for DjangoPlay.

text
Client
   │
   ▼
 AuthX
   │
   │ authenticated identity / JWT
   ▼
DjangoPlay

DjangoPlay does not treat authentication and authorization as the same concern.

The authentication boundary establishes the identity context that downstream authorization policies consume.

AuthX JWT Authority

AuthX is the sole JWT signing authority for AuthX identity JWTs.

text
                         signs
DjangoPlay  ───────────► AuthX
                           │
                           │ JWT
                           ▼
                      DjangoPlay
                           │
                           │ verifies
                           ▼
                    AuthX public key

AuthX owns the RSA private signing key.

DjangoPlay uses the corresponding public verification material rather than possessing AuthX's private signing key.

This creates a clear trust boundary:

text
AuthX
 └── JWT signing authority

DjangoPlay
 └── JWT consumer / verifier

DjangoPlay's own JWT_SIGNING_KEY is a separate credential and must not be confused with AuthX's RSA signing keys.

Authentication Boundary

The authentication context flows into the DjangoPlay request pipeline.

text
                  AuthX
                    │
                    ▼
             Authenticated Identity
                    │
                    ▼
          DjangoPlay Request Context
                    │
                    ▼
            Authorization Policies

Downstream application code should consume the established identity context rather than implementing independent authentication mechanisms.

Authorization

Authentication alone does not grant access to application resources.

DjangoPlay applies authorization through permissions, roles, and resource-specific policies.

text
Authenticated Identity
          │
          ▼
   Authorization Policy
          │
     ┌────┴────┐
     │         │
    Allow     Deny
     │         │
     ▼         ▼
 Application  Request

The authorization layer is responsible for decisions such as:

  • Whether the caller has the required permission
  • Whether a resource is visible to the caller
  • Whether an operation is allowed for the caller's role
  • Whether an internal resource should remain restricted

RBAC and Policy Enforcement

DjangoPlay uses role-aware policies rather than assuming that authentication implies unrestricted access.

The IssueTracker integration is an example of this boundary.

text
Authenticated User
        │
        ▼
Identity Resolver
        │
        ▼
Issue Visibility / RBAC Policy
        │
        ├── Public / permitted resource
        │
        └── Internal / restricted resource

For GenericIssueTracker, DjangoPlay owns application-specific visibility and RBAC policy while the reusable package remains independent of DjangoPlay's role model.

This follows the broader platform principle that application-specific policy belongs in DjangoPlay rather than being embedded into reusable infrastructure.

Request Boundary

All incoming application requests pass through the Django request boundary before reaching application behavior.

text
Client
  │
  ▼
Middleware / Request Context
  │
  ▼
URL Routing
  │
  ├── Django Web Views
  │
  └── DRF APIs

The request boundary is responsible for establishing the context in which authentication, authorization, validation, and application services operate.

The application architecture explicitly places authentication, security, permissions, and request context in this boundary.

Input and Request Protection

Request protection is applied before untrusted input reaches sensitive application workflows.

The security boundary includes:

  • Request validation
  • Authentication checks
  • Authorization checks
  • CSRF protection for applicable browser flows
  • CORS policy for browser/API interaction
  • Security headers
  • Request throttling
  • Bot protection where enabled

These controls complement application-level validation.

text
Incoming Request
       │
       ▼
Request Protection
       │
       ▼
Authentication
       │
       ▼
Authorization
       │
       ▼
Application Validation
       │
       ▼
Business Workflow

CSRF and CORS

DjangoPlay distinguishes browser request protection from cross-origin API policy.

CSRF

CSRF protection applies to browser-based state-changing request flows where Django's CSRF mechanism is applicable.

text
Browser
   │
   ▼
Django CSRF Protection
   │
   ▼
State-changing Request

CORS

CORS controls which browser origins may interact with API endpoints across origins.

text
Browser Origin
      │
      ▼
CORS Policy
      │
 ┌────┴────┐
 │         │
Allow     Deny

CORS configuration is environment-specific. The development configuration uses local origins while production uses the actual production browser origins.

Bot Protection

DjangoPlay supports Cloudflare Turnstile as an optional request-protection integration.

text
Client
  │
  ▼
Turnstile Challenge
  │
  ▼
DjangoPlay Verification
  │
  ├── Valid
  │    │
  │    ▼
  │  Continue
  │
  └── Invalid
       │
       ▼
     Reject

Turnstile credentials are environment-specific and are only required when Turnstile protection is enabled.

The supported configuration includes development, staging, and production Turnstile key pairs.

Abuse Protection

DjangoPlay supports application-level flow throttling and optional IP reputation checks.

text
Request
   │
   ▼
Flow Throttling
   │
   ├── Within limit ──────► Continue
   │
   └── Limit exceeded ────► Reject / throttle

AbuseIPDB is an optional integration.

text
Request / IP
     │
     ▼
Abuse Detection
     │
     ▼
AbuseIPDB

An AbuseIPDB API key is not required for a normal installation. It is only required when AbuseIPDB-backed abuse/IP reputation functionality is enabled.

Flow Throttling

DjangoPlay uses flow-oriented throttling for sensitive application workflows.

The purpose is to limit repeated requests rather than relying exclusively on global API rate limiting.

Examples include flows such as:

text
Signup
Password Reset
Verification
Authentication-related Requests

The throttling layer can enforce limits based on configured dimensions such as email or IP.

text
Request
  │
  ▼
Flow Identifier
  │
  ▼
Throttle Policy
  │
  ├── Allowed ──────► Execute Flow
  │
  └── Limited ──────► Reject / Delay

This provides a security control against automated abuse of high-value application workflows.

Application Validation

Validation is performed before business operations are executed.

text
Request
   │
   ▼
Serializer / Form / Input Validation
   │
   ▼
Application Service
   │
   ▼
Domain Operation

Validation is not treated as a replacement for authorization.

A valid request from an unauthorized identity must still be rejected.

text
Valid Input
     +
Authorized Identity
     │
     ▼
Allowed Operation

Both conditions are required.

Service-Layer Security

DjangoPlay follows a service-first architecture.

Views and DRF endpoints should delegate meaningful application behavior to services rather than implementing complete workflows themselves.

text
Web View / DRF API
        │
        ▼
Application Service
        │
   ┌────┼────┐
   │    │    │
Auth  Policy Validation
   │    │    │
   └────┼────┘
        ▼
   Domain Operation

This provides a consistent location for enforcing business-level policy, validation, and integration orchestration.

Secret Protection

Sensitive DjangoPlay configuration is separated from non-secret structured configuration.

text
~/.dplay/
├── .secrets
├── .authx
├── config.yaml
└── .appdata

.secrets contains DjangoPlay secrets, credentials, passwords, API keys, and other sensitive integration configuration.

The encryption workflow uses:

text
~/.dplay/.secrets
        │
        ▼
paystream/security/encrypt_env.py
        │
        ▼
Encrypted DjangoPlay Environment

The configuration reference explicitly identifies ENCRYPTION_KEY as the master key used by DjangoPlay's environment encryption workflow.

Credential Separation

DjangoPlay deliberately separates credentials belonging to different security domains.

text
DjangoPlay
    │
    ├── DB_PASSWORD
    ├── JWT_SIGNING_KEY
    └── AUTHX_SERVICE_TOKEN


AuthX
    │
    ├── POSTGRES_PASSWORD
    ├── JWT_PRIVATE_KEY
    └── JWT_PUBLIC_KEY

These values have different owners and purposes.

In particular:

text
DB_PASSWORD
    !=
POSTGRES_PASSWORD

JWT_SIGNING_KEY
    !=
JWT_PRIVATE_KEY

AUTHX_SERVICE_TOKEN
    !=
database password

The configuration reference explicitly documents these boundaries.

AuthX Service Authentication

DjangoPlay communicates with AuthX using a dedicated service credential.

text
DjangoPlay
     │
     │ AUTHX_SERVICE_TOKEN
     ▼
   AuthX

The service credential is distinct from:

  • DjangoPlay's database password
  • AuthX's database password
  • AuthX's JWT private key
  • DjangoPlay's own JWT signing secret

This prevents one credential from implicitly becoming a credential for another security domain.

Data Protection

Persistent application data is protected behind the application data boundary.

text
Application Service
       │
       ▼
Data Access
       │
       ▼
PostgreSQL

The application should not expose raw persistence operations directly to untrusted request handlers.

Application services and policies determine which domain operations are permitted before persistent state is changed.

Auditability

Security-relevant and meaningful application state changes are observable through DjangoPlay's audit infrastructure.

text
Authorization
     │
     ▼
Application Service
     │
     ▼
State Change
     │
     ▼
Audit

Auditability provides attribution and traceability for meaningful state changes.

The platform's design principle is Auditability by Default: meaningful state changes should be observable and attributable.

Security and Background Tasks

Celery tasks execute outside the HTTP request lifecycle, but they remain part of the trusted application runtime.

text
Django Request
     │
     ▼
Application Service
     │
     ▼
Celery Task
     │
     ▼
Background Operation

Background tasks must not be treated as implicitly authorized merely because they execute outside an HTTP request.

Task-level workflows should operate using trusted application context and explicitly defined service boundaries.

Security Across Web and API Interfaces

DjangoPlay exposes both server-rendered Django views and DRF APIs.

Both interfaces ultimately converge on application services and security policies.

text
                 Request
                    │
             ┌──────┴──────┐
             ▼             ▼
         Django Web      DRF API
             │             │
             └──────┬──────┘
                    ▼
             Security / Policy
                    │
                    ▼
             Application Service

This prevents the API and web interfaces from developing completely separate authorization rules for the same application operation.

Security and GenericIssueTracker

GenericIssueTracker is integrated through DjangoPlay's dedicated integration layer.

Security responsibilities are split between the reusable package and DjangoPlay.

text
DjangoPlay Identity
        │
        ▼
IssueTracker Identity Resolver
        │
        ▼
Issue Visibility / RBAC Policy
        │
        ▼
IssueTracker Services
        │
        ▼
GenericIssueTracker

DjangoPlay owns:

  • Identity adaptation
  • Application-specific RBAC
  • Visibility rules
  • Integration services
  • UI/API access policy

GenericIssueTracker owns its reusable issue domain.

This prevents DjangoPlay-specific authorization assumptions from leaking into the reusable package.

Fail-Closed Authorization

DjangoPlay follows a fail-closed security principle.

text
Authorization Decision
        │
   ┌────┴────┐
   │         │
 Allow      Unknown
   │         │
   ▼         ▼
Execute     Reject

An operation should not become permitted merely because a permission check is missing, ambiguous, or unable to establish the required authorization context.

This principle is particularly important for internal resources and administrative operations.

Security Configuration

Security-sensitive configuration is environment-aware.

Typical differences include:

Security Area Development Production
Django settings paystream.settings.dev paystream.settings.prod
JWT keys Development key pair Fresh production key pair
Service credentials Development values Unique production values
CORS Local development origins Production browser origins
Google OAuth Only when tested/enabled Only when enabled
Turnstile Only when enabled Only when enabled
AbuseIPDB Only when used Only when used
R2 Only when used When CDN/R2 publishing is used
AI credentials Selected development provider Selected production provider

Development credentials and private keys must not be reused in production.

Security Responsibility Matrix

Security Area Primary Responsibility
Identity AuthX
JWT signing for AuthX identity tokens AuthX
JWT verification in DjangoPlay DjangoPlay
Application authentication context DjangoPlay
RBAC DjangoPlay
Resource visibility DjangoPlay
Request context Django middleware / application boundary
Input validation Django forms / DRF serializers / application services
CSRF Django/browser request protection
CORS DjangoPlay API configuration
Flow throttling DjangoPlay application/security services
Bot protection Cloudflare Turnstile integration
IP reputation Optional AbuseIPDB integration
Secret encryption DjangoPlay encryption workflow
Persistent application data PostgreSQL
Auditability DjangoPlay audit infrastructure

Security Layers

The complete security model can be summarized as layered controls:

text
                    CLIENT
                       │
                       ▼
              ┌─────────────────┐
              │ Request Boundary │
              └────────┬────────┘
                       │
          ┌────────────┼────────────┐
          ▼            ▼            ▼
    Authentication   Request      Abuse
       / AuthX      Protection   Protection
          │            │            │
          └────────────┼────────────┘
                       ▼
              ┌─────────────────┐
              │ Authorization   │
              │ RBAC / Policies │
              └────────┬────────┘
                       │
                       ▼
              ┌─────────────────┐
              │ Validation      │
              │ / Services      │
              └────────┬────────┘
                       │
                       ▼
              ┌─────────────────┐
              │ Data Boundary   │
              │ PostgreSQL      │
              └────────┬────────┘
                       │
                       ▼
              ┌─────────────────┐
              │ Audit / Logging │
              └─────────────────┘

Architectural Principles

The security architecture follows these principles:

  1. Identity is a protected boundary.
  2. AuthX is the identity authority for DjangoPlay authentication.
  3. AuthX is the sole signing authority for AuthX identity JWTs.
  4. Authentication and authorization remain separate concerns.
  5. Authorization is enforced through explicit permissions and policies.
  6. Application-specific RBAC does not belong inside reusable packages.
  7. Request protection occurs before sensitive application workflows execute.
  8. Input validation does not replace authorization.
  9. Sensitive workflows are protected by flow-level throttling.
  10. Bot protection and IP reputation are optional, feature-specific controls.
  11. Secrets and service credentials are separated by ownership and purpose.
  12. DjangoPlay and AuthX database credentials are independent.
  13. DjangoPlay's own JWT secret is separate from AuthX's RSA signing keys.
  14. Meaningful state changes remain attributable through audit infrastructure.
  15. Security controls should fail closed when authorization cannot be established.
  16. Development and production security credentials must remain separate.

Architectural Principle

DjangoPlay does not depend on a single security mechanism.

Security is implemented as a chain of independent controls:

text
Identity
   │
   ▼
Request Protection
   │
   ▼
Authorization
   │
   ▼
Validation
   │
   ▼
Business Policy
   │
   ▼
Data Protection
   │
   ▼
Auditability

Each layer has a specific responsibility.

A valid identity does not automatically grant access.

Valid input does not automatically authorize an operation.

An authenticated request still passes through application policy.

A successful operation remains observable through the audit boundary.

This layered model allows DjangoPlay to maintain a consistent security posture across its web UI, DRF APIs, background processing, reusable integrations, and external service boundaries.