feat(service): P5.2 adapter tables (raw_event, outbound_command, delivery_attempt, rate_limit_bucket) + resetDb
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "IiosInboundRawEvent" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"channelType" TEXT NOT NULL,
|
||||||
|
"externalEventId" TEXT,
|
||||||
|
"signatureStatus" TEXT NOT NULL,
|
||||||
|
"status" TEXT NOT NULL DEFAULT 'RECEIVED',
|
||||||
|
"headers" JSONB,
|
||||||
|
"payload" JSONB NOT NULL,
|
||||||
|
"traceId" TEXT,
|
||||||
|
"interactionId" TEXT,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "IiosInboundRawEvent_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "IiosOutboundCommand" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"channelType" TEXT NOT NULL,
|
||||||
|
"target" TEXT NOT NULL,
|
||||||
|
"payload" JSONB NOT NULL,
|
||||||
|
"status" TEXT NOT NULL DEFAULT 'PENDING',
|
||||||
|
"idempotencyKey" TEXT NOT NULL,
|
||||||
|
"providerRef" TEXT,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "IiosOutboundCommand_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "IiosDeliveryAttempt" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"commandId" TEXT NOT NULL,
|
||||||
|
"attemptNo" INTEGER NOT NULL,
|
||||||
|
"status" TEXT NOT NULL,
|
||||||
|
"providerRef" TEXT,
|
||||||
|
"latencyMs" INTEGER,
|
||||||
|
"errorCode" TEXT,
|
||||||
|
"at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
CONSTRAINT "IiosDeliveryAttempt_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "IiosRateLimitBucket" (
|
||||||
|
"channelType" TEXT NOT NULL,
|
||||||
|
"bucketKey" TEXT NOT NULL,
|
||||||
|
"windowStart" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"count" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"resetAt" TIMESTAMP(3) NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "IiosRateLimitBucket_pkey" PRIMARY KEY ("channelType","bucketKey")
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "IiosInboundRawEvent_status_idx" ON "IiosInboundRawEvent"("status");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "IiosInboundRawEvent_channelType_externalEventId_key" ON "IiosInboundRawEvent"("channelType", "externalEventId");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "IiosOutboundCommand_idempotencyKey_key" ON "IiosOutboundCommand"("idempotencyKey");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "IiosOutboundCommand_channelType_status_idx" ON "IiosOutboundCommand"("channelType", "status");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "IiosDeliveryAttempt_commandId_idx" ON "IiosDeliveryAttempt"("commandId");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE "IiosDeliveryAttempt" ADD CONSTRAINT "IiosDeliveryAttempt_commandId_fkey" FOREIGN KEY ("commandId") REFERENCES "IiosOutboundCommand"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
@@ -517,3 +517,63 @@ model IiosCallbackRequest {
|
|||||||
|
|
||||||
@@index([scopeId, status])
|
@@index([scopeId, status])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── P5: Adapters (anti-corruption layer, simulation mode) ────────
|
||||||
|
|
||||||
|
/// Raw inbound provider payload (claim-check / replay). Verified before storing.
|
||||||
|
model IiosInboundRawEvent {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
channelType String
|
||||||
|
externalEventId String?
|
||||||
|
signatureStatus String // VERIFIED | INVALID | UNSIGNED
|
||||||
|
status String @default("RECEIVED") // RECEIVED | NORMALIZED | REJECTED | FAILED
|
||||||
|
headers Json?
|
||||||
|
payload Json
|
||||||
|
traceId String?
|
||||||
|
interactionId String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
@@unique([channelType, externalEventId])
|
||||||
|
@@index([status])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A signed command to send on an external channel — executed by the sandbox sink.
|
||||||
|
model IiosOutboundCommand {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
channelType String
|
||||||
|
target String
|
||||||
|
payload Json
|
||||||
|
status String @default("PENDING") // PENDING | SENT | FAILED | RATE_LIMITED
|
||||||
|
idempotencyKey String @unique
|
||||||
|
providerRef String?
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
|
||||||
|
attempts IiosDeliveryAttempt[]
|
||||||
|
|
||||||
|
@@index([channelType, status])
|
||||||
|
}
|
||||||
|
|
||||||
|
model IiosDeliveryAttempt {
|
||||||
|
id String @id @default(cuid())
|
||||||
|
commandId String
|
||||||
|
command IiosOutboundCommand @relation(fields: [commandId], references: [id], onDelete: Cascade)
|
||||||
|
attemptNo Int
|
||||||
|
status String
|
||||||
|
providerRef String?
|
||||||
|
latencyMs Int?
|
||||||
|
errorCode String?
|
||||||
|
at DateTime @default(now())
|
||||||
|
|
||||||
|
@@index([commandId])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Per-(channelType, key) token/window bucket for outbound throttling.
|
||||||
|
model IiosRateLimitBucket {
|
||||||
|
channelType String
|
||||||
|
bucketKey String
|
||||||
|
windowStart DateTime @default(now())
|
||||||
|
count Int @default(0)
|
||||||
|
resetAt DateTime
|
||||||
|
|
||||||
|
@@id([channelType, bucketKey])
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ import type { PrismaClient } from '@prisma/client';
|
|||||||
export async function resetDb(prisma: PrismaClient): Promise<void> {
|
export async function resetDb(prisma: PrismaClient): Promise<void> {
|
||||||
await prisma.$executeRawUnsafe(
|
await prisma.$executeRawUnsafe(
|
||||||
`TRUNCATE TABLE
|
`TRUNCATE TABLE
|
||||||
|
"IiosInboundRawEvent","IiosDeliveryAttempt","IiosOutboundCommand","IiosRateLimitBucket",
|
||||||
|
"IiosTicketStateHistory","IiosTicketThreadLink","IiosCallbackRequest","IiosTicket",
|
||||||
|
"IiosSupportTeamMember","IiosSupportQueue",
|
||||||
"IiosInboxItemStateHistory","IiosInboxItem","IiosUnreadCounter","IiosMessageReceipt",
|
"IiosInboxItemStateHistory","IiosInboxItem","IiosUnreadCounter","IiosMessageReceipt",
|
||||||
"IiosOutboxEvent","IiosProcessedEvent","IiosMessagePart","IiosInteraction",
|
"IiosOutboxEvent","IiosProcessedEvent","IiosMessagePart","IiosInteraction",
|
||||||
"IiosThreadParticipant","IiosThread","IiosActorRef","IiosSourceHandle","IiosChannel","IiosScope"
|
"IiosThreadParticipant","IiosThread","IiosActorRef","IiosSourceHandle","IiosChannel","IiosScope"
|
||||||
|
|||||||
Reference in New Issue
Block a user