Review an idempotent webhook replay service

src/webhook-replay-types.tsTypeScript
@@ -0,0 +1,57 @@
1+export interface WebhookDelivery {
2+ tenantId: string;
3+ provider: string;
4+ deliveryId: string;
5+ rawBytes: Uint8Array;
6+ signature: string;
7+}
8+
9+export interface ArchivedDelivery extends WebhookDelivery {
10+ archiveId: string;
11+}
12+
13+export interface AppliedDelivery {
14+ key: string;
15+ payloadDigest: string;
16+ outcome: string;
17+}
18+
19+export type DeliveryClaimResult =
20+ | { status: "acquired"; claimId: string }
21+ | { status: "completed"; outcome: string }
22+ | { status: "in-progress" }
23+ | { status: "conflict" };
24+
25+export type DeliveryClaimWaitResult =
26+ | { status: "completed"; outcome: string }
27+ | { status: "retryable" }
28+ | { status: "conflict" };
29+
30+export interface WebhookReplayDependencies {
31+ verifier: {
32+ verify(provider: string, body: Uint8Array, signature: string): Promise<boolean>;
33+ };
34+ digests: {
35+ sha256(body: Uint8Array): Promise<string>;
36+ };
37+ repository: {
38+ find(key: string): Promise<AppliedDelivery | undefined>;
39+ insert(delivery: AppliedDelivery): Promise<void>;
40+ claim(key: string, payloadDigest: string): Promise<DeliveryClaimResult>;
41+ waitForCompletion(
42+ key: string,
43+ payloadDigest: string,
44+ ): Promise<DeliveryClaimWaitResult>;
45+ complete(claimId: string, outcome: string): Promise<void>;
46+ release(claimId: string): Promise<void>;
47+ };
48+ archive: {
49+ load(archiveId: string): Promise<ArchivedDelivery>;
50+ };
51+ handler: {
52+ apply(tenantId: string, event: unknown): Promise<string>;
53+ };
54+ ids: {
55+ next(): string;
56+ };
57+}