# Architecture — Social Proximity ## System Overview Social Proximity er bygget som et minimal monorepo med tre separate komponenter: ``` ┌────────────────────────────────────────────────────────┐ │ Mobile App (Flutter) │ │ │ │ BLE Scanner ──► Match Screen ──► "Say hello" nudge │ └───────────────────────┬────────────────────────────────┘ │ HTTPS + WebSocket ▼ ┌────────────────────────────────────────────────────────┐ │ Backend (FastAPI) │ │ │ │ Match Engine ──► Session Store (Redis) ──► DB (PG) │ └───────────┬────────────────────────────────────────────┘ │ Internal API ▼ ┌────────────────────────────────────────────────────────┐ │ Admin Dashboard (Next.js) │ │ │ │ Anonymised stats — pings, sessions, interest counts │ └────────────────────────────────────────────────────────┘ ``` ## Components ### Mobile App - **Technology:** Flutter (Dart) — cross-platform Android + iOS - **BLE library:** `flutter_blue_plus` - **Responsibility:** BLE scanning and advertisement, interest profile, consent toggle, nudge display - **Does NOT:** store data persistently, track location, communicate with other users directly ### Backend - **Technology:** FastAPI (Python) + WebSockets - **Session store:** Redis — ephemeral sessions, no long-term identity storage - **Database:** PostgreSQL — anonymised aggregate stats only - **Responsibility:** receive BLE advertisement tokens, match users, push nudge via WebSocket, aggregate stats ### Admin Dashboard - **Technology:** Next.js (TypeScript) - **Responsibility:** display anonymised platform stats — no PII, no user-level data - **Access:** Internal only (no public-facing auth in MVP) ## Data Flow ### Happy path — two users nudged to talk ``` User A opens app, selects interests, enables "open to talk" └─► App generates ephemeral BLE token └─► App advertises token via BLE └─► App registers token + interests with backend (POST /session) User B nearby detects User A's BLE token └─► App sends token to backend (POST /match) └─► Backend checks: does B's interest list overlap with A's? └─► If overlap + both consent: backend sends WebSocket nudge to both "Someone nearby also works with DevOps and enjoys hardstyle" └─► Users see nudge, put phones down, say hello └─► Session expires automatically (Redis TTL: 2 hours) ``` ### Privacy properties - BLE tokens are ephemeral — regenerated every session - Backend never stores exact location or movement history - Interest matching happens server-side — apps never see each other's raw profile - After session expiry, all session data is deleted from Redis ## Infrastructure | Environment | Platform | |---|---| | Local dev | Docker Compose (backend + PostgreSQL + Redis) | | Production | Azure Container Apps or Kubernetes (i80.dk) | ## Repository Structure ``` SigHej/ ├── README.md ├── Docs/ ← Technical documentation (this folder) ├── backend/ ← FastAPI application ├── app/ ← Flutter mobile app ├── admin/ ← Next.js admin dashboard └── docker-compose.yml ``` See individual docs for each component: - [BACKEND.md](./BACKEND.md) - [APP.md](./APP.md) - [ADMIN.md](./ADMIN.md) - [TESTING.md](./TESTING.md) - [DECISIONS.md](./DECISIONS.md)