Desi-Clans/docs/ARCHITECTURE.md
2026-10-08 02:52:58 +05:30

275 lines
9 KiB
Markdown

# Architecture — Desi Clans
**Version:** 1.0
**Last updated:** 2026-04-04
---
## 1. System context
```
┌─────────────┐ HTTPS ┌──────────────┐ SQL ┌────────────┐
│ Browser │ ──────────────► │ FastAPI API │ ◄──────────► │ PostgreSQL │
│ (React) │ │ + static │ └────────────┘
└─────────────┘ │ media │
│ └──────┬───────┘
│ │
│ optional ▼
└──────────────────────► S3 / CDN (prod media)
```
- **Monorepo:** `frontend/`, `backend/`, `docs/`.
- **Deployment unit:** API container + static frontend (CDN or same origin) + managed Postgres.
- **No microservices in v1.** One API process, clear router boundaries for future split.
---
## 2. Architectural principles
1. **API-first content** — Public UI never hardcodes event copy or images.
2. **Thin client** — Business rules (inventory, check-in) live in the backend.
3. **Explicit phases** — Ship discovery + admin before native payments if needed.
4. **Boring tech** — Stack locked to PRD; no extra frameworks without ADR.
5. **Security defaults** — JWT for auth, parameterized SQL via SQLAlchemy, validated Pydantic I/O.
---
## 3. Repository layout (target)
```
DESI-CLANS/
├── frontend/
│ ├── public/
│ ├── src/
│ │ ├── api/ # Axios clients, types mirroring API_SPEC
│ │ ├── components/ # UI primitives + composites
│ │ ├── hooks/
│ │ ├── layouts/
│ │ ├── pages/ # Route-level views
│ │ ├── styles/ # Tailwind entry, tokens
│ │ ├── utils/ # seo, dates, formatters
│ │ ├── animations/ # GSAP contexts, ScrollTrigger setup
│ │ ├── App.jsx
│ │ └── main.jsx
│ ├── index.html
│ ├── vite.config.js
│ ├── tailwind.config.js
│ └── package.json
├── backend/
│ ├── alembic/
│ ├── app/
│ │ ├── routers/ # public, auth, admin, share, analytics, orders (future)
│ │ ├── services/ # domain logic
│ │ ├── models.py
│ │ ├── schemas.py
│ │ ├── auth.py
│ │ ├── config.py
│ │ ├── database.py
│ │ └── main.py
│ ├── scripts/ # seed, migrate helpers
│ ├── tests/
│ ├── Dockerfile
│ └── requirements.txt
├── docs/
└── README.md
```
---
## 4. Backend layers
| Layer | Responsibility |
|-------|----------------|
| **Routers** | HTTP, status codes, dependency injection, no business logic |
| **Services** | Transactions, orchestration (editions, media, tickets, email) |
| **Models** | SQLAlchemy ORM, enums |
| **Schemas** | Pydantic request/response; never expose hashed passwords |
**Cross-cutting**
- `config.py` — settings from environment (see `.env.example` when added).
- `auth.py` — JWT create/verify, `get_current_admin`, future `get_current_user`.
- Migrations — Alembic only; avoid `create_all` in production (dev convenience may exist temporarily).
---
## 5. Frontend layers
| Layer | Responsibility |
|-------|----------------|
| **Pages** | Data loading per route, SEO hooks, layout composition |
| **Components** | Presentational; accept props, no direct Axios in leaf components |
| **api/** | Base Axios instance, interceptors for admin token |
| **animations/** | GSAP timelines registered once; respect `prefers-reduced-motion` |
**Routing (React Router)**
- Public: `/`, `/events`, `/events/:slug`, `/subscribe` (optional dedicated page)
- Admin: `/admin/login`, `/admin/*` (protected)
- Account (phase): `/account`, `/account/tickets/:id`
- Check-in (phase): `/admin/check-in` or staff-only route
**SEO**
- Vite SPA: use `react-helmet-async` **only if** needed; prefer minimal approach:
- Default meta in `index.html`
- Per-route `document.title` + meta updates in page `useEffect`
- Backend `/share/events/{slug}` HTML for crawlers (already planned in API)
---
## 6. API boundaries
| Namespace | Auth | Purpose |
|-----------|------|---------|
| `/api/public/*` | None | Read editions, config, subscribe, outbound redirect, calendar |
| `/api/auth/*` | Credentials | Admin login (attendee login added with ticketing) |
| `/api/admin/*` | Admin JWT | CRUD editions, media, links, users, subscribers |
| `/api/admin/analytics/*` | Admin JWT | Click summaries |
| `/share/events/{slug}` | None | OG HTML for social crawlers |
| `/api/orders/*` (future) | User JWT | Checkout, my tickets |
| `/api/check-in/*` (future) | Staff JWT | Validate QR, mark checked in |
Public reads are cache-friendly (CDN `Cache-Control` on GET editions list with short TTL).
---
## 7. Media pipeline
1. Admin uploads via multipart → service stores file.
2. **Local:** `upload_dir` served at `/media/...`
3. **Production:** S3 bucket + public or signed URLs; store `file_path` key in DB.
4. Optional thumbnails generated on upload (service layer); expose `thumb_url` in API.
---
## 8. Ticketing architecture (target)
```
EventEdition ──< TicketTier
│
Order ──────────────┼──< OrderLine (tier, qty, unit_price)
│
└──< Ticket (code, qr_secret, status, checked_in_at)
```
**Checkout flow (native)**
1. Client POST order intent with tier + quantity.
2. Server validates window, inventory; creates `pending` order; returns payment session (phase B).
3. Webhook confirms payment → status `paid` → issue tickets with unique codes.
4. Email service sends QR (PNG or link to ticket page).
**QR validation**
- Payload: `ticket_id` + HMAC signature (server secret).
- Scan endpoint: verify signature, edition match, status `issued` → `checked_in`.
**Outbound mode (per edition flag)**
- `ticketing_mode: outbound | native`
- Outbound uses existing `bookmyshow_url`, `district_url`, etc., via `/api/public/go` click tracking.
---
## 9. Security
- Passwords: bcrypt via passlib.
- JWT: HS256, `ACCESS_TOKEN_EXPIRE_MINUTES` configurable.
- CORS: explicit origin list from env.
- Rate limit: add at reverse proxy (nginx/Cloudflare) for public POST subscribe and auth login.
- Admin actions audited via structured logs (user id, action, entity id).
---
## 10. Performance requirements
| Area | Target |
|------|--------|
| Public GET editions | p95 &lt; 300ms @ warm DB |
| Image delivery | WebP/AVIF where supported; width variants |
| Frontend bundle | Route-based code splitting for admin |
| DB | Indexes on `slug`, `event_type`, `is_published`, `event_date` |
| Animation | GSAP only on hero/key sections; disable heavy ScrollTrigger on mobile low power |
---
## 11. Observability
- Health: `GET /api/public/health`
- Structured JSON logs (request id, path, status, duration)
- Production: disable OpenAPI UI (`openapi_url = None` when `environment=production`)
---
## 12. Coding conventions
### Python (backend)
- Python 3.11+
- Type hints on public functions
- `ruff` or `flake8` + `black` (pick one formatter in CI)
- Router functions: max ~30 lines; delegate to services
- Enums in `models.py` for DB enums; mirror in Pydantic where needed
### JavaScript (frontend)
- React 18 functional components only
- Named exports for components; default export for pages optional
- Tailwind for styling; no CSS-in-JS library
- Axios instance with `baseURL` from `import.meta.env.VITE_API_URL`
- Env vars prefixed `VITE_` only for client-safe values
### Git
- Conventional commits encouraged: `feat:`, `fix:`, `docs:`
- One Alembic revision per schema change
---
## 13. Implementation phases
### Phase 0 — Constitution (current)
Documentation only; no new application features.
### Phase 1 — Public experience + admin content
- Vite + React + Tailwind + Router
- Wire public API: home, list, detail, subscribe, outbound go links
- Admin: login, edition CRUD, media upload
- Share previews + basic SEO
- **Aligns with partial backend already in repo**
### Phase 2 — Polish & performance
- GSAP hero + scroll sections with reduced-motion guard
- Image lazy loading, skeleton states
- Accessibility pass (focus, contrast, aria labels)
### Phase 3 — Native ticketing
- DB: tiers, orders, tickets
- Attendee auth
- Checkout + payment webhook
- Ticket page + QR generation
- Staff check-in UI
### Phase 4 — Hardening
- E2E smoke tests, load test on read paths
- CDN, backup strategy, runbooks
---
## 14. ADR policy
Significant deviations (new dependency, new service, auth model change) require a short `docs/adr/NNN-title.md` before implementation.
---
## 15. Related documents
- [API_SPEC.md](./API_SPEC.md)
- [DATABASE.md](./DATABASE.md)
- [DESIGN_SYSTEM.md](./DESIGN_SYSTEM.md)