PHPackages                             azaharizaman/nexus-messaging - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Mail &amp; Notifications](/categories/mail)
4. /
5. azaharizaman/nexus-messaging

ActiveLibrary[Mail &amp; Notifications](/categories/mail)

azaharizaman/nexus-messaging
============================

Channel-agnostic, immutable communication record management for Email, SMS, Chat, Webhooks with protocol abstraction

v0.1.0-alpha1(1mo ago)02↓100%MITHTMLPHP ^8.3

Since May 5Pushed 1mo agoCompare

[ Source](https://github.com/azaharizaman/nexus-messaging)[ Packagist](https://packagist.org/packages/azaharizaman/nexus-messaging)[ RSS](/packages/azaharizaman-nexus-messaging/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (2)Versions (2)Used By (0)

Nexus\\Messaging
================

[](#nexusmessaging)

**Channel-agnostic, immutable communication record management for Email, SMS, Chat, WhatsApp, and more.**

[![PHP Version](https://camo.githubusercontent.com/c8d8dad6beb757a2b8acba331d16140813699543b88a37af0a81f20bd35f61de/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e332532422d626c7565)](https://php.net)[![License](https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e)](LICENSE)![Test Coverage](https://camo.githubusercontent.com/2b732858c71e7bf8132caff599a40b22368d09b5026f643738bec8c99b83e45e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f7665726167652d39352532352d627269676874677265656e)

---

📦 Overview
----------

[](#-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

[](#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
-----------

[](#-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 &amp; Audit:** Immutable records for SOX, GDPR, HIPAA
- **ERP Systems:** Communication history on orders, invoices, shipments

---

🚀 Installation
--------------

[](#-installation)

```
composer require azaharizaman/nexus-messaging:"*@dev"
```

---

✨ Features
----------

[](#-features)

### Level 1 (MVP)

[](#level-1-mvp)

- ✅ Immutable `MessageRecord` value 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)

[](#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)

[](#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
-------------

[](#-quick-start)

### 1. Implement Repository Interface

[](#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

[](#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

[](#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

[](#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

[](#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
---------------

[](#️-architecture)

### Value Objects

[](#value-objects)

- **`MessageRecord`** - Immutable aggregate root containing all message data
- **`AttachmentMetadata`** - Attachment references (no file I/O)

### Enums

[](#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

[](#contracts)

- **`MessagingRepositoryInterface`** - Persistence abstraction
- **`MessagingConnectorInterface`** - External provider abstraction
- **`RateLimiterInterface`** - High-volume throttling
- **`MessageTemplateEngineInterface`** - Template rendering

### Services

[](#services)

- **`MessageManager`** - Core orchestrator (send, receive, query)

---

🔌 Supported Channels &amp; Providers
------------------------------------

[](#-supported-channels--providers)

The package is **protocol-agnostic**. The application layer implements connectors for specific providers:

ChannelExample ProvidersImplementation**Email**SendGrid, Postmark, AWS SES, SMTPVia `MessagingConnectorInterface`**SMS**Twilio, Nexmo, AWS SNSVia `MessagingConnectorInterface`**WhatsApp**Twilio WhatsApp API, Meta Business APIVia `MessagingConnectorInterface`**iMessage**Apple Business ChatVia `MessagingConnectorInterface`**Phone Call**Twilio Voice, SIPLog call notes as messages**Chat**Slack, Discord, MS TeamsVia `MessagingConnectorInterface`**Webhook**Custom HTTP webhooksGeneric webhook handler**Internal Note**Internal system notesNo external provider---

📊 Protocol Abstraction Pattern
------------------------------

[](#-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 &amp; Security
---------------------------

[](#-compliance--security)

### PII Handling (L3.2)

[](#pii-handling-l32)

```
$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)

[](#encryption-neutrality-l37)

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)

[](#archival-policies-l36)

```
// 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
--------------------------

[](#-high-volume-optimization)

### Rate Limiting (L3.1)

[](#rate-limiting-l31)

```
$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)

[](#optimized-timeline-loading-l34)

```
// Fast query for UI timeline (limit 20, optimized indexes)
$latestMessages = $messageManager->getLatestMessages(
    entityType: 'customer',
    entityId: 'cust-123',
    limit: 20
);
```

---

🧪 Testing
---------

[](#-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
----------------------

[](#-available-interfaces)

### MessagingRepositoryInterface

[](#messagingrepositoryinterface)

```
saveRecord(MessageRecord): void
findById(string): ?MessageRecord
findByEntity(string, string, int, int): array
findLatestByEntity(string, string, int): array
findByTenant(string, int, int): array
findBySender(string, int, int): array
findByChannel(string, string, int, int): array
countByEntity(string, string): int
```

### MessagingConnectorInterface

[](#messagingconnectorinterface)

```
send(MessageRecord): MessageRecord
processInboundWebhook(array): MessageRecord
getSupportedChannel(): string
isConfigured(): bool
```

### RateLimiterInterface (Optional)

[](#ratelimiterinterface-optional)

```
allowAction(string, int, int): bool
remainingAttempts(string, int): int
availableIn(string): int
clear(string): void
```

### MessageTemplateEngineInterface (Optional)

[](#messagetemplateengineinterface-optional)

```
render(string, array): string
templateExists(string): bool
renderSubject(string, array): ?string
```

---

🔗 Integration with Other Nexus Packages
---------------------------------------

[](#-integration-with-other-nexus-packages)

PackageIntegration PointUsage**Nexus\\Party**`senderPartyId`, `recipientPartyId`Link messages to Party entities**Nexus\\AuditLogger**Optional `$auditLogger` callbackLog "message\_sent", "message\_received" events**Nexus\\Connector**Application layer uses itExternal API integration**Nexus\\Tenant**`tenantId` fieldMulti-tenant isolation**Nexus\\Telemetry**Optional `TelemetryTrackerInterface`Track message metrics**Nexus\\SSO**User attribution`senderPartyId` from authenticated user---

🎓 Best Practices
----------------

[](#-best-practices)

1. **Always use ULIDs for message IDs** - Sortable, globally unique
2. **Set `containsPII` flag** - When messages contain sensitive data
3. **Implement rate limiting** - For production environments
4. **Use optimized queries** - `findLatestByEntity()` for UI timelines
5. **Validate provider responses** - In connector implementations
6. **Log delivery failures** - For debugging and monitoring
7. **Test webhook parsers** - Validate all provider webhook formats

---

📖 Documentation
---------------

[](#-documentation)

- [Getting Started](docs/getting-started.md) - Quick start guide
- [API Reference](docs/api-reference.md) - Complete API documentation
- [Integration Guide](docs/integration-guide.md) - Laravel/Symfony examples
- [Examples](docs/examples/) - Working code samples
- [Requirements](REQUIREMENTS.md) - All 20 requirements tracked
- [Implementation Summary](IMPLEMENTATION_SUMMARY.md) - Development metrics
- [Test Suite Summary](TEST_SUITE_SUMMARY.md) - Test coverage report
- [Valuation Matrix](VALUATION_MATRIX.md) - Package business value

---

🤝 Contributing
--------------

[](#-contributing)

This package follows strict Nexus architectural guidelines:

- ✅ Framework-agnostic (no Laravel/Symfony dependencies)
- ✅ Immutable value objects with `readonly` properties
- ✅ Native PHP 8.3 enums
- ✅ Constructor property promotion
- ✅ Strict types (`declare(strict_types=1)`)
- ✅ PSR-12 coding standards
- ✅ 95%+ test coverage

---

📄 License
---------

[](#-license)

MIT License. See [LICENSE](LICENSE) for details.

---

🙏 Credits
---------

[](#-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
---------------

[](#-documentation-1)

### Package Documentation

[](#package-documentation)

- **[Getting Started Guide](docs/getting-started.md)** - Quick start guide with prerequisites and basic configuration
- **[API Reference](docs/api-reference.md)** - Complete documentation of all interfaces and components
- **[Integration Guide](docs/integration-guide.md)** - Laravel and Symfony integration examples
- **[Basic Usage Example](docs/examples/basic-usage.php)** - Simple usage patterns
- **[Advanced Usage Example](docs/examples/advanced-usage.php)** - Advanced scenarios

### Additional Resources

[](#additional-resources)

- `IMPLEMENTATION_SUMMARY.md` - Implementation progress and metrics
- `REQUIREMENTS.md` - Detailed requirements
- `TEST_SUITE_SUMMARY.md` - Test coverage and results
- `VALUATION_MATRIX.md` - Package valuation metrics
- See root `ARCHITECTURE.md` for overall system architecture

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance93

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity34

Early-stage or recently created project

 Bus Factor1

Top contributor holds 76.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

36d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/117408?v=4)[Azahari Zaman](/maintainers/azaharizaman)[@azaharizaman](https://github.com/azaharizaman)

---

Top Contributors

[![azaharizaman](https://avatars.githubusercontent.com/u/117408?v=4)](https://github.com/azaharizaman "azaharizaman (460 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (139 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

---

Tags

emailsmsmessagingtimelinechatwhatsappcommunicationaudit-trailconversation

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/azaharizaman-nexus-messaging/health.svg)

```
[![Health](https://phpackages.com/badges/azaharizaman-nexus-messaging/health.svg)](https://phpackages.com/packages/azaharizaman-nexus-messaging)
```

###  Alternatives

[mageplaza/module-smtp

SMTP Extension for Magento 2 helps the owner of store simply install SMTP (Simple Mail Transfer Protocol) server which transmits the messages into codes or numbers

3116.1M9](/packages/mageplaza-module-smtp)[infobip/infobip-api-php-client

PHP library for consuming Infobip's API

961.9M10](/packages/infobip-infobip-api-php-client)[symfony/fake-sms-notifier

Fake SMS (as email or log during development) Notifier Bridge.

27826.9k1](/packages/symfony-fake-sms-notifier)[cmdotcom/text-sdk-php

PHP SDK to send messages with CM.com

25723.6k4](/packages/cmdotcom-text-sdk-php)[symfony/fake-chat-notifier

Fake Chat (as email or log during development) Notifier Bridge.

10306.1k4](/packages/symfony-fake-chat-notifier)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
