| name | gdpr-compliance |
| description | Ensure GDPR compliance for personal data processing in CIA platform with privacy-by-design principles |
| license | Apache-2.0 |
GDPR Compliance Skill
Purpose
Ensure CIA platform complies with EU General Data Protection Regulation (GDPR) requirements for processing personal data of politicians and users.
When to Use
- ✅ Processing personal identifiable information (PII)
- ✅ Implementing user consent mechanisms
- ✅ Handling data subject requests
- ✅ International data transfers
- ✅ Privacy impact assessments
GDPR Principles
1. Lawfulness, Fairness, and Transparency
@Entity
public class DataProcessingRecord {
private String purpose;
private String legalBasis;
private LocalDateTime consentDate;
private boolean consentGiven;
public enum LegalBasis {
CONSENT,
CONTRACT,
LEGAL_OBLIGATION,
VITAL_INTERESTS,
PUBLIC_TASK,
LEGITIMATE_INTERESTS
}
}
2. Purpose Limitation
@Service
public class DataProcessingService {
public void processPersonalData(PersonalData data, String purpose) {
if (!data.getConsentedPurposes().contains(purpose)) {
throw new GDPRViolationException(
"Processing not covered by original consent"
);
}
auditLogger.logDataProcessing(data, purpose);
performProcessing(data, purpose);
}
}
3. Data Minimization
@Entity
public class PoliticianPublicProfile {
private String firstName;
private String lastName;
private String party;
private String district;
}
4. Accuracy
@Service
public class DataAccuracyService {
@Scheduled(cron = "0 0 0 * * *")
public void verifyDataAccuracy() {
List<Politician> politicians = politicianRepository.findAll();
for (Politician p : politicians) {
PoliticianDTO official = riksdagenClient.getPolitician(p.getId());
if (!p.isAccurate(official)) {
p.updateFrom(official);
p.setLastVerified(LocalDateTime.now());
politicianRepository.save(p);
}
}
}
}
5. Storage Limitation
@Entity
public class UserAccount {
private LocalDateTime createdAt;
private LocalDateTime lastLoginAt;
@Column(name = "data_retention_until")
private LocalDateTime retentionUntil;
public void setRetentionPeriod(int years) {
this.retentionUntil = LocalDateTime.now().plusYears(years);
}
}
@Service
public class DataRetentionService {
@Scheduled(cron = "0 0 3 * * *")
public void enforceRetentionPolicies() {
List<UserAccount> expired = userRepository.findByRetentionUntilBefore(LocalDateTime.now());
for (UserAccount user : expired) {
anonymizationService.anonymize(user);
auditLogger.log("Data deleted per retention policy: " + user.getId());
}
}
}
6. Integrity and Confidentiality
@Configuration
public class DataSecurityConfig {
@Bean
public BytesEncryptor piiEncryptor() {
String key = System.getenv("PII_ENCRYPTION_KEY");
String salt = System.getenv("PII_ENCRYPTION_SALT");
return Encryptors.stronger(key, salt);
}
}
Data Subject Rights Implementation
Right to Access (Article 15)
@RestController
@RequestMapping("/api/gdpr")
public class GDPRController {
@GetMapping("/data-export")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<DataExport> exportUserData(
@AuthenticationPrincipal UserDetails user) {
DataExport export = gdprService.generateDataExport(user.getUsername());
auditLogger.logDataSubjectRequest("ACCESS", user.getUsername());
return ResponseEntity.ok(export);
}
}
@Service
public class GDPRService {
public DataExport generateDataExport(String userId) {
DataExport export = new DataExport();
export.setPersonalInfo(userRepository.findById(userId));
export.setActivityLog(activityRepository.findByUserId(userId));
export.setPreferences(preferencesRepository.findByUserId(userId));
export.setProcessingRecords(processingRepository.findByUserId(userId));
return export;
}
}
Right to Erasure (Article 17)
@DeleteMapping("/data")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<Void> deleteUserData(
@AuthenticationPrincipal UserDetails user,
@RequestBody DeletionRequest request) {
if (!gdprService.canDelete(user.getUsername(), request.getReason())) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
gdprService.eraseUserData(user.getUsername());
auditLogger.logDataSubjectRequest("ERASURE", user.getUsername());
return ResponseEntity.noContent().build();
}
Right to Data Portability (Article 20)
@GetMapping("/data-export/json")
public ResponseEntity<byte[]> exportDataPortable(
@AuthenticationPrincipal UserDetails user) {
DataExport export = gdprService.generateDataExport(user.getUsername());
String json = objectMapper.writeValueAsString(export);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setContentDisposition(
ContentDisposition.attachment()
.filename("user-data-" + user.getUsername() + ".json")
.build()
);
return ResponseEntity.ok()
.headers(headers)
.body(json.getBytes(StandardCharsets.UTF_8));
}
Right to Object (Article 21)
@PostMapping("/object-processing")
public ResponseEntity<Void> objectToProcessing(
@AuthenticationPrincipal UserDetails user,
@RequestBody ObjectionRequest request) {
gdprService.recordObjection(user.getUsername(), request.getProcessingType());
if (request.getProcessingType() == ProcessingType.MARKETING) {
marketingService.unsubscribe(user.getUsername());
}
return ResponseEntity.accepted().build();
}
Privacy by Design
@Service
public class PrivacyByDesignService {
public String pseudonymize(String userId) {
return DigestUtils.sha256Hex(userId + SALT);
}
public void anonymize(User user) {
user.setFirstName("DELETED");
user.setLastName("USER");
user.setEmail("deleted@" + UUID.randomUUID() + ".invalid");
user.setPhone(null);
user.setPersonalId(null);
user.setAnonymized(true);
user.setAnonymizedAt(LocalDateTime.now());
}
}
Consent Management
@Entity
public class ConsentRecord {
@Id
private String id;
private String userId;
@Enumerated(EnumType.STRING)
private ConsentPurpose purpose;
private boolean granted;
private LocalDateTime consentDate;
private LocalDateTime withdrawnDate;
private String consentText;
}
@Service
public class ConsentService {
public void recordConsent(String userId, ConsentPurpose purpose, boolean granted) {
ConsentRecord consent = new ConsentRecord();
consent.setUserId(userId);
consent.setPurpose(purpose);
consent.setGranted(granted);
consent.setConsentDate(LocalDateTime.now());
consent.setConsentText(getConsentText(purpose));
consentRepository.save(consent);
auditLogger.logConsent(userId, purpose, granted);
}
public boolean hasConsent(String userId, ConsentPurpose purpose) {
return consentRepository.findByUserIdAndPurpose(userId, purpose)
.filter(c -> c.isGranted() && c.getWithdrawnDate() == null)
.isPresent();
}
}
Data Protection Impact Assessment (DPIA)
Required when processing involves:
- ✅ Large-scale systematic monitoring
- ✅ Sensitive data processing
- ✅ High risk to rights and freedoms
# DPIA Template for CIA Platform
## Processing Description
- **Purpose**: Political activity monitoring and transparency
- **Data Types**: Names, party affiliation, voting records, financial declarations
- **Data Subjects**: Swedish politicians
- **Legal Basis**: Public task (Article 6(1)(e))
## Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|------|-----------|--------|------------|
| Data breach | Medium | High | Encryption, access controls |
| Unauthorized access | Medium | High | MFA, audit logging |
| Inaccurate data | Low | Medium | Regular verification |
## Compliance Measures
- ✅ Encryption at rest and in transit
- ✅ Access control and authentication
- ✅ Regular security audits
- ✅ Incident response plan
- ✅ Data retention policies
GDPR Compliance Checklist
- ✅ Privacy policy published
- ✅ Cookie consent implemented
- ✅ Data protection officer appointed
- ✅ DPIA completed for high-risk processing
- ✅ Data breach notification procedure
- ✅ International data transfer safeguards
- ✅ Regular compliance audits
Hack23 ISMS Policy References
GDPR Compliance Framework:
All Hack23 ISMS Policies: https://github.com/Hack23/ISMS-PUBLIC
CIA Platform Architecture References
References