Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@suaveplan/sms - Universal SMS core: provider-agnostic send pipeline with E.164 validation, Zod boundaries, template rendering, opt-out registry, token-bucket rate limiter, exponential-backoff retry, message scheduler, bounded delivery-tracker LRU cache, typed EventBus, legacy on/off mirror, in-memory test provider, four OTel instruments, thirteen SMS.* error codes via defineCodes, and back-compat for upstream SmsError + SMS_ERROR_METADATA.
Universal SMS core: provider-agnostic send pipeline with strict
E.164 validation, Zod boundaries, template rendering, opt-out
registry, token-bucket rate limiter, exponential-backoff retry with
abort propagation, message scheduling, bounded LRU delivery tracker,
typed EventBus + legacy on/off/emit mirror, an in-memory test
provider, four OpenTelemetry instruments, thirteen SMS.* error
codes via defineCodes, and full back-compat for the upstream
SmsError class and SMS_ERROR_METADATA table.
This package is the SMS core. Concrete provider integrations
(Twilio, Vonage, AWS SNS, etc.) ship in @suaveplan/sms-providers.
Documentation tree
- delivery-tracker —
delivery-trackeris the bounded LRU cache ofSmsDeliveryReportrecords thatSmsServiceconsults for delivery stat…- delivery-tracker —
delivery-trackeris the bounded LRU cache ofSmsDeliveryReportrecords thatSmsServiceconsults for delivery stat…
- delivery-tracker —
- error-codes — The error-codes module owns the canonical
SMS.*registry for@suaveplan/sms. Every error surfaced by the package —…- error-codes — The error-codes module owns the canonical
SMS.*registry for@suaveplan/sms. Every error surfaced by the package —…
- error-codes — The error-codes module owns the canonical
- in-memory-provider —
InMemorySmsProvideris the production-quality in-processSmsProviderimplementation that ships with `@suaveplan/sms…- in-memory-provider —
InMemorySmsProvideris the production-quality in-processSmsProviderimplementation that ships with `@suaveplan/sms…
- in-memory-provider —
- legacy-errors —
legacy-errorspreserves the upstream@suaveplan/smsv1 public surface — theSmsErrorclass, theSmsErrorCodest…- legacy-errors —
legacy-errorspreserves the upstream@suaveplan/smsv1 public surface — theSmsErrorclass, theSmsErrorCodest…
- legacy-errors —
- legacy-metadata —
legacy-metadatapreserves the upstreamSMS_ERROR_METADATAtable — the per-code mapping ofhttpStatus,severity,…- legacy-metadata —
legacy-metadatapreserves the upstreamSMS_ERROR_METADATAtable — the per-code mapping ofhttpStatus,severity,…
- legacy-metadata —
- opt-out —
opt-outis the in-memory opt-out registry thatSmsServiceconsults before every outbound message. Recipients on the…- opt-out —
opt-outis the in-memory opt-out registry thatSmsServiceconsults before every outbound message. Recipients on the…
- opt-out —
- otel —
otel/metricsis the OpenTelemetry instrumentation layer for@suaveplan/sms. It owns four meter instruments — three…- metrics —
otel/metricsis the OpenTelemetry instrumentation layer for@suaveplan/sms. It owns four meter instruments — three…
- metrics —
- rate-limiter —
rate-limiteris the token-bucket throttle thatSmsServiceconsults before every outbound send. The limiter is keyed…- rate-limiter —
rate-limiteris the token-bucket throttle thatSmsServiceconsults before every outbound send. The limiter is keyed…
- rate-limiter —
- retry —
retryis the exponential-backoff retry policy used bySmsService.sendto absorb transient provider failures. The po…- retry —
retryis the exponential-backoff retry policy used bySmsService.sendto absorb transient provider failures. The po…
- retry —
- routes —
routes/problem-jsonis the RFC 7807application/problem+jsonresponse helper for hosts wiring@suaveplan/smserro…- problem-json —
routes/problem-jsonis the RFC 7807application/problem+jsonresponse helper for hosts wiring@suaveplan/smserro…
- problem-json —
- scheduler —
schedulerprovidesMessageScheduler— the minimal timer seam thatSmsService.scheduleAtuses to fire a delayed de…- scheduler —
schedulerprovidesMessageScheduler— the minimal timer seam thatSmsService.scheduleAtuses to fire a delayed de…
- scheduler —
- schemas —
schemasis the Zod boundary for every public input that@suaveplan/smsexposes. The schemas mirror the public type…- schemas —
schemasis the Zod boundary for every public input that@suaveplan/smsexposes. The schemas mirror the public type…
- schemas —
- bus-map —
bus-mapdeclaresSmsBusMap— the single-payload topic contract used bySmsService.bus(anEventBus<SmsBusMap>).… - legacy-emitter —
LegacyEmitteris the back-compat shim that preserves the upstream@suaveplan/smsv1on/off/emitlistener API on t… - sms-service —
SmsServiceis the provider-agnostic orchestrator that ties together every primitive in@suaveplan/sms. A single `se… - templates —
templatesis the in-process template registry and renderer used bySmsServiceto expand{{variable}}placeholders…- templates —
templatesis the in-process template registry and renderer used bySmsServiceto expand{{variable}}placeholders…
- templates —
- validation —
validation/phoneis the strict-E.164 phone number validator used by every public input boundary in@suaveplan/sms.…- phone —
validation/phoneis the strict-E.164 phone number validator used by every public input boundary in@suaveplan/sms.…
- phone —
Highlights
SmsService— orchestrates the full send pipeline: abort check → provider check → E.164 validation → opt-out check → rate-limit → template render → retry → provider send → delivery tracker ingest → OTel + bus emit.InMemorySmsProvider— production-quality in-processSmsProviderfor tests and demos; records every sent message, supports configurable failure predicates and status transitions.TemplateRegistry+renderTemplate—{{var}}substitution with template-level and call-leveldefaultsmaps.OptOutRegistry— channel-scoped opt-out / opt-in with bulk import/export.RateLimiter— token bucket per(channel, recipient)key with injectableClock.RetryPolicy— exponential backoff with full jitter, AbortSignal-aware, injectableTimersseam.MessageScheduler—scheduleAt(date, fn)with cancel handle, injectable timers + clock.DeliveryTracker— bounded LRU receipt cache with provider fall-back vialookupOrFetch.- Typed
EventBusonservice.busplus the upstreamon/off/emitAPI mirroring against it. - Four OTel instruments:
sms.sent_total,sms.failed_total,sms.retry_total,sms.send_duration_ms. - Thirteen
SMS.*error codes viadefineCodes("SMS", [...])plus the upstreamSmsErrorlegacy class preserved verbatim for back-compat.
Install
bun add @suaveplan/sms
Quick start
import {
InMemorySmsProvider,
SmsService,
} from "@suaveplan/sms";
const provider = new InMemorySmsProvider();
const service = new SmsService({ provider });
service.registerTemplate({
id: "welcome",
body: "Hi {{name}}!",
variables: ["name"],
});
service.bus.on("sms.sent", (report) => {
console.log("delivered", report.messageId, "→", report.to);
});
await service.send({
to: "+15551234567",
body: "ignored when templateId is set",
templateId: "welcome",
templateVars: { name: "Alice" },
});
Modules
error-codes/error-codes.md—defineCodes("SMS", [...]), leaf classeslegacy-errors/legacy-errors.md— upstreamSmsErrorback-compatlegacy-metadata/legacy-metadata.md—SMS_ERROR_METADATAtableschemas/schemas.md— Zod boundary parsersvalidation/phone.md— strict E.164 validatortemplates/templates.md—TemplateRegistry,renderTemplateopt-out/opt-out.md—OptOutRegistryrate-limiter/rate-limiter.md— token-bucket limiterretry/retry.md—RetryPolicyscheduler/scheduler.md—MessageSchedulerdelivery-tracker/delivery-tracker.md— bounded LRU receipt cachein-memory-provider/in-memory-provider.md—InMemorySmsProviderservice/sms-service.md— orchestratorservice/legacy-emitter.md— legacyon/off/emitmirrorroutes/problem-json.md— RFC 7807 Hono helperotel/metrics.md— OpenTelemetry instruments