vt-c-compliance-checklist¶
GDPR, SOC2, and security compliance patterns for B2B SaaS applications. Activates when discussing data handling, privacy, audit logging, or compliance requirements.
Plugin: core-standards
Category: Security & Compliance
Command: /vt-c-compliance-checklist
Compliance Checklist¶
This skill provides technical implementation guidance for common B2B SaaS compliance requirements.
When This Skill Activates¶
- Implementing user data handling
- Building audit logging
- Discussing data retention or deletion
- Working on authentication/authorization
- Security review or compliance audit
GDPR Technical Requirements¶
1. Right to Access (Data Export)¶
Users must be able to export all their personal data.
// API endpoint for data export
app.get('/api/user/data-export', async (req, res) => {
const userId = req.user.id;
const userData = {
profile: await db.user.findUnique({ where: { id: userId } }),
preferences: await db.preferences.findMany({ where: { userId } }),
activityLog: await db.activityLog.findMany({ where: { userId } }),
// Include ALL user data across all tables
};
// Return as downloadable JSON
res.setHeader('Content-Disposition', 'attachment; filename=my-data.json');
res.json(userData);
});
2. Right to Erasure (Data Deletion)¶
Users must be able to request deletion of their data.
// Soft delete with scheduled hard delete
async function deleteUserData(userId: string) {
// 1. Soft delete user record
await db.user.update({
where: { id: userId },
data: {
deletedAt: new Date(),
email: `deleted-${userId}@deleted.local`, // Anonymize
name: 'Deleted User'
}
});
// 2. Schedule hard delete after retention period
await queue.add('hard-delete-user', { userId }, {
delay: 30 * 24 * 60 * 60 * 1000 // 30 days
});
// 3. Audit log the deletion request
await auditLog('user_deletion_requested', { userId });
}
3. Data Minimization¶
Only collect data that's necessary.
// ❌ OVER-COLLECTION
interface UserRegistration {
email: string;
password: string;
dateOfBirth: Date; // Not needed
phoneNumber: string; // Not needed
address: string; // Not needed
}
// ✅ MINIMAL COLLECTION
interface UserRegistration {
email: string;
password: string;
// Only collect additional data when needed for features
}
4. Consent Management¶
Track consent for data processing.
interface ConsentRecord {
userId: string;
purpose: 'marketing' | 'analytics' | 'product_updates';
granted: boolean;
grantedAt: Date;
ipAddress: string;
userAgent: string;
}
// Always check consent before processing
async function sendMarketingEmail(userId: string) {
const consent = await db.consent.findFirst({
where: { userId, purpose: 'marketing', granted: true }
});
if (!consent) {
throw new Error('Marketing consent not granted');
}
// Proceed with email
}
SOC 2 Technical Controls¶
1. Audit Logging¶
Log all security-relevant events.
interface AuditLogEntry {
timestamp: Date;
eventType: string;
userId: string | null;
tenantId: string;
resourceType: string;
resourceId: string;
action: 'create' | 'read' | 'update' | 'delete';
ipAddress: string;
userAgent: string;
outcome: 'success' | 'failure';
metadata: Record<string, unknown>;
}
// Events that MUST be logged
const REQUIRED_AUDIT_EVENTS = [
'user_login',
'user_logout',
'user_login_failed',
'password_change',
'permission_change',
'data_export',
'data_deletion',
'admin_action',
'api_key_created',
'api_key_revoked',
'settings_changed',
];
2. Access Control¶
Implement role-based access control.
// Define permissions
const PERMISSIONS = {
'user:read': ['admin', 'manager', 'user'],
'user:write': ['admin', 'manager'],
'user:delete': ['admin'],
'billing:read': ['admin', 'billing'],
'billing:write': ['admin'],
} as const;
// Check permission before action
function requirePermission(permission: keyof typeof PERMISSIONS) {
return (req: Request, res: Response, next: NextFunction) => {
const userRole = req.user.role;
if (!PERMISSIONS[permission].includes(userRole)) {
auditLog('permission_denied', {
userId: req.user.id,
permission,
outcome: 'failure'
});
return res.status(403).json({ error: 'Forbidden' });
}
next();
};
}
3. Encryption¶
Encrypt sensitive data at rest and in transit.
// At-rest encryption for sensitive fields
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';
class EncryptedField {
private key = Buffer.from(process.env.ENCRYPTION_KEY!, 'hex');
encrypt(plaintext: string): string {
const iv = randomBytes(16);
const cipher = createCipheriv('aes-256-gcm', this.key, iv);
const encrypted = Buffer.concat([
cipher.update(plaintext, 'utf8'),
cipher.final()
]);
const authTag = cipher.getAuthTag();
return Buffer.concat([iv, authTag, encrypted]).toString('base64');
}
decrypt(ciphertext: string): string {
const data = Buffer.from(ciphertext, 'base64');
const iv = data.subarray(0, 16);
const authTag = data.subarray(16, 32);
const encrypted = data.subarray(32);
const decipher = createDecipheriv('aes-256-gcm', this.key, iv);
decipher.setAuthTag(authTag);
return decipher.update(encrypted) + decipher.final('utf8');
}
}
// Use for PII storage
const encryptedSSN = encryptedField.encrypt(user.ssn);
4. Session Management¶
Secure session handling.
const SESSION_CONFIG = {
// Maximum session duration
maxAge: 8 * 60 * 60 * 1000, // 8 hours
// Idle timeout
idleTimeout: 30 * 60 * 1000, // 30 minutes
// Require re-auth for sensitive actions
sensitiveActionTimeout: 5 * 60 * 1000, // 5 minutes
// Cookie settings
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict' as const,
}
};
// Force re-auth for sensitive actions
async function requireRecentAuth(req: Request) {
const lastAuth = req.session.lastAuthAt;
const now = Date.now();
if (now - lastAuth > SESSION_CONFIG.sensitiveActionTimeout) {
throw new Error('Please re-authenticate for this action');
}
}
Compliance Checklist¶
Before Launch¶
- [ ] Data Inventory - Document all personal data collected
- [ ] Privacy Policy - Published and linked from signup
- [ ] Consent Mechanism - Users can grant/revoke consent
- [ ] Data Export - Users can download their data
- [ ] Data Deletion - Users can request deletion
- [ ] Audit Logging - All security events logged
- [ ] Access Control - RBAC implemented
- [ ] Encryption - Sensitive data encrypted at rest
- [ ] HTTPS Only - All traffic encrypted in transit
- [ ] Session Security - Proper session management
- [ ] Password Policy - Strong password requirements
- [ ] MFA Support - Multi-factor auth available
Periodic Review¶
- [ ] Review access logs for anomalies
- [ ] Audit user permissions
- [ ] Test data export functionality
- [ ] Test data deletion functionality
- [ ] Review and rotate encryption keys
- [ ] Update dependencies for security patches
- [ ] Conduct penetration testing
- [ ] Review third-party integrations
Data Retention¶
Define and enforce retention periods:
const RETENTION_PERIODS = {
// Active data
user_data: 'until_deletion_requested',
// Audit logs (compliance requirement)
audit_logs: '7_years',
// Session data
sessions: '30_days',
// Analytics (anonymized)
analytics: '2_years',
// Soft-deleted data
deleted_users: '30_days',
};
// Scheduled job to enforce retention
async function enforceRetention() {
// Delete expired audit logs
const auditCutoff = subYears(new Date(), 7);
await db.auditLog.deleteMany({
where: { createdAt: { lt: auditCutoff } }
});
// Hard delete soft-deleted users
const deletionCutoff = subDays(new Date(), 30);
await db.user.deleteMany({
where: { deletedAt: { lt: deletionCutoff } }
});
}