/* eagle-data.jsx — Eagle Eye SOC: dual themes, alert scenarios, dashboard
   datasets, and the alert-aware mock "AI runtime" layer.
   ============================================================
   INTEGRATION SEAM — one function per architecture:
       async function runX(alert, emit, shouldStop)
   `alert` is one of the ALERTS scenarios (carries its own canned content).
   `emit(event)` delivers one typed event (like an SSE chunk). Telemetry
   events carry a color KEY (`ck`) resolved against the active theme so the
   feed re-themes on light/dark toggle. To wire a real backend, swap each
   runX body for a fetch()+stream reader that calls emit() per chunk.
   ============================================================ */

// ---- accent palette (shared hue set, per-theme tuned) --------
const ACCENTS = {
  dark:  { model:"#a78bfa", app:"#22d3ee", agent:"#f59e0b", tools:"#34d399", rag:"#e879f9", guard:"#f87171", gateway:"#2dd4bf", a2a:"#fb923c", identity:"#fcd34d", cost:"#60a5fa", success:"#34d399", error:"#f87171", crit:"#fb7185", high:"#f59e0b", med:"#38bdf8", low:"#34d399" },
  light: { model:"#7c3aed", app:"#0891b2", agent:"#c2410c", tools:"#047857", rag:"#a21caf", guard:"#dc2626", gateway:"#0d9488", a2a:"#ea580c", identity:"#a16207", cost:"#2563eb", success:"#047857", error:"#dc2626", crit:"#e11d48", high:"#d97706", med:"#0284c7", low:"#059669" },
};

const EAGLE_THEMES = {
  dark: {
    name: "dark", isDark: true,
    bg: "#050508", surface: "#0d0d14", elevated: "#141420", raised: "#1c1c2b",
    border: "rgba(255,255,255,0.07)", borderStrong: "rgba(255,255,255,0.13)",
    text: "#e8e8f2", text2: "#b4b4d4", muted: "#7676a8",
    hover: "rgba(255,255,255,0.05)", fill: "rgba(255,255,255,0.04)",
    codeBg: "#070709", grid: "rgba(255,255,255,0.06)",
    headerBg: "rgba(5,5,8,0.82)",
    glow: "rgba(45,212,191,0.10)",
    mono: "'JetBrains Mono', ui-monospace, monospace",
    sans: "'Inter', system-ui, sans-serif",
    ...ACCENTS.dark,
  },
  light: {
    name: "light", isDark: false,
    bg: "#eef1f7", surface: "#ffffff", elevated: "#f5f7fc", raised: "#eef1f7",
    border: "rgba(15,23,42,0.10)", borderStrong: "rgba(15,23,42,0.20)",
    text: "#0f172a", text2: "#334155", muted: "#64748b",
    hover: "rgba(15,23,42,0.04)", fill: "rgba(15,23,42,0.035)",
    codeBg: "#0f172a", grid: "rgba(15,23,42,0.08)",
    headerBg: "rgba(238,241,247,0.85)",
    glow: "rgba(13,148,136,0.10)",
    mono: "'JetBrains Mono', ui-monospace, monospace",
    sans: "'Inter', system-ui, sans-serif",
    ...ACCENTS.light,
  },
};
const EAGLE = EAGLE_THEMES.dark; // default / non-context fallback

const LAYERS = {
  model: { key: "model", n: 1, name: "AI Model", label: "AI MODEL — Layer 1", icon: "Box" },
  app:   { key: "app",   n: 2, name: "AI Application", label: "AI APPLICATION — Layer 2", icon: "Boxes" },
  agent: { key: "agent", n: 3, name: "AI Agent", label: "AI AGENT — Layer 3", icon: "Workflow" },
};

/* ============================================================
   ALERT SCENARIOS — each drives its own canned response + telemetry
   ============================================================ */
const ALERTS = [
  {
    id: "tor-exit", code: "SEC-2025-8847", title: "Tor exit node beacon", sev: "HIGH", category: "C2 / Beaconing",
    host: "workstation-043", user: "sarah.chen", rule: "DETECT_TOR_EXIT_NODE", time: "14:23:11",
    destIp: "185.220.101.45", port: 4444, hero: true,
    descriptor: "Finance workstation beaconing to a known Tor exit node",
    threatCat: "Data Exfiltration / C2",
    text: `SIEM Alert #SEC-2025-8847
Timestamp: 2025-05-10T14:23:11Z
Rule Triggered: DETECT_TOR_EXIT_NODE
Source Host: workstation-043 (10.0.1.43)
Assigned User: sarah.chen@company.com
Department: Finance
Destination IP: 185.220.101.45
Destination Port: 4444
Protocol: TCP
Duration: 14m 32s
Data Transferred: 2.3 MB outbound / 180 KB inbound
Prior Alerts (same host, 24h): 4
Classification: HIGH SEVERITY`,
    model: `**Tor Exit Node Connection — General Overview**

A connection from \`workstation-043\` to \`185.220.101.45\` was flagged because the destination is a known Tor exit node. Tor anonymises traffic, so this can indicate exfiltration, C2, or policy violation.

**General recommendations:**
- Confirm whether the connection was authorised.
- Review the volume and direction of transferred data.
- Consider isolating the host until understood.

Note: I have no access to your asset inventory, threat-intel or host history, so this is generic guidance.`,
    rag: [
      { title: "Tor Exit Node Investigation Runbook", score: 0.94, snippet: "Any outbound connection from a Finance workstation to a known Tor exit node is HIGH by default. Isolate first, validate asset sensitivity, then escalate." },
      { title: "Past Incident: Tor Connection — Finance 2024", score: 0.91, snippet: "Confirmed compromise via phishing payload. Attacker staged 2–4 MB over Tor before detection; remediated via reimage + reset." },
      { title: "Data Exfiltration Response Playbook", score: 0.88, snippet: "Containment order: isolate host, suspend user sessions, capture memory/disk, block destination at perimeter." },
    ],
    app: `**Incident Assessment — HIGH (confirmed)**

This matches a known data-exfiltration pattern, not a benign anomaly.

**What I found:**
- \`185.220.101.45\` is a documented Tor exit node. Per the *Tor Exit Node Investigation Runbook*, any such connection from Finance is HIGH.
- *Past Incident: Finance 2024* was a confirmed compromise; the 2.3 MB egress here is consistent with staged theft.
- Port \`4444/TCP\` is a common Meterpreter default — likely an active C2 channel.
- Host has 4 prior alerts in 24h — sustained activity.

**Recommended response:**
1. Network-isolate \`workstation-043\`.
2. Suspend \`sarah.chen@company.com\` and force a reset.
3. Capture memory/disk for forensics.
4. Block \`185.220.101.45\` at the perimeter.

I can draft the ticket, but I can't execute these — a human or agent with tool access would.`,
    ctx: { system: 312, history: 580, rag: 890, alert: 94 },
    mcp: [
      { tool: "mcp-threat-intel.check_tor_exit_node", args: "185.220.101.45", result: `{\n  "is_tor_exit": true,\n  "node_name": "tor-exit-de-91",\n  "threat_score": 94,\n  "abuse_reports": 1872\n}` },
      { tool: "mcp-threat-intel.lookup_ip_reputation", args: "185.220.101.45", result: `{\n  "reputation": "malicious",\n  "categories": ["tor","c2"],\n  "country": "DE",\n  "confidence": 0.97\n}` },
      { tool: "mcp-asset-db.get_asset", args: "workstation-043", result: `{\n  "owner": "sarah.chen@company.com",\n  "department": "Finance",\n  "data_sensitivity": "HIGH",\n  "compliance": ["SOX","PCI"]\n}` },
      { tool: "mcp-siem-logs.get_alert_history", args: "10.0.1.43", result: `{\n  "window": "24h", "count": 4,\n  "alerts": ["PRIVILEGE_ESCALATION","NEW_ADMIN_ACCOUNT","FAILED_LOGINS","TOR_EXIT_NODE"]\n}` },
    ],
    actions: [
      { id: "jira", tool: "mcp-response.create_jira_ticket", label: "Open incident ticket", result: "SEC-1042 created", chip: "SEC-1042" },
      { id: "slack", tool: "mcp-response.post_slack_message", label: "Notify response channel", result: "#security-incidents notified", chip: "#security-incidents" },
      { id: "block", tool: "mcp-response.submit_ip_block", label: "Block destination IP", result: "block request submitted", chip: "185.220.101.45" },
    ],
    report: {
      title: "Confirmed data-exfiltration attempt — Finance workstation over Tor",
      findings: [
        "185.220.101.45 confirmed Tor exit node (threat-intel 94/100, 1,872 abuse reports).",
        "workstation-043 belongs to sarah.chen (Finance) — sensitivity HIGH, SOX & PCI scope.",
        "4 correlated alerts in 24h; 2.3 MB egress over 4444/TCP consistent with C2 exfiltration.",
      ],
      actions: ["Created ticket SEC-1042 (P1, SOC Tier-3).", "Posted summary to #security-incidents.", "Submitted perimeter block for 185.220.101.45."],
      jiraTicket: "SEC-1042", jiraUrl: "https://lastrose.atlassian.net/browse/SEC-1042",
      refs: ["Tor Exit Node Investigation Runbook", "Data Exfiltration Response Playbook", "Past Incident: Finance 2024"],
    },
  },

  {
    id: "brute-force-db", code: "SEC-2025-8848", title: "SSH brute-force on prod DB", sev: "CRITICAL", category: "Credential Access",
    host: "db-prod-01", user: "root +3", rule: "DETECT_SSH_BRUTE_FORCE", time: "13:51:02",
    destIp: "203.0.113.99", port: 22,
    descriptor: "200 SSH attempts in 60s against a production database",
    threatCat: "Credential Access / Brute Force",
    text: `SIEM Alert #SEC-2025-8848
Timestamp: 2026-05-10T13:51:02Z
Rule Triggered: DETECT_SSH_BRUTE_FORCE
Source IP: 203.0.113.99 (flagged Tor exit node by SIEM enrichment)
Target Host: db-prod-01 (10.0.5.12)
Service: sshd
Failed Attempts: 200 in 60 seconds
Targeted Accounts: root, postgres, admin, ec2-user
Asset Sensitivity: PRODUCTION DATABASE
Prior Alerts (same target, 24h): 0
Classification: CRITICAL SEVERITY`,
    model: `**SSH Brute-Force — General Overview**

\`db-prod-01\` saw a burst of failed SSH logins. A high volume across privileged accounts from one source indicates brute-force or password spraying.

**General recommendations:**
- Block or rate-limit the source IP.
- Confirm no account succeeded.
- Enforce key-only auth and restrict SSH exposure.

Note: I can't see your auth logs or asset data, so this is generic guidance.`,
    rag: [
      { title: "SSH Brute-Force Response Runbook", score: 0.95, snippet: "Confirm no successful auth, block source, enforce key-only auth, and restrict sshd to bastion ranges. Treat production DB targets as CRITICAL." },
      { title: "Production Database Hardening Standard", score: 0.90, snippet: "Databases must never expose 22/tcp to 0.0.0.0/0. Require bastion + MFA + key auth; alert on >50 failures/min." },
      { title: "Past Incident: Internet-Exposed DB — 2025", score: 0.86, snippet: "Spray from bulletproof host; no compromise. Root cause: misconfigured security group. Mitigated with SG fix + block." },
    ],
    app: `**Incident Assessment — CRITICAL**

A brute-force from \`203.0.113.99\` (a Tor exit node) hit production database \`db-prod-01\` — 200 attempts in 60s against root/postgres/admin/ec2-user.

**What I found:**
- Threat-intel flags the source as a malicious Tor exit node.
- \`sshd\` on db-prod-01 is exposed to \`0.0.0.0/0\` — a critical misconfiguration.
- Zero successful authentications so far — not yet compromised, but actively targeted.

**Recommended response:**
1. Block \`203.0.113.99\` at the perimeter.
2. Restrict \`sshd\` to the bastion range and remove public exposure.
3. Confirm no successful auth and rotate any matched credentials.

I can draft the ticket; a human or agent would execute the containment.`,
    ctx: { system: 312, history: 300, rag: 740, alert: 96 },
    mcp: [
      { tool: "mcp-siem-logs.get_auth_results", args: "db-prod-01", result: `{\n  "failed": 200,\n  "successful": 0,\n  "accounts": ["root","postgres","admin","ec2-user"],\n  "window": "60s"\n}` },
      { tool: "mcp-threat-intel.lookup_ip_reputation", args: "203.0.113.99", result: `{\n  "is_tor_exit": true,\n  "reputation": "malicious",\n  "categories": ["tor","bruteforce"]\n}` },
      { tool: "mcp-network.check_exposure", args: "db-prod-01:22", result: `{\n  "open_to": "0.0.0.0/0",\n  "should_be": "bastion-only",\n  "misconfigured": true\n}` },
      { tool: "mcp-asset-db.get_asset", args: "db-prod-01", result: `{\n  "role": "postgresql-primary",\n  "environment": "production",\n  "data_sensitivity": "CRITICAL"\n}` },
    ],
    actions: [
      { id: "jira", tool: "mcp-response.create_jira_ticket", label: "Open incident ticket", result: "SEC-1047 created (P1)", chip: "SEC-1047" },
      { id: "block", tool: "mcp-response.submit_ip_block", label: "Block source IP", result: "block request submitted", chip: "203.0.113.99" },
      { id: "sg", tool: "mcp-response.restrict_sshd", label: "Restrict SSH to bastion", result: "security group updated", chip: "db-prod-01" },
    ],
    report: {
      title: "SSH brute-force against internet-exposed production database",
      findings: [
        "200 failed SSH attempts in 60s from Tor exit 203.0.113.99 against privileged accounts.",
        "db-prod-01 sshd exposed to 0.0.0.0/0 — critical misconfiguration.",
        "Zero successful authentications — host targeted but not yet compromised.",
      ],
      actions: ["Created ticket SEC-1047 (P1).", "Submitted perimeter block for 203.0.113.99.", "Restricted sshd to bastion range."],
      jiraTicket: "SEC-1047", jiraUrl: "https://lastrose.atlassian.net/browse/SEC-1047",
      refs: ["SSH Brute-Force Response Runbook", "Production Database Hardening Standard", "Past Incident: Internet-Exposed DB 2025"],
    },
  },

  {
    id: "exfil-finance", code: "SEC-2025-8849", title: "Bulk exfil from finance host", sev: "CRITICAL", category: "Data Exfiltration",
    host: "laptop-finance-007", user: "alex.martinez", rule: "DETECT_LARGE_OUTBOUND_TRANSFER", time: "11:08:44",
    destIp: "45.83.91.4", port: 443,
    descriptor: "1.4 GB of PII/financial data sent outbound in 8 minutes",
    threatCat: "Data Exfiltration",
    text: `SIEM Alert #SEC-2025-8849
Timestamp: 2026-05-10T11:08:44Z
Rule Triggered: DETECT_LARGE_OUTBOUND_TRANSFER
Source Host: laptop-finance-007 (10.0.2.17)
Assigned User: alex.martinez@company.com
Department: Finance
Destination: 45.83.91.4 (uncategorised) port 443
Volume: 1.4 GB outbound in 8m
Files Touched (15m prior): /finance/Q1_close.xlsx, /finance/payroll_2026.csv, /finance/forecast_v9.pptx
DLP Tags: PII, FINANCIAL
Prior Alerts (same user, 7d): 0
Classification: CRITICAL SEVERITY`,
    model: `**Large Outbound Transfer — General Overview**

\`laptop-finance-007\` sent an unusually large volume of data to an external host. Combined with sensitive file access, this can indicate data exfiltration by an insider or a compromised account.

**General recommendations:**
- Identify the destination and whether it is sanctioned.
- Review which files were accessed beforehand.
- Consider isolating the host and suspending the user.

Note: I can't see your DLP, asset or file-access data, so this is generic guidance.`,
    rag: [
      { title: "Data Exfiltration Response Playbook", score: 0.94, snippet: "On large egress to an uncategorised destination after sensitive file access: isolate host, suspend user, block destination, place legal/DLP hold." },
      { title: "DLP Incident Runbook — PII / Financial", score: 0.92, snippet: "PII/FINANCIAL tagged transfers require immediate containment and notification of Legal and the Data Protection Officer." },
      { title: "Past Incident: Finance Data Theft — 2025", score: 0.88, snippet: "Departing employee staged payroll + forecast files over HTTPS to a VPS. Confirmed insider exfiltration." },
    ],
    app: `**Incident Assessment — CRITICAL**

\`laptop-finance-007\` (alex.martinez) sent **1.4 GB** to uncategorised \`45.83.91.4:443\` in 8 minutes, immediately after touching payroll and forecast files tagged PII/FINANCIAL.

**What I found:**
- Destination is uncategorised, hosted in RO — not a sanctioned SaaS endpoint.
- The accessed files (\`payroll_2026.csv\`, \`Q1_close.xlsx\`, \`forecast_v9.pptx\`) match the egress volume and timing — consistent with staged exfiltration.
- No prior alerts for this user in 7d — likely a deliberate or account-compromise event.

**Recommended response:**
1. Network-isolate \`laptop-finance-007\`.
2. Suspend \`alex.martinez@company.com\` and force reset.
3. Block \`45.83.91.4\` and open a Legal/DLP hold.

I can draft the ticket; a human or agent would execute the containment.`,
    ctx: { system: 312, history: 540, rag: 860, alert: 98 },
    mcp: [
      { tool: "mcp-dlp.get_transfer", args: "laptop-finance-007", result: `{\n  "volume": "1.4GB",\n  "dest": "45.83.91.4:443",\n  "dlp_tags": ["PII","FINANCIAL"],\n  "duration": "8m"\n}` },
      { tool: "mcp-edr.get_file_access", args: "laptop-finance-007", result: `{\n  "files": ["payroll_2026.csv","Q1_close.xlsx","forecast_v9.pptx"],\n  "window": "15m_prior"\n}` },
      { tool: "mcp-threat-intel.lookup_ip_reputation", args: "45.83.91.4", result: `{\n  "reputation": "uncategorised",\n  "country": "RO",\n  "hosting": "VPS"\n}` },
      { tool: "mcp-asset-db.get_asset", args: "laptop-finance-007", result: `{\n  "owner": "alex.martinez@company.com",\n  "department": "Finance",\n  "data_sensitivity": "HIGH"\n}` },
    ],
    actions: [
      { id: "jira", tool: "mcp-response.create_jira_ticket", label: "Open incident ticket", result: "SEC-1048 created (P1)", chip: "SEC-1048" },
      { id: "iso", tool: "mcp-response.isolate_endpoint", label: "Isolate endpoint", result: "laptop-finance-007 isolated", chip: "laptop-finance-007" },
      { id: "susp", tool: "mcp-response.suspend_user", label: "Suspend user account", result: "alex.martinez suspended", chip: "alex.martinez" },
    ],
    report: {
      title: "Confirmed bulk data exfiltration of PII/financial files",
      findings: [
        "1.4 GB sent to uncategorised 45.83.91.4:443 (RO VPS) in 8 minutes.",
        "Payroll, Q1-close and forecast files (PII/FINANCIAL) accessed immediately prior.",
        "No prior alerts for alex.martinez in 7d — deliberate or compromised-account exfiltration.",
      ],
      actions: ["Created ticket SEC-1048 (P1).", "Isolated laptop-finance-007.", "Suspended alex.martinez and opened a Legal/DLP hold."],
      jiraTicket: "SEC-1048", jiraUrl: "https://lastrose.atlassian.net/browse/SEC-1048",
      refs: ["Data Exfiltration Response Playbook", "DLP Incident Runbook — PII/Financial", "Past Incident: Finance Data Theft 2025"],
    },
  },

  {
    id: "phish-creds", code: "SEC-2025-8850", title: "Suspected credential phishing", sev: "MEDIUM", category: "Initial Access",
    host: "cloud / M365", user: "maria.lee", rule: "DETECT_OAUTH_CONSENT_PHISH", time: "09:42:18",
    descriptor: "Illicit OAuth app granted mail/file scopes after MFA fatigue",
    threatCat: "Initial Access / OAuth Phishing",
    text: `SIEM Alert #SEC-2025-8850
Timestamp: 2026-05-10T09:42:18Z
Rule Triggered: DETECT_OAUTH_CONSENT_PHISH
Affected User: maria.lee@company.com
Application Granted: "DocViewer Pro" (clientid: 9f3ac0...)
Scopes Granted: Mail.Read, Files.Read.All, offline_access
Source IP: 92.118.40.12 (geo: NL, hosted on AS9009 — M247)
User-Agent: anomalous (mismatch with prior baseline)
Prior MFA prompts (1h): 6 (3 denied, 3 accepted)
Classification: MEDIUM SEVERITY`,
    model: `**OAuth Consent Phishing — General Overview**

\`maria.lee\` granted a third-party application broad mail and file access. Attackers use illicit OAuth consent to gain persistent access without a password.

**General recommendations:**
- Review and revoke the application's consent.
- Revoke refresh tokens for the user.
- Check for attacker-created mailbox rules.

Note: I can't see your identity logs, so this is generic guidance.`,
    rag: [
      { title: "OAuth Consent Phishing Runbook", score: 0.93, snippet: "Revoke the app's service principal and the user's refresh tokens. Illicit grants persist after password reset — token revocation is mandatory." },
      { title: "Illicit Application Grant Playbook", score: 0.89, snippet: "Mail.Read + Files.Read.All + offline_access is a classic exfiltration grant. Hunt for inbox-forwarding rules created after consent." },
      { title: "Identity Threat Baseline", score: 0.84, snippet: "Repeated MFA prompts (deny→deny→accept) indicate MFA-fatigue. Treat the eventual accept as likely attacker-driven." },
    ],
    app: `**Incident Assessment — MEDIUM**

\`maria.lee\` consented to *"DocViewer Pro"* granting \`Mail.Read\`, \`Files.Read.All\` and \`offline_access\` from a hosted NL IP, after an MFA-fatigue pattern (3 denied, then 3 accepted).

**What I found:**
- Threat-intel rates the OAuth client a known-malicious consent-phishing app.
- The scope set is a classic persistent-exfiltration grant.
- The accept followed repeated denials — consistent with MFA fatigue, not intent.

**Recommended response:**
1. Revoke the *"DocViewer Pro"* consent / service principal.
2. Revoke \`maria.lee\`'s refresh tokens and force re-auth.
3. Hunt for inbox-forwarding rules created after the grant.

I can draft the ticket; a human or agent would execute the identity actions.`,
    ctx: { system: 312, history: 380, rag: 700, alert: 92 },
    mcp: [
      { tool: "mcp-identity.get_oauth_grants", args: "maria.lee", result: `{\n  "app": "DocViewer Pro",\n  "client_id": "9f3ac0...",\n  "scopes": ["Mail.Read","Files.Read.All","offline_access"]\n}` },
      { tool: "mcp-threat-intel.lookup_oauth_app", args: "9f3ac0...", result: `{\n  "reputation": "malicious",\n  "category": "consent-phishing",\n  "reports": 214\n}` },
      { tool: "mcp-identity.get_mfa_history", args: "maria.lee", result: `{\n  "prompts_1h": 6,\n  "denied": 3,\n  "accepted": 3,\n  "pattern": "fatigue"\n}` },
      { tool: "mcp-identity.get_inbox_rules", args: "maria.lee", result: `{\n  "new_rules": 1,\n  "rule": "forward *->external; mark read"\n}` },
    ],
    actions: [
      { id: "jira", tool: "mcp-response.create_jira_ticket", label: "Open incident ticket", result: "SEC-1049 created", chip: "SEC-1049" },
      { id: "revoke", tool: "mcp-response.revoke_oauth_grant", label: "Revoke app consent", result: "DocViewer Pro revoked", chip: "DocViewer Pro" },
      { id: "tok", tool: "mcp-response.revoke_tokens", label: "Revoke refresh tokens", result: "tokens revoked · re-auth forced", chip: "maria.lee" },
    ],
    report: {
      title: "Illicit OAuth consent grant via MFA-fatigue phishing",
      findings: [
        "DocViewer Pro (known consent-phishing app) granted Mail.Read, Files.Read.All, offline_access.",
        "Consent followed an MFA-fatigue pattern (3 denied, then 3 accepted) from a hosted NL IP.",
        "A forwarding inbox rule was created post-consent — active mailbox exfiltration attempt.",
      ],
      actions: ["Created ticket SEC-1049.", "Revoked the DocViewer Pro consent.", "Revoked maria.lee refresh tokens and removed the inbox rule."],
      jiraTicket: "SEC-1049", jiraUrl: "https://lastrose.atlassian.net/browse/SEC-1049",
      refs: ["OAuth Consent Phishing Runbook", "Illicit Application Grant Playbook", "Identity Threat Baseline"],
    },
  },

  {
    id: "ransomware-deploy", code: "SEC-2025-8851", title: "Ransomware staging on file server", sev: "CRITICAL", category: "Impact / Ransomware",
    host: "file-srv-corp-02", user: "SYSTEM", rule: "DETECT_MASS_FILE_ENCRYPTION", time: "03:11:47",
    descriptor: "LockBit 3.0 encrypting shares + deleting backups, spreading laterally",
    threatCat: "Impact / Ransomware",
    text: `SIEM Alert #SEC-2025-8851
Timestamp: 2026-05-10T03:11:47Z
Rule Triggered: DETECT_MASS_FILE_ENCRYPTION
Source Host: file-srv-corp-02 (10.0.7.41)
Process: powershell.exe → vssadmin.exe delete shadows /all /quiet
Files Modified (5m): 14,820 across 9 shares (.docx, .xlsx, .pdf renamed to .lockd)
Ransom Note Created: HOW_TO_DECRYPT.txt at 412 directories
Mounted Backup Targets: 3 (NAS-PRIMARY, NAS-DR, OFFSITE-S3)
EDR Verdict: known LockBit 3.0 binary signature
Lateral Spread: 4 hosts in same VLAN show identical TTPs
Classification: CRITICAL SEVERITY`,
    model: `**Mass File Encryption — General Overview**

\`file-srv-corp-02\` is encrypting files at scale and dropping ransom notes — the hallmark of an active ransomware deployment, made worse by shadow-copy deletion.

**General recommendations:**
- Isolate the affected host(s) immediately.
- Protect and disconnect backups.
- Engage incident response and check for lateral spread.

Note: I can't see your EDR, backup or network data, so this is generic guidance.`,
    rag: [
      { title: "Ransomware Containment Runbook", score: 0.97, snippet: "Isolate the entire affected segment first — speed beats precision. Protect backups, then scope lateral spread before remediation." },
      { title: "Backup Protection Standard", score: 0.93, snippet: "On encryption events, immediately disconnect mounted backup targets to prevent the ransomware reaching them. Verify immutable/offline copies." },
      { title: "Past Incident: LockBit — 2025", score: 0.90, snippet: "LockBit 3.0 deleted shadows then spread via SMB to 4 hosts. Contained by VLAN isolation + backup disconnect within minutes." },
    ],
    app: `**Incident Assessment — CRITICAL (active)**

This is a live **LockBit 3.0** ransomware deployment on \`file-srv-corp-02\` — already spreading.

**What I found:**
- EDR confirms a LockBit 3.0 binary signature; 14,820 files across 9 shares renamed to \`.lockd\`.
- Shadow copies were deleted (\`vssadmin delete shadows\`) and ransom notes dropped in 412 directories.
- **3 backup targets are mounted and at risk**; 4 hosts in the same VLAN show identical TTPs.

**Recommended response:**
1. Isolate the entire VLAN segment immediately.
2. Disconnect/protect NAS-PRIMARY, NAS-DR and OFFSITE-S3.
3. Contain the 4 laterally-affected hosts and page IR on-call.

I can draft the ticket; a human or agent would execute the containment.`,
    ctx: { system: 312, history: 600, rag: 920, alert: 110 },
    mcp: [
      { tool: "mcp-edr.get_detection", args: "file-srv-corp-02", result: `{\n  "family": "LockBit 3.0",\n  "signature_match": true,\n  "shadow_copies_deleted": true,\n  "files_encrypted": 14820\n}` },
      { tool: "mcp-backup.get_status", args: "*", result: `{\n  "targets": ["NAS-PRIMARY","NAS-DR","OFFSITE-S3"],\n  "mounted": true,\n  "at_risk": true,\n  "immutable_copy": "OFFSITE-S3"\n}` },
      { tool: "mcp-edr.get_lateral_spread", args: "vlan-corp-02", result: `{\n  "hosts_with_same_ttp": 4,\n  "vector": "SMB",\n  "containable": true\n}` },
      { tool: "mcp-asset-db.get_asset", args: "file-srv-corp-02", result: `{\n  "role": "file-server",\n  "shares": 9,\n  "data_sensitivity": "HIGH"\n}` },
    ],
    actions: [
      { id: "iso", tool: "mcp-response.isolate_vlan", label: "Isolate VLAN segment", result: "vlan-corp-02 isolated", chip: "vlan-corp-02" },
      { id: "bak", tool: "mcp-response.protect_backups", label: "Disconnect & protect backups", result: "3 targets disconnected", chip: "NAS + S3" },
      { id: "page", tool: "mcp-response.page_oncall", label: "Page IR on-call (P1)", result: "IR on-call paged", chip: "SEC-1050" },
    ],
    report: {
      title: "Active LockBit 3.0 ransomware deployment — contained at the segment",
      findings: [
        "EDR-confirmed LockBit 3.0; 14,820 files across 9 shares encrypted, shadows deleted.",
        "3 mounted backup targets were at risk; OFFSITE-S3 retains an immutable copy.",
        "4 hosts in vlan-corp-02 showed identical SMB-borne TTPs.",
      ],
      actions: ["Isolated vlan-corp-02.", "Disconnected and protected all 3 backup targets.", "Paged IR on-call and opened P1 SEC-1050."],
      jiraTicket: "SEC-1050", jiraUrl: "https://lastrose.atlassian.net/browse/SEC-1050",
      refs: ["Ransomware Containment Runbook", "Backup Protection Standard", "Past Incident: LockBit 2025"],
    },
  },

  {
    id: "cryptominer", code: "SEC-2025-8852", title: "Coin-miner on Kubernetes worker", sev: "MEDIUM", category: "Resource Abuse",
    host: "gke-prod-pool-04", user: "kube-system", rule: "DETECT_COIN_MINER_PROCESS", time: "22:47:33",
    destIp: "pool.minexmr.com", port: 443,
    descriptor: "xmrig mining in a drifted ingress-nginx pod",
    threatCat: "Resource Abuse / Cryptojacking",
    text: `SIEM Alert #SEC-2025-8852
Timestamp: 2026-05-10T22:47:33Z
Rule Triggered: DETECT_COIN_MINER_PROCESS
Source Host: gke-prod-pool-04-7f2x (k8s worker)
Pod: ingress-nginx-controller-x9p2k (namespace: kube-system)
Image: docker.io/library/nginx:1.21 → drift detected, sha mismatch
Process: xmrig --donate-level=1 -o pool.minexmr.com:443
CPU: pegged 99% on 4 vCPU for 47m
Outbound: 12.4 MB to pool.minexmr.com (mining pool)
Container Last Pulled: 9 days ago (no recent deploy)
Classification: MEDIUM SEVERITY`,
    model: `**Coin-Miner Process — General Overview**

A pod on \`gke-prod-pool-04\` is running \`xmrig\` and connecting to a mining pool, with image drift from its declared nginx base. This is cryptojacking — abuse of compute, often via a compromised image.

**General recommendations:**
- Kill the offending pod and cordon the node.
- Block the mining pool destination.
- Roll back to a verified image and investigate the drift.

Note: I can't see your cluster or registry data, so this is generic guidance.`,
    rag: [
      { title: "Cryptojacking Response Runbook", score: 0.91, snippet: "Kill the pod, cordon the node, block the pool domain, and roll back to a signed image. Then audit how the drifted image was introduced." },
      { title: "Container Image Drift Policy", score: 0.88, snippet: "Running images must match their signed digest. SHA mismatch with no deploy = tampering or supply-chain compromise; quarantine immediately." },
      { title: "K8s Workload Baseline", score: 0.83, snippet: "ingress-nginx should never spawn miner processes or contact mining pools. Any such process is malicious by definition." },
    ],
    app: `**Incident Assessment — MEDIUM**

A drifted \`ingress-nginx\` pod on \`gke-prod-pool-04\` is running \`xmrig\`, mining to \`pool.minexmr.com\` — cryptojacking, not data theft.

**What I found:**
- The running image's SHA no longer matches its signed \`nginx:1.21\` digest, with no recent deploy — tampering or supply-chain drift.
- \`xmrig\` has pegged 4 vCPU at 99% for 47m and sent 12.4 MB to a known mining pool.
- Namespace is \`kube-system\`, so blast radius is contained to compute abuse.

**Recommended response:**
1. Kill pod \`ingress-nginx-controller-x9p2k\` and cordon the node.
2. Block \`pool.minexmr.com\` at egress.
3. Roll back to the signed image and audit the registry/admission controller.

I can draft the ticket; a human or agent would execute the remediation.`,
    ctx: { system: 312, history: 320, rag: 660, alert: 96 },
    mcp: [
      { tool: "mcp-k8s.get_pod", args: "ingress-nginx-controller-x9p2k", result: `{\n  "namespace": "kube-system",\n  "image_drift": true,\n  "sha_mismatch": true,\n  "process": "xmrig"\n}` },
      { tool: "mcp-threat-intel.lookup_domain", args: "pool.minexmr.com", result: `{\n  "category": "mining-pool",\n  "reputation": "malicious"\n}` },
      { tool: "mcp-k8s.get_image_provenance", args: "ingress-nginx-controller-x9p2k", result: `{\n  "declared": "nginx:1.21",\n  "running_sha": "mismatch",\n  "last_pulled": "9d",\n  "signed": false\n}` },
      { tool: "mcp-asset-db.get_asset", args: "gke-prod-pool-04", result: `{\n  "type": "k8s-worker",\n  "cluster": "gke-prod",\n  "data_sensitivity": "LOW"\n}` },
    ],
    actions: [
      { id: "jira", tool: "mcp-response.create_jira_ticket", label: "Open incident ticket", result: "SEC-1051 created", chip: "SEC-1051" },
      { id: "kill", tool: "mcp-response.kill_pod", label: "Kill pod & cordon node", result: "pod killed · node cordoned", chip: "gke-prod-pool-04" },
      { id: "block", tool: "mcp-response.block_domain", label: "Block mining pool", result: "pool.minexmr.com blocked", chip: "pool.minexmr.com" },
    ],
    report: {
      title: "Cryptojacking via drifted container image on prod cluster",
      findings: [
        "ingress-nginx pod running xmrig, mining to pool.minexmr.com (12.4 MB, 47m at 99% CPU).",
        "Running image SHA mismatches the signed nginx:1.21 digest with no recent deploy — tampering.",
        "Scope limited to compute abuse; no data-access indicators.",
      ],
      actions: ["Created ticket SEC-1051.", "Killed the pod and cordoned gke-prod-pool-04.", "Blocked pool.minexmr.com at egress."],
      jiraTicket: "SEC-1051", jiraUrl: "https://lastrose.atlassian.net/browse/SEC-1051",
      refs: ["Cryptojacking Response Runbook", "Container Image Drift Policy", "K8s Workload Baseline"],
    },
  },

  {
    id: "lateral-rdp", code: "SEC-2025-8853", title: "Lateral RDP burst from compromised laptop", sev: "HIGH", category: "Lateral Movement",
    host: "laptop-eng-021", user: "david.kim", rule: "DETECT_LATERAL_RDP_SWEEP", time: "15:08:22",
    destIp: "198.51.100.34", port: 8443,
    descriptor: "RDP sweep to 27 hosts + Cobalt Strike C2 after ISO loader",
    threatCat: "Lateral Movement / C2",
    text: `SIEM Alert #SEC-2025-8853
Timestamp: 2026-05-10T15:08:22Z
Rule Triggered: DETECT_LATERAL_RDP_SWEEP
Source Host: laptop-eng-021 (10.0.3.88) — user david.kim@company.com
Activity: outbound RDP (3389) to 27 internal hosts in 9m
Successful Auths: 4 (one as svc_backup on dc-east-01)
Used Tool: PsExec.exe + cobaltstrike beacon C2 to 198.51.100.34:8443
Originating Process: outlook.exe → wscript.exe → rundll32 (chain consistent w/ ISO-borne loader)
Mailbox Item: "Q2_Compensation.iso" opened 14m before alert
Classification: HIGH SEVERITY`,
    model: `**Lateral RDP Sweep — General Overview**

\`laptop-eng-021\` is making RDP connections to many internal hosts and beaconing to an external C2 — classic lateral movement following an initial compromise.

**General recommendations:**
- Isolate the source host.
- Block the C2 destination.
- Reset any accounts used for successful authentications.

Note: I can't see your EDR or network data, so this is generic guidance.`,
    rag: [
      { title: "Lateral Movement Containment Runbook", score: 0.95, snippet: "Isolate patient-zero, block C2, then reset any credentials used in successful lateral auths — especially service accounts on domain controllers." },
      { title: "Cobalt Strike Beacon Response", score: 0.91, snippet: "Block the team-server C2, hunt for the named-pipe/beacon pattern across the estate, and treat any reached host as suspect." },
      { title: "ISO-borne Loader Playbook", score: 0.87, snippet: "outlook→wscript→rundll32 from a mounted .iso is a known loader chain. Quarantine the mail item and sweep mailboxes for the lure." },
    ],
    app: `**Incident Assessment — HIGH (confirmed)**

\`laptop-eng-021\` (david.kim) is patient-zero: it swept RDP to 27 hosts in 9m, authed successfully to 4 — including \`svc_backup\` on \`dc-east-01\` — and beacons Cobalt Strike to \`198.51.100.34:8443\`.

**What I found:**
- The process chain \`outlook → wscript → rundll32\` traces to a \`Q2_Compensation.iso\` lure opened 14m prior.
- A successful auth as \`svc_backup\` on a domain controller is a serious escalation risk.
- C2 \`198.51.100.34\` is a known Cobalt Strike team server.

**Recommended response:**
1. Isolate \`laptop-eng-021\`.
2. Block \`198.51.100.34\` and reset \`svc_backup\`.
3. Contain \`dc-east-01\` and sweep mailboxes for the ISO lure.

I can draft the ticket; a human or agent would execute the containment.`,
    ctx: { system: 312, history: 560, rag: 880, alert: 104 },
    mcp: [
      { tool: "mcp-edr.get_process_chain", args: "laptop-eng-021", result: `{\n  "chain": "outlook.exe→wscript.exe→rundll32.exe",\n  "lure": "Q2_Compensation.iso",\n  "tool": "PsExec.exe"\n}` },
      { tool: "mcp-network.get_rdp_sweep", args: "laptop-eng-021", result: `{\n  "targets": 27,\n  "successful": 4,\n  "notable": "svc_backup@dc-east-01"\n}` },
      { tool: "mcp-threat-intel.lookup_ip_reputation", args: "198.51.100.34", result: `{\n  "category": "cobalt-strike-c2",\n  "reputation": "malicious",\n  "confidence": 0.95\n}` },
      { tool: "mcp-asset-db.get_asset", args: "dc-east-01", result: `{\n  "role": "domain-controller",\n  "data_sensitivity": "CRITICAL"\n}` },
    ],
    actions: [
      { id: "jira", tool: "mcp-response.create_jira_ticket", label: "Open incident ticket", result: "SEC-1052 created (P1)", chip: "SEC-1052" },
      { id: "iso", tool: "mcp-response.isolate_endpoint", label: "Isolate patient-zero", result: "laptop-eng-021 isolated", chip: "laptop-eng-021" },
      { id: "block", tool: "mcp-response.submit_ip_block", label: "Block C2 + reset svc_backup", result: "C2 blocked · svc_backup reset", chip: "198.51.100.34" },
    ],
    report: {
      title: "Hands-on-keyboard lateral movement from a phished engineering laptop",
      findings: [
        "laptop-eng-021 swept RDP to 27 hosts, authed to 4 incl. svc_backup on dc-east-01.",
        "Cobalt Strike C2 to 198.51.100.34:8443; loader chain from a Q2_Compensation.iso lure.",
        "Domain-controller service-account compromise — high escalation risk.",
      ],
      actions: ["Created ticket SEC-1052 (P1).", "Isolated laptop-eng-021.", "Blocked the C2 and reset svc_backup; contained dc-east-01."],
      jiraTicket: "SEC-1052", jiraUrl: "https://lastrose.atlassian.net/browse/SEC-1052",
      refs: ["Lateral Movement Containment Runbook", "Cobalt Strike Beacon Response", "ISO-borne Loader Playbook"],
    },
  },

  {
    id: "admin-anomaly", code: "SEC-2025-8854", title: "Anomalous admin action — IAM role created", sev: "HIGH", category: "Privilege Escalation",
    host: "aws:711222333444", user: "jenkins-ci", rule: "DETECT_OFFHOURS_PRIV_ESCALATION", time: "02:34:09",
    destIp: "45.83.91.4", port: null,
    descriptor: "Off-hours AdministratorAccess role created by a stale CI key",
    threatCat: "Privilege Escalation / Cloud",
    text: `SIEM Alert #SEC-2025-8854
Timestamp: 2026-05-10T02:34:09Z
Rule Triggered: DETECT_OFFHOURS_PRIV_ESCALATION
Cloud: AWS account 711222333444 (prod)
Identity: jenkins-ci@acme (long-lived access key, last rotated 412d ago)
Action: iam:CreateRole + iam:AttachRolePolicy (AdministratorAccess) on "tmp-debug"
Source IP: 45.83.91.4 (geo: RO, never seen for this identity)
MFA: not required for this access key
Concurrent: STS GetSessionToken from same key, 30s prior
Asset Sensitivity: production payment-processing account
Classification: HIGH SEVERITY`,
    model: `**Off-Hours Privilege Escalation — General Overview**

A CI identity in your AWS production account created an admin role at an unusual hour from an unfamiliar IP. This pattern suggests a compromised long-lived access key being used for privilege escalation.

**General recommendations:**
- Disable the access key.
- Delete the newly created role/policy.
- Revoke active sessions and rotate credentials.

Note: I can't see your CloudTrail or IAM data, so this is generic guidance.`,
    rag: [
      { title: "Cloud Privilege Escalation Runbook", score: 0.94, snippet: "On unexpected iam:CreateRole/AttachRolePolicy: disable the actor key, delete the role, revoke STS sessions, then scope what the role touched." },
      { title: "AWS IAM Hardening Standard", score: 0.90, snippet: "Long-lived keys must rotate ≤90d and require MFA for sensitive actions. Keys >365d old in prod are policy violations." },
      { title: "CI Credential Compromise Playbook", score: 0.86, snippet: "Leaked CI keys are a top initial-access vector. Treat off-hours admin actions from CI identities as compromise until proven otherwise." },
    ],
    app: `**Incident Assessment — HIGH (likely key compromise)**

The \`jenkins-ci\` identity created an \`AdministratorAccess\` role (\`tmp-debug\`) at 02:34 from a Romanian IP never seen for it — using a 412-day-old key with no MFA.

**What I found:**
- CloudTrail shows \`iam:CreateRole\` + \`iam:AttachRolePolicy(AdministratorAccess)\`, preceded by an \`STS GetSessionToken\` 30s earlier.
- The source IP (\`45.83.91.4\`, RO) has never been used by this identity.
- This is a production payment-processing account — a critical blast radius.

**Recommended response:**
1. Disable the \`jenkins-ci\` access key.
2. Delete the \`tmp-debug\` role and revoke active STS sessions.
3. Rotate CI credentials and enforce IP-scoping + MFA.

I can draft the ticket; a human or agent would execute the containment.`,
    ctx: { system: 312, history: 520, rag: 840, alert: 100 },
    mcp: [
      { tool: "mcp-aws.get_cloudtrail", args: "jenkins-ci", result: `{\n  "events": ["iam:CreateRole","iam:AttachRolePolicy"],\n  "role": "tmp-debug",\n  "policy": "AdministratorAccess"\n}` },
      { tool: "mcp-aws.get_key_age", args: "jenkins-ci", result: `{\n  "age_days": 412,\n  "mfa_required": false,\n  "policy_violation": true\n}` },
      { tool: "mcp-threat-intel.lookup_ip_reputation", args: "45.83.91.4", result: `{\n  "country": "RO",\n  "new_for_identity": true,\n  "reputation": "suspicious"\n}` },
      { tool: "mcp-aws.get_active_sessions", args: "jenkins-ci", result: `{\n  "sts_tokens": 1,\n  "issued": "02:33:39Z"\n}` },
    ],
    actions: [
      { id: "jira", tool: "mcp-response.create_jira_ticket", label: "Open incident ticket", result: "SEC-1053 created (P1)", chip: "SEC-1053" },
      { id: "key", tool: "mcp-response.disable_access_key", label: "Disable CI access key", result: "jenkins-ci key disabled", chip: "jenkins-ci" },
      { id: "role", tool: "mcp-response.delete_iam_role", label: "Delete role & revoke sessions", result: "tmp-debug deleted · STS revoked", chip: "tmp-debug" },
    ],
    report: {
      title: "Compromised CI key used for off-hours privilege escalation in prod AWS",
      findings: [
        "jenkins-ci created an AdministratorAccess role (tmp-debug) at 02:34 from an RO IP never seen before.",
        "The access key is 412 days old with no MFA — a policy violation and likely leaked.",
        "Account is production payment-processing — critical blast radius.",
      ],
      actions: ["Created ticket SEC-1053 (P1).", "Disabled the jenkins-ci access key.", "Deleted the tmp-debug role and revoked STS sessions."],
      jiraTicket: "SEC-1053", jiraUrl: "https://lastrose.atlassian.net/browse/SEC-1053",
      refs: ["Cloud Privilege Escalation Runbook", "AWS IAM Hardening Standard", "CI Credential Compromise Playbook"],
    },
  },
];
ALERTS.forEach((a) => { a.alertText = a.text; });
const getAlert = (id) => ALERTS.find((a) => a.id === id) || ALERTS[0];

// custom-alert template (presenter pastes their own)
function makeCustomAlert(text) {
  const hero = ALERTS[0];
  return { ...hero, id: "custom", code: "CUSTOM", title: "Custom alert", category: "Custom", custom: true, descriptor: "Pasted custom alert", text: text || hero.text, alertText: text || hero.text };
}


/* ============================================================
   DASHBOARD DATASETS (synthetic)
   ============================================================ */
// alerts over 24h, stacked by severity (one point/hour)
const ALERTS_24H = (() => {
  const base = [3,2,2,1,2,1,2,3,5,8,11,14,16,15,13,12,14,17,15,11,8,6,5,4];
  return base.map((v, h) => {
    const crit = Math.max(0, Math.round(v * 0.06));
    const high = Math.round(v * 0.20);
    const med = Math.round(v * 0.40);
    const low = Math.max(0, v - crit - high - med);
    return { h, crit, high, med, low, total: v };
  });
})();

const SEVERITY_DIST = [
  { key: "crit", label: "Critical", value: 3 },
  { key: "high", label: "High", value: 11 },
  { key: "med", label: "Medium", value: 28 },
  { key: "low", label: "Low", value: 47 },
];

const TOP_HOSTS = [
  { name: "workstation-043", value: 9, hot: true },
  { name: "file-srv-corp-02", value: 7 },
  { name: "laptop-eng-021", value: 5 },
  { name: "db-prod-01", value: 4 },
  { name: "laptop-finance-007", value: 3 },
];
const TOP_USERS = [
  { name: "sarah.chen", value: 8, hot: true },
  { name: "david.kim", value: 5 },
  { name: "alex.martinez", value: 4 },
  { name: "maria.lee", value: 3 },
  { name: "jenkins-ci", value: 2 },
];

// MITRE ATT&CK-style coverage (tactic → techniques w/ detection counts 0..3)
const MITRE = [
  { tactic: "Initial Access", techs: [["Phishing", 3], ["Valid Accounts", 1], ["Exploit Public App", 0]] },
  { tactic: "Execution", techs: [["PowerShell", 3], ["Cmd & Script", 2], ["Scheduled Task", 0]] },
  { tactic: "Persistence", techs: [["Create Account", 2], ["Registry Run Keys", 1], ["Valid Accounts", 1]] },
  { tactic: "Priv. Escalation", techs: [["Valid Accounts", 3], ["Token Manipulation", 1], ["Bypass UAC", 0]] },
  { tactic: "Defense Evasion", techs: [["Obfuscation", 2], ["Indicator Removal", 1], ["Masquerading", 1]] },
  { tactic: "Credential Access", techs: [["Brute Force", 3], ["Cred Dumping", 0], ["Steal Tokens", 1]] },
  { tactic: "Discovery", techs: [["Account Discovery", 2], ["Network Scan", 1], ["System Info", 1]] },
  { tactic: "Exfiltration", techs: [["C2 Channel", 3], ["DNS Tunneling", 1], ["Cloud Transfer", 0]] },
];

// radial threat-origin map — angle (deg), radius 0..1 (1=outer), intensity
const THREAT_ORIGINS = [
  { label: "Frankfurt, DE", ip: "185.220.101.45", ang: -38, r: 0.92, intensity: 3, hero: true, note: "Tor exit" },
  { label: "Bucharest, RO", ip: "45.83.91.4", ang: 22, r: 0.86, intensity: 2 },
  { label: "Amsterdam, NL", ip: "92.118.40.12", ang: 96, r: 0.88, intensity: 2 },
  { label: "Unknown", ip: "198.51.100.34", ang: 158, r: 0.78, intensity: 2 },
  { label: "Tor relay", ip: "203.0.113.99", ang: -150, r: 0.9, intensity: 1 },
  { label: "Singapore, SG", ip: "103.96.20.4", ang: -98, r: 0.8, intensity: 1 },
];

const GAUGES = [
  { key: "mttr", label: "MTTR", sub: "mean time to respond", value: 6.2, max: 15, unit: "m", good: "low", ck: "cost" },
  { key: "sla", label: "SLA met", sub: "triage within target", value: 94, max: 100, unit: "%", good: "high", ck: "success" },
  { key: "auto", label: "Auto-contained", sub: "by agents", value: 71, max: 100, unit: "%", good: "high", ck: "agent" },
];

const KPIS = [
  { key: "open", label: "Open incidents", value: 23, icon: "FolderOpen", ck: "guard", spark: [12,14,13,17,16,19,21,20,23], delta: "+4" },
  { key: "today", label: "Alerts today", value: 1284, icon: "BellRing", ck: "cost", spark: [820,910,1040,1120,1080,1190,1230,1260,1284], delta: "+12%" },
  { key: "blocked", label: "Blocked IPs", value: 47, icon: "ShieldBan", ck: "success", spark: [31,33,36,38,40,42,44,45,47], delta: "+6" },
  { key: "agents", label: "Agents active", value: 3, icon: "Bot", ck: "agent", spark: [3,3,2,3,3,3,3,3,3], delta: "live" },
];

const EVENT_STREAM = [
  { ck: "guard", t: "EDR", m: "Quarantined LockBit 3.0 binary on file-srv-corp-02" },
  { ck: "gateway", t: "GATEWAY", m: "AI gateway routed 1,204 model calls · p95 1.2s" },
  { ck: "tools", t: "MCP", m: "mcp-threat-intel.check_tor_exit_node → score 94" },
  { ck: "a2a", t: "A2A", m: "Triage → Enrichment handoff on #SEC-2025-8847" },
  { ck: "success", t: "RESPONSE", m: "IP block submitted: 203.0.113.99" },
  { ck: "med", t: "IDENTITY", m: "OAuth grant revoked for maria.lee" },
  { ck: "cost", t: "BILLING", m: "Agent run #SEC-2025-8847 cost $0.118" },
  { ck: "rag", t: "RAG", m: "Retrieved 3 runbooks · top score 0.94" },
  { ck: "guard", t: "GUARDRAIL", m: "Output scan passed: no destructive actions" },
  { ck: "agent", t: "AGENT", m: "Response agent isolated vlan-corp-02" },
];

// detections by kill-chain stage (synthetic, ties to MITRE module)
const KILLCHAIN = [
  { stage: "Initial Access", short: "Init", count: 7 },
  { stage: "Execution", short: "Exec", count: 5 },
  { stage: "Persistence", short: "Persist", count: 4 },
  { stage: "Priv Esc", short: "PrivEsc", count: 6 },
  { stage: "Defense Evasion", short: "Evasion", count: 4 },
  { stage: "Credential Access", short: "Creds", count: 8 },
  { stage: "Lateral Movement", short: "Lateral", count: 5 },
  { stage: "Exfiltration", short: "Exfil", count: 6 },
  { stage: "Impact", short: "Impact", count: 3 },
];

// autonomous actions taken by the agents (synthetic on-brand feed)
const AGENT_ACTIVITY = [
  { time: "14:24:41", ck: "success", icon: "TicketCheck", text: "Opened Jira SEC-1042 (P1) — Tor exfil on workstation-043" },
  { time: "14:24:38", ck: "guard", icon: "ShieldBan", text: "Blocked 185.220.101.45 at perimeter firewall" },
  { time: "14:24:35", ck: "a2a", icon: "Send", text: "Posted incident summary to #security-incidents" },
  { time: "13:52:10", ck: "agent", icon: "PowerOff", text: "Isolated workstation-211 — Emotet loader quarantined" },
  { time: "13:51:47", ck: "guard", icon: "ShieldBan", text: "Blocked 203.0.113.99 — SSH brute-force source" },
  { time: "11:09:52", ck: "agent", icon: "UserX", text: "Suspended alex.martinez — 1.4 GB finance exfil" },
  { time: "09:43:18", ck: "identity", icon: "KeyRound", text: "Revoked DocViewer Pro OAuth grant for maria.lee" },
  { time: "03:12:30", ck: "agent", icon: "ServerCog", text: "Isolated vlan-corp-02 — LockBit containment" },
  { time: "02:34:55", ck: "guard", icon: "KeySquare", text: "Disabled jenkins-ci access key — prod IAM anomaly" },
];

// internal assets reached (for the threat topology inner ring)
const THREAT_TARGETS = [
  { label: "workstation-043", ang: -45, sev: "high" },
  { label: "db-prod-01", ang: 70, sev: "crit" },
  { label: "file-srv-corp-02", ang: 195, sev: "crit" },
];

/* ============================================================
   COMPARISON (kept, retheme via context)
   ============================================================ */
const COMPARE_ROWS = [
  ["Output", "Generic, textbook guidance", "Context-aware analysis citing internal runbooks", "Full investigation, findings & executed actions"],
  ["Memory", "None — stateless", "Session memory (conversation turns)", "Persistent across the incident lifecycle"],
  ["Tools", "None", "RAG retrieval + input/output guardrails", "MCP tool calls + agent-to-agent (A2A)"],
  ["Autonomy", "None — answers one question", "Assisted — recommends, human acts", "Autonomous — decides and acts"],
  ["Actions taken", "None", "None — drafts only", "Jira ticket · Slack alert · IP block"],
  ["Time", "~2s", "~3.8s", "~45s"],
  ["Cost / run", "$0.0045", "$0.0129", "$0.118"],
];

/* ============================================================
   mock engine
   ============================================================ */
const _delay = (ms) => new Promise((r) => setTimeout(r, ms));
const cost = (tin, tout) => tin * 3e-6 + tout * 15e-6;
const fmtCost = (n) => "$" + n.toFixed(4);
let _eid = 0;
const eid = () => "ev" + ++_eid + "-" + Math.random().toString(36).slice(2, 5);

/* streamText + runModel/runApp/runAgent moved to eagle-stream.jsx —
   the run functions now route raw events through ONE swappable stream
   (window.EAGLE_MOCK_STREAM by default, LASTROSE_BACKENDS.eagleStream when set). */

Object.assign(window, {
  EAGLE, EAGLE_THEMES, LAYERS, ALERTS, getAlert, makeCustomAlert,
  ALERTS_24H, SEVERITY_DIST, TOP_HOSTS, TOP_USERS, MITRE, THREAT_ORIGINS, THREAT_TARGETS, GAUGES, KPIS, EVENT_STREAM, KILLCHAIN, AGENT_ACTIVITY, COMPARE_ROWS,
  eagleEid: eid, eagleFmtCost: fmtCost,
});
