- Introduction
- Pitch
- Hogwarts
- Live Demo
- MVP
- Roadmap
- Launch Sprint
- PRD
- Get Started
- Localhost
- Architecture
- Structure
- Pattern
- Page
- Layout
- Content
- Types
- Config
- Actions
- Queries
- Authorization
- Validation
- Form
- Table
- Detail
- Card
- Util
- Hooks
- List Params
- Views
- README.md
- ISSUE.md
- Technology Stack
- Database
- File
- CDN Assets
- Entry Points
- Dashboard
- Authentication
- Credentials
- OAuth
- Flow Diagrams
- Multi-Tenancy
- Offline
- Onboarding
- Onboarding Videos
- Add Values
- Admission
- Application
- Attendance
- Compliance
- Profile
- Exams
- Exam Wizard
- Timetable
- Classrooms
- Notifications
- Conference
- LMS (Lumos)
- Finance
- Fee Management
- Invoice
- Wallet
- Salary
- Payroll
- Timesheet
- Expenses
- Budget
- Receipt
- Accounts
- Banking
- Reports
- Dashboard
- Permissions
- Messages
- Integration Flow
- Provision
- AI Document Processing
- Document Intelligence
- Internationalization
- Translation
- Translation Guide
- Icons
- Docs Factory
- Inspiration
- Listings
- Teachers
- Students
- Catalog
- Library
- Contributing
- Code of conduct
- GitHub Workflow
- Database Seeds
- Database Safety
- Test Accounts
- Playwright
- Prettier
- Block Rebound
The compliance block lets schools submit data to a government regulator on a
scheduled cadence and prove they met regulator-specific SLAs. ADEK eSIS
(Abu Dhabi Department of Education and Knowledge) is the first provider; the
framework is generic so future authorities (SEC KSA, MoE Qatar, MoE Sudan)
plug in by adding one ComplianceProvider enum value and a sibling directory
under src/lib/compliance/providers/<authority>/.
Ship tracker: databayt/hogwarts#1 — consolidated attendance + compliance master tracker. See also Aldar Epic 01.
Status
| Capability | Status | Notes |
|---|---|---|
| Daily CSV submission | Production (DRY_RUN) | Generic mapper, ADEK 2025/26 absence categories |
| 2-hour parent-contact SLA cron | Production | /api/cron/absence-followup, every 30 min, UTC arithmetic |
| Per-school settings UI | Production | /{lang}/compliance (ADMIN/STAFF/DEVELOPER) |
| Cross-tenant credential groups | Production | DEVELOPER only, /{lang}/(saas-dashboard)/compliance |
| Circuit breaker | Production | 3 failures within 1h → halt; 1h cooldown → HALF_OPEN |
| Encryption (AES-256-GCM) | Production | COMPLIANCE_ENCRYPTION_KEY env, key-version rotation supported |
| Audit log integration | Production | Namespaced compliance.* action strings |
| ADEK piggyback connector | Wired | Awaits Aldar group eSIS credentials |
| ADEK official API connector | Stub | Awaits ADEK developer access |
| RPA worker (Playwright) | Scaffold | tools/adek-rpa-worker/, awaits eSIS portal selectors |
| ADEK async webhook receiver | Wired | /api/webhooks/adek (HMAC + ProcessedWebhookEvent dedupe) |
Multi-tenant boundary
- Per-school config table:
SchoolComplianceConfig(one row per school × provider, opt-in default off). - Worker / claim endpoint requires a
SchoolApiTokenwith scopecompliance.rpa_claim— the token'sschoolIdIS the tenant; request body schoolId is never trusted. - DEVELOPER-only saas-dashboard at
/{lang}/(saas-dashboard)/compliancefor cross-tenant credential groups. Page is role-gated at the layout level. - All
compliance.*audit entries recordschoolId(ornullfor DEVELOPER cross-tenant actions like creating a credential group).
Sidebar visibility
- The school-dashboard
/complianceentry appears in the sidebar forADMIN | STAFF | DEVELOPERroles. - The page itself enforces a country gate: schools where
school.country !== "AE"are redirected to/dashboardunless the actor is aDEVELOPER.
Connector modes
| Mode | Behavior |
|---|---|
DRY_RUN | Build CSV → persist inline (csvArtifactContent) → mark SUBMITTED. School registrar uploads to eSIS manually. Default for the Yasmina BA pilot. |
PIGGYBACK | Decrypt shared-group credentials, upload via the group's eSIS account. Circuit breaker halts cascading failures across all schools in the group. |
OFFICIAL_API | Documented vendor contract. Currently returns OFFICIAL_API_NOT_AVAILABLE. |
RPA | Leaves the row at QUEUED for the external Fly.io worker. Worker claims via POST /api/compliance/worker/claim, runs Playwright session against eSIS, acks via POST /api/compliance/worker/ack. |
DISABLED | Skipped in cron. |
Cron schedules (vercel.json)
/api/cron/esis-submit—0 10 * * *(10:00 UTC = 14:00 GST, ADEK rule). Enqueues oneComplianceSubmissionrow per eligible school whose configuredsubmissionTimeUtchas already passed; fans out viaafter()for non-RPA modes./api/cron/absence-followup—*/30 * * * *. For each compliance-enabled school, finds ABSENT rows older thanparentContactSlaMinutes, dispatchesabsence_unreported_followupto guardians onin_app + email + whatsapp, and writes anAttendanceInterventionrow of typePARENT_EMAILas audit evidence.
Audit namespace
All compliance events log to AuditLog with action prefix compliance.*:
compliance.config.enabled/disabled/mode_changedcompliance.credential.created/rotated/revokedcompliance.submission.queued/submitted/accepted/rejected/failed/claimedcompliance.parent_contact.queued/delivered/failedcompliance.circuit_breaker.opened/closed/half_open
AuditLog.userId is nullable so cron / worker / webhook events record with
userId: null rather than violating the FK.
Schema
Models live in prisma/models/compliance.prisma:
ComplianceProviderenum (ADEK_ESIS,CUSTOM)ConnectorModeenum (DRY_RUN,PIGGYBACK,OFFICIAL_API,RPA,DISABLED)ComplianceSubmissionStatus+CircuitBreakerStateenumsSchoolComplianceConfig,SharedComplianceCredentialGroup,SchoolComplianceCredential,ComplianceSubmission(idempotency key:[schoolId, provider, submissionDate, attemptNumber])
Environment variables
COMPLIANCE_ENCRYPTION_KEY— 32-byte hex (openssl rand -hex 32). Required in production; encryption helper throws at module load if absent.ADEK_WEBHOOK_SECRET— HMAC secret for the async receipt webhook (/api/webhooks/adek).CRON_SECRET— shared with all other Vercel crons.
See also
- Attendance — the upstream data and notification triggers
- Notifications — multi-channel dispatch
- Multi-tenancy — tenant boundary enforcement