Commit graph

2 commits

Author SHA1 Message Date
28451daca1 Harden packaging, add error taxonomy, persist pending messages
Packaging
- Drop stale `main: dist/index.js` from package.json (no build workflow)
- Move `prisma` to dependencies and add `postinstall: prisma generate`
  so a fresh `npm ci` on the server produces a runnable client
- Add `prisma:deploy` script for `prisma migrate deploy`
- Rename src/services/Twilioservice.ts -> TwilioService.ts (case fix;
  invisible on macOS APFS, would crash on Linux)

Node version guards
- .nvmrc (22.23.1) so `nvm use` picks the right runtime
- .npmrc `engine-strict=true` so npm respects `engines` on install
- Runtime guard in scripts/navigator-patch.cjs that fails fast with an
  actionable message on Node < 22.18 (native .ts stripping requirement)

Twilio error taxonomy (src/lib/twilioErrors.ts)
- `classifyTwilioError(err)` for send-time exceptions, mapping known
  Twilio REST codes (20003/20429/20500/21211..21614) plus HTTP-status
  and Node errno fallback to `{ kind: retryable|terminal, category }`
- `classifyDeliveryFailure(code)` for the 30xxx delivery-status family
- `sendViaTwilio` persists a `send_error[_retryable]` Message row on
  failure and surfaces the classified message to the user
- `/callback` extracts ErrorCode and passes classified failure info to
  `deliveryStatusCard`, which renders the code + retry-hint inline

Persistent PendingMessageStore
- New PrismaPendingMessageStore (upsert-based) becomes the default
  singleton; InMemoryPendingMessageStore retained for tests
- `startPendingMessageSweeper()` runs hourly, drops entries >24h old,
  unref()s its timer, and is disabled under NODE_ENV=test
- Wired into the shutdown handler in src/index.ts

Tests (39 total, up from 13)
- Integration: tests/integration/twilioRoutes.test.ts hits /sms and
  /callback through the real createApp() with a stub bot, real Twilio
  signatures, plus /healthz
- Unit: twilioErrors.test.ts (14), pendingMessageStore.test.ts (5)
- typecheck clean

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 11:41:18 -04:00
d0a0dda2b8 Initial commit: Sendi 2.0 SMS gateway (Webex + Twilio)
Sendi is a Webex to Twilio SMS gateway written in TypeScript that runs
directly on Node 22.18+ via native type-stripping (no bundler/transpiler).
Each Webex space represents one external SMS contact; inbound MMS is
proxied both ways, with delivery-status cards for outbound sends.

Highlights:
- Express 5 HTTP surface for Twilio /sms and /callback (signature-validated)
- webex-node-bot-framework in websocket transport mode for bot control plane
- Prisma 6 + SQLite via better-sqlite3 driver adapter
- Zod-validated env with fail-fast startup and pino secret redaction
- Pino logging: pretty in dev, structured JSON in prod
- 13 vitest unit tests (phone normalization, Twilio signature validation,
  card action dispatch)
- Native --require preload patches Node 22's read-only globalThis.navigator
  so @webex/internal-media-core (transitive) can load

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-06 11:10:44 -04:00