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,103 @@
# Enterprise migration: `@suaveplan/sms`
- **Change ID**: `enterprise-sms`
- **Status**: PROPOSED
- **Capability**: `sms`
- **Target package**: `@suaveplan/sms` at `0.1.0`
- **Target path**: `packages/communication/messaging/sms/`
- **Design**: ./design.md
- **Spec delta**: ./specs/sms/spec.md
- **Source on main**: `/mnt/s/web/suaveplan/packages/server/sms` (`~1389 LOC`)
- **Enterprise plan**: `/mnt/s/web/suaveplan/enterprise/sms.md`
## Why
`@suaveplan/sms` is the universal SMS core: a provider-agnostic
sending pipeline with template rendering, opt-out management, rate
limiting, scheduling, retry, and delivery tracking. Providers
(Twilio, Vonage, MessageBird, AWS SNS, in-house gateways) plug into
the abstract `SmsProvider` contract.
The upstream package (`v1.0.2`) is functionally narrow — provider
seam, template render, opt-out list, four events — but is missing
every enterprise lever the genesis tree commits to:
- `BaseError` legacy hierarchy instead of `defineCodes("SMS", [...])`.
- No Zod boundary on `SmsMessage`, `SmsTemplate`, `SmsProvider` inputs.
- No OpenTelemetry counters or histograms.
- No retry/backoff on transient provider failures.
- No scheduling (`sendAt`) or batched dispatch.
- No rate limiting per provider / per recipient.
- No delivery-receipt ingest pipeline; status is fetched on demand.
- No `AbortSignal` propagation on send / scheduler / status pulls.
- No in-memory test provider; tests use ad-hoc anonymous mocks.
- One global event-emitter shape; no typed `EventBus` bridge.
- Tests pass with vi-mocks (`@suaveplan/testing` `vi.fn()`) — fine for
unit harnesses, but the package never exercises a real provider
round-trip end-to-end.
This change rewrites the package on genesis at enterprise quality
while preserving every upstream export, then layers the SMS-core
features (`MessageScheduler`, `RateLimiter`, `DeliveryTracker`,
`RetryPolicy`, OTel instruments, Zod boundaries, abort signals,
`EventBus` bridge, in-memory test provider).
## Parity Checklist
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
| `SmsService` send / template render / opt-out | ✅ | ✅ | Preserved verbatim, plus rate-limit + abort + retry on top. |
| `SmsProvider` abstract contract | ✅ | ✅ | Preserved (`name`, `send`, `getStatus`). |
| `SmsTemplate` (`{{var}}` substitution) | ✅ | ✅ | Preserved + `defaults` map + escape pass. |
| `SmsMessage` / `SmsDeliveryReport` / `SmsDeliveryStatus` | ✅ | ✅ | Preserved + Zod schemas. |
| `OptOutEntry` registry | ✅ | ✅ | Preserved + bulk import / export. |
| `SmsEventMap` (`sms.sent`/`delivered`/`failed`/`opted_out`/`opted_in`) | ✅ | ✅ | Preserved + new `sms.scheduled` / `sms.retry` / `sms.rate_limited`. |
| Legacy `EventEmitter` surface (`on/off/emit`) | ✅ | ✅ | Preserved (delegates to typed `EventBus`). |
| `SmsError` legacy class + factory methods | ✅ | ✅ | Preserved as back-compat alias over genesis `defineCodes` family. |
| `respondProblemJson` Hono helper | ✅ | ✅ | Preserved. |
| `registerSmsErrorCodes` / `SMS_ERROR_METADATA` | ✅ | ✅ | Preserved via genesis `ErrorCodes.registerMany`. |
| Stable `SMS.*` `defineCodes` registry | 🚫 (legacy `BaseError`) | ⬆️ | Genesis addition. |
| Zod boundary on every public input | 🚫 | ⬆️ | Genesis addition. |
| OTel counters + histogram | 🚫 | ⬆️ | Genesis addition (4 instruments). |
| `MessageScheduler` (sendAt + cancel) | 🚫 | ⬆️ | Genesis addition. |
| `RateLimiter` (token bucket per recipient) | 🚫 | ⬆️ | Genesis addition. |
| `DeliveryTracker` (receipt ingest + cache) | 🚫 | ⬆️ | Genesis addition. |
| `RetryPolicy` (exponential backoff w/ jitter) | 🚫 | ⬆️ | Genesis addition. |
| `InMemorySmsProvider` (test provider) | 🚫 | ⬆️ | Genesis addition; replaces ad-hoc test mocks. |
| `AbortSignal` propagation | 🚫 | ⬆️ | Genesis addition. |
| 100/100/100/100 coverage | 🚫 | ⬆️ | Genesis gate. |
## What
A net-new package at `packages/communication/messaging/sms/` at
`0.1.0`, universal tier (no Node/Bun-only APIs), Zod-validated
boundaries, OTel-instrumented, with the full upstream public
surface plus the genesis enterprise additions.
This is the SMS **core** — not the providers package. The abstract
`SmsProvider` interface ships with an in-memory test provider
(`InMemorySmsProvider`) so consumers and integration tests can run
without external services. Concrete provider integrations
(Twilio, Vonage, AWS SNS) ship in the sibling `@suaveplan/sms-providers`
package next wave.
## Impact
### Affected dependents
Run `bunx turbo ls --filter=...@suaveplan/sms` to enumerate.
No genesis package currently imports `@suaveplan/sms`:
- `@suaveplan/sms-providers` — pending migration, will consume this as `workspace:^0.1.0`. [x] no action needed (reason: package not yet on genesis)
- `@suaveplan/api-plugin-messaging` — pending migration. [x] no action needed (reason: package not yet on genesis)
Foundation deps (`@suaveplan/error`, `@suaveplan/events`,
`@suaveplan/types`) are read-only consumers; no change required.
## Out of scope
Nothing. Per `feedback_no_deferrals_on_migration.md` and AGENTS §2b,
no "phase 2" is permitted. The whole upstream surface plus the
enterprise additions land here, feature-complete, with
100/100/100/100 coverage.