Files
hub/docs/messaging.md
kelly ce5c670bf2 feat: Add AI Copilot module with multi-provider support + brand-scoped campaigns + comprehensive docs
## AI Copilot Module System
- Add copilot_enabled flag to businesses table
- Add Copilot Module toggle in Filament admin (Premium Features)
- Gate all Copilot buttons with copilot_enabled check
- Enable by default for Cannabrands only

## AI Settings Multi-Provider Support
- Support 5 AI providers: Anthropic, OpenAI, Perplexity, Canva, Jasper
- Separate encrypted API keys per provider
- Model dropdowns populated from config/ai.php
- Test Connection feature with real API validation
- Existing Connections summary shows status for all providers
- Provider-specific settings only shown when provider selected

## Brand-Scoped Campaign System
- Add brand_id to broadcasts table
- Brand selector component (reusable across forms)
- Campaign create/edit requires brand selection
- All campaigns now scoped to specific brand

## Documentation (9 New Files)
- docs/modules.md - Module system architecture
- docs/messaging.md - Messaging and conversation system
- docs/copilot.md - AI Copilot features and configuration
- docs/segmentation.md - Buyer segmentation system
- docs/sendportal.md - SendPortal multi-brand integration
- docs/campaigns.md - Campaign creation and delivery flow
- docs/conversations.md - Conversation lifecycle and threading
- docs/brand-settings.md - Brand configuration and voice system
- docs/architecture.md - High-level system overview

## Bug Fixes
- Remove duplicate FailedJobResource (Horizon already provides this at /horizon/failed)
- Fix missing Action import in Filament resources
- Update brand policy for proper access control

## Database Migrations
- 2025_11_23_175211_add_copilot_enabled_to_businesses_table.php
- 2025_11_23_180000_add_brand_id_to_broadcasts_table.php
- 2025_11_23_180326_update_ai_settings_for_multiple_providers.php
- 2025_11_23_184331_add_new_ai_providers_to_ai_settings.php

## Notes
- Pint:  Passed (all code style checks)
- Tests: Failing due to pre-existing database schema dump conflicts (not related to these changes)
- Schema issue needs separate fix: pgsql-schema.sql contains tables that migrations also create
2025-11-23 12:31:19 -07:00

5.4 KiB

Messaging System Architecture

Overview

The messaging system provides unified conversation threading for Email and SMS communications between brands and their buyers. All messages are organized into conversations with full delivery tracking.

Database Schema

Tables

conversations

  • id - Primary key
  • brand_id - Owner brand
  • buyer_business_id - Buyer/contact business
  • contact_id - Specific contact (nullable)
  • subject - Conversation subject
  • status - open, closed
  • last_message_at - Timestamp of most recent message
  • created_at, updated_at

messages

  • id - Primary key
  • conversation_id - Parent conversation
  • brand_id - Sending/receiving brand
  • direction - inbound or outbound
  • channel - email or sms
  • from - Sender address/number
  • to - Recipient address/number (can be JSON array for multi-recipient)
  • subject - Email subject (nullable for SMS)
  • body - Message content (HTML for email, plain text for SMS)
  • message_id - External provider message ID
  • in_reply_to - Email threading header
  • references - Email threading references
  • delivery_status - Delivery state (see below)
  • delivery_status_detail - Provider-specific status detail
  • delivery_attempted_at - When delivery was attempted
  • delivery_detail_message - Human-readable delivery message
  • created_at, updated_at

conversation_participants

  • conversation_id
  • participant_type - App\Models\Business or App\Models\Contact
  • participant_id
  • joined_at
  • left_at (nullable)

Inbound Message Flow

Inbound Email

  1. Receiving: Email arrives at brand's custom inbox (e.g., support@cannabrands.sendportal.io)
  2. Mailbox Processing: BrandEmailMailbox class processes via Laravel Mailbox
  3. Parsing:
    • Extract From, To, Subject, Body, Message-ID, In-Reply-To, References
    • Identify brand from recipient email
    • Find or create contact from sender email
  4. Threading:
    • Check for existing conversation using In-Reply-To or References headers
    • If found, append to conversation
    • If not found, create new conversation
  5. Storage: Create Message record with direction = 'inbound', channel = 'email'

Inbound SMS

  1. Receiving: SMS webhook from Twilio/provider hits /webhooks/sms/inbound
  2. Controller Processing: SmsController@handleInbound
  3. Parsing:
    • Extract From (phone number), To (brand's phone number), Body
    • Identify brand from recipient phone number
    • Find or create contact from sender phone number
  4. Threading:
    • Check for existing open conversation between brand and contact
    • If found and recent, append to conversation
    • If not found or old, create new conversation
  5. Storage: Create Message record with direction = 'inbound', channel = 'sms'

Outbound Message Flow

Outbound Email

  1. Composition: Brand composes message in /s/{business}/messaging/{conversation}/show
  2. Sending:
    • Use brand's configured email channel (SendPortal, SMTP, etc.)
    • Set From to brand's email
    • Set Message-ID, In-Reply-To, References for threading
  3. Storage: Create Message record with direction = 'outbound', channel = 'email'
  4. Delivery Tracking:
    • Initial status: pending or queued
    • Provider callbacks update status (see Delivery Status below)

Outbound SMS

  1. Composition: Brand composes SMS message
  2. Sending:
    • Use Twilio API with brand's phone number
    • Character limit: 1600 chars (10 segments)
  3. Storage: Create Message record with direction = 'outbound', channel = 'sms'
  4. Delivery Tracking: Twilio webhooks update delivery status

Delivery Status Fields

delivery_status Enum

Status Description Color
pending Queued, not yet sent Gray
sent Successfully handed to provider Blue
delivered Confirmed delivered to recipient Green
failed Delivery failed Red
bounced Email bounced Red
opened Email opened (tracking pixel) Green
clicked Link clicked in message Green

delivery_status_detail

Provider-specific status code:

  • Twilio: delivered, undelivered, failed, queued, sent, receiving, received
  • SendPortal: Event types from webhook
  • SMTP: Bounce codes, error messages

delivery_detail_message

Human-readable message:

  • "Delivered to recipient's device"
  • "Message bounced: Invalid email address"
  • "Failed: Phone number unreachable"

delivery_attempted_at

Timestamp when delivery was last attempted (for retries and tracking).

Conversation Features

Filters

Available in /s/{business}/messaging/index:

  • Status: all, open, closed
  • Unread: Show conversations with unread messages
  • Channel: email, sms, or all

Full-text search across:

  • Conversation subject
  • Participant names/emails
  • Message body content

Close/Reopen

  • Close: Mark conversation as closed (still viewable, no notifications)
  • Reopen: Mark as open again (resumes notifications)
  • Route: POST /s/{business}/messaging/{conversation}/close or /reopen

Timeline Display Rules

Messages displayed in chronological order with:

  • Sender name/email/phone
  • Timestamp (relative: "2 hours ago")
  • Direction indicator (inbound badge vs outbound styling)
  • Delivery status badge (for outbound messages)
  • Channel icon (email/SMS)