sendi/prisma/migrations/20260626221023_init/migration.sql
jmcqueen 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

110 lines
3.1 KiB
SQL

-- CreateTable
CREATE TABLE "Space" (
"id" TEXT NOT NULL PRIMARY KEY,
"roomId" TEXT NOT NULL,
"smsPhone" TEXT NOT NULL,
"wbxTmPhone" TEXT NOT NULL,
"smsName" TEXT NOT NULL,
"title" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "Contact" (
"id" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"phone" TEXT NOT NULL,
"blocked" BOOLEAN NOT NULL DEFAULT false,
"blockReason" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- CreateTable
CREATE TABLE "Message" (
"id" TEXT NOT NULL PRIMARY KEY,
"sid" TEXT,
"roomId" TEXT NOT NULL,
"from" TEXT NOT NULL,
"body" TEXT NOT NULL,
"mediaUrls" TEXT NOT NULL,
"status" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Message_roomId_fkey" FOREIGN KEY ("roomId") REFERENCES "Space" ("roomId") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "BulkJob" (
"id" TEXT NOT NULL PRIMARY KEY,
"parentId" TEXT NOT NULL,
"senderEmail" TEXT NOT NULL,
"text" TEXT NOT NULL,
"files" TEXT NOT NULL,
"status" TEXT NOT NULL DEFAULT 'pending',
"analytics" JSONB,
"sentAt" DATETIME,
"completedAt" DATETIME,
"spaceId" TEXT,
CONSTRAINT "BulkJob_spaceId_fkey" FOREIGN KEY ("spaceId") REFERENCES "Space" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "Survey" (
"id" TEXT NOT NULL PRIMARY KEY,
"roomId" TEXT NOT NULL,
"question" TEXT NOT NULL,
"endDate" DATETIME NOT NULL,
"responses" TEXT NOT NULL,
"completed" BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT "Survey_roomId_fkey" FOREIGN KEY ("roomId") REFERENCES "Space" ("roomId") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "OutboundRouting" (
"email" TEXT NOT NULL PRIMARY KEY,
"phoneNumber" TEXT NOT NULL,
"groups" TEXT NOT NULL
);
-- CreateTable
CREATE TABLE "InboundRouting" (
"phoneNumber" TEXT NOT NULL PRIMARY KEY,
"site" TEXT NOT NULL,
"people" TEXT NOT NULL,
"keywords" JSONB,
"outOfOffice" JSONB
);
-- CreateTable
CREATE TABLE "BlockNumber" (
"phoneNumber" TEXT NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"reason" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- CreateTable
CREATE TABLE "PendingMessage" (
"roomId" TEXT NOT NULL PRIMARY KEY,
"text" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "PendingMessage_roomId_fkey" FOREIGN KEY ("roomId") REFERENCES "Space" ("roomId") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateIndex
CREATE UNIQUE INDEX "Space_roomId_key" ON "Space"("roomId");
-- CreateIndex
CREATE INDEX "Space_smsPhone_wbxTmPhone_idx" ON "Space"("smsPhone", "wbxTmPhone");
-- CreateIndex
CREATE UNIQUE INDEX "Contact_phone_key" ON "Contact"("phone");
-- CreateIndex
CREATE UNIQUE INDEX "Message_sid_key" ON "Message"("sid");
-- CreateIndex
CREATE INDEX "Message_roomId_idx" ON "Message"("roomId");
-- CreateIndex
CREATE INDEX "Message_createdAt_idx" ON "Message"("createdAt");