How We Built a GDPR-Compliant Anti-Corruption Platform with 9 Institutional Roles

When a Bulgarian civic rights organisation approached us with a vision to transform how citizens report corruption, we knew this would be one of our most technically demanding and socially meaningful projects. Moite Prava (moiteprava.bg) needed a platform that could do what email chains and paper forms never could: give citizens a secure, anonymous way to report corruption while giving government institutions the structure to actually investigate and resolve those complaints.

The stakes were real. In Bulgaria, corruption complaints submitted via email or paper often disappeared into bureaucratic black holes. Citizens had no way to track whether their complaint was being reviewed, investigated, or ignored. Government agents lacked structured workflows, and there was no accountability trail. Moite Prava wanted to change that with technology - and they came to us to build it.

Project: moiteprava.bg

The Challenge

This was not a standard web application. The platform needed to serve two fundamentally different user groups with opposing requirements. Citizens needed simplicity, privacy, and trust. Government agents needed power, structure, and oversight. Bridging that gap while maintaining strict data boundaries was the core architectural challenge.

The specific requirements included:

The complexity was compounded by the fact that this platform would handle sensitive data about corruption allegations. A single data leak or privacy violation could undermine the entire initiative and put whistleblowers at risk. Security and privacy could not be afterthoughts - they had to be fundamental to the architecture.

Our Solution

We built the platform on Next.js and Supabase, leveraging Supabase Row-Level Security (RLS) as the backbone of the privacy architecture. Rather than relying on application-level access controls alone, we pushed data isolation down to the database layer. This meant that even if a bug existed in the frontend, the database itself would refuse to serve citizen identity data to institutional users.

Citizen-Facing Platform

For citizens, we built a guided complaint submission form that walks users through the process step by step. Instead of a blank text field, citizens answer structured questions about the type of corruption, the institution involved, dates, and supporting evidence. This structured approach helps investigators and reassures citizens that their complaint is being taken seriously.

Once submitted, each complaint enters an 8-stage tracking pipeline: Submitted, Registered, Under Review, Investigation, Legal Assessment, Decision, Resolution, and Closed. Citizens see a real-time progress bar and receive email notifications via Resend at each stage transition. The cryptographic separation means their identity is linked to the case through a one-way reference that institutional users cannot reverse.

Institutional Platform

The institutional side was where the real complexity lived. We implemented 9 distinct roles, each with a purpose-built dashboard:

Each role has granular permissions controlling which cases they can see, what actions they can take, and what data fields are visible. Case management includes internal notes, document attachments, stage transitions, and a complete audit log. Every action - from opening a case to adding a note to changing a status - is recorded with the user, timestamp, and action detail.

Public Transparency Dashboard

To build public trust, we created a statistics dashboard accessible without login. It shows aggregated data: total complaints received, average resolution time, complaints by category and region, and resolution rates. The dashboard uses Recharts for interactive visualisations. All data is pre-aggregated so that no individual case details can be inferred. This transparency layer was critical for Moite Prava mission of public accountability.

The Results

The platform delivered a complete transformation of how corruption complaints are handled in Bulgaria. What was once an opaque, paper-based process became a structured, transparent, and accountable digital workflow.

Technology Stack

TechnologyPurpose
Next.jsServer-side rendering, routing, and API layer
React + TypeScriptType-safe component architecture for both citizen and institutional interfaces
Supabase (RLS)Database with Row-Level Security for privacy-by-design data isolation
RechartsInteractive data visualisations for the public transparency dashboard
ResendTransactional email notifications for complaint status updates
Zod + React Hook FormSchema validation and guided complaint submission forms

The choice of Supabase was strategic. Its Row-Level Security policies allowed us to enforce data boundaries at the database level, meaning that even a compromised frontend could not expose citizen data to institutional users. Combined with Next.js server-side rendering for fast initial loads and Zod for rigorous input validation, the stack delivered both security and usability.