#!/usr/bin/env python3 """ GDPR Article 30 RoPA Report Generator. Generates a formatted Article 30 Records of Processing Activities report in Markdown format suitable for supervisory authority submission. Usage: python generate_ropa_report.py --input ropa.json --output Article30_Register.md python generate_ropa_report.py --input ropa.json --output report.pdf --format pdf """ import argparse import json import sys from datetime import datetime, timezone def format_list(items): """Format a list of items as bullet points.""" if not items: return "*[None specified]*" if isinstance(items, str): return items return "\n".join(f"- {item}" for item in items) def generate_markdown(ropa): """Generate Markdown report from RoPA JSON.""" org = ropa.get("organization", {}) activities = ropa.get("processing_activities", []) lines = [] lines.append("# Article 30 Records of Processing Activities") lines.append("") lines.append(f"**Organization**: {org.get('name', '[Organization Name]')}") lines.append(f"**Controller Contact**: {org.get('controller_contact', '[Contact Details]')}") if org.get('dpo_contact'): lines.append(f"**Data Protection Officer**: {org.get('dpo_contact')}") lines.append(f"**Generated**: {org.get('generated_date', datetime.now(timezone.utc).isoformat())}") lines.append(f"**Total Processing Activities**: {len(activities)}") lines.append("") lines.append("---") lines.append("") for idx, activity in enumerate(activities, 1): lines.append(f"## Processing Activity {idx}: {activity.get('source_file', 'Unnamed Activity')}") lines.append("") # Purposes lines.append("### Purposes of Processing") lines.append(format_list(activity.get('purposes', []))) lines.append("") # Data Subjects lines.append("### Categories of Data Subjects") lines.append(format_list(activity.get('data_subjects', []))) lines.append("") # Personal Data lines.append("### Categories of Personal Data") lines.append(format_list(activity.get('personal_data_categories', []))) lines.append("") # Recipients lines.append("### Categories of Recipients") lines.append(format_list(activity.get('recipients', []))) lines.append("") # Retention lines.append("### Retention Period") retention = activity.get('retention_period', '*[Not specified]*') lines.append(f"{retention}") lines.append("") # International Transfers lines.append("### International Transfers") transfers = activity.get('international_transfers', []) if transfers: lines.append(format_list(transfers)) else: lines.append("*No international transfers*") lines.append("") # Security Measures lines.append("### Technical and Organizational Security Measures") lines.append(format_list(activity.get('security_measures', []))) lines.append("") lines.append("---") lines.append("") # Completion Notes if ropa.get('completion_notes'): lines.append("## Completion Notes") lines.append("") for note in ropa['completion_notes']: lines.append(f"- {note}") lines.append("") # Footer lines.append("---") lines.append("*This document fulfills the requirements of GDPR Article 30 (Records of Processing Activities).*") lines.append("*Controllers must maintain this register and make it available to supervisory authorities upon request.*") return "\n".join(lines) def generate_html(markdown_content): """Convert Markdown to basic HTML.""" html_header = """