SPMB Tests · CBT · Ranking · Penerimaan · Pengumuman — Audit & Gap Analysis
Status: Audit dokumen (read-only, no code changes). Sumber: source code FE scola-fe-v2 + BE scola-odoo-module (tag/branch develop per Apr 2026), Permendikdasmen No. 3 Tahun 2025, dan Surat Edaran Dirjen PAUD Dikdasmen No. 0301/C/HK.04.01/2026.
Pendamping: Implementation plan di docs/implementation/spmb-tests-cbt-ranking-plan.md. Audit lama spmb-flow-audit.md (wizard/upload) tetap berlaku — dokumen ini melengkapi.
Lingkup: 5 domain — Tes Masuk, CBT, Penilaian/Ranking, Penerimaan/Daftar Ulang, Pengumuman. Lintas-repo (FE + BE).
1. Latar & Scope
1.1 Mengapa audit ini ada
Audit spmb-flow-audit.md (Q1 2026) fokus pada wizard registrasi & upload dokumen. Bagian downstream — tes masuk, eksekusi CBT, skoring, ranking, penerimaan, pengumuman — belum punya audit terkonsolidasi. Beberapa indikasi gap muncul saat refactor menu v2 dan smoke test admin SPMB:
- SPMBCBTRunner route tidak ada → klik "Mulai CBT" crash.
- /spmb/dashboard di-redirect dari SPMBDaftarUlang.vue setelah enrollment confirm → 404.
- Tidak ada UI proctor / pewawancara / grader esai untuk SPMB.
- FE pendaftar tampilkan tab "Tes Masuk" walau register tidak punya jadwal (variant tanpa tes).
1.2 Ruang lingkup audit
| Domain |
FE |
BE |
Endpoint |
| Tes Masuk (jadwal & kehadiran) |
Public/SPMBTestSchedule.vue, Public/SPMBAdmissionDetail.vue |
spmb_api.py::get_my_test_schedules; scola_admission/models/admission_test.py (test_type, schedule, slot, result); overlay scola_admission_assessment |
/api/SPMB/my/test-schedules, /api/SPMB/test-schedules* (admin) |
| CBT (start & runner) |
Public/SPMBCBTStart.vue, hilang SPMBCBTRunner.vue |
scola_cbt/models/{exam,attempt,participant,question}.py + scola_admission_assessment::cbt_participant.py |
belum ada endpoint pendaftar untuk launch/submit |
| Penilaian (rapor + achievement + tes) |
Public/SPMBAdmissionDetail.vue, services/spmb/spmb.service.js (saveRaporGrades, getMyTestResults) |
spmb_api.py::get_my_test_results, admission.py::_compute_total_test_score, _compute_ranking_score |
/api/SPMB/my/test-results |
| Ranking |
AdmissionApplicationList.vue, RankingList.vue (admin) |
spmb_complaints_ranking_api.py::ranking_list, ranking_update_status; admission.py::action_calculate_ranks |
/api/SPMB/ranking, /api/SPMB/ranking/update-status |
| Penerimaan / Daftar Ulang |
Public/SPMBDaftarUlang.vue, services/spmb/spmbEnrollment.service.js |
spmb_api.py::confirm_enrollment, get_admission_invoice, create_admission_invoice |
/api/SPMB/my/admission/confirm-enrollment, /api/SPMB/my/admission/invoice* |
| Pengumuman |
components/spmb/SPMBAnnouncementBanner.vue, Public/SPMBStatusCheck.vue |
spmb_api.py::get_selection_result, get_public_status |
/api/SPMB/selection/result, /api/SPMB/public/status |
2. Inventaris
2.1 FE Vue Components / Routes (pendaftar portal)
| File |
Role |
Route |
Catatan |
src/views/AdmissionManagement/Public/SPMBAdmissionDetail.vue |
pendaftar |
/spmb/admission/:id |
Hub utama: mengandung SPMBAnnouncementBanner, jadwal tes, dokumen, status |
src/views/AdmissionManagement/Public/SPMBTestSchedule.vue |
pendaftar |
/spmb/admission/:id/test-schedule |
Listing jadwal tes; tombol "Mulai CBT" → SPMBCBTRunner (route tidak ada) |
src/views/AdmissionManagement/Public/SPMBCBTStart.vue |
pendaftar |
belum terdaftar |
Orphan; router.push('/spmb/dashboard') ke route mati |
src/views/AdmissionManagement/Public/SPMBDaftarUlang.vue |
pendaftar |
/spmb/admission/:id/enrollment |
Konfirmasi enrollment → redirect /spmb/dashboard (mati) |
src/views/AdmissionManagement/Public/SPMBStatusCheck.vue |
publik (no auth) |
/spmb/status-check |
Cek status by application number |
src/components/spmb/SPMBAnnouncementBanner.vue |
shared |
embed |
Banner accepted/rejected/pending + jadwal tes |
src/components/spmb/SPMBNotificationBell.vue |
shared |
embed |
Listing notifikasi portal |
src/components/spmb/SPMBCountdownTimer.vue |
shared |
embed |
Countdown enrollment deadline |
2.2 FE Services
| File |
Methods relevan |
src/services/spmb/spmb.service.js |
getAdmissionDetail, submitAdmission, confirmEnrollment, getMyTestSchedules, getMyTestResults, getSelectionResult, saveRaporGrades |
src/services/spmb/spmbEnrollment.service.js |
getSpmbEnrollmentInvoice, createSpmbEnrollmentInvoice |
src/services/spmb/spmbPublicStatus.service.js |
checkPublicStatus (sudah ada vitest contract) |
2.3 BE Models utama
| Model |
File |
Purpose |
op.admission |
openeducat_admission + scola_admission/models/admission.py |
Record pendaftaran utama; punya state, ranking_score, rank_in_pathway, total_test_score |
op.admission.register |
openeducat_admission |
Periode SPMB (gelombang); punya pathway_quota, registration_fee |
op.admission.pathway |
scola_admission |
Jalur (domisili/afirmasi/prestasi/mutasi); kode pathway dipakai di _compute_ranking_score |
scola.admission.test.type |
scola_admission/models/admission_test.py |
Jenis tes (kode, durasi, max_score, weight, is_required) |
scola.admission.test.schedule |
scola_admission + overlay scola_admission_assessment |
Jadwal tes; overlay menambah cbt_exam_id, cbt_participant_count, cbt_last_synced_at |
scola.admission.test.slot |
scola_admission + overlay |
Slot peserta per jadwal; punya attendance_status, attendance_time, score; overlay menambah cbt_participant_id, cbt_last_attempt_id |
scola.admission.test.result |
scola_admission |
Summary skor per admission × test_type; punya weighted_score (computed) |
op.exam (CBT) |
scola_cbt/models/exam.py |
Exam header; punya exam_context (learning/admission/independent), is_cbt |
scola.cbt.participant |
scola_cbt/models/participant.py |
Peserta CBT; bisa identity_type=admission dengan FK admission_id |
scola.cbt.attempt |
scola_cbt/models/attempt.py |
Attempt (jawaban + skor); state submitted/graded |
2.4 BE Endpoints (controller)
| Endpoint |
Auth |
File |
/api/SPMB/my/test-schedules |
user (pendaftar) |
spmb_api.py::get_my_test_schedules |
/api/SPMB/my/test-results |
user |
spmb_api.py::get_my_test_results |
/api/SPMB/my/admission/confirm-enrollment |
user |
spmb_api.py::confirm_enrollment |
/api/SPMB/my/admission/invoice |
user |
spmb_api.py::get_admission_invoice |
/api/SPMB/my/admission/invoice/create |
user |
spmb_api.py::create_admission_invoice |
/api/SPMB/selection/result |
user |
spmb_api.py::get_selection_result |
/api/SPMB/public/status |
public |
spmb_api.py::get_public_status |
/api/SPMB/test-schedules* (overloaded) |
user (admin) |
spmb_complaints_ranking_api.py::test_schedule_* (overlay overrides type='json') |
/api/SPMB/ranking, /api/SPMB/ranking/update-status |
user (admin) |
spmb_complaints_ranking_api.py |
/api/SPMB/complaints/* |
user |
spmb_complaints_ranking_api.py |
3. Data Flow Diagram (tekstual)
┌──────────────────────────────────────────────────────┐
│ ADMIN SPMB SETUP │
│ │
│ op.admission.register ──┬── pathway_quota │
│ └── registration_fee │
│ scola.admission.test.type ─── (CBT|Tulis|Wawancara) │
│ op.exam (is_cbt, exam_context='admission') │
│ scola.admission.test.schedule ─── cbt_exam_id? │
└────────────┬─────────────────────────────────────────┘
│
▼
PENDAFTAR ── register ──► op.admission (draft)
│ │
│ submit form │ upload doc + rapor + achievement
▼ ▼
(state=submit)
│
│ admin verify + invoice biaya pendaftaran (opsional)
▼
(state=confirm)
│
│ admin assign slot per schedule (auto-sync ke scola.cbt.participant kalau CBT)
▼
scola.admission.test.slot ─────► scola.cbt.participant (kalau V1)
│ │
│ HARI-H tes │
│ V1 (CBT): pendaftar attempt │
│ V2 (tulis): hadir + jawab kertas │
│ V3 (wawancara): rubrik │
│ ▼
│ scola.cbt.attempt (state=submitted)
│ │
│ admin/sistem score+attendance ─────┘
▼
scola.admission.test.slot.score
│ rollup
▼
scola.admission.test.result.weighted_score
│ rollup
▼
op.admission.total_test_score
│ + rapor_average + total_achievement_score + distance_to_school
▼
op.admission.ranking_score (compute per pathway formula)
│ admin: action_calculate_ranks
▼
op.admission.rank_in_pathway
│ admin set hasil per kandidat
▼
(state=admission|reject|pending)
│ scheduled release saat announcement_at (gap)
│ notif portal+email
▼
PENDAFTAR lihat banner pengumuman
│ kalau diterima:
▼
stage daftar ulang (dok + invoice + confirm)
▼
(state=done) ───► confirm_enrollment ───► op.student
4. Variasi Metode Seleksi (Selection Variants)
Tes masuk TIDAK WAJIB. Sistem mendukung kombinasi berikut, ditentukan implisit dari setup data:
| Variant |
Metode |
Komponen Skor |
Stage Tes (8) |
Stage Skoring (9) |
| V1 |
Full CBT online |
total_test_score (weighted) |
Pendaftar via runner CBT |
Auto via _sync_from_cbt_attempts |
| V2 |
Tes tulis manual (PBT) |
total_test_score (weighted) |
Hadir lokasi, jawab kertas, panitia koreksi |
Admin input slot.score manual |
| V3 |
Wawancara |
total_test_score dengan test_type ber-rubrik wawancara |
Hadir slot, pewawancara nilai |
Pewawancara input score manual |
| V4 |
Hybrid (CBT + wawancara, tulis + wawancara, dll) |
Sum weighted_score semua test_type |
Pendaftar ikuti semua jadwal |
Auto (CBT) + manual |
| V5 |
Tanpa tes — administrative only |
total_test_score=0, sisanya rapor + achievement + jarak (sesuai pathway formula) |
DILEWATI |
Auto via _compute_ranking_score |
| V6 |
Portfolio / berkas |
total_achievement_score + verifikasi manual |
DILEWATI |
Admin proxy via test_result atau adjust achievement |
Pemilihan variant saat ini implisit dari:
- Ada/tidaknya scola.admission.test.schedule per register × pathway (kosong → V5/V6)
- cbt_exam_id di-set atau null (kosong → V2/V3/V4 manual)
- pathway.code di _compute_ranking_score (domisili/afirmasi/prestasi/mutasi punya formula khusus; "else" hanya pakai tes)
5. Role Mapping (BE-authoritative + FE Scola UX)
SSOT: BE Odoo groups (authoritative) + mapping FE Scola role untuk navigasi/UX.
5.1 Pembuat soal CBT (Question Bank)
| Aktivitas |
BE group |
FE Scola role |
Bukti |
| Buat bank soal & choice |
scola_cbt.group_cbt_exam_creator (own) + group_cbt_manager (semua) |
teacher, homeroom, admin, head_admin (capability academics.question_bank.manage) |
scola_cbt/security/cbt_security.xml:13-19; FE teacherPortalApp.js "Bank Soal" |
| Buat blueprint / question_set |
group_cbt_exam_creator + group_cbt_manager |
sama |
cbt_security.xml:14-19 |
Catatan: untuk konteks admission (exam_context='admission'), question bank tetap dibuat oleh CBT Exam Creator. Belum ada role khusus "SPMB Question Author" — risiko: guru biasa bisa lihat/buat soal tes masuk. SOP belum dokumentasikan.
5.2 Pembuat jadwal tes SPMB
| Aktivitas |
BE group |
FE Scola role |
Buat scola.admission.test.schedule |
openeducat_admission.group_op_admission_admin (di-bridge dari group_scola_admin, group_scola_admin_staff, group_scola_head_admin) |
admin, admin_staff, head_admin (capability admissions.schedule.view/manage) |
Buat scola.admission.test.type |
sama |
sama |
Sumber bridge: scola_admission/security/scola_admission_security.xml:11-21. Tidak ada role granular "Panitia SPMB" — semua admin staff sama level.
5.3 Pengisi kehadiran peserta tes
| Aktivitas |
BE group |
FE Scola role |
Bukti |
action_mark_present / action_mark_absent slot |
group_op_admission_admin |
admin, admin_staff, head_admin |
scola_admission/models/admission_test.py:213-220 |
| Sync attendance dari CBT attempt |
sistem (sudo) |
sistem |
scola_admission_assessment/models/admission_test.py:269 |
Gap: tidak ada role "Pengawas/Proctor SPMB" terpisah. CBT punya group_cbt_proctor tapi tidak diaktifkan untuk konteks admission. UI live monitor sesi belum ada di FE.
5.4 Penghubung soal CBT ↔ jadwal tes masuk
| Aktivitas |
BE group |
FE Scola role |
Set cbt_exam_id di schedule |
group_op_admission_admin |
admin, admin_staff, head_admin |
Sync slot → scola.cbt.participant (auto on create/write) |
sistem |
sistem |
| Sync hasil CBT → score slot (manual / cron) |
group_op_admission_admin |
sama |
Gap critical: pembuatan op.exam ber-exam_context='admission' butuh group_cbt_exam_creator ATAU group_cbt_manager. Admin SPMB tidak otomatis punya CBT Exam Creator (tidak ada bridge XML). Constraint: cbt_security.xml belum bridge ke group_scola_admin_staff/head_admin.
5.5 Pendaftar mengerjakan CBT
| Aktivitas |
BE group |
FE Scola role |
| Login portal SPMB |
base.group_portal + role custom |
pendaftar |
Mulai exam (scola.cbt.attempt) |
record rule via participant.user_id |
pendaftar |
Gap: FE runner CBT pendaftar belum ada (lihat F-001 di gap matrix).
5.6 Penilai esai (manual scoring)
| Aktivitas |
BE group |
FE Scola role |
| Grade essay/manual question |
group_cbt_grader |
belum di-bridge ke role Scola apapun |
Gap: untuk SPMB, tidak jelas siapa yang grade esai. UI grading di FE Scola belum ada.
5.7 Audit / read-only
| Aktivitas |
BE group |
FE Scola role |
| Lihat audit log CBT |
group_cbt_auditor, group_cbt_manager |
belum di-bridge |
| Lihat ranking & seleksi (read) |
group_op_admission_user (di-bridge ke group_scola_principal) |
principal, plus admin |
5.8 Aktor E2E SPMB
| Aktor |
Role Scola |
BE group |
Tanggung Jawab |
| Calon siswa / orang tua |
pendaftar |
base.group_portal + portal pendaftar |
Daftar akun, isi formulir, upload dok, kerja CBT, daftar ulang |
| Admin SPMB / Panitia |
admin_staff, head_admin |
group_op_admission_admin (bridged) |
Buka register, buat jadwal tes, verifikasi dok, isi kehadiran, hitung ranking, umumkan |
| Pembuat soal CBT |
teacher / admin_staff |
group_cbt_exam_creator (need bridge) |
Tulis question bank, blueprint, link ke exam |
| Pengawas / Proctor |
belum ada role spesifik |
group_cbt_proctor (belum aktif untuk SPMB) |
Monitor sesi CBT, force submit, perpanjang waktu |
| Pewawancara |
belum ada role spesifik |
belum ada |
Wawancara V3 |
| Grader esai |
belum ada role spesifik |
group_cbt_grader (belum aktif untuk SPMB) |
Nilai jawaban esai manual |
| Treasurer / Keuangan |
treasurer, vice_principal_finance |
scola_finance + accounting |
Validasi pembayaran biaya pendaftaran & daftar ulang |
| Kepala Sekolah |
principal |
group_op_admission_user (read) |
Approve hasil seleksi |
| Foundation |
foundation_chairman |
group_op_admission_user (read) |
Oversight |
| Sistem / Cron |
system |
sudo |
Kirim notif, sync CBT result, lock/unlock pengumuman |
6. E2E Workflow (14 Stage, dengan branching variant)
| # |
Stage |
Aktor primer |
Aksi |
Endpoint / Komponen |
State op.admission |
| 1 |
Setup periode |
Admin SPMB |
Buat op.admission.register + pathway_quota + registration_fee + (gap) announcement_at |
/admin/spmb/periode |
n/a |
| 2 |
Setup metode seleksi (opsional, tergantung variant) |
Admin SPMB + Exam Creator |
V1: buat test_type + CBT exam + schedule + link cbt_exam_id. V2: test_type tulis + schedule (no CBT). V3: test_type wawancara + schedule (no CBT). V4: kombinasi. V5/V6: skip. |
/admin/spmb/test, /faculty/question-bank |
n/a |
| 3 |
Pendaftar register akun |
Calon siswa |
Form register → OTP email |
/api/SPMB/account/register, verify-email |
n/a |
| 4 |
Buat admission |
Pendaftar |
Login → pilih register & pathway → submit form data pribadi |
/api/SPMB/my/admission/create |
draft |
| 5 |
Lengkapi & submit |
Pendaftar |
Upload dokumen, isi rapor, achievement → submit |
/api/SPMB/my/admission/submit |
draft → submit |
| 6 |
Verifikasi & invoice biaya pendaftaran (opsional, gap A17) |
Admin SPMB + Treasurer |
Admin verifikasi dok, generate invoice (jika is_paid_admission); pendaftar bayar |
confirm_in_progress, /api/SPMB/my/admission/invoice |
submit → confirm |
| 7 |
Assign jadwal tes (skip jika V5/V6) |
Admin SPMB |
Buat slot. V1: auto sync slot → cbt.participant. V2-V4 manual: cukup slot. |
admin Test Schedule UI |
confirm |
| 8 |
Hari-H tes (skip jika V5/V6) |
Pendaftar + Proctor/Pewawancara |
V1: runner CBT (gap). V2: tandai kehadiran + jawab tulis. V3: rubrik wawancara (gap UI). V4: kombinasi. |
gap Phase 2 |
confirm |
| 9 |
Skoring & ranking |
Sistem + Admin SPMB |
V1: auto-sync. V2/V3: input manual (gap UI). V5/V6: skip skoring tes. _compute_ranking_score auto, admin klik "Hitung Ranking" → action_calculate_ranks. |
/api/SPMB/ranking |
confirm |
| 10 |
Approve & umumkan |
Principal + Admin SPMB |
Principal review, admin set hasil per admission, sistem cron release saat announcement_at (gap), notif portal+email. |
admission_confirm, confirm_rejected |
confirm → admission atau reject |
| 11 |
Daftar ulang & invoice |
Pendaftar + Treasurer |
Pendaftar lihat banner, sistem buat invoice, pendaftar bayar+upload dok+konfirmasi |
confirm-enrollment, invoice/create |
admission → done |
| 12 |
Konversi ke siswa |
Sistem |
confirm_enrollment membuat op.student, assign batch, generate NIS |
confirm_enrollment |
done |
| 13 |
(Opsional) Sanggah / banding |
Pendaftar + Admin SPMB |
Pendaftar buat complaint; admin proses (process → resolve/reject) |
/api/SPMB/complaints/* |
tidak berubah |
| 14 |
(Opsional) Reapply |
Pendaftar |
Ditolak → reapply ke register lain |
/api/SPMB/my/admission/reapply |
new admission draft |
Decision Gates
- Gate 1 (post-5): dokumen wajib lengkap → admin verify; bila gagal status balik
draft + alasan.
- Gate 2 (post-6): invoice biaya pendaftaran lunas (jika
is_paid_admission) → admin assign jadwal (V1-V4) atau langsung skoring (V5/V6).
- Gate 3 (post-8): kondisional per variant — V1-V4 kehadiran & skor terisi; V5/V6 rapor & achievement terverifikasi → ranking compute.
- Gate 4 (post-10): approve principal + tanggal pengumuman tercapai → state release.
- Gate 5 (post-11): dok daftar ulang lengkap + invoice lunas →
confirm_enrollment diizinkan.
Notifikasi (existing vs gap)
| Trigger |
Channel |
Status |
| Admission confirmed (post 6) |
Portal + email |
✅ ada (admission_confirmed) |
| Test schedule assigned (7) |
Portal |
✅ ada (admission_test_scheduled) |
| Result released (10) |
Portal + email |
⚠️ partial (admission_accepted ada tapi tanpa scheduled release) |
| Enrollment deadline reminder (11) |
Portal + email + WA |
❌ gap |
| Waitlist promoted |
Portal + email |
❌ gap |
7. Gap Matrix
Severity: Critical (broken/blocking) | High (kontrak FE↔BE timpang / regulasi) | Medium (UX/resilience) | Low (cleanliness)
7.1 FE/BE Functional Gaps
| ID |
Sev |
Domain |
Finding |
Bukti |
Owner |
| F-001 |
Critical |
CBT |
SPMBCBTRunner route name dirujuk dari SPMBTestSchedule.vue → router.push({ name: 'SPMBCBTRunner' }) tapi tidak terdaftar di src/router/spmbRoutes.js. Klik "Mulai CBT" → router warning + UI dead-end. |
SPMBTestSchedule.vue:74 |
FE |
| F-002 |
Critical |
Penerimaan |
/spmb/dashboard tidak terdaftar di router. Dirujuk dari SPMBCBTStart.vue:15 & SPMBDaftarUlang.vue:582 setelah confirmEnrollment sukses → 404. |
SPMBDaftarUlang.vue:582 |
FE |
| F-003 |
Critical |
CBT |
SPMBCBTStart.vue orphan: dipanggil dengan name: 'SPMBCBTStart' dari SPMBTestSchedule.vue:272 tapi router tidak punya entry untuk komponen ini. |
SPMBTestSchedule.vue:272 |
FE |
| F-004 |
Critical |
CBT |
Tidak ada FE runner CBT pendaftar + tidak ada BE endpoint launch/save-answer/submit untuk pendaftar. Kontrak cbt_launch.enabled ada di response BE tapi target endpoint untuk start session belum eksis. Best practice CBT (anti-cheat, auto-save, time sync, integrity token) belum diadopsi. |
spmb_complaints_ranking_api.py (admin only); search FE: tidak ada SPMBCBTRunner.vue |
FE+BE |
| F-005 |
High |
Tes Masuk |
schedule.attendance_status digunakan FE (SPMBTestSchedule.vue); _schedule_to_dict BE belum konfirmasi mengembalikan field ini untuk pendaftar (route get_my_test_schedules). Risk: undefined → label tampil mentah. |
SPMBTestSchedule.vue consumer |
BE |
| F-006 |
High |
Penilaian |
testResults.total_test_score & result.weighted_score dipakai FE; perlu sinkron dengan schema scola.admission.test.result. Bila tidak selalu disertakan, tabel tampil 0. |
getMyTestResults consumer |
BE |
| F-007 |
High |
CBT |
schedule.cbt_launch.return_to diasumsikan FE; perlu konfirmasi BE menyertakan saat schedule sync ke cbt_exam. |
launchCbt di FE |
BE |
| F-008 |
High |
Penilaian |
Komponen skor ranking tidak transparan ke pendaftar — ranking_score hanya angka final di Detail; tidak ada breakdown rapor/achievement/test. Tidak memenuhi prinsip transparansi Permendikdasmen. |
SPMBAdmissionDetail.vue |
FE+BE |
| F-009 |
High |
Pengumuman |
Pengumuman hasil tidak punya scheduled release. State berubah segera setelah admin update; tidak ada announcement_at / locking di BE. Tidak ada countdown pre-announcement di FE. |
admission.py (no announcement_at field) |
FE+BE |
| F-010 |
Medium |
Pengumuman |
SPMBAnnouncementBanner tidak menampilkan komponen waitlist promotion / refund flow. |
SPMBAnnouncementBanner.vue |
FE |
| F-011 |
Medium |
Penerimaan |
confirmEnrollment redirect ke route mati (/spmb/dashboard); FE belum punya success destination yang tahan banting. |
SPMBDaftarUlang.vue:582 |
FE |
| F-012 |
Medium |
Pengumuman |
Tidak ada notifikasi push/email saat ranking dirilis (BE punya notification_type_spmb tapi tidak di-trigger di state transition ke result). |
grep notification_type_spmb |
BE |
| F-013 |
Medium |
CBT |
SPMBCBTStart.vue dan SPMBTestSchedule.vue duplikat logika listing CBT (state, attendance config, formatDate). |
grep duplikasi |
FE |
| F-014 |
Medium |
QA |
testing-guidelines.md belum punya kontrak test untuk endpoint /api/SPMB/my/test-schedules, /api/SPMB/my/test-results, /api/SPMB/selection/result. Tidak ada vitest service contract. |
tests/unit/services/spmb/ |
FE |
| F-015 |
Medium |
Penilaian |
Admin SPMB tidak punya UI "input skor manual per slot" yang explicit untuk V2/V3 — saat ini hanya bisa via tree edit score di Odoo backend. |
grep admin FE |
FE |
| F-016 |
Medium |
Penilaian |
Tidak ada UI rubric scoring untuk wawancara (V3) — pewawancara harus mengetik angka mentah. |
n/a |
FE+BE |
| F-017 |
Medium |
Tes Masuk |
FE pendaftar tidak adaptif: tab "Tes Masuk" tampil walau register tidak punya schedule (V5/V6). Tampil "Belum ada jadwal" alih-alih "Pathway ini tidak memerlukan tes". |
SPMBAdmissionDetail.vue |
FE |
| F-018 |
Medium |
Penilaian |
_compute_ranking_score else-branch fallback hanya pakai tes — kalau pathway baru tanpa tes & kode tidak match domisili/prestasi/afirmasi/mutasi, ranking_score = 0 silently. |
admission.py:316 |
BE |
| F-019 |
Low |
Ranking |
Admin Ranking re-calc (AdmissionApplicationList.vue) panggil calculateRegisterRanks tanpa konfirmasi modal / audit trail. |
AdmissionApplicationList.vue |
FE+BE |
| F-020 |
Low |
Ranking |
PDF export ranking (generateRankingAnnouncementPDF) tidak punya watermark / metadata signer. |
grep export |
FE |
| F-021 |
Low |
Penerimaan |
Tidak ada idempotency/lock pada confirm_enrollment BE (potensi double-click race). |
spmb_api.py::confirm_enrollment |
BE |
7.2 Role Gaps
| ID |
Sev |
Finding |
Resolusi |
| R-001 |
High |
Tidak ada bridge group_scola_admin_staff/head_admin → group_cbt_exam_creator/group_cbt_manager. Admin SPMB tidak bisa buat CBT exam tanpa grant manual. |
Phase 7 |
| R-002 |
Medium |
Tidak ada role granular "Panitia SPMB" / "Proctor SPMB" / "SPMB Question Author". |
Phase 7 (opsional) |
| R-003 |
Medium |
group_cbt_proctor tidak dipakai di konteks admission (UI proctor SPMB belum ada). |
Phase 7 |
| R-004 |
Medium |
group_cbt_grader tidak terhubung ke FE Scola — manual scoring esai SPMB tidak punya UI. |
Phase 7 |
| R-005 |
Low |
FE roleApps.js tidak ada konfigurasi khusus untuk SPMB committee. |
Phase 7 |
7.3 Variant Gaps
| ID |
Sev |
Finding |
Resolusi |
| V-Gap-1 |
High |
Tidak ada field eksplisit selection_method (enum) di op.admission.register atau op.admission.pathway. Risiko mis-config & sulit audit. |
Phase 8 |
| V-Gap-2 |
Medium |
FE pendaftar tidak adaptif terhadap V5/V6 (lihat F-017). |
Phase 8 |
| V-Gap-3 |
Medium |
_compute_ranking_score else-branch silent zero (lihat F-018). |
Phase 5 |
| V-Gap-4 |
Medium |
Admin tidak punya UI input skor manual untuk V2/V3 (lihat F-015). |
Phase 3 |
| V-Gap-5 |
Medium |
Tidak ada UI rubric scoring untuk wawancara V3 (lihat F-016). |
Phase 3 |
7.4 Regulatory Gaps (Permendikdasmen 3/2025)
| ID |
Sev |
Aspek |
Status |
Resolusi |
| Reg-1 |
High |
Tie-breaker jenjang-aware (SD: usia→jarak; SMP: jarak→usia; SMA: TKA→jarak→usia) |
❌ tidak ada |
Phase 8 |
| Reg-2 |
High |
Domisili by wilayah administrasi (kelurahan/kecamatan), bukan jarak murni |
❌ tidak ada (distance_to_school only) |
Phase 8 |
| Reg-3 |
Medium |
Validasi kuota minimum jenjang (SD ≥70%/SMP ≥40%/SMA ≥30% domisili dst.) |
❌ tidak ada |
Phase 8 |
| Reg-4 |
Medium |
Validasi kk_issued_date ≥ 1 tahun, achievement_date ≤ 3 tahun, rapor 5 semester |
⚠️ field ada, validasi belum |
Phase 5 / 8 |
| Reg-5 |
Medium |
Flag is_paid_admission (sekolah negeri dilarang pungut biaya pendaftaran) |
❌ tidak ada |
Phase 8 |
| Reg-6 |
Medium |
Public quota monitor (transparansi daya tampung) |
❌ tidak ada |
Phase 8 |
| Reg-7 |
Low |
Validasi DTKS afirmasi |
❌ tidak ada (manual verify only) |
Phase 7 backlog |
| Reg-8 |
Low |
Penyaluran murid tertolak ke sekolah lain (untuk pemda) |
❌ tidak ada |
Phase 6 backlog |
| Reg-9 |
Low |
Integrasi Dapodik (untuk pemda) |
❌ tidak ada |
backlog |
| Reg-10 |
Low |
Terminologi PPDB → SPMB consistency |
⚠️ mixed |
backlog |
8. Best Practice Reference
8.1 Permendikdasmen No. 3 Tahun 2025 — Highlights
- 4 jalur wajib: Domisili, Afirmasi, Prestasi, Mutasi.
- Kuota minimum acuan nasional:
- Domisili: SD ≥70%, SMP ≥40%, SMA ≥30%
- Afirmasi: SD ≥15%, SMP ≥20%, SMA ≥30%
- Prestasi: SMP ≥25%, SMA ≥30% (tidak berlaku SD)
- Mutasi: maks 5% semua jenjang
- Domisili = wilayah administrasi, bukan zonasi jarak murni. Pemda boleh: (a) admin area, (b) radius, (c) metode lain.
- Tie-breaker jenjang-aware (lihat tabel di bagian audit plan).
- Validasi: KK ≥ 1 tahun, prestasi maks 3 tahun, rapor 5 semester.
- Afirmasi pakai DTKS / bansos / kartu disabilitas, bukan SKTM kelurahan.
- Prinsip wajib: objektif, transparan, akuntabel, berkeadilan, tanpa diskriminasi.
- Pendaftaran daring paling lambat minggu pertama Mei (jenjang dasar/menengah negeri).
8.2 CBT Best Practice (UTBK/SNBT-style)
- Anti-cheat: tab visibility detection, blur warn, fullscreen enforcement, copy-paste block, keyboard shortcut block, mouse leave warn, max N violations → auto-submit.
- Auto-save: simpan jawaban tiap N detik atau saat blur.
- Server time sync: hindari client-side timer manipulation; backend-authoritative.
- Integrity token: signed JWT per attempt, validasi tiap save.
- Resume support: kalau koneksi putus, attempt bisa dilanjutkan (state intermediate).
- Logging: setiap event (start, answer, focus, submit) audit-logged.
8.3 Transparansi Skoring (PMB Public Sector)
- Breakdown skor publik (rapor, achievement, test_total, weighted) per kandidat di portal pendaftar masing-masing.
- Formula publik (read-only di footer pengumuman / link "Bagaimana skor dihitung").
- Tie-breaker rule visible.
- Dispute window (sanggah) ≥ 2 hari kerja setelah pengumuman.
8.4 Notifikasi & Komunikasi
- Multi-channel mandatory untuk milestone kritis (assign jadwal, hasil, deadline daftar ulang): Portal + Email; WA opsional.
- Idempotency_key per notif untuk hindari duplikat saat retry.
- Email template branded + i18n.
9. Risk Register
| ID |
Risk |
Likelihood |
Impact |
Mitigation |
| RK-1 |
Pendaftar klik "Mulai CBT" → crash; massa keluhan saat hari-H tes |
High |
Critical |
Phase 0 (route fix skeleton) sebelum periode SPMB aktif |
| RK-2 |
Setelah daftar ulang sukses, redirect 404 → pendaftar panik, support ticket banyak |
High |
High |
Phase 0 |
| RK-3 |
Kontrak FE↔BE timpang → silent UI bug (label kosong, score 0) |
Medium |
Medium |
Phase 1 (contract test) |
| RK-4 |
CBT runner tanpa anti-cheat → integritas tes diragukan |
Medium |
Critical |
Phase 2 (anti-cheat hooks + audit log) |
| RK-5 |
Pengumuman bocor lebih awal (admin mengubah state sebelum tanggal) |
Medium |
High |
Phase 4 (announcement_at lock + cron release) |
| RK-6 |
Sekolah negeri pakai Scola tapi default ada registration_fee → pelanggaran regulasi |
Low |
Critical |
Phase 8 (is_paid_admission flag) |
| RK-7 |
Tie-breaker SMA tidak pakai TKA → ranking dibantah, sanggah massal |
Medium |
High |
Phase 8 (jenjang-aware tie-breaker) |
| RK-8 |
Domisili by jarak murni → tidak match juknis pemda 2026 |
Medium |
Medium |
Phase 8 (domicile_method) |
| RK-9 |
Race condition confirm_enrollment (double-click) → invoice/student dobel |
Low |
High |
Phase 4 (idempotency lock) |
10. Out of Scope
- Audit performa (backend query, FE bundle size).
- Audit i18n / a11y SPMB pages.
- Migrasi data SPMB lama (PPDB → SPMB schema).
- Integrasi pembayaran provider baru (di luar invoice flow existing).
- Audit security pen-test (di-handle Tier 2 audit terpisah).
11. Referensi
- Permendikdasmen No. 3 Tahun 2025 — Sistem Penerimaan Murid Baru
- Surat Edaran Dirjen PAUD Dikdasmen No. 0301/C/HK.04.01/2026
docs/qa/spmb-flow-audit.md — audit wizard/upload (existing)
docs/qa/spmb-end-to-end-uat.md — UAT skenario (existing)
docs/qa/testing-guidelines.md — kontrak test guidelines
docs/implementation/spmb-tests-cbt-ranking-plan.md — implementation plan (companion)