Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
# Enterprise migration — `@suaveplan/sms-providers`
## Why
`@suaveplan/sms` shipped a clean send/receive/template/scheduler/opt-out core with `InMemorySmsProvider` as the canonical test double. Production deployments need real provider clients — Twilio, Vonage, MessageBird, Plivo, AWS SNS — each speaking its own REST dialect, authenticating with its own scheme, returning its own status vocabulary, and signing its own webhooks. Upstream `packages/universal/sms-providers` shipped *simulated* providers (random IDs, no network IO, no signature verification) — not enterprise grade.
This change ports the package fresh under `packages/communication/messaging/sms-providers/` (per `assignment.yml`), replacing every simulated implementation with real HTTP clients over an injectable `FetchLike` seam, real HMAC/signature verifiers for each provider's inbound webhook contract, and a typed `SMS_PROVIDERS.*` error registry. Tests bind a real `node:http` server on a random port for end-to-end flows; no mocks.
## What changes
- **ADDED** Package `@suaveplan/sms-providers` at `packages/communication/messaging/sms-providers/`, version `0.1.0`, universal-tier `src/` (zero hard browser/node deps; injectable `fetch` + injectable HMAC seam).
- **ADDED** `SMS_PROVIDERS.*` namespaced error code registry via `defineCodes("SMS_PROVIDERS", […])` with eight codes: `HTTP_ERROR`, `TIMEOUT`, `PARSE_ERROR`, `CONFIG_MISSING`, `SIGNATURE_INVALID`, `INVALID_NUMBER`, `PROVIDER_NOT_REGISTERED`, `PROVIDER_ALREADY_REGISTERED`.
- **ADDED** `SmsProvidersError` discriminated subclass of `SuaveplanError` carrying `provider`, `httpStatus`, `url`, `bodyExcerpt` discriminants; factory helpers per code.
- **ADDED** Slim foundation: `httpRequest` over `FetchLike` with composed `AbortSignal` + per-call timeout + JSON parse + typed error translation; `composeAbortSignal` helper.
- **ADDED** `ProviderRegistry` indexing `SmsProvider` instances by name (insertion-ordered, strict register/lookup, frozen `list()`).
- **ADDED** Five real provider clients implementing `SmsProvider` from `@suaveplan/sms`:
1. `TwilioProvider` — `POST /2010-04-01/Accounts/{AccountSid}/Messages.json`, HTTP Basic auth (`AccountSid:AuthToken`), form-encoded body, MMS `MediaUrl` pass-through, status URL → polled, X-Twilio-Signature HMAC-SHA1 webhook verifier.
2. `VonageProvider` — `POST /sms/json`, `api_key`+`api_secret` body params, alphanumeric / short-code / long-code `from`, HMAC-SHA256 webhook signature verifier honouring `sig`/`timestamp`.
3. `MessageBirdProvider` — `POST /messages`, `AccessKey <key>` auth header, JSON body, `Messagebird-Signature-Jwt` JWT (HS256) webhook verifier with timestamp freshness window.
4. `PlivoProvider` — `POST /v1/Account/{AuthId}/Message/`, HTTP Basic auth (`AuthId:AuthToken`), JSON body, `X-Plivo-Signature-V3` HMAC-SHA256 webhook verifier (canonical-string of URL+nonce+body).
5. `AwsSnsProvider` — `POST /` to `sns.{region}.amazonaws.com` with AWS SigV4 signing (computed inline; no aws-sdk dep), `Action=Publish` form body, message-attribute mapped sender + `SMSType` (Transactional/Promotional); SNS webhook verifier accepts subscription confirmation, notification, and unsubscribe-confirmation payloads with PEM-cert injectable resolver.
- **ADDED** Per-provider raw-status → `SmsDeliveryStatus` map; injectable `Clock` + `IdGenerator` per provider for deterministic message-id fallbacks (when the provider does not return one synchronously).
- **ADDED** Inbound webhook router pipeline per provider: signature verify → header timestamp freshness check → discriminated `InboundSmsEvent` (`message_received` | `delivery_receipt` | `opt_out` | `opt_in`) — opt-in/opt-out keywords (STOP/UNSTOP/HELP family) recognised from inbound body.
- **ADDED** OTel instruments (5):
- counter `sms_providers.send_total{provider,outcome}`
- counter `sms_providers.webhook_total{provider,event,outcome}`
- counter `sms_providers.signature_failures_total{provider}`
- histogram `sms_providers.send_duration_ms{provider}`
- histogram `sms_providers.webhook_verify_duration_ms{provider}`
- **ADDED** Real `node:http` round-trip integration tests per provider (test binds an HTTP server on a random port, captures the request, returns a canned response, asserts URL/method/headers/body) and real-`node:crypto`-driven webhook signature suites (accept + reject paths).
- **ADDED** Co-located `.md` per `.ts` (six required sections, ≥200 words excl. code) and a root `README.md`.
- **MODIFIED** STATUS.md row for `@suaveplan/sms-providers` flipped `–` → `✅`.
## Parity Checklist
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
| `TwilioProvider` simulated send | ✅ | ⬆️ | Replaced: real HTTP Basic + form-encoded POST + MMS `MediaUrl` + status poll + X-Twilio-Signature HMAC-SHA1 verifier. |
| `VonageProvider` simulated send | ✅ | ⬆️ | Replaced: real POST + alpha/short/long sender parsing + HMAC-SHA256 webhook verifier. |
| `MessageBirdProvider` simulated send | ✅ | ⬆️ | Replaced: real `AccessKey` POST + JWT (HS256) webhook verifier with timestamp freshness. |
| `AwsSnsProvider` simulated send | ✅ | ⬆️ | Replaced: real SigV4-signed POST to `sns.<region>.amazonaws.com` + PEM-cert injectable SNS verifier. |
| `PlivoProvider` | 🚫 | ✅ | ADDED — orchestrator scope explicitly names Plivo. |
| `httpRequest` helper | ✅ | ⬆️ | Re-implemented over injectable `FetchLike` + composed `AbortSignal` + `SMS_PROVIDERS.*` codes. |
| `SMS_PROVIDER_*` codes on shared `ErrorCodes` | ✅ | ⬆️ | Migrated to genesis-native `defineCodes("SMS_PROVIDERS", […])`. |
| `mapStatus(raw)` per provider | ✅ | ✅ | Preserved on every provider class. |
| Webhook signature verification | 🚫 | ✅ | ADDED — production requirement. |
| Provider registry | 🚫 | ✅ | ADDED — multiplexing by name (mirrors `@suaveplan/payment-providers`). |
| OTel instrumentation | 🚫 | ✅ | ADDED — production requirement. |
| `node:http` round-trip tests | 🚫 | ✅ | ADDED — orchestrator requirement; real in-process server, no mocks. |
| Inbound opt-in/opt-out keyword detection | 🚫 | ✅ | ADDED — required for compliance integration with `@suaveplan/sms`'s `OptOutRegistry`. |