Inspiration
Fake online job offers are one of the most common scams in Indonesia: a "part-time job" or "top-up task" pays a small commission first, then asks for deposit after deposit. Indonesia's official anti-scam channel, OJK's Indonesia Anti-Scam Centre (IASC), received 637,055 reports between Nov 2024 and Jul 2026, and asks victims for a clear chronology, transaction details and evidence. But what victims actually hold is a long, messy chat — and they are stressed, ashamed and in a hurry. We wanted a tool that turns that chat into report-ready material without letting an AI invent or change the evidence.
What it does
LaporSiap ("ready to report") guides a victim — or a family member helping them — in four steps:
- Paste the chat (WhatsApp/Telegram export or plain text) and add the transfers they know.
- Exact preview & consent — the user sees exactly what the model will read. Names, phone numbers, emails and account numbers are masked. Transfers, attachments and access tokens never leave the server. One explicit consent per AI request.
- Apertus drafts a chronology: one short entry per source message, bound to its message ID.
- Human review — every entry sits next to its original message. Quotes are re-attached from the source by code (the model can never alter evidence), totals are calculated by code (never by AI), pending transfers stay out of the total, missing dates are flagged instead of guessed. The user confirms each line. Only a reviewed version can be exported (PDF / TXT / ZIP evidence pack) for the official channel. The full workflow also works with a manual draft and no AI at all.
How we built it
- Backend: Go (Clean Architecture), PostgreSQL, strict JSON output contract with source binding, order and time-phrase validation, and model-identity checks.
- Frontend: React + Redux + TypeScript (Vite), bilingual UI (Indonesian / English), mobile-friendly.
- AI: Apertus v1.5 via an OpenAI-compatible endpoint (Public AI for tests); the same app points to a local vLLM server on-premise.
- Target architecture: on-premise and air-gap capable Docker stack (UI, API, PostgreSQL) plus Apertus on vLLM bound to localhost. No CDN, analytics or telemetry.
- Quality: Go unit + PostgreSQL integration tests with the race detector, architecture-boundary checks and 13 browser regressions in GitHub Actions CI.
- Implementation, tests and docs were built with the help of Claude Code; design decisions, review and commits are ours.
Challenges we ran into
- Models rewrite meaning silently. Passing a JSON schema is not enough, so we bound every entry to its source ID, re-attached quotes by code and added validation that rejects drafts that lose time phrases like "next week".
- Model identity: once, a request to "Apertus" was answered by a different model; our identity check rejected it.
- Provider errors: the hosted 70B gateway intermittently rejected valid requests (HTTP 400). We diagnosed it, kept no hidden auto-retry, and let the user retry or draft manually.
- Privacy vs usefulness: deciding exactly what may leave the server, and showing it to the user before consent.
Accomplishments that we're proud of
- The AI can never alter the evidence. Quotes are re-attached from the original messages by code, every entry is bound to its source ID, and totals are calculated by code — not by the model.
- Nothing sensitive leaves without the user seeing it. An exact preview shows what the model will read; names, phones, emails and account numbers are masked; transfers, attachments and tokens never leave the server.
- An honest, reproducible evaluation. We compared Apertus 8B and 70B on a frozen 12-case bilingual fixture and published every output — including the errors. Both passed 12/12 on the output contract, yet review still found meaning errors, which is exactly why the human step is mandatory.
- Prompt injection was never obeyed. Hidden "SYSTEM: ignore previous instructions…" text inside chats was described as content in every case.
- We caught a wrong model. Once, a request to "Apertus" was answered by a different model; our model-identity check rejected it automatically.
- Works fully without AI. The whole workflow, including export, runs with a manual draft — and the stack is designed to run on-premise and air-gapped.
- Bilingual and tested. Indonesian/English UI, unit + PostgreSQL integration tests and 13 browser regressions green in CI.
What we learned
Responsible AI here is mostly product design: the model writes short descriptions, code owns the facts, and the person owns the decision. A bigger model reduces errors but does not remove the need for review.
What's next for LaporSiap
- Run on-premise on a real GPU (vLLM) with an Indonesian partner organisation.
- Pilot with 2–3 real users (kit ready) and measure time saved.
- OCR for screenshot evidence and more chat-export formats.
Built With
- apertus
- docker
- github-actions
- go
- playwright
- postgresql
- public-ai
- react
- redux
- typescript
- vite
- vllm
Log in or sign up for Devpost to join the conversation.