Skip to main content

Security and Compliance

Related docs: Payment Architecture · SDLC/REQUIREMENTS · Roles & Permissions · Fraud Detection


1. PCI-DSS SAQ A Compliance

Pakashop qualifies for PCI-DSS SAQ A (the most reduced scope) because it never collects, processes, transmits, or stores raw card data.

PrincipleImplementation
No raw card dataCard payments redirect to Flutterwave's hosted payment page; Pakashop never sees card numbers, CVV, or expiry
No card data in logsComplianceLogger scrubs PANs matching /\b\d{13,19}\b/ from all log lines
Encrypted transportAll API traffic over TLS 1.2+ (Cloudflare + Nginx with Cloudflare Origin Certificate)
Scope boundaryFlutterwave is the Cardholder Data Environment (CDE); Pakashop is out of scope

Prohibited code patterns:

// NEVER do this — collecting card data on Pakashop
const { cardNumber, cvv, expiry } = req.body;

// Correct — redirect to hosted page
const { redirectUrl } = await FlutterwaveAdapter.createPaymentLink(order);
res.json({ type: 'redirect', redirectUrl });

2. Bank of Zambia (BoZ) NPS Act

Pakashop operates as a marketplace (not a payment service provider), so it does not require a BoZ payment service licence. However, it must comply with the NPS Act through its licensed partners.

2.1 Delayed Settlement (Escrow-Avoidance Model)

Pakashop does not hold customer funds. Instead:

  1. PawaPay or Flutterwave (both BoZ-licensed) collects and holds the funds.
  2. Pakashop instructs disbursement only after delivery confirmation (PIN + digital signature).
  3. The SettlementLedger tracks each order item through HELD → RELEASABLE → PAID_OUT.

This model avoids the need for a BoZ escrow licence while still providing buyer protection.

2.2 Licensed Providers

ProviderLicence TypeAuthority
PawaPayMobile Money Operator / Payment AggregatorBank of Zambia
FlutterwavePayment Service ProviderBank of Zambia (via ZambiaPayments licence)

3. Zambia Data Protection Act 2021

  • Mobile money payments require an explicit consent checkbox: "I confirm that the mobile money wallet is registered in my name and I agree to Pakashop's Terms of Service."
  • Consent is logged with a timestamp in Order.consentGivenAt.
  • Marketing emails require a separate opt-in; transactional emails do not.

3.2 Data Minimisation

  • Phone numbers in logs are masked: +26097*****56.
  • Email addresses in logs are masked: jo***@example.com.
  • Full PAN patterns are scrubbed by regex before any log write.
  • The ComplianceLogger enforces all of the above centrally.
// ComplianceLogger.scrub() strips PII automatically
logger.info({ orderId, phone: complianceLogger.maskPhone(phone) }, 'Payment initiated');

3.3 Data Processor Agreements (DPAs)

Data processor agreements must be in place with:

  • PawaPay (phone numbers shared for payment processing)
  • Flutterwave (email, phone shared for card payment and KYC)
  • Cloudinary (product images and KYC document storage)
  • Sightengine (images analysed for moderation)
  • Resend (email addresses for transactional email)
  • Twilio (phone numbers for SMS/WhatsApp)
  • Middleware.io (logs and traces for observability)

3.4 Breach Notification

Per the Zambia DPA 2021, the Data Controller (Pakashop) must notify the Data Protection Commission within 72 hours of discovering a personal data breach. The incident response process is documented in SDLC/MAINTENANCE.md.

3.5 Data Subject Rights

Pakashop must provide mechanisms for:

  • Access: User can request their personal data via account settings.
  • Rectification: User can update profile data.
  • Erasure: Account deletion removes personal data; anonymises order history for audit trail.
  • Portability: Data export in JSON format (planned feature).

4. General Security Measures

4.1 Authentication and Authorisation

MechanismImplementation
AuthenticationJWT-based; accessToken (24h TTL) + refreshToken (30d)
Session storageRedis session:{sessionId} with rolling expiry
Role enforcementrequireRoles('PLATFORM_ADMIN') middleware on all admin routes
OAuthGoogle OAuth via OAuthService.js; no passwords stored for OAuth users
MFAMandatory for elevated roles; TOTP (speakeasy), email OTP, SMS (Twilio)

4.2 Multi-Factor Authentication (MFA)

Pakashop enforces a strict, robust Multi-Factor Authentication (MFA) system to secure accounts, particularly partner and administrative roles.

4.2.1 Role-Based Enforcement Rules

  • Elevated Roles (Mandatory): Users with the role of PLATFORM_ADMIN, SHOP_OWNER, DELIVERY_AGENT, MODERATOR, FRAUD_ANALYST, FINANCE_ADMIN, or FLEET_MANAGER must enroll in and verify at least one MFA channel. Upon initial registration or login, if MFA is not enabled, the system intercepts the session and issues a restricted mfa_setup token with a 30-minute expiration. The user cannot access protected resources or issue session cookies until MFA setup is completed.
  • Standard Roles (Optional): Users with the role of CUSTOMER, SERVICE_PROVIDER, or SUPPORT_AGENT can optionally enroll in MFA via their profile configuration.

4.2.2 Supported Channels

The system supports three fully redundant verification methods:

  1. Authenticator App (TOTP):

    • Engine: Powered by speakeasy (standard RFC 6238 TOTP) and qrcode for visual provisioning.
    • Security: base32 secrets are encrypted using aes-256-cbc with a SHA-256 derived key (via TOTP_ENCRYPTION_KEY or JWT_SECRET) prior to database storage.
    • Timing: 30-second steps with 1-step clock drift window allowed for latency protection.
  2. Email Verification:

    • Engine: Transactional emails containing 6-digit cryptographically secure numeric codes.
    • Database: Tracked in the EmailOtp database table with limited retry attempts and a 10-minute validity duration.
  3. SMS / WhatsApp:

    • Engine: Powered by Twilio Verify service.
    • Resilience: Integrates strict try-catch handlers to catch Twilio outages or invalid configuration gracefully, raising a custom SMS_SERVICE_UNAVAILABLE error instead of breaking the main API gateway or auth pipeline.

4.2.3 Challenge Tokens and Intermediate State

Partial authorization sessions do not receive cookies. Instead, the backend operates a secure intermediate state machine:

  • Challenge Token: A short-lived JWT token (5-minute expiration) with the mfa_login claim and user metadata.
  • Multi-Method Selection: If a user has multiple active verified channels, they are presented with a method selection screen where they can choose to receive their OTP code.
  • Verification Routing: The POST /api/auth/2fa/verify-login endpoint decodes the challenge token, validates the code against the specific method selected, and initiates the final cookie-based Express session on success.

4.3 Transport Security

  • All traffic served over TLS 1.2+ enforced by Cloudflare (Full Strict mode).
  • Strict-Transport-Security (HSTS) header set with 1-year max-age.
  • Cloudflare WAF blocks OWASP Top 10 attack patterns (SQLi, XSS, path traversal).

4.4 Input Validation

  • All request bodies validated using express-validator or Prisma type constraints.
  • File upload types validated server-side (multer + MIME type check) before Cloudinary upload.
  • Payment amounts are always re-calculated server-side from order items; client-supplied totals are rejected.

4.5 Rate Limiting

Endpoint classLimitWindow
General API1,000 req15 min
Authentication20 req15 min
Payment initiation20 req15 min
Webhook ingestionUnlimited (IP-whitelisted from gateway IPs)

Rate limiting backed by Redis (express-rate-limit with ioredis store).

4.6 CSRF Protection

  • The Express API uses SameSite=Strict cookies for session tokens.
  • API calls from the Next.js frontend include the Authorization: Bearer <token> header; no cookie-based auth on the API layer.

4.7 Logging Without PII

All logs route through the ComplianceLogger which applies the following scrubbing rules before writing:

Data typeMasking rule
Phone number+26097*****56 (keep first 5, last 2 digits)
Email addressjo***@example.com (mask local part after first 2 chars)
Credit/debit card PANReplaced with [CARD-REDACTED]
National ID (NRC)12****/10/1 (mask first segment; last 4 digits)

4.8 Webhook Security

ProviderVerification method
PawaPayHMAC-SHA256 over raw request body; secret from PAWAPAY_WEBHOOK_SECRET
Flutterwaveverif-hash header compared to FLUTTERWAVE_SECRET_HASH

Webhook endpoints use express.raw() (not express.json()) so the raw bytes are preserved for HMAC verification before parsing.

4.9 Dependency Security

  • npm audit runs in CI on every pull request.
  • Dependabot alerts are reviewed weekly.
  • Node.js version pinned in .nvmrc; updated quarterly.
  • OWASP ZAP baseline scan runs weekly on staging.

4.10 API Gateway Dual-Key Security

All requests to the gateway must include one of:

HeaderValueUsed By
x-pakashop-keyClient API keyFrontend, mobile apps, external integrations
x-internal-keyInternal service keyMicroservices calling each other
// Gateway middleware
const validateGatewayKey = (req, res, next) => {
const clientKey = req.headers['x-pakashop-key'];
const internalKey = req.headers['x-internal-key'];

if (clientKey === process.env.PAKASHOP_CLIENT_KEY) {
req.keyType = 'external';
return next();
}
if (internalKey === process.env.INTERNAL_API_KEY) {
req.keyType = 'internal';
return next();
}

return res.status(401).json({
success: false,
code: 'GATEWAY_001',
message: 'Invalid or missing API key'
});
};

5. Fraud Detection

Pakashop implements a dedicated fraud detection layer via the pakashop-fraud microservice (port 3006).

5.1 Real-Time Rules Engine

The fraud service evaluates every payment initiation in parallel:

RuleThresholdAction
Velocity>5 payments/hour from same IPFlag for review
Amount Anomaly>3x average order valueFlag for review
Self-DealingBuyer and seller same accountBlock immediately
New DeviceFirst payment from new deviceElevated scrutiny
GeographicPayment from unexpected locationFlag for review

5.2 Risk Scoring

Composite risk score (0-100) based on weighted rule triggers:

  • Score < 30: Pass automatically
  • Score 30-70: Flag for admin review (payment blocked pending review)
  • Score > 70: Block immediately

5.3 Admin Review Queue

Blocked payments appear in the fraud analyst dashboard:

  • FRAUD_ANALYST and PLATFORM_ADMIN roles can review
  • Approve: payment proceeds normally
  • Reject: order cancelled, customer notified
  • All actions logged with traceId correlation

See fraud-detection.md for full details.


6. Content Moderation

All uploaded images pass through the pakashop-moderation microservice (Python, port 3110) which calls Sightengine for automated NSFW/violence detection.

  • Flagged images are hidden from public display pending admin review.
  • MODERATOR and PLATFORM_ADMIN roles can approve/reject/escalate flagged content.
  • KYC documents are hidden by default until explicitly approved.

See content-moderation.md for full details.


7. Role-Based Access Control (RBAC)

Pakashop implements 12 roles with granular permissions:

RoleDescriptionMFA Required
CUSTOMEREnd consumerOptional
SHOP_OWNERApproved vendorMandatory
SERVICE_PROVIDERService vendorOptional
DELIVERY_AGENTDelivery partnerMandatory
PLATFORM_ADMINFull adminMandatory
MODERATORContent moderatorMandatory
FRAUD_ANALYSTFraud reviewerMandatory
FINANCE_ADMINFinancial opsMandatory
SUPPORT_AGENTCustomer supportOptional
SELLERPending vendorN/A
FLEET_MANAGERCourier adminMandatory
SYSTEMAutomated processesN/A

See roles-permissions.md for the full permissions matrix.


For internal use only. Do not distribute outside Pakashop engineering.