--- since: 1.2.1 --- # DjangoPlay — Integration Architecture DjangoPlay uses integration boundaries to connect the application with identity services, reusable platform components, infrastructure services, and external providers. The integration architecture separates: * Internal reusable Django integrations * External identity and service providers * AI provider integrations * Storage and CDN integrations * Email integrations * Application-specific adapters and policies The goal is to keep provider-specific and integration-specific behavior outside the core application workflows. ## Architecture ```mermaid flowchart TD APP["DjangoPlay Application"] subgraph INTERNAL["DjangoPlay Internal Integrations"] ISSUE["GenericIssueTracker Integration
paystream.integrations.issuetracker"] ISSUE_ID["DjangoPlay Identity Resolver"] ISSUE_POLICY["Visibility / RBAC Policy"] ISSUE_SERVICE["Issue Query / Mutation Services"] ISSUE_EVENTS["IssueTracker Signals
Domain Events / Audit"] ISSUE --> ISSUE_ID ISSUE --> ISSUE_POLICY ISSUE --> ISSUE_SERVICE ISSUE --> ISSUE_EVENTS ISSUE_ID --> APP ISSUE_POLICY --> APP ISSUE_SERVICE --> APP ISSUE_EVENTS --> APP end subgraph EXTERNAL["External Integrations"] AUTHX["AuthX
Identity Service"] EMAIL["SMTP / Email Provider"] R2["Cloudflare R2
Asset Storage / CDN"] AI["AI Providers"] XAI["xAI"] OPENAI["OpenAI"] OPENROUTER["OpenRouter"] CUSTOM["Custom / Local
Ollama / vLLM"] AI --> XAI AI --> OPENAI AI --> OPENROUTER AI --> CUSTOM end APP --> AUTHX APP --> EMAIL APP --> R2 APP --> AI ISSUE_SERVICE --> AUTHX ISSUE_EVENTS --> APP classDef application fill:#e5f6f1,stroke:#159a7a,stroke-width:2px,color:#075d4b classDef internal fill:#fff2d9,stroke:#d89b18,stroke-width:2px,color:#76520b classDef external fill:#eeeeff,stroke:#5a55c9,stroke-width:2px,color:#403b91 classDef provider fill:#f5f3ed,stroke:#777777,stroke-width:1px,color:#444444 class APP application class ISSUE,ISSUE_ID,ISSUE_POLICY,ISSUE_SERVICE,ISSUE_EVENTS internal class AUTHX,EMAIL,R2,AI external class XAI,OPENAI,OPENROUTER,CUSTOM provider ```` ## Integration Flow ```text DJANGOPLAY │ ┌───────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ Internal Identity / External Integrations Application Services │ │ │ │ ▼ ├── SMTP / Email │ AuthX ├── Cloudflare R2 │ └── AI Providers │ ▼ GenericIssueTracker │ ┌─────┼─────────────┐ │ │ │ ▼ ▼ ▼ Identity RBAC Services Resolver / Policy / Queries │ │ │ └─────┼─────────────┘ │ ▼ GenericIssueTracker Domain API ``` ## Integration Categories DjangoPlay integrations fall into two primary categories. | Category | Examples | Responsibility | | ------------------------------- | --------------------- | ---------------------------------------------------------------- | | Internal / Reusable Integration | GenericIssueTracker | Integrates reusable Django platform capabilities into DjangoPlay | | External Service Integration | AuthX | Identity and authentication services | | External Service Integration | SMTP / Email Provider | Transactional email delivery | | External Service Integration | Cloudflare R2 | Asset storage and CDN workflow | | External Service Integration | AI Providers | LLM inference and model catalog services | Internal integrations are still kept behind explicit adapter boundaries so that the host application does not become tightly coupled to reusable package internals. ## GenericIssueTracker Integration GenericIssueTracker is a reusable Django issue-tracking package integrated into DjangoPlay through the dedicated: ```text paystream.integrations.issuetracker ``` integration layer. The integration provides the DjangoPlay-specific behavior required to use the generic package without modifying the package itself. ```text DjangoPlay │ ▼ paystream.integrations.issuetracker │ ▼ GenericIssueTracker ``` GenericIssueTracker provides the reusable issue-tracking domain and API capabilities, while DjangoPlay provides application-specific integration behavior. ## GenericIssueTracker Integration Boundary The DjangoPlay integration layer contains several responsibilities. ```text GenericIssueTracker Integration │ ┌───────┼──────────────┬───────────────┐ │ │ │ │ ▼ ▼ ▼ ▼ Identity Access Mutation Query Resolver / RBAC Services Services │ │ │ │ └───────┼──────────────┴───────────────┘ │ ▼ GenericIssueTracker ``` The integration therefore adapts DjangoPlay application concepts to the generic package rather than duplicating the package's domain logic. ## Identity Integration DjangoPlay provides a dedicated identity resolver: ```text users.services.issuetracker_identity_resolver ``` The resolver adapts DjangoPlay's authenticated user model to the identity contract expected by GenericIssueTracker. Conceptually: ```text DjangoPlay User │ ▼ DjangoPlay IssueTracker Identity Resolver │ ▼ GenericIssueTracker Identity Contract ``` The identity contract includes information such as: * User ID * Email * Authentication state * Superuser state * Role code The integration remains read-only with respect to identity resolution. GenericIssueTracker therefore does not need to understand DjangoPlay's internal user or employment-profile implementation. ## GenericIssueTracker Authorization DjangoPlay applies its own application-level authorization policies to the GenericIssueTracker integration. The integration includes an explicit visibility service: ```text IssueVisibilityService ``` The service applies role-based visibility rules for internal issues. ```text Authenticated Identity │ ▼ IssueVisibilityService │ ├── Superuser override ├── Allowed role check └── Public / reporter visibility │ ▼ Visible Issue Queryset ``` Internal issue access is controlled through the configured allowed roles rather than through implicit role hierarchy. This keeps authorization policy in DjangoPlay instead of embedding DjangoPlay-specific policy into GenericIssueTracker. ## GenericIssueTracker Mutation Services DjangoPlay provides an integration-level mutation service: ```text IssueMutationService ``` The service coordinates operations such as: * Issue creation * Comment creation * Attachment handling * Identity resolution * Anonymous reporting policy * Visibility checks * Validation * Issue lifecycle operations The service delegates domain operations to GenericIssueTracker rather than reimplementing the issue lifecycle. ```text DjangoPlay UI / API │ ▼ IssueMutationService │ ├── Identity resolution ├── DjangoPlay policy checks ├── Validation │ ▼ GenericIssueTracker │ └── Domain operation ``` ## GenericIssueTracker Query Services DjangoPlay also provides integration-level query services. ```text IssueQueryService │ ├── Base queryset ├── Visibility filtering ├── Status filtering ├── Priority filtering └── Deterministic ordering │ ▼ GenericIssueTracker Issue ``` The query service keeps DjangoPlay-specific presentation and filtering requirements outside the reusable package. ## GenericIssueTracker UI DjangoPlay provides its own server-rendered IssueTracker UI. The integration exposes UI routes separately from the package's reusable domain/API functionality. ```text Browser │ ▼ DjangoPlay IssueTracker UI │ ▼ paystream.integrations.issuetracker.views.ui │ ▼ Integration Services │ ▼ GenericIssueTracker ``` The UI includes functionality for: * Issue listing * Issue creation * Issue detail * Comments * Attachments * Status handling * Authentication/session handling The UI therefore remains a DjangoPlay concern. ## GenericIssueTracker API DjangoPlay exposes the GenericIssueTracker functionality through its own integration API boundary. ```text REST Client │ ▼ DjangoPlay IssueTracker API │ ▼ paystream.integrations.issuetracker.views.api.v1 │ ▼ GenericIssueTracker ``` The integration contains DjangoPlay-specific serializers and API views while reusing the generic package's domain and serializer capabilities where appropriate. ## GenericIssueTracker Events GenericIssueTracker emits domain signals such as: ```text issue_created issue_updated issue_deleted issue_commented issue_status_changed ``` DjangoPlay subscribes to these events through: ```text paystream.integrations.issuetracker.signals ``` The integration converts relevant IssueTracker activity into DjangoPlay internal domain events. ```text GenericIssueTracker │ ▼ IssueTracker Signal │ ▼ DjangoPlay Integration Signal Handler │ ▼ DjangoPlay Domain Event │ ▼ Audit / Observability Subscribers ``` The signal integration deliberately avoids coupling the GenericIssueTracker domain model directly to DjangoPlay's audit or event infrastructure. ## GenericIssueTracker Audit Boundary IssueTracker models are registered with DjangoPlay's audit tracking system. The integration tracks objects such as: ```text genericissuetracker.Issue genericissuetracker.IssueComment genericissuetracker.IssueAttachment ``` The integration therefore connects IssueTracker activity to DjangoPlay's existing audit infrastructure without placing audit persistence logic inside the reusable package. ## GenericIssueTracker Labels DjangoPlay maintains its own application-specific IssueTracker labels. The integration provides: ```text IssueLabelBootstrapService ``` which ensures required labels exist during application startup. Examples include: ```text bug-internal bug-public ``` The label definitions are maintained by the DjangoPlay integration rather than being hard-coded into GenericIssueTracker. ```text DjangoPlay Integration │ ▼ IssueLabelBootstrapService │ ▼ GenericIssueTracker Labels ``` ## GenericIssueTracker and Helpdesk DjangoPlay also integrates existing Helpdesk functionality with GenericIssueTracker. Migrated or synchronized Helpdesk records can reference corresponding GenericIssueTracker issues. The architecture therefore allows the reusable IssueTracker domain to act as the common issue representation while legacy/application-specific Helpdesk workflows remain in DjangoPlay. ```text DjangoPlay Helpdesk │ │ migration / synchronization ▼ GenericIssueTracker Issue ``` Support-ticket-synchronized issues can remain available for internal traceability without necessarily being presented as ordinary issues on the public IssueTracker board. ## AuthX Integration AuthX is DjangoPlay's external identity service. ```text DjangoPlay │ ▼ AuthX │ └── Identity / Authentication ``` Authentication architecture is documented separately. The integration boundary is responsible for communication with AuthX while DjangoPlay retains application-level authorization. GenericIssueTracker uses DjangoPlay's identity resolver rather than directly implementing its own authentication integration. ```text AuthX │ ▼ DjangoPlay Authentication │ ▼ DjangoPlay User Context │ ▼ GenericIssueTracker Identity Resolver ``` ## Email Integration DjangoPlay communicates with an SMTP or email provider for transactional email. ```text DjangoPlay │ ▼ SMTP / Email Provider │ ▼ Recipient ``` Email operations may originate from: * Web requests * Application services * Celery background tasks The provider remains external to DjangoPlay. ## Cloudflare R2 Integration Cloudflare R2 provides object storage for the frontend CDN workflow. ```text DjangoPlay / Frontend Packaging │ ▼ Cloudflare R2 │ ▼ CDN Delivery ``` R2 is optional for ordinary local development when frontend assets are served locally. The integration becomes active when the CDN asset workflow is enabled. ## AI Provider Integration DjangoPlay's `aicore` application uses a provider abstraction rather than coupling application logic directly to one LLM provider. ```text DjangoPlay │ ▼ aicore │ ▼ Provider Registry │ ├── xAI ├── OpenAI ├── OpenRouter └── Custom / Local │ ├── Ollama └── vLLM ``` The provider registry allows the application to switch providers without changing the higher-level chat workflow. Provider credentials remain server-side where the provider integration requires them. BYOK flows are handled separately by `aicore` and are scoped according to its security model. ## Integration Isolation DjangoPlay keeps integration-specific behavior outside the core application layers. ```text DjangoPlay Application │ ┌────────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ Internal Identity External Integrations Services Providers │ │ │ ▼ ▼ ├── SMTP GenericIssueTracker AuthX ├── R2 └── AI ``` This allows each integration boundary to own: * Provider-specific configuration * Request/response adaptation * Authentication credentials * Integration-specific policy * Error handling * Mapping between external and internal representations ## Integration Responsibility | Integration | Type | DjangoPlay Responsibility | External / Reusable Responsibility | | ------------------- | ------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------- | | GenericIssueTracker | Reusable internal package | Identity adapter, RBAC, visibility, UI/API integration, services, events, labels | Issue domain, lifecycle, reusable API capabilities | | AuthX | External service | Authentication integration and application context | Identity authority, credentials, JWT issuance | | SMTP / Email | External service | Email composition and delivery orchestration | Message transport and delivery | | Cloudflare R2 | External service | Asset packaging/upload workflow | Object storage | | AI Providers | External services | Provider registry, chat orchestration, access controls | Model inference and provider APIs | ## Configuration Boundaries Integration credentials and settings remain associated with the integration that consumes them. Examples include: ```text AuthX ├── AuthX service URL ├── Service credentials └── JWT verification configuration Email └── SMTP credentials Cloudflare R2 ├── Endpoint ├── Access key ├── Secret key └── Bucket configuration AI ├── Provider configuration ├── API keys └── Custom provider configuration ``` GenericIssueTracker itself is primarily configured through DjangoPlay's `GENERIC_ISSUETRACKER_*` settings and the integration's application-level services and policies. ## Failure Isolation Integration boundaries should prevent provider-specific failures from unnecessarily propagating through unrelated application functionality. For example: ```text AI Provider Failure │ ▼ aicore integration X │ └── Core authentication remains available R2 Failure │ ▼ CDN asset workflow X │ └── Core Django application remains available GenericIssueTracker Failure │ ▼ IssueTracker integration X │ └── Unrelated DjangoPlay applications remain isolated ``` The exact failure behavior depends on the calling workflow and whether the operation is synchronous or asynchronous. ## Local Development Local development does not require every integration to be active. A minimal runtime can use: ```text DjangoPlay │ ├── PostgreSQL ├── Redis └── AuthX ``` Additional integrations can be enabled when required: ```text Optional ├── Google SSO ├── SMTP ├── Cloudflare R2 ├── AI provider └── CDN workflow ``` GenericIssueTracker is part of the DjangoPlay application integration when the IssueTracker functionality is installed and enabled. ## Integration Boundaries The resulting architecture can be summarized as: ```text DJANGOPLAY │ ┌───────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ Internal Identity External Integrations Service Providers │ │ │ ▼ ▼ ┌───────┼────────┐ GenericIssueTracker AuthX │ │ │ │ SMTP R2 AI ┌──────┼──────┐ │ │ │ │ ┌─────┼─────┐ Identity RBAC Services xAI OpenAI Custom Resolver Policy / Queries │ │ OpenRouter ``` ## Architectural Principles The integration architecture follows these principles: 1. **Integrations have explicit boundaries.** 2. **Reusable packages remain generic and do not contain DjangoPlay-specific business policy.** 3. **DjangoPlay-specific adapters translate application concepts into reusable package contracts.** 4. **GenericIssueTracker owns issue-domain behavior; DjangoPlay owns its integration policy and presentation.** 5. **Identity resolution is adapted through a dedicated DjangoPlay resolver.** 6. **Authorization and visibility remain DjangoPlay application concerns.** 7. **IssueTracker domain events are adapted into DjangoPlay internal events without coupling the reusable package to DjangoPlay infrastructure.** 8. **External provider credentials remain isolated to their respective integrations.** 9. **AI provider implementations are accessed through a provider abstraction.** 10. **External integrations should be replaceable without rewriting core application workflows.** 11. **Optional integrations should not become mandatory dependencies for unrelated application functionality.** 12. **Integration failures should remain isolated wherever the workflow permits.** ## Architectural Principle DjangoPlay treats integrations as boundaries between the application and capabilities that are either reusable or externally provided. ```text DjangoPlay │ ┌─────────────┼─────────────┐ │ │ │ ▼ ▼ ▼ Reusable Identity External Packages Services Providers │ │ │ ▼ ▼ ▼ GenericIssueTracker AuthX SMTP / R2 / AI ``` The integration layer adapts these capabilities to DjangoPlay without allowing provider-specific implementation details or reusable-package assumptions to spread throughout the application. This keeps DjangoPlay modular while allowing reusable platform components such as GenericIssueTracker to evolve independently.