1. Overview
1.1 What WhatsApp Integration Is
Shumoul.Saas.WhatsAppIntegration is a standalone, narrowly-scoped library that owns everything required to
speak to Meta's WhatsApp Cloud API: the HTTP client, webhook signature validation, webhook payload parsing,
and the provider-facing DTOs and configuration shapes. It ships as three NuGet packages — Contracts,
Abstractions, Core — consumed by Shumoul.Saas.Api via ordinary PackageReference, never
ProjectReference (see the platform's Dependency Law in docs/ARCHITECTURE/STANDARDS/).
It is a provider integration library, not a Framework. ADR-001
in the library's own repository formally records this as a deliberate "third module shape" — distinct
from both Blueprint shapes the platform's certified Frameworks use (the 6-package data/delivery shape and the
5-package execution/runtime shape). It has no Adapters package and no Persistence package, because it
holds no state and needs no host-agnostic adapter layer — every consumer of it is Shumoul.Saas.Api.
1.2 What It Owns
- The Meta Cloud API HTTP client (
WhatsAppCloudApiClient) — sending text and template messages, retrieving media metadata, downloading media bytes. - Webhook signature validation (
WhatsAppSignatureValidator) — HMAC-SHA256 overX-Hub-Signature-256. - Webhook payload parsing (
WhatsAppWebhookParser) — turning Meta's raw JSON into typedWhatsAppWebhookMessageDto/WhatsAppWebhookStatusDtoobjects. - Provider-facing DTOs and configuration (
WhatsAppCloudApiOptionsand friends). - The three public interfaces consumers code against:
IWhatsAppService,IWhatsAppWebhookParser,IWhatsAppSignatureValidator.
1.3 What the ERP Owns
Everything business-shaped stays in Shumoul.Saas.Api:
- The Inbox/Conversation system — conversations, messages, notes, tags, saved replies, timeline, read state, favorites, agent presence, and the real-time SignalR layer built on top of it.
- OTP and tenant-activation WhatsApp business messages.
- The ERP's
Communicationmodule — a channel-agnostic send API (Email/WhatsApp/SMS/Push/In-App) with its own tenant-scoped WhatsApp sender. - Every controller, permission, route, and the entire Angular/Flutter-facing API surface.
- Phone number normalization — a Saudi-market business rule that stays in the ERP by design (see §4 Configuration and ADR-001).
1.4 Why It Is Not a Full Framework
Two alternatives were explicitly considered and rejected during the platform's Phase 0.5 boundary review:
- Restructure into a 5-package execution/runtime Framework (matching the Background Jobs Framework's
shape) — rejected because no legitimate
Adapterspackage content exists. Both plausible adapter candidates (the ERP's controllers, and the Notification Framework's channel-provider bridge) are Host-tier concerns under the platform's Adapter Standard, not library-tier. - Generalize into a
MessagingFrameworkcovering multiple providers — rejected as premature generalization: no second provider exists or is planned, and Meta's WhatsApp Cloud API is specific enough that a generic abstraction would either leak Meta concepts or under-serve them.
The repository name deliberately uses the Integration suffix rather than Framework — a documented,
precedent-setting convention for narrow, stateless provider-integration libraries with no persistence or
adapter layer of their own.
1.5 Relationship With the Notification Framework
WhatsApp is one of six channels the platform's Notification Framework
can dispatch through, alongside Email, SMS, Push, In-App, and SignalR — and, as of the Phase 2.3 runtime
audit, is routed through INotificationChannelProviderResolver exactly like the other five (an earlier
belief that it bypassed the resolver via a class called WhatsAppNotificationSender was based on dead code
that was never actually wired in — see §18 Architecture Validation). What
remains WhatsApp-specific is template resolution: Meta's template model (template name, template language,
positional body parameters) doesn't fit the generic channel-provider contract, so the dispatch service reads
those fields from AppNotificationTemplate before resolving the provider. The Notification Framework's
MetaWhatsAppProvider (ERP-owned) is one of four ERP-side consumers of this library's IWhatsAppService —
see §2 Architecture for the complete consumer map.
1.6 Relationship With ERP Communication / Inbox
Two more ERP subsystems consume this library independently of the Notification Framework:
- The Communication module (
CommunicationController) exposes a generic, channel-agnosticSend/WhatsAppandSend/DocumentAPI for tenant-triggered business messages (e.g. sending an invoice by WhatsApp). It uses the tenant's own Meta credentials viaTenantWhatsAppSender, which — since the Phase 1 Runtime Consolidation — constructs the sameWhatsAppCloudApiClientevery other path uses (see §2.4). - The Inbox/Conversation system (
WhatsAppInboxControllerand siblings) is the two-way, agent-facing customer-service surface: receiving inbound messages via webhook, replying, assigning, tagging, and tracking SLA metrics. It is the largest single consumer ofIWhatsAppService, and the only one that also needs SignalR for real-time agent presence, typing indicators, and inbox updates.
None of these three ERP subsystems know about each other's existence through the library — each holds its
own reference to IWhatsAppService via dependency injection, and the library itself has no concept of
"tenant," "conversation," "OTP," or "invoice."
