Information Security Policy
Document ID: ISP-001 Version: 1.0 Classification: Internal Effective Date: January 2026 Next Review: July 2026 Owner: Keshless Security Team
1. Policy Statement and Scope
1.1 Purpose
This Information Security Policy establishes the framework for protecting Keshless information assets, systems, and infrastructure from unauthorized access, disclosure, modification, destruction, or disruption. It defines the security controls, procedures, and responsibilities necessary to maintain the confidentiality, integrity, and availability of all information processed by Keshless.
1.2 Scope
This policy applies to:
- All employees, contractors, and third parties with access to Keshless systems
- All information systems, networks, and data processing facilities
- All data processed, stored, or transmitted through Keshless infrastructure
- Mobile applications (User App, Vendor App)
- Web applications (Admin Dashboard)
- API services and integrations
- Cloud infrastructure (GCP)
1.3 Regulatory Framework
Keshless security controls are designed to comply with:
| Regulation | Applicability |
|---|---|
| POPIA (Protection of Personal Information Act) | Data protection for cross-border transactions |
| FATF Recommendations | AML/CFT international standards |
| Eswatini Financial Services Act | Local regulatory requirements |
| PCI DSS (principles) | Payment security standards |
| Central Bank of Eswatini Guidelines | Mobile money regulations |
1.4 Policy Review
This policy shall be reviewed:
- At least semi-annually (every 6 months)
- Following any significant security incident
- When regulatory requirements change
- After major system changes
2. Information Security Governance
2.1 Organizational Structure
┌─────────────────────────────────────────┐
│ Board of Directors │
│ (Ultimate Security Accountability) │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ Chief Executive Officer │
│ (Security Policy Endorsement) │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ Chief Technology Officer (CTO) │
│ (Security Strategy & Budget) │
└──────────────────┬──────────────────────┘
│
┌─────────────┼─────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│Security │ │Compliance│ │ IT Ops │
│ Team │ │ Officer │ │ Team │
└─────────┘ └─────────┘ └─────────┘2.2 Roles and Responsibilities
| Role | Responsibilities |
|---|---|
| Board of Directors | Ultimate accountability for information security; approve security policies |
| CEO | Endorse security policies; allocate resources |
| CTO | Define security strategy; oversee implementation; report to board |
| Security Team | Implement controls; monitor threats; respond to incidents |
| Compliance Officer | Ensure regulatory compliance; conduct audits; manage AML/KYC |
| System Administrators | Maintain secure configurations; apply patches; manage access |
| All Employees | Follow security policies; report incidents; complete training |
2.3 Security Governance Meetings
| Meeting | Frequency | Participants | Purpose |
|---|---|---|---|
| Security Review | Monthly | CTO, Security Team, Compliance | Review incidents, metrics, compliance |
| Risk Assessment | Quarterly | All stakeholders | Identify and prioritize risks |
| Board Security Update | Quarterly | Board, CEO, CTO | Strategic security reporting |
| Incident Review | Post-incident | Relevant teams | Lessons learned, improvements |
3. Access Control Security
3.1 Authentication Mechanisms
3.1.1 Password Security
Implementation: bcrypt with 12 salt rounds
// Password hashing implementation (lib/prisma.ts)
const SALT_ROUNDS = 12;
export async function hashPassword(password: string): Promise<string> {
return bcrypt.hash(password, SALT_ROUNDS);
}
export async function comparePassword(password: string, hash: string): Promise<boolean> {
return bcrypt.compare(password, hash);
}Password Requirements:
- Minimum 8 characters
- Mixed case letters
- At least one number
- At least one special character
- Not matching common password lists
- No reuse of last 5 passwords
3.1.2 JWT Token Authentication
| Token Type | Expiry | Purpose |
|---|---|---|
| Access Token | 7 days | API authentication |
| Refresh Token | 30 days | Token renewal |
Token Structure:
{
"sub": "user_id",
"type": "USER|VENDOR|ADMIN",
"role": "USER|ADMIN|SUPER_ADMIN",
"iat": 1704067200,
"exp": 1704672000
}3.1.3 OTP Verification
Configuration:
- Length: 6 digits
- Expiry: 5 minutes
- Maximum attempts: 3
- Channel: WhatsApp (primary), SMS (fallback)
OTP Purposes (Defined in Schema):
REGISTRATION
PASSWORD_RESET
PHONE_VERIFICATION
TRANSACTION_VERIFICATION
CARD_OPERATION
PIN_RESET
CARD_BLOCK / CARD_UNBLOCK
CARD_RELINK / CARD_LINK
VENDOR_PIN_SETUP
LOGOUT3.2 Role-Based Access Control (RBAC)
3.2.1 User Roles
| Role | Access Level | Capabilities |
|---|---|---|
| USER | End user | Own wallet, transactions, profile |
| ADMIN | Administrative | User management, verifications, monitoring |
| SUPER_ADMIN | Full access | All admin functions, system configuration |
3.2.2 Admin Employee Roles
| Role | Permissions |
|---|---|
| SUPER_ADMIN | All permissions, cannot be restricted |
| ADMIN | Full admin with configurable permissions |
| SUPPORT_AGENT | Customer support focused |
| COMPLIANCE_OFFICER | AML/KYC focused |
| FINANCE_MANAGER | Financial operations focused |
| AUDITOR | Read-only access |
| CUSTOM | Custom permissions |
3.2.3 Vendor Access
| Entity | Access Scope |
|---|---|
| Vendor (Owner) | Full business management, sub-user creation |
| VendorSubUser (Cashier) | Transaction processing, limited dashboard |
3.3 API Key Authentication
For vendor integrations:
| Field | Description |
|---|---|
apiKey | SHA-256 hashed key stored in database |
apiKeyPrefix | First 16 characters for display/identification |
ipWhitelist | Allowed IP addresses (array) |
status | ACTIVE, REVOKED, EXPIRED |
expiresAt | Optional expiration date |
lastUsedAt | Usage tracking |
Authentication Flow:
- Client sends
X-API-Keyheader - Server extracts prefix, finds integration record
- Verify full key hash matches stored hash
- Check IP against whitelist
- Verify status is ACTIVE and not expired
- Update
lastUsedAtandrequestCount
3.4 Session Management
Security Measures:
- JWT tokens are stateless (no server-side session storage)
- Token rotation on refresh
- Immediate invalidation on logout
- OTP required for sensitive operations
- Device fingerprinting for anomaly detection
4. Cryptographic Controls
4.1 Encryption Standards
| Purpose | Algorithm | Key Size | Implementation |
|---|---|---|---|
| Password Hashing | bcrypt | 12 rounds | Application layer |
| Secrets Backup | AES-256-GCM | 256-bit | Backup service |
| Audit Log Integrity | SHA-256 | 256-bit | Hash chaining |
| Data in Transit | TLS 1.3 | 256-bit | Cloud Run / Load Balancer |
| Database at Rest | AES-256 | 256-bit | Cloud SQL default |
4.2 Key Management
4.2.1 Secrets Encryption
Backup Encryption Process:
// AES-256-GCM encryption for secrets backup
const algorithm = 'aes-256-gcm';
const key = crypto.createHash('sha256').update(encryptionKey).digest();
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, key, iv);
// authTag ensures integrityKey Storage:
SECRETS_ENCRYPTION_KEYstored in password manager (offline)- Never stored in code repositories
- Rotated annually or after suspected compromise
4.2.2 JWT Secrets
| Secret | Environment Variable | Rotation |
|---|---|---|
| Access Token | JWT_SECRET | Annually |
| Refresh Token | JWT_REFRESH_SECRET | Annually |
4.3 Audit Log Integrity
Hash Chain Implementation:
Each audit log entry includes:
hashPrevious: SHA-256 hash of previous entryhashCurrent: SHA-256 hash of current entry
This creates an immutable chain where any tampering is detectable.
Entry 1: hashCurrent = SHA-256(data1)
Entry 2: hashPrevious = Entry1.hashCurrent, hashCurrent = SHA-256(data2 + hashPrevious)
Entry 3: hashPrevious = Entry2.hashCurrent, hashCurrent = SHA-256(data3 + hashPrevious)5. Network Security
5.1 Infrastructure Architecture
Cloud Provider: Google Cloud Platform (GCP) Region: europe-west1 (Belgium)
Internet
│
▼
┌─────────────────────┐
│ Cloud Load Balancer │ ← TLS 1.3 termination
│ (Global HTTPS LB) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Cloud Run │ ← Auto-scaling, containerized
│ (keshless-api) │
└──────────┬──────────┘
│
┌──────┴──────┐
│ │
┌───▼───┐ ┌────▼────┐
│Cloud │ │ GCP │
│ SQL │ │ GCS │
│(Postgres)│ │ (Storage) │
└───────┘ └──────────┘5.2 Network Segmentation
| Network Zone | Components | Access |
|---|---|---|
| Public | Load Balancer | Internet-facing |
| Application | Cloud Run | Internal + LB |
| Data | Cloud SQL | VPC Connector only |
| Storage | GCS | Service account authenticated |
5.3 Rate Limiting
Standard Rate Limits:
| Endpoint Category | Limit | Window |
|---|---|---|
| General API | 100 requests | 15 minutes |
| Authentication | 10 requests | 15 minutes |
| OTP Requests | 5 requests | 15 minutes |
| Transaction | 50 requests | 15 minutes |
Extreme Rate Limiting (Emergency Control):
When RATE_LIMIT_EXTREME is activated:
- All endpoints: 10 requests per minute
- Used for DDoS protection
5.4 Firewall Rules
Cloud SQL:
- Public IP: 34.22.177.12
- Authorized networks only (Cloud Run, admin IPs)
- SSL required for connections
GCS Storage:
- Access via service account only
- Private buckets (public-access-prevention)
- All documents accessed via signed URLs (15-min expiry for KYC)
6. Application Security
6.1 Secure Development Practices
Input Validation:
- All inputs validated using Joi schemas
- Type checking with TypeScript
- SQL injection prevented by Prisma ORM
- XSS prevented by output encoding
Example Validation Schema:
const createUserSchema = Joi.object({
phoneNumber: Joi.string().pattern(/^\+268[0-9]{8}$/).required(),
password: Joi.string().min(8).required(),
firstName: Joi.string().max(100).required(),
lastName: Joi.string().max(100).required(),
});6.2 API Security
Security Headers:
X-Content-Type-Options: nosniffX-Frame-Options: DENYContent-Security-Policy: default-src 'self'Strict-Transport-Security: max-age=31536000
Request Validation:
- Content-Type enforcement
- Request size limits
- Malformed JSON rejection
6.3 Error Handling
Principles:
- Never expose stack traces to clients
- Log detailed errors server-side
- Return generic error messages
- Use error codes for client handling
// Production error response
{
"success": false,
"error": {
"code": "AUTH_FAILED",
"message": "Authentication failed"
}
}
// Internal log: Full stack trace, request details, user context6.4 Dependency Management
- Regular dependency audits (
npm audit) - Automated vulnerability scanning
- Pinned dependency versions
- No use of deprecated packages
7. Data Security
7.1 Data Classification
| Classification | Description | Examples | Handling |
|---|---|---|---|
| Restricted | Highly sensitive PII, financial data | ID numbers, passwords, PINs | Encrypted, minimal access |
| Confidential | Business-sensitive data | Transaction details, KYC status | Access-controlled |
| Internal | General business data | Logs, configurations | Internal use only |
| Public | Non-sensitive information | FAQs, public docs | No restrictions |
7.2 Sensitive Data Fields
User PII (Restricted):
personalIdNumber- National IDdateOfBirth- Date of birthpassword- Hashed passwordwalletPin- Hashed PINidFrontImage,idBackImage,selfieImage- KYC documents
Vendor Sensitive:
businessRegistration- Company registrationtaxNumber- Tax IDpassword- Hashed passwordwalletPin- Hashed PIN
7.3 Data Masking
Display Masking:
- Phone:
+268****2613 - ID Number:
****789123 - Card Number:
****1234
Log Masking:
- Passwords: Never logged
- OTPs: Never logged
- Full PII: Masked in application logs
8. Physical Security
8.1 Cloud Infrastructure
All physical security is managed by cloud providers:
Google Cloud Platform:
- ISO 27001 certified data centers
- SOC 2 Type II compliance
- 24/7 security monitoring
- Biometric access controls
- Fire suppression systems
GCP Cloud Storage:
- Private buckets (europe-west1)
- Signed URLs with expiration
- AES-256 encryption at rest
- Service account authentication
8.2 Administrative Access
- All infrastructure access via secure channels (SSH, VPN)
- Multi-factor authentication required
- Access logging enabled
- Regular access review (quarterly)
9. Incident Response
See Incident Response Plan for detailed procedures.
Quick Reference - Emergency Controls:
| Control | Activation Command |
|---|---|
| SYSTEM_SHUTDOWN | POST /api/admin/emergency/activate |
| DISABLE_ALL_TRANSACTIONS | Body: { "controlType": "disable_all_transactions", "reason": "..." } |
| READ_ONLY_MODE | See IRP-001 for full procedures |
10. Compliance and Audit
10.1 Internal Audits
| Audit Type | Frequency | Scope |
|---|---|---|
| Access Review | Quarterly | User permissions, API keys |
| Configuration Audit | Monthly | Security settings, firewall rules |
| Log Review | Weekly | Security events, anomalies |
| Vulnerability Scan | Monthly | Infrastructure, applications |
10.2 External Audits
| Audit | Frequency | Provider |
|---|---|---|
| Penetration Test | Annually | Third-party security firm |
| Compliance Assessment | Annually | Regulatory auditor |
| Financial Audit | Annually | External auditor |
10.3 Audit Logging
Events Logged:
enum AuditEventType {
JOURNAL_CREATED
JOURNAL_POSTED
JOURNAL_REVERSED
JOURNAL_CANCELLED
BALANCE_UPDATED
RECONCILIATION_COMPLETED
MANUAL_ADJUSTMENT
}Log Retention:
- Audit logs: 7 years
- Application logs: 90 days
- Security events: 7 years
10.4 Regulatory Reporting
| Report | Regulator | Frequency |
|---|---|---|
| AML Compliance | Central Bank of Eswatini | Quarterly |
| SAR Reports | Financial Intelligence Unit | As required |
| Security Incidents | Central Bank | Within 72 hours |
| Annual Compliance | Central Bank | Annually |
11. Training and Awareness
11.1 Security Training Program
| Training | Audience | Frequency |
|---|---|---|
| Security Awareness | All employees | Annually |
| Secure Coding | Developers | Annually |
| Incident Response | IT Team | Quarterly |
| AML/KYC Procedures | Operations | Annually |
| Phishing Awareness | All employees | Quarterly |
11.2 Training Records
All training completion must be documented with:
- Employee name
- Training type
- Completion date
- Assessment score (if applicable)
- Certificate (if applicable)
12. Policy Violations
12.1 Violation Categories
| Category | Examples | Potential Actions |
|---|---|---|
| Minor | Weak password, missed training | Warning, retraining |
| Moderate | Sharing credentials, bypassing controls | Written warning, access review |
| Severe | Data breach, unauthorized access | Termination, legal action |
12.2 Reporting Violations
All security concerns or violations should be reported to:
- Immediate supervisor
- Security Team: security@keshless.app
- Anonymous reporting channel (if available)
Appendix A: Demonstration Procedure
A.1 Access Control Demonstration
For regulatory presentations, demonstrate the following:
1. Authentication Flow:
# Failed login attempt
curl -X POST https://keshless-api-dev.../api/auth/login \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+26812345678", "password": "wrong"}'
# Response: 401 Unauthorized2. OTP Verification:
# Request OTP
curl -X POST https://keshless-api-dev.../api/auth/request-otp \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+26878422613", "purpose": "PHONE_VERIFICATION"}'
# Verify OTP (within 5 minutes, max 3 attempts)
curl -X POST https://keshless-api-dev.../api/auth/verify-otp \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+26878422613", "otp": "123456"}'3. Rate Limiting:
# Trigger rate limit by exceeding 10 auth requests in 15 minutes
for i in {1..15}; do
curl -X POST https://keshless-api-dev.../api/auth/login \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+26812345678", "password": "test"}'
done
# Response after limit: 429 Too Many RequestsA.2 Dashboard Demo
Navigate to /compliance-demo in the admin dashboard to:
- View authentication flow visualization
- Test role-based access permissions
- Demonstrate rate limiting
- Show API key validation with IP whitelisting
Document Control
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | January 2026 | Security Team | Initial release |
Approval:
| Role | Name | Signature | Date |
|---|---|---|---|
| CTO | _____________ | _____________ | _____________ |
| Compliance Officer | _____________ | _____________ | _____________ |
| CEO | _____________ | _____________ | _____________ |