# CRM outreach automation — roadmap

Goal: automate the outreach pipeline (draft -> send -> monitor replies ->
classify -> draft response -> advance stage) with human review gates at:
first send per prospect, any reply before it sends, and anything meeting- or
commitment-related. See conversation record for the full reasoning on why
the first-send gate stays human (diplomatic/government contacts in this CRM
make an unreviewed autonomous mistake costly).

**Blocking dependency:** actual AI drafting/reply-classification needs the
webapp itself to call an LLM (Anthropic API) - it needs its own
`ANTHROPIC_API_KEY` (this is the production webapp's own API access, separate
from Claude Code). Everything up to the draft/review queue can be built and
used with manually-written drafts in the meantime; AI generation slots in
once the key is available.

**Sending mechanism:** reconsidered twice - see Phase D below for where
this landed (Outlook, not the webapp's SMTP settings).

## Phase A — foundation (no new credentials needed)

- [x] `ProspectActivity` model + migration: prospectId, type (note/email_sent/
      email_received/stage_change/system), body, createdBy, createdAt.
- [x] Activity log UI on the prospect edit page (chronological list + quick
      add-note form).
- [x] Duplicate detection on prospect create/seed: warn on matching email or
      close companyName match before inserting.
- [x] `OutreachDraft` model: prospectId, direction (outbound/reply), subject,
      body, status (pending_review/approved/rejected/sent), generatedBy
      (ai/human), reviewedBy, createdAt.
- [x] Review queue admin page (`/admin/crm/drafts`): list pending drafts,
      approve / reject, per draft.
- [x] Wire "approve" to hand off to Outlook for the actual send - see
      Phase D.

## Phase B — reusable templates (no API key - decided against AI drafting
for now; the project owner will write templates by hand)

- [x] `EmailTemplate` model: name, subject, body (with `{{placeholder}}`
      tokens), category.
- [x] Template management UI (list/new/edit/delete) at `/admin/crm/templates`.
- [x] Template picker on the new-draft form: pick a template, it merges in
      the current prospect's data client-side (companyName, contactName,
      email, sector, region), still fully editable before it joins the
      review queue.
- [ ] (Later, if an API key becomes available) an AI-generation option can
      slot in alongside templates rather than replacing them - same
      review-queue gate either way.

## Phase C — reply detection (rescoped again: Outlook stays the real inbox,
no mailbox lives on the webapp)

First version of this phase had the webapp poll a real mailbox over IMAP.
Reconsidered: the project owner wants to keep using Outlook (desktop, the
jambo@zucegroup.com account already set up) as the actual inbox, not have
the webapp hold mailbox credentials or poll it directly. New design:

- [x] `POST /api/crm/inbox-sync` on the webapp - API-key authenticated (not
      session/cookie auth, since the caller is a local script, not a
      browser), takes `{ fromEmail, subject, body }`, matches against
      Prospect.email, logs a `ProspectActivity` (`email_received`), sets
      `needsReview: true`. Same effect as the old IMAP script's match/flag
      step, just reached from outside instead of the webapp reading mail
      itself.
- [x] `outlook-sync/` (local-machine-only, not deployed) - a PowerShell
      script using the same Outlook COM automation already set up earlier
      in this project, reading unread mail from jambo@zucegroup.com and
      POSTing each to the endpoint above, then marking it read. Scheduled
      via Windows Task Scheduler on the dev machine - runs independent of
      the resource-constrained cPanel account entirely.
- [x] Removed: `scripts/check-inbox.js`, its cron job, the IMAP settings
      fields (Admin > Settings > Email), and the `imapflow`/`mailparser`
      dependencies - no longer needed now the webapp never touches a real
      mailbox.
- [ ] If an Anthropic API key becomes available later, classification and
      AI-drafted replies can slot in on top of this foundation (either in
      the API endpoint, or as a separate step) without changing the
      matching/flagging logic above.

## Phase D — sending via Outlook (rescoped a third time)

First cut had drafts sent via the webapp's own SMTP settings, with a
signature hand-coded in `mailer.js` to match Collins' Outlook signature.
Reconsidered: that's a copy to keep in sync by hand, and the project owner
would rather sending itself happen through Outlook (consistent with Phase
C's choice to keep Outlook as the real inbox too). New design:

- [x] Approving a draft in the review queue now sets `status: 'approved'`
      instead of sending anything - see `crm.controller.js`'s
      `approveDraft`.
- [x] `GET /api/crm/outreach-approved` / `POST /api/crm/outreach-sent/:id`
      (API-key authenticated, same key as Phase C's inbox-sync endpoint) -
      the Outlook side polls the first, reports back via the second.
- [x] `outlook-sync/send-approved-drafts.ps1` (local-machine-only) - reads
      Collins' signature fresh from Outlook's own signature file every run
      (not a copy in code, so an Outlook-side signature update needs no
      script change), builds each approved draft as a new Outlook
      `MailItem`, and sends it.
- [x] Removed: `sendOutreachEmail`/`buildSignatureHtml` from `mailer.js`
      and the signature logo asset - dead code once sending moved to
      Outlook.
- [ ] **Still needed:** the `send-approved-drafts.ps1` Task Scheduler entry
      (see `outlook-sync/README.md`) - not set up yet, so approved drafts
      currently need a manual run of that script to actually go out.

## Explicitly out of scope for now

- Autonomous meeting booking/calendar integration - meetings stay
  human-handled per the original ask ("come in as human... for a meeting").
- Sending the *first* outreach message to any prospect without human
  approval - stays a hard gate regardless of classification confidence.
