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.

The audit hash chain

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 got
Data Protection & Privacy Act 2019

Verify-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.

Sovereign architecture

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.