Generated 2026-05-22

Burro Architecture Review

Static review of /root/projects/burro. This report focuses on module depth, test seams, locality, and high-risk behavior found in backend and frontend.

System Map

flowchart LR User[Student/Admin] --> Frontend[Vite React frontend] Frontend --> API[NestJS API] API --> Prisma[Prisma/Postgres] API --> Redis[Redis cache] API --> Storage[R2/S3 storage] API --> Mail[AWS SES mail] API --> Telegram[Telegram integration] API --> Learning[Modules / Questions / Attempts / XP / Streak]

Attempt Answer Seam Is Too Shallow

Strong

Files: burro-backend/src/modules/attempts/attempts.service.ts, burro-backend/prisma/schema.prisma

Problem: submitAnswer accepts any question id and uses a check-then-create flow without a database uniqueness seam. The Attempt module interface leaks too much responsibility to callers: callers must only send questions from the active module, but the module does not enforce it.

Solution: deepen the Attempt answer module by enforcing question ownership and one answer per attempt/question inside the service plus database constraint. The test surface becomes the public answer-submission behavior.

Before

flowchart TD UI[Practice UI] --> Submit[submitAnswer] Submit --> Q[find question by id only] Submit --> A[create answer] Submit --> C[increment counters] X[Question from another module] --> Q

After

flowchart TD UI[Practice UI] --> Submit[submitAnswer] Submit --> O[load active attempt] O --> Q[find question by id + moduleId] Q --> U[unique attemptId/questionId answer] U --> C[transactional counters]

Student Route Access Misses Verification Seam

Strong

Files: burro-frontend/src/routes/public.tsx, burro-frontend/src/components/guards/email-verified-guard.tsx

Problem: Dashboard routes compose AuthGuard and EmailVerifiedGuard, but Burro student routes compose only AuthGuard and StudentGuard. The access-control interface is inconsistent by route group.

Solution: create or reuse a deeper authenticated-student route module that packages auth, email verification, and student-role checks in one local seam.

Before

flowchart TD BurroRoute --> AuthGuard --> StudentGuard --> Page DashboardRoute --> AuthGuard2[AuthGuard] --> EmailGuard[EmailVerifiedGuard] --> Dashboard

After

flowchart TD BurroRoute --> VerifiedStudentRoute[Verified student route seam] VerifiedStudentRoute --> AuthGuard VerifiedStudentRoute --> EmailVerifiedGuard VerifiedStudentRoute --> StudentGuard StudentGuard --> Page

Test and Runtime Contract Seams Are Thin

Worth exploring

Files: backend package.json; frontend playwright.config.ts, tests/*.spec.ts, src/modules/arabtilibot/api/burroAPI.ts.

Problem: backend tests can pass with no tests, frontend E2E does not start its own app server, legacy tests target old routes, and frontend API contracts are TypeScript-only.

Solution: prioritize behavior-level tests around learning attempts and route guards; add Playwright webServer or documented startup; add runtime validation at high-risk API seams.

Top Recommendation

Fix backend Attempt answer ownership and duplicate-answer idempotency first. It has the highest correctness impact, a clear regression-test seam, and improves locality by making the Attempt module enforce its own invariants.