Now I have a thorough understanding of the entire project. Here is the comprehensive summary:
---
## COMPREHENSIVE PROJECT ANALYSIS: school-administrative-system (MCP Unified System)
---
### 1. OVERALL PROJECT STRUCTURE -- DIRECTORY TREE (3+ levels)
```
school-administrative-system/
├── .dockerignore
├── .gitignore
├── .gitmodules # Git submodules config
├── buffalo_l/ # ONNX face recognition models (buffalo_l)
│ ├── 1k3d68.onnx
│ ├── 2d106det.onnx
│ ├── det_10g.onnx
│ ├── genderage.onnx
│ └── w600k_r50.onnx
├── deploy-out/ # PRIMARY API: @bio/api (Fastify/TypeScript)
│ ├── .env # Active environment config
│ ├── .env.example
│ ├── package.json # Dependencies (fastify, mongoose, bcryptjs, etc.)
│ ├── tsconfig.json
│ ├── scripts/
│ │ ├── seed.ts # Seeds SUPER_ADMIN user
│ │ └── seed-tenant.ts # Seeds tenant + admin user
│ ├── src/
│ │ ├── index.ts # Fastify entry point (all routes, middleware)
│ │ ├── loadEnv.ts # dotenv loader
│ │ ├── lib/ # Core utilities
│ │ │ ├── academicSession.ts # Suggest next session label
│ │ │ ├── auth.ts # Password hashing (bcrypt), JWT verify, RBAC
│ │ │ ├── crypto.ts # AES-256-GCM template encryption
│ │ │ ├── db.ts # Mongoose connection
│ │ │ ├── deviceAuth.ts # Device API-key auth
│ │ │ ├── faceClient.ts # Face service client (InsightFace/ArcFace)
│ │ │ ├── matchingClient.ts # SourceAFIS fingerprint matching client
│ │ │ ├── notifications.ts # Email + In-App notifications
│ │ │ ├── resolveAcademicYear.ts
│ │ │ ├── serialize.ts # Mongo _id -> id mapping
│ │ │ └── tenantScope.ts # Multi-tenant data isolation
│ │ ├── models/
│ │ │ ├── lean.ts # TypeScript plain-object interfaces
│ │ │ ├── roles.ts # Role enum: SUPER_ADMIN, TENANT_ADMIN, ENROLLER, INVIGILATOR, VIEWER
│ │ │ └── schemas.ts # Mongoose schemas (17 collections)
│ │ ├── routes/
│ │ │ ├── academic-sessions.ts
│ │ │ ├── auth.ts
│ │ │ ├── course-registrations.ts
│ │ │ ├── courses.ts
│ │ │ ├── departments.ts
│ │ │ ├── devices.ts
│ │ │ ├── enrollments.ts # Biometric enrollment (fingerprint + face)
│ │ │ ├── exams.ts
│ │ │ ├── faculties.ts
│ │ │ ├── notifications.ts
│ │ │ ├── reports.ts
│ │ │ ├── students.ts
│ │ │ ├── sync.ts # Offline exam data sync
│ │ │ ├── tenants.ts
│ │ │ └── verify.ts # 1:1 + 1:N biometric verification (fingerprint + face)
│ │ └── types/
│ │ └── fastify.d.ts # Fastify type augmentations
│ └── dist/ # Compiled JS output
├── docker/ # Dockerfiles and nginx config
│ ├── admin.Dockerfile # React SPA + nginx proxy
│ ├── bio-api.Dockerfile # @bio/api Fastify service
│ ├── cbt.Dockerfile # Go CBT API
│ ├── face-service.Dockerfile # Python face recognition (InsightFace)
│ ├── matching.Dockerfile # Java SourceAFIS matching service
│ └── nginx-admin.conf # Nginx reverse proxy config
├── docker-compose.yml # Full stack: mongo + matching + bio-api + face + cbt + admin + ollama
├── env.docker # Docker env template
├── scripts/
│ └── cbt_seed.ps1 # PowerShell CBT AI seed/test script
├── package.json # Root pnpm workspace
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
│
├── MCP/ # Git submodule -- Mobile apps
│ └── mobile/
│ └── cbt_mobile/ # Flutter mobile app
│ ├── lib/ # Dart source
│ ├── android/
│ ├── ios/
│ └── pubspec.yaml
│
├── MCP-ADMIN/ # Git submodule -- Admin frontend
│ ├── admin/ # React + Vite + Tailwind SPA
│ │ ├── package.json # react, react-router-dom, lucide-react, tailwindcss
│ │ ├── vite.config.ts # Dev proxy to bio-api and CBT API
│ │ ├── tsconfig.json
│ │ ├── tailwind.config.js
│ │ ├── index.html
│ │ └── src/
│ │ ├── main.tsx # Entry: BrowserRouter + ThemeProvider
│ │ ├── App.tsx # Routes (auth gating)
│ │ ├── api.ts # API client with JWT + tenant queries
│ │ ├── styles.css
│ │ ├── components/
│ │ │ ├── Header.tsx
│ │ │ ├── Sidebar.tsx
│ │ │ └── WebcamCapture.tsx
│ │ ├── context/
│ │ │ └── ThemeContext.tsx
│ │ ├── lib/
│ │ │ └── capture.ts
│ │ └── pages/
│ │ ├── Login.tsx
│ │ ├── Layout.tsx # Main shell with tenant selector
│ │ ├── Home.tsx
│ │ ├── Students.tsx
│ │ ├── StudentAdd.tsx
│ │ ├── StudentEdit.tsx
│ │ ├── Enroll.tsx # Biometric enrollment UI
│ │ ├── Exams.tsx
│ │ ├── Verify.tsx # Verification UI
│ │ ├── Reports.tsx
│ │ ├── Notifications.tsx
│ │ ├── Catalog.tsx # Faculties + Departments + Courses
│ │ ├── AcademicSessions.tsx
│ │ ├── CourseRegistrations.tsx
│ │ ├── Devices.tsx
│ │ ├── SettingsLayout.tsx
│ │ └── cbt/ # CBT-specific pages
│ │ ├── CBTDashboard.tsx
│ │ ├── CBTExams.tsx
│ │ ├── CBTMarking.tsx
│ │ └── CBTQuestions.tsx
│ └── cbt-admin-archive/
│
└── MCP-BACKEND/ # Git submodule -- Backend services
├── docs/
├── scripts/
│ └── start-matching.mjs # Starts Java matching service
└── services/
├── biometric-api/ # Original (Prisma-based) bio API (older version)
├── capture-bridge/ # Python Futronic fingerprint scanner bridge
│ ├── futronic_bridge.py
│ └── *.dll # Futronic SDK DLLs
├── cbt/ # Go-based CBT (Computer-Based Testing) API
│ ├── cmd/server/ # Go entry point
│ ├── internal/ # Go internal packages
│ ├── pkg/
│ └── go.mod
├── face-service/ # Python InsightFace/ArcFace service
│ ├── app.py
│ └── requirements.txt
├── hall-node/ # Exam hall client (Express)
│ └── src/
├── matching/ # Empty (legacy?)
├── matching-java/ # Java SourceAFIS fingerprint matching
│ ├── pom.xml
│ └── src/
└── shared/ # @bio/shared TypeScript library
└── src/
├── capture.ts
├── httpCaptureDriver.ts
└── index.ts
```
---
### 2. TECH STACK
| Layer | Technology | Version |
|-------|-----------|---------|
| **Package Manager** | pnpm (workspace monorepo) | 9.14.2 |
| **Primary API** | Fastify (Node.js) | 5.1.0 |
| **Language** | TypeScript | 5.6.3 |
| **Database** | MongoDB (via Mongoose) | Mongoose 8.9.5, MongoDB 7 |
| **Auth** | JWT (fastify/jwt), bcryptjs | jwt 9.0.1, bcrypt 2.4.3 |
| **Validation** | Zod | 3.23.8 |
| **Admin Frontend** | React 18 + Vite 6 + Tailwind CSS 3 | React 18.3.1 |
| **Routing** | react-router-dom | 7.1.1 |
| **Icons** | lucide-react | 0.468.0 |
| **CBT API** | Go | 1.23 |
| **Matching Service** | Java (SourceAFIS, Maven) | Java 17 |
| **Face Service** | Python (InsightFace/ArcFace, gunicorn) | Python 3.11 |
| **Capture Bridge** | Python (Futronic SDK) | Python |
| **Mobile** | Flutter (Dart) | -- |
| **LLM/AI** | Ollama (gemma2:12b) | latest |
| **Email** | Nodemailer (SMTP) | 8.0.5 |
| **Reverse Proxy** | Nginx (Alpine) | -- |
| **Containerization** | Docker Compose (7 services) | -- |
---
### 3. EXISTING FEATURES
#### Core Biometric System (deploy-out/src):
- **Multi-tenancy**: Full tenant isolation via `tenantId` on all collections. SUPER_ADMIN selects tenant via `?tenantId=` query param
- **User/Role Management**: 5 roles (SUPER_ADMIN, TENANT_ADMIN, ENROLLER, INVIGILATOR, VIEWER)
- **Student Management**: CRUD with search, pagination, filtering by faculty/department/level/enrollment status
- **Bulk Student Population**: Auto-generate students from department matric patterns
- **Biometric Enrollment**: Fingerprint enrollment (via SourceAFIS) and face enrollment (via InsightFace/ArcFace)
- **Biometric Verification (1:1)**: Verify a claimed student identity against stored biometrics
- **Biometric Identification (1:N)**: Identify unknown student from biometrics (searches all enrollments)
- **Impersonation Detection**: If 1:1 fails, system automatically does 1:N to detect impersonation
- **Exam Management**: Create exams, manage rosters (bulk by department or individual), course matching
- **Course Registration**: Track eligible students per course per academic year/semester
- **Device/Exam Hall Management**: Register hall devices with API keys; track last seen
- **Offline Sync**: Hall devices download encrypted biometric packages; upload verification events later
- **Academic Session Management**: Create/view/edit sessions (e.g., "2024/2025"), with auto-suggest for next
- **Faculty & Department Management**: Hierarchical organization with matric patterns
- **Course Management**: CRUD with faculty/department associations
- **Reports**: Verification events JSON + CSV export, CBT statistics
- **Notifications**: In-app (MongoDB) + email (SMTP via Nodemailer) for biometric mismatches and admin alerts
- **Audit Logging**: All CRUD operations logged with actor, entity, action
#### CBT (Computer-Based Testing) - Go Service:
- Question bank with MCQ and essay types
- AI-powered question generation (via Ollama)
- Essay grading (AI-based)
- Semantic similarity for plagiarism detection
- Model answer comparison
- Exam/test/assignment management
#### Frontend Admin (React SPA):
- Full dashboard with all management pages
- Dark/light theme
- Webcam capture for biometric enrollment (WebcamCapture component)
- Tenant switcher for SUPER_ADMIN
- Notification badge with unread count polling
- CBT dashboard, exam management, marking, and question pages
#### Mobile (Flutter):
- CBT mobile app (cbt_mobile)
---
### 4. AUTHENTICATION
**Flow:**
1. `POST /auth/login` with `{ email, password }` -- validates via bcrypt against User collection
2. On success, issues JWT with payload: `{ sub: userId, role: string, tenantId: string | null }`
3. JWT is set as `Bearer` token in `Authorization` header
4. Fastify decorator `app.authenticate` verifies JWT on protected routes
5. `requireRole(roles[])` middleware checks RBAC permissions
**API Authentication (Devices):**
- Devices authenticate via `X-Device-Id` and `X-Device-Secret` headers
- API key hash is bcrypt-hashed; verified on each request
- Sets `req.device = { id, tenantId }` for downstream route context
**Frontend:**
- Token stored in `localStorage` (`token`, `user`, `selectedTenantId`)
- `api.ts` wraps fetch with auto-injected Authorization header and tenant query params for SUPER_ADMIN
- `withTenantQuery()` adds `?tenantId=` for SUPER_ADMIN on all tenant-scoped paths
- Login page: `/login`; app gating via `authed` state in `<App />`
---
### 5. DATABASE SETUP
**Database:** MongoDB 7 (via Mongoose 8.9.5)
**Connection:** `MONGODB_URI` or `DATABASE_URL` environment variable
**Mongoose Schemas/Collections (17 total):**
| Collection | Key Fields | Indexes |
|-----------|-----------|---------|
| `tenants` | _id, name, slug (unique) | slug unique |
| `users` | _id, tenantId, email (unique), passwordHash, role (enum), displayName | email unique |
| `faculties` | _id, tenantId, name | {tenantId, name} unique |
| `departments` | _id, tenantId, facultyId, name, matricPattern | {tenantId, facultyId, name} unique |
| `academic_sessions` | _id, tenantId, label | {tenantId, label} unique |
| `students` | _id, tenantId, matricNo, fullName, email, facultyId, departmentId, faculty, department, level, photoUrl | {tenantId, matricNo} unique |
| `courses` | _id, tenantId, code, title, facultyId, departmentId, faculty, department | {tenantId, code} unique |
| `course_registrations` | _id, tenantId, studentId, courseId, academicSessionId, academicYear, semester | {tenantId, studentId, courseId, academicYear, semester} unique |
| `biometric_enrollments` | _id, tenantId, studentId, modality (fingerprint/face), fingerCode, templateEnc (encrypted Buffer), faceEmbedding (encrypted Buffer), qualityScore, templateVersion | {studentId, fingerCode} unique sparse; {studentId, modality:"face"} unique partial |
| `devices` | _id, tenantId, name, hallLabel, apiKeyHash, lastSeenAt | -- |
| `exams` | _id, tenantId, title, courseId, academicSessionId, academicYear, semester, startsAt, endsAt | -- |
| `exam_roster_entries` | _id, examId, studentId, hallLabel | {examId, studentId} unique |
| `verification_events` | _id, tenantId, deviceId, studentId, mismatchStudentId, examId, courseId, academicSessionId, academicYear, semester, result, matchScore, modality, idempotencyKey, capturedAt, syncedAt | {tenantId, capturedAt}, {studentId}, {tenantId, studentId, examId, result:"match"} unique partial |
| `audit_logs` | _id, tenantId, actorId, action, entityType, entityId, meta, createdAt | {tenantId, createdAt} |
| `notifications` | _id, tenantId, recipientId, type (INAPP/EMAIL), title, message, isRead, meta | {tenantId, createdAt} |
**Important:** All IDs are generated via `randomUUID()` (not MongoDB ObjectIDs). Template data (`templateEnc`, `faceEmbedding`) are encrypted via AES-256-GCM before storage (`TEMPLATE_ENCRYPTION_KEY` required).
**Seed scripts:**
- `deploy-out/scripts/seed.ts`: Creates SUPER_ADMIN user (`super@example.edu` / `ChangeMe123!`)
- `deploy-out/scripts/seed-tenant.ts`: Creates tenant + TENANT_ADMIN user (CLI args)
- `scripts/cbt_seed.ps1`: Seeds CBT data (questions, exams) via HTTP
---
### 6. API STRUCTURE
**Base:** Built on Fastify 5.1.0 with CORS enabled (all origins)
**Registered Routes (prefix: none -- routes are self-contained):**
| Route | Methods | Auth |
|-------|---------|------|
| `/health` | GET | Public |
| `/auth/login` | POST | Public (JWT issuance) |
| `/tenants` | GET, POST | SUPER_ADMIN only |
| `/students` | GET, POST | All roles (post: SUPER_ADMIN, TENANT_ADMIN, ENROLLER) |
| `/students/:id` | GET, PATCH | All roles / admin+enroller |
| `/students/populate` | POST | SUPER_ADMIN, TENANT_ADMIN |
| `/students/:studentId/enrollments` | POST, DELETE | Admin + Enroller |
| `/students/:studentId/enrollments/status` | GET | Admin + Enroller + Invigilator |
| `/students/:studentId/enrollments/face` | POST | Admin + Enroller |
| `/devices` | GET, POST, DELETE | Admin / Admin+Viewer |
| `/exams` | GET, POST, PATCH, DELETE | All roles (write: admin+enroller) |
| `/exams/:examId/roster` | POST | Admin + Enroller |
| `/exams/:examId/roster/bulk-department` | POST | Admin + Enroller |
| `/verify/one-to-one` | POST | Admin + Enroller + Invigilator |
| `/verify/identify` | POST | Admin + Enroller + Invigilator |
| `/verify/face/one-to-one` | POST | Admin + Enroller + Invigilator |
| `/verify/face/identify` | POST | Admin + Enroller + Invigilator |
| `/device/verify/one-to-one` | POST | Device auth (X-Device-Id / X-Device-Secret) |
| `/device/verify/identify` | POST | Device auth |
| `/device/verify/face/one-to-one` | POST | Device auth |
| `/device/verify/face/identify` | POST | Device auth |
| `/sync/exam-package` | GET | Device auth |
| `/sync/verification-events` | POST | Device auth |
| `/reports/verification-events` | GET | Admin + Viewer |
| `/reports/verification-events/export.csv` | GET | Admin + Viewer |
| `/reports/cbt-stats` | GET | Admin + Viewer |
| `/courses` | GET, POST, PATCH, DELETE | All read / admin+enroller write |
| `/course-registrations` | GET, POST, DELETE | All read / admin+enroller write |
| `/faculties` | GET, POST, PATCH, DELETE | All read / admin+enroller write |
| `/departments` | GET, POST, PATCH, DELETE | All read / admin+enroller write |
| `/academic-sessions` | GET, POST, PATCH, DELETE | All read / admin+enroller write |
| `/academic-sessions/suggest-next` | GET | All |
| `/notifications` | GET | Admin |
| `/notifications/unread-count` | GET | Admin |
| `/notifications/:id/read` | POST | Admin |
| `/notifications/read-all` | POST | Admin |
**CBT API (Go, port 8080):**
- `/api/v1/questions` -- CRUD question bank
- `/api/v1/exams` -- Create/list exams
- `/api/v1/ai/generate` -- AI question generation
- `/api/v1/ai/generate-from-text` -- AI questions from text
- `/api/v1/ai/grade-essay` -- AI essay grading
- `/api/v1/ai/similarity` -- Semantic similarity
- `/api/v1/ai/model-answer` -- Save model answers
- `/api/v1/ai/curriculum` -- Upload curriculum
- `/api/v1/ai/compare-answer` -- Compare student answer to model
- `/api/v1/stats` -- System statistics
- `/api/v1/ai/health` -- Health check
---
### 7. FRONTEND FRAMEWORK & COMPONENT STRUCTURE
**Framework:** React 18.3.1 + Vite 6 + TypeScript 5.6.3
**Styling:** Tailwind CSS 3.4.16 (dark mode via class strategy)
**Icons:** lucide-react 0.468.0
**Routing:** react-router-dom 7.1.1
**Component Tree:**
```
<BrowserRouter>
<ThemeProvider defaultTheme="dark">
<App>
<Routes>
/login -> <Login />
/ -> <Layout> (gated by auth)
<Sidebar /> -- navigation
<Header /> -- tenant selector, logout, notification badge
<Home /> -- dashboard
<Students /> -- student list table
<StudentAdd /> -- student registration form
<StudentEdit /> -- edit student
<Enroll /> -- biometric enrollment with WebcamCapture
<Exams /> -- exam management
<Verify /> -- biometric verification
<Reports /> -- reports & CSV export
<Notifications /> -- notification list
<SettingsLayout> -- sub-navigation
<Catalog /> -- faculties + departments + courses
<AcademicSessions />
<CourseRegistrations />
<Devices />
</SettingsLayout>
<CBTDashboard /> -- CBT stats
<CBTExams /> -- CBT exam management
<CBTMarking /> -- AI-assisted marking
<CBTQuestions /> -- AI question generation
</Layout>
</Routes>
</App>
</ThemeProvider>
</BrowserRouter>
```
**API Client (`api.ts`):**
- Two methods: `api<T>()` for bio-api routes, `apiCBT<T>()` for CBT routes
- Auto-injects JWT from localStorage
- Auto-appends `?tenantId=` for SUPER_ADMIN users
- Error handling with text parsing
---
### 8. EXISTING INTEGRATION POINTS & EXTERNAL SERVICES
| Service | Protocol | Port | Purpose |
|---------|----------|------|---------|
| **MongoDB** | MongoDB wire | 27017 | Primary database |
| **Matching Service** | HTTP REST (Java/SourceAFIS) | 5050 | `/extract`, `/match`, `/quality` for fingerprint processing |
| **Face Service** | HTTP REST (Python/InsightFace) | 5056 | `/extract-face` for face embedding extraction |
| **CBT API** | HTTP REST (Go) | 8080 | `/api/v1/*` for CBT features |
| **Ollama (LLM)** | HTTP REST | 11434 | AI features (question generation, essay grading, similarity) |
| **SMTP** | TCP (nodemailer) | Configurable | Email notifications for mismatches and alerts |
| **Futronic Bridge** | Python subprocess | -- | Fingerprint scanner hardware (Windows DLLs) |
| **Nginx** | HTTP reverse proxy | 80 | Routes `/api/` -> bio-api:4000, `/cbt-api/` -> cbt-api:8080, `/` -> React SPA |
| **Flutter Mobile** | Dart | -- | CBT mobile app (Android/iOS/Web/Desktop) |
---
### 9. CONFIGURATION FILES
**Environment Variables (`.env` / `env.docker`):**
| Variable | Purpose | Default |
|----------|---------|---------|
| `MONGODB_URI` / `DATABASE_URL` | MongoDB connection | `mongodb://localhost:27017/school` |
| `JWT_SECRET` | JWT signing key | Required |
| `TEMPLATE_ENCRYPTION_KEY` | AES-256 key (64 hex chars) for biometric template encryption | Required |
| `ENCRYPTION_KEY` | 32-byte key for CBT payload encryption | Required |
| `MATCHING_SERVICE_URL` | Fingerprint matching service | `http://127.0.0.1:5050` |
| `FACE_SERVICE_URL` | Face recognition service | `http://127.0.0.1:5056` |
| `PORT` | Bio-api port | 4000 |
| `HOST` | Bio-api host | 0.0.0.0 |
| `SMTP_HOST/PORT/USER/PASS/FROM` | Email notification config | Not set by default |
| `ADMIN_ALERT_EMAIL` | Mismatch alert recipient | Not set by default |
| `OLLAMA_MODEL` | LLM model | `gemma2:12b` |
**Docker Compose services:**
1. `mongo` -- MongoDB 7
2. `matching` -- Java SourceAFIS (port 5050)
3. `bio-api` -- Fastify API (port 4000)
4. `face-service` -- Python face recognition (port 5056)
5. `cbt-api` -- Go CBT service (port 8080)
6. `admin` -- Nginx + React SPA (port 80)
7. `ollama` -- LLM inference (port 11434, GPU optional)
---
### 10. GIT HISTORY (last 5 commits)
```
ed3315c3 cxx
be322171 jjhj
00953bf7 90op
7bed5ac4 Clean root repo and remove accidental generated files
9b050f6e Convert root repo into superproject with submodules
```
The repository was recently converted to a Git superproject with three submodules:
- `MCP` (mobile app) -> `https://github.com/Junman140/MCP.git`
- `MCP-ADMIN` (admin frontend) -> `https://github.com/Junman140/MCP-ADMIN.git`
- `MCP-BACKEND` (all backend services) -> `https://github.com/Junman140/MCP-BACKEND.git`
The `deploy-out/` directory (the primary bio-api) is tracked directly in the root repository (not a submodule). Root-level files like `docker-compose.yml`, Dockerfiles, and `package.json` are also in the root repo.
---
### KEY OBSERVATIONS
1. **This is a biometric attendance/exam verification system** for Nigerian educational institutions. The core feature is fingerprint/face verification during exams to prevent impersonation.
2. **Multi-tenant architecture** supports multiple institutions on a single deployment with complete data isolation.
3. **Two biometric modalities**: fingerprint (SourceAFIS) and face (InsightFace/ArcFace), both with templates encrypted at rest via AES-256-GCM.
4. **Offline-capable**: Hall devices sync encrypted biometric packages before exams and upload verification events afterward.
5. **AI-powered CBT**: Integrated Ollama for question generation, essay grading, and plagiarism detection.
6. **The deploy-out directory** is the primary evolved codebase; the MCP-BACKEND submodule contains older/original services including an earlier Prisma-based version (`biometric-api/`).
7. **The project uses pnpm workspaces** with four packages: `@bio/api` (main), `@bio/admin` (frontend), `@bio/hall-node` (exam hall client), and `@bio/shared` (common library).