add crm pipeline and suppression center
This commit is contained in:
@@ -154,6 +154,34 @@ Dashboard counts are clickable only when their scope and query semantics are cle
|
||||
|
||||
The Phase 11 slice now provides tenant-scoped saved-filter storage/listing, a bounded review-queue read, clickable dashboard filter metadata, and a bounded bulk review route (`POST /api/v1/businesses/bulk-review`) for verify/reject/assign. The current implementation is still pilot-grade: saved-filter update/delete routes are not wired, the queue does not yet expose full matching-set counts or filter snapshots, dashboard click metadata is not a complete predicate contract, bulk actions lack preview/idempotency/per-record outcomes, and audit coverage is aggregate for bulk operations. Production work requires those hardening items plus regression tests for suppression precedence, merge eligibility, cross-tenant IDs, stale counts, and partial bulk failure.
|
||||
|
||||
## Phase 12 CRM pipeline, interactions, outcomes, reporting, and suppression center
|
||||
|
||||
Phase 12 adds the CRM coordination contract around a tenant-scoped pipeline, an append-oriented interaction timeline, normalized interaction outcomes, bounded reporting, and a suppression center. These features are review and record-keeping tools; they do **not** turn the platform into an outreach system. Every read, write, export, report, and background operation must carry the authenticated `organization_id` scope, and a child ID, report ID, filter, or aggregate count is never authorization.
|
||||
|
||||
### Pipeline state and transition rules
|
||||
|
||||
The canonical lifecycle is `new` → `contacted` → `qualified` → `proposal` → `negotiation` → `won` or `lost`. The API exposes these configured stages; any future paused/disqualified state must be explicitly added to the tenant's stage configuration and may be reopened only by an authorized human with a reason. A transition must name the target state, actor, timestamp, and reason/source; the API validates transitions server-side and records the before/after state in the audit trail. Repeating the current state is idempotent, not a new transition. Direct jumps, client-supplied history, edits to historical transitions, and transitions for merged/inactive records are rejected. Reopening `lost`, `paused`, or `disqualified` creates a new transition and does not rewrite history.
|
||||
|
||||
An interaction may suggest a state change, but it never changes pipeline state implicitly. A state change and its related interaction/outcome are separate auditable events, and a failed or partial write must not leave a fabricated outcome. `won`/`lost` require an explicit outcome and reason; `won` is not proof of payment or fulfillment. Suppression/do-not-contact overrides every pipeline state and makes contact eligibility false.
|
||||
|
||||
### Interactions and outcome taxonomy
|
||||
|
||||
Interactions are append-only, tenant-scoped records of an operator-observed event. The record should retain the business/contact reference when known, channel (`note`, `phone`, `email`, `meeting`, or `other`), occurred time, actor, bounded redacted summary, provenance, and correlation/idempotency key. The current product does not send or validate communication: an interaction records what an operator says happened, not what the platform performed.
|
||||
|
||||
Outcomes are normalized and mutually explicit: `connected`, `no_answer`, `left_message`, `meeting_booked`, `meeting_held`, `qualified`, `disqualified`, `won`, `lost`, and `other`. `other` is an explicit catch-all, not proof of success or failure; missing/unknown data must not be silently converted to a negative outcome. `disqualified` and `lost` require an explicit reason under the configured workflow. `do_not_contact` is a separate safety state, immediately creates or confirms tenant suppression, and cannot be downgraded by a later positive outcome. Free-text notes supplement but do not replace the taxonomy; corrections append a new record rather than mutating history.
|
||||
|
||||
### Reporting, audit, tenant scope, and retention
|
||||
|
||||
Reports use an explicit `as_of` time, tenant scope, timezone, date interval, and inclusion policy. Pipeline reports count the latest effective state per active business; interaction reports count events by `occurred_at` (not ingestion time); outcome reports count normalized outcomes and may include a separate `unknown` bucket. Suppressed, merged, deleted, and inactive records must be labeled and excluded from contact-eligible totals; they must not silently disappear from safety/audit counts. Page counts, matching-set counts, and distinct-business counts are different metrics and must be named. Late-arriving or corrected interactions preserve original and corrected timestamps and are never double-counted without an explicit correction policy.
|
||||
|
||||
Audit events cover pipeline transitions, interaction/outcome creation or correction, suppression changes, report/export requests, and report results. Store tenant, actor, target, action, timestamps, safe reason, bounded filter/as-of snapshot or hash, policy/version, correlation/idempotency ID, and per-item outcomes where applicable. Redact full contact values and free text unless required for the approved purpose. Retain CRM records, suppression decisions, interaction provenance, report snapshots, and audit events according to the approved tenant/data-retention schedule; deletion or legal-hold behavior must be explicit and auditable. A report cache is tenant-keyed, bounded, and labeled with its `as_of`/freshness; it is never a live authorization decision.
|
||||
|
||||
### Suppression center and remaining outreach limitations
|
||||
|
||||
Suppression is a tenant-scoped deny list for email, domain, phone, and other approved identifiers. Matching is normalized server-side and must run before persistence, display, export, report inclusion as eligible, queueing, or any future action. Suppression wins over pipeline state, outcome, score, verification, cached data, and operator intent. The center must show the source, reason, actor, created/updated time, scope, and effective status; removal or expiry requires explicit authorization, reason, audit, and re-evaluation. Existing records remain visible as **Do not contact** and are not silently deleted. No Phase 12 route may send email/SMS, probe SMTP, validate an address by message, create a campaign, schedule follow-up delivery, or imply consent/deliverability. Any future outreach requires separate product, legal, security, and operational approval and must remain disabled by default.
|
||||
|
||||
Phase 12 remains pilot-grade until transition validation, immutable interaction/outcome history, suppression precedence, report definitions/timezones, retention/deletion jobs, export controls, idempotent writes, and cross-tenant regression tests are exercised end to end. The current Compose stack still has no durable CRM worker, scheduler, delivery provider, or outreach capability.
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user