Skip to content
All projects

CampusOS — Smart Campus OFPPT

Fraud-proof QR attendance, dropout risk detection, and an on-premise AI assistant for OFPPT campuses.

Role
Full-stack developer: architecture, Laravel backend, React/Inertia frontend, AI layer, NativePHP mobile app
Team
4 contributors
Year
2026
Duration
Hackathon sprint — OFPPT Hackathon 2026
Status
Prototype
Trainer view of the dynamic QR code with cryptographic token countdown and live scan feed

Overview

A full-stack campus operations platform built for OFPPT, Morocco's vocational training office. It replaces paper roll-call with a rotating, HMAC-signed QR code that trainers project in class and students scan from a native mobile app. Every scan is validated against GPS geofencing, campus Wi-Fi subnet and device fingerprinting, so proxy check-ins fail. On top of that attendance ledger it encodes OFPPT's real regulatory logic, surfaces at-risk trainees before they cross the exam-exclusion threshold, and answers regulatory questions through a role-aware AI assistant running entirely on-premise.

  • Rotating HMAC-SHA256 QR codes on a 30-second validity window, layered with GPS geofencing, Wi-Fi subnet matching, and per-session device fingerprinting — four independent checks a proxy check-in has to beat at once.
  • Predictive risk dashboard encoding OFPPT's actual exclusion rule (30h unjustified absences), ranking trainees by accumulated hours and attendance rate with escalation actions built into the row.
  • Fully on-premise AI assistant: Ollama with Mistral for generation, nomic-embed-text for embeddings, cosine-similarity RAG over institutional regulations, and a guardrail layer scoping it to campus topics — zero third-party API calls.
  • Conflict-aware timetable manager with room, trainer, and group collision detection plus a trainer→admin approval workflow for reschedules, fully audit-logged.
  • Companion NativePHP mobile app for trainees — camera QR scanning, timetable, assiduity, messaging — sharing the same Laravel API behind token-authenticated middleware.

Stack

  • PHP
  • Laravel
  • Inertia.js
  • React
  • Tailwind CSS
  • Vite
  • MySQL
  • SQLite
  • Ollama
  • Spatie Laravel Permission
  • NativePHP Mobile
  • Mistral
  • nomic-embed-text
  • PHPUnit

My role

Full-stack developer: architecture, Laravel backend, React/Inertia frontend, AI layer, NativePHP mobile app

The problem

OFPPT campuses still run attendance on paper. Roll-call eats the first ten minutes of every session, sheets are easy to fake through friends signing in for absentees, and totals are only tallied weeks later. By that point a trainee has already crossed the 30-hour unjustified-absence threshold and is barred from end-of-module exams. Nobody sees the slide coming: administration has no live view of who is drifting, trainers cannot intervene early, and trainees have no visibility into a score that quietly decides their academic year. Timetabling has the same blind spot. Sessions get rescheduled into rooms already booked or over capacity, because conflicts are only caught by whoever happens to notice.

The approach

One system that owns the attendance ledger end to end. The trainer projects a QR code that regenerates every 30 seconds, each payload carrying an HMAC-SHA256 signature over the session ID and timestamp. A scan is accepted only if the signature verifies, the timestamp is inside the tolerance window, the device is within 50m of the room or on the campus Wi-Fi subnet, and its fingerprint has not already been used by another trainee in the same session. That combination structurally kills screenshot sharing and proxy check-ins. Every accepted scan feeds three engines: assiduity applies OFPPT's penalty rules and flags risk tiers, gamification awards badges and recomputes standing, and the notification layer alerts the trainee.

What was hard

Admin dashboard showing campus attendance rate, enrolment counts, pending justifications, and critical absenteeism alerts

A QR code on a projector is trivially screenshotted and forwarded to an absent friend. The whole attendance ledger is worthless if one photo can mark someone present.

Made the code a moving target and the scan context-bound. The payload is signed with HMAC-SHA256 under the app key, regenerated every 30 seconds and rejected outside a 30-second tolerance, so a forwarded screenshot expires before it can be used. The scan must also originate within 50m of the room or from the campus Wi-Fi subnet, and a device fingerprint already used by another trainee in the same session is refused outright.

Trade-off

Signature verification depends on server/client clock agreement, and a tight window means a slow camera or bad signal can cost a legitimate trainee their scan. We accepted that friction and gave trainers a manual override endpoint as the escape hatch, rather than widening the window and weakening the guarantee.

Predictive risk management table ranking trainees by accumulated unjustified absence hours and attendance rate

Campus attendance is regulated student data, and 'add an AI assistant' normally means shipping it to a third-party API, which is a non-starter for an institutional deployment.

Kept the entire inference path on-premise: Ollama hosting Mistral for generation and nomic-embed-text for embeddings, with a hand-rolled RAG pipeline: chunk institutional documents, embed, store vectors, rank by cosine similarity at query time. A guardrail service allow-lists campus topics and a role-aware context builder injects only the caller's own scoped data.

Trade-off

Cosine similarity computed in PHP over all stored chunks is O(n) per query. That is fine at hackathon corpus size, but it needs a real vector index before the document set grows. Local Mistral also answers slower and less fluently than a frontier hosted model. Both were the right trade for data residency.

Trainer dashboard listing the day's sessions with attendance activation locked until each session starts

Attendance is not one action — a single scan has to update the assiduity score, re-evaluate risk, award badges, recompute leaderboard rank and notify the trainee, without leaving the ledger half-written if any step fails.

Kept the write path in one DB transaction and pushed each rule set into its own injectable service, so ValidateurPointage orchestrates rather than implements. Each engine is unit-tested in isolation, which is what made the interacting rules safe to change during the sprint.

Trade-off

Running gamification and risk recalculation synchronously inside the check-in request adds latency at exactly the moment 30 students scan at once. The database queue is already wired up, so moving that work async is the next step — we kept it inline so demo state stayed immediately consistent.

Weekly timetable manager with per-group, per-room, and per-trainer views and inline session editing

Rescheduling a session can quietly create a double-booked room, a trainer in two places, or a group with overlapping courses — and trainers, not admins, are the ones who need to move sessions.

Built SolveurConflits as a standalone service checking room, trainer and group collisions plus capacity, exposed both as a pre-submit check and as a server-side gate. Trainers submit requests instead of writing directly; admins approve from a moderation queue, and every accepted change is audit-logged.

Trade-off

Approval-gated edits mean a trainer cannot fix their own timetable in the moment. For an institution where the timetable is a contractual artifact, traceability beat convenience.

More screens

Global trainee leaderboard with engagement scores, attendance rates, and awarded badges

The engagement leaderboard: attendance, assiduity note and badges collapsed into one transparent score across all groups.

01 / 06

Results

QR token lifetime
30s

QR token lifetime

HMAC-SHA256 signed payload, regenerated and expiring every 30 seconds

Independent anti-fraud checks
4

Independent anti-fraud checks

Signature validity, time window, GPS/Wi-Fi proximity, device fingerprint uniqueness

Automated tests
69

Automated tests

PHPUnit unit and feature suites covering QR signing, check-in validation, assiduity, gamification, conflicts, RAG and the mobile API

Eloquent models
28

Eloquent models

Across 35 migrations — attendance, gamification, scheduling, messaging, AI and audit domains

Role-scoped pages
18

Role-scoped pages

8 admin, 6 trainer, 3 student, 1 auth — all React 19 over Inertia

On-premise AI inference
100%

On-premise AI inference

Ollama, Mistral and nomic-embed-text run locally; no student data leaves the campus network