"""Data Breach Response Plan handler (template-based). Generates a data breach incident response plan by filling a comprehensive DOCX template with customer-specific information. Does not require LLM generation — uses pre-written plan sections with variable substitution. """ from __future__ import annotations import os from datetime import datetime from .base_handler import BaseServiceHandler class BreachResponseHandler(BaseServiceHandler): SERVICE_SLUG = "breach-response" SERVICE_NAME = "Data Breach Response Plan" TEMPLATE_NAME = "breach_response_template.docx" REQUIRES_LLM = False async def process(self, order_data: dict) -> list[str]: work_dir = self._make_work_dir() order_number = order_data["name"] template_path = self._get_template_path() docx_filename = self._output_filename(order_number, "docx") docx_path = os.path.join(work_dir, docx_filename) now = datetime.now() variables = { "order_number": order_number, "customer_name": order_data.get("customer_name", ""), "date": now.strftime("%B %d, %Y"), "effective_date": now.strftime("%B %d, %Y"), "service_name": self.SERVICE_NAME, # Company details "company_name": order_data.get("custom_company_legal_name", order_data.get("customer_name", "")), "company_address": order_data.get("custom_company_address", "[ADDRESS]"), "company_phone": order_data.get("custom_contact_phone", "[PHONE]"), "company_email": order_data.get("custom_contact_email", "[EMAIL]"), # Incident response team "irt_lead": order_data.get("custom_irt_lead", "[IRT LEAD]"), "irt_lead_title": order_data.get("custom_irt_lead_title", "[TITLE]"), "irt_lead_phone": order_data.get("custom_irt_lead_phone", "[PHONE]"), "irt_lead_email": order_data.get("custom_irt_lead_email", "[EMAIL]"), "legal_counsel": order_data.get("custom_legal_counsel", "[LEGAL COUNSEL]"), "legal_counsel_phone": order_data.get("custom_legal_counsel_phone", "[PHONE]"), "it_security_lead": order_data.get("custom_it_security_lead", "[IT SECURITY LEAD]"), "communications_lead": order_data.get("custom_communications_lead", "[COMMUNICATIONS LEAD]"), "hr_lead": order_data.get("custom_hr_lead", "[HR LEAD]"), # External contacts "cyber_insurance_carrier": order_data.get("custom_cyber_insurance_carrier", "[CARRIER]"), "cyber_insurance_policy": order_data.get("custom_cyber_insurance_policy", "[POLICY #]"), "forensics_vendor": order_data.get("custom_forensics_vendor", "[FORENSICS VENDOR]"), "pr_firm": order_data.get("custom_pr_firm", "[PR FIRM]"), # Jurisdiction & regulation "state": order_data.get("custom_state", "California"), "notification_deadline_days": order_data.get("custom_notification_deadline", "30"), "ag_notification_threshold": order_data.get("custom_ag_threshold", "500"), "applicable_laws": order_data.get("custom_applicable_breach_laws", "Cal. Civ. Code § 1798.82"), # Infrastructure "total_records": order_data.get("custom_total_records", "[TOTAL RECORDS]"), "data_types": order_data.get("custom_sensitive_data_types", "SSN, financial account numbers, health information"), "primary_systems": order_data.get("custom_primary_systems", "[PRIMARY SYSTEMS]"), } self._fill_template(template_path, variables, docx_path) pdf_path = self._convert_to_pdf(docx_path) return [docx_path, pdf_path]