think
16px
820px

Audit Verifikator — PT & Apostille/Legalisasi (2026-07-11)

TL;DR: mesin verifikator-nya solid di jalur utama (queue PT ter-merge 7 flow, decision state-machine + voting, advisory LLM, audit trail) — tapi ada 4 tema masalah nyata: (T1) lubang integritas/audit pada aksi paling sensitif, (T2) verifikator punya DUA inbox terpisah yang tidak konsisten, (T3) tiga implementasi paralel untuk panel yang sama + tiga flow verifikator TANPA PDF viewer, (T4) struktural: keluarga PP — prioritas #1-mu — belum punya permukaan verifikator sama sekali. Semua temuan sudah kuverifikasi langsung di kode (file:line di bawah). Belum ada yang kuubah — menunggu pilihanmu di bagian Paket Rekomendasi.


Peta kondisi sekarang

flowchart LR subgraph Inbox1["Inbox 1: /verifikator (GET /api/verifikator/submissions)"] Q1[PERUBAHAN · AKUISISI · PENGGABUNGAN\nPELEBURAN · PEMBUBARAN · BERAKHIRNYA\n+ PERBAIKAN_DATA_PT di-merge] end subgraph Inbox2["Inbox 2: /apostille/daftar (GET /api/apostille/list)"] Q2[APOSTILLE + LEGALISASI] end Q1 -->|"/verifikator/review/:id (3 flow)"| R1[VerifikatorReviewPage\nadvisory LLM + diff + voting + PDF] Q1 -->|"/verifikator/{pembubaran,berakhirnya,peleburan}/:id"| R2[3 halaman kompak\nTANPA PDF viewer] Q1 -->|"/verifikator/perbaikan/:id"| R3[Halaman perbaikan\npanel advisory/audit/decision SENDIRI] Q2 -->|"/apostille/permohonan/:id/review"| R4[ApostilleReviewPage mode verifikator\nReviewEngine + signature AI + decide] PP[Keluarga PP\npendirian/perubahan/pembubaran/perbaikan] -.->|TIDAK ADA jalur verifikator| X((∅))
  • Decision recording: PT-family → VerifikasiPerubahan + VerifikasiDecisionLog + VerifikasiAuditEvent (lengkap). Perbaikan → VerifikasiPerbaikan + decision log (audit parsial). Apostille → ApostilleVerification upsert (tanpa log, tanpa audit event).
  • Advisory: 3 implementasi paralel — engine LLM+deterministik server-side (perubahan-family; ai-advisory-engine.ts), advisory LLM terpisah untuk perbaikan (llm/perbaikan-advisory.ts), dan sintesis deterministik client-side untuk apostille (frontend/src/lib/apostille-advisory.ts, hanya 1 dari 4 cek engine).
  • Role: role verifikator murni UX (jotai + localStorage); server shadow-mode — semua endpoint decide bisa dipanggil siapa pun hari ini, dan /api/apostille + /api/perbaikan bahkan tidak diberi policy VERIFIKATOR untuk saat enforcement dinyalakan nanti.

T1 — Integritas & audit (taruhan paling tinggi)

# Temuan Lokasi Kenapa penting
1.1 POST /api/apostille/:id/decide tidak menulis audit event apa pun (0 panggilan recordAuditEvent; tidak ada decision-log) — keputusan APPROVE/REJECT/REVISE apostille tak terlacak routes/apostille.ts:866-922 Satu-satunya flow yang keputusannya invisible di audit trail
1.2 POST /:id/override-validation — meng-override FAIL bisa TANPA alasan dan TANPA audit event, dan endpoint-nya AUTHED (bukan verifikator-scoped), tanpa atribusi siapa pelakunya routes/submissions.ts:1830-1861, route-policies.ts:43 Ini aksi kepatuhan paling sensitif di seluruh sistem (melewati gate FAIL) — dipakai PT, PP, dan Apostille sekaligus
1.3 Catatan keputusan Perbaikan opsional (note: z.string().optional()) padahal PT & Apostille mewajibkannya — tiga kebijakan berbeda untuk aksi yang sama schema/perbaikan-corrections.ts:69-70 Konsistensi bukti keputusan
1.4 VerifikasiPerbaikan.verifikatorUserId mati — kolom ada tapi tidak pernah ditulis; keputusan perbaikan selamanya tanpa atribusi prisma/schema.prisma:1383, routes/perbaikan.ts:798-877 Audit
1.5 5 panggilan audit di perbaikan.ts melewati helper recordAuditEvent → kehilangan requestId/IP/user-agent/principal routes/perbaikan.ts:449,531,555,618,644 Jejak lebih lemah diam-diam di tabel yang sama
1.6 REVISE tidak konsisten me-reset state: perbaikan me-reset override FAIL (fix "M7"), perubahan-family TIDAK (verifikator.ts:276-289); apostille REVISE tidak me-reset konfirmasi field → re-submit bisa lolos gate "semua terkonfirmasi" dengan konfirmasi basi routes/verifikator.ts:276-289, routes/apostille.ts:908 Kelas bug yang persis sama dengan yang M7 perbaiki di perbaikan
1.7 verifikatorId hardcoded "verifikator-dev" di SEMUA halaman FE VerifikatorReviewPage.tsx:305 dkk. Wajar untuk PoC no-auth, tapi patut dicatat: audit trail tak pernah bisa membedakan manusia

T2 — Dua inbox, satu verifikator

# Temuan Lokasi
2.1 Apostille tidak masuk queue verifikator — dua inbox terpisah (/verifikator + /apostille/daftar), dua link sidebar, tanpa hitungan gabungan routes/verifikator.ts:384-386 vs routes/apostille.ts:279-314
2.2 Queue PT tidak polling (data statis sampai reload) sementara list apostille polling 5 dtk hooks/use-verifikator.ts:210-228
2.3 Tidak ada filter jenis flow di queue PT padahal me-merge 7 tipe VerifikatorDashboardPage.tsx:39-59
2.4 GET /api/apostille/list tanpa pagination (kontras queue PT page/limit) routes/apostille.ts:279-314
2.5 Tidak ada konsep SLA/prioritas di queue PT (apostille percepatan sudah punya slaDeadline + sort prioritas; PT hanya sort risk — dan baris Perbaikan selalu di ekor sort risk karena tanpa aiRecommendation) routes/verifikator.ts:456-464,553
2.6 Copy salah label: header queue & help modal bilang "Triage submisi Perubahan PT" padahal isinya 7 flow; judul halaman review bersama hardcoded "Review Perubahan PT" bahkan untuk Akuisisi/Penggabungan (payload-nya memang tak membawa type) VerifikatorDashboardPage.tsx:201-204, VerifikatorReviewPage.tsx:335
2.7 Tidak ada badge jumlah pending di sidebar sidebar.tsx:99-118

T3 — Pengalaman review tidak seragam

# Temuan Lokasi
3.1 Pembubaran, Berakhirnya, Peleburan: verifikator TIDAK BISA melihat PDF sumber sama sekali (tiga halaman itu tak mengimpor ReviewPdfViewer) — memeriksa "buta" dari snapshot field VerifikatorPembubaranReviewPage.tsx dkk.
3.2 3 implementasi Decision Panel (verifikator/review, perbaikan raw-<button> dengan aturan catatan berbeda, apostille), 2 Audit Trail Panel, 3 advisory — visual & perilaku beda-beda components/verifikator/review/* vs components/perbaikan/* vs components/apostille/*
3.3 Tidak ada tombol kembali-ke-queue di halaman perbaikan & apostille (verifikator "terdampar" setelah memutus) VerifikatorPerbaikanReviewPage.tsx, ApostilleReviewPage.tsx
3.4 Read-back keputusan (banner "apa yang terjadi") hanya rapi di Apostille; PT sub-flow bergantung render internal DecisionPanel apostille-verifikator-blocks.tsx:112-123
3.5 Advisory LLM sengaja di-nol-kan untuk pembubaran/berakhirnya/peleburan ("perubahan-shaped diff report" tidak cocok) — verifikator flow ini tanpa "Saran AI" pembubaran.ts:262 dkk.
3.6 Tidak ada keyboard shortcut / bulk triage di mana pun (murni klik satu-satu)

T4 — Struktural

# Temuan
4.1 Keluarga PP tidak punya permukaan verifikator SAMA SEKALI — semua PP flow selesai lewat finalize milik pemohon (atau konfirmasi email BO), tanpa queue, tanpa decide, tanpa audit keputusan. Padahal prioritasmu PP > Apostille > PT.
4.2 Enforcement role server-side masih shadow (by design sampai token issuance ada); tapi policy map-nya pun belum siap: /api/apostille & /api/perbaikan (yang memuat endpoint decide) cuma AUTHED — begitu enforcement nyala, notaris legal memanggil decide. Butuh policy per-route yang lebih halus dari prefix-mount.

Paket rekomendasi (pilih yang mau dikerjakan)

Paket Isi Dampak Effort
P1 — Integritas & Audit (backend) Audit event + decision log untuk apostille /decide; override-validation wajib alasan + audit event + atribusi; catatan perbaikan wajib + verifikatorUserId ditulis; 5 panggilan audit perbaikan → recordAuditEvent; reset override saat REVISE perubahan-family + reset konfirmasi saat REVISE apostille; policy VERIFIKATOR untuk kedua endpoint decide (siap-enforcement, tetap shadow sekarang) Tinggi (kepatuhan/bukti) ~1 sesi
P2 — Satu Inbox Apostille masuk GET /api/verifikator/submissions (atau list terpadu baru): satu queue lintas 8 flow + kolom Jalur/SLA, filter jenis flow, polling, pagination apostille, badge pending di sidebar, perbaiki copy salah label + judul type-aware Tinggi (UX harian verifikator) ~1 sesi
P3 — Review UX Seragam PDF viewer untuk pembubaran/berakhirnya/peleburan; perbaikan pindah ke panel bersama (advisory/audit/decision); banner read-back keputusan seragam; tombol kembali-ke-queue di semua halaman Sedang-tinggi ~1–1,5 sesi
P4 — Verifikator PP (baru) Rancang + bangun staging verifikator untuk keluarga PP (model keputusan + queue + decide + audit, pola VerifikasiPerubahan), masuk ke inbox terpadu Tinggi (prioritas #1-mu, gap terbesar) ~2 sesi; butuh keputusan scope: PP flow mana saja & apakah menggantikan finalize milik pemohon atau menjadi tahap setelahnya
P5 — Lanjutan Advisory terpadu (apostille server-side + persisted; advisory non-diff untuk pembubaran/berakhirnya/peleburan); keyboard shortcuts + bulk triage; identitas verifikator nyata (bareng token issuance) Sedang ~1–2 sesi

Rekomendasiku kalau disuruh memilih urutan: P1 → P2 → P3 (P1 menambal lubang bukti/kepatuhan yang murah tapi penting; P2 mengubah pengalaman harian verifikator paling terasa; P3 menyeragamkan). P4 paling strategis tapi butuh keputusan desainmu (PP selama ini sengaja self-service — menambah verifikator mengubah alur produknya). P5 menyusul.

Semua temuan diverifikasi manual pada commit e7abdd11. Belum ada perubahan kode.