# REVOPS-LI-007 — Ghosted Proposal 5-Day Check-In

This package implements the proposal recovery blueprint as seven coordinated n8n workflows with HubSpot as the CRM system of record.

## Workflow architecture

1. **Daily ghosted proposal detector** searches configured open proposal stages, applies the 5–7 day window, checks HubSpot activity timestamps, and retrieves contact/company context.
2. **Follow-up planner and routing** creates a deterministic personalized draft, optionally enhances it with an AI model, and creates owner tasks for manual or high-value cases.
3. **High-value approval API** provides protected pending-review and approve/reject endpoints with single-use tokens.
4. **Revalidated SMTP sender** fetches fresh HubSpot data immediately before sending, sends only eligible email cases, and logs the result to HubSpot.
5. **Reply intake** receives authenticated reply events, marks the deal re-engaged, logs a note, and assigns a high-priority owner task.
6. **HubSpot property setup** creates the required deal properties.
7. **Operations** records failures and reports workflow status counts.

PostgreSQL provides idempotency, queue state, approvals, and an append-only audit trail. HubSpot holds the current deal state and timeline records.

## Channel behavior

Email and CRM-email proposals can use SMTP automation. LinkedIn, WhatsApp, SMS, and manual sales channels generate a HubSpot task because HubSpot CRM activity records do not provide a universal outbound transport for those services.

The sender uses a configured verified mailbox. If messages must come from each assigned salesperson, replace the single SMTP credential/from address with an owner-to-mailbox mapping or dedicated Gmail/Outlook nodes.

## Safety defaults

- `send_enabled` is `false` in workflow 04.
- AI enhancement is `false` in workflow 02.
- High-value deals require human approval.
- A deal/contact is retrieved again immediately before delivery.
- Changed stages, recent activity, proposal-date changes, email changes, opt-outs, and do-not-contact flags block delivery.
- The SMTP node has no automatic retry.
- A stale `SENDING` case becomes `SEND_REVIEW_REQUIRED`; it is never automatically resent.
- Stable UUIDs prevent duplicate reply processing, tasks, and notes.

## Required HubSpot setup

Run workflow 06 once. Your proposal process must populate at least:

- `revops_proposal_sent_at`
- `revops_proposal_channel`
- proposal context fields used in the draft

Set the internal HubSpot deal-stage IDs in workflows 01 and 04. Labels such as “Proposal Sent” are not API stage IDs. Obtain internal IDs from HubSpot pipeline settings or the Pipelines API.

The private app requires read/write access for deals, contacts, companies, tasks, and notes. Verify the exact scopes shown by your HubSpot portal.

## Installation

1. Run `database-setup.sql` on the PostgreSQL database used by n8n.
2. Import all seven `.n8n.json` files.
3. Attach the PostgreSQL credential to every PostgreSQL node.
4. Attach a HubSpot private-app Header Auth credential: header `Authorization`, value `Bearer YOUR_TOKEN`.
5. Configure SMTP in workflow 04.
6. Configure separate Header Auth credentials for approval and reply endpoints.
7. Replace all `REPLACE_...` values.
8. Set workflow 07 as the Error Workflow for workflows 01, 02, 04, and 05.
9. Run workflow 06 and test with HubSpot sandbox records.
10. Keep `send_enabled:false` until UAT confirms timing, suppression, ownership, associations, and message content.

## Detection rules

A deal can continue when:

- it remains open and in a configured proposal stage;
- its proposal is 5–7 days old;
- no meaningful activity timestamp is later than the proposal timestamp plus a 15-minute grace period;
- it has one associated contact;
- it has at most one associated company;
- the associated company does not have another open deal;
- the contact has an email and is not suppressed;
- the proposal channel is email or CRM email;
- no previous LI-007 follow-up state already handles it.

The activity check uses HubSpot summary properties for last activity, sales activity, notes, contact, and the LI-007 last-reply field. This is safer and more efficient than assuming that every associated engagement is customer activity. If your portal uses custom activity objects, add their authoritative timestamp to `DEAL_PROPS` and `ghosted-logic.js` before deployment.

## High-value approval

Set `high_value_threshold` in workflow 01. Deals at or above the threshold receive an approval task and do not enter the send queue until approved.

GET `/webhook/revops-li-007-pending` with the approval credential to list cases. POST `/webhook/revops-li-007-approval` with the same credential:

```json
{
  "case_id": "39a69165-5f79-4196-a2a6-2f383bc91674",
  "approval_token": "4cf616b0-c436-4743-9844-4a39278dbfcb",
  "decision": "APPROVE",
  "approver_email": "sales.manager@example.com",
  "note": "Approved after reviewing the proposal and draft."
}
```

Tokens expire after seven days and rotate after the first decision.

## AI drafting

The deterministic fallback template is always generated first. To enable AI enhancement:

1. configure the OpenAI Header Auth credential;
2. replace `REPLACE_OPENAI_MODEL` with an available model that supports structured outputs;
3. set `use_ai:true` in workflow 02.

The model receives selected CRM context and must return only a subject and body under a strict JSON schema. A failed or invalid response falls back to the deterministic message.

## Reply monitoring

Connect your inbound email provider, channel parser, or a HubSpot workflow to POST `/webhook/revops-li-007-reply` using the reply Header Auth credential:

```json
{
  "event_id": "85ad6438-a9cb-46d9-a498-54c014b818db",
  "deal_id": "123456789",
  "contact_id": "987654321",
  "reply_at": "2026-10-08T10:30:00Z",
  "channel": "email",
  "summary": "The prospect asked for clarification about implementation timing."
}
```

The endpoint intentionally accepts a bounded summary instead of requiring the raw email body. Replaying the same event UUID returns success without creating another note or task.

## HubSpot associations

The templates use HubSpot-defined association IDs for note-to-deal (`214`), note-to-contact (`202`), task-to-deal (`216`), and task-to-contact (`204`). Confirm these with `GET /crm/v4/associations/{fromObjectType}/{toObjectType}/labels` during UAT, especially if you replace standard objects with custom objects.

## Package contents

- `01-daily-ghosted-proposal-detector.n8n.json`
- `02-followup-planner-and-routing.n8n.json`
- `03-high-value-followup-approvals.n8n.json`
- `04-revalidated-smtp-sender-and-crm-logger.n8n.json`
- `05-reply-intake-and-owner-notification.n8n.json`
- `06-hubspot-proposal-property-setup.n8n.json`
- `07-proposal-recovery-operations.n8n.json`
- `database-setup.sql`
- `hubspot-proposal-properties.json`
- sample payloads and validation report

