Resavi

Trust & Security

Security is built in, not bolted on

Resavi connects customers with service businesses across East Africa. Every layer — from the network edge to the database — is designed so that personal data stays protected, accounts stay in the right hands, and payments flow without compromise.

HTTPS

All endpoints, always

RBAC

Five-role hierarchy

AES-256

Credentials at rest

48 hr

Disclosure response SLA

Infrastructure

Hardened from the network edge inward

Traffic enters through nginx reverse proxies that terminate TLS. Beyond that boundary, all communication happens inside an isolated Docker network with no public route to any service, database, or cache.

TLS Everywhere

All public endpoints are served over HTTPS. nginx handles SSL termination and injects X-Forwarded-Proto: https so every downstream service generates correct secure URLs in its API responses.

TLS 1.2+HSTSHTTP → HTTPS redirect

Network Isolation

Each microservice runs in a private Docker network. There is no public route to any database, message broker, or cache — only the API gateway accepts inbound traffic, and only on the ports it needs.

Docker networkNo direct DB access

Rate Limiting

A Redis-backed token bucket enforces per-IP limits at the gateway. Registration, review creation, and payment initiation carry tighter budgets than read-only endpoints.

Per-IP bucketRedis-backedGraduated limits

Security Response Headers

nginx injects Strict-Transport-Security, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, and Referrer-Policy: strict-origin-when-cross-origin on every response.

HSTSClickjacking protectionMIME sniffing off

Identity & Access

The right person, in the right place

Authentication is delegated to Keycloak, an open-source identity server running on dedicated infrastructure. Authorisation is enforced server-side by the gateway and each individual service — never by the client.

OAuth 2.0 + OpenID Connect

Keycloak issues short-lived, signed JWTs. No passwords travel to application services — only tokens that expire automatically and can be revoked immediately if an account is compromised.

JWT RS256Short-lived tokensInstant revocation

Google Social Login

Users may sign in with Google via Keycloak's Identity Provider federation. The flow is PKCE-enabled and runs entirely through Keycloak — Resavi never sees the user's Google password or access token.

PKCEIDP federationNo Google token stored

Role-Based Access Control

Five roles — Customer, Business Owner, Staff, Admin, Superadmin — form a composite hierarchy in Keycloak. Every service re-validates the caller's roles from the signed token; no endpoint trusts client-supplied claims.

5-tier hierarchyServer-enforcedComposite roles

Service-to-Service Auth

Internal calls between microservices carry a rotating shared secret validated on receipt. No internal endpoint is exposed through the public gateway — internal routes are unreachable from outside the Docker network.

HMAC shared secretNot gateway-routed

CORS Allowlist

The gateway enforces a strict origin allowlist. Only resavi.com, biz.resavi.com, and dashboard.resavi.com — and their staging equivalents — may make cross-origin requests. No wildcard origins.

No wildcardExplicit allowlist

Payments

Payment flows designed to be tamper-proof

Resavi processes payments through established providers. Every inbound payment event is cryptographically verified before any action is taken — a tampered or unsigned webhook is rejected with no side effects.

Webhook Signature Verification

Every inbound payment webhook is verified against an HMAC-SHA256 signature before business logic runs. Unsigned or replayed payloads are rejected at the boundary — no partial state changes occur.

HMAC-SHA256Reject-first policyNo partial state

No Raw Card Storage

Resavi does not store card numbers, CVCs, or expiry dates. Tokenisation and card processing are handled entirely by the payment provider. Resavi stores only the transaction reference.

Tokenised refs onlyReduced PCI scope

Idempotent Event Processing

Payment events are processed with idempotency guards using the outbox pattern. A duplicate webhook from the provider triggers no double-charge, no duplicate fulfillment, and no phantom notifications.

Idempotency keysOutbox pattern

Data Protection

Minimal collection. Deliberate handling.

Resavi collects what is necessary to provide the service. Third-party API keys held on behalf of businesses are encrypted with AES-256 before touching a database — the raw key and the encryption passphrase are never stored together.

Encryption at Rest

Business API credentials are encrypted with AES-256 derived from a secret passphrase held outside the database. The stored row contains only ciphertext — decryption requires both the row and the externally-held key.

AES-256External key store

Isolated Notification Delivery

SMS and email are dispatched via RabbitMQ through a single dedicated notifications service. No other service calls the SMS or email provider directly, so outbound communication has a single, auditable path.

RabbitMQSingle delivery path

Data Minimisation

Each service owns only the data it needs to perform its function. There are no cross-service joins or shared databases — a booking service holds booking records, not user passwords or payment tokens.

Per-service DBNo cross-service joins

Monitoring & Response

Problems surface before customers notice

Every service reports structured errors and warnings to Sentry. Abuse events — rate-limit violations, failed auth attempts — are tagged with IP, path, and method so patterns are visible without combing through raw logs.

Structured Error Tracking

Sentry captures warnings and errors across all services in real time. Each event carries the environment, service name, and request context so engineers can triage without digging through container logs.

SentryStructured tagsAll services

Abuse Visibility

Every 429 Too Many Requests response is forwarded to Sentry with the source IP, endpoint, and method as searchable tags. Repeat offenders are visible as patterns, not buried in access logs.

429 events taggedIP + path indexed

Health Checks

Every service exposes a health endpoint. Docker and the load balancer use these to detect degraded containers and remove them from rotation before they serve broken responses to real users.

Spring ActuatorContainer-levelAuto-removal

Responsible Disclosure

Found a vulnerability?

If you believe you have found a security issue in Resavi, please let us know before disclosing it publicly. We take all reports seriously and commit to acknowledging your message within 48 hours.

Please include a clear description, reproduction steps, and your assessment of the potential impact. We ask that you avoid accessing other users' data, conducting denial-of-service tests, or running automated scanners beyond what is needed to demonstrate the issue. We do not take legal action against researchers acting in good faith.

Report to

info@resavi.com

We aim to respond within 48 hours and resolve critical issues within 7 days of confirmation.