# LeadPilot — Authoritative Acceptance Criteria (P0 Verification)

**Document Version:** 1.0.0 (Phase 1 Scope Lock)  
**Status:** Approved & Ready for Test Generation  

---

## 1. Multi-Tenancy & Workspace Security

* **AC-TENANT-01 (Strict Isolation):** A user belonging exclusively to Workspace A who attempts to access `/leads/{uuid_from_workspace_b}` via direct URL or API MUST receive HTTP 404 (Not Found).
* **AC-TENANT-02 (Database Query Scoping):** Every SQL query generated by Eloquent for workspace-bound entities MUST include `WHERE workspace_id = ?` matching the session's active workspace.
* **AC-TENANT-03 (Role Permissions):** 
  * A user with role `Member` MUST NOT be able to access Workspace Settings, Billing, or generate API Keys.
  * A user with role `Admin` or `Owner` MUST be able to invite members and manage workspace settings.

---

## 2. Lead Ingestion Engine

### Website Form Endpoint
* **AC-INGEST-01 (Valid Submission):** POSTing valid form data (`first_name`, `email`, `message`) to `/api/v1/capture/form/{workspace_uuid}` creates exactly one lead with `source = 'Website Form'`, sets `stage = 'new'`, `status = 'active'`, and returns HTTP 200 with JSON payload `{ success: true }`.
* **AC-INGEST-02 (Anti-Spam Honeypot):** If the hidden input field `_hp_lead_time` or `_hp_verify` is populated in a form submission, the system MUST return HTTP 200 (to deceive the bot) but MUST NOT insert any lead into the database.
* **AC-INGEST-03 (Rate Limiting):** An IP address submitting more than 10 form submissions per minute to the capture endpoint MUST be throttled with HTTP 429 (Too Many Requests).

### REST API
* **AC-API-01 (Token Authentication):** Sending `POST /api/v1/leads` without a valid `Bearer` token or with a revoked token MUST return HTTP 401 (Unauthorized).
* **AC-API-02 (Idempotency):** Submitting identical lead payloads with the same `Idempotency-Key` header twice within 24 hours MUST return the cached HTTP 201 response and MUST NOT create a second lead in the database.

### Inbound Webhook
* **AC-WH-01 (Payload Ingestion):** Inbound webhook payload mapping MUST successfully extract deeply nested fields (e.g. `data.contact.email`) into the `leads.email` column based on the workspace's JSON path configuration.
* **AC-WH-02 (Malformed Payload Safety):** A corrupt or non-JSON webhook payload MUST return HTTP 400, record an entry in `webhook_logs` with `status = 'failed'`, and MUST NOT crash the background queue worker.

### CSV Import
* **AC-CSV-01 (Chunked Processing):** Uploading a CSV file with 500 records MUST process asynchronously in batches $\le 250$ rows without exceeding PHP execution memory limits ($< 64\text{MB}$).
* **AC-CSV-02 (Duplicate Strategy):** When CSV import is configured with `Skip Duplicates`, any row with an email matching an existing lead in the workspace MUST be skipped and reported in the final import summary.

### Manual Lead Creation
* **AC-MANUAL-01 (Validation):** Submitting the manual lead modal without providing either a valid `email` or a valid `phone` MUST fail validation and display an inline error message.

---

## 3. Lead Management & 360 Detail View

* **AC-MGMT-01 (Instant Search):** Typing in the lead search bar MUST filter leads by first name, last name, email, company, and phone with a query execution time $< 100\text{ms}$ on a dataset of 5,000 leads.
* **AC-MGMT-02 (Activity Audit):** Changing any core lead field (`assigned_user_id`, `pipeline_stage`, `deal_value`) MUST create an immutable activity entry with user ID, previous value, new value, and timestamp.
* **AC-MGMT-03 (Note Creation):** Adding an internal note in the 360 view MUST instantly display the note at the top of the activity timeline without requiring a full-page reload.

---

## 4. Pipeline & State Progression

* **AC-PIPE-01 (Linear Kanban Move):** Dragging a lead card from `New` to `Contacted` on the Kanban board MUST update `lead.pipeline_stage = 'contacted'` and lock `lead.first_contacted_at` to the current timestamp.
* **AC-PIPE-02 (Won Trigger):** Moving a lead to `Won` MUST set `lead.status = 'won'`, `lead.won_at = NOW()`, and automatically cancel all active/scheduled follow-ups for that lead.
* **AC-PIPE-03 (Mandatory Lost Reason):** Moving a lead to `Lost` MUST trigger the Lost Reason Modal. If the user cancels or submits without selecting a valid reason from the dictionary, the stage transition MUST NOT be committed.

---

## 5. AI Lead Intelligence & Safety Boundary

* **AC-AI-01 (Structured Output Compliance):** The AI Qualification service MUST return a validated JSON object conforming to the schema: `{ score: int(0-100), temperature: enum(HOT,WARM,COLD), intent: string, urgency: enum(LOW,MED,HIGH), fit_summary: string, reason: string, recommended_action: string }`.
* **AC-AI-02 (Zero Ingestion Blocking):** If the LLM provider returns an HTTP 500 error or times out ($> 8\text{ seconds}$), the lead ingestion MUST succeed with `ai_status = 'fallback_rules'` and deterministic scoring applied.
* **AC-AI-03 (No Autonomous State Mutating):** The AI worker MUST NEVER mutate `lead.pipeline_stage` or `lead.status` directly; it is strictly restricted to updating the `ai_intelligence` relation.

---

## 6. Follow-up Engine & Sequences

* **AC-FLW-01 (Due State Calculation):** A follow-up scheduled for timestamp $T$ MUST be categorized as `due` when $\text{NOW}() \ge T$ and $\text{NOW}() < T + 24\text{ hours}$, and as `overdue` when $\text{NOW}() \ge T + 24\text{ hours}$.
* **AC-FLW-02 (Auto-Pause Invariant):** When an inbound communication is logged for a lead or when the lead moves to `Won`/`Lost`, any active follow-up sequence MUST immediately transition to `status = 'paused'` or `status = 'cancelled'`.
* **AC-FLW-03 (Template Merge Tags):** Selecting a template containing `{{lead.first_name}}` and `{{workspace.name}}` MUST correctly interpolate the lead's first name and active workspace name.

---

## 7. "No Lead Left Behind" Attention Engine

* **AC-ATTN-01 (Hot Lead Overdue):** A lead with `pipeline_stage = 'new'` and `ai_intelligence.temperature = 'HOT'` that remains uncontacted for $> 2\text{ hours}$ MUST be surfaced in the Attention Hub with urgency level `URGENT`.
* **AC-ATTN-02 (Stale Proposal Alert):** A lead with `pipeline_stage = 'proposal'` with zero logged activities for $> 5\text{ days}$ MUST be surfaced in the Attention Hub with the alert *"Stale Proposal"*.
* **AC-ATTN-03 (1-Click Resolution):** Clicking "Mark Contacted" or "Reschedule" on an attention card MUST immediately remove the item from the active attention queue.

---

## 8. Dashboard Telemetry & Recovered Revenue

* **AC-DASH-01 (First Response Time Accuracy):** Median First Response Time on the dashboard MUST be calculated as the difference between `created_at` and `first_contacted_at` for all leads created in the selected date range.
* **AC-DASH-02 (Recovered Lead Attribution):** A lead MUST increment the "Leads Recovered" counter if and ONLY if:
  1. It had an active attention condition for $\ge 48\text{ hours}$.
  2. A follow-up or contact action was logged.
  3. The lead was marked `Won` or advanced stage within 30 days of that action.
* **AC-DASH-03 (Recovered Revenue Calculation):** The "Recovered Revenue" card on the dashboard MUST equal the exact mathematical sum of `deal_value` for leads satisfying AC-DASH-02.
