13 KiB
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
.emlattachments exist, the system prefersrfc.emlas the original reported message overOriginatingEmail.eml(wrapper/context), matching case-insensitively and bymessage/rfc822content-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: unavailablefor 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 arequires_approvalflag - 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
THREATabsent 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
proposedbut 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}/remediateproceeds only for approved actions against a configured, non-destructive-by-default provider path; otherwise it returnsnot_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
Approval UI (LiveLink)
- 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
unavailablestate 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_AWARENESSverdict to campaigns confirmed as phishing-simulation-vendor (KnowBe4/Breach Secure Now) reports, replacing the previous forced-UNWANTEDdisposition for these confirmed-simulation cases - CLASSDISP-02:
USER_AWARENESSmaps to a new non-destructiveacknowledge_useraction that posts a customer-visible thank-you note (AutotasknoteType: 18, "Client Portal Note") to the reporting employee - CLASSDISP-03: The campaign review UI surfaces
USER_AWARENESSandacknowledge_userdistinctly from the existing SPAM/UNWANTED/THREAT verdicts and their actions - AUTOGATE-01: A per-company
phishing_automation_gatetable and admin-gatedGET/PATCH/DELETEAPI 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-automationpage lists companies with three independent per-companySwitchtoggles (one per automation stage), backed by theAUTOGATE-01API - 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_userauto-post carve-out narrowly scoped toUSER_AWARENESSverdicts 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)*