wulf-pulse/.planning/milestones/v3.0-REQUIREMENTS.md

13 KiB

Requirements Archive: v3.0 Phishing Triage Automation

Archived: 2026-07-17 Status: SHIPPED

For current requirements, see .planning/REQUIREMENTS.md.


Requirements: Pulse — v3.0 Phishing Triage Automation

Defined: 2026-07-14 Core Value: A manager/security operator can see every phishing/spam report ticket automatically triaged, deduplicated into campaigns, and classified — with any destructive remediation gated behind explicit human approval.

v1 Requirements

Detection

  • DETECT-01: System scans recent Autotask/Pulse tickets and flags candidates matching known phishing/spam-report patterns (title/body: "Phishing Report", "Spam Alert", "Phishing Alert - Email Security Report", "KnowBe4 Phish Alert Report", "Source: KnowBe4 Phish Alert Button", "userSubmissionsReportMessage", "reported message destinations", "Microsoft directly")
  • DETECT-02: Re-scanning does not reprocess a ticket already ingested unless its source ticket data has changed since last processed (idempotent)
  • DETECT-03: An operator can trigger analysis of one specific ticket by ID on demand (POST /api/phishing/tickets/{ticket_id}/analyze) instead of waiting for the scheduled scan

Evidence Extraction

  • EVID-01: For each candidate ticket, the system extracts ticket ID/number, company, requester/reporter, title, description, notes, relevant time entries, and attachment metadata
  • EVID-02: When multiple .eml attachments exist, the system prefers rfc.eml as the original reported message over OriginatingEmail.eml (wrapper/context), matching case-insensitively and by message/rfc822 content-type, not filename alone
  • EVID-03: The system parses the selected original email's RFC822/MIME structure into normalized headers (From, display name, sender email/domain, Reply-To, Return-Path, To, Cc, Subject, Date, Message-ID, Received chain, SPF/DKIM/DMARC authentication results), extracted URLs, and attachment metadata (name, content-type, size, hash)
  • EVID-04: The system stores a sanitized/truncated body preview alongside raw evidence, and never executes or fetches any URL found in a message

Campaign Grouping

  • CAMP-01: Reports are grouped into a campaign using original Message-ID first, then attachment-hash/URL-domain + subject + sender + time-window, then sender + normalized subject + client + time-window as fallback keys
  • CAMP-02: A campaign can accumulate many linked ticket reports and recipients over time as duplicates are detected
  • CAMP-03: An operator can list campaigns and view a single campaign's full detail (linked reports, messages, indicators, classification history) via API (GET /api/phishing/campaigns, GET /api/phishing/campaigns/{id})

Blast Radius (Mimecast)

  • BLAST-01: The system can query a Mimecast blast-radius abstraction for message delivery data (matched/delivered/held/rejected/clicked counts, per-recipient status) when Mimecast is configured, keyed on message ID, sender, recipient/reporter, subject, and date window
  • BLAST-02: When Mimecast is not configured, the system records status: unavailable for that lookup and classification proceeds using ticket/email evidence alone — it never blocks on missing Mimecast config

Classification

  • CLASSIFY-01: The system classifies a campaign as exactly one of SPAM / UNWANTED / THREAT, with confidence, a short summary, evidence-backed reasons, recommended actions, and a requires_approval flag
  • CLASSIFY-02: Any classification recommending a destructive action (purge, block, delete, reset, etc.) always sets requires_approval: true
  • CLASSIFY-03: When evidence is incomplete (no Mimecast data, no .eml, etc.), confidence is lowered and the missing evidence is named in the reasons
  • CLASSIFY-04: Known/expected KnowBe4 security-awareness simulations are not classified as THREAT absent contrary evidence
  • CLASSIFY-05: An operator can (re-)trigger classification of a campaign via API (POST /api/phishing/campaigns/{id}/classify)
  • CLASSIFY-06: The classifier accepts structured, size-bounded evidence (not raw unbounded email bodies) — long bodies are redacted/truncated before reaching any AI layer, and IT Glue-sourced evidence goes through the existing redacted search path if referenced

Remediation & Approval Safety

  • REMED-01: Recommended remediation actions are recorded as proposed but never executed automatically in this milestone
  • REMED-02: An authorized operator can approve a campaign's remediation via API (POST /api/phishing/campaigns/{id}/approve), recording approver, timestamp, and the exact approved action parameters
  • REMED-03: POST /api/phishing/campaigns/{id}/remediate proceeds only for approved actions against a configured, non-destructive-by-default provider path; otherwise it returns not_implemented/an explicit failure — it never silently succeeds without taking or logging an action
  • REMED-04: Re-running remediation against an already-completed action does not duplicate the destructive effect (idempotent)
  • REMED-05: An operator can mark a campaign as a false positive via API (POST /api/phishing/campaigns/{id}/mark-false-positive)
  • REMED-06: Every state-changing action (classify, approve, remediate, mark-false-positive) is recorded as an audit event with actor, event type, and payload

Autotask Integration

  • NOTE-01: If Pulse already has a safe Autotask note-writing method, the system can post an internal triage note summarizing classification, evidence, blast radius, and recommended actions (sanitized — no raw secrets/tokens/full malicious URL query strings); otherwise the note text is returned via API without writing anything to Autotask

Access Control

  • ACCESS-01: All /api/phishing/* endpoints enforce existing Pulse auth conventions (requireAuth/requirePermission), with approve/remediate requiring elevated permission beyond plain read access
  • REVIEW-01: A stable, ticket-ID-addressable Pulse route (e.g. /phishing/tickets/{ticketId}) resolves the ticket to its campaign and renders that campaign's review page, suitable as an Autotask LiveLink target (LiveLink supplies the ticket ID as dynamic content, not the internal campaign UUID), authenticated via the existing Better Auth session only — no separate token or query-param auth scheme
  • REVIEW-02: The page displays the campaign's timeline — linked reports, classification history, and audit events (classify/approve/ remediate/mark-false-positive) — in chronological order
  • REVIEW-03: The page displays the gathered evidence — parsed EML headers/URLs/attachments, sanitized body preview, and Mimecast blast-radius data (including an explicit unavailable state when Mimecast isn't configured) — never rendering a raw/unsanitized body or unredacted secrets
  • REVIEW-04: The page displays the current classification (SPAM/ UNWANTED/THREAT), confidence, reasons, and recommended remediation action(s)
  • REVIEW-05: An operator can approve, remediate, or mark a campaign as a false positive directly from the page, calling the existing /api/phishing/campaigns/{id} approve/remediate/mark-false-positive endpoints and reflecting the resulting state (e.g. a remediated campaign shows as remediated, not re-offered for approval)
  • REVIEW-06: An operator without the elevated permission approve/ remediate already require sees those actions disabled or hidden rather than a failed request; the page enforces no separate or relaxed permission model from the underlying APIs

Classification Disposition + Automation Gate

  • CLASSDISP-01: The classifier assigns a dedicated USER_AWARENESS verdict to campaigns confirmed as phishing-simulation-vendor (KnowBe4/Breach Secure Now) reports, replacing the previous forced-UNWANTED disposition for these confirmed-simulation cases
  • CLASSDISP-02: USER_AWARENESS maps to a new non-destructive acknowledge_user action that posts a customer-visible thank-you note (Autotask noteType: 18, "Client Portal Note") to the reporting employee
  • CLASSDISP-03: The campaign review UI surfaces USER_AWARENESS and acknowledge_user distinctly from the existing SPAM/UNWANTED/THREAT verdicts and their actions
  • AUTOGATE-01: A per-company phishing_automation_gate table and admin-gated GET/PATCH/DELETE API let an operator read and set three independent opt-in automation flags (auto_parse, auto_classify, auto_report) per Autotask company, defaulting to all-OFF when no row exists
  • AUTOGATE-02: An /admin/phishing-automation page lists companies with three independent per-company Switch toggles (one per automation stage), backed by the AUTOGATE-01 API
  • AUTOGATE-03: When a company's automation gate stages are enabled, the Autotask webhook automatically runs the gated parse→classify→acknowledge chain for that company's phishing reports, with the acknowledge_user auto-post carve-out narrowly scoped to USER_AWARENESS verdicts only — all other verdicts/actions still require manual approval regardless of gate state

v2 Requirements

Deferred to future release. Tracked but not in current roadmap.

Remediation Execution

  • REMEDEXEC-01: Actually execute Mimecast sender/domain/URL block (behind approval, once REMED-01..06 land and are trusted)
  • REMEDEXEC-02: Microsoft Graph mailbox search/delete/move for delivered copies
  • REMEDEXEC-03: Microsoft Defender/Exchange purge (may be preferable to Graph — needs its own evaluation)
  • REMEDEXEC-04: Auto-create/associate an Autotask parent incident ticket
  • REMEDEXEC-05: Auto-close duplicate reports once a campaign is resolved

Enrichment

  • ENRICH-01: URL reputation lookup / safe expansion of shortened links (without detonation)
  • ENRICH-02: LLM-backed classification layer wired into the CLASSIFY-* rule engine (rule layer ships first; this plugs in behind the same interface)

Out of Scope

Feature Reason
Automatic tenant-wide mailbox purge Destructive; requires proven accuracy and explicit approval infrastructure first (REMED-01..04)
Automatic password reset / session revocation Too high-blast-radius for an MVP triage tool; human-in-the-loop only
URL detonation / sandbox execution Security risk of interacting with malicious infra; reputation-only enrichment deferred to v2
Fully automated ticket closure Accuracy not yet proven; operator closes tickets manually in this milestone
Assuming Microsoft Graph is the eventual purge mechanism Defender/Exchange purge may be preferable; decision deferred to whichever v2 remediation-execution phase picks it up
Real customer .eml fixtures in tests Privacy/security — all test fixtures are synthetic

Traceability

Populated during roadmap creation.

Requirement Phase Status
DETECT-01 Phase 15 Complete
DETECT-02 Phase 15 Complete
DETECT-03 Phase 18 Complete
EVID-01 Phase 15 Complete
EVID-02 Phase 16 Complete
EVID-03 Phase 16 Complete
EVID-04 Phase 16 Complete
CAMP-01 Phase 18 Complete
CAMP-02 Phase 18 Complete
CAMP-03 Phase 18 Complete
BLAST-01 Phase 17 Complete
BLAST-02 Phase 17 Complete
CLASSIFY-01 Phase 19 Complete
CLASSIFY-02 Phase 19 Complete
CLASSIFY-03 Phase 19 Complete
CLASSIFY-04 Phase 19 Complete
CLASSIFY-05 Phase 19 Complete
CLASSIFY-06 Phase 19 Complete
REMED-01 Phase 20 Complete
REMED-02 Phase 20 Complete
REMED-03 Phase 20 Complete
REMED-04 Phase 20 Complete
REMED-05 Phase 20 Complete
REMED-06 Phase 20 Complete
NOTE-01 Phase 21 Complete
ACCESS-01 Phase 18 Complete
REVIEW-01 Phase 22 Complete
REVIEW-02 Phase 22 Complete
REVIEW-03 Phase 22 Complete
REVIEW-04 Phase 22 Complete
REVIEW-05 Phase 22 Complete
REVIEW-06 Phase 22 Complete
CLASSDISP-01 Phase 23 Complete
CLASSDISP-02 Phase 23 Complete
CLASSDISP-03 Phase 23 Complete
AUTOGATE-01 Phase 23 Complete
AUTOGATE-02 Phase 23 Complete
AUTOGATE-03 Phase 23 Complete

Coverage:

  • v1 requirements: 38 total
  • Mapped to phases: 38 (Phases 15-23)
  • Unmapped: 0 ✓

Requirements defined: 2026-07-14 Traceability populated: 2026-07-14 — ROADMAP.md Phases 15-21 Last updated: 2026-07-16 — backfilled Phase 23 CLASSDISP-/AUTOGATE-* entries (23-03)*