// Local-only real PostgreSQL, Redis and Nest callback validation. No supplier connection or SMS submitter. import assert from 'node:assert/strict'; import { createRequire } from 'node:module'; import { randomUUID, randomBytes } from 'node:crypto'; import { readFileSync } from 'node:fs'; const url = new URL(process.env.PROTOCOL_TEST_DATABASE_URL || ''); assert(['127.0.0.1', 'localhost'].includes(url.hostname) && url.pathname.startsWith('/cmpp_qa_')); const redisUrl = new URL(process.env.PROTOCOL_TEST_REDIS_URL || 'redis://127.0.0.1:16441'); assert(['127.0.0.1', 'localhost'].includes(redisUrl.hostname)); Object.assign(process.env, { NODE_ENV: 'test', DATABASE_URL: url.href, REDIS_URL: redisUrl.href, HTTP_API_MASTER_KEY: randomBytes(32).toString('hex'), CMPP_PROCESS_ROLE: 'gateway-callback', GATEWAY_CONTROL_URL: 'http://127.0.0.1:1', GATEWAY_CONNECTION_RECONCILER_DISABLED: 'true', GATEWAY_CONNECTING_TIMEOUT_SCANNER_DISABLED: 'true', SMS_RECEIPT_TIMEOUT_SCAN_ENABLED: 'false', SMS_SCHEDULED_DISPATCH_SCAN_ENABLED: 'false', CMPP_INBOUND_LONG_MESSAGE_SCAN_ENABLED: 'false', UPSTREAM_RECEIPT_INBOX_SCAN_ENABLED: 'false', CMPP_DOWNSTREAM_REQUEUE_TASK_SCAN_ENABLED: 'false', API_ENABLE_SEND_WORKER: 'false', CMPP_INBOUND_WORKFLOW_WORKER_ENABLED: 'false', }); const require = createRequire(new URL('../../api/package.json', import.meta.url)); require('reflect-metadata'); // Match the existing bootstrap money serializer. Protocol field conversion is separately asserted below. Object.defineProperty(BigInt.prototype, 'toJSON', { configurable: true, value() { assert(this <= BigInt(Number.MAX_SAFE_INTEGER)); return Number(this); }, }); const { NestFactory } = require('@nestjs/core'); const { GatewayCallbackModule } = require('./dist/gateway-callback.module'); const { PrismaService } = require('./dist/prisma/prisma.service'); const { SendChainService } = require('./dist/send-chain/send-chain.service'); const { protocolFieldsToJson } = require('./dist/common/protocol-uint32'); const { Client } = require('pg'); const Redis = require('ioredis'); const key = () => randomUUID(); const pass = (name, detail) => console.log(JSON.stringify({ passed: name, ...detail })); const app = await NestFactory.create(GatewayCallbackModule, { logger: ['error'] }); app.setGlobalPrefix('api'); const redis = new Redis(redisUrl.href); try { await app.listen(0, '127.0.0.1'); const base = await app.getUrl(), db = app.get(PrismaService), chain = app.get(SendChainService); assert.equal( await db.smsMessageRecord.count(), 0, 'Use a fresh isolated database: fixed maximum Msg_Id fixtures must not collide with earlier runs', ); const post = async (path, body, expected = 201) => { const r = await fetch(`${base}/api/gateway/events/${path}`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body), }); const json = await r.json(); assert.equal(r.status, expected, JSON.stringify(json)); return json; }; const tenant = await db.tenant.create({ data: { name: 'protocol QA', code: key() } }); const application = await db.smsApplication.create({ data: { tenantId: tenant.id, name: 'protocol QA', cmppAccount: key(), cmppEnterpriseCode: '000001', secretHash: 'disabled', interfaceEnabled: true, }, }); const channel = await db.smsChannel.create({ data: { name: 'protocol QA disabled', code: key(), gatewayHost: '127.0.0.1', gatewayPort: 1, account: key(), passwordCipher: 'unused', srcId: '1069', carriers: ['mobile'], status: 'disabled', }, }); const maxMsgId = '18446744073709551615'; for (const [index, sequenceId] of [0, 2147483647, 2147483648, 4294967295].entries()) { const gatewayMessageId = (BigInt(maxMsgId) - BigInt(index)).toString(); const m = await db.smsMessageRecord.create({ data: { messageId: key(), phoneNumber: `1380013800${index}`, content: 'isolated', billingUnits: 1, status: 'submitted', channelId: channel.id, submitId: key(), tenantId: tenant.id, applicationId: application.id, cmppSubmitSequenceId: String(sequenceId), cmppRegisteredDelivery: true, }, }); await db.smsSubmitRecord.create({ data: { messageRecordId: m.id, tenantId: tenant.id, channelId: channel.id, submitId: m.submitId, submitStatus: 'accepted', }, }); await post('submit-segment-result', { messageId: m.messageId, channelId: channel.id, submitId: m.submitId, gatewayMessageId, sequenceId, segmentIndex: 1, segmentTotal: 1, submitStatus: 'accepted', }); const receipt = { messageId: m.messageId, channelId: channel.id, sequenceId, gatewayMessageId, phoneNumber: m.phoneNumber, receiptStatus: 'delivered', rawStatus: 'DELIVRD', deliveredAt: new Date().toISOString(), }; const stream = `qa:protocol:${key()}`; try { await redis.xadd(stream, '*', 'payload', JSON.stringify(receipt)); const entries = await redis.xrange(stream, '-', '+'); const wire = JSON.parse(entries[0][1][1]); assert.equal(wire.gatewayMessageId, gatewayMessageId); assert.equal(wire.sequenceId, sequenceId); const [intake, concurrent] = await Promise.all([post('receipt/intake', wire), post('receipt/intake', wire)]); assert.equal(intake.inboxId, concurrent.inboxId); for (let i = 0; i < 100; i++) { const inbox = await db.upstreamReceiptInbox.findUnique({ where: { id: intake.inboxId } }); if (inbox.status === 'matched') break; await new Promise((resolve) => setTimeout(resolve, 30)); } const batch = await post('batch', { batchId: key(), gatewayInstanceId: 'qa', events: [{ eventId: key(), type: 'receipt_intake', payload: wire }], }); assert( batch.results.every((r) => r.accepted), JSON.stringify(batch), ); const inbox = await db.upstreamReceiptInbox.findUnique({ where: { id: intake.inboxId } }); assert.equal(inbox.status, 'matched'); assert.equal(inbox.sequenceId, BigInt(sequenceId)); const receipts = await db.smsReceiptRecord.findMany({ where: { messageRecordId: m.id } }); assert.equal(receipts.length, 1); assert.equal(receipts[0].sequenceId, BigInt(sequenceId)); const [submit, segment] = await Promise.all([ db.smsSubmitRecord.findFirst({ where: { messageRecordId: m.id } }), db.smsMessageSegmentAudit.findFirst({ where: { messageRecordId: m.id } }), ]); assert.equal(submit.sequenceId, BigInt(sequenceId)); assert.equal(segment.sequenceId, BigInt(sequenceId)); assert.equal((await db.smsMessageRecord.findUnique({ where: { id: m.id } })).status, 'delivered'); const delivery = await db.cmppDownstreamDelivery.findFirst({ where: { messageRecordId: m.id } }); assert(delivery); assert.equal(delivery.payload.submitSequenceId, sequenceId); await chain.acknowledgeDownstreamDelivery({ id: delivery.id, claimId: key(), connectionId: 'qa', sequenceId: String(sequenceId), messageId: gatewayMessageId, result: sequenceId, }); const ack = await db.cmppDownstreamDelivery.findUnique({ where: { id: delivery.id }, include: { attempts: true }, }); assert.equal(ack.ackResult, BigInt(sequenceId)); assert.equal(ack.attempts[0].ackResult, BigInt(sequenceId)); assert.equal(ack.status === 'delivered', sequenceId === 0); assert.equal(protocolFieldsToJson(ack).ackResult, sequenceId); const uplink = { eventId: key(), channelId: channel.id, sequenceId, gatewayMessageId, phoneNumber: m.phoneNumber, destId: '1069', content: 'QA', receivedAt: new Date().toISOString(), }; const first = await post('uplink', uplink), duplicate = await post('uplink', uplink); assert.equal(first.id, duplicate.id); assert.equal(first.sequenceId, sequenceId); assert.equal(first.gatewayMessageId, gatewayMessageId); assert.equal((await db.smsUplinkMessage.findUnique({ where: { id: first.id } })).sequenceId, BigInt(sequenceId)); pass('uint32_real_chain', { sequenceId, gatewayMessageId, deduplicated: true, sevenColumns: true, notificationQueued: true, }); if (sequenceId === 4294967295) { // Model the emergency legacy case: receipt fact exists but optional sequence was omitted. const notices = await db.cmppDownstreamDelivery.count({ where: { messageRecordId: m.id } }); await db.upstreamReceiptInbox.update({ where: { id: inbox.id }, data: { sequenceId: null } }); await db.smsReceiptRecord.update({ where: { id: receipts[0].id }, data: { sequenceId: null } }); await post('receipt/intake', wire); await post('receipt', { ...wire, receiptStatus: 'undelivered', rawStatus: 'REJECTD' }); assert.equal((await db.upstreamReceiptInbox.findUnique({ where: { id: inbox.id } })).sequenceId, null); assert.equal((await db.smsReceiptRecord.findUnique({ where: { id: receipts[0].id } })).sequenceId, null); assert.equal((await db.smsMessageRecord.findUnique({ where: { id: m.id } })).status, 'delivered'); assert.equal(await db.cmppDownstreamDelivery.count({ where: { messageRecordId: m.id } }), notices); pass('historical_null_and_contradictory_high_sequence_no_reopen'); } } finally { await redis.del(stream); } } const count = await db.upstreamReceiptInbox.count(); for (const bad of [-1, 4294967296, 1.5, '', '0']) await post('receipt/intake', { channelId: channel.id, sequenceId: bad }, 400); assert.equal(await db.upstreamReceiptInbox.count(), count); const invalid = await post('batch', { batchId: key(), gatewayInstanceId: 'qa', events: [{ eventId: 'bad', type: 'receipt_intake', payload: { channelId: channel.id, sequenceId: -1 } }], }); assert.equal(invalid.results[0].accepted, false); assert.equal(invalid.results[0].retryable, false); pass('invalid_events_no_writes'); const models = [ 'UpstreamReceiptInbox', 'SmsReceiptRecord', 'SmsUplinkMessage', 'SmsSubmitRecord', 'SmsMessageSegmentAudit', 'CmppDownstreamDelivery', 'CmppDownstreamDeliveryAttempt', ]; for (const [i, table] of models.entries()) { const col = i < 5 ? 'sequenceId' : 'ackResult'; for (const bad of [-1, 4294967296]) await assert.rejects(db.$executeRawUnsafe(`UPDATE "${table}" SET "${col}" = ${bad}`)); } pass('database_constraints_all_seven'); // Rehearse the exact migration with old values and an unrelated index, then a bad historical value and lock contention. const sql = readFileSync( new URL('../../api/prisma/migrations/20260920160000_cmpp_protocol_uint32/migration.sql', import.meta.url), 'utf8', ); const pg = new Client({ connectionString: url.href }), blocker = new Client({ connectionString: url.href }); await pg.connect(); await blocker.connect(); try { const schema = 'qa_' + key().replaceAll('-', ''); await pg.query(`CREATE SCHEMA "${schema}"; SET search_path TO "${schema}"`); for (const [i, table] of models.entries()) { const col = i < 5 ? 'sequenceId' : 'ackResult'; await pg.query( `CREATE TABLE "${table}" (id int, "${col}" integer); CREATE INDEX "${table}_qa" ON "${table}"(id); INSERT INTO "${table}" VALUES (1,NULL),(2,0),(3,2147483647)`, ); } await pg.query('UPDATE "CmppDownstreamDeliveryAttempt" SET "ackResult"=-1 WHERE id=2'); await assert.rejects(pg.query(sql)); await pg.query('ROLLBACK'); assert.equal( (await pg.query('SELECT pg_typeof("sequenceId")::text AS typ FROM "UpstreamReceiptInbox" LIMIT 1')).rows[0].typ, 'integer', ); await pg.query('UPDATE "CmppDownstreamDeliveryAttempt" SET "ackResult"=0 WHERE id=2'); await blocker.query(`BEGIN; LOCK TABLE "${schema}"."UpstreamReceiptInbox" IN ACCESS EXCLUSIVE MODE`); await assert.rejects(pg.query(sql), (e) => e.code === '55P03'); await pg.query('ROLLBACK'); await blocker.query('ROLLBACK'); const before = await pg.query('SELECT pg_current_wal_lsn() AS lsn'); const started = Date.now(); await pg.query(sql); const wal = await pg.query('SELECT pg_wal_lsn_diff(pg_current_wal_lsn(), $1) AS bytes', [before.rows[0].lsn]); for (const [i, table] of models.entries()) { const col = i < 5 ? 'sequenceId' : 'ackResult'; assert.deepEqual( (await pg.query(`SELECT "${col}" FROM "${table}" ORDER BY id`)).rows.map((r) => r[col]), [null, '0', '2147483647'], ); } assert.equal( Number((await pg.query('SELECT count(*) AS n FROM pg_indexes WHERE schemaname=$1', [schema])).rows[0].n), 7, ); pass('migration_rollback_lock_timeout_and_preservation', { durationMs: Date.now() - started, walBytes: wal.rows[0].bytes, fixtureRows: 21, }); } finally { await pg.end(); await blocker.end(); } } finally { await redis.quit(); await app.close(); }