docs: define milestone v3.0 requirements

This commit is contained in:
lorentz 2026-07-14 23:38:23 -04:00
parent 149bd08bd6
commit cefa963565

View file

@ -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 `is<Name>Configured()` 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
<!-- Deferred — not this milestone. -->
### 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
<!-- Explicit exclusions with reasoning. -->
- 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*