Multi-tenant SaaS attendance platform built phase by phase.
- The backend and frontend are wired to persistent storage and live APIs only. No sample organisations, offices, employees, shifts, or monitor devices are auto-created.
- Bootstrap creates roles plus the first super-admin account from environment variables. All tenant data is expected to be created through the application after login.
- Phase 1: Setup backend, auth, RBAC, DB
- Phase 2: Super admin + organisation CRUD
- Phase 3: Office + employee CRUD
- Phase 4: Photo upload + validation
- Phase 5: AI embedding + FAISS
- Phase 6: Monitor + camera + attendance
- Phase 7: Anti-spoof + mask + multi-face
- Phase 8: Shifts + rules
- Phase 9: Reports
- Phase 10: UI polish + Docker + tests hardening
- FastAPI backend scaffold under
backend/ - SQLAlchemy 2.0 models for:
rolesorganisationsofficesemployeesemployee_photosemployee_face_embeddingsmonitor_devicesattendance_logsrecognition_eventsshiftsshift_rulesemployee_shift_assignmentsusersaudit_logsimpersonation_logs
- Soft-delete support fields on phase-1 entities where required:
is_activedeleted_at
- JWT authentication
- Password hashing
- RBAC dependency guards
- Standard API response envelope:
{
"success": true,
"message": "string",
"data": {},
"errors": []
}- Alembic migration for initial schema
- Bootstrap command for default roles and the first super admin
- Super admin APIs for:
- create organisation
- list organisations
- update organisation
- activate/deactivate organisation
- impersonate organisation admin
- Automatic org admin creation during organisation onboarding
- Login lockout for org-bound users when their organisation is inactive or soft-deleted
- Audit log entries for organisation create/update/status changes
- Impersonation log entries with:
actual_user_idacting_as_user_idorganisation_idactiontimestamp
- Automated tests for auth, RBAC, organisation CRUD, impersonation, and tenant lockout after deactivation
- Organisation admin APIs for:
- create office
- list offices
- update office
- soft delete office
- create employee
- list employees
- update employee
- soft delete employee
- Employee uniqueness rules scoped per organisation for:
employee_codeemailmobile
- Office timezone validation using IANA timezone names such as
Asia/Dubai - Tenant isolation checks for office and employee operations
- Automated tests for office CRUD, employee CRUD, per-organisation uniqueness, and org-admin route protection
- Employee photo enrollment APIs for:
- upload employee photo
- list employee photos
- delete employee photo
- get enrollment status
- Local file storage for employee photos under
STORAGE_ROOT - Photo validation for:
- empty file rejection
- max upload size
- JPEG/PNG/WEBP detection by file signature
- consent-gated biometric enrollment
- Enrollment status tracking with minimum 3 active photos required
- Automated tests for consent enforcement, upload validation, enrollment counting, and file deletion behavior
- Embedding generation per employee photo with DB-backed vectors in
employee_face_embeddings - Rebuildable organisation face index stored under
STORAGE_ROOT/indexes/... - Real provider wiring for:
insightfaceface detection and embeddingsfaissvector indexing and search
- Deterministic embedding and JSON index backends remain available only as explicit non-default dev/test modes
- Org-admin APIs for:
- get embedding status
- generate embeddings
- rebuild face index
- search face index
- Automated tests for minimum-photo embedding prerequisites, embedding generation, face-index rebuild, and similarity search
- Monitor APIs for:
- list monitor offices
- start monitor session
- process recognition frame
- Org-admin APIs for:
- create monitor user credentials
- list monitor users
- list monitor devices
- Attendance flow implemented for monitor scans:
- first valid scan marks
IN - next valid scan marks
OUT - duplicate scans inside the configured window are ignored
- unknown faces are logged but never marked present
- first valid scan marks
- Device session persistence through
monitor_devices - Recognition and attendance event storage in:
recognition_eventsattendance_logs
- Automated tests for monitor session start, recognition, duplicate prevention, IN/OUT toggling, and unknown-face handling
- Monitor anti-spoof and safety gates for:
- no-face rejection
- multi-face rejection
- liveness failure rejection
- masked-face confirmation requirement
- stricter thresholding for masked recognition
- Recognition responses now return:
mask_detectedliveness_statusfallback_required- explicit rejection messages for kiosk guidance
- Automated tests for multi-face rejection, liveness failure, masked-face confirmation, and masked successful recognition
- Shift APIs for:
- create/list/update shifts
- assign shifts to employees
- list assignments
- evaluate attendance for a selected day
- Shift rule support for:
- grace period
- late mark
- half day
- early exit
- overtime
- weekly off
- holiday dates
- night shift / cross-day evaluation
- Automated tests for late arrival, early exit, overtime, and night-shift evaluation
- Reporting APIs for:
- daily summary
- monthly summary
- employee-wise report
- office-wise report
- shift-wise report
- late/absent report
- CSV export
- Report generation reuses the shift evaluation engine so attendance classification is consistent across monitor flow, evaluation, and reports
- Automated tests for daily summary, late/absent filtering, and CSV export
- Deployment packaging:
- backend Dockerfile
- frontend Dockerfile
- root
docker-compose.ymlfor backend + frontend + PostgreSQL
- React frontend shell under
frontend/with:- unified login
- super admin organisation view
- org admin operational panels
- monitor session and frame-submit screen
- Final verification completed for:
- backend automated test suite
- frontend production build
- Docker Compose configuration parsing
- Manual attendance correction endpoints with required reason and audit log entries
- Browser monitor frontend now supports:
- Webcam API preview
- Fullscreen monitor mode
- periodic frame capture
- camera permission / no-camera / disconnect handling
- offline frame queue with retry after reconnect
- backend-derived face count and liveness handling instead of browser-supplied recognition flags
The current implementation defaults to SQLite for local verification. PostgreSQL remains the target production database and can be enabled through DATABASE_URL.
cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -e '.[dev,ai]'
cp .env.example .env
alembic upgrade head
python -m app.db.init_data
uvicorn app.main:app --reloadSet FIRST_SUPERADMIN_EMAIL and FIRST_SUPERADMIN_PASSWORD in backend/.env before running python -m app.db.init_data. The bootstrap command will stop if the placeholder admin password is still present.
Provision the InsightFace model pack locally under STORAGE_ROOT/models/insightface/models/buffalo_l before using photo embedding generation, face search, or monitor recognition. The backend no longer falls back to downloading model assets at runtime.
Open http://127.0.0.1:8000/docs.
For the packaged stack:
docker compose up --buildThen open:
- Frontend:
http://127.0.0.1:3000 - Backend docs:
http://127.0.0.1:8000/docs
Frontend verification:
cd frontend
npm install --cache /tmp/afras-npm-cache
npm run buildThe bootstrap command reads these values from .env:
FIRST_SUPERADMIN_EMAIL=admin@your-domain.comFIRST_SUPERADMIN_PASSWORD=replace-this-before-first-runSTORAGE_ROOT=./storageEMPLOYEE_PHOTO_MAX_SIZE_MB=5FACE_EMBEDDING_PROVIDER=insightfaceFACE_INDEX_BACKEND=faissFACE_ANALYSIS_MODEL_NAME=buffalo_lFACE_ANALYSIS_MODEL_ROOT=./storage/models/insightfaceMONITOR_SIGNAL_SOURCE=backendFACE_MATCH_THRESHOLD=0.98ATTENDANCE_DUPLICATE_WINDOW_MINUTES=5
No other data is bootstrapped.
GET /api/v1/healthPOST /api/v1/auth/loginGET /api/v1/auth/meGET /api/v1/auth/rbac-checkGET /api/v1/org-admin/officesPOST /api/v1/org-admin/officesPATCH /api/v1/org-admin/offices/{office_id}DELETE /api/v1/org-admin/offices/{office_id}GET /api/v1/org-admin/employeesPOST /api/v1/org-admin/employeesPATCH /api/v1/org-admin/employees/{employee_id}DELETE /api/v1/org-admin/employees/{employee_id}GET /api/v1/org-admin/employees/{employee_id}/photosPOST /api/v1/org-admin/employees/{employee_id}/photosDELETE /api/v1/org-admin/employees/{employee_id}/photos/{photo_id}GET /api/v1/org-admin/employees/{employee_id}/enrollment-statusGET /api/v1/org-admin/employees/{employee_id}/embedding-statusPOST /api/v1/org-admin/employees/{employee_id}/embeddings/generatePOST /api/v1/org-admin/face-index/rebuildPOST /api/v1/org-admin/face-searchGET /api/v1/org-admin/monitor-usersPOST /api/v1/org-admin/monitor-usersGET /api/v1/org-admin/monitor-devicesGET /api/v1/org-admin/shiftsPOST /api/v1/org-admin/shiftsPATCH /api/v1/org-admin/shifts/{shift_id}GET /api/v1/org-admin/shift-assignmentsPOST /api/v1/org-admin/shift-assignmentsGET /api/v1/org-admin/attendance-evaluationGET /api/v1/org-admin/reports/dailyGET /api/v1/org-admin/reports/monthlyGET /api/v1/org-admin/reports/employeeGET /api/v1/org-admin/reports/officeGET /api/v1/org-admin/reports/shiftGET /api/v1/org-admin/reports/late-absentGET /api/v1/org-admin/reports/export/csvGET /api/v1/org-admin/attendance-logsPATCH /api/v1/org-admin/attendance-logs/{attendance_log_id}/manual-correctionGET /api/v1/monitor/officesPOST /api/v1/monitor/session/startPOST /api/v1/monitor/recognizeGET /api/v1/super-admin/organisationsPOST /api/v1/super-admin/organisationsPATCH /api/v1/super-admin/organisations/{organisation_id}PATCH /api/v1/super-admin/organisations/{organisation_id}/statusPOST /api/v1/super-admin/impersonations/{target_user_id}
- The repository now defaults to backend-owned recognition inputs rather than browser-supplied demo flags.
- A local InsightFace model pack and AI runtime dependencies are still required in the target environment for enrollment, indexing, and live recognition.