Skip to content
AFM Studio
GovernmentWeb AppInternal Tool

JDIH OIKN

Government legal document portal with editorial workflow, tiered access control, and offline AI summaries

All projects4 min read

Role

Fullstack Developer

Timeframe

Mar – Jun 2026

On this page

The problem

OIKN (Otorita Ibu Kota Nusantara) is a new government body that issues its own legal instruments — regulations, decrees, MoUs, and more. Before this system, legal documents were scattered across email threads and local drives, the public had no way to find official OIKN regulations, there was no controlled review process, access to sensitive documents was enforced informally with no audit trail, and the annual reporting mandated by Peraturan Kepala OIKN No. 14 Tahun 2025 had to be assembled by hand.

JDIH (Jaringan Dokumentasi dan Informasi Hukum) is a nationally mandated legal information network. OIKN needed a compliant implementation covering both a public-facing portal and an internal editorial workflow.

The approach

A role hierarchy that grew to match the org chart

The original plan called for four roles. In production it became five: superadmin, admin_jdih (Direktorat Hukum), admin_anggota, walidata, registered. The nuance that justified the split — admin_jdih can approve documents even though it sits below superadmin, while admin_anggota, despite also being "admin," can create and edit but never approve. Every admin endpoint declares an explicit permission class (IsAdminOrAbove, IsWalidata, IsSuperAdmin) from a single permissions.py rather than checking roles inline, and the frontend mirrors the same boundary — the document review route is gated to admin_jdih, walidata, and superadmin, explicitly excluding admin_anggota.

Three-tier access control enforced at the download endpoint, not the UI

Documents are classified open, restricted, or closed. Restricted documents require an access request that a walidata officer approves, with an optional expiry. A /accesses/check/ endpoint lets the frontend show the right call-to-action — download, request access, or a login prompt — without ever leaking the document URL to someone who shouldn't have it, and every access and download is written to an audit trail.

An AI feature matured in three stages: ship, harden, govern

Document summarization shipped first against the Gemini Flash API (v1.8.0) to prove the feature was worth building. By v1.9.0 it was rebuilt as a fully offline pipeline — pdfplumber extracts PDF text, sumy and nltk produce an extractive plain-language summary, a keyword-weighted classifier assigns the legal domain — because sending government legal documents to a third-party cloud API is a compliance risk a JDIH system can't take on. That would have been a reasonable place to stop, but a quiet month of further work (never given a version bump in the in-app changelog) added a governance layer on top: a RingkasanEvalRun model, a human-correction ("gold summary") editor for staff, a legalese-to-plain-language glossary pass, and a weekly scheduled quality evaluation feeding an evaluate_ai_summaries benchmark command — turning the summarizer from a one-shot generator into something that catches its own quality drift over time.

A Celery task scans published document titles for Indonesian legal citation patterns — "mencabut Perka No. 14 Tahun 2022" — resolves the referenced document, and creates a RelationCandidate for admin review. Confirmed relationships render as a navigable regulatory tree at /pohon-peraturan, showing which documents repeal, amend, or implement each other.

Statistics that never touch a live COUNT query

Both the admin dashboard and a public-facing /statistik page (a 365-day activity heatmap, trending document types, top legal domains by engagement) read from pre-aggregated tables refreshed nightly by Celery Beat rather than computing anything live against a growing document corpus. A fallback added later reads straight from the activity log if the nightly table hasn't populated yet, so the dashboard never shows a hard zero.

Dual authentication without session conflicts

OIKN staff authenticate through Keycloak SSO; the OIDC backend maps department, NIP, and name claims directly onto JDIH user records. External and public users use ordinary email-and-password with JWT. The two coexist because Keycloak is used purely as an authentication step that mints a JWT for the frontend — the Keycloak session itself never leaves the server.

Trust-building features beyond the mandate

Past what Perka 14/2025 strictly required: verified users can bookmark documents for later reference; an in-app notification system with an unread badge tells users when their access request status changes; a moderated 1–5 star rating system surfaces approved testimonials on the homepage; and faceted, URL-shareable document search exports up to 2,000 rows to CSV for offline analysis.

Outcome

Version 1.10.0 is the last release logged in the in-app changelog, but real commit history — 100 backend and 91 frontend commits on main, independently verified — runs a full month past that, through 24 June 2026, spanning roughly sixteen weeks total. The system now covers 7 Django apps, 25 database models, 90 API endpoints, 9 named Celery tasks, and 76 frontend source files (~15,800 lines). Early commit messages were loose; a consistent type(scope): message convention took over from mid-April and held through the entire AI governance build-out — a small but real signal of process maturing alongside the feature set. Active in production for OIKN's Directorate of Law staff, with the public portal serving open documents to any visitor.

Outcomes

REST API endpoints, OpenAPI-documented
95
Frontend routes, public + admin
37
Tests guarding the external API
29
Commits, two repos, solo-authored
210

Screenshots

Beranda
Beranda Jenis Dokumen Hukum
Beranda Dokumen Terbaru
Beranda User Feedback
Dokumen Hukum List
Dokumen Detail

Have a project like this?

If you need a system built with the same care — clear scope, solid execution — let's talk.

Start a project