System Blueprint

Complete functional specification and replication guide

American Open University Admissions Platform

Complete System Blueprint, Functional Specification and Replication Guide

This document describes the entire admissions platform in enough detail that an independent engineering team (or an AI development platform) can rebuild it accurately: data model, business rules, decision engines, status machines, screens, permissions, communications, documents, payments, exports and audit trails.


1. Purpose and Scope

The platform is an end-to-end university admissions system covering two programme levels:

  1. Undergraduate (UG) - three entry pathways (tracks) with automated eligibility decisioning and transfer-credit awards.
  2. Postgraduate (PG) - masters-level admission (MBA, MIT, MPA) with qualification-based decisioning, referees and statement of purpose.

It serves four audiences:

AudienceAccess modelPrimary surface
Prospective applicantPublic, no account required; retrieval by email + application referenceApplication wizard, applicant dashboard
Admitted studentActivated after acceptance fee verificationStudent portal (documents, fees, materials)
Admissions officer / department head / system administratorAuthenticated staff with permission-gated capabilitiesAdmin dashboards
Recruitment partners (agents, affiliates, partners)Tracked by referral code embedded in applicationsAdmin partner reports

Design principles that must be preserved in any replication:

  • No forced signup before applying. Conversion is protected by allowing anonymous drafts and email-based retrieval.
  • Drafts are never lost. Local autosave plus server-side draft persistence.
  • Every decision is explainable. The engine stores the reasons and the missing requirements, not just the outcome.
  • Every status change is auditable. Actor, old status, new status, timestamp, reason and origin screen.
  • Admin discretion is a first-class feature, not a hack. Overrides are structured, justified, attributed and blocked from silently bypassing verification.

2. Technology Baseline

  • Frontend: React (SPA) + Tailwind CSS, component library of composable primitives (button, card, dialog, select, table, tabs, badge, checkbox, textarea, toast), Lucide icon set, Framer Motion for entry animations, Recharts for analytics, date-fns/moment for dates, TanStack Query for server state on admin screens.
  • Backend: schema-defined entities (document store) with row-level security, plus serverless HTTP functions for privileged logic.
  • Integrations used: LLM invocation (AI review and document analysis), file upload/storage, transactional email, PDF generation client-side (jsPDF) for letters.
  • Client routing: explicit route table; every page reachable by a URL that can be emailed to an applicant (deep links carry ?id= or ?draft_id=).

Replication note: any equivalent stack works, but three backend behaviours are mandatory - (a) service-role functions that can read/write applications without an end-user session, (b) row-level security so applicants cannot enumerate other records, (c) file storage with both public and signed-private URLs.


3. Data Model

3.1 Application (undergraduate)

Identity and routing

  • application_id - human-readable unique reference shown to the applicant and used in all letters and lookups.
  • programme_level - "Undergraduate" | "Postgraduate" (UG records use Undergraduate).
  • track - "Start" | "Accelerate" | "Advance" | "Postgraduate".
  • credential_type - free text of the applicant's declared highest previous credential, used to pick the wizard branch.
  • referral_code - recruiter attribution.

Personal

  • first_name, middle_name, last_name, gender (Male | Female | Other | Prefer not to say), date_of_birth, email, phone, city, state_region, nationality.

Programme choice

  • program (e.g. Data Science, Cybersecurity, Software Engineering, Information Technology, business disciplines), study_mode ("Fully Online" | "On Campus" | "Blended"), campus (required when study mode is On Campus or Blended), highest_degree, comments.

O-Level academics

  • olevel_exam_bodies - array from WAEC | NECO | NABTEB (combination of sittings allowed).
  • olevel_results - array of { exam_body, subject, grade } where grade is one of A1, A2, A3, B2, B3, C4, C5, C6, D7, E8, F9.
  • olevel_year_completed.

Tertiary academics (branch-specific)

  • ND/NID/NCE: nd_nce_institution, nd_nce_state, nd_nce_program, nd_nce_grade (Distinction | Upper Credit | Lower Credit | Pass), nd_nce_credits, nd_nce_year_completed.
  • HND: hnd_institution, hnd_program, hnd_grade, hnd_year_completed.
  • Degree: bsc_institution, bsc_degree, bsc_class (First Class | Second Class Upper | Second Class Lower | Third Class | Pass), bsc_discipline, bsc_year_completed.
  • Professional: professional_body (ICAN, CITN, CIBN, CIPM ...), professional_membership_number, professional_year.
  • work_experience_years, career_transition (boolean).

JAMB UTME (informational, never used for the decision)

  • jamb_utme_registered, jamb_utme_score, jamb_utme_year, jamb_utme_result_url.

Attestations and advising

  • terms_agreed, signature (captured drawing, stored as an image), fraud_caveat_accepted.
  • advisor_meeting_requested, advisor_meeting_requested_date, advisor_meeting_handled.

Admin override (conditional admission)

  • conditional_admission object: active, admission_type ("Conditional" | "Full"), reason_type ("requirement_waiver" | "advisor_recommendation"), waived_requirements (array of the exact unmet-requirement strings produced by the engine), justification, condition_deadline, decided_by, decided_by_email, decided_at, conditions_cleared, conditions_cleared_at, conditions_cleared_by.

Decision output

  • decision_result object: eligible, conditional, reasons (array of human-readable pass/fail explanations), missing (array of unmet requirement strings), evaluated_at, requirement_id (which requirement record was applied), override_mismatch (set when a re-evaluation still fails on a manually admitted record), program_recommendations (array of { program, track, meets_requirements }).
  • credits_transfer - awarded transfer credits.

Documents

  • passport_photo_url, statement_of_purpose_url, birth_certificate_url, olevel_result_url, highest_credential_url, relevant_document_url, government_id_url, admission_letter_url (admin upload), provisional_admission_letter_url, enrollment_documents (object of post-admission uploads).

Payments

  • payment_proof_url, acceptance_fee_paid, acceptance_fee_payment_reference, acceptance_fee_payment_method (paystack | paypal | bank_transfer), acceptance_fee_paid_date, acceptance_payment_status (pending | pending_verification | verified | rejected), student_portal_activated.

Review and lifecycle

  • status - draft | submitted | provisionally_accepted | document_verification | under_review | interview_scheduled | interview_completed | approved | matriculated | rejected.
  • ai_review_flags - array of { severity: low|medium|high, category, message, timestamp }.
  • document_verification - object holding per-document AI verification output.
  • documents_verified_by_admin, documents_verified_at.
  • admin_notes - array of { note, author, timestamp }.
  • reminders_sent - array of { reminder_type: 3_day|7_day|14_day|manual, sent_date, template_used }, plus last_reminder_sent.

Required fields: first_name, last_name, email (everything else can be progressively completed - this is what makes anonymous drafts possible).

3.2 PostgraduateApplication

  • application_reference (e.g. AGL-PG-2026-0001), programme_level fixed to Postgraduate, current_step (wizard resume pointer).
  • Personal: names, date_of_birth, gender, nationality, phone, email, contact_address, country_of_residence, state_region, city, is_international.
  • Programme: program (MBA | MIT | MPA), program_name, entry_term, study_mode, campus, specialization, doctoral_intent (In Nigeria | Abroad | Undecided | No).
  • Academic history: qualifications array of { institution, country, qualification_type, field_of_study, class_of_degree, year_awarded }; nysc_status (Completed | Exempted | Foreign-trained, not applicable | Not yet completed); language_of_instruction (English | Other); below_threshold; review_required.
  • Decision: decision_result with eligible, conditional, reasons, missing, best_class, min_class, evaluated_at, requirement_id.
  • Documents: olevel_result_url, degree_certificate_url, transcript_url, nysc_certificate_url, cv_url, passport_photo_url, valid_id_url, english_proficiency_url, gre_gmat_url (optional), documents_submitted_date, class_documents array of { label, url, uploaded_date }.
  • Referees: array of { full_name, title, organization, relationship: Academic|Professional, email, phone, letter_url }.
  • Statement of purpose: statement_of_purpose (text), word_count, statement_of_purpose_url (uploaded file alternative).
  • Declarations: info_confirmed, attestation_confirmed, fee_confirmed.
  • Fees: application_fee_paid, payment_method (paystack | paypal | flywire | bank_transfer | waived), payment_reference, payment_status (pending | pending_verification | paid | waived | failed), payment_proof_url; acceptance stage: acceptance_fee_paid, acceptance_payment_proof_url, acceptance_payment_status.
  • Lifecycle: status - draft | provisionally_accepted | document_verification | submitted | under_review | admitted | conditional_offer | not_admitted | enrolled_pending_registration | matriculated; decision_note, decision_date, admin_notes, document_verification, provisional_admission_letter_url.

3.3 AdmissionRequirement (the rules table - the heart of the engine)

Keyed by program + track, with is_active flag:

  • O-Level: olevel_min_credits, olevel_min_grade (A1..C6), olevel_required_subjects (compulsory, e.g. English Language, Mathematics), olevel_required_for_program (programme-specific, e.g. Physics for computing).
  • Tertiary minimums: nd_min_grade, nd_min_credits, hnd_min_grade, bsc_min_class.
  • Flexibility: accept_career_transition, professional_bodies_accepted, special_conditions.
  • Money: acceptance_fee_nigeria, acceptance_fee_international.

This entity makes the whole platform configurable without code changes; universities adjust requirements per programme and per pathway from an admin screen.

3.4 Supporting entities

  • PostgraduateProgram - name, code, tuition (NGN/USD), application fee, acceptance fee, specializations, is_active.
  • PostgraduateSettings - entry_terms, study_modes, campuses, default fees, application_fee_waived + fee_waiver_session (promotional waivers), payment links (paystack, paypal, flywire), bank transfer details (bank name, account name, number, routing/SWIFT).
  • ReferralPartner - name, partner_type (agent | affiliate | partner), referral_code, email, phone, organization, is_active.
  • StatusChangeLog - application_id, application_type (undergraduate | postgraduate), application_reference, applicant_name, old_status, new_status, changed_by, changed_by_id, changed_by_email, reason, source (detail_page | list_page | kanban_board | bulk_action | system).
  • DocumentRequest - application_id, document_name, description, status (pending | uploaded | approved | rejected), uploaded_file_url, uploaded_date, requested_by.
  • ApplicationMessage - application_id, sender_type (admin | applicant), sender_name, sender_email, message, is_read. Powers two-way threaded messaging.
  • MessageTemplate - name, subject, message/body, category (request_documents | status_update | interview | general | follow_up | campaign), is_active.
  • ReminderTemplate - name, subject, body (HTML), reminder_type (3_day | 7_day | 14_day | manual), is_active.
  • ReminderSchedule - schedule_name, days_after_creation, reminder_type, is_enabled, only_for_status (draft | submitted | under_review | all).
  • EmailLog - recipient_email, subject, email_type (submission_confirmation | status_change | incomplete_reminder | otp_verification | welcome | campaign), application_id, status (sent | failed | retrying | delivered), retry_count, error_message, sent_at, last_retry_at.
  • User (staff) - built-in identity plus admin_role and optional custom permissions array.

3.5 Row-level security posture

  • Administrative entities (AdmissionRequirement, ReferralPartner, StatusChangeLog, EmailLog, MessageTemplate, ReminderTemplate, ReminderSchedule) - read/create/update/delete restricted to admin role.
  • PostgraduateProgram / PostgraduateSettings - public read (needed by the public wizard for fees and terms), admin-only write.
  • DocumentRequest - admin create/delete; applicants may upload against an existing request.
  • ApplicationMessage - admin delete only; both parties append.
  • Application / PostgraduateApplication - reached by applicants only through service-role backend functions, never by direct client queries, so no applicant can list or enumerate records.

4. Backend Functions (privileged logic)

All are HTTP endpoints executing with service-role credentials.

4.1 saveApplication

Creates or updates a draft/submission for an anonymous applicant. Accepts an application payload plus optional record id. Responsibilities: whitelist writable fields, generate application_id on first create, persist status transitions permitted to applicants (draft, submitted), and return the saved record. Replication requirement: strict field whitelisting - never spread arbitrary client keys into the record, or applicants can inject status, decision or payment fields.

4.2 getApplicationById

Returns a single application by record id for the applicant dashboard deep link. Should return only applicant-safe fields.

4.3 getApplicationsByEmail

Returns the list of applications belonging to an email address, for the retrieval screen. Should be rate-limited/OTP-gated to avoid enumeration.

4.4 generateOtp

Issues a one-time code to the applicant's email for verified retrieval of an existing application.

4.5 evaluateAdmission (undergraduate decision engine)

Input: application_id.

Algorithm:

  1. Load the application; abort 404 if absent.
  2. Compute hasOverride = conditional_admission.active === true.
  3. Resolve the governing rule: active AdmissionRequirement matching the application's program + track; if none, fall back to a default rule set.
  4. If the applicant's academic payload is incomplete (e.g. no O-Level results where they are needed), produce a decision with eligible: false, an explanatory missing list, and set status to under_review - unless hasOverride, in which case the status is left untouched and override_mismatch: true is recorded.
  5. Otherwise evaluate by track:
    • Start (O-Level entry) - count credits at or above olevel_min_grade across all declared exam bodies (best grade per subject across sittings); require olevel_min_credits; require every subject in olevel_required_subjects and olevel_required_for_program at credit level.
    • Accelerate (ND/NID/NCE) - compare nd_nce_grade against nd_min_grade on the ordered scale Distinction > Upper Credit > Lower Credit > Pass; validate nd_nce_credits against nd_min_credits; O-Level requirements still apply as a foundation check where configured.
    • Advance (HND / degree / chartered) - compare hnd_grade against hnd_min_grade, or bsc_class against bsc_min_class on the ordered scale First Class > Second Class Upper > Second Class Lower > Third Class > Pass; accept a listed professional body membership as an alternative route; honour accept_career_transition with work_experience_years.
  6. Award transfer credits (credits_transfer) from the pathway - typically ND/NCE credits for Accelerate and a larger block for Advance - capped by the programme's total credit requirement (120 credit units).
  7. Build program_recommendations: for each active requirement record, test the same profile and report meets_requirements, so an applicant who fails one programme can be steered to one they qualify for.
  8. Persist decision_result with reasons (every check, passed or failed, in plain English) and missing (only the failures).
  9. Set status: eligible to provisionally_accepted, otherwise under_review. If hasOverride, keep the existing status and set override_mismatch when the re-check still fails.

Two invariants that must be replicated: the engine is idempotent (re-running never loses admin decisions) and never rejects outright - a failing applicant lands in under_review for human judgement, never in a dead end.

4.6 evaluatePGAdmission (postgraduate decision engine)

Input: PG application id.

  1. Determine the best qualification from qualifications by class_of_degree on the ordered class scale; store as best_class, with the governing rule's minimum as min_class.
  2. Check the minimum class for the chosen programme; if below, set below_threshold and review_required rather than declining.
  3. Check O-Level foundation, NYSC status (Completed / Exempted / Foreign-trained are acceptable; "Not yet completed" becomes a condition), and English language of instruction (non-English requires proficiency evidence).
  4. Check the required document set and referee count; missing items become missing entries and produce a conditional rather than a negative outcome.
  5. Persist decision_result and move the record to provisionally_accepted, conditional_offer or under_review.

5. The Undergraduate Applicant Journey

5.1 Programme selection (entry point)

The landing decision screen asks the applicant to choose Undergraduate or Postgraduate, and for undergraduate, to declare their highest previous credential. That declaration maps to a track:

Declared credentialTrackMeaning
O'Level / SSCEStartStandard entry, 120 credits to complete
ND / NID / NCEAccelerateDirect entry with transfer credits
HND / B.Sc / B.A / B.Tech / chartered membershipAdvanceAdvanced standing with a larger credit block

The chosen credential and provisional credit estimate are carried into the wizard as URL parameters (credential, credits) so the form self-configures.

5.2 The application wizard

A stepped form with a persistent step indicator, forward/back navigation, per-step validation and autosave.

Steps:

  1. Personal details - names, gender, date of birth, email, phone, nationality, then location fields (state/region and city driven by a locations dataset, with Nigerian states enumerated).
  2. Programme choice - programme, study mode, and campus (campus field appears and becomes required only for On Campus and Blended).
  3. Academic credentials - branch rendered by track:
    • O-Level section: choose exam bodies (multiple sittings supported), then add subject rows using a grouped subject dropdown (grouped by discipline to guarantee exact backend-matching strings) with a grade dropdown; year completed.
    • ND/NCE, HND, degree and professional sections rendered per track, with institution pickers backed by a curated Nigerian institutions dataset (grouped dropdowns; searchable command palette) so institution names are consistent.
  4. JAMB UTME (optional) - registered flag, score, year, and result slip upload. Explicitly labelled as not affecting the admission decision. When the applicant has a JAMB registration, the dashboard later surfaces a Change of Institution guidance banner.
  5. Documents - uploads for passport photograph, O-Level result, highest credential, birth certificate, government ID, statement of purpose and any other relevant document. Each upload field shows progress, accepts image/PDF, and stores the returned file URL on the record.
  6. Declarations and signature - terms agreement, a fraud caveat ("admission is rescinded if any entry is false"), and a drawn signature captured to an image.
  7. Review and submit - a read-back of everything with per-section edit jumps, then submit.

Wizard mechanics to replicate:

  • Local autosave on every change into browser storage keyed to the draft, so a refresh, crash or dropped connection never loses input.
  • Server draft sync through saveApplication, giving the applicant an application_id and a resumable record even before submission.
  • Resume by link - ?draft_id= reopens the exact draft, and the admin/applicant dashboards link back into it.
  • Submit guard - the submit button disables while in flight and always resolves (never stranded in a "Submitting..." state).
  • Advisor request - the applicant may ask to speak to an advisor, which sets advisor_meeting_requested and raises an admin action item.

5.3 Submission and instant decision

On submit: the record becomes submitted, a confirmation email is queued, and evaluateAdmission runs. Within seconds the applicant is routed to a submission confirmation screen showing the outcome:

  • Eligible - provisionally accepted, with the acceptance-fee call to action and a downloadable provisional letter.
  • Not yet eligible - under review, with the explained missing list, the option to edit and resubmit for re-evaluation, and programme recommendations they do qualify for.

5.4 Application retrieval (no password)

The access screen accepts an email address (optionally with an emailed OTP) and lists matching applications with status; selecting one opens the applicant dashboard deep link.

5.5 Applicant dashboard

A three-column responsive dashboard (single column on mobile, with horizontal overflow contained) containing:

  • Header with edit and refresh actions (auto-refresh every 60 seconds, plus manual refresh) and a logout that returns to the access screen. Editing is blocked once the record is approved or matriculated.
  • Progress bar - visual stage mapping of the status machine.
  • Conditional offer notice - shown when an admin override granted a conditional admission: the outstanding items, the deadline, and a cleared state once conditions are met.
  • Update-your-application banner - shown for under_review and rejected, with encouraging copy ("does not currently meet the admission requirements ... you can update your information or select a different program, then resubmit") and a direct edit link.
  • JAMB change-of-institution banner when applicable.
  • Acceptance fee workflow when provisionally_accepted (see section 8).
  • Congratulations panel for approved / matriculated.
  • Left column: application overview (reference, programme, track, credits, status) and quick actions.
  • Middle column: status timeline, next steps (status-derived checklist), recent activity.
  • Right column: documents list with inline upload/replace, outstanding document requests, and the messaging thread with the admissions office.
  • Help panel with the university's email, phone and WhatsApp.

5.6 Post-admission

  • Account setup - an admin can send an account-setup invitation so the applicant becomes an authenticated user.
  • Student portal - unlocked when student_portal_activated is true: enrollment document uploads, fee payment, and course materials.

6. The Postgraduate Applicant Journey

A parallel wizard with PG-specific steps and its own dashboard:

  1. Personal details - including is_international and country of residence, which switch fee currency and payment rails.
  2. Programme choice - MBA / MIT / MPA from active PostgraduateProgram records, entry term, study mode, campus, specialization from the programme's list, and doctoral intent.
  3. Academic history - repeatable qualification rows (institution, country, qualification type, field, class of degree, year), NYSC status, language of instruction.
  4. Documents - degree certificate, transcript, O-Level result, NYSC certificate, CV, passport photograph, valid ID, English proficiency, optional GRE/GMAT; a "recommended documents" helper explains what strengthens an application.
  5. Referees - academic and professional referees with contact details and optional uploaded letters.
  6. Statement of purpose - typed with live word count, or uploaded as a document.
  7. Review - full read-back with declarations: information confirmed, attestation of genuineness and commitment to credential verification, fee acknowledgement.
  8. Payment - application fee by Paystack (NGN), PayPal/Flywire (USD) or bank transfer with proof upload; a global waiver switch (application_fee_waived + session label) can zero the fee for a promotional session.
  9. Confirmation - reference number, decision summary, next steps.

current_step is persisted so a returning applicant resumes exactly where they stopped.

The PG dashboard mirrors the UG one: summary, progress bar, overview, timeline, next steps, recent activity, document panel with verification state, class-document uploads for enrolled students, quick actions, messaging, and the provisional/official letter downloads.


7. Status Machines

7.1 Undergraduate

draft
  -> submitted                (applicant submits)
  -> provisionally_accepted   (engine: eligible, or admin override)
  -> under_review             (engine: not eligible, or incomplete academics)
  -> document_verification    (admin moves record into credential checking)
  -> interview_scheduled -> interview_completed   (optional programme-specific stage)
  -> approved                 (admission confirmed)
  -> matriculated             (enrollment complete - gated, see 7.3)
  -> rejected                 (displayed to applicants as "Does Not Meet Requirements")

7.2 Postgraduate

draft -> submitted -> under_review
      -> provisionally_accepted | conditional_offer | admitted | not_admitted
      -> document_verification
      -> enrolled_pending_registration
      -> matriculated

7.3 Matriculation gate (hard business rule)

A record may only become matriculated when all of the following hold:

  1. Admin document verification is certified (documents_verified_by_admin true, with documents_verified_at recorded).
  2. Acceptance fee payment is verified.
  3. If a conditional admission override is active with admission_type: "Conditional", its conditions_cleared flag must be true.

Violations are surfaced as explicit blocking messages naming the missing precondition. Note: "Highest Academic Credential" is deliberately a recommended, not required, field for both application and matriculation checks.

7.4 Audit

Every transition writes a StatusChangeLog row with old status, new status, actor identity, reason, and the source screen (detail page, list page, kanban board, bulk action, or system). An admin log viewer lists and filters this history.


8. Fees and Payments

8.1 Undergraduate acceptance fee workflow

Displayed on the applicant dashboard while provisionally_accepted:

  1. Show the fee - Naira for Nigerian applicants, USD for international - taken from the governing AdmissionRequirement (acceptance_fee_nigeria / acceptance_fee_international) with a safe default fallback.
  2. Offer payment routes: Paystack link (NGN), PayPal (USD), or bank transfer.
  3. Applicant uploads proof and enters a reference; the record moves to acceptance_payment_status: pending_verification.
  4. An admin verifies or rejects. On verification: acceptance_fee_paid true, acceptance_fee_paid_date set, student_portal_activated true, and the student portal unlocks.

8.2 Tuition and scholarship logic (encoded in the letters)

  • Programmes are grouped into a technology college (cybersecurity, data science, software engineering, information technology) and a business college (everything else).
  • Regular annual tuition: technology NGN 2,100,000; business NGN 1,800,000; international USD 1,500.
  • Merit scholarship by pathway: Start and Accelerate up to 70%; Advance up to 50%. Resulting net tuition: technology 630,000 (Start/Accelerate) or 1,050,000 (Advance); business 540,000 or 900,000. International applicants pay the USD rate without the scholarship schedule.
  • The acceptance fee is deducted from tuition, and the letter prints Regular Tuition, Scholarship (negative), Tuition After Scholarship, Acceptance Fee (negative) and Balance Due.
  • Official tuition payment links are centralised in a single module so a change propagates to every UG and PG letter.

8.3 Postgraduate fees

Application fee and acceptance fee come from the programme record, falling back to global PostgraduateSettings, in NGN or USD by is_international. Rails: Paystack, PayPal, Flywire, bank transfer (bank name, account name, account number, routing/SWIFT all configurable). A session-scoped waiver can set the fee to zero.


9. Documents, Verification and AI Review

9.1 Upload handling

Every upload field: file picker, in-flight progress, success/replace state, and storage of the returned URL on the record. Private/sensitive artefacts use signed URLs with short expiry.

9.2 AI document verification

For each submitted document, the platform runs an AI verification pass (document read plus structured extraction) and stores the outcome in document_verification, surfaced to admins as a per-document panel with an accept/reject action. The applicant sees only a simple verified/pending state.

9.3 AI application review

An AI review pass produces ai_review_flags - severity-tagged findings such as inconsistent dates, name mismatches between documents and the form, implausible grades, or duplicate submissions. Admins see these in an AI review panel; they are advisory and never auto-reject.

9.4 Document requests

An admin can raise a DocumentRequest against an application with a name and instructions. It appears on the applicant dashboard as an outstanding item; the applicant uploads against it; the admin approves or rejects.


10. Admin Platform

10.1 Roles and permissions

Permissions are derived from admin_role (plus any custom permissions array on the user):

RolePermissions
Admissions officerview_applications, edit_applications, change_status, view_all_data, add_notes, request_documents, view_reports, send_emails, bulk_actions, view_analytics
Department headall of the above plus approve_decisions
System administrator / adminall of the above plus delete_applications, manage_campaigns, manage_users, manage_reminders

Enforcement pattern: a usePermissions hook exposes hasPermission, hasAnyPermission, hasAllPermissions and a display role name; a PermissionGate component wraps any action or panel and renders a fallback when access is absent. A role badge shows the current actor's role. Replication note: client gating is for usability - the authoritative enforcement must be row-level security and server-side checks.

10.2 Undergraduate applications dashboard

  • Summary statistics (totals per status, conversion rate) and analytics charts (volume over time, status distribution, programme mix, track mix).
  • Admin action alerts - a collapsible, severity-grouped panel of items needing follow-up (unhandled advisor requests, payments pending verification, documents awaiting verification, records stuck in review, unconditional-but-unmatriculated records). Each category expands to the specific records and links to the detail page or filters the list. The component is reusable across UG and PG dashboards via optional props.
  • Filters: free-text search (name, email, reference), status, programme, track, date; sortable, paginated table.
  • Two view modes: table and kanban board with drag-and-drop status changes (each drop writes a StatusChangeLog row with source kanban_board).
  • Bulk actions: multi-select rows, then bulk status change (single batched update rather than sequential writes) or bulk email.
  • Exports (CSV):
    • Full application export with all mapped columns.
    • Export by date - a reusable date-range dialog with presets (last 7/30/90 days, this year, custom), an optional status filter, server pagination through the records and client-side date filtering for accuracy, streamed to a CSV download.
    • JAMB score export - reference, name, contact, JAMB registration, score, year.
    • Conditional admissions export - every override with admission type, basis, waived requirements, justification, deadline, cleared state, deciding officer and timestamp.

10.3 Application detail page (undergraduate)

A multi-column workspace:

  • Applicant profile, contact, and programme summary.
  • Academic credentials card rendering the track-appropriate credentials, including the full O-Level grid.
  • System review card - the engine's verdict: eligible/not, every reason, the missing list, evaluated timestamp, the requirement record applied, programme recommendations, a re-evaluate button, plus the conditional-admission summary and override action (section 11).
  • Credentials verification card and AI-powered document verification panel.
  • AI review panel (flags with severity).
  • Admin notes panel (append-only, attributed, timestamped).
  • Messaging panel (two-way thread with the applicant).
  • Acceptance payment verification (approve/reject proof).
  • Admission letter upload (attach an official signed letter) and letter generation buttons.
  • Status control with reason capture, the matriculation gate, re-evaluation, deletion (permission-gated), and account-setup invitation email.
  • Edit dialog for administrative corrections to the application data.

10.4 Postgraduate admin dashboard and detail

Feature parity with UG: statistics, action alerts, filters, pagination, sortable table, PG status badges, bulk email, date-range export, and a programme admission tracking panel breaking applicants down by discipline (MBA, MIT, MPA). The PG detail view adds referee review, statement-of-purpose review, PG document verification, acceptance payment verification, PG messaging, and the PG system review card.

10.5 Other admin screens

  • Admission requirements manager - CRUD over the rules table per programme and track, including fees; this is how a university tunes the engine.
  • Referral partners - CRUD over agents/affiliates/partners and reporting of applications by referral code.
  • Email campaigns - template management (subject, body, category) and campaign sends to filtered audiences.
  • Automated reminders - schedule configuration (days after creation, reminder type, target status, enabled flag), reminder templates, bulk manual sends, and per-application reminder history.
  • Email monitor - the EmailLog with delivery status, retry counts and error messages.
  • Messaging centre - all applicant threads in one place with quick templates.
  • Analytics - funnel and volume reporting.
  • User management - invite staff by email with a role, change roles, and activate/deactivate accounts.
  • Status change log viewer - full audit trail.

11. Conditional Admission and Administrative Override

This is the discretionary layer that lets human judgement outrank the engine without breaking the audit trail.

Availability. The override action appears on the system review card only when the record actually needs discretion - the engine returned not-eligible, or the applicant requested an advisor meeting - and only for actors holding change_status or approve_decisions.

The decision dialog captures:

  1. Admission type - Conditional (applicant still owes items) or Full (no outstanding conditions).
  2. Basis - requirement waiver (discretionary) or advisor recommendation.
  3. Requirements being waived - checkboxes generated from the engine's own missing list, so the waiver refers to the exact machine-stated requirement.
  4. Condition deadline (Conditional only).
  5. Justification - mandatory free text.

On apply: status becomes provisionally_accepted; conditional_admission is written with active true, the selections, the deciding officer's name and email, and a timestamp; conditions_cleared is preset true for a Full override and false for a Conditional one. A StatusChangeLog row records the transition with a reason string naming the basis and justification.

Engine interaction. evaluateAdmission reads the override first. When active, it still recomputes and stores the decision (so the findings stay current) but never changes the status, and sets decision_result.override_mismatch when the record still fails. The admin UI shows a warning strip for a mismatch.

Clearing conditions. The conditional-admission summary on the detail page shows the type, basis, deciding officer, date, waived items, justification, deadline, and a "Mark Conditions as Met" action recording conditions_cleared, conditions_cleared_at and conditions_cleared_by. Until then, matriculation is blocked with an explicit message.

Applicant-facing. A conditional offer notice on the dashboard states that the place is confirmed once the listed items are received and verified, lists the items, states the deadline, and switches to a cleared confirmation once satisfied. The provisional letter prints "Provisionally Accepted (Conditional)" and adds a numbered condition listing the outstanding items and the deadline.


12. Admission Letters (PDF generation)

Letters are generated client-side into A4 PDFs with the university's letterhead: coloured spine bars, seal/logo image, watermark circle, and a footer with the postal address, email and phone. All branding constants - address, email, phone, registrar signature image - live in a single branding module, and all UG and PG provisional and official letters consume it, so a signature or address change is one edit.

Provisional offer of acceptance (UG) contains: centred title, reference line AGL/ADM/<year>/<application_id> and date; salutation; the offer paragraph naming the programme and academic session; a subject-to-conditions paragraph; an Acceptance Details block (application ID, applicant name, programme, track, transfer credits granted, credits to complete out of 120, admission status); a Conditions of Acceptance block (provisional pending credential verification, acceptance fee required, originals required on portal activation, offer withdrawn for false information, plus the extra conditional-override clause when applicable); a Tuition and Fees block with the scholarship maths and balance due; the payment link; a note that the student portal activates on payment; the closing, registrar signature image, name and title.

Official admission letter (UG) and PG provisional / official letters follow the same structure with programme-appropriate fee tables and wording. Currency symbols are driven by the applicant's nationality/international flag.


13. Communications

Channels. Transactional email through the platform's email integration, in-app messaging threads, and admin-composed bulk email.

Email types and triggers.

TypeTrigger
submission_confirmationApplication submitted
status_changeAny admin status transition
incomplete_reminderReminder schedule matches a draft/stalled record
otp_verificationApplicant requests retrieval access
welcome / account setupAdmin invites the applicant to create an account
campaignManual campaign send

Templating. Status-keyed message templates with placeholder substitution (applicant first name, full name, application reference, programme, track, status, deadline, payment link). A bulk email dialog lets an admin pick recipients from a selection, choose or edit a status-appropriate template, preview a personalised sample, send in batches with a live progress indicator, and review per-recipient results. Invalid or missing email addresses are skipped and reported.

Delivery service. A central send helper writes an EmailLog row for every attempt with status, retry count and error, so failures are visible in the email monitor and can be retried. PG applicants must be routed to the PG status/login surface in automated emails (a UG-specific link is a defect).

Automated reminders. Configurable schedules (e.g. 3-day, 7-day, 14-day after creation, targeting drafts) select matching applications, send the matching reminder template, append to reminders_sent, and update last_reminder_sent so a reminder is never duplicated.


14. Reference Data Sets

Replication requires these curated datasets, because free text destroys the engine's ability to match requirements:

  • O-Level subjects - grouped dropdown (sciences, arts, commercial, technical, languages) using the exact strings the requirement records reference.
  • O-Level grades - the full A1-F9 ladder with credit threshold logic.
  • Nigerian institutions - degree-awarding institutions and ND/NCE institutions as separate grouped, searchable selectors.
  • States and cities - Nigerian states plus international fallbacks.
  • Professional bodies - ICAN, CITN, CIBN, CIPM and equivalents.
  • Programme catalogue - UG programmes with their college grouping; PG programmes with specializations.
  • Campuses, entry terms, study modes - configurable lists.

15. UX and Content Standards (mandatory in replication)

  • American English spelling throughout ("Program", not "Programme", in user-facing copy).
  • No em-dashes in UI copy; use standard punctuation.
  • Soft language for negative outcomes - never "Rejected" or "Not Admitted" to an applicant; use "Does Not Meet Requirements", always paired with what to change and which programmes they do qualify for.
  • Mobile-first responsive layouts - dashboards collapse from three columns to one, tables scroll horizontally inside contained wrappers, action bars wrap, and no layout produces horizontal page overflow.
  • Loading and empty states everywhere - spinners for in-flight integration calls, retry-with-backoff on dashboard loads (up to two retries, two seconds apart), explicit "not found" screens with a route back to retrieval.
  • Every action confirms - toasts for success, inline errors for failure, disabled buttons while in flight.
  • Deep-linkable - every applicant surface can be reached by an emailed URL.

16. Security and Integrity Checklist

Any replication must satisfy all of these:

  1. Applicant-facing writes go only through server functions with field whitelisting - never accept client-supplied status, decision_result, conditional_admission, credits_transfer or payment fields.
  2. Application lookup by email is OTP-verified and rate-limited to prevent enumeration.
  3. Admin pages are protected both by route guards and by row-level security on every administrative entity.
  4. Human-readable references use a collision-resistant generator (cryptographic randomness plus a uniqueness check), not a weak random.
  5. File uploads enforce type and size limits; sensitive documents use signed, expiring URLs.
  6. Bulk operations use batched writes with loading state and error surfacing; no unbounded sequential loops.
  7. Admin stat and export queries must paginate through the full set, never silently truncate at a page cap.
  8. The decision engine is idempotent and override-aware; overrides are attributed, justified and auditable.
  9. Every status change is logged with actor and origin; logs are admin-read-only.
  10. The matriculation gate cannot be bypassed from any surface (detail page, list page, kanban, bulk action).

17. Recommended Build Order

  1. Entities and row-level security (Application, AdmissionRequirement, supporting entities).
  2. Reference datasets and the requirements admin screen (the engine is useless without configurable rules).
  3. Server functions: saveApplication, getApplicationById, getApplicationsByEmail, generateOtp.
  4. The UG wizard with autosave, draft sync and resume.
  5. evaluateAdmission plus the submission confirmation screen.
  6. Applicant dashboard, documents, messaging, document requests.
  7. Admin list, detail, status machine and StatusChangeLog.
  8. Acceptance fee workflow, payment verification, student portal activation.
  9. Letters and the centralised branding module.
  10. Email delivery service, templates, campaigns, automated reminders, email monitor.
  11. AI review and document verification.
  12. Conditional admission override, matriculation gate, conditional exports.
  13. The PG entity set, wizard, engine, dashboard and admin parity.
  14. Analytics, exports, action alerts, roles and user management.

18. Glossary

  • Track / Pathway - the entry route determined by the applicant's highest prior credential (Start, Accelerate, Advance, Postgraduate).
  • Provisional acceptance - an offer granted before credential verification and payment.
  • Conditional admission - an admin-granted offer with named outstanding requirements and a deadline.
  • Matriculation - final enrollment, gated on verification, payment and cleared conditions.
  • Requirement record - the configurable rule row (programme + track) the engine applies.
  • Override mismatch - a re-evaluation that still fails on a record already admitted by discretion.
  • Action alert - an aggregated administrative to-do derived from record state.