Trust & Security
Designed to be
verifiable.
OneGov is anti-corruption infrastructure. Every authenticated action is recorded on a tamper-evident hash chain, every byte stays in the Government Data Centre, and citizen data is reused — never duplicated.
Tamper-evident, by design.
Every authenticated mutation on OneGov is appended to a SHA-256 hash chain. Each row stores both its own hash and the previous row's — modify, delete, or insert any row out of order, and every hash after it breaks. The integrity check walks the whole chain and pinpoints exactly which row was tampered with.
- SHA-256 over a stable canonical form of each entry.
- Microsecond-precision timestamps so write-hash always matches verify-hash.
- A single writer goroutine serializes inserts — no chain forks.
- The super-admin's dashboard runs the check in one click.
✓ Chain intact — 12,453 entries verified
row hash = SHA-256(prev_hash || canonical(row))
canonical(row) = {
user_id, method, path, status,
payload_digest, ip, user_agent,
duration_ms, created_at_unix_micro
}
verify: walk every row in (created_at, id) order
and recompute the hash.
result: pass or first-broken-row + expected vs gotVerify-once, reuse-everywhere.
OneGov doesn't hold a "master" citizen record. Identity is verified against the national register through our internal exchange layer, then cached as a CitizenProfile so subsequent applications never bother NIRA again. Data minimisation, built into the architecture.
Once-only principle
Citizens enter their NIN once. Every service reuses the verified profile through the exchange layer — no re-submission.
Read, don't duplicate
Authoritative registries (NIRA, URA) remain the source of truth. OneGov reads through a swappable RegistryProvider; we never become a competing master copy.
Audit-logged sharing
Every exchange-layer read is itself an auditable event in the hash chain — statutory data-sharing has a cryptographic paper trail.
Built, owned, and hosted in Uganda.
OneGov runs entirely on infrastructure inside the Government Data Centre. No foreign cloud lock-in. The framework (Grit) is owned by Desishub Technologies — a Kampala company — so Uganda controls the platform end-to-end.
- Self-hosted Go API + PostgreSQL + Redis + MinIO.
- Containerised — grit deploy or plain docker-compose, your choice.
- Caddy auto-TLS for the live demo.
- Code in a Ugandan-owned repository, no foreign vendor dependency.
Production deployment
Government Data Centre ├── onegov-api (Go, port 8080) ├── onegov-portal (Next.js, port 3002) ├── onegov-admin (Next.js, port 3001) ├── onegov-web (Next.js, port 3000) ├── postgres (citizen profiles, apps, payments…) ├── redis (cache, queue, sessions) └── minio (uploads, generated PDFs) Edge: └── caddy (auto-TLS, single ingress) Zero external services on the critical path.
The security stack
JWT + TOTP 2FA
Short-lived access tokens, refresh rotation, optional time-based one-time codes for staff.
Server-side RBAC
Citizen / Officer / MDA Admin / Super Admin — enforced on every endpoint, never trusted from the client.
WAF + rate limits
Sentinel mounts a per-IP rate limiter + brute-force protection + a WAF rule engine in front of every route.
Idempotency-Key
Unsafe methods accept Idempotency-Key headers. The middleware + DB unique index together ensure a retry never double-charges.
Document verifier
Every issued document carries a verification_code anyone can confirm at /verify/{code} — minimal, non-PII metadata only.
MDA scoping
An MDA's officers never see another MDA's data. Unknown apps return 404 (not 403), so existence isn't even leaked across boundaries.