Multi-Tenant SaaS Platform

EduAssess

Secure examination platform with AI proctoring, browser lockdown, offline answer syncing, TOTP 2FA, and integrated billing — deployed on AWS and serving real university users.

PHP 8.3PostgreSQL 16JavaScriptTailwind CSSDocker

EduAssess

A multi-tenant educational assessment platform designed for universities, corporate training, and certification bodies. Built to handle secure remote examinations across unreliable infrastructure — with anti-cheating enforcement, cross-platform lockdown, and offline-first resilience that keeps students' answers safe no matter what happens.

Why I Built It

Egyptian universities spend millions on platforms like Blackboard and ProctorU. These platforms are designed for stable Western infrastructure — always-on broadband, reliable webcams, modern hardware. That doesn't reflect reality for most institutions in the region.

EduAssess was built from day one to solve exam delivery under hostile conditions: intermittent internet, students on budget Android phones, institutions that need proctoring but can't afford $10/student licensing fees. Every architectural decision traces back to this constraint.

This is not a graduation project. It's a production system serving real users, with real billing, and real data isolation between institutions.

Architecture

text
┌─────────────────────────────────────────────────────────────┐ │ NGINX REVERSE PROXY │ │ (SSL termination) │ ├─────────────┬─────────────────┬─────────────────────────────┤ │ Web Client │ Desktop Client │ Mobile Client │ │ (Browser) │ (Electron) │ (React Native) │ ├─────────────┴─────────────────┴─────────────────────────────┤ │ REST API v2 (PHP 8.3) │ │ ┌──────────────────────────┐ │ │ │ Authentication Layer │ │ │ │ (Session + TOTP 2FA) │ │ │ ├──────────────────────────┤ │ │ │ RBAC Authorization │ │ │ │ (SaaS → Org → Prof) │ │ │ ├──────────────────────────┤ │ │ │ Multi-Tenant Scoping │ │ │ │ (org_id isolation) │ │ │ └──────────────────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ PostgreSQL 16 (JSONB + RLS) │ │ ┌──────────────────────────┐ │ │ │ organizations │ │ │ │ users (org_id scoped) │ │ │ │ exams & sessions │ │ │ │ proctoring_events │ │ │ └──────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘

Anti-Cheating Pipeline

The proctoring system operates as a state machine with multiple detection layers running simultaneously:

Browser Lockdown (Web)

  • Intercepts Alt-Tab, Ctrl+W, Ctrl+Tab, F11, right-click, and dev tools shortcuts
  • Monitors document.visibilityState — any tab switch triggers a violation event
  • Blocks clipboard operations during active exam sessions
  • Forces fullscreen mode and detects exits

Desktop Lockdown (Electron)

  • OS-level keyboard hook blocks Alt+F4, Win key, and task manager shortcuts
  • Process monitoring kills unauthorized applications
  • Kiosk mode prevents desktop access entirely
  • Blocks external monitors and screen sharing

Webcam Monitoring

  • TensorFlow.js face detection runs locally in the browser
  • Flags: no face detected, multiple faces, face turned away
  • Snapshots uploaded to POST /proctoring/snapshot at configurable intervals
  • All violations logged with timestamps for instructor review

Violation Severity Engine

Level 1 (Warning):     Tab switch, brief face absence
Level 2 (Alert):       Multiple tab switches, screen resize, dev tools
Level 3 (Auto-submit): Process tampering, kiosk escape, sustained face absence

Each violation is logged to the proctoring_events table with a timestamp, severity level, and raw event data. Instructors see a real-time violation feed during live exams.

Offline-First Answer Syncing

This is the critical differentiator. In environments where internet drops mid-exam, students cannot lose their work.

Dual Persistence Pattern:

  1. Every answer keystroke writes to IndexedDB first (local, instant)
  2. A background sync worker attempts PUT /session/{id}/answer every few seconds
  3. If the network fails, answers accumulate locally
  4. When connectivity returns, the sync worker replays all queued writes
  5. Server resolves conflicts by timestamp — latest answer wins

Heartbeat System:

  • Client sends POST /sync/heartbeat every 30 seconds
  • Server responds with remote commands: "Force Submit", "Extend Time", "Send Warning"
  • If heartbeat stops for >2 minutes, the proctor dashboard flags the student as "disconnected"
php
<?php declare(strict_types=1); // Exam session state machine: pending → in_progress → submitted → graded $stmt = $pdo->prepare(" UPDATE exam_sessions SET status = 'submitted', submitted_at = NOW(), answers = :answers WHERE id = :session_id AND student_id = :student_id AND status = 'in_progress' "); $stmt->execute([ 'answers' => json_encode($answersFromIndexedDB), 'session_id' => $sessionId, 'student_id' => $currentUser->id, ]);

Multi-Tenant Data Isolation

Every database query is scoped by org_id. There is no way for Organization A to access Organization B's data — not through the API, not through the UI, not through SQL injection. The scoping is enforced at the query layer, not just the application layer.

4-Tier RBAC:

RoleScopeCapabilities
SaaS OwnerGlobalManage all organizations, billing, system config
Org AdminSingle organizationManage professors, students, settings
ProfessorOwn coursesCreate exams, view results, proctor sessions
StudentOwn sessionsTake exams, view grades

API v2

RESTful JSON API at /api/v2/* powering all client applications:

EndpointPurpose
POST /auth/loginReturns temp_token if 2FA enabled, or access_token
POST /session/startValidates device, locks the exam seat
PUT /session/{id}/answerGranular auto-save every few seconds
POST /sync/heartbeat"I am alive" signal; receives remote commands
POST /proctoring/snapshotUploads webcam frame
POST /proctoring/violationReports local heuristic events

Technical Stack

LayerTechnologyWhy
BackendPHP 8.3Fast SSR, zero hydration overhead, PDO prepared statements
DatabasePostgreSQL 16Row-level security, JSONB for flexible exam schemas
Web ClientVanilla JS + TailwindNo framework overhead for exam-taking UI
DesktopElectronOS-level lockdown capabilities
MobileReact Native (Expo)Cross-platform student access
AuthSession + TOTP 2FAQR code setup, time-based codes
BillingDodo PaymentsSubscription management, free tier to enterprise
EmailBrevo SMTP + Gmail IMAPOutbound notifications + admin inbox

Deployment

Docker Compose on AWS EC2 (Ubuntu 22.04). PostgreSQL, PHP-FPM, and Nginx run in separate containers. Deployed via a PowerShell script that SSHs in, uploads a tarball, and restarts services. Nginx Proxy Manager handles SSL and reverse proxying.

Impact

  • Serves real university users with production uptime
  • Handles concurrent exam sessions across multiple institutions
  • Reduces proctoring costs by ~90% compared to commercial platforms
  • Works on budget hardware and unreliable connections where competitors fail

Co-founded with Khaled Essam (CFO).