Commit graph

605 commits

Author SHA1 Message Date
4857a35629 docs(16): capture phase context 2026-07-15 09:26:15 -04:00
d7b8c6b72d docs(15): add pattern map 2026-07-15 08:23:34 -04:00
c33f52b435 docs(phase-15): evolve PROJECT.md after phase completion 2026-07-15 08:23:10 -04:00
664dfcb763 docs(phase-15): complete phase execution 2026-07-15 08:22:05 -04:00
c33b6615c9 test(15): persist verification report 2026-07-15 08:21:58 -04:00
502e0b95a7 docs(15): re-review after code-review fixes 2026-07-15 08:17:36 -04:00
9c4584d428 fix(15): exclude soft-deleted notes/time entries from phishing evidence
ticket_notes and time_entries both carry an is_deleted soft-delete flag
(per CLAUDE.md audit-column convention); gatherTicketEvidence was reading
both without filtering it, so retracted notes and reversed time entries
showed up as evidence for every phishing report. Found during code-review
re-verification of the Phase 15 CR-01/WR-01/WR-02 fixes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wWroM6FXkQJiH3JgYcony
2026-07-15 08:17:07 -04:00
cb9d5af784 docs(15): add code review fix report 2026-07-15 08:09:49 -04:00
7c63c5f76d fix(15): WR-02 refresh evidence snapshot even when content_hash unchanged 2026-07-15 08:08:20 -04:00
c875081275 fix(15): WR-01 use shared getAutotaskClient factory in phishing-detector 2026-07-15 08:07:45 -04:00
ecc34b4bad fix(15): CR-01 fix webhook-triggered phishing detection reading from unpopulated payload.entity 2026-07-15 08:05:30 -04:00
e94482bd0b docs(15): add code review report 2026-07-15 07:58:33 -04:00
35339a62b8 docs(phase-15): update tracking after wave 3 2026-07-15 07:51:46 -04:00
86d6c63207 chore: merge executor worktree (worktree-agent-aec0d43efe5a155a3) 2026-07-15 07:50:30 -04:00
315a804fc3 docs(15-03): record self-check results in summary
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wWroM6FXkQJiH3JgYcony
2026-07-15 07:50:09 -04:00
63b4aabc5e docs(15-03): add plan execution summary
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wWroM6FXkQJiH3JgYcony
2026-07-15 07:49:51 -04:00
b199d9991c feat(15-03): register phishing-sweep schedule + migration 098
- extend sync_type union with 'phishing-sweep'
- add defaultSchedules entry (disabled by default, daily 5am cron)
- dispatch branch dynamically imports and calls sweepPhishingTickets
- migrations/098_phishing_sweep_schedule.sql seeds the row for existing installs
2026-07-15 07:49:01 -04:00
194b58b196 feat(15-03): fire-and-forget phishing detection on ticket.created webhook
- triggerPhishingDetection() mirrors triggerWorkflowEngine's payload.entity-first shape
- reads createdByContactID (Autotask field) into created_by_contact_id, per entity-mapper.ts:211
- called alongside the existing workflow-engine trigger, not awaited in the request path
2026-07-15 07:48:17 -04:00
dbd2ebe63c feat(15-03): add bounded phishing sweep service
- sweepPhishingTickets() queries recently-modified tickets (7d window, LIMIT 500)
- delegates each ticket to shared detectPhishingTicket (no duplicated match/hash logic)
- per-row try/catch increments errors without aborting the loop
2026-07-15 07:47:08 -04:00
191a8c7210 docs(phase-15): update tracking after wave 2 2026-07-15 07:45:47 -04:00
829cdd4d1d chore: merge executor worktree (worktree-agent-a4899913938a2f6e7) 2026-07-15 07:44:22 -04:00
d629679f71 docs(15-02): append self-check results to summary
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 07:43:58 -04:00
92ed5c0e5e docs(15-02): add plan 02 summary
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 07:43:43 -04:00
15d0caa20d feat(15-02): add evidence capture + detectPhishingTicket orchestration
- gatherTicketEvidence: company_name, ticket_notes, time_entries (all
  parameterized $1 queries), and Autotask attachment metadata only
  (fullPath/title/contentType, never base64 data); Autotask call wrapped in
  try/catch so a failure degrades to an empty attachments array
- detectPhishingTicket: matches, hashes, checks D-04 idempotency guard
  (skips re-gathering/writing when content_hash is unchanged), then upserts
  one reports row via ON CONFLICT (ticket_id) DO UPDATE ... RETURNING id
- requester_contact_id binds from ticket.contact_id, created_by_contact_id
  from ticket.created_by_contact_id per interfaces contract
2026-07-15 07:42:59 -04:00
aabf5322e9 feat(15-02): implement phishing pattern matcher + content hash
- KNOWN_PHISHING_PATTERNS: the 8 locked DETECT-01 strings
- matchesPhishingPatterns: case-insensitive substring match (toLowerCase +
  includes only, no RegExp/eval), mirrors robotic-classifier.evaluateContains
- computePhishingContentHash: sha256 over title+description only (D-04),
  excludes bump-prone fields like status/last_activity_date
2026-07-15 07:42:14 -04:00
0e7daf9a6a test(15-02): add failing tests for phishing pattern matcher + content hash
- Covers all 8 locked DETECT-01 patterns individually, negative case,
  case-insensitivity, and content-hash stability/change/null-normalization
2026-07-15 07:41:14 -04:00
6dffb7b358 docs(phase-15): update tracking after wave 1 2026-07-15 07:39:39 -04:00
6787308c04 chore: merge executor worktree (worktree-agent-aa19352a908fc6624) 2026-07-15 07:37:11 -04:00
8084997bfe docs(15-01): append self-check results to summary 2026-07-15 07:36:40 -04:00
15d8a691a7 docs(15-01): complete phishing triage schema foundation plan
- Migration 097 applied and verified in dev DB (7 tables, idempotent re-run confirmed)
- SUMMARY.md documents schema design decisions and worktree-path caveat with scripts/apply-migrations.sh
2026-07-15 07:36:29 -04:00
84a37e20be feat(15-01): add phishing-triage schema migration 097
- 7-table schema: campaigns, reports, messages, indicators, classifications, remediation_actions, audit_events
- reports table fully designed with ticket_id FK, content_hash (D-04 idempotency), matched_patterns, evidence (EVID-01) columns
- All tables/indexes use IF NOT EXISTS for idempotent re-application
- Remaining 6 tables are stubs for Phases 16-21
2026-07-15 07:35:10 -04:00
13208b3a92 docs(15): create phase plan 2026-07-15 07:31:25 -04:00
3f8e8dc826 docs(phase-15): create phase plan
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012wWroM6FXkQJiH3JgYcony
2026-07-15 07:17:10 -04:00
7fa94cb6a5 docs(state): record phase 15 context session 2026-07-15 06:56:47 -04:00
d3ff9d088b docs(15): capture phase context 2026-07-15 06:56:37 -04:00
0228639f24 docs: create milestone v3.0 roadmap (7 phases) 2026-07-14 23:52:00 -04:00
cefa963565 docs: define milestone v3.0 requirements 2026-07-14 23:38:23 -04:00
149bd08bd6 chore: clear v2.0 phase directories for v3.0 milestone start
Phase artifacts remain in git history (v2.0 PAX8 Integration); .planning/phases/
is cleared for the new v3.0 Phishing Triage Automation phase numbering.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 23:34:37 -04:00
93d2715fe7 docs: start milestone v3.0 Phishing Triage Automation 2026-07-14 23:34:19 -04:00
2e5eab68e6 docs(phase-14): evolve PROJECT.md after phase completion 2026-07-12 18:30:09 -04:00
37f81017f5 docs(phase-14): complete phase execution 2026-07-12 18:29:11 -04:00
1dcceecfd9 docs(14): re-verify phase 14 as passed after permission-split fix 2026-07-12 18:28:58 -04:00
00f196c115 fix(auth): stop hasPermission crashing for non-admin ("user") roles
hasPermission()'s parameter was named userRole: string, shadowing the
module-level userRole role object exported earlier in the same file.
The internal roles map's `user: userRole` entry therefore bound to the
shadowed string parameter (e.g. "user") instead of the actual role
object — so any permission check for a "user"-role session (the only
non-admin role in the app) hit `"user".statements[resource]`, which is
undefined, and threw instead of returning false.

Net effect: every requirePermission()-gated route in the app returned
a 500 instead of a 403 for non-admin users. This predates phase 14 —
surfaced now because phase 14's PAX8 resolve route is admin-gated and
got exercised by a non-admin account during verification.

Renamed the parameter to roleName to remove the collision. Added
lib/permissions.test.ts (previously zero coverage on this file) to
lock in the "user"/admin/super-admin behavior and prevent regression.
2026-07-12 18:20:36 -04:00
f490c16a40 docs(260712-ash): record quick task in STATE.md 2026-07-12 07:54:00 -04:00
8df563c533 chore: merge executor worktree (worktree-agent-ae30b6495d2fffaf0) 2026-07-12 07:53:13 -04:00
9627b8b73c docs(260712-ash): add execution summary
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 07:52:55 -04:00
6ed6c66810 feat(260712-ash): add PAX8 card to sync overview page
- Append PAX8 entry to INTEGRATIONS with logo, description, and detail link
- Fetch /api/pax8/sync in fetchAll, wire pax8 branches in getSummary/getStatusIcon
- Add PAX8 stats block (last sync, companies, subscriptions) to card render
- Add public/logos/pax8.ico as placeholder (copied from itglue.ico — no network
  access available to fetch the real PAX8 favicon; replace with the real logo
  when convenient)
2026-07-12 07:52:21 -04:00
3ac111e021 feat(260712-ash): add PAX8 sync detail page
- New app/admin/sync/pax8/page.tsx mirroring sentinelone/duo pattern
- Polls GET /api/pax8/sync every 10s, shows companies/subscriptions/products stats
- Sync Now button POSTs with triggeredBy, handles 403/409 via sonner toast, polls until complete
2026-07-12 07:51:23 -04:00
a8e5afe73a docs(260712-ash): pre-dispatch plan for PAX8 admin sync UI 2026-07-12 07:49:50 -04:00
770cc836ef docs(14): add code review report and human verification checkpoint 2026-07-11 15:25:39 -04:00