Proposed (STA-923, batch stackra-47). It closes the Commerce gap “notifications: inbound WhatsApp”
(native WhatsApp carts in R1, COM-297) and the Chatwoot item of STA-805 (OS-204, OS-206).
Context
@stackra/notifications sends WhatsApp messages (ADR 0223, WhatsAppTransport) but cannot read what a customer sends
back. Commerce takes native WhatsApp cart orders at launch (COM-297), confirms cash-on-delivery orders by a button reply
and answers order questions, so every host would otherwise parse Meta’s Cloud API payload itself. Separately, inbound
Chatwoot webhooks (OS messaging’s headless inbox, OS-204, OS-206) declared no signature scheme, so the OS could not
verify them (build-wave10 note 4). Vendor Integrations and Connections live in the OS integrations service (owner
decision R3-8); @stackra/webhooks verifies any HMAC whose recipe is data (scheme: "hmac", ADR 0308 rule 15).
Decision
WhatsAppInboundis a port in@stackra/notifications/contracts.read(body)turns one verified delivery intoInboundWhatsAppmessages of three kinds:text,cart(catalogue id, retailer ids, quantities and unit prices asMoneyAmount, ADR 0220) andreply(a button or list row, or a template quick reply). Each carries the provider’s message id (the dedupe key), the customer’s E.164 number, the receiving number’schannelId(the host maps it to its scope), the send time and the id of the business message it answers. A driver never throws for the body and leaves out what it cannot read. The host dedupes, routes and acts; the port decides nothing about carts or orders.- Two drivers:
memoryandmeta.memoryhands out messages a dev or test pushed.metadecodes the Cloud API payload only, liketwimlencodes Twilio’s: it holds no credential and makes no call, so R3-8 stands (the Meta Integration stays in OS integrations). Meta’s signature is the recipeMETA_WHATSAPP_WEBHOOK_SIGNATURE(x-hub-signature-256: sha256=<hex>of the body), which the Meta Integration declares underscheme: "hmac", so the delivery is verified beforereadruns. - Chatwoot is a recipe, not a scheme.
CHATWOOT_WEBHOOK_SIGNATUREin@stackra/webhooksisx-chatwoot-signature: sha256=<hex>of<x-chatwoot-timestamp>.<body>, five minutes either way. The Chatwoot Integration declares it underscheme: "hmac"; noSignatureSchemecode and no verifier is added.
Consequences
- Commerce and OS messaging read carts and replies through one port; another WhatsApp provider is one more driver.
- Media, locations, reactions and delivery statuses are not read yet; a later decision adds kinds additively.
- The Meta subscribe handshake (
hub.challenge) stays in the host’s route. - Both recipes are written from the providers’ published schemes; certification against live traffic is pending (owner decision D3: ship marked, certify later).
- Runway placement is unchanged; the catalogue row for
@stackra/notificationsgoes to stackra-90.