Security model
This page is the canonical reference for how Relavoi protects credentials, phone numbers, recordings, and tenant data.
Encryption at rest
All sensitive fields are encrypted with AES-256-GCM:
- Phone numbers (
partyA,partyB) insessions.party_a_phone_enc/party_b_phone_enc - SMS bodies in
sms_records.message_text_enc - Call recordings in object storage
Key hierarchy:
KMS Master Key (AWS KMS, region-locked)
-> Tenant KEK (one per tenant, rotated annually)
-> Per-record DEK (envelope-encrypted, stored alongside ciphertext)
The DEK is generated per record and discarded from memory after use. Plaintext phone numbers only ever exist in the Call Router process for the few milliseconds required to issue the dial command to the CPaaS.
Hash lookups use a separate SHA-256 + per-tenant salt column (party_a_phone_hash). This lets the routing layer match incoming callers without decrypting any session.
Encryption in transit
- External: TLS 1.3 only. TLS 1.2 was deprecated in 2025. HSTS preload with
max-age=31536000; includeSubDomains; preload. - Internal: mTLS between every Kubernetes service. Certificates rotated every 24 hours via cert-manager + SPIFFE identities.
- WebSocket: WSS with the same TLS 1.3 ciphers; JWT presented on handshake.
Phone numbers never logged in plaintext
Logging policy is enforced by lint rules and a redaction layer in the logger:
- Any field matching
/\+\d{10,15}/is masked to+234XXXXX5678(last four digits only) - Database query logs use bound parameters, never inline string interpolation
- Crash reports and APM traces redact PII before transmission
If you spot a plaintext MSISDN in any Relavoi log or response, file a security bug at security@relavoi.com — that is a P0.
API key and secret model
Tenants authenticate with an apiKey + apiSecret pair. The key is prefixed rk_live_ and the secret rs_ (for example rk_live_dd38d52e..., rs_e028efcc...).
apiKeyis a SHA-256 hash stored intenants.api_key_hashapiSecretis a bcrypt hash (cost factor 12) stored intenants.api_secret_hash- Neither value is recoverable. Rotation via
POST /v1/auth/rotate-key(OWNER only) issues a new pair and immediately invalidates the old.
The credentials never appear in dashboard URLs, logs, or webhook payloads.
SDKs trade the key+secret for a short-lived JWT (15 min TTL) at startup and refresh transparently. The JWT carries tenantId, tier, and scopes. Tenant-user (dashboard) JWTs carry a different typ discriminator so they cannot be used against SDK endpoints.
NDPR compliance
Relavoi is built around the Nigeria Data Protection Regulation 2019 (and the NDPA 2023):
- Consent for recording: enforced at API layer (see Call recording)
- Data minimization: phone numbers encrypted at rest, hashed for lookup, never logged
- Retention limits: default 90 days for call data, configurable down to 30
- Breach notification: 72-hour notification SLA via
security@relavoi.com - Data Processing Agreements with our telephony sub-processors cover sub-processor obligations
- Right to erasure: tenant-initiated deletion endpoint scrubs all session, call, and recording data within 30 days
For a copy of the NDPR DPA template or our SOC 2 Type II report, contact your account manager.
Abuse prevention
- Per-tier rate limits on session creation (see Rate limits)
- Hard ceilings on concurrent sessions per tenant
- Per-session max call duration default 60 minutes
- Anomaly detection on unusual call-volume patterns triggers a webhook to your security team
- Numbers reported for abuse are quarantined within 10 minutes