diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index eba5c48..375c678 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -1,74 +1,186 @@ -# Requirements: PAX8 Integration (v2.0) +# Requirements: Pulse — v3.0 Phishing Triage Automation -**Defined:** 2026-07-10 -**Core Value:** Managers can see PAX8 subscription costs and seat counts alongside existing Autotask company data in Pulse, without manually cross-referencing PAX8's own portal. -**Source:** `.planning/seeds/SEED-002-pax8-integration.md` (scoped via `/gsd-explore` on 2026-07-10) +**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. -## v2.0 Requirements +## v1 Requirements -Requirements for this milestone. Each maps to a roadmap phase. +### Detection -### PAX8 — Client & Auth +- [ ] **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 -- [x] **PAX8-01**: Pulse authenticates to the PAX8 REST API (`api.pax8.com/v1`) via OAuth2 client-credentials, using the developer-provisioned client ID/secret -- [x] **PAX8-02**: `isPax8Configured()` helper reports whether PAX8 credentials are present, following the existing `isConfigured()` factory pattern (`lib/services/pax8-factory.ts`) +### Evidence Extraction -### PAX8 — Data Sync +- [ ] **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 -- [x] **PAX8-03**: Pulse syncs PAX8 companies into Postgres -- [x] **PAX8-04**: Pulse syncs PAX8 subscriptions (product, seat count, billing term) into Postgres -- [x] **PAX8-05**: Pulse syncs PAX8 product catalog (SKUs, categories) into Postgres, so subscriptions are human-readable -- [x] **PAX8-06**: Pulse syncs PAX8 orders/invoices (historical line items) into Postgres, enabling cost reconciliation over time, not just current-state seats -- [x] **PAX8-07**: Sync runs on a daily schedule via the existing `sync-scheduler.ts` cron pattern -- [x] **PAX8-08**: All PAX8 sync operations are read-only — no writes back to the PAX8 API (no seat adjustments, no order placement) -- [x] **PAX8-09**: PAX8 integration can be toggled on/off via `/admin/integrations`, consistent with other integrations (`integration_settings` table) +### Campaign Grouping -### PAX8 — Company Matching +- [ ] **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}`) -- [x] **PAX8-10**: PAX8 companies are automatically matched to existing Autotask companies by fuzzy name similarity at sync time -- [x] **PAX8-11**: Unmatched or ambiguous company matches are flagged rather than silently guessed -- [x] **PAX8-12**: An admin can view flagged/ambiguous company matches and manually resolve them to the correct Autotask company +### Blast Radius (Mimecast) -### PAX8 — UI Surface +- [ ] **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 -- [x] **PAX8-13**: A new `/pax8` page lists PAX8 companies with their subscriptions and a cost breakdown -- [x] **PAX8-14**: The `/pax8` page surfaces flagged/ambiguous company matches (PAX8-11) for manual resolution +### Classification -## Future Requirements +- [ ] **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 -- Write access to PAX8 (seat adjustments, order placement) — no concrete need identified yet; revisit only if reconciliation surfaces one -- Domain-based or external-ID-based company matching, if research resolves [[RESEARCH-pax8-company-identifiers]] in `.planning/research/questions.md` and finds a more stable join key than name -- General Pulse data assistant (chatbot) consuming this data — separate future milestone, see `.planning/seeds/SEED-003-general-pulse-data-assistant.md` +- [ ] **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 + +## 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 - - -- Write-back to PAX8 — this integration is read-only in v2.0, matching the pattern of most existing Pulse integrations (RMM, IT Glue, Veeam) -- Chatbot/NL query layer — deliberately separated into SEED-003 so this milestone stays scoped to the data sync itself +| 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 | |-------------|-------|--------| -| PAX8-01 | Phase 10 | Complete | -| PAX8-02 | Phase 10 | Complete | -| PAX8-03 | Phase 11 | Complete | -| PAX8-04 | Phase 11 | Complete | -| PAX8-05 | Phase 11 | Complete | -| PAX8-08 | Phase 11 | Complete | -| PAX8-06 | Phase 12 | Complete | -| PAX8-10 | Phase 12 | Complete | -| PAX8-11 | Phase 12 | Complete | -| PAX8-07 | Phase 13 | Complete | -| PAX8-09 | Phase 13 | Complete | -| PAX8-12 | Phase 14 | Complete | -| PAX8-13 | Phase 14 | Complete | -| PAX8-14 | Phase 14 | Complete | +| DETECT-01 | TBD | Pending | +| DETECT-02 | TBD | Pending | +| DETECT-03 | TBD | Pending | +| EVID-01 | TBD | Pending | +| EVID-02 | TBD | Pending | +| EVID-03 | TBD | Pending | +| EVID-04 | TBD | Pending | +| CAMP-01 | TBD | Pending | +| CAMP-02 | TBD | Pending | +| CAMP-03 | TBD | Pending | +| BLAST-01 | TBD | Pending | +| BLAST-02 | TBD | Pending | +| CLASSIFY-01 | TBD | Pending | +| CLASSIFY-02 | TBD | Pending | +| CLASSIFY-03 | TBD | Pending | +| CLASSIFY-04 | TBD | Pending | +| CLASSIFY-05 | TBD | Pending | +| CLASSIFY-06 | TBD | Pending | +| REMED-01 | TBD | Pending | +| REMED-02 | TBD | Pending | +| REMED-03 | TBD | Pending | +| REMED-04 | TBD | Pending | +| REMED-05 | TBD | Pending | +| REMED-06 | TBD | Pending | +| NOTE-01 | TBD | Pending | +| ACCESS-01 | TBD | Pending | -**Coverage:** 14/14 v2.0 requirements mapped ✓ +**Coverage:** +- v1 requirements: 26 total +- Mapped to phases: 0 (pending roadmap) +- Unmapped: 26 ⚠️ (resolved by roadmapper) --- -*Requirements defined: 2026-07-10* +*Requirements defined: 2026-07-14* +*Last updated: 2026-07-14 after initial definition*