ai-interview-mentor / docs /architecture.md
samar m
Add architecture docs and Phase 0 scaffolding design spec
6a8e2e2
# AI InterviewMentor β€” Architecture Overview
## System Architecture
```
Browser (React SPA)
β”‚
β–Ό
HF Spaces Docker Container (port 7860)
β”œβ”€β”€ FastAPI (Python 3.11)
β”‚ β”œβ”€β”€ /api/auth/* β†’ Custom JWT auth (jose + bcrypt)
β”‚ β”œβ”€β”€ /api/batches/* β†’ Batch/class management
β”‚ β”œβ”€β”€ /api/topics/* β†’ Topic CRUD + unlock control
β”‚ β”œβ”€β”€ /api/upload β†’ CSV question bank ingestion
β”‚ β”œβ”€β”€ /api/sessions/* β†’ Session detail + reports
β”‚ β”œβ”€β”€ /api/instructor/* β†’ Dashboard + student analytics
β”‚ β”œβ”€β”€ /api/student/* β†’ Student dashboard
β”‚ β”œβ”€β”€ /interview/* β†’ LangGraph interview engine
β”‚ └── / (catch-all) β†’ React static files (Vite build)
β”‚
β”œβ”€β”€ LangGraph Engine
β”‚ β”œβ”€β”€ ask_question β†’ Picks next question from bank
β”‚ β”œβ”€β”€ evaluate_answer β†’ Scores: strong | shallow | wrong
β”‚ β”œβ”€β”€ counter_question β†’ Probing follow-up for shallow answers
β”‚ β”œβ”€β”€ summarize β†’ Compresses conversation every 4 turns
β”‚ └── generate_report β†’ Final scored feedback JSON
β”‚
└── External Services
β”œβ”€β”€ NeonDB (PostgreSQL)
β”‚ β”œβ”€β”€ public schema β†’ App data (users, batches, topics, questions, sessions)
β”‚ └── checkpointer β†’ LangGraph state (auto-managed)
└── OpenRouter API β†’ MiniMax 2.7 model
```
## Tech Stack
| Layer | Technology |
|-------|-----------|
| Frontend | React 18 + Vite + TypeScript + Tailwind CSS v3 (dark theme only) |
| Backend | FastAPI (Python 3.11) |
| AI Orchestration | LangGraph (state machine with checkpointing) |
| Database | NeonDB (PostgreSQL) β€” app data + LangGraph checkpoints |
| AI Gateway | OpenRouter β†’ MiniMax 2.7 |
| Auth | Custom JWT (jose + bcrypt) β€” no third-party auth |
| Deployment | Single Docker container on Hugging Face Spaces (port 7860) |
## Key Design Decisions
1. **Single container deployment** β€” React static build served by FastAPI, no split deployment
2. **Same-origin API calls** β€” No CORS needed, browser hits FastAPI directly
3. **Two DB schemas** β€” `public` for app data, `checkpointer` for LangGraph state
4. **Token budget control** β€” Summarize every 4 turns, ~700 token ceiling per LLM call
5. **session_id = thread_id** β€” Natural scoping between DB sessions and LangGraph state
6. **CSV-to-DB question ingestion** β€” No file storage needed (no S3/R2)
7. **Custom JWT only** β€” Supabase/Firebase explicitly banned (hackathon rules)
## Database Schema
### Tables
- **users** β€” id, full_name, email, password_hash, role (student|instructor), batch_id
- **refresh_tokens** β€” id, user_id, token_hash, expires_at
- **batches** β€” id, name, instructor_id, class_code (auto-generated)
- **topics** β€” id, batch_id, name, is_unlocked, order_index
- **questions** β€” id, topic_id, question_text, difficulty (easy|medium|hard)
- **interview_sessions** β€” id, student_id, topic_id, status, score, feedback (JSONB)
### Relationships
```
instructor (user) β†’ creates batches β†’ has topics β†’ has questions
student (user) β†’ joins batch via class_code β†’ takes interview_sessions on topics
```
## Auth Flow
- **Access token**: HS256 JWT, 15min expiry, sent in `Authorization: Bearer` header
- **Refresh token**: 7-day expiry, bcrypt-hashed in DB, sent as httpOnly cookie
- **Route protection**: `get_current_user` dependency extracts JWT β†’ `require_instructor` / `require_student` role guards
## LangGraph Interview Flow
```
START β†’ ask_question β†’ [wait for student answer] β†’ evaluate_answer
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β–Ό β–Ό β–Ό
counter_question ask_question generate_report β†’ END
β”‚ (or summarize
β–Ό every 4 turns)
evaluate_answer
```
- **8 turns max** or question bank exhausted β†’ generate_report
- **Counter-questions** fire once per shallow answer (no double-countering)
- **Summarize node** compresses messages every 4 turns to keep token usage flat
## Frontend Architecture
- **Routing**: React Router with `ProtectedRoute` wrapper
- **State**: Zustand stores β€” `authStore` (JWT + user), `interviewStore` (session state)
- **API layer**: Single `apiFetch` wrapper with auto-refresh on 401
- **Pages**: Login, Signup, StudentDashboard, Interview, Report, InstructorDashboard, Upload, StudentDetail
## Scope Boundary (Not In V1)
Voice input, email notifications, leaderboard, certificates, question bank editor UI, light theme, multi-instructor batches.