Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 27 additions & 15 deletions docs/codebase/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- The `ai-service` is isolated as a separate Python process because it requires Python-specific ML/AI tooling.
- **Primary constraints:**
1. All real-time features (Defend sessions, War Rooms) must go through the API's Socket.io server.
2. AI operations (code generation, quiz generation, diff scoring) are only available through the Python AI service, which calls Claude.
2. AI operations (code generation, quiz generation, diff scoring) are only available through the Python AI service, which calls OpenRouter (200+ models).
3. Database access is exclusively through the API's Prisma ORM — the web app never connects to PostgreSQL directly.

### 2) System Flow
Expand All @@ -27,30 +27,30 @@ Browser (Next.js App)
│ │
├── WebSocket (socket.io-client) ─┘
└── HTTP ──► Python FastAPI (PORT 8000) ──► Anthropic Claude API
└── HTTP ──► Python FastAPI (PORT 8000) ──► OpenRouter API (200+ models)
└── Judge0 (planned, self-hosted sandboxed code execution)
```

**End-to-end flow (Decode → Rebuild → Defend):**

1. **User selects module** in browser → frontend calls backend API via tRPC
2. **Backend calls AI service** (`POST /generate/`) to get production code from Claude
2. **Backend calls AI service** (`POST /generate/`) to get production code from the configured LLM via OpenRouter
3. **Code stored** in PostgreSQL via Prisma
4. **User annotates code** in Decode phase — saved via debounced API calls
5. **Quiz generated** by AI service (`POST /quiz/generate`) from annotations
5. **Quiz generated** by AI service (`POST /quiz/generate`) from annotations using OpenRouter
6. **User writes solution** in Rebuild phase using Monaco editor
7. **On submit**, code sent to AI service (`POST /diff/`) for AST diff scoring
8. **Score stored** → IRS Engine recalculates user's Irreplaceability Score
9. **Defend session scheduled** via BullMQ — on fire, Claude generates questions from user's rebuild
7. **On submit**, code sent to AI service (`POST /diff/`) for AST-based offline diff scoring (no LLM call)
8. **Score stored** → BullMQ worker (`submission-worker.ts`) recalculates IRS score and schedules Defend session
9. **Defend session** — Socratic Q&A via AI service (`POST /defend/respond`) using OpenRouter

### 3) Layer/Module Responsibilities

| Layer or module | Owns | Must not own | Evidence |
|-----------------|------|--------------|----------|
| `apps/web` (Frontend) | UI rendering, client state (Zustand), server state caching (React Query), routing, auth UI, animations | Direct database access, AI orchestration | `apps/web/src/app/layout.tsx`, `apps/web/src/app/providers.tsx` |
| `apps/api` (Backend) | HTTP/tRPC endpoints, authentication, business logic, database access (Prisma), job queue (BullMQ), real-time (Socket.io), logging, rate limiting | AI model calls, frontend rendering | `apps/api/src/index.ts` |
| `apps/ai-service` (AI) | LLM integration (Claude), code generation, quiz generation, diff scoring, defend Q&A, code execution (Judge0 — planned) | User data storage, authentication, frontend rendering | `apps/ai-service/app/main.py`, `apps/ai-service/app/routes/` |
| `apps/api` (Backend) | HTTP/tRPC endpoints, authentication, business logic, database access (Prisma), job queue (BullMQ), real-time (Socket.io), logging, rate limiting | AI model calls, frontend rendering | `apps/api/src/index.ts`, `apps/api/src/services/ai-client.ts`, `apps/api/src/services/submission-worker.ts` |
| `apps/ai-service` (AI) | LLM integration via OpenRouter (or offline AST diff), code generation, quiz generation, diff scoring, defend Q&A | User data storage, authentication, frontend rendering | `apps/ai-service/app/main.py`, `apps/ai-service/app/routes/`, `apps/ai-service/app/services/llm_client.py`, `apps/ai-service/app/services/ast_differ.py` |
| `packages/types` (Shared types) | TypeScript interfaces shared between web + api | Runtime logic, external dependencies | `packages/types/src/index.ts` |
| `infra/docker-compose.yml` (Infrastructure) | PostgreSQL, Redis for local development | Application code, migrations | `infra/docker-compose.yml` |

Expand All @@ -60,27 +60,39 @@ Browser (Next.js App)
|---------|-------------|---------------|
| tRPC (Type-safe RPC) | `apps/api/src/trpc.ts` — router, publicProcedure, middleware factories | Type-safe API contracts between frontend and backend |
| Prisma ORM (Repository pattern) | `apps/api/prisma/schema.prisma` + `apps/api/src/index.ts` singleton PrismaClient | Type-safe database access with migrations |
| BullMQ (Job queue) | `apps/api/src/index.ts` — `submissions` queue + worker | Async processing of Defend session scheduling |
| BullMQ (Job queue) | `apps/api/src/index.ts` — `submissions` queue + `submission-worker.ts` worker | Async processing of submission scoring and Defend session scheduling |
| Socket.io (Pub/sub) | `apps/api/src/index.ts` — Socket.io server with wildcard CORS | Real-time features (Defend sessions, War Rooms) |
| NextAuth.js (Auth adapter) | `apps/web/src/auth.ts` — GitHub + Google OAuth providers; `apps/web/src/app/api/auth/[...nextauth]/route.ts` | Authentication with OAuth providers |
| Sentry (Error monitoring) | `apps/web/sentry.client.config.ts`, `sentry.server.config.ts`, `sentry.edge.config.ts`; `apps/api/src/index.ts` conditional Sentry init | Error tracking across frontend and backend |
| Turborepo (Monorepo orchestration) | `turbo.json` pipeline with dependency ordering | Parallel builds, consistent task execution across workspaces |
| OpenAI SDK → OpenRouter | `apps/ai-service/app/services/llm_client.py` — uses OpenAI SDK pointed at OpenRouter's base URL | Unified API client for 200+ models from any provider |
| AST diff engine | `apps/ai-service/app/services/ast_differ.py` — offline Python AST comparison across 4 dimensions | Zero-cost code scoring without any LLM call; works entirely offline |

### 5) Known Architectural Risks

| Risk | Impact | Evidence |
|------|--------|----------|
| AI service routes are all **mocked** (no real Claude calls) | The core learning loop cannot function until real AI integration is implemented | `apps/ai-service/app/routes/generate.py` (commented-out Claude client), `routes/diff.py` (hardcoded response), `routes/quiz.py` (dummy questions), `routes/defend.py` (generic questions) |
| No service layer in any app — logic lives inline in routes | As the codebase grows, routes will become bloated, untestable, and hard to maintain | `apps/api/src/index.ts` has health check inline; no `services/` directory exists |
| API has no auth middleware on tRPC | Any endpoint added by default is public | `apps/api/src/trpc.ts` only exports `publicProcedure` — no `protectedProcedure` |
| No auth middleware on tRPC | Any endpoint added by default is public | `apps/api/src/trpc.ts` only exports `publicProcedure` — no `protectedProcedure` |
| CORS set to `allow_origins=["*"]` on both API and AI service | Insecure for production — allows any origin to make requests | `apps/api/src/index.ts` CORS config; `apps/ai-service/app/main.py` CORS config |
| AI service uses thread-pool async (sync calls wrapped with `anyio.to_thread.run_sync`) | Under load, the GIL may become a bottleneck for concurrent LLM requests | `apps/ai-service/app/services/llm_client.py` — `generate_async()` wraps sync `generate()` |
| No database migrations committed | The Prisma schema exists but `prisma/migrations/` is empty; no deployment path | `apps/api/prisma/` directory |
| Frontend still operates on client-side mock data | All frontend pages render mock data; no real API/tRPC calls from the web app | `apps/web/src/lib/mock-data/` — entire mock data layer |
| No test coverage for backend routes or tRPC routers | 12 TypeScript tests exist for `ai-client.ts` only; Python has 28 tests for AI service | `apps/api/src/__tests__/` (single test file); `apps/ai-service/tests/` |

### 6) Evidence

- `apps/api/src/index.ts` — entry point showing Express, tRPC, BullMQ, Socket.io setup
- `apps/api/src/trpc.ts` — tRPC initialization (only publicProcedure exists)
- `apps/ai-service/app/main.py` — FastAPI app setup with mocked routes
- `apps/ai-service/app/routes/generate.py` — mocked Claude integration
- `apps/api/src/services/ai-client.ts` — typed HTTP client for Python AI service (camelCase ↔ snake_case mapping)
- `apps/api/src/services/submission-worker.ts` — BullMQ worker for async submission processing
- `apps/ai-service/app/main.py` — FastAPI app setup with real route mounts
- `apps/ai-service/app/routes/generate.py` — real LLM code generation via OpenRouter
- `apps/ai-service/app/routes/quiz.py` — real LLM quiz generation via OpenRouter
- `apps/ai-service/app/routes/diff.py` — offline AST-based code diff scoring (no LLM call)
- `apps/ai-service/app/routes/defend.py` — real LLM Socratic Q&A via OpenRouter
- `apps/ai-service/app/services/llm_client.py` — OpenRouter LLM client with retry + logging
- `apps/ai-service/app/services/prompt_manager.py` — prompt template loader with versioning
- `apps/ai-service/app/services/ast_differ.py` — AST-based code comparison engine
- `apps/web/src/auth.ts` — NextAuth configuration
- `apps/web/src/app/providers.tsx` — client-side provider setup
- `turbo.json` — pipeline orchestration
Loading