# Architecture ## Technology Stack ### Backend - **Django 5.2** — Web framework - **Django REST Framework** — RESTful API - **django-filter** — Advanced queryset filtering - **mozilla-django-oidc** — OpenID Connect authentication - **Pillow** — Image handling for documents and media - **Gunicorn** — Production WSGI server - **SQLite** — Development database - **PostgreSQL** — Production database - **Python 3.11+** ### Frontend - **PatternFly 5** — Enterprise UI framework (no build tools; loaded from CDN) - **Alpine.js 3** — Lightweight reactive framework (~3KB) - **Chart.js 4** — Oil/fuel consumption charts - **Font Awesome** — Icons No build pipeline. All JS is vanilla Alpine.js loaded as static files or from CDN. ### Deployment - **Red Hat UBI 9** — Container base image - **nginx** — Static/media file serving and TLS termination (sidecar) - **OpenShift / Kubernetes** — Container platform ## Project Structure ``` simple-aircraft-manager/ ├── simple_aircraft_manager/ # Project configuration │ ├── settings.py # Development settings (SQLite, DEBUG=True) │ ├── settings_prod.py # Production settings (requires env vars) │ ├── urls.py # URL routing │ └── wsgi.py ├── core/ # Core aircraft management │ ├── models.py # Aircraft, AircraftNote, AircraftEvent, roles, share tokens │ ├── views.py # API ViewSets + template views + public sharing │ ├── serializers.py # DRF serializers │ ├── permissions.py # RBAC permission classes │ ├── mixins.py # AircraftScopedMixin, EventLoggingMixin │ ├── events.py # Event logging (log_event) │ ├── oidc.py # OIDC backend + logout URL builder │ ├── context_processors.py # Template context (OIDC_ENABLED) │ ├── templates/ │ │ ├── base.html # Base template with PatternFly + Alpine.js │ │ ├── dashboard.html # Fleet dashboard │ │ ├── aircraft_detail.html # Tabbed aircraft detail page │ │ └── includes/ # Reusable template partials │ └── static/ │ ├── css/app.css # Custom styles │ └── js/ # Alpine.js components (see below) ├── health/ # Maintenance & compliance │ ├── models.py # Component, Squawk, Logbook, AD, Inspection, etc. │ ├── views.py # API ViewSets │ ├── serializers.py # DRF serializers (includes upload validation) │ ├── services.py # Airworthiness calculation logic │ └── logbook_import.py # AI-assisted logbook transcription ├── examples/openshift/ # OpenShift deployment manifests ├── Containerfile # Container image definition ├── docker-entrypoint.sh # Container startup script ├── requirements.txt # Development dependencies └── requirements-prod.txt # Production dependencies ``` ## Frontend Architecture (Alpine.js Mixin Pattern) The aircraft detail page is composed from feature mixins merged by `mergeMixins()` in `utils.js`: | File | Function | Feature | |------|----------|---------| | `aircraft-detail-components.js` | `componentsMixin()` | Component CRUD, tree sorting, status | | `aircraft-detail-squawks.js` | `squawksMixin()` | Squawk CRUD, priority helpers | | `aircraft-detail-notes.js` | `notesMixin()` | Note CRUD | | `aircraft-detail-oil.js` | `oilMixin()` | Oil record CRUD, consumption chart | | `aircraft-detail-fuel.js` | `fuelMixin()` | Fuel record CRUD, burn rate chart | | `aircraft-detail-logbook.js` | `logbookMixin()` | Logbook CRUD, file uploads, AI import | | `aircraft-detail-ads.js` | `adsMixin()` | AD CRUD, compliance records, history | | `aircraft-detail-inspections.js` | `inspectionsMixin()` | Inspection CRUD, history | | `aircraft-detail-documents.js` | `documentsMixin()` | Document/collection CRUD, viewer | | `aircraft-detail-major-records.js` | `majorRecordsMixin()` | Major repair/alteration CRUD | | `aircraft-detail-events.js` | `eventsMixin()` | Recent activity card, history modal | | `aircraft-detail-roles.js` | `rolesMixin()` | Role management, public sharing toggle | Composer: `aircraft-detail.js`. **Never use `{...spread}` to merge mixins** — it eagerly evaluates `get` properties. `mergeMixins()` preserves getter descriptors via `Object.getOwnPropertyDescriptors()`. Shared utilities in `utils.js` (loaded globally via `base.html`): `getCookie`, `mergeMixins`, `apiRequest`, `showNotification`, `formatDate`, `formatHours`, `getAirworthinessClass/Text/Tooltip`, `getSquawkPriorityClass`, `formatApiError`. ## Airworthiness Calculation `calculate_airworthiness(aircraft)` in `health/services.py` checks in order: 1. AD compliance 2. Grounding squawks (priority 0) 3. Inspection recurrency 4. Component replacement intervals Thresholds: overdue → RED; within 10 hours / 30 days → ORANGE. ## Content Security Policy All JS must be external files in `core/static/js/` — inline `