September 2026

Penerimaan Pengawas Desa

Sistem seleksi end-to-end terintegrasi: pendaftaran pelamar, seleksi administratif, test online (CBT), wawancara, hingga pengumuman kelulusan.

πŸ“‹ Ikhtisar Sistem

Platform penerimaan Pendamping & Pengawas Desa yang menjalankan proses seleksi secara menyeluruh dari pendaftaran hingga pengumuman kelulusan. Terdiri dari 4 aplikasi web yang saling terintegrasi dan berbagi 1 basis data PostgreSQL bernama online_test.

APP 1 Pendaftaran PD

Portal pelamar: isi data diri, pilih posisi & lokasi, unggah dokumen ke MinIO.

APP 2 Manajemen Test

Panel panitia: orkestrasi seluruh seleksi, multi-role, CSV export, pengumuman publik.

APP 3 Test Online

Portal CBT: pelamar login, kerjakan soal pilihan ganda & esai, upload jawaban.

APP 4 Test Wawancara penguji-only

Aplikasi khusus penguji: lihat jadwal & beri penilaian wawancara. Admin tidak bisa login di sini.

πŸ”„ Alur Seleksi End-to-End (5 Tahap)

1

Pendaftaran

Isi data diri, pilih posisi, upload dokumen. Status: draft β†’ submitted

2

Seleksi Administratif

Panitia verifikasi berkas β†’ passed / rejected

3

Test Online

CBT pilihan ganda & esai. Panitia set passing score β†’ publish

4

Wawancara

Jadwal + penguji. Multi-kriteria 0-100, rata-rata otomatis

5

Kelulusan

Keputusan akhir + pengumuman publik (bisa dicetak)

πŸ— Arsitektur Sistem

PostgreSQL online_test 1 database bersama Β· remote server :5432
β–² β–² β–² β–²
Test Online
BE :5000FE :5173
Pendaftaran PD
BE :5001FE :5174
↳ MinIO
Manajemen Test
BE :5002FE :5175
↳ MinIO
Test Wawancara
BE :5004FE :5177
πŸ“¦
MinIO Object Storage S3-compatible Β· dokumen & berkas pelamar (upload pendaftaran, pengelolaan manajemen)

Frontend (Vite dev) me-proxy /api ke backend-nya masing-masing.
MinIO menyimpan dokumen pendaftaran β€” dipakai bersama oleh Pendaftaran PD & Manajemen Test.

πŸ” Arsitektur & Peran Pengguna (User Role)

Bagaimana Aplikasi Saling Terhubung

Keempat aplikasi berbagi satu database PostgreSQL (online_test), bukan saling memanggil API. Artinya, data yang ditulis satu aplikasi langsung terbaca aplikasi lain. Alur integrasinya:

  • Manajemen β†’ Test Online : panitia buat jadwal & undangan (pd_test_schedules / pd_test_invitations); pelamar yang sama login di Test Online dan mengerjakan test via jadwal tersebut.
  • Test Online β†’ Manajemen : hasil CBT ditulis ke test_sessions (berkorelasi test_id + user_id); Manajemen membaca skor untuk set passing score & publish.
  • Manajemen β†’ Pendaftaran : status seleksi/kelulusan ditulis ke pd_applicants; pelamar melihat progres 5 tahap di portal Pendaftaran karena membaca tabel yang sama.
  • Manajemen β†’ Wawancara : penjadwalan, penugasan penguji, dan kelola akun penguji (CRUD + is_active) di Manajemen; penilaian wawancara dilakukan penguji di Test Wawancara (ownership guard). Tabel bersama pd_interview_*.
  • Buka/Tutup gelombang : pengaturan di pd_settings diubah panitia (Manajemen), dibaca publik oleh Pendaftaran untuk menutup/menampilkan banner.
Aplikasi Portal Role Hak Akses / Kemampuan
test_online
CBT
Pelamar participant Login, melihat jadwal/undangan test, mulai sesi, kerjakan pilihan ganda & esai, upload jawaban/foto, melihat skor sesi. Tidak ada role admin di app ini β€” semua pengaturan via Manajemen.
pendaftaran_pd
Portal Pelamar
Pelamar (publik) participant Registrasi, isi/simpan form pendaftaran (draft), unggah dokumen, submit saat gelombang buka, pantau status 5 tahap. Tidak ada login panitia; pengaturan gelombang dari Manajemen.
manajemen_test_pd
Panel Panitia
Panitia / Manajemen pd_admin
seleksi@test.com
Akses penuh: semua grup menu (Pendaftaran, Seleksi Adm, Test Online, Wawancara, Hasil Akhir), kelola gelombang, verifikasi seleksi, jadwal CBT, passing score & publish, jadwal wawancara, kelola penguji (CRUD + is_active), keputusan kelulusan, ekspor CSV, pengumuman. Admin wawancara digabung ke pd_admin.
test_wawancara
Penguji-only
Penguji Wawancara penguji
penguji1@test.com
penguji2@test.com
Jadwal & Penilaian: melihat jadwal wawancara yang ditugaskan (read-only), mengisi nilai multi-kriteria (0–100) + catatan. Hanya bisa menilai jadwal miliknya (ownership guard). Admin tidak bisa login di app ini β€” kelola akun penguji (CRUD, is_active) dilakukan di Manajemen.

Skeema autentikasi Manajemen: hanya pd_admin_users (type pd_admin) yang bisa login. Akun di pd_interview_users (penguji & admin wawancara) ditolak di Manajemen. Penguji login di Test Wawancara. Admin wawancara digabung ke pd_admin. Test Wawancara authenticate: role penguji + is_active check.

βš™ Teknologi yang Digunakan

Frontend (semua aplikasi)

React 19 Vite Tailwind CSS v4 React Router Axios oxlint

Backend (semua aplikasi)

Node.js Express PostgreSQL (pg) JWT bcryptjs multer

Pendaftaran & Manajemen

MinIO (S3) uuid presigned PUT

Test Online saja

node-cron multer (esai/foto)

πŸ“± Detail 4 Aplikasi

Aplikasi Fungsi Utama Port DB Tables Status
pendaftaran_pd Portal pelamar: form pendaftaran, upload dokumen (MinIO), pemilihan posisi & lokasi, progres 5 tahap 5001 / 5174 pd_provinces, pd_regencies, pd_districts, pd_villages, pd_applicants, pd_education, pd_work_experiences, pd_documents Aktif
manajemen_test_pd Panel panitia: 5 grup menu (Pendaftaran, Seleksi, Test Online, Wawancara, Hasil Akhir), multi-role, CSV async (job queue + BullMQ), pengumuman publik 5002 / 5175 pd_admin_users, pd_settings, pd_selections, pd_test_schedules, pd_test_invitations, pd_interview_*, job_queue Pusat
test_online CBT: login pelamar, kerjakan soal PG & esai, bulk submit jawaban (multi-row), hitung skor bulk 5000 / 5173 users, tests, questions, answer_options, test_sessions, user_answers, essay_scores Aktif
test_wawancara Aplikasi khusus penguji: jadwal wawancara (read-only) + penilaian multi-kriteria. Admin tidak bisa login. 5004 / 5177 pd_interview_users, pd_interview_criteria, pd_interviews, pd_interview_scores Idle

⚑ Skala & Arsitektur Queue

Sistem dirancang untuk menangani volume peserta riil: Β±600.000 pendaftar, Β±600.000 peserta CBT, Β±200.000 peserta wawancara. Arsitektur berikut memastikan stabilitas di skala tersebut.

Tier 1 Postgres Job Queue

Tabel job_queue di DB online_test (shared). Worker polling tiap 3 dtk dengan FOR UPDATE SKIP LOCKED, retry 3Γ—, exponential backoff. Tanpa infra baru β€” langsung jalan.

Tier 2 Redis + BullMQ

Queue export.csv, invitation.send, announcement.broadcast di Redis. Rate-limit 50 email/dtk, concurrency 3, exponential backoff. Monitoring via /admin/queues (bull-board).

Tugas yang masuk queue

TugasQueueTierMekanisme
Ekspor CSV (5 tahap, Β±600rb baris) export.csv BullMQ + Postgres Stream DB β†’ csv-stringify β†’ MinIO β†’ presigned download URL. Bukan lagi res.send(csv()) di memori.
Kirim undangan CBT (Β±600rb) invitation.send BullMQ Multi-row INSERT 1 transaksi + batch email (50/dtk via limiter). Bukan N+1 per pelamar.
Publish hasil test online β€” (bulk SQL) Postgres Bulk UPDATE via unnest() β€”1 query untuk semua peserta, bukan loop per baris.
Submit jawaban CBT β€” (bulk SQL) Postgres POST /save-answers multi-row INSERT ... ON CONFLICT dalam1 transaksi. Scoring via bulk UPDATE unnest().
Upload dokumen pendaftaran β€” (presigned PUT) MinIO langsung Browser upload langsung ke MinIO via presigned PUT URL (offload backend). Backend hanya generate URL + simpan metadata.

Optimasi skala besar

# Pool koneksi configurable di semua backend
PG_POOL_MAX=20 # default 20, naikkan sesuai beban

# Interval polling worker (ms)
JOB_POLL_INTERVAL_MS=3000

# Redis URL untuk BullMQ
REDIS_URL=redis://127.0.0.1:6379

# BullMQ concurrency per worker
BULLMQ_CONCURRENCY=3

# Monitoring queue (bull-board)
GET /admin/queues # UI monitoring job BullMQ

πŸ—„ Database online_test

Semua aplikasi berbagi 1 database PostgreSQL yang sama. Berikut pembagian tabel per scope:

Test Online

users
tests
questions
answer_options
test_sessions
user_answers
essay_scores

Pendaftaran

pd_provinces, pd_regencies,
pd_districts, pd_villages
pd_applicants
pd_education
pd_work_experiences
pd_documents

Manajemen

pd_admin_users
pd_settings
pd_selections
pd_test_schedules
pd_test_invitations
job_queue

Wawancara

pd_interview_users
pd_interview_criteria
pd_interviews
pd_interview_scores

πŸ‘€ Akun Test

AD
seleksi@test.com admin123 Β· pd_admin / panitia utama
P1
penguji1@test.com admin123 Β· penguji wawancara (login di Test Wawancara)
P2
penguji2@test.com admin123 Β· penguji wawancara (login di Test Wawancara)
SI
siti.amelia@test.com Pelamar123 Β· pelamar contoh (lolos semua tahap)

πŸš€ Cara Menjalankan

Setiap aplikasi berjalan mandiri. Jalankan backend & frontend secara terpisah:

# Contoh: jalankan Manajemen Test
cd penerimaan_pengawas_desa/manajemen_test_pd/backend
npm install # pertama kali
node src/server.js # β†’ jalan di :5002

cd ../frontend
npm install
npm run dev # β†’ jalan di :5175

# Build produksi frontend:
npm run build # output ke dist/

# Lint (oxlint):
npm run lint

Penting: isi file backend/.env sebelum menjalankan (DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME, JWT_SECRET, PORT, dll). Kredensial tidak tercantum di dokumentasi ini demi keamanan.

πŸ— Cara Deploy (Urutan & Konfigurasi)

Urutan deploy penting β€” ada dependency antar layanan. Ikuti urutan di bawah agar tidak ada error koneksi.

0. Prerequisites (Infrastruktur)

LayananPortKeterangan
PostgreSQL 14+5432Buat database online_test. Semua 4 app share DB ini.
Redis 6+6379Untuk BullMQ (job queue tier 2). Wajib untuk manajemen_test_pd.
MinIO9002Object storage dokumen & ekspor CSV. Bucket: seleksi-pendamping-desa.
Node.js 18+β€”Semua backend & build frontend.

0a. Install & Jalankan Redis

Redis dipakai oleh manajemen_test_pd untuk BullMQ (job queue tier 2).

# Ubuntu/Debian
sudo apt update && sudo apt install redis-server -y
sudo systemctl enable redis-server
sudo systemctl start redis-server

# Verifikasi
redis-cli ping # β†’ PONG

# Docker (alternatif)
docker run -d --name redis -p 6379:6379 redis:7-alpine

# Konfigurasi opsional (/etc/redis/redis.conf)
# maxmemory 256mb
# maxmemory-policy allkeys-lru
# requirepass your_password (kalau perlu auth)

Kalau Redis pakai password: REDIS_URL=redis://:password@127.0.0.1:6379 di .env manajemen_test_pd.

0b. Arsitektur BullMQ

BullMQ berjalan otomatis saat manajemen_test_pd start β€” tidak perlu proses terpisah. Worker + queue terintegrasi di src/server.js.

QueueFungsiRate LimitRetry
export.csvEkspor CSV async (stream DB→MinIO)—3×
invitation.sendKirim undangan CBT (batch email)50/dtk3Γ—
announcement.broadcastBroadcast pengumumanβ€”2Γ—
# Environment variables BullMQ (di .env manajemen_test_pd)
REDIS_URL=redis://127.0.0.1:6379
BULLMQ_CONCURRENCY=3 # worker concurrent jobs
JOB_POLL_INTERVAL_MS=3000 # Postgres queue polling (tier 1)

# Monitoring (bull-board UI)
GET /admin/queues # akses via browser

# Proteksi dengan basic auth (Nginx)
# location /admin/queues {
# proxy_pass http://127.0.0.1:5002;
# auth_basic "Queue Monitor";
# auth_basic_user_file /etc/nginx/.htpasswd;
# }

1. Urutan Deploy

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# STEP 1: Database
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
createdb online_test

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# STEP 2: Jalankan 4 backend (urutan bebas, tapi pendaftaran dulu karena tabel induk)
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

# 2a. test_online (CBT) β€” :5000
cd test_online/backend
cp .env.example .env # edit isi .env
npm install
node migrations/migrate.js # buat tabel users, tests, dll
node src/server.js # β†’ :5000, worker auto-start

# 2b. pendaftaran_pd β€” :5001
cd pendaftaran_pd/backend
cp .env.example .env
npm install
node migrations/migrate.js # buat tabel pd_applicants, pd_documents, dll
node src/server.js # β†’ :5001

# 2c. manajemen_test_pd β€” :5002
cd manajemen_test_pd/backend
cp .env.example .env
npm install
node migrations/migrate.js # buat tabel + job_queue
node migrations/seed_admin.js # seed akun admin (seleksi@test.com)
node src/server.js # β†’ :5002, worker + BullMQ worker auto-start

# 2d. test_wawancara β€” :5004
cd test_wawancara/backend
cp .env.example .env
npm install
node migrations/migrate.js
node src/server.js # β†’ :5004

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# STEP 3: Build & jalankan 4 frontend
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

cd test_online/frontend && npm install && npm run build # β†’ dist/
cd pendaftaran_pd/frontend && npm install && npm run build
cd manajemen_test_pd/frontend && npm install && npm run build
cd test_wawancara/frontend && npm install && npm run build

# Serve dist/ dengan Nginx / serve / reverse proxy

# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# STEP 4: Verifikasi
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
curl http://localhost:5000/api/health # test_online
curl http://localhost:5001/api/health # pendaftaran_pd
curl http://localhost:5002/api/health # manajemen_test_pd
curl http://localhost:5004/api/health # test_wawancara
curl http://localhost:5002/admin/queues # bull-board UI

2. Checklist Environment Variables

VariableWajib diContoh
DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAMESemua backendlocalhost, 5432, postgres, ****, online_test
JWT_SECRET, JWT_EXPIRESSemua backendrahasia-super-rahasia, 24h
PORTSemua backend5000, 5001, 5002, 5004
PG_POOL_MAXSemua backend20 (default)
MINIO_ENDPOINT, MINIO_PORT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY, MINIO_BUCKETpendaftaran_pd, manajemen_test_pd47.251.15.245, 9002, ****, seleksi-pendamping-desa
REDIS_URLmanajemen_test_pdredis://127.0.0.1:6379
TEST_ONLINE_URLmanajemen_test_pdhttp://localhost:5000 (integrasi CBT)

3. Urutan Deploy yang Benar (Ringkasan)

1. PostgreSQL β†’ buat DB online_test
2. Redis β†’ jalankan redis-server
3. MinIO β†’ buat bucket seleksi-pendamping-desa, set CORS
4. Backend test_online β†’ migrate β†’ start (:5000)
5. Backend pendaftaran_pd β†’ migrate β†’ start (:5001)
6. Backend manajemen_test_pd β†’ migrate β†’ seed admin β†’ start (:5002)
7. Backend test_wawancara β†’ migrate β†’ start (:5004)
8. Frontend (4 app) β†’ npm run build β†’ serve dist/ via Nginx
9. Verifikasi: /api/health di semua backend + /admin/queues di manajemen

4. Nginx Reverse Proxy (Contoh)

# /etc/nginx/sites-available/penerimaan-desa

server {
  listen 80;
  server_name penerimaan-desa.local;

# Frontend (serve static build)
  location / {
    root /var/www/penerimaan-desa/frontend/dist;
    try_files $uri /index.html;
  }

# Backend API (proxy ke Node.js)
  location /api/ {
    proxy_pass http://127.0.0.1:5002;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }

# Bull-board monitoring (manajemen_test_pd)
  location /admin/queues {
    proxy_pass http://127.0.0.1:5002;
    auth_basic "Queue Monitor";
    auth_basic_user_file /etc/nginx/.htpasswd;
  }
}

πŸ“¦ Repository GitLab

Setiap project punya repo git sendiri (folder .git masing-masing). Folder induk ini bukan repo git, sehingga dokumentasi tidak ikut terpush.