feat: pre-launch vs post-launch analysis modes

- Backend: mode field in request, adapts summary tone and email subject
- Pre-launch: "Implementieren Sie X vor Veroeffentlichung"
- Post-launch: "ACHTUNG: Maengel sind oeffentlich sichtbar, sofortige Nachbesserung"
- Frontend: Mode toggle (internes Dokument vs. Live-Website)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-28 14:07:32 +02:00
parent cb5aa2949b
commit 1988274420
3 changed files with 80 additions and 11 deletions

View File

@@ -41,6 +41,7 @@ SDK_HEADERS = {
class AnalyzeRequest(BaseModel):
url: str
recipient: str = "dsb@breakpilot.local"
mode: str = "post_launch" # "pre_launch" or "post_launch"
class FollowUpQuestion(BaseModel):
@@ -97,12 +98,13 @@ async def analyze_url(req: AnalyzeRequest):
esc_level = "E1"
role = ESCALATION_ROLES["E1"]
summary = _build_summary(req.url, classification, assessment, role, findings_str, controls_str)
summary = _build_summary(req.url, classification, assessment, role, findings_str, controls_str, req.mode)
# Step 7: Send notification
mode_label = "INTERNE PRUEFUNG" if req.mode == "pre_launch" else "LIVE-WEBSITE"
email_result = send_email(
recipient=req.recipient,
subject=f"Compliance-Finding: {classification}{req.url[:60]}",
subject=f"[{mode_label}] Compliance-Finding: {classification}{req.url[:60]}",
body_html=f"<div>{summary}</div>",
)
@@ -350,17 +352,27 @@ def _risk_to_escalation(risk_level: str) -> str:
def _build_summary(
url: str, classification: str, assessment: dict, role: str,
findings_str: list[str], controls_str: list[str],
mode: str = "post_launch",
) -> str:
"""Build a German manager summary."""
"""Build a German manager summary, adapted to pre/post-launch context."""
risk = assessment.get("risk_level", "unbekannt")
score = assessment.get("risk_score", 0)
recommendation = assessment.get("recommendation", "")
dsfa = assessment.get("dsfa_recommended", False)
is_live = mode == "post_launch"
findings_text = "\n".join(f"- {f}" for f in findings_str[:5]) if findings_str else "Keine"
controls_text = "\n".join(f"- {c}" for c in controls_str[:5]) if controls_str else "Keine"
mode_header = (
"PRUEFUNG LIVE-WEBSITE — Das Dokument ist bereits oeffentlich zugaenglich."
if is_live else
"INTERNE PRUEFUNG — Das Dokument ist noch nicht veroeffentlicht."
)
parts = [
mode_header,
"",
f"Dokumenttyp: {classification}",
f"Quelle: {url}",
f"Risikobewertung: {risk} ({score}/100)",
@@ -371,6 +383,19 @@ def _build_summary(
"",
f"Erforderliche Massnahmen:\n{controls_text}",
]
if is_live and findings_str:
parts.extend([
"",
"ACHTUNG: Diese Maengel sind bereits oeffentlich sichtbar. "
"Sofortige Nachbesserung empfohlen um Abmahnrisiken zu minimieren.",
])
elif not is_live and controls_str:
parts.extend([
"",
"Empfehlung: Implementieren Sie die erforderlichen Kontrollen vor der Veroeffentlichung.",
])
if recommendation:
parts.extend(["", f"Empfehlung: {recommendation}"])
parts.extend(["", f"Weitere Empfehlung: {recommendation}"])
return "\n".join(parts)