UK Tech Compliance Tutorial: How to Implement GDPR-Compliant Consent & Audit Logs in Your Backend
Under the UK GDPR and Data Protection Act 2018, user consent must be freely given, specific, informed, and unambiguous. Moreover, as developers, we must be able to demonstrate compliance on demand through immutable records.


Here is how to design a clean, developer-friendly backend pattern to manage consent and maintain audit trails.


Step 1: Define Explicit Schema for Consent State
Avoid storing consent as a simple boolean (is_agreed: true). Instead, record the exact version, purpose, timestamp, and IP/User-Agent context.


TypeScript
// Example TypeScript interface for User Consent Record
interface UserConsent {
userId: string;
consentType: 'marketing_email' | 'analytics_cookies' | 'third_party_sharing';
status: 'GRANTED' | 'WITHDRAWN';
policyVersion: string; // e.g., 'v2.1'
timestamp: string; // ISO 8601 UTC timestamp
ipAddress: string; // Anonymized/hashed IP for audit proof
}
Step 2: Implement an Idempotent API Endpoint
Create a dedicated API endpoint that updates user preferences while atomically writing to an immutable append-only audit trail table.


JavaScript
// Middleware / API Route Concept (Express/Node.js)
app.post('/api/v1/user/consent', async (req, res) => {
const { userId, consentType, status, policyVersion } = req.body;

if (!['GRANTED', 'WITHDRAWN'].includes(status)) {
return res.status(400).json({ error: 'Invalid consent status' });
}


// 1. Update user profile state
await db.users.update(userId, { [`consents.${consentType}`]: status });


// 2. Write immutable event to audit log table
await db.consentAuditLogs.insert({
logId: crypto.randomUUID(),
userId,
consentType,
status,
policyVersion,
timestamp: new Date().toISOString(),
ipHash: hashIP(req.ip) // Hash IP to balance auditability with privacy
});


return res.status(200).json({ message: 'Consent recorded successfully' });
});
Step 3: Enforce "Right to be Forgotten" Safely
When executing deletion requests under UK GDPR Article 17, ensure that core PII is deleted or anonymized, but anonymized security/audit records are retained for legal defense obligations without linking back to the individual.


Key Takeaways
Consent requires context: Always log the policyVersion and explicit timestamp alongside the preference state.


Append-only logs: Keep consent history in a dedicated, append-only table to maintain an immutable paper trail for ICO audits.


Balance retention with privacy: Hash IP addresses and anonymize audit logs when a user executes a "Right to Erasure" request.


CTA
Are you an engineer, tech lead, or founder building software in the UK? Join Techawks UK today!
UK Tech Compliance Tutorial: How to Implement GDPR-Compliant Consent & Audit Logs in Your Backend Under the UK GDPR and Data Protection Act 2018, user consent must be freely given, specific, informed, and unambiguous. Moreover, as developers, we must be able to demonstrate compliance on demand through immutable records. Here is how to design a clean, developer-friendly backend pattern to manage consent and maintain audit trails. Step 1: Define Explicit Schema for Consent State Avoid storing consent as a simple boolean (is_agreed: true). Instead, record the exact version, purpose, timestamp, and IP/User-Agent context. TypeScript // Example TypeScript interface for User Consent Record interface UserConsent { userId: string; consentType: 'marketing_email' | 'analytics_cookies' | 'third_party_sharing'; status: 'GRANTED' | 'WITHDRAWN'; policyVersion: string; // e.g., 'v2.1' timestamp: string; // ISO 8601 UTC timestamp ipAddress: string; // Anonymized/hashed IP for audit proof } Step 2: Implement an Idempotent API Endpoint Create a dedicated API endpoint that updates user preferences while atomically writing to an immutable append-only audit trail table. JavaScript // Middleware / API Route Concept (Express/Node.js) app.post('/api/v1/user/consent', async (req, res) => { const { userId, consentType, status, policyVersion } = req.body; if (!['GRANTED', 'WITHDRAWN'].includes(status)) { return res.status(400).json({ error: 'Invalid consent status' }); } // 1. Update user profile state await db.users.update(userId, { [`consents.${consentType}`]: status }); // 2. Write immutable event to audit log table await db.consentAuditLogs.insert({ logId: crypto.randomUUID(), userId, consentType, status, policyVersion, timestamp: new Date().toISOString(), ipHash: hashIP(req.ip) // Hash IP to balance auditability with privacy }); return res.status(200).json({ message: 'Consent recorded successfully' }); }); Step 3: Enforce "Right to be Forgotten" Safely When executing deletion requests under UK GDPR Article 17, ensure that core PII is deleted or anonymized, but anonymized security/audit records are retained for legal defense obligations without linking back to the individual. Key Takeaways Consent requires context: Always log the policyVersion and explicit timestamp alongside the preference state. Append-only logs: Keep consent history in a dedicated, append-only table to maintain an immutable paper trail for ICO audits. Balance retention with privacy: Hash IP addresses and anonymize audit logs when a user executes a "Right to Erasure" request. CTA Are you an engineer, tech lead, or founder building software in the UK? Join Techawks UK today!
0 Comentários 0 Compartilhamentos 10 Visualizações 0 Anterior