Files
azionelab/docs/architecture.md

163 lines
5.8 KiB
Markdown

# Architecture
AzioneLab is a public website for a theatre company with a small booking system for performances.
The architecture is intentionally simple: one Django backend, one Angular frontend, one PostgreSQL database, and nginx as the public reverse proxy. There is no Celery, Redis, message broker, or separate worker service at this stage.
## Components
### Public frontend
The public frontend is an Angular application using Angular Material.
Responsibilities:
- render descriptive pages for the theatre company;
- render the public list of shows;
- render public show and performance detail pages;
- provide the booking form for a selected performance;
- show reservation submission, confirmation, and check-in feedback states;
- call the backend through REST APIs.
The frontend must not calculate authoritative availability. It may display availability returned by the backend, but the backend remains responsible for final capacity validation.
### Backend API
The backend is a Django 5.2 LTS application using Django REST Framework.
Responsibilities:
- expose public read APIs for shows, venues, and performances;
- expose public booking and reservation confirmation APIs;
- expose an authenticated check-in verification API;
- provide Django admin or an equivalent authenticated administration area;
- store reservations, tokens, and check-in state;
- calculate performance availability server-side;
- send reservation confirmation emails;
- generate QR codes after reservation confirmation.
The backend runs with gunicorn in production.
### Administration area
The first administration area should use Django admin unless a custom Angular admin becomes necessary later.
Administrators can manage:
- shows;
- venues;
- performances;
- total room capacity;
- manually occupied seats;
- optional additional seats available during booking;
- reservation status and check-in records when operationally necessary.
Admin functionality must require authenticated staff access.
### Database
PostgreSQL is the system of record.
It stores:
- show and venue content;
- performance scheduling and capacity configuration;
- reservations and explicit reservation status;
- reservation tokens used for confirmation and QR verification;
- check-in records.
Capacity checks must happen inside database transactions to avoid overbooking when multiple users book at the same time.
### Email
The backend sends transactional emails for:
- reservation confirmation link after booking submission;
- optional confirmation success email containing the QR code or QR verification link.
Email delivery can use Django's email backend configuration. No asynchronous email worker is required initially; failures should be logged without exposing tokens or personal data.
### QR code generation
The backend generates QR codes using a small Python library such as `qrcode` or `segno`.
QR codes must contain only an opaque token or verification URL. They must not contain names, email addresses, phone numbers, notes, or other personal data.
### nginx
nginx is the public entry point.
Responsibilities:
- terminate HTTP traffic, and TLS when configured;
- serve the built Angular static assets;
- reverse proxy API and admin requests to gunicorn;
- serve static and media files according to the deployment configuration.
## Runtime Dependencies
Required runtime dependencies:
- Python;
- Django 5.2 LTS;
- Django REST Framework;
- gunicorn;
- PostgreSQL;
- Angular;
- Angular Material;
- nginx;
- Docker Compose;
- a Python QR code library such as `qrcode` or `segno`;
- an SMTP-compatible email provider or relay.
Not included at this stage:
- Celery;
- Redis;
- background workers;
- separate search, cache, or queue services.
## Data Flow
1. A visitor opens the website through nginx.
2. nginx serves the Angular frontend.
3. The frontend calls public backend API endpoints for shows and performances.
4. The visitor submits a booking form for a specific performance.
5. The backend validates input, checks capacity server-side, creates a pending reservation, creates a confirmation token, and sends a confirmation email.
6. The visitor opens the confirmation link.
7. The backend validates the token, confirms the reservation if capacity is still available, and generates a QR code token or QR code image.
8. The visitor presents the QR code at the venue using a smartphone or printed copy.
9. Staff scans the QR code.
10. The backend validates the token and records a check-in if the reservation is confirmed and not already checked in.
## Deployment Topology
The initial deployment uses Docker Compose with these services:
- `nginx`: public reverse proxy and static frontend server;
- `frontend`: Angular build stage or static asset build source;
- `backend`: Django application served by gunicorn;
- `postgres`: PostgreSQL database.
Only nginx should be publicly exposed. The backend and database should be reachable only on the internal Compose network.
The initial Compose files live under `infra/docker/`. The backend and frontend images are placeholders until the Django and Angular applications are implemented.
## Architectural Constraints
- Keep the booking workflow synchronous and explicit.
- Keep all capacity validation on the backend.
- Store reservation status explicitly.
- Use opaque, random, non-guessable tokens.
- Do not place personal data in QR codes.
- Avoid optional infrastructure until the project needs it.
- Prefer Django admin for internal management before building custom admin UI.
## Relevant ADRs
- [ADR-0001: Use Django Monolith](adr/0001-use-django-monolith.md)
- [ADR-0002: Do Not Add an Async Task Queue Yet](adr/0002-no-async-task-queue.md)
- [ADR-0003: Use Opaque Tokens in QR Codes](adr/0003-qr-code-token-strategy.md)
- [ADR-0004: Use Email Confirmation for Reservations](adr/0004-email-confirmation-flow.md)
- [ADR-0007: Use Docker Compose for Deployment](adr/0007-use-docker-compose-for-deployment.md)