| name | compliance-patterns |
| description | GDPR data handling, audit logging, data classification, retention policies, and consent management for regulatory compliance. |
Compliance Patterns
Data governance and regulatory compliance patterns for software systems.
Data Classification
enum DataClass {
PUBLIC = 'public',
INTERNAL = 'internal',
CONFIDENTIAL = 'confidential',
RESTRICTED = 'restricted',
}
interface UserRecord {
id: string
email: string
displayName: string
passwordHash: string
dateOfBirth: string
preferences: object
createdAt: Date
}
const ENCRYPTED_FIELDS: Record<string, DataClass> = {
'user.email': DataClass.CONFIDENTIAL,
'user.dateOfBirth': DataClass.RESTRICTED,
'user.ssn': DataClass.RESTRICTED,
'payment.cardNumber': DataClass.RESTRICTED,
}
function shouldEncryptAtRest(fieldPath: string): boolean {
const classification = ENCRYPTED_FIELDS[fieldPath]
return classification === DataClass.RESTRICTED
}
function shouldMaskInLogs(fieldPath: string): boolean {
const classification = ENCRYPTED_FIELDS[fieldPath]
return classification === DataClass.CONFIDENTIAL || classification === DataClass.RESTRICTED
}
Audit Logging
interface AuditEvent {
id: string
timestamp: string
actor: {
id: string
type: 'user' | 'system' | 'admin'
ip?: string
}
action: string
resource: {
type: string
id: string
}
changes?: {
field: string
oldValue: unknown
newValue: unknown
}[]
metadata?: Record<string, unknown>
result: 'success' | 'failure' | 'denied'
reason?: string
}
class AuditLogger {
constructor(private store: AuditStore) {}
async log(: <, | >): <> {
: = {
...event,
: crypto.(),
: ().(),
: event.?.( ({
...c,
: (c.) ? : c.,
: (c.) ? : c.,
})),
}
..(auditEvent)
}
}
() {
(: , : , : ) => {
originalJson = res..(res)
res. = () {
([, , , ].(req.)) {
auditLogger.({
: { : req.?. ?? , : , : req. },
: ,
: { : req..()[], : req.. ?? },
: res. < ? : ,
}).( .(, err))
}
(body)
}
()
}
}
GDPR Data Subject Rights
async function exportUserData(userId: string): Promise<DataExport> {
const user = await db.user.findUnique({ where: { id: userId } })
const orders = await db.order.findMany({ where: { userId } })
const activityLog = await db.activityLog.findMany({ where: { userId } })
const consents = await db.consent.findMany({ where: { userId } })
return {
exportDate: new Date().toISOString(),
subject: { id: userId, email: user?.email },
personalData: {
profile: sanitizeForExport(user),
orders: orders.map(sanitizeForExport),
activity: activityLog,
consents,
},
format: 'JSON',
version: '1.0',
}
}
(): <> {
: = { userId, : (), : [] }
db..({
: { : userId },
: { : , : () }
})
report..({ : , : })
{ count } = db..({ : { userId } })
report..({ : , : , count })
db..({
: { userId },
: { : , : }
})
report..({ : , : })
auditLogger.({
: { : userId, : },
: ,
: { : , : userId },
: ,
})
report
}
Consent Management
interface ConsentRecord {
userId: string
purpose: string
granted: boolean
grantedAt: Date
expiresAt?: Date
source: string
version: string
}
async function checkConsent(userId: string, purpose: string): Promise<boolean> {
const consent = await db.consent.findFirst({
where: {
userId,
purpose,
granted: true,
OR: [
{ expiresAt: null },
{ expiresAt: { gt: new Date() } },
],
}
})
return consent !== null
}
async function sendMarketingEmail(userId: ): <> {
hasConsent = (userId, )
(!hasConsent) {
.()
}
emailService.(userId, marketingTemplate)
}
Retention Policies
const RETENTION_POLICIES: RetentionPolicy[] = [
{ dataType: 'session_logs', retentionDays: 90, action: 'delete' },
{ dataType: 'audit_logs', retentionDays: 2555, action: 'archive' },
{ dataType: 'user_activity', retentionDays: 365, action: 'anonymize' },
{ dataType: 'deleted_accounts', retentionDays: 30, action: 'purge' },
]
async function enforceRetention(): Promise<RetentionReport> {
const report: RetentionReport = { executedAt: new Date(), actions: [] }
for (const policy of RETENTION_POLICIES) {
const cutoffDate = new Date()
cutoffDate.setDate(cutoffDate.getDate() - policy.retentionDays)
count = (policy., cutoffDate, policy.)
report..({
: policy.,
: policy.,
: count,
cutoffDate,
})
}
report
}
Checklist
Anti-Patterns
- Logging PII in application logs (searchable by anyone with log access)
- Hard-deleting without audit trail (no proof of compliance)
- Single "I agree" checkbox for all purposes (GDPR requires granular consent)
- Retaining data indefinitely "just in case" (violates data minimization)
- Consent version not tracked: consent invalidated when terms change
- No data inventory: unable to locate all PII for subject access requests