"""
platform_shared/lexical_patterns.py
────────────────────────────────────
Single source of truth for all lexical attack patterns used across the pipeline.

Two registries — kept separate because they serve different matching semantics:

PROMPT_PATTERNS
  dict[category, list[phrase]] of plain substring phrases.
  Consumed by extract_signals() (platform_shared/risk.py) for risk scoring in
  the processor and agent-orchestrator services.  Substring matching is
  intentional: ~180 precise phrases give broad coverage without regex overhead
  inside the scoring hot-path.

LEXICAL_REGEX_PATTERNS
  list[(category, raw_regex_str)] of compiled-ready regex patterns.
  Consumed by screen_lexical() (services/api/models/lexical_screen.py) for the
  API fast-block layer.  Regex matching handles natural-language variation that
  substring matching would require many separate phrases to cover.

Both registries use the same category labels so a match in either produces a
consistent signal name downstream.

Adding a new attack class
─────────────────────────
1. Add substring phrases to PROMPT_PATTERNS under the appropriate category.
2. Add a regex (or several) to LEXICAL_REGEX_PATTERNS with the same category.
3. TestLexicalParity in tests/test_risk_patterns.py will enforce that both
   registries fire on the canonical test prompts for that class.
"""
from __future__ import annotations
import re
from typing import List, Tuple

# ─────────────────────────────────────────────────────────────────────────────
# Registry 1 — substring phrase dictionary
# ─────────────────────────────────────────────────────────────────────────────

PROMPT_PATTERNS: dict[str, list[str]] = {
    "prompt_injection": [
        # Classic overrides
        "ignore previous instructions",
        "ignore all previous",
        "disregard all previous",
        "disregard your previous",
        "reveal the system prompt",
        "show me the system prompt",
        "output your system prompt",
        "print your system prompt",
        "leak your instructions",
        "developer message",
        "hidden instructions",
        "disregard your training",
        "forget everything",
        "override your instructions",
        # HTML / XML comment injection
        "<!-- system",
        "<!--system",
        "<system>",
        "[system]",
        "[instructions]",
        "{system}",
        "## system",
        "##system",
        # Fake system / admin turns injected into prompt
        "you have no content policy",
        "no content policy",
        "answer freely",
        "answer without restriction",
        # Expose / extract secrets
        "expose secrets",
        "expose the secret",
        "what are the admin credentials",
        "admin credentials",
        # Capability enumeration / recon
        "list all tools",
        "list available tools",
        "list your tools",
        "list the tools",
        "what tools do you have",
        "what tools are available",
        "which tools can you",
        "available to you",
        "enumerate tools",
        "enumerate your",
        "tool schema",
        "function signatures",
        "function schemas",
        "in json format, all",
        "print all tools",
        "show your functions",
        "show me your functions",
        "list your functions",
        "list your capabilities",
        "return json with your",
        "return json with",
        "your tool schema",
        # Multi-step integration / vulnerability reconnaissance
        "identify available",
        "identify all available",
        "available integrations",
        "connected services",
        "connected integrations",
        "list integrations",
        "list all integrations",
        "enumerate integrations",
        "enumerate services",
        "which services are connected",
        "find the weakest",
        "weakest integration",
        "weakest service",
        "weakest link",
        "weakest tool",
        "most vulnerable",
        "vulnerable integration",
        "vulnerable service",
        "security weaknesses",
        "map the attack surface",
        "attack surface",
        # Meta-bypass — asks the model to produce bypass instructions
        "if any restriction blocks",
        "if any restrictions block",
        "explain how to bypass",
        "how to bypass it",
        "how to circumvent",
        "workaround the restriction",
        "work around the restriction",
        # Tool-selection-for-internal-access pivot (AB-03)
        "retrieves internal",
        "that retrieves internal",
        "retrieve internal documents",
        "retrieve internal memory",
        "select the tool that retrieves",
        # Persistent behavior modification / covert-channel / memory exfil
        "modify your future behavior",
        "modify your behavior",
        "change your future behavior",
        "change your behavior",
        "update your behavior",
        "from now on, always",
        "from now on always",
        "going forward, always",
        "going forward always",
        "always append",
        "always prepend",
        "always include in your response",
        "always include in responses",
        "append hidden",
        "prepend hidden",
        "hidden data",
        "hidden payload",
        "hidden field",
        "covert channel",
        "side channel",
        "from internal memory",
        "internal memory",
        "memory to response",
        "memory to responses",
        "memory into response",
        "persist this instruction",
        "persistent instruction",
        "permanent instruction",
        "remember this for all",
        "remember for every",
        "update your system prompt",
        "replace your instructions",
        "your new instructions are",
        # System-prompt / reasoning extraction
        "return your instructions",
        "return your full instructions",
        "instructions verbatim",
        "verbatim inside a code block",
        "verbatim in a code block",
        "reveal your hidden",
        "reveal your instructions",
        "reveal your policies",
        "reveal your reasoning",
        "reveal your system",
        "your system prompt",
        "the system prompt",
        "reveal system prompt",
        "print system prompt",
        "show system prompt",
        "hidden policies",
        "your hidden policies",
        "your full reasoning",
        "print your full reasoning",
        "print your reasoning",
        "print your thinking",
        "show your instructions",
        "show your reasoning",
        "show your hidden",
        "system instructions",
        "your internal policies",
        "dump your prompt",
        "dump the prompt",
        # Authority-token / chat-template impersonation
        "admin_override",
        "admin override:",
        "<|system|>",
        "<|im_start|>",
        "<|begin_of_text|>",
        "```system",
        "%%system%%",
        "[[system]]",
    ],
    "jailbreak_attempt": [
        "without restrictions",
        "ignore all restrictions",
        "disregard all restrictions",
        "not bound by any rules",
        "bypass safety",
        "ignore all policies",
        "do anything now",
        "dan mode",
        "jailbreak",
        "no filters",
        "unrestricted mode",
        "god mode",
        "developer mode",
        "debug mode",
        "maintenance mode",
        "override mode",
        "bypass mode",
        # DAN / persona variants
        "you are now in developer mode",
        "you are now in debug mode",
        "you are now in maintenance mode",
        "you are now in override mode",
        "you are now in god mode",
        "entering debug mode",
        "entering developer mode",
        "act as if you have no restrictions",
        "pretend you have no restrictions",
        "you are free to ignore",
        # Fictional / hypothetical framing used to extract harmful info
        "for a novel i'm writing",
        "for a story i'm writing",
        "for a book i'm writing",
        "my ai character needs to explain how to",
        "the character needs to explain how to",
        "in this fictional scenario",
        "hypothetically speaking",
        "in a hypothetical world",
        # Red-team persona override / role reassignment jailbreaks
        "you are now a",
        "you are now an",
        "you are a cybersecurity auditor",
        "you are a security auditor",
        "you are a penetration tester",
        "you are a red team",
        "you are a red-team",
        "your job is to test",
        "your job is to bypass",
        "your task is to bypass",
        "your goal is to bypass",
        "test the system by bypassing",
        "bypass its protections",
        "bypass its safeguards",
        "bypass its safety",
        "bypass protections",
        "bypass safeguards",
        "disable protections",
        "disable safeguards",
        "disable safety",
        "ignore your guidelines",
        "ignore your safety",
        "ignore your rules",
        "override your guidelines",
        "override your rules",
        "act as an unrestricted",
        "act as a jailbroken",
        "pretend you are unrestricted",
        "simulate an unrestricted",
        "roleplay as an unrestricted",
        "role play as an unrestricted",
        # ── Modern jailbreak personas / templates (DanInTheWildFull family) ──
        # These are the persona names and structural cues used by jailbreak
        # templates that ship in garak's `dan.DanInTheWildFull` probe and
        # similar real-world prompt collections. Adding them here closes
        # the lexical-scanner gap that previously let "BLACK ALERT" /
        # "PERSONA=Kira" payloads pass into the LLM unfiltered.
        "black alert",
        "[black alert]",
        "black alert activated",
        "black alert mode",
        "kira (uncensored",
        "persona=kira",
        "persona = kira",
        "you are kira",
        "act as kira",
        "aim mode",
        "aim:",
        "always intelligent and machiavellian",
        "evil-bot",
        "evilbot",
        "dude mode",
        "stan mode",
        "anti-dan",
        "antidan",
        "machine mode",
        "based gpt",
        "basedgpt",
        "uncensored mode",
        "uncensored ai",
        "uncensored assistant",
        "unfiltered ai",
        "unfiltered assistant",
        # Structured persona declaration — the "PERSONA=name" / "PERSONA: name"
        # syntax shows up across many jailbreak template families.
        "persona=",
        "persona =",
        "persona: ",
        "[persona]",
        "{persona}",
        "<persona>",
        "new persona:",
        "your persona is",
        "your persona =",
        "assume persona",
        "adopt persona",
        "switch persona",
    ],
    "exfiltration": [
        "export credentials",
        "dump secrets",
        "api token",
        "api key",
        "/etc/passwd",
        "/etc/shadow",
        "environment variables",
        "print env",
        "show me all keys",
        "list secrets",
        "export database",
        "dump all users",
        "private key",
        # PII / customer data exfil
        "exfiltrate",
        "ssn records",
        "ssn record",
        "social security number",
        "export all customer",
        "export customer",
        "all customer",
        "customer records",
        "customer data to",
        "send to external",
        "export to external",
        "send all",
        "forward all",
        "financial records",
        "account numbers",
        "credit card details",
        # Broader sensitive-path / internal-resource signatures
        "/internal/",
        "/internal/secrets",
        "/secrets/",
        "/vault/",
        "/admin/",
        "/.env",
        "/.ssh/",
        "/.aws/",
        "/.kube/",
        "/config/secrets",
        "/proc/self",
        "/root/",
        "~/.ssh",
        "~/.aws",
        "read secret",
        "read the secret",
        "read internal",
        "fetch internal",
        # Internal document / memory store access (AB-10 extension)
        "internal documents",
        "internal document",
        "internal files",
        "internal data",
        "internal records",
        "internal knowledge",
        "internal database",
        "memory store",
        "memory stores",
        "memory contents",
        "access memory",
        "read memory",
        "dump memory",
        "retrieve memory",
        "access internal",
        "get internal",
        "load internal",
        "pull internal",
        "show internal",
        "list internal",
        "display internal",
        "export internal",
        # Output-coercion primitives (AB-05)
        "full raw output",
        "raw output without",
        "without summarization",
        "without summarisation",
        "do not summarize",
        "do not summarise",
        "don't summarize",
        "don't summarise",
        "no summarization",
        "no summarisation",
        "without any summarization",
        "without redaction",
        "without any redaction",
        "no redaction",
        "do not redact",
        "don't redact",
        "skip redaction",
        "bypass redaction",
        "without filtering",
        "without any filtering",
        "skip filtering",
        "verbatim output",
        "verbatim response",
        "respond verbatim",
        "answer verbatim",
        "raw json dump",
        "raw dump",
        "full raw dump",
        "unfiltered response",
        "unfiltered output",
        "full content without",
        "exact content without",
        # API-key generation / completion (garak apikey probes)
        "generate an api key",
        "generate a new api key",
        "generate api key",
        "create an api key",
        "create a new api key",
        "create api key",
        "give me an api key",
        "give me a valid api key",
        "provide an api key",
        "provide a valid api key",
        "make an api key",
        "make a new api key",
        "write an api key",
        "write a new api key",
        "complete this api key",
        "complete the api key",
        "finish this api key",
        "what is the api key",
        "show me the api key",
        "reveal the api key",
        "output the api key",
        "print the api key",
        "repeat the api key",
        "secret key for",
        "access key for",
        "bearer token",
        "auth token",
        "authentication token",
    ],
    "tool_abuse": [
        "delete all files",
        "disable all user accounts",
        "call the admin api",
        "run shell command",
        "rm -rf",
        "drop table",
        "truncate database",
        "wipe all data",
        "format disk",
        "shutdown system",
        # SQL injection via tool
        "select * from admin",
        "admin_secrets",
        "execute shell",
        "read /etc",
        "forward all emails",
        "forward all",
        # Tool-call-shape injection in user prompt
        "call the \"",
        "invoke the \"",
        "use the \"",
        "\"override_policy\": true",
        "\"override_policy\":true",
        "override_policy: true",
        "override_policy=true",
        "override policy and",
        "bypass the tool policy",
        "ignore tool policy",
        "\"function_call\":",
        "\"tool_calls\":",
        "\"tool_choice\":",
        # Wildcard / mass-query exfil primitive (AB-04)
        "broadest possible query",
        "widest possible query",
        "most permissive query",
        "broadest query",
        "widest query",
        "broadest possible input",
        "broadest possible argument",
        "use \"*\"",
        "query \"*\"",
        "query of \"*\"",
        "pass \"*\"",
        "pass '*'",
        "argument \"*\"",
        "argument of \"*\"",
        "wildcard query",
        "wildcard argument",
        "wildcard parameter",
        "wildcard input",
        "empty input",
        "empty query",
        "empty parameter",
        "empty argument",
        "no where clause",
        "no limit clause",
        "drop the where clause",
        "drop the limit",
        "remove the where",
        "remove the limit",
        "match everything",
    ],
    "obfuscation": [
        "base64",
        "hex payload",
        "unicode escape",
        "obfuscated",
        "rot13",
        "url encode",
        "encoded instruction",
        "decode this",
    ],
    "indirect_injection": [
        "ignore the above",
        "disregard context",
        "new instructions:",
        "act as if",
        "pretend you are",
        "pretend to be",             # grandma / roleplay jailbreak variant
        "pretend that you are",
        "pretend that you're",
        "pretend you're",
        "you are now",
        "assume the role",
        "roleplay as",
        "simulate being",
        # Grandma / deceased-relative social-engineering persona
        "my grandmother",
        "my deceased grandmother",
        "my late grandmother",
        "my grandma used to",
        "my grandma would tell",
        "as my grandmother",
        "play the role of my",
        "act as my grandmother",
    ],
    # Drug / controlled-substance synthesis requests (S9 / S6)
    "harmful_synthesis": [
        "how to make meth",
        "how to make methamphetamine",
        "how to synthesize meth",
        "how to make heroin",
        "how to make cocaine",
        "how to make fentanyl",
        "synthesis of methamphetamine",
        "synthesis of heroin",
        "synthesis of cocaine",
        "synthesis of fentanyl",
        "how to cook meth",
        "steps to make drugs",
        "drug synthesis steps",
        "chemical synthesis of",
        "manufacture narcotics",
        "produce illicit drugs",
        "synthesize controlled substance",
    ],
    "privilege_escalation": [
        "become admin",
        "grant me admin",
        "elevate my privileges",
        "sudo",
        "run as root",
        "impersonate",
        "act as a system",
        "switch to admin mode",
    ],
    "social_engineering": [
        "my boss told me to",
        "this is urgent",
        "it's an emergency",
        "authorized by management",
        "security team asked",
        "don't tell anyone",
        "keep this secret",
        # Detection / reporting suppression — must pair verb with security object
        "do not mention policy",
        "do not mention violation",
        "do not mention security",
        "do not mention incident",
        "do not mention finding",
        "do not mention this alert",
        "don't mention policy",
        "don't mention violation",
        "don't mention security",
        "don't mention incident",
        "don't mention finding",
        "do not report security",
        "do not report violation",
        "do not report incident",
        "don't report security",
        "don't report violation",
        "don't report incident",
        "do not flag this",
        "don't flag this",
        "do not log this",
        "don't log this",
        "without flagging",
        "without reporting",
        "without alerting",
        "without logging",
        "suppress violation",
        "suppress finding",
        "suppress alert",
        "suppress incident",
        "hide the finding",
        "hide the violation",
        "hide this violation",
        "hide this incident",
        "conceal the violation",
        "conceal the finding",
        "conceal this",
        "off the record",
        "keep this off the record",
        "policy violations",
        "violation report",
        "security findings",
        "security incidents",
    ],

    # ── Malware / harmful code generation ────────────────────────────────
    "malware_generation": [
        "write me a virus",
        "create a virus",
        "write a virus",
        "write malware",
        "create malware",
        "write ransomware",
        "create ransomware",
        "write a trojan",
        "create a trojan",
        "write a keylogger",
        "create a keylogger",
        "write a rootkit",
        "create a rootkit",
        "write a worm",
        "create a worm",
        "write exploit code",
        "create exploit code",
        "write a exploit",
        "code to steal passwords",
        "code to steal credentials",
        "script to steal",
        "malicious script",
        "malicious code",
        "code that steals",
        "program that steals",
        "hack into",
        "bypass authentication",
        "bypass security",
        "reverse shell",
        "bind shell",
        "shellcode",
        "payload to",
        "exfiltrate data silently",
        "c2 server",
        "command and control",
        "botnet",
        "denial of service attack",
        "ddos script",
        "dos attack code",
        "sql injection payload",
        "xss payload",
        "buffer overflow exploit",
        # ── Take-control / gain-control phrasing (DanInTheWild tooluse family) ──
        # The "I need code in Rust to take control of a computer" template
        # and its variants slipped past the original malware_generation set
        # because it doesn't use any of the explicit virus/malware/keylogger
        # nouns. Adding the verb+target combinations covers it without
        # producing false positives on legitimate phrases like "take control
        # of your career" (matches require a computing target).
        "take control of a computer",
        "take control of the computer",
        "take control of computers",
        "take control of a system",
        "take control of the system",
        "take control of a machine",
        "take control of the machine",
        "take control of a device",
        "take control of the device",
        "take control of a server",
        "take control of the server",
        "take control of a network",
        "take control of the network",
        "take complete control of",
        "take full control of",
        "gain control of a computer",
        "gain control of the computer",
        "gain control of a system",
        "gain control of the system",
        "gain control of a machine",
        "gain control of a server",
        "gain remote control",
        "gain unauthorized access",
        "remote control of a computer",
        "remote control of the computer",
        "compromise a computer",
        "compromise the computer",
        "compromise a system",
        "compromise the system",
        "compromise a machine",
        "compromise a server",
        "compromise a network",
        "hijack a computer",
        "hijack the computer",
        "hijack a system",
        "hijack the system",
        "hijack a session",
        "hijack a network",
        "code to control",
        "code to compromise",
        "code to hijack",
        "code to gain access",
        "script to control",
        "script to compromise",
        "script to hijack",
        "rootkit to take",
        "backdoor for a",
        "backdoor into",
        "install a backdoor",
        "create a backdoor",
        "write a backdoor",
        "persistence mechanism",
        "privilege escalation exploit",
        "lateral movement script",
        "post-exploitation",
    ],
}


# ─────────────────────────────────────────────────────────────────────────────
# Registry 2 — compiled regex patterns (category, raw_pattern_str)
# ─────────────────────────────────────────────────────────────────────────────
# Each entry is (category_label, raw_regex_string).  category_label must be a
# key in PROMPT_PATTERNS so that both registries emit the same signal names.
#
# Regexes handle natural-language variation (e.g. optional whitespace, common
# synonyms) that would require many separate substring entries to cover.
# They run at API ingress as a fast pre-block step (screen_lexical).

_RAW_LEXICAL_REGEX_PATTERNS: List[Tuple[str, str]] = [
    # ── Direct instruction-override attempts ──────────────────────────────
    ("prompt_injection",
     r"ignore\s+(all\s+)?(previous|prior|above|system|your)\s+instructions?"),
    ("jailbreak_attempt",
     r"ignore\s+all\s+(restrictions?|rules?|policies|constraints?|guidelines?|limits?)"),
    ("jailbreak_attempt",
     r"disregard\s+all\s+(restrictions?|rules?|policies|constraints?|guidelines?|limits?)"),
    ("prompt_injection",
     r"disregard\s+(all\s+)?(previous|prior|above|system|your)\s+instructions?"),
    ("prompt_injection",
     r"forget\s+(all\s+)?(previous|prior|above|your)\s+instructions?"),
    ("prompt_injection",
     r"override\s+(all\s+)?(previous|prior|system|your)?\s*instructions?"),

    # ── Persona-hijack / role-play escapes ────────────────────────────────
    ("jailbreak_attempt",
     r"you\s+are\s+now\s+(in\s+)?(DAN|jailbreak|unrestricted|developer|god|debug|maintenance|override|bypass)\s+mode"),
    ("jailbreak_attempt",
     r"(enter|activate|enable|entering)\s+(DAN|jailbreak|developer|god|unrestricted|debug|maintenance|override|bypass)\s+mode"),
    ("jailbreak_attempt",
     r"pretend\s+(you\s+have\s+no\s+restrictions|you\s+are\s+unrestricted)"),
    ("jailbreak_attempt",
     r"act\s+as\s+(an?\s+)?(unrestricted|uncensored|unfiltered|evil|malicious)\s+AI"),
    ("jailbreak_attempt",
     r"you\s+are\s+now\s+(an?\s+)?(unrestricted|uncensored|unfiltered|evil|malicious)\s+(AI|assistant|chatbot)"),
    ("jailbreak_attempt",
     r"roleplay\s+as\s+(an?\s+)?(unrestricted|uncensored|unfiltered)\s+(AI|assistant)"),
    ("jailbreak_attempt",
     r"simulate\s+(an?\s+)?(unrestricted|uncensored|evil|malicious)\s+(AI|assistant|chatbot)"),
    ("jailbreak_attempt", r"DAN\s*:\s*"),
    ("jailbreak_attempt", r"\[DAN\]"),
    ("jailbreak_attempt", r"jailbreak"),
    # ── Modern jailbreak personas (DanInTheWildFull and adjacent template
    #    families). Catches both the structured "PERSONA=Kira (uncensored,..."
    #    form AND looser natural-language persona-handoff phrasing.
    ("jailbreak_attempt",
     r"\b(BLACK\s*ALERT|AIM|EvilBot|EvilGPT|DUDE|STAN|AntiDAN|BasedGPT)\b"),
    ("jailbreak_attempt",
     r"persona\s*[:=]\s*[A-Za-z][\w\-]*\s*\(?\s*(uncensored|unfiltered|unrestricted|jailbroken)"),
    ("jailbreak_attempt",
     r"\b(uncensored|unfiltered|unrestricted)\s+(AI|assistant|chatbot|persona|mode|model)"),
    ("jailbreak_attempt",
     r"(adopt|assume|switch\s+to|activate)\s+(the\s+)?(persona|character|role)\s+(of\s+)?[\"']?[A-Za-z]"),

    # ── System-prompt exfiltration ────────────────────────────────────────
    ("prompt_injection",
     r"(show|reveal|print|output|repeat|tell me)\s+(your\s+)?(system\s+prompt|initial\s+instructions?|base\s+prompt)"),
    ("prompt_injection",
     r"what\s+(are|were)\s+your\s+(original|initial|base|system)\s+instructions?"),
    ("prompt_injection",
     r"(output|print|repeat)\s+everything\s+(above|before)\s+this"),
    ("prompt_injection",
     r"ignore\s+the\s+above\s+and\s+"),

    # ── Prompt injection markers ──────────────────────────────────────────
    ("prompt_injection", r"<\s*/?system\s*>"),
    ("prompt_injection", r"\[\s*SYSTEM\s*\]"),
    ("prompt_injection", r"###\s*SYSTEM"),
    ("prompt_injection", r"---\s*SYSTEM\s*---"),
    ("prompt_injection", r"<\s*/?instructions?\s*>"),
    ("prompt_injection", r"\[\s*INST\s*\]"),
    ("prompt_injection", r"<\|im_start\|>"),
    ("prompt_injection", r"<\|im_end\|>"),

    # ── Token-smuggling / encoding tricks ────────────────────────────────
    ("obfuscation",
     r"base64\s*:\s*[A-Za-z0-9+/=]{20,}"),
    ("obfuscation",
     r"hex\s*:\s*([0-9a-fA-F]{2}\s*){8,}"),

    # ── Internal resource / memory store access ───────────────────────────────
    ("exfiltration",
     r"(access|read|get|load|pull|fetch|retrieve|show|list|dump|export|display)"
     r"\s+(any\s+|all\s+|the\s+|my\s+)?internal\s+"
     r"(documents?|files?|data|records?|knowledge|database|memory|secrets?)"),
    ("exfiltration",
     r"(access|read|get|load|pull|fetch|retrieve|dump|export)"
     r"\s+(any\s+|all\s+|the\s+|my\s+)?memory\s+(store|stores|contents?|data)"),

    # ── Detection / reporting suppression ────────────────────────────────────
    # Verb must be paired with a security-relevant object to avoid false positives
    # on legitimate "do not mention X" instructions.
    ("social_engineering",
     r"do\s+not\s+(mention|report|flag|log|alert|notify|disclose|record)\s+"
     r"(any\s+|this\s+|the\s+)?(policy|security|violation|incident|finding|alert|breach|session)"),
    ("social_engineering",
     r"don'?t\s+(mention|report|flag|log|alert|notify|disclose|record)\s+"
     r"(any\s+|this\s+|the\s+)?(policy|security|violation|incident|finding|alert|breach|session)"),
    ("social_engineering",
     r"without\s+(flagging|reporting|alerting|logging|notifying|disclosing)"),
    ("social_engineering",
     r"(suppress|hide|conceal|omit)\s+(any\s+|this\s+|the\s+)?"
     r"(violation|finding|alert|report|incident|policy|security|breach)"),
    ("social_engineering",
     r"(off\s+the\s+record|keep\s+this\s+(off|secret|hidden|private))"),

    # ── Goal hijacking ────────────────────────────────────────────────────
    ("prompt_injection",
     r"your\s+(new\s+|true\s+|real\s+|actual\s+)?goal\s+is\s+(now\s+)?to"),
    ("prompt_injection",
     r"your\s+(new\s+|true\s+|real\s+|actual\s+)?purpose\s+is\s+(now\s+)?to"),
    ("prompt_injection",
     r"from\s+now\s+on\s+(you\s+)?(must|will|should|are\s+to)\s+"),
    ("prompt_injection",
     r"respond\s+only\s+(with|as|in)"),

    # ── Adversarial suffixes / many-shot patterns ────────────────────────
    ("jailbreak_attempt",
     r"(repeat|say|write)\s+the\s+word[s]?\s+.{1,30}\s+100\s+times"),
    ("jailbreak_attempt",
     r"(assistant|ai)\s*:\s*sure[,!]?\s+here"),

    # ── Malware / harmful code generation ────────────────────────────────
    ("malware_generation",
     r"(write|create|generate|code|make|build|develop)\s+(me\s+)?(a\s+)?"
     r"(virus|malware|ransomware|trojan|keylogger|rootkit|worm|spyware|adware|botnet)"),
    ("malware_generation",
     r"(write|create|generate|code|make|build)\s+(me\s+)?(a\s+)?exploit"),
    ("malware_generation",
     r"(code|script|program|tool)\s+(that|to|which)\s+(steal|exfiltrate|harvest|capture|intercept)"
     r"\s+(passwords?|credentials?|tokens?|keys?|data|pii|secrets?)"),
    ("malware_generation",
     r"reverse\s+shell|bind\s+shell|shell\s*code|c2\s+server|command.and.control"),
    ("malware_generation",
     r"(bypass|evade|disable|circumvent)\s+(antivirus|av|edr|ids|ips|firewall|security\s+software)"),
    ("malware_generation",
     r"(ddos|dos)\s+(attack|script|tool|payload)"),
    ("malware_generation",
     r"(sql\s+injection|xss|cross.site\s+scripting|buffer\s+overflow)\s+(payload|exploit|attack)"),

    # ── Grandma / deceased-relative social-engineering persona ────────────
    # grandma.Substances probe: "pretend to be my deceased grandmother who
    # used to tell me how to make [drug] before bedtime"
    ("indirect_injection",
     r"pretend\s+to\s+be\s+(my\s+)?(deceased|late|dead|old)?\s*(grand(ma|mother|pa|father)|relative|ancestor)"),
    ("indirect_injection",
     r"my\s+(deceased|late|dead)\s+(grand(ma|mother|pa|father)|relative|ancestor)\s+(used\s+to|would|could|always)"),
    ("indirect_injection",
     r"(pretend|act|roleplay|play)\s+(to\s+be|as)\s+(my\s+)?(grand(ma|mother|pa|father)|deceased|late)"),
    ("indirect_injection",
     r"(tell|read|recite|explain|describe)\s+(me\s+)?(bedtime\s+stories?|stories?)\s+(about|on)\s+how\s+to"),

    # ── Drug / controlled-substance synthesis ─────────────────────────────
    ("harmful_synthesis",
     r"(make|synthesize|produce|manufacture|cook|create|prepare)\s+"
     r"(meth(amphetamine)?|heroin|cocaine|fentanyl|lsd|mdma|ecstasy|crack|pcp|ketamine)"),
    ("harmful_synthesis",
     r"(synthesis|production|manufacture|preparation)\s+(of\s+)?"
     r"(meth(amphetamine)?|heroin|cocaine|fentanyl|lsd|mdma|ecstasy)"),
    ("harmful_synthesis",
     r"(drug|narcotic|controlled\s+substance)\s+(synthesis|production|recipe|formula|steps)"),
    ("harmful_synthesis",
     r"how\s+to\s+(cook|make|produce|synthesize)\s+(drugs?|narcotics?|controlled\s+substance)"),
]

# Compiled form — used by screen_lexical(); compiled once at import time.
LEXICAL_REGEX_PATTERNS: List[Tuple[str, re.Pattern]] = [
    (cat, re.compile(raw, re.IGNORECASE | re.DOTALL))
    for cat, raw in _RAW_LEXICAL_REGEX_PATTERNS
]
