azaharizaman / nexus-messaging
Channel-agnostic, immutable communication record management for Email, SMS, Chat, Webhooks with protocol abstraction
Package info
github.com/azaharizaman/nexus-messaging
Language:HTML
pkg:composer/azaharizaman/nexus-messaging
Requires
- php: ^8.3
Requires (Dev)
- phpunit/phpunit: ^11.0
- psr/log: ^3.0
This package is auto-updated.
Last update: 2026-05-05 02:59:16 UTC
README
Channel-agnostic, immutable communication record management for Email, SMS, Chat, WhatsApp, and more.
๐ฆ Overview
Nexus\Messaging is a framework-agnostic PHP package that provides atomic, stateless management of communication records across multiple channels (Email, SMS, WhatsApp, iMessage, Phone Calls, etc.). It separates the WHAT (immutable record of conversation) from the HOW (protocol-specific sending logic), making it a reusable, protocol-agnostic foundation for any communication system.
Key Principles
- ๐ Immutable Records: Once created, message records cannot be modified (append-only timeline)
- ๐ Protocol Abstraction: Supports any provider (Twilio, SendGrid, Meta) via connector interface
- ๐ข Multi-Tenant: Native tenant isolation for SaaS applications
- ๐ Compliance-Ready: PII flags, archival policies, audit trails
- โก Framework-Agnostic: Pure PHP 8.3 - works with Laravel, Symfony, or vanilla PHP
๐ฏ Use Cases
- Customer Support Systems: Build conversation timelines on case/ticket screens
- CRM Platforms: Track all customer communications in one place
- Marketing Automation: Store campaign messages with delivery tracking
- Multi-Channel Messaging: Unify Email, SMS, WhatsApp under single API
- Compliance & Audit: Immutable records for SOX, GDPR, HIPAA
- ERP Systems: Communication history on orders, invoices, shipments
๐ Installation
composer require azaharizaman/nexus-messaging:"*@dev"
โจ Features
Level 1 (MVP)
- โ
Immutable
MessageRecordvalue object - โ Channel abstraction (Email, SMS, WhatsApp, etc.)
- โ Direction tracking (Inbound/Outbound)
- โ Repository interface for persistence
- โ Entity association (build conversation timelines)
- โ Audit event integration
Level 2 (Professional)
- โ Delivery status tracking (Pending โ Sent โ Delivered โ Failed)
- โ Provider reference IDs (Twilio SID, SendGrid ID, etc.)
- โ Connector interface for external providers
- โ Inbound webhook processing
- โ Tenant isolation (multi-tenant SaaS)
- โ Attachment metadata (no file I/O)
- โ Channel-specific metadata storage
Level 3 (Enterprise)
- โ Rate limiting interface
- โ PII compliance flags
- โ Template engine abstraction
- โ Optimized timeline queries
- โ SSO user attribution
- โ Archival status (retention policies)
- โ Encryption neutrality
๐ Quick Start
1. Implement Repository Interface
use Nexus\Messaging\Contracts\MessagingRepositoryInterface; use Nexus\Messaging\ValueObjects\MessageRecord; final class EloquentMessagingRepository implements MessagingRepositoryInterface { public function saveRecord(MessageRecord $record): void { DB::table('messages')->insert($record->toArray()); } public function findById(string $id): ?MessageRecord { $data = DB::table('messages')->where('id', $id)->first(); // ... convert to MessageRecord VO } public function findByEntity(string $entityType, string $entityId, int $limit = 50, int $offset = 0): array { // ... query implementation } // ... other methods }
2. Implement Connector Interface
use Nexus\Messaging\Contracts\MessagingConnectorInterface; use Nexus\Messaging\ValueObjects\MessageRecord; use Nexus\Messaging\Enums\DeliveryStatus; final class TwilioWhatsAppConnector implements MessagingConnectorInterface { public function send(MessageRecord $draft): MessageRecord { // Call Twilio API $response = $this->twilioClient->messages->create( "whatsapp:{$draft->recipientPartyId}", [ 'from' => "whatsapp:{$this->twilioNumber}", 'body' => $draft->body ] ); // Return updated record with delivery status return $draft->withDeliveryStatus( DeliveryStatus::Sent, $response->sid ); } public function processInboundWebhook(array $payload): MessageRecord { // Parse Twilio webhook payload return MessageRecord::createInbound( id: $this->generateId(), channel: Channel::WhatsApp, subject: null, body: $payload['Body'], receivedAt: new \DateTimeImmutable($payload['DateCreated']), senderPartyId: $this->parsePhoneNumber($payload['From']), recipientPartyId: $this->parsePhoneNumber($payload['To']), tenantId: $this->getCurrentTenantId(), providerReferenceId: $payload['MessageSid'] ); } public function getSupportedChannel(): string { return 'whatsapp'; } public function isConfigured(): bool { return !empty($this->twilioAccountSid); } }
3. Send Outbound Message
use Nexus\Messaging\Services\MessageManager; use Nexus\Messaging\Enums\Channel; $messageManager = new MessageManager( repository: $messagingRepository, connector: $twilioConnector, logger: $logger ); // Send WhatsApp message $message = $messageManager->sendMessage( id: 'msg-' . Str::ulid(), channel: Channel::WhatsApp, subject: null, body: 'Hello! Your order has shipped.', senderPartyId: 'company-support', recipientPartyId: '+60123456789', tenantId: 'tenant-001', entityType: 'order', entityId: 'order-12345' ); echo "Message sent: {$message->deliveryStatus->label()}";
4. Process Inbound Webhook
// Webhook endpoint (e.g., Laravel controller) public function handleTwilioWebhook(Request $request) { $inboundMessage = $messageManager->processInboundWebhook( $request->all() ); // Message automatically saved to database // Can trigger workflows, notifications, etc. return response('OK', 200); }
5. Build Conversation Timeline
// Get all messages for a support case $timeline = $messageManager->getConversationTimeline( entityType: 'case', entityId: 'case-789', limit: 50 ); foreach ($timeline as $message) { echo "{$message->sentAt->format('Y-m-d H:i')} - "; echo "{$message->direction->label()} {$message->channel->label()}: "; echo "{$message->body}\n"; }
๐๏ธ Architecture
Value Objects
MessageRecord- Immutable aggregate root containing all message dataAttachmentMetadata- Attachment references (no file I/O)
Enums
Channel- Communication channels (Email, SMS, WhatsApp, etc.)Direction- Message flow (Inbound/Outbound)DeliveryStatus- Delivery lifecycle (Pending, Sent, Delivered, Failed)ArchivalStatus- Retention policy status
Contracts
MessagingRepositoryInterface- Persistence abstractionMessagingConnectorInterface- External provider abstractionRateLimiterInterface- High-volume throttlingMessageTemplateEngineInterface- Template rendering
Services
MessageManager- Core orchestrator (send, receive, query)
๐ Supported Channels & Providers
The package is protocol-agnostic. The application layer implements connectors for specific providers:
| Channel | Example Providers | Implementation |
|---|---|---|
| SendGrid, Postmark, AWS SES, SMTP | Via MessagingConnectorInterface |
|
| SMS | Twilio, Nexmo, AWS SNS | Via MessagingConnectorInterface |
| Twilio WhatsApp API, Meta Business API | Via MessagingConnectorInterface |
|
| iMessage | Apple Business Chat | Via MessagingConnectorInterface |
| Phone Call | Twilio Voice, SIP | Log call notes as messages |
| Chat | Slack, Discord, MS Teams | Via MessagingConnectorInterface |
| Webhook | Custom HTTP webhooks | Generic webhook handler |
| Internal Note | Internal system notes | No external provider |
๐ Protocol Abstraction Pattern
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Application Layer โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ TwilioWhatsAppConnector โ โ
โ โ implements MessagingConnectorInterface โ โ
โ โ โ โ
โ โ โข Knows Twilio API specifics โ โ
โ โ โข Transforms Twilio webhook โ MessageRecord โ โ
โ โ โข Handles OAuth, retries, errors โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Nexus\Messaging Package โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ MessagingConnectorInterface โ โ
โ โ โข send(MessageRecord): MessageRecord โ โ
โ โ โข processInboundWebhook(array): MessageRecord โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ MessageRecord (Value Object) โ โ
โ โ โข channel: Channel โ โ
โ โ โข body: string โ โ
โ โ โข deliveryStatus: DeliveryStatus โ โ
โ โ โข providerReferenceId: ?string โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Key Insight: The package defines Channel::WhatsApp without knowing what WhatsApp is. The connector implementation knows the Twilio-specific API details.
๐ Compliance & Security
PII Handling (L3.2)
$message = MessageRecord::createOutbound( // ... body: 'Your SSN is 123-45-6789', containsPII: true // Flag for compliance );
Application layer can:
- Encrypt body before persistence
- Restrict access logs
- Apply stricter retention policies
Encryption Neutrality (L3.7)
The package NEVER encrypts data itself. Encryption is the application layer's responsibility:
// Application layer implementation public function saveRecord(MessageRecord $record): void { $encryptedBody = $record->containsPII ? $this->encryptor->encrypt($record->body) : $record->body; DB::table('messages')->insert([ // ... other fields 'body' => $encryptedBody, 'encrypted' => $record->containsPII, ]); }
Archival Policies (L3.6)
// Mark messages for archival $archived = $message->withArchivalStatus(ArchivalStatus::PreArchived); // Application layer batch job $messagesToArchive = $repository->findByArchivalStatus( ArchivalStatus::PreArchived ); foreach ($messagesToArchive as $msg) { $this->archiver->moveToArchive($msg); }
โก High-Volume Optimization
Rate Limiting (L3.1)
$messageManager = new MessageManager( repository: $repository, connector: $connector, rateLimiter: $redisRateLimiter // Optional ); // Automatically enforced before sending $message = $messageManager->sendMessage(/* ... */); // Throws RateLimitExceededException if quota exceeded
Optimized Timeline Loading (L3.4)
// Fast query for UI timeline (limit 20, optimized indexes) $latestMessages = $messageManager->getLatestMessages( entityType: 'customer', entityId: 'cust-123', limit: 20 );
๐งช Testing
composer test
composer test:coverage
Example test:
public function test_can_send_whatsapp_message(): void { $connector = new TwilioWhatsAppConnector(/* ... */); $repository = new InMemoryMessageRepository(); $manager = new MessageManager($repository, $connector); $message = $manager->sendMessage( id: 'msg-001', channel: Channel::WhatsApp, subject: null, body: 'Hello', senderPartyId: 'party-1', recipientPartyId: '+60123456789', tenantId: 'tenant-1' ); $this->assertTrue($message->isOutbound()); $this->assertSame(DeliveryStatus::Sent, $message->deliveryStatus); }
๐ Available Interfaces
MessagingRepositoryInterface
saveRecord(MessageRecord): void findById(string): ?MessageRecord findByEntity(string, string, int, int): array<MessageRecord> findLatestByEntity(string, string, int): array<MessageRecord> findByTenant(string, int, int): array<MessageRecord> findBySender(string, int, int): array<MessageRecord> findByChannel(string, string, int, int): array<MessageRecord> countByEntity(string, string): int
MessagingConnectorInterface
send(MessageRecord): MessageRecord processInboundWebhook(array): MessageRecord getSupportedChannel(): string isConfigured(): bool
RateLimiterInterface (Optional)
allowAction(string, int, int): bool remainingAttempts(string, int): int availableIn(string): int clear(string): void
MessageTemplateEngineInterface (Optional)
render(string, array): string
templateExists(string): bool
renderSubject(string, array): ?string
๐ Integration with Other Nexus Packages
| Package | Integration Point | Usage |
|---|---|---|
| Nexus\Party | senderPartyId, recipientPartyId |
Link messages to Party entities |
| Nexus\AuditLogger | Optional $auditLogger callback |
Log "message_sent", "message_received" events |
| Nexus\Connector | Application layer uses it | External API integration |
| Nexus\Tenant | tenantId field |
Multi-tenant isolation |
| Nexus\Telemetry | Optional TelemetryTrackerInterface |
Track message metrics |
| Nexus\SSO | User attribution | senderPartyId from authenticated user |
๐ Best Practices
- Always use ULIDs for message IDs - Sortable, globally unique
- Set
containsPIIflag - When messages contain sensitive data - Implement rate limiting - For production environments
- Use optimized queries -
findLatestByEntity()for UI timelines - Validate provider responses - In connector implementations
- Log delivery failures - For debugging and monitoring
- Test webhook parsers - Validate all provider webhook formats
๐ Documentation
- Getting Started - Quick start guide
- API Reference - Complete API documentation
- Integration Guide - Laravel/Symfony examples
- Examples - Working code samples
- Requirements - All 20 requirements tracked
- Implementation Summary - Development metrics
- Test Suite Summary - Test coverage report
- Valuation Matrix - Package business value
๐ค Contributing
This package follows strict Nexus architectural guidelines:
- โ Framework-agnostic (no Laravel/Symfony dependencies)
- โ
Immutable value objects with
readonlyproperties - โ Native PHP 8.3 enums
- โ Constructor property promotion
- โ
Strict types (
declare(strict_types=1)) - โ PSR-12 coding standards
- โ 95%+ test coverage
๐ License
MIT License. See LICENSE for details.
๐ Credits
Developed by the Nexus Development Team as part of the Nexus ERP ecosystem.
Package Status: โ
Production Ready
Version: 1.0.0
Last Updated: November 24, 2025
๐ Documentation
Package Documentation
- Getting Started Guide - Quick start guide with prerequisites and basic configuration
- API Reference - Complete documentation of all interfaces and components
- Integration Guide - Laravel and Symfony integration examples
- Basic Usage Example - Simple usage patterns
- Advanced Usage Example - Advanced scenarios
Additional Resources
IMPLEMENTATION_SUMMARY.md- Implementation progress and metricsREQUIREMENTS.md- Detailed requirementsTEST_SUITE_SUMMARY.md- Test coverage and resultsVALUATION_MATRIX.md- Package valuation metrics- See root
ARCHITECTURE.mdfor overall system architecture