""" Migration endpoints: Compliance-Check → Customer Banner / Documents. After a /compliance/agent/compliance-check run finishes, the user can migrate the extracted CMP vendor list + extracted profile into: - their CookieBanner config (admin-compliance /sdk/einwilligungen) - their Document-Generator (Cookie-Policy / VVT / Privacy-Policy) These endpoints are read-only previews — the actual write to a tenant's SDK state is initiated by the frontend with the existing save endpoints (/sdk/cookie-banner, /sdk/document-generator). We only return the ready-to-apply payload + flags for manual review. """ from __future__ import annotations import logging from typing import Any from fastapi import APIRouter, HTTPException, Query from compliance.services.compliance_audit_log import ( get_check_payload, get_check_run, ) from compliance.services.migration_to_banner import build_banner_config from compliance.services.migration_to_document import build_document_prefills logger = logging.getLogger(__name__) router = APIRouter(prefix="/compliance/agent/migration", tags=["agent-migration"]) def _load_check_context(check_id: str) -> tuple[list[dict], dict, dict]: """Return (vendors, profile, run_meta) for a stored check_id.""" # Prefer the in-memory job cache (richest data, before sidecar trim). try: from compliance.api.agent_compliance_check_routes import ( _compliance_check_jobs, ) job = _compliance_check_jobs.get(check_id) except Exception: job = None if job and (result := job.get("result")): return ( result.get("cmp_vendors") or [], result.get("extracted_profile") or {}, { "site_name": result.get("business_profile", {}).get("siteName", ""), "base_domain": result.get("business_profile", {}).get("baseUrl", ""), }, ) payload = get_check_payload(check_id) if payload is None: raise HTTPException(404, f"Unknown check_id '{check_id}'") run = get_check_run(check_id) or {} return ( payload.get("vendors") or [], payload.get("profile") or {}, { "site_name": run.get("site_name", ""), "base_domain": run.get("base_domain", ""), }, ) @router.get("/{check_id}/banner-preview") async def preview_banner_migration( check_id: str, language: str = Query("de", pattern="^(de|en)$"), ) -> dict[str, Any]: """Build a CookieBannerConfig from a finished compliance-check run. Returns: { config, flags, summary } — the frontend renders a diff against the tenant's current banner and lets the user accept. """ vendors, _profile, meta = _load_check_context(check_id) return build_banner_config( vendors=vendors, site_name=meta["site_name"] or meta["base_domain"], privacy_policy_url="", language=language, ) @router.get("/{check_id}/document-preview") async def preview_document_migration(check_id: str) -> dict[str, Any]: """Return pre-fills for cookie_policy / vvt_register / privacy_policy.""" vendors, profile, meta = _load_check_context(check_id) prefills = build_document_prefills( vendors=vendors, extracted_profile={"company_profile": profile} if profile else None, site_name=meta["site_name"] or meta["base_domain"], privacy_policy_url="", ) return { "check_id": check_id, "site_name": meta["site_name"], "base_domain": meta["base_domain"], "vendor_count": len(vendors), "templates": prefills, } @router.get("/{check_id}/summary") async def migration_summary(check_id: str) -> dict[str, Any]: """High-level summary: how many vendors, how many cookies, how many issues.""" vendors, profile, meta = _load_check_context(check_id) banner = build_banner_config( vendors=vendors, site_name=meta["site_name"] or meta["base_domain"], ) return { "check_id": check_id, "site_name": meta["site_name"], "base_domain": meta["base_domain"], "company_name": (profile or {}).get("companyName", ""), "vendor_count": len(vendors), "banner_summary": banner.get("summary"), "available_templates": [ "cookie_policy", "vvt_register", "privacy_policy", ], }