# Phase 18: Campaign Grouping & Phishing Analysis API - Discussion Log

> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.

**Date:** 2026-07-15
**Phase:** 18-campaign-grouping-phishing-analysis-api
**Areas discussed:** Grouping trigger, Grouping params, Campaign merge, Permission model, Route auth

---

## Grouping Trigger

| Option | Description | Selected |
|--------|-------------|----------|
| Auto-group on every detection | Hook grouping into the same webhook + cron path Phase 15 uses; new `/analyze` endpoint reuses the same shared function on-demand. | ✓ |
| On-demand only via the new API | Grouping only happens when `POST /analyze` is explicitly called. | |

**User's choice:** Auto-group on every detection (recommended option).
**Notes:** None.

---

## Grouping Params

| Option | Description | Selected |
|--------|-------------|----------|
| 24h window, strip Re:/Fwd: + lowercase + trim | Same-day mass-phishing blast window; standard subject normalization. | ✓ |
| 72h window, same subject normalization | Wider window, catches slower-trickling reports at cost of looser grouping. | |
| You decide (Claude's discretion) | No strong preference. | |

**User's choice:** 24h window, strip Re:/Fwd: + lowercase + trim (recommended option).
**Notes:** None.

---

## Campaign Merge

| Option | Description | Selected |
|--------|-------------|----------|
| Never merge existing campaigns | Attach to single best-matching existing campaign or create new; no merge logic. | ✓ |
| Support merging two campaigns when both match | Transactional reassignment of reports/messages/indicators/classifications across campaigns. | |

**User's choice:** Never merge existing campaigns (recommended option).
**Notes:** None.

---

## Permission Model

| Option | Description | Selected |
|--------|-------------|----------|
| New 'phishing' resource: read + analyze actions now, full statement vocabulary declared | `phishing: ["read","analyze","approve","remediate"]` in statement; only read+analyze granted this phase. | ✓ |
| New 'phishing' resource: read + analyze actions only, extend later | Only declare read+analyze now; Phase 20 adds approve/remediate to the statement itself. | |

**User's choice:** New 'phishing' resource: read + analyze actions now (recommended option).
**Notes:** None.

---

## Route Auth (follow-up)

| Option | Description | Selected |
|--------|-------------|----------|
| requirePermission('phishing','read'/'analyze') on every route | Fine-grained check on all routes from day one. | ✓ |
| requireAuth() only for GETs, requirePermission for POST /analyze | Looser check on reads. | |

**User's choice:** requirePermission on every route (recommended option).
**Notes:** Asked as a follow-up after the Permission Model question to nail down route-level specifics.

---

## Claude's Discretion

- Exact SQL/query shape for `GET /api/phishing/campaigns/{id}`'s nested response
- Exact shape of the tiered-key matching queries against the `indicators` table
- Response body shape for `POST /analyze`
- Where the shared grouping function lives (new file vs. extending `phishing-detector.ts`)
- Whether `campaigns.status` transitions in this phase (likely out of scope)

## Deferred Ideas

- Multi-campaign merge logic — deferred per D-04, future work if it proves to be a real recurring problem
- `campaigns.status` transition logic — belongs to Phase 19/20
- approve/remediate permission grants — declared now (D-05), granted in Phase 20
