first commit
This commit is contained in:
commit
34ea15a54d
246 changed files with 18660 additions and 0 deletions
275
docs/ARCHITECTURE.md
Normal file
275
docs/ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
# 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 < 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue