Skip to main content

Security & Compliance

Protect your business and customers with comprehensive security measures and ensure compliance with regulatory requirements.

🛡️ Security Overview

Security Principles

Torque follows industry-leading security practices to protect your business:

Data Protection

  • End-to-End Encryption: All data encrypted in transit and at rest
  • Secure Storage: Data stored in enterprise-grade secure facilities
  • Access Controls: Strict access controls and authentication
  • Regular Audits: Continuous security monitoring and testing

Infrastructure Security

  • Cloud Security: Built on secure cloud infrastructure
  • Network Security: Protected network with firewalls and monitoring
  • Physical Security: Secure data centers with 24/7 monitoring
  • Disaster Recovery: Comprehensive backup and recovery systems

🔑 API Security

API Key Management

Key Security Best Practices

Generate Strong Keys

# Use our secure key generation
# Keys are automatically generated with high entropy
# Format: torque_live_64characterstring

Secure Storage

# Environment Variables (Recommended)
export TORQUE_API_KEY="torque_live_your_api_key_here"
export TORQUE_BUSINESS_ID="business_your_business_id"

# Never commit to version control
# .gitignore should include:
.env
*.env
config/secrets.*

Key Rotation

  • Regular Rotation: Rotate keys every 90 days
  • Immediate Rotation: Rotate immediately if compromised
  • Gradual Rollout: Update applications gradually
  • Monitor Usage: Watch for unusual API activity

Key Permissions

Permission Levels

  • Read Only: View orders, analytics, customer data
  • Write Access: Create checkout links, manage orders
  • Admin Access: Full account management (use sparingly)

Access Control

// Example: Role-based API access
const apiPermissions = {
'analytics': ['read'],
'orders': ['read', 'write'],
'webhooks': ['read', 'write'],
'business': ['read', 'write', 'admin']
};

function checkPermission(resource, action) {
const permissions = apiPermissions[resource] || [];
return permissions.includes(action);
}

Request Security

HTTPS Enforcement

  • Always Use HTTPS: All API requests must use HTTPS
  • Certificate Validation: Verify SSL certificates
  • TLS 1.2+: Use modern TLS versions only

Request Validation

// Validate all input data
function validateCheckoutRequest(data) {
const errors = [];

// Required fields
if (!data.businessId) errors.push('Business ID is required');
if (!data.cart?.items?.length) errors.push('Cart must contain items');
if (!data.customerData?.email) errors.push('Customer email is required');

// Data format validation
if (data.cart?.items) {
data.cart.items.forEach((item, index) => {
if (!item.productId) errors.push(`Item ${index}: Product ID required`);
if (!item.quantity || item.quantity < 1) errors.push(`Item ${index}: Valid quantity required`);
if (!item.price || item.price <= 0) errors.push(`Item ${index}: Valid price required`);
});
}

return errors;
}

Rate Limiting

// Implement rate limiting
class RateLimiter {
constructor(maxRequests = 1000, windowMs = 60000) {
this.maxRequests = maxRequests;
this.windowMs = windowMs;
this.requests = new Map();
}

isAllowed(clientId) {
const now = Date.now();
const clientRequests = this.requests.get(clientId) || [];

// Remove old requests
const recentRequests = clientRequests.filter(time => now - time < this.windowMs);

if (recentRequests.length >= this.maxRequests) {
return false;
}

// Add current request
recentRequests.push(now);
this.requests.set(clientId, recentRequests);

return true;
}
}

🔗 Webhook Security

Webhook Verification

Signature Verification

HMAC SHA256 Verification

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}

// Usage in webhook handler
app.post('/webhooks/torque', (req, res) => {
const signature = req.headers['x-torque-signature'];
const payload = req.body;

if (!verifyWebhookSignature(payload, signature, webhookSecret)) {
return res.status(401).json({ error: 'Invalid signature' });
}

// Process webhook...
});

PHP Verification

<?php
function verifyWebhookSignature($payload, $signature, $secret) {
$expectedSignature = hash_hmac('sha256', $payload, $secret);
return hash_equals($expectedSignature, $signature);
}

// Usage
$signature = $_SERVER['HTTP_X_TORQUE_SIGNATURE'] ?? '';
$payload = file_get_contents('php://input');

if (!verifyWebhookSignature($payload, $signature, $webhookSecret)) {
http_response_code(401);
echo json_encode(['error' => 'Invalid signature']);
exit;
}
?>

Python Verification

import hmac
import hashlib

def verify_webhook_signature(payload, signature, secret):
expected_signature = hmac.new(
secret.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
).hexdigest()

return hmac.compare_digest(expected_signature, signature)

# Usage
@app.route('/webhooks/torque', methods=['POST'])
def webhook():
signature = request.headers.get('X-Torque-Signature', '')
payload = request.get_data(as_text=True)

if not verify_webhook_signature(payload, signature, webhook_secret):
return jsonify({'error': 'Invalid signature'}), 401

# Process webhook...

Webhook Security Best Practices

Endpoint Security

  • HTTPS Only: Require HTTPS for all webhook endpoints
  • Authentication: Implement additional authentication if needed
  • IP Whitelisting: Restrict webhook sources if possible
  • Request Validation: Validate all webhook data

Error Handling

// Secure error handling
app.post('/webhooks/torque', async (req, res) => {
try {
// Verify signature first
const signature = req.headers['x-torque-signature'];
if (!verifyWebhookSignature(req.body, signature, webhookSecret)) {
return res.status(401).json({ error: 'Unauthorized' });
}

// Process webhook
await processWebhook(req.body);

// Return success
res.json({ success: true });
} catch (error) {
// Log error securely (don't expose sensitive data)
console.error('Webhook processing error:', {
timestamp: new Date().toISOString(),
error: error.message,
stack: error.stack
});

// Return generic error
res.status(500).json({ error: 'Internal server error' });
}
});

🔒 Data Security

Customer Data Protection

PII Handling

  • Data Minimization: Only collect necessary data
  • Encryption: Encrypt sensitive data at rest
  • Access Control: Limit access to customer data
  • Data Retention: Implement data retention policies

Secure Data Storage

// Example: Secure customer data handling
class CustomerDataManager {
constructor(encryptionKey) {
this.encryptionKey = encryptionKey;
}

encryptCustomerData(data) {
// Encrypt sensitive fields
const sensitiveFields = ['email', 'phone', 'address'];
const encrypted = { ...data };

sensitiveFields.forEach(field => {
if (data[field]) {
encrypted[field] = this.encrypt(data[field]);
}
});

return encrypted;
}

decryptCustomerData(encryptedData) {
// Decrypt sensitive fields
const sensitiveFields = ['email', 'phone', 'address'];
const decrypted = { ...encryptedData };

sensitiveFields.forEach(field => {
if (encryptedData[field]) {
decrypted[field] = this.decrypt(encryptedData[field]);
}
});

return decrypted;
}
}

Payment Data Security

PCI Compliance

  • No Payment Storage: Never store payment card data
  • Tokenization: Use payment tokens when possible
  • Secure Transmission: Encrypt all payment data in transit
  • Access Logging: Log all access to payment information

Secure Payment Handling

// Example: Secure payment processing
class PaymentProcessor {
constructor() {
this.paymentGateway = new SecurePaymentGateway();
}

async processPayment(paymentData) {
try {
// Validate payment data
this.validatePaymentData(paymentData);

// Process payment securely
const result = await this.paymentGateway.process(paymentData);

// Log payment attempt (no sensitive data)
this.logPaymentAttempt({
amount: paymentData.amount,
currency: paymentData.currency,
status: result.status,
timestamp: new Date().toISOString()
});

return result;
} catch (error) {
// Log error securely
this.logPaymentError(error);
throw error;
}
}

validatePaymentData(data) {
// Validate payment data without exposing sensitive information
if (!data.amount || data.amount <= 0) {
throw new Error('Invalid payment amount');
}

if (!data.currency) {
throw new Error('Payment currency required');
}
}
}

📋 Compliance Requirements

GDPR Compliance

Data Protection Principles

  • Lawful Processing: Process data only with legal basis
  • Purpose Limitation: Use data only for specified purposes
  • Data Minimization: Collect only necessary data
  • Accuracy: Keep data accurate and up-to-date
  • Storage Limitation: Don't keep data longer than needed
  • Integrity & Confidentiality: Protect data security

Customer Rights

  • Right to Access: Provide data access upon request
  • Right to Rectification: Allow data correction
  • Right to Erasure: Delete data upon request
  • Right to Portability: Export data in standard format
  • Right to Object: Allow processing objections
  • Right to Restriction: Limit data processing

Implementation

// Example: GDPR compliance implementation
class GDPRCompliance {
constructor() {
this.dataRetentionDays = 365; // 1 year retention
}

async handleDataRequest(customerId, requestType) {
switch (requestType) {
case 'access':
return await this.provideDataAccess(customerId);
case 'rectification':
return await this.rectifyData(customerId);
case 'erasure':
return await this.eraseData(customerId);
case 'portability':
return await this.exportData(customerId);
default:
throw new Error('Invalid request type');
}
}

async provideDataAccess(customerId) {
const customerData = await this.getCustomerData(customerId);
return {
personalData: customerData.personal,
processingPurposes: ['order_processing', 'customer_support'],
dataRetention: this.dataRetentionDays,
rights: ['access', 'rectification', 'erasure', 'portability']
};
}

async eraseData(customerId) {
// Implement data erasure
await this.anonymizeCustomerData(customerId);
await this.logDataErasure(customerId);
return { success: true, message: 'Data erased successfully' };
}
}

CCPA Compliance

California Privacy Rights

  • Right to Know: What personal information is collected
  • Right to Delete: Request data deletion
  • Right to Opt-Out: Opt out of data sales
  • Non-Discrimination: Equal service regardless of privacy choices

Implementation

// Example: CCPA compliance
class CCPACompliance {
constructor() {
this.privacyNotice = this.getPrivacyNotice();
}

async handleCCPARequest(customerId, requestType) {
switch (requestType) {
case 'know':
return await this.provideDataInventory(customerId);
case 'delete':
return await this.deleteCustomerData(customerId);
case 'opt-out':
return await this.optOutOfDataSales(customerId);
default:
throw new Error('Invalid CCPA request type');
}
}

async provideDataInventory(customerId) {
const dataInventory = await this.getDataInventory(customerId);
return {
categories: dataInventory.categories,
sources: dataInventory.sources,
purposes: dataInventory.purposes,
thirdParties: dataInventory.thirdParties
};
}

getPrivacyNotice() {
return {
dataCollection: ['identifiers', 'commercial', 'internet'],
dataUse: ['order_processing', 'customer_support', 'analytics'],
dataSharing: ['payment_processors', 'shipping_partners'],
optOutRights: ['data_sales', 'marketing_communications']
};
}
}

🚨 Security Incident Response

Incident Detection

Monitoring & Alerting

// Example: Security monitoring
class SecurityMonitor {
constructor() {
this.alerts = [];
this.thresholds = {
failedLogins: 5,
apiErrors: 100,
suspiciousActivity: 10
};
}

monitorLoginAttempts(userId, success) {
if (!success) {
this.recordFailedLogin(userId);
this.checkFailedLoginThreshold(userId);
}
}

monitorAPIUsage(clientId, endpoint, responseCode) {
if (responseCode >= 400) {
this.recordAPIError(clientId, endpoint, responseCode);
this.checkAPIErrorThreshold(clientId);
}
}

checkFailedLoginThreshold(userId) {
const failedAttempts = this.getFailedLoginCount(userId);
if (failedAttempts >= this.thresholds.failedLogins) {
this.triggerSecurityAlert('Multiple failed login attempts', { userId, attempts: failedAttempts });
this.lockAccount(userId);
}
}

triggerSecurityAlert(type, details) {
const alert = {
type,
details,
timestamp: new Date().toISOString(),
severity: this.calculateSeverity(type, details)
};

this.alerts.push(alert);
this.notifySecurityTeam(alert);
}
}

Incident Response Plan

Response Steps

  1. Detection: Identify security incident
  2. Assessment: Evaluate incident severity
  3. Containment: Limit incident impact
  4. Investigation: Determine root cause
  5. Remediation: Fix security vulnerabilities
  6. Recovery: Restore normal operations
  7. Lessons Learned: Improve security measures

Response Team

// Example: Incident response team structure
const incidentResponseTeam = {
incidentCommander: {
name: 'Security Manager',
responsibilities: ['Overall incident management', 'Communication coordination']
},
technicalLead: {
name: 'Senior Developer',
responsibilities: ['Technical investigation', 'Vulnerability assessment']
},
communicationsLead: {
name: 'PR Manager',
responsibilities: ['Customer communication', 'External reporting']
},
legalAdvisor: {
name: 'Legal Counsel',
responsibilities: ['Compliance requirements', 'Legal obligations']
}
};

🔐 Security Best Practices

Development Security

Code Security

  • Input Validation: Validate all user inputs
  • Output Encoding: Encode output to prevent XSS
  • SQL Injection Prevention: Use parameterized queries
  • Authentication: Implement strong authentication
  • Authorization: Enforce proper access controls

Security Testing

// Example: Security testing framework
class SecurityTester {
constructor() {
this.testResults = [];
}

async runSecurityTests() {
await this.testAuthentication();
await this.testAuthorization();
await this.testInputValidation();
await this.testOutputEncoding();
await this.testSQLInjection();
await this.testXSS();

return this.generateSecurityReport();
}

async testAuthentication() {
// Test authentication bypass attempts
const testCases = [
{ username: '', password: 'test' },
{ username: 'admin', password: '' },
{ username: 'admin', password: 'admin' },
{ username: 'admin', password: 'password' }
];

for (const testCase of testCases) {
const result = await this.testLogin(testCase);
this.testResults.push({
test: 'Authentication',
case: testCase,
result: result.success ? 'FAIL' : 'PASS',
details: result.message
});
}
}

generateSecurityReport() {
const passed = this.testResults.filter(r => r.result === 'PASS').length;
const total = this.testResults.length;
const score = (passed / total) * 100;

return {
score,
passed,
total,
results: this.testResults,
recommendations: this.generateRecommendations()
};
}
}

Operational Security

Access Management

  • Principle of Least Privilege: Grant minimal necessary access
  • Role-Based Access Control: Assign permissions by role
  • Regular Access Reviews: Review access permissions regularly
  • Access Logging: Log all access attempts and actions

Security Monitoring

// Example: Security monitoring dashboard
class SecurityDashboard {
constructor() {
this.metrics = {
failedLogins: 0,
suspiciousActivities: 0,
securityAlerts: 0,
complianceScore: 100
};
}

updateMetrics(event) {
switch (event.type) {
case 'failed_login':
this.metrics.failedLogins++;
break;
case 'suspicious_activity':
this.metrics.suspiciousActivities++;
break;
case 'security_alert':
this.metrics.securityAlerts++;
break;
}

this.updateDashboard();
}

updateDashboard() {
// Update real-time dashboard
this.displayMetrics(this.metrics);
this.checkThresholds(this.metrics);
}

checkThresholds(metrics) {
if (metrics.failedLogins > 10) {
this.triggerHighAlert('High number of failed login attempts');
}

if (metrics.suspiciousActivities > 5) {
this.triggerHighAlert('Multiple suspicious activities detected');
}
}
}

🔗 Next Steps


Need help with security? Contact our security team at security@torque.fi or check our security documentation.