examforge / ARCHITECTURE.md
Benjahmin's picture
feat(ui): implement design token system and core components
bf954c9
|
Raw
History Blame Contribute Delete
9.81 kB

ExamForge Engine Architecture & System Design Blueprint

Proprietary Core Platform Design for Multi-School, Multi-Tenant Scaling (up to 1,000+ Schools)


1. Single-Page Architecture Overview

ExamForge leverages a Modular Monolith ("Engine Architecture") structure built using React+Vite in the frontend, backed by a robust and secure Firebase Firestore persistence layer + server-side validation proxies.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      CLIENT LAYER                      β”‚
β”‚                                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚       UI Engine       β”‚   β”‚     Auth Engine      β”‚  β”‚
β”‚  β”‚   (Design System)     β”‚   β”‚   (Tenant Boundary)  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚              β”‚                           β”‚             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚     Parsing Engine    β”‚   β”‚     Exam Engine      β”‚  β”‚
β”‚  β”‚   (Extraction Layer)  β”‚   β”‚   (Submission Loop)  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚                           β”‚
               β–Ό Secure API HTTP/S         β–Ό WebSocket Channels (Realtime)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      BACKEND CORE                      β”‚
β”‚                                                        β”‚
β”‚             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
β”‚             β”‚    Server-Side Controllers  β”‚            β”‚
β”‚             β”‚     - Multi-Tenant Rule App β”‚            β”‚
β”‚             β”‚     - AI NVIDIA NIM Router  β”‚            β”‚
β”‚             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
                             β–Ό Secure SDK
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        DATA WAREHOUSE                  β”‚
β”‚                                                        β”‚
β”‚             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
β”‚             β”‚   Multi-Tenant Cloud Store  β”‚            β”‚
β”‚             β”‚   (Firestore Isolated Node) β”‚            β”‚
β”‚             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Directory & Folder Structure

To scale past 100,000+ operations without component namespace clashing, our files are partitioned strictly into context-isolated Engine namespaces.

/src
β”œβ”€β”€ /engines                       # Shared Application Micro-Engines
β”‚   β”œβ”€β”€ /ui                        # UI Engine Core (Tokens, Layouts, Spring Assets)
β”‚   β”‚   β”œβ”€β”€ /components            # Atomic design pieces (Button, Card, Input...)
β”‚   β”‚   β”œβ”€β”€ /hooks                 # useLayoutValidator, etc.
β”‚   β”‚   └── tokens.ts              # Global 8px grid tokens
β”‚   β”‚
β”‚   β”œβ”€β”€ /auth                      # Authentication & Identity Engine
β”‚   β”‚   β”œβ”€β”€ /services              # TenantAuthService
β”‚   β”‚   β”œβ”€β”€ /validators            # Identity, PIN, & schema rules
β”‚   β”‚   └── types.ts               # Tenancy schema maps
β”‚   β”‚
β”‚   └── /parsing                   # Content Parsing Engine
β”‚       β”œβ”€β”€ /services              # Orchestrators and OCR Pipelines
β”‚       β”œβ”€β”€ /validators            # Syntactic structural rules
β”‚       └── types.ts               # Extraction payloads
β”‚
β”œβ”€β”€ /pages                         # Standard View Compositions
β”‚   β”œβ”€β”€ /teacher                   # Teacher Dashboard & Classroom portals
β”‚   β”œβ”€β”€ CreateExam.tsx             # Exam configuration bounds
β”‚   └── ExamInterface.tsx          # Realtime assessment loop
β”‚
β”œβ”€β”€ /services                      # Core server communications
└── /types                         # Domain types

3. Modular Service Boundaries & Shared Contracts

  • Boundary Isolations: Direct mutations of raw databases are strictly forbidden. To talk across engine lines, engines must consume public contract classes (TenantAuthService, ParsingEngineService).
  • No Circular Dependencies: Lower-level engines (like /ui and /auth) never import components or hooks from higher-level features (like /parsing).

4. Multi-Tenant Firestore Schema Design

To guarantee perfect performance and isolation for over 100 schools without rewriting, schools are split utilizing Single-Collection Multi-Tenant Partitioning.

1. schools Collection

Stores metadata regarding active institutional tenants.

// Collection: schools/{schoolId}
{
  "id": "school-british-academy",
  "name": "British International School",
  "domain": "britishacademy.edu",
  "tenantStatus": "active",
  "createdAt": "2026-06-03T12:00:00Z"
}

2. users Collection

Explicitly binds users to their parent schoolId to guarantee robust multi-school data safety.

// Collection: users/{uid}
{
  "id": "usr_stu_0091",
  "fullName": "Jane Doe",
  "email": "jane.doe@britishacademy.edu",
  "role": "student",
  "schoolId": "school-british-academy", // Partition key
  "createdAt": "2026-06-03T12:00:00Z"
}

3. exams Collection

// Collection: exams/{examId}
{
  "id": "exam_math_01",
  "schoolId": "school-british-academy", // Partition key
  "title": "Algebraic Differential Topology",
  "status": "published",
  "questionIds": ["q_01", "q_02"],
  "duration": 60
}

5. Row-Level Security Rules (firestore.rules)

To enforce multi-tenant isolation directly on the database node, we apply strict token-to-record matching rules in firestore.rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    
    // Match current user payload
    function getUserData() {
      return get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
    }

    // Verify school membership
    function belongsToSameSchool(resourceData) {
      return request.auth != null && getUserData().schoolId == resourceData.schoolId;
    }

    match /users/{userId} {
      allow read, write: if request.auth != null && (request.auth.uid == userId || getUserData().role == 'school_admin');
    }

    match /exams/{examId} {
      allow read: if belongsToSameSchool(resource.data);
      allow write: if request.auth != null && getUserData().role == 'teacher' && belongsToSameSchool(request.resource.data);
    }
  }
}

6. Intelligent Caching Strategy (Latency Reduction)

  1. AI Cache Resolution: Background compilation prompts and analytics reviews are cached using a secure, client-server Redis or server-side memory buffer map (aiCache) with a 60-minute TTL.
  2. Snapshot Preservation: High-frequency exam questions are stored locally during student CBT assessments as a JSON snapshot in the Attempt state, bypassing Firestore real-time reads on every navigation.

7. Integrated Performance, Logging & Monitoring Strategy

To prevent high-cost bills or unexpected cloud latency during active CBT exams:

  • System Telemetry Logging: Every AI extraction, classification, or scoring action calls logAiOperation, recording latency metrics in a local append-only database.
  • Optimistic Sync Reconciliation: Progress coordinates are batched and saved asynchronously during active exams every 30 seconds rather than on every keystroke, reducing network requests by 95%.

8. Relational Postgres (SQL) Migration Pathway

When transitioning from 100 to 1,000+ schools, we migrate to PostgreSQL utilizing an execution flow that preserves our existing backend router interfaces cleanly:

  1. Phase 1: Abstract Service Interfaces: Ensure all data calls utilize repository wrappers (DataService).
  2. Phase 2: Relational Schema Mapping: Translate JSON models into relational tables (e.g. schools table has many-to-one relationship on users and exams).
  3. Phase 3: Database Driver Switchover: Replace SDK implementations in DataService with a PostgreSQL driver (via Prisma or Knex), leaving the frontend completely unchanged.