@voltro/plugin-webhooks 0.32.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,16 +1,23 @@
1
- import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c } from "./signing-DUG4JWwk.js";
2
- import { WebhookDeliveryNotFound as l, WebhookPayloadInvalid as u, WebhookPayloadUnrepresentable as d, WebhookPayloadVersionInvalid as f, WebhookSubscribeInvalid as p } from "./errors.js";
3
- import { _voltroWebhookDeliveriesTable as m, _voltroWebhookEventStatsTable as h, _voltroWebhookRateWindowsTable as g, _voltroWebhookTargetsTable as _, webhookTables as v } from "./mixin.js";
4
- import { randomBytes as y, randomUUID as b } from "node:crypto";
5
- import { Context as ee, Effect as x, Either as te, Schema as S } from "effect";
6
- import { and as C, eq as w } from "@voltro/database";
7
- import { assertPublicUrl as T } from "@voltro/integration-http";
8
- import { publishServerError as ne } from "@voltro/protocol";
9
- import { createLogger as E } from "@voltro/logger";
10
- import { Activity as D, DurableClock as O, Workflow as re } from "@effect/workflow";
11
- import { defineOutboxHandler as ie } from "@voltro/runtime";
12
- //#region src/eventAudience.ts
13
- var ae = (e) => e.webhook !== void 0, k = (e) => {
1
+ import { C as e, E as t, S as n, T as r, _ as i, a, b as o, c as s, d as c, f as l, g as u, h as d, i as f, l as p, m, n as h, o as g, p as _, r as v, s as y, t as b, u as ee, v as te, w as ne, x as re, y as ie } from "./signing-DeHObNv6.js";
2
+ import { WebhookDeliveryNotFound as ae, WebhookPayloadInvalid as x, WebhookPayloadUnrepresentable as S, WebhookPayloadVersionInvalid as C, WebhookSubscribeInvalid as w } from "./errors.js";
3
+ import { _voltroWebhookDeliveriesTable as oe, _voltroWebhookEventStatsTable as se, _voltroWebhookRateWindowsTable as ce, _voltroWebhookTargetsTable as le, webhookTables as ue } from "./mixin.js";
4
+ import { Context as de, Effect as T, Either as fe, Schema as E } from "effect";
5
+ import { definePlugin as pe, publishServerError as me } from "@voltro/protocol";
6
+ import { randomBytes as he, randomUUID as D } from "node:crypto";
7
+ import { and as O, eq as k } from "@voltro/database";
8
+ import { assertPublicUrl as ge } from "@voltro/integration-http";
9
+ import { createLogger as A } from "@voltro/logger";
10
+ import { Activity as j, DurableClock as M, Workflow as _e } from "@effect/workflow";
11
+ import { defineOutboxHandler as ve } from "@voltro/runtime";
12
+ //#region src/plugin.ts
13
+ var N = ["network:outbound:*"], ye = (e = {}) => pe({
14
+ name: e.name ? `@voltro/plugin-webhooks#${e.name}` : "@voltro/plugin-webhooks",
15
+ description: "Outgoing webhooks (multi-target, durable-workflow delivery, HMAC signing, retry policies, rate limits) + incoming (signature verification, idempotency, provider templates). Declares wildcard outbound network access because targets are user-configured URLs.",
16
+ permissions: N,
17
+ onActivate: (e) => T.sync(() => {
18
+ e.logger.info("webhooks active", { outbound: "network:outbound:* (subscriber-configured target URLs — audit visibility, not a restriction)" });
19
+ })
20
+ }), be = (e) => e.webhook !== void 0, P = (e) => {
14
21
  let t = e.webhook;
15
22
  if (t !== void 0) return {
16
23
  _tag: "outgoingEvent",
@@ -20,8 +27,8 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
20
27
  ...t.version === void 0 ? {} : { version: t.version },
21
28
  ...t.rateLimit === void 0 ? {} : { globalRateLimit: t.rateLimit }
22
29
  };
23
- }, oe = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, A = (e) => {
24
- let t = oe.exec(e);
30
+ }, xe = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)?$/, F = (e) => {
31
+ let t = xe.exec(e);
25
32
  if (!t) throw Error(`invalid duration literal: ${e}`);
26
33
  let n = Number(t[1]), r = t[2] ?? "s";
27
34
  switch (r) {
@@ -32,7 +39,7 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
32
39
  case "d": return n * 864e5;
33
40
  default: throw Error(`unreachable unit: ${r}`);
34
41
  }
35
- }, j = [
42
+ }, I = [
36
43
  408,
37
44
  425,
38
45
  429,
@@ -40,16 +47,16 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
40
47
  502,
41
48
  503,
42
49
  504
43
- ], M = (e, t, n) => {
44
- if (t >= e.maxAttempts || n?.status !== void 0 && !(e.retryOn ?? j).includes(n.status)) return null;
50
+ ], L = (e, t, n) => {
51
+ if (t >= e.maxAttempts || n?.status !== void 0 && !(e.retryOn ?? I).includes(n.status)) return null;
45
52
  if (e.honourRetryAfter !== !1 && n?.retryAfterSeconds !== void 0) {
46
- let t = n.retryAfterSeconds * 1e3, r = A(e.maxDelay), i = Math.min(t, r);
53
+ let t = n.retryAfterSeconds * 1e3, r = F(e.maxDelay), i = Math.min(t, r);
47
54
  return {
48
55
  delayMs: i,
49
56
  baseDelayMs: i
50
57
  };
51
58
  }
52
- let r = A(e.initialDelay), i = A(e.maxDelay), a;
59
+ let r = F(e.initialDelay), i = F(e.maxDelay), a;
53
60
  switch (e.strategy) {
54
61
  case "fixed":
55
62
  a = r;
@@ -67,111 +74,118 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
67
74
  delayMs: Math.max(1, Math.floor(o)),
68
75
  baseDelayMs: a
69
76
  };
70
- }, se = () => ({
77
+ }, R = () => ({
71
78
  strategy: "exponential",
72
79
  maxAttempts: 8,
73
80
  initialDelay: "5s",
74
81
  maxDelay: "1h",
75
- retryOn: j,
82
+ retryOn: I,
76
83
  honourRetryAfter: !0,
77
84
  jitter: "full"
78
- }), ce = () => ({
85
+ }), Se = () => ({
79
86
  strategy: "fixed",
80
87
  maxAttempts: 120,
81
88
  initialDelay: "30s",
82
89
  maxDelay: "30s",
83
- retryOn: j,
90
+ retryOn: I,
84
91
  honourRetryAfter: !0,
85
92
  jitter: "full"
86
- }), N = class extends ee.Tag("@voltro/webhooks/WebhooksService")() {}, le = 32, P = 32, F = () => y(le).toString("hex"), I = (e) => e.events ?? (e.event === void 0 ? [] : [e.event]), L = (e) => {
93
+ }), Ce = class extends de.Tag("@voltro/webhooks/WebhooksService")() {}, we = 32, Te = 32, z = () => he(we).toString("hex"), B = (e) => e.events ?? (e.event === void 0 ? [] : [e.event]), V = (e) => {
87
94
  let t;
88
95
  try {
89
96
  t = new URL(e.url);
90
97
  } catch (e) {
91
- throw new p({
98
+ throw new w({
92
99
  field: "url",
93
100
  reason: `invalid subscriber url: ${e.message}`
94
101
  });
95
102
  }
96
- if (t.protocol !== "http:" && t.protocol !== "https:") throw new p({
103
+ if (t.protocol !== "http:" && t.protocol !== "https:") throw new w({
97
104
  field: "url",
98
105
  reason: `url protocol must be http or https, got ${t.protocol}`
99
106
  });
100
107
  if (process.env.NODE_ENV === "production") try {
101
- T(e.url);
108
+ ge(e.url);
102
109
  } catch (e) {
103
- throw new p({
110
+ throw new w({
104
111
  field: "url",
105
112
  reason: e.message
106
113
  });
107
114
  }
108
- let n = I(e);
109
- if (n.length === 0) throw new p({
115
+ let n = B(e);
116
+ if (n.length === 0) throw new w({
110
117
  field: "event",
111
118
  reason: "event id required"
112
119
  });
113
- if (e.event !== void 0 && e.events !== void 0) throw new p({
120
+ if (e.event !== void 0 && e.events !== void 0) throw new w({
114
121
  field: "event",
115
122
  reason: "pass `event` OR `events`, not both — the row set would be ambiguous"
116
123
  });
117
- if (n.some((e) => e.length === 0)) throw new p({
124
+ if (n.some((e) => e.length === 0)) throw new w({
118
125
  field: "events",
119
126
  reason: "event id required"
120
127
  });
121
- if (new Set(n).size !== n.length) throw new p({
128
+ if (new Set(n).size !== n.length) throw new w({
122
129
  field: "events",
123
130
  reason: "duplicate event — one row per event, so a repeat would deliver twice"
124
131
  });
125
- if (e.secret !== void 0 && e.secret.length < P) throw new p({
132
+ if (e.secret !== void 0 && e.secret.length < Te) throw new w({
126
133
  field: "secret",
127
- reason: `secret must be at least ${P} chars`
134
+ reason: `secret must be at least ${Te} chars`
135
+ });
136
+ if (e.secret !== void 0 && e.signing?._tag === "standardWebhooks" && !te(e.secret)) throw new w({
137
+ field: "secret",
138
+ reason: "a standard-webhooks target needs the spec's secret serialization (\"whsec_\" + base64 of 24..64 random bytes) — mint one with generateStandardWebhooksSecret(), or omit `secret` and let subscribe mint it"
128
139
  });
129
140
  if (e.retry !== void 0) {
130
- if (e.retry.maxAttempts < 1) throw new p({
141
+ if (e.retry.maxAttempts < 1) throw new w({
131
142
  field: "retry",
132
143
  reason: "retry.maxAttempts must be ≥ 1"
133
144
  });
134
- if (e.retry.maxAttempts > 1e3) throw new p({
145
+ if (e.retry.maxAttempts > 1e3) throw new w({
135
146
  field: "retry",
136
147
  reason: "retry.maxAttempts must be ≤ 1000"
137
148
  });
138
149
  }
139
- if (e.rateLimitPerMinute !== void 0 && e.rateLimitPerMinute < 1) throw new p({
150
+ if (e.rateLimitPerMinute !== void 0 && e.rateLimitPerMinute < 1) throw new w({
140
151
  field: "rateLimitPerMinute",
141
152
  reason: "rateLimitPerMinute must be ≥ 1"
142
153
  });
143
- if (e.autoDisableAfter !== void 0 && (e.autoDisableAfter < 1 || !Number.isInteger(e.autoDisableAfter))) throw new p({
154
+ if (e.autoDisableAfter !== void 0 && (e.autoDisableAfter < 1 || !Number.isInteger(e.autoDisableAfter))) throw new w({
144
155
  field: "autoDisableAfter",
145
156
  reason: `autoDisableAfter must be a positive integer, got ${e.autoDisableAfter}`
146
157
  });
147
- }, ue = (e, t, n, r) => ({
148
- id: b(),
149
- tenantId: e.tenantId ?? null,
150
- event: n ?? e.event ?? "",
151
- url: e.url,
152
- secret: r ?? e.secret ?? F(),
153
- signing: e.signing ?? t?.defaultSigning ?? c(),
154
- retry: e.retry ?? t?.defaultRetry ?? se(),
155
- filter: e.filter ?? null,
156
- scope: e.scope ?? null,
157
- headers: e.headers ?? null,
158
- rateLimitPerMinute: e.rateLimitPerMinute ?? null,
159
- active: !0,
160
- format: e.format ?? "json",
161
- autoDisableAfter: e.autoDisableAfter ?? null,
162
- consecutiveFailures: 0,
163
- autoDisabledAt: null,
164
- autoDisableReason: null,
165
- payloadVersion: e.payloadVersion ?? t?.version ?? 1,
166
- description: e.description ?? null
167
- }), de = (e) => e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : 0, R = (e) => e instanceof Date ? e.toISOString() : typeof e == "string" ? e : null, fe = (e) => {
158
+ }, Ee = (e, t, n, r) => {
159
+ let a = e.signing ?? t?.defaultSigning ?? b(), o = a._tag === "standardWebhooks" ? i : z;
160
+ return {
161
+ id: D(),
162
+ tenantId: e.tenantId ?? null,
163
+ event: n ?? e.event ?? "",
164
+ url: e.url,
165
+ secret: r ?? e.secret ?? o(),
166
+ signing: a,
167
+ retry: e.retry ?? t?.defaultRetry ?? R(),
168
+ filter: e.filter ?? null,
169
+ scope: e.scope ?? null,
170
+ headers: e.headers ?? null,
171
+ rateLimitPerMinute: e.rateLimitPerMinute ?? null,
172
+ active: !0,
173
+ format: e.format ?? "json",
174
+ autoDisableAfter: e.autoDisableAfter ?? null,
175
+ consecutiveFailures: 0,
176
+ autoDisabledAt: null,
177
+ autoDisableReason: null,
178
+ payloadVersion: e.payloadVersion ?? t?.version ?? 1,
179
+ description: e.description ?? null
180
+ };
181
+ }, De = (e) => e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : 0, H = (e) => e instanceof Date ? e.toISOString() : typeof e == "string" ? e : null, Oe = (e) => {
168
182
  if (typeof e != "string") return e;
169
183
  try {
170
184
  return JSON.parse(e);
171
185
  } catch {
172
186
  return e;
173
187
  }
174
- }, pe = (e) => ({
188
+ }, U = (e) => ({
175
189
  id: String(e.id),
176
190
  deliveryId: String(e.deliveryId),
177
191
  targetId: String(e.targetId),
@@ -182,28 +196,28 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
182
196
  responseStatus: e.responseStatus ?? null,
183
197
  errorMessage: e.errorMessage ?? null,
184
198
  latencyMs: e.latencyMs ?? null,
185
- scheduledAt: R(e.scheduledAt),
186
- nextAttemptAt: R(e.nextAttemptAt),
187
- createdAt: R(e.createdAt)
188
- }), me = (e, t) => e === t ? "current" : e < t ? "behind" : "ahead", he = (e, t) => {
199
+ scheduledAt: H(e.scheduledAt),
200
+ nextAttemptAt: H(e.nextAttemptAt),
201
+ createdAt: H(e.createdAt)
202
+ }), ke = (e, t) => e === t ? "current" : e < t ? "behind" : "ahead", Ae = (e, t) => {
189
203
  if (e === null) return !0;
190
204
  let n = { payload: t };
191
- for (let [t, r] of Object.entries(e)) if (!_e(ge(n, t), r)) return !1;
205
+ for (let [t, r] of Object.entries(e)) if (!Me(je(n, t), r)) return !1;
192
206
  return !0;
193
- }, ge = (e, t) => {
207
+ }, je = (e, t) => {
194
208
  let n = t.split("."), r = e;
195
209
  for (let e of n) {
196
210
  if (typeof r != "object" || !r) return;
197
211
  r = r[e];
198
212
  }
199
213
  return r;
200
- }, z = (e, t) => {
214
+ }, W = (e, t) => {
201
215
  if (typeof e == "number" && typeof t == "number") return e - t;
202
216
  if (typeof e == "string" && typeof t == "string") return e < t ? -1 : +(e > t);
203
- }, _e = (e, t) => {
217
+ }, Me = (e, t) => {
204
218
  if (typeof t == "object" && t && !Array.isArray(t)) {
205
219
  let n = t;
206
- return "eq" in n && e !== n.eq || "in" in n && (!Array.isArray(n.in) || !n.in.includes(e)) || "gt" in n && !((z(e, n.gt) ?? 0) > 0) || "gte" in n && !((z(e, n.gte) ?? -1) >= 0) || "lt" in n && !((z(e, n.lt) ?? 0) < 0) || "lte" in n && !((z(e, n.lte) ?? 1) <= 0) ? !1 : [
220
+ return "eq" in n && e !== n.eq || "in" in n && (!Array.isArray(n.in) || !n.in.includes(e)) || "gt" in n && !((W(e, n.gt) ?? 0) > 0) || "gte" in n && !((W(e, n.gte) ?? -1) >= 0) || "lt" in n && !((W(e, n.lt) ?? 0) < 0) || "lte" in n && !((W(e, n.lte) ?? 1) <= 0) ? !1 : [
207
221
  "eq",
208
222
  "in",
209
223
  "gt",
@@ -213,9 +227,9 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
213
227
  ].some((e) => e in n);
214
228
  }
215
229
  return e === t;
216
- }, B = (e, t) => e !== null && Object.entries(t).every(([t, n]) => e[t] === n), V = 500, H = 200, U = async (e, t) => {
230
+ }, Ne = (e, t) => e !== null && Object.entries(t).every(([t, n]) => e[t] === n), G = 500, Pe = 200, K = async (e, t) => {
217
231
  let n = [];
218
- for (let r = 0; r < H; r += 1) {
232
+ for (let r = 0; r < Pe; r += 1) {
219
233
  let i = await e.store.query({
220
234
  table: "_voltro_webhook_targets",
221
235
  predicate: t,
@@ -223,24 +237,24 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
223
237
  column: "id",
224
238
  direction: "asc"
225
239
  }],
226
- take: V,
227
- skip: r === 0 ? void 0 : r * V,
240
+ take: G,
241
+ skip: r === 0 ? void 0 : r * G,
228
242
  projection: void 0
229
243
  });
230
- if (n.push(...i), i.length < V) return n;
244
+ if (n.push(...i), i.length < G) return n;
231
245
  }
232
- throw Error(`webhooks: more than ${H * V} rows in \`_voltro_webhook_targets\` — refusing to answer a scope lookup from a partial scan. A truncated scan mints a fresh secret for a live endpoint (breaking its signatures) or reports that a real scope matches nothing.`);
233
- }, ve = async (e, t) => {
234
- let n = (await U(e)).filter((e) => B(e.scope, t));
246
+ throw Error(`webhooks: more than ${Pe * G} rows in \`_voltro_webhook_targets\` — refusing to answer a scope lookup from a partial scan. A truncated scan mints a fresh secret for a live endpoint (breaking its signatures) or reports that a real scope matches nothing.`);
247
+ }, Fe = async (e, t) => {
248
+ let n = (await K(e)).filter((e) => Ne(e.scope, t));
235
249
  if (n.length === 0) return;
236
250
  let r = new Set(n.map((e) => e.secret));
237
251
  if (r.size > 1) throw Error(`webhooks.subscribe: the scope ${JSON.stringify(t)} matches ${n.length} targets with ${r.size} different secrets, so it is not one endpoint. Pass \`secret\` explicitly, or narrow the scope.`);
238
252
  return [...r][0];
239
- }, ye = async (e, t) => {
253
+ }, Ie = async (e, t) => {
240
254
  try {
241
255
  let n = await e.store.query({
242
256
  table: "_voltro_webhook_event_stats",
243
- predicate: w("event", t),
257
+ predicate: k("event", t),
244
258
  order: [],
245
259
  take: 1,
246
260
  skip: void 0,
@@ -262,11 +276,11 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
262
276
  updatedAt: r
263
277
  });
264
278
  } catch {}
265
- }, be = (e, t, n = {}) => {
279
+ }, Le = (e, t, n = {}) => {
266
280
  let r = new Map((n.events ?? []).map((e) => [e.id, e])), i = {
267
281
  subscribe: async (t) => {
268
- L(t);
269
- let n = I(t), i = t.secret === void 0 && t.scope !== void 0 ? await ve(e, t.scope) : void 0, a = t.secret ?? i ?? F(), o = n.map((e) => ue(t, r.get(e), e, a));
282
+ V(t);
283
+ let n = B(t), i = t.secret === void 0 && t.scope !== void 0 ? await Fe(e, t.scope) : void 0, a = t.secret ?? i ?? z(), o = n.map((e) => Ee(t, r.get(e), e, a));
270
284
  for (let t of o) await e.store.insert("_voltro_webhook_targets", {
271
285
  ...t,
272
286
  createdAt: /* @__PURE__ */ new Date(),
@@ -287,26 +301,26 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
287
301
  };
288
302
  },
289
303
  emit: async (n, i, a) => {
290
- let o = typeof n == "object" && n.kind === "event" ? k(n) : void 0, s = typeof n == "string" ? r.get(n) : o ?? n, c = typeof n == "string" ? n : n.id ?? n.name;
304
+ let o = typeof n == "object" && n.kind === "event" ? P(n) : void 0, s = typeof n == "string" ? r.get(n) : o ?? n, c = typeof n == "string" ? n : n.id ?? n.name;
291
305
  if (s !== void 0) {
292
- let e = S.decodeUnknownEither(s.payload)(i, { errors: "all" });
293
- if (te.isLeft(e)) throw new u({
306
+ let e = E.decodeUnknownEither(s.payload)(i, { errors: "all" });
307
+ if (fe.isLeft(e)) throw new x({
294
308
  event: c,
295
309
  issues: e.left.message
296
310
  });
297
311
  }
298
- let l = b(), d = a?.tenantId, f = await U(e, d == null ? w("event", c) : C(w("event", c), w("tenantId", d)));
299
- await ye(e, c);
300
- let p = f.filter((e) => he(e.filter, i)), m = [], h = JSON.stringify(i);
301
- for (let n of p) {
302
- let r = b();
312
+ let l = D(), u = a?.tenantId, d = await K(e, u == null ? k("event", c) : O(k("event", c), k("tenantId", u)));
313
+ await Ie(e, c);
314
+ let f = d.filter((e) => Ae(e.filter, i)), p = [], m = JSON.stringify(i);
315
+ for (let n of f) {
316
+ let r = D();
303
317
  n.active ? (await t({
304
318
  deliveryId: r,
305
319
  targetId: n.id,
306
320
  event: c,
307
321
  eventId: l,
308
- payloadJson: h
309
- }), m.push({
322
+ payloadJson: m
323
+ }), p.push({
310
324
  targetId: n.id,
311
325
  deliveryId: r,
312
326
  status: "dispatched"
@@ -319,11 +333,11 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
319
333
  eventId: l,
320
334
  attempt: 1,
321
335
  status: "pending",
322
- payload: h,
336
+ payload: m,
323
337
  scheduledAt: /* @__PURE__ */ new Date(),
324
338
  createdAt: /* @__PURE__ */ new Date(),
325
339
  updatedAt: /* @__PURE__ */ new Date()
326
- }), m.push({
340
+ }), p.push({
327
341
  targetId: n.id,
328
342
  deliveryId: r,
329
343
  status: "queued"
@@ -331,13 +345,13 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
331
345
  }
332
346
  return {
333
347
  eventId: l,
334
- deliveries: m
348
+ deliveries: p
335
349
  };
336
350
  },
337
351
  replay: async (n) => {
338
352
  let r = (await e.store.query({
339
353
  table: "_voltro_webhook_deliveries",
340
- predicate: w("deliveryId", n),
354
+ predicate: k("deliveryId", n),
341
355
  order: [{
342
356
  column: "attempt",
343
357
  direction: "asc"
@@ -346,19 +360,19 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
346
360
  skip: void 0,
347
361
  projection: void 0
348
362
  }))[0];
349
- if (r === void 0) throw new l({ deliveryId: n });
363
+ if (r === void 0) throw new ae({ deliveryId: n });
350
364
  await t({
351
365
  deliveryId: r.deliveryId,
352
366
  targetId: r.targetId,
353
367
  event: r.event,
354
- eventId: r.eventId ?? b(),
368
+ eventId: r.eventId ?? D(),
355
369
  payloadJson: typeof r.payload == "string" ? r.payload : JSON.stringify(r.payload),
356
370
  attemptEpoch: Date.now()
357
371
  });
358
372
  },
359
373
  resolveTargets: async (t) => {
360
374
  if (typeof t == "string") return [t];
361
- let n = (await U(e)).filter((e) => B(e.scope, t.scope)).map((e) => e.id);
375
+ let n = (await K(e)).filter((e) => Ne(e.scope, t.scope)).map((e) => e.id);
362
376
  if (n.length === 0) throw Error(`webhooks: no target matches scope ${JSON.stringify(t.scope)} — the operation would have silently done nothing`);
363
377
  return n;
364
378
  },
@@ -379,7 +393,7 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
379
393
  });
380
394
  let n = await e.store.query({
381
395
  table: "_voltro_webhook_deliveries",
382
- predicate: C(w("targetId", r), w("status", "pending")),
396
+ predicate: O(k("targetId", r), k("status", "pending")),
383
397
  order: [{
384
398
  column: "createdAt",
385
399
  direction: "asc"
@@ -392,17 +406,17 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
392
406
  deliveryId: e.deliveryId,
393
407
  targetId: r,
394
408
  event: e.event,
395
- eventId: e.eventId ?? b(),
409
+ eventId: e.eventId ?? D(),
396
410
  payloadJson: typeof e.payload == "string" ? e.payload : JSON.stringify(e.payload),
397
411
  attemptEpoch: i
398
412
  });
399
413
  }
400
414
  },
401
415
  deleteTarget: async (t) => {
402
- for (let n of await i.resolveTargets(t)) await e.store.delete("_voltro_webhook_targets", n), await e.store.deleteMany("_voltro_webhook_deliveries", { where: C(w("targetId", n), w("status", "pending")) });
416
+ for (let n of await i.resolveTargets(t)) await e.store.delete("_voltro_webhook_targets", n), await e.store.deleteMany("_voltro_webhook_deliveries", { where: O(k("targetId", n), k("status", "pending")) });
403
417
  },
404
418
  rotateSecret: async (t) => {
405
- let n = F();
419
+ let n = z();
406
420
  for (let r of await i.resolveTargets(t)) await e.store.update("_voltro_webhook_targets", r, {
407
421
  secret: n,
408
422
  updatedAt: /* @__PURE__ */ new Date()
@@ -410,7 +424,7 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
410
424
  return { secret: n };
411
425
  },
412
426
  updateTarget: async (t, n) => {
413
- if (n.url !== void 0 && L({
427
+ if (n.url !== void 0 && V({
414
428
  event: "x",
415
429
  url: n.url
416
430
  }), n.rateLimitPerMinute !== void 0 && n.rateLimitPerMinute !== null && (!Number.isInteger(n.rateLimitPerMinute) || n.rateLimitPerMinute < 1)) throw Error("updateTarget: rateLimitPerMinute must be a positive integer or null");
@@ -430,14 +444,14 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
430
444
  testTarget: async (n, r) => {
431
445
  let i = (await e.store.query({
432
446
  table: "_voltro_webhook_targets",
433
- predicate: w("id", n),
447
+ predicate: k("id", n),
434
448
  order: [],
435
449
  take: 1,
436
450
  skip: void 0,
437
451
  projection: void 0
438
452
  }))[0];
439
453
  if (i === void 0) throw Error(`testTarget: no target ${n}`);
440
- let a = b(), o = JSON.stringify(r ?? {
454
+ let a = D(), o = JSON.stringify(r ?? {
441
455
  test: !0,
442
456
  targetId: n,
443
457
  at: (/* @__PURE__ */ new Date()).toISOString()
@@ -446,7 +460,7 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
446
460
  deliveryId: a,
447
461
  targetId: i.id,
448
462
  event: i.event,
449
- eventId: b(),
463
+ eventId: D(),
450
464
  payloadJson: o
451
465
  }) : await e.store.insert("_voltro_webhook_deliveries", {
452
466
  id: `${a}:1`,
@@ -466,7 +480,7 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
466
480
  listDeliveries: async (t) => {
467
481
  let n = t?.scope === void 0 ? void 0 : new Set(await i.resolveTargets({ scope: t.scope })), r = await e.store.query({
468
482
  table: "_voltro_webhook_deliveries",
469
- predicate: t?.targetId === void 0 ? void 0 : w("targetId", t.targetId),
483
+ predicate: t?.targetId === void 0 ? void 0 : k("targetId", t.targetId),
470
484
  order: [{
471
485
  column: "createdAt",
472
486
  direction: "desc"
@@ -475,25 +489,25 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
475
489
  skip: void 0,
476
490
  projection: void 0
477
491
  }), a = t?.since?.getTime();
478
- return r.filter((e) => n === void 0 || n.has(String(e.targetId))).filter((e) => t?.status === void 0 || e.status === t.status).filter((e) => a === void 0 || de(e.createdAt) >= a).slice(0, t?.limit ?? 200).map(pe);
492
+ return r.filter((e) => n === void 0 || n.has(String(e.targetId))).filter((e) => t?.status === void 0 || e.status === t.status).filter((e) => a === void 0 || De(e.createdAt) >= a).slice(0, t?.limit ?? 200).map(U);
479
493
  },
480
494
  getDelivery: async (t) => {
481
495
  let n = (await e.store.query({
482
496
  table: "_voltro_webhook_deliveries",
483
- predicate: w("id", t),
497
+ predicate: k("id", t),
484
498
  order: [],
485
499
  take: 1,
486
500
  skip: void 0,
487
501
  projection: void 0
488
502
  }))[0];
489
503
  return n === void 0 ? null : {
490
- ...pe(n),
491
- payload: fe(n.payload),
504
+ ...U(n),
505
+ payload: Oe(n.payload),
492
506
  responseBody: n.responseBody ?? null
493
507
  };
494
508
  },
495
509
  updateTargetPayloadVersion: async (t, n) => {
496
- if (n < 1 || !Number.isInteger(n)) throw new f({ version: n });
510
+ if (n < 1 || !Number.isInteger(n)) throw new C({ version: n });
497
511
  await e.store.update("_voltro_webhook_targets", t, {
498
512
  payloadVersion: n,
499
513
  updatedAt: /* @__PURE__ */ new Date()
@@ -502,7 +516,7 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
502
516
  listTargets: async (t, n) => {
503
517
  let r = await e.store.query({
504
518
  table: "_voltro_webhook_targets",
505
- predicate: t === void 0 ? void 0 : w("event", t),
519
+ predicate: t === void 0 ? void 0 : k("event", t),
506
520
  order: [{
507
521
  column: "createdAt",
508
522
  direction: "desc"
@@ -528,15 +542,15 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
528
542
  }
529
543
  };
530
544
  return i;
531
- }, xe = x.gen(function* () {
532
- return yield* N;
533
- }), Se = (e) => {
545
+ }, Re = T.gen(function* () {
546
+ return yield* Ce;
547
+ }), ze = (e) => {
534
548
  if (e.webhooks === void 0) throw Error("useWebhooks: `ctx.webhooks` is not set. Add @voltro/plugin-webhooks to your app.config.ts plugin list and declare at least one *.webhook.tsx file.");
535
549
  return e.webhooks;
536
- }, Ce = 1e4, W = class {
550
+ }, Be = 1e4, Ve = class {
537
551
  capacity;
538
552
  cache = /* @__PURE__ */ new Map();
539
- constructor(e = Ce) {
553
+ constructor(e = Be) {
540
554
  this.capacity = e;
541
555
  }
542
556
  evictExpired() {
@@ -571,20 +585,36 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
571
585
  clear() {
572
586
  this.cache.clear();
573
587
  }
574
- }, G = null, K = () => (G === null && (G = new W()), G), q = {
588
+ }, q = null, He = () => (q === null && (q = new Ve()), q), J = {
575
589
  "5m": 5 * 6e4,
576
590
  "1h": 60 * 6e4,
577
591
  "6h": 360 * 6e4,
578
592
  "1d": 1440 * 6e4,
579
593
  "7d": 10080 * 6e4,
580
594
  "30d": 720 * 60 * 6e4
581
- }, J = (e) => e === void 0 ? q["7d"] : q[e] ?? q["7d"], Y = (e, t) => ({
595
+ }, Ue = (e) => e === void 0 ? J["7d"] : J[e] ?? J["7d"], Y = (e, t) => ({
582
596
  status: e,
583
597
  contentType: "application/json; charset=utf-8",
584
598
  body: JSON.stringify(t)
585
- }), we = (e, t) => {
586
- let n = e.provider, r = e.signature ?? n?.signature ?? null, i = e.idempotency ?? n?.idempotency ?? null, o = e.bodyType ?? n?.bodyType ?? "json", s = t.idempotencyCache ?? K(), c = J(i?.ttl), l = t.log ?? ((e) => {
587
- E({ scope: `webhook:${e.webhookId}` }).debug("incoming webhook", {
599
+ }), We = "voltroWebhookVerification", Ge = class extends Error {
600
+ webhookId;
601
+ name = "UnverifiedIncomingWebhook";
602
+ constructor(e) {
603
+ super(`incoming webhook '${e}' declares no verification. It would be mounted as a public, unauthenticated POST that runs your application code, so the framework refuses to mount it. Pick one on the descriptor:\n · provider: stripeWebhookProvider() — a preset (HMAC scheme + idempotency + body type)\n · signature: { _tag: 'hmac', algorithm: 'hmacSha256', header: 'X-Signature', encoding: 'hex', includeTimestamp: true }\n · verification: 'provider' — the handler verifies with the provider's own SDK\n · verification: 'none' — deliberately public; a gateway / IP allow-list owns it\nA signature-verified webhook reads its shared secret from VOLTRO_WEBHOOK_SECRET_${e.toUpperCase().replace(/[^A-Z0-9]/g, "_")}. The framework never invents that value — the sender holds the other half of it.`), this.webhookId = e;
604
+ }
605
+ }, Ke = (e) => `VOLTRO_WEBHOOK_SECRET_${e.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`, qe = (e) => {
606
+ let t = e.signature ?? e.provider?.signature ?? null;
607
+ return (e.verification === void 0 || e.verification === "signature") && t === null ? null : e.verification ?? "signature";
608
+ }, Je = (e, t) => {
609
+ let n = e.provider, r = e.signature ?? n?.signature ?? null, i = e.idempotency ?? n?.idempotency ?? null, a = e.bodyType ?? n?.bodyType ?? "json", o = qe(e);
610
+ if (o === null) throw new Ge(e.id);
611
+ let c = o;
612
+ c === "none" && A({ scope: `webhook:${e.id}` }).warn("incoming webhook mounted WITHOUT verification — anyone who can reach this URL can run its handler", {
613
+ webhookId: e.id,
614
+ verification: "none"
615
+ });
616
+ let l = t.idempotencyCache ?? He(), u = Ue(i?.ttl), d = t.log ?? ((e) => {
617
+ A({ scope: `webhook:${e.webhookId}` }).debug("incoming webhook", {
588
618
  status: e.status,
589
619
  signatureOk: e.signatureOk,
590
620
  idempotency: e.idempotency,
@@ -592,115 +622,129 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
592
622
  ...e.errorMessage === void 0 ? {} : { errorMessage: e.errorMessage }
593
623
  });
594
624
  });
595
- return async (n) => {
596
- let u = Date.now();
625
+ return Object.assign(async (n) => {
626
+ let o = Date.now();
597
627
  if (n.method !== "POST") {
598
628
  let t = Y(405, {
599
629
  error: "method not allowed",
600
630
  expected: "POST"
601
631
  });
602
- return l({
632
+ return d({
603
633
  webhookId: e.id,
604
634
  status: 405,
605
635
  signatureOk: "skipped",
606
636
  idempotency: "skipped",
607
- durationMs: Date.now() - u
637
+ durationMs: Date.now() - o
608
638
  }), t;
609
639
  }
610
- let d = "skipped";
611
- if (r !== null) {
640
+ let f = "skipped";
641
+ if (r !== null && c === "signature") {
612
642
  let i = await t.resolveSecret(e.id);
613
- if (i === null) d = "skipped";
614
- else {
615
- let t = n.headers[r.header.toLowerCase()], o = t;
616
- r._tag === "custom" && n.headers["x-slack-request-timestamp"] && (o = `${n.headers["x-slack-request-timestamp"]}|${t ?? ""}`);
617
- let s = a(r, n.rawBody, i, o);
618
- if (d = s.ok, !s.ok) {
619
- let t = Y(401, {
643
+ if (i === null) {
644
+ let t = `no signing secret configured — set ${Ke(e.id)}`, n = Y(503, {
645
+ error: "webhook not configured",
646
+ reason: t
647
+ });
648
+ return d({
649
+ webhookId: e.id,
650
+ status: 503,
651
+ signatureOk: !1,
652
+ idempotency: "skipped",
653
+ durationMs: Date.now() - o,
654
+ errorMessage: t
655
+ }), n;
656
+ } else {
657
+ let t = s(r, {
658
+ rawBody: n.rawBody,
659
+ secret: i,
660
+ headers: n.headers
661
+ });
662
+ if (f = t.ok, !t.ok) {
663
+ let n = Y(401, {
620
664
  error: "invalid signature",
621
- reason: s.reason
665
+ reason: t.reason
622
666
  });
623
- return l({
667
+ return d({
624
668
  webhookId: e.id,
625
669
  status: 401,
626
670
  signatureOk: !1,
627
671
  idempotency: "skipped",
628
- durationMs: Date.now() - u,
629
- errorMessage: s.reason
630
- }), t;
672
+ durationMs: Date.now() - o,
673
+ errorMessage: t.reason
674
+ }), n;
631
675
  }
632
676
  }
633
677
  }
634
- let f;
678
+ let p;
635
679
  try {
636
- if (o === "json") {
680
+ if (a === "json") {
637
681
  let e = new TextDecoder().decode(n.rawBody);
638
- f = e.length === 0 ? null : JSON.parse(e);
639
- } else if (o === "form") {
682
+ p = e.length === 0 ? null : JSON.parse(e);
683
+ } else if (a === "form") {
640
684
  let e = new TextDecoder().decode(n.rawBody), t = new URLSearchParams(e), r = {};
641
685
  for (let [e, n] of t.entries()) r[e] = n;
642
- f = r;
643
- } else f = n.rawBody;
686
+ p = r;
687
+ } else p = n.rawBody;
644
688
  } catch (t) {
645
689
  let n = Y(400, {
646
690
  error: "malformed body",
647
691
  reason: t.message
648
692
  });
649
- return l({
693
+ return d({
650
694
  webhookId: e.id,
651
695
  status: 400,
652
- signatureOk: d,
696
+ signatureOk: f,
653
697
  idempotency: "skipped",
654
- durationMs: Date.now() - u,
698
+ durationMs: Date.now() - o,
655
699
  errorMessage: t.message
656
700
  }), n;
657
701
  }
658
- let p;
702
+ let m;
659
703
  try {
660
- p = S.decodeUnknownSync(e.payload)(f);
704
+ m = E.decodeUnknownSync(e.payload)(p);
661
705
  } catch (t) {
662
706
  let n = Y(422, {
663
707
  error: "schema validation failed",
664
708
  reason: t.message
665
709
  });
666
- return l({
710
+ return d({
667
711
  webhookId: e.id,
668
712
  status: 422,
669
- signatureOk: d,
713
+ signatureOk: f,
670
714
  idempotency: "skipped",
671
- durationMs: Date.now() - u,
715
+ durationMs: Date.now() - o,
672
716
  errorMessage: t.message
673
717
  }), n;
674
718
  }
675
- let m, h = "skipped";
719
+ let h, g = "skipped";
676
720
  if (i !== null) {
677
721
  let t = i.from;
678
- if (m = typeof t == "string" ? n.headers[t.toLowerCase()] : t(n.headers, n.rawBody), m !== void 0 && m.length > 0) {
679
- let t = s.claim(m, c);
680
- if (h = t, t === "duplicate") {
722
+ if (h = typeof t == "string" ? n.headers[t.toLowerCase()] : t(n.headers, n.rawBody), h !== void 0 && h.length > 0) {
723
+ let t = l.claim(h, u);
724
+ if (g = t, t === "duplicate") {
681
725
  let t = Y(200, {
682
726
  received: !0,
683
727
  duplicate: !0
684
728
  });
685
- return l({
729
+ return d({
686
730
  webhookId: e.id,
687
731
  status: 200,
688
- signatureOk: d,
732
+ signatureOk: f,
689
733
  idempotency: "duplicate",
690
- durationMs: Date.now() - u
734
+ durationMs: Date.now() - o
691
735
  }), t;
692
736
  }
693
737
  if (t === "inflight") {
694
738
  let t = Y(409, {
695
739
  error: "request already in flight",
696
- idempotencyKey: m
740
+ idempotencyKey: h
697
741
  });
698
- return l({
742
+ return d({
699
743
  webhookId: e.id,
700
744
  status: 409,
701
- signatureOk: d,
745
+ signatureOk: f,
702
746
  idempotency: "inflight",
703
- durationMs: Date.now() - u
747
+ durationMs: Date.now() - o
704
748
  }), t;
705
749
  }
706
750
  }
@@ -708,55 +752,55 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
708
752
  try {
709
753
  let r = t.resolveWorkflows?.();
710
754
  await e.handler({
711
- body: p,
755
+ body: m,
712
756
  rawBody: n.rawBody,
713
757
  headers: n.headers,
714
- idempotencyKey: m ?? "",
758
+ idempotencyKey: h ?? "",
715
759
  ...r ? { workflows: r } : {}
716
- }), m !== void 0 && s.commit(m);
760
+ }), h !== void 0 && l.commit(h);
717
761
  let i = Y(200, { received: !0 });
718
- return l({
762
+ return d({
719
763
  webhookId: e.id,
720
764
  status: 200,
721
- signatureOk: d,
722
- idempotency: h,
723
- durationMs: Date.now() - u
765
+ signatureOk: f,
766
+ idempotency: g,
767
+ durationMs: Date.now() - o
724
768
  }), i;
725
769
  } catch (t) {
726
- m !== void 0 && s.release(m);
770
+ h !== void 0 && l.release(h);
727
771
  let n = Y(500, {
728
772
  error: "handler threw",
729
773
  reason: t.message
730
774
  });
731
- return l({
775
+ return d({
732
776
  webhookId: e.id,
733
777
  status: 500,
734
- signatureOk: d,
735
- idempotency: h,
736
- durationMs: Date.now() - u,
778
+ signatureOk: f,
779
+ idempotency: g,
780
+ durationMs: Date.now() - o,
737
781
  errorMessage: t.message
738
- }), ne({
782
+ }), me({
739
783
  error: t,
740
784
  source: "webhook",
741
785
  name: e.id,
742
786
  fields: { status: 500 }
743
787
  }), n;
744
788
  }
745
- };
746
- }, Te = (e) => `/webhooks/${e}`, Ee = "_voltro_webhook_rate_windows", De = 6e4, Oe = (e, t) => `${e}@${t}`, ke = async (e, t, n) => (await e.query({
789
+ }, { [We]: c });
790
+ }, Ye = (e) => `/webhooks/${e}`, Xe = "_voltro_webhook_rate_windows", Ze = 6e4, Qe = (e, t) => `${e}@${t}`, $e = async (e, t, n) => (await e.query({
747
791
  table: "_voltro_webhook_rate_windows",
748
- predicate: C(w("scope", t), w("bucket", n)),
792
+ predicate: O(k("scope", t), k("bucket", n)),
749
793
  order: [],
750
794
  take: 1,
751
795
  skip: void 0,
752
796
  projection: void 0
753
- }))[0] ?? null, X = 32, Ae = async (e, t, n) => {
797
+ }))[0] ?? null, X = 32, et = async (e, t, n) => {
754
798
  for (let r = 0; r < X; r++) {
755
799
  r > 0 && await new Promise((e) => setTimeout(e, r));
756
- let i = await ke(e, t.key, n);
800
+ let i = await $e(e, t.key, n);
757
801
  if (i === null) {
758
- await e.insertIgnore(Ee, {
759
- id: Oe(t.key, n),
802
+ await e.insertIgnore(Xe, {
803
+ id: Qe(t.key, n),
760
804
  scope: t.key,
761
805
  bucket: n,
762
806
  count: 0,
@@ -769,31 +813,31 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
769
813
  if (await e.updateMany("_voltro_webhook_rate_windows", {
770
814
  count: i.count + 1,
771
815
  updatedAt: /* @__PURE__ */ new Date()
772
- }, { where: C(w("id", i.id), w("count", i.count)) }) === 1) return !0;
816
+ }, { where: O(k("id", i.id), k("count", i.count)) }) === 1) return !0;
773
817
  }
774
818
  throw Error(`webhook rate window: contention on (${t.key}, ${n}) exceeded ${X} attempts`);
775
- }, je = async (e, t, n) => {
819
+ }, tt = async (e, t, n) => {
776
820
  for (let r = 0; r < X; r++) {
777
821
  r > 0 && await new Promise((e) => setTimeout(e, r));
778
- let i = await ke(e, t, n);
822
+ let i = await $e(e, t, n);
779
823
  if (i === null || i.count <= 0 || await e.updateMany("_voltro_webhook_rate_windows", {
780
824
  count: i.count - 1,
781
825
  updatedAt: /* @__PURE__ */ new Date()
782
- }, { where: C(w("id", i.id), w("count", i.count)) }) === 1) return;
826
+ }, { where: O(k("id", i.id), k("count", i.count)) }) === 1) return;
783
827
  }
784
828
  throw Error(`webhook rate window: release contention on (${t}) exceeded ${X} attempts`);
785
- }, Me = async (e, t, n, r = De) => {
829
+ }, nt = async (e, t, n, r = Ze) => {
786
830
  if (t.length === 0) return {
787
831
  acquired: !0,
788
832
  retryInMs: 0
789
833
  };
790
834
  let i = Math.floor(n / r), a = [];
791
835
  for (let o of t) {
792
- if (await Ae(e, o, i)) {
836
+ if (await et(e, o, i)) {
793
837
  a.push(o);
794
838
  continue;
795
839
  }
796
- for (let t of a) await je(e, t.key, i);
840
+ for (let t of a) await tt(e, t.key, i);
797
841
  return {
798
842
  acquired: !1,
799
843
  retryInMs: (i + 1) * r - n
@@ -803,7 +847,7 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
803
847
  acquired: !0,
804
848
  retryInMs: 0
805
849
  };
806
- }, Ne = (e, t) => {
850
+ }, rt = (e, t) => {
807
851
  if (e === "json") return {
808
852
  contentType: "application/json",
809
853
  bytes: Buffer.from(t, "utf8")
@@ -812,22 +856,22 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
812
856
  try {
813
857
  n = JSON.parse(t);
814
858
  } catch (t) {
815
- throw new d({
859
+ throw new S({
816
860
  format: e,
817
861
  reason: `payload is not valid JSON: ${t.message}`
818
862
  });
819
863
  }
820
864
  return e === "form" ? {
821
865
  contentType: "application/x-www-form-urlencoded",
822
- bytes: Buffer.from(Pe(n), "utf8")
866
+ bytes: Buffer.from(it(n), "utf8")
823
867
  } : {
824
868
  contentType: "application/xml",
825
- bytes: Buffer.from(Ie(n), "utf8")
869
+ bytes: Buffer.from(ot(n), "utf8")
826
870
  };
827
- }, Pe = (e) => {
828
- if (typeof e != "object" || !e || Array.isArray(e)) throw new d({
871
+ }, it = (e) => {
872
+ if (typeof e != "object" || !e || Array.isArray(e)) throw new S({
829
873
  format: "form",
830
- reason: `form encoding requires a JSON object at the top level, got ${ze(e)}`
874
+ reason: `form encoding requires a JSON object at the top level, got ${lt(e)}`
831
875
  });
832
876
  let t = new URLSearchParams();
833
877
  for (let [n, r] of Object.entries(e)) Z(t, n, r);
@@ -846,13 +890,13 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
846
890
  return;
847
891
  }
848
892
  e.append(t, String(n));
849
- }, Fe = /^[A-Za-z_][A-Za-z0-9_.-]*$/, Ie = (e) => `<?xml version="1.0" encoding="UTF-8"?>${Q("webhook", e)}`, Q = (e, t) => {
850
- if (!Fe.test(e)) throw new d({
893
+ }, at = /^[A-Za-z_][A-Za-z0-9_.-]*$/, ot = (e) => `<?xml version="1.0" encoding="UTF-8"?>${Q("webhook", e)}`, Q = (e, t) => {
894
+ if (!at.test(e)) throw new S({
851
895
  format: "xml",
852
896
  reason: `object key ${JSON.stringify(e)} is not a valid XML element name`
853
897
  });
854
- return `<${e}>${Le(e, t)}</${e}>`;
855
- }, Le = (e, t) => t == null ? "" : Array.isArray(t) ? t.map((e) => Q("item", e)).join("") : typeof t == "object" ? Object.entries(t).map(([e, t]) => Q(e, t)).join("") : Re(String(t)), Re = (e) => e.replace(/[&<>"']/g, (e) => {
898
+ return `<${e}>${st(e, t)}</${e}>`;
899
+ }, st = (e, t) => t == null ? "" : Array.isArray(t) ? t.map((e) => Q("item", e)).join("") : typeof t == "object" ? Object.entries(t).map(([e, t]) => Q(e, t)).join("") : ct(String(t)), ct = (e) => e.replace(/[&<>"']/g, (e) => {
856
900
  switch (e) {
857
901
  case "&": return "&amp;";
858
902
  case "<": return "&lt;";
@@ -860,98 +904,102 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
860
904
  case "\"": return "&quot;";
861
905
  default: return "&apos;";
862
906
  }
863
- }), ze = (e) => e === null ? "null" : Array.isArray(e) ? "array" : typeof e, Be = "_voltro_webhook_targets", Ve = 32, He = async (e, t) => (await e.query({
907
+ }), lt = (e) => e === null ? "null" : Array.isArray(e) ? "array" : typeof e, ut = "_voltro_webhook_targets", dt = 32, ft = async (e, t) => (await e.query({
864
908
  table: "_voltro_webhook_targets",
865
- predicate: w("id", t),
909
+ predicate: k("id", t),
866
910
  order: [],
867
911
  take: 1,
868
912
  skip: void 0,
869
913
  projection: void 0
870
- }))[0] ?? null, Ue = async (e, t, n, r, i = /* @__PURE__ */ new Date()) => {
871
- for (let a = 0; a < Ve; a++) {
872
- a > 0 && await new Promise((e) => setTimeout(e, a));
873
- let o = await He(e, t);
874
- if (o === null) return {
914
+ }))[0] ?? null, pt = async (e, t, n, r, i = /* @__PURE__ */ new Date(), a = !1) => {
915
+ for (let o = 0; o < dt; o++) {
916
+ o > 0 && await new Promise((e) => setTimeout(e, o));
917
+ let s = await ft(e, t);
918
+ if (s === null) return {
875
919
  consecutiveFailures: 0,
876
920
  autoDisabled: !1
877
921
  };
878
- let s = o.consecutiveFailures ?? 0;
922
+ let c = s.consecutiveFailures ?? 0;
879
923
  if (n) {
880
- if (s === 0 || await e.updateMany("_voltro_webhook_targets", {
924
+ if (c === 0 || await e.updateMany("_voltro_webhook_targets", {
881
925
  consecutiveFailures: 0,
882
926
  updatedAt: i
883
- }, { where: C(w("id", t), w("consecutiveFailures", s)) }) === 1) return {
927
+ }, { where: O(k("id", t), k("consecutiveFailures", c)) }) === 1) return {
884
928
  consecutiveFailures: 0,
885
929
  autoDisabled: !1
886
930
  };
887
931
  continue;
888
932
  }
889
- let c = s + 1, l = o.autoDisableAfter, u = typeof l == "number" && l > 0 && o.active && c >= l, d = {
890
- consecutiveFailures: c,
933
+ let l = c + 1, u = s.autoDisableAfter, d = s.active && (a || typeof u == "number" && u > 0 && l >= u), f = {
934
+ consecutiveFailures: l,
891
935
  updatedAt: i
892
936
  };
893
- if (u && (d.active = !1, d.autoDisabledAt = i, d.autoDisableReason = r.slice(0, 500)), await e.updateMany("_voltro_webhook_targets", d, { where: C(w("id", t), w("consecutiveFailures", s)) }) === 1) return {
894
- consecutiveFailures: c,
895
- autoDisabled: u
937
+ if (d && (f.active = !1, f.autoDisabledAt = i, f.autoDisableReason = r.slice(0, 500)), await e.updateMany("_voltro_webhook_targets", f, { where: O(k("id", t), k("consecutiveFailures", c)) }) === 1) return {
938
+ consecutiveFailures: l,
939
+ autoDisabled: d
896
940
  };
897
941
  }
898
- throw Error(`webhook auto-disable: streak CAS contention on target ${t} exceeded ${Ve} attempts`);
899
- }, We = S.Struct({
900
- status: S.Number,
901
- body: S.String,
902
- latencyMs: S.Number,
903
- retryAfterSec: S.Union(S.Number, S.Undefined),
904
- transportError: S.Union(S.String, S.Undefined),
905
- encodeError: S.Union(S.String, S.Undefined)
906
- }), Ge = S.Struct({
907
- outcome: S.Literal("succeeded", "failed", "retry"),
908
- delayMs: S.Union(S.Number, S.Undefined),
909
- reason: S.Union(S.String, S.Undefined),
910
- autoDisabled: S.Union(S.Boolean, S.Undefined),
911
- consecutiveFailures: S.Union(S.Number, S.Undefined)
912
- }), Ke = S.Struct({
913
- acquired: S.Boolean,
914
- retryInMs: S.Number
915
- }), qe = re.make({
942
+ throw Error(`webhook auto-disable: streak CAS contention on target ${t} exceeded ${dt} attempts`);
943
+ }, mt = E.Struct({
944
+ status: E.Number,
945
+ body: E.String,
946
+ latencyMs: E.Number,
947
+ retryAfterSec: E.Union(E.Number, E.Undefined),
948
+ transportError: E.Union(E.String, E.Undefined),
949
+ encodeError: E.Union(E.String, E.Undefined)
950
+ }), ht = E.Struct({
951
+ outcome: E.Literal("succeeded", "failed", "retry"),
952
+ delayMs: E.Union(E.Number, E.Undefined),
953
+ reason: E.Union(E.String, E.Undefined),
954
+ autoDisabled: E.Union(E.Boolean, E.Undefined),
955
+ consecutiveFailures: E.Union(E.Number, E.Undefined)
956
+ }), gt = E.Struct({
957
+ acquired: E.Boolean,
958
+ retryInMs: E.Number
959
+ }), _t = _e.make({
916
960
  name: "voltro.deliverWebhook",
917
961
  payload: {
918
- deliveryId: S.String,
919
- targetId: S.String,
920
- event: S.String,
921
- eventId: S.String,
922
- payloadJson: S.String,
923
- attemptEpoch: S.optionalWith(S.Number, { default: () => 0 })
962
+ deliveryId: E.String,
963
+ targetId: E.String,
964
+ event: E.String,
965
+ eventId: E.String,
966
+ payloadJson: E.String,
967
+ attemptEpoch: E.optionalWith(E.Number, { default: () => 0 })
924
968
  },
925
- success: S.Struct({
926
- finalStatus: S.Literal("succeeded", "failed", "deferred"),
927
- attempts: S.Number
969
+ success: E.Struct({
970
+ finalStatus: E.Literal("succeeded", "failed", "deferred"),
971
+ attempts: E.Number
928
972
  }),
929
973
  idempotencyKey: ({ deliveryId: e, attemptEpoch: t }) => `voltro.deliverWebhook:${e}:${t ?? 0}`
930
- }), Je = (e, t = {}) => (n, r) => {
931
- let { deliveryId: i, targetId: a, event: s, eventId: c, payloadJson: l } = n, u = E({ scope: `webhook:${i}` });
932
- return x.gen(function* () {
933
- let n = yield* D.make({
974
+ }), vt = 3e4, yt = (e, t) => {
975
+ if (e !== void 0) return e;
976
+ let n = Number(t.VOLTRO_WEBHOOK_TIMEOUT_MS);
977
+ return Number.isFinite(n) && n > 0 ? n : vt;
978
+ }, bt = (e, t = {}) => (n, r) => {
979
+ let { deliveryId: i, targetId: a, event: o, eventId: s, payloadJson: c } = n, l = A({ scope: `webhook:${i}` });
980
+ return T.gen(function* () {
981
+ let n = yield* j.make({
934
982
  name: "fetch-target",
935
- success: S.Union(S.Null, S.Struct({
936
- id: S.String,
937
- event: S.String,
938
- url: S.String,
939
- secret: S.String,
940
- signing: S.Any,
941
- retry: S.Any,
942
- headers: S.Union(S.Record({
943
- key: S.String,
944
- value: S.String
945
- }), S.Null),
946
- rateLimitPerMinute: S.Union(S.Number, S.Null),
947
- active: S.Boolean,
948
- format: S.Literal("json", "form", "xml"),
949
- tenantId: S.Union(S.String, S.Null)
983
+ success: E.Union(E.Null, E.Struct({
984
+ id: E.String,
985
+ event: E.String,
986
+ url: E.String,
987
+ secret: E.String,
988
+ signing: E.Any,
989
+ retry: E.Any,
990
+ headers: E.Union(E.Record({
991
+ key: E.String,
992
+ value: E.String
993
+ }), E.Null),
994
+ rateLimitPerMinute: E.Union(E.Number, E.Null),
995
+ active: E.Boolean,
996
+ format: E.Literal("json", "form", "xml"),
997
+ tenantId: E.Union(E.String, E.Null)
950
998
  })),
951
- execute: x.tryPromise({
999
+ execute: T.tryPromise({
952
1000
  try: async () => (await e.store.query({
953
1001
  table: "_voltro_webhook_targets",
954
- predicate: w("id", a),
1002
+ predicate: k("id", a),
955
1003
  order: [{
956
1004
  column: "createdAt",
957
1005
  direction: "asc"
@@ -960,107 +1008,107 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
960
1008
  skip: void 0,
961
1009
  projection: void 0
962
1010
  }))[0] ?? null,
963
- catch: (e) => (u.debug("fetch-target raw error", {
1011
+ catch: (e) => (l.debug("fetch-target raw error", {
964
1012
  targetId: a,
965
- event: s,
1013
+ event: o,
966
1014
  cause: String(e)
967
1015
  }), /* @__PURE__ */ Error(`fetch-target failed: ${e.message}`))
968
- }).pipe(x.orDie)
1016
+ }).pipe(T.orDie)
969
1017
  });
970
1018
  if (n === null) return {
971
1019
  finalStatus: "failed",
972
1020
  attempts: 0
973
1021
  };
974
- let r = async (t, r, o) => {
1022
+ let r = async (t, r, l) => {
975
1023
  await e.store.update("_voltro_webhook_deliveries", t, {
976
- ...o,
1024
+ ...l,
977
1025
  updatedAt: /* @__PURE__ */ new Date()
978
1026
  }) === null && await e.store.insert("_voltro_webhook_deliveries", {
979
1027
  id: t,
980
1028
  deliveryId: i,
981
1029
  targetId: a,
982
1030
  tenantId: n.tenantId ?? null,
983
- event: s,
984
- eventId: c,
1031
+ event: o,
1032
+ eventId: s,
985
1033
  attempt: r,
986
- payload: l,
1034
+ payload: c,
987
1035
  scheduledAt: /* @__PURE__ */ new Date(),
988
1036
  createdAt: /* @__PURE__ */ new Date(),
989
1037
  updatedAt: /* @__PURE__ */ new Date(),
990
- ...o
1038
+ ...l
991
1039
  });
992
1040
  };
993
- if (n.active !== !0) return yield* D.make({
1041
+ if (n.active !== !0) return yield* j.make({
994
1042
  name: "record-paused-pending",
995
- success: S.Void,
996
- execute: x.tryPromise({
1043
+ success: E.Void,
1044
+ execute: T.tryPromise({
997
1045
  try: () => r(`${i}:1`, 1, { status: "pending" }),
998
1046
  catch: (e) => /* @__PURE__ */ Error(`record-paused-pending failed: ${e.message}`)
999
- }).pipe(x.orDie)
1047
+ }).pipe(T.orDie)
1000
1048
  }), {
1001
1049
  finalStatus: "deferred",
1002
1050
  attempts: 0
1003
1051
  };
1004
- let f = (e) => typeof e == "string" ? JSON.parse(e) : e, p = f(n.retry), m = f(n.signing), h = n.headers === null ? null : f(n.headers), g = t.rateWindowMs ?? 6e4, _ = t.events?.find((e) => e.id === s)?.globalRateLimit, v = [...typeof n.rateLimitPerMinute == "number" && n.rateLimitPerMinute > 0 ? [{
1052
+ let u = (e) => typeof e == "string" ? JSON.parse(e) : e, d = u(n.retry), p = u(n.signing), m = n.headers === null ? null : u(n.headers), h = t.rateWindowMs ?? 6e4, g = yt(t.timeoutMs, process.env), _ = t.events?.find((e) => e.id === o)?.globalRateLimit, v = [...typeof n.rateLimitPerMinute == "number" && n.rateLimitPerMinute > 0 ? [{
1005
1053
  key: `target:${n.id}`,
1006
1054
  limit: n.rateLimitPerMinute
1007
1055
  }] : [], ..._ !== void 0 && _.perMinute > 0 ? [{
1008
- key: `event:${s}`,
1056
+ key: `event:${o}`,
1009
1057
  limit: _.perMinute
1010
1058
  }] : []];
1011
- for (let t = 1; t <= p.maxAttempts; t++) {
1012
- let f = `${i}:${t}`;
1059
+ for (let t = 1; t <= d.maxAttempts; t++) {
1060
+ let u = `${i}:${t}`;
1013
1061
  if (v.length > 0) for (let n = 0;; n++) {
1014
- let i = yield* D.make({
1062
+ let i = yield* j.make({
1015
1063
  name: `rate-acquire-${t}-${n}`,
1016
- success: Ke,
1017
- execute: x.tryPromise({
1018
- try: () => Me(e.store, v, Date.now(), g),
1019
- catch: (e) => (u.debug("rate-acquire raw error", {
1064
+ success: gt,
1065
+ execute: T.tryPromise({
1066
+ try: () => nt(e.store, v, Date.now(), h),
1067
+ catch: (e) => (l.debug("rate-acquire raw error", {
1020
1068
  targetId: a,
1021
- event: s,
1069
+ event: o,
1022
1070
  attempt: t,
1023
1071
  cause: String(e)
1024
1072
  }), /* @__PURE__ */ Error(`rate-acquire failed: ${e.message}`))
1025
- }).pipe(x.orDie)
1073
+ }).pipe(T.orDie)
1026
1074
  });
1027
1075
  if (i.acquired) break;
1028
- yield* D.make({
1076
+ yield* j.make({
1029
1077
  name: `record-rate-deferral-${t}-${n}`,
1030
- success: S.Void,
1031
- execute: x.tryPromise({
1032
- try: () => r(f, t, {
1078
+ success: E.Void,
1079
+ execute: T.tryPromise({
1080
+ try: () => r(u, t, {
1033
1081
  status: "pending",
1034
1082
  nextAttemptAt: new Date(Date.now() + i.retryInMs)
1035
1083
  }),
1036
1084
  catch: (e) => /* @__PURE__ */ Error(`record-rate-deferral failed: ${e.message}`)
1037
- }).pipe(x.orDie)
1038
- }), yield* O.sleep({
1085
+ }).pipe(T.orDie)
1086
+ }), yield* M.sleep({
1039
1087
  name: `rate-window-sleep-${t}-${n}`,
1040
1088
  duration: `${i.retryInMs} millis`
1041
1089
  });
1042
1090
  }
1043
- yield* D.make({
1091
+ yield* j.make({
1044
1092
  name: `record-attempt-start-${t}`,
1045
- success: S.Void,
1046
- execute: x.tryPromise({
1047
- try: () => r(f, t, {
1093
+ success: E.Void,
1094
+ execute: T.tryPromise({
1095
+ try: () => r(u, t, {
1048
1096
  status: "inFlight",
1049
1097
  nextAttemptAt: null,
1050
1098
  scheduledAt: /* @__PURE__ */ new Date()
1051
1099
  }),
1052
1100
  catch: (e) => /* @__PURE__ */ Error(`record-attempt-start failed: ${e.message}`)
1053
- }).pipe(x.orDie)
1101
+ }).pipe(T.orDie)
1054
1102
  });
1055
- let _ = yield* D.make({
1103
+ let _ = yield* j.make({
1056
1104
  name: `sign-and-post-${t}`,
1057
- success: We,
1058
- execute: x.promise(async () => {
1105
+ success: mt,
1106
+ execute: T.promise(async () => {
1059
1107
  let e = Date.now(), r;
1060
1108
  try {
1061
- r = Ne(n.format, l);
1109
+ r = rt(n.format, c);
1062
1110
  } catch (t) {
1063
- if (t instanceof d) return {
1111
+ if (t instanceof S) return {
1064
1112
  status: 0,
1065
1113
  body: "",
1066
1114
  latencyMs: Date.now() - e,
@@ -1070,26 +1118,32 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
1070
1118
  };
1071
1119
  throw t;
1072
1120
  }
1073
- let a = Buffer.from(r.bytes), { headerName: u, headerValue: f } = o(m, a, n.secret);
1074
- process.env.NODE_ENV === "production" && T(n.url);
1121
+ let a = Buffer.from(r.bytes), { headers: l } = f(p, {
1122
+ rawBody: a,
1123
+ secret: n.secret,
1124
+ messageId: i
1125
+ });
1126
+ process.env.NODE_ENV === "production" && ge(n.url);
1075
1127
  try {
1076
- let o = await fetch(n.url, {
1128
+ let c = await fetch(n.url, {
1077
1129
  method: "POST",
1078
1130
  headers: {
1079
1131
  "content-type": r.contentType,
1080
- [u]: f,
1081
- "x-voltro-event": s,
1082
- "x-voltro-event-id": c,
1132
+ ...l,
1133
+ "x-voltro-event": o,
1134
+ "x-voltro-event-id": s,
1083
1135
  "x-voltro-delivery-id": i,
1084
1136
  "x-voltro-attempt": String(t),
1085
1137
  "idempotency-key": i,
1086
- ...h ?? {}
1138
+ ...m ?? {}
1087
1139
  },
1088
- body: a
1089
- }), l = (await o.text()).slice(0, 8192), d = o.headers.get("retry-after");
1140
+ body: a,
1141
+ redirect: "manual",
1142
+ signal: AbortSignal.timeout(g)
1143
+ }), u = (await c.text()).slice(0, 8192), d = c.headers.get("retry-after");
1090
1144
  return {
1091
- status: o.status,
1092
- body: l,
1145
+ status: c.status,
1146
+ body: u,
1093
1147
  latencyMs: Date.now() - e,
1094
1148
  retryAfterSec: d !== null && /^\d+$/.test(d) ? Number(d) : void 0,
1095
1149
  transportError: void 0,
@@ -1106,21 +1160,21 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
1106
1160
  };
1107
1161
  }
1108
1162
  })
1109
- }), y = yield* D.make({
1163
+ }), y = yield* j.make({
1110
1164
  name: `classify-and-record-${t}`,
1111
- success: Ge,
1112
- execute: x.tryPromise({
1165
+ success: ht,
1166
+ execute: T.tryPromise({
1113
1167
  try: async () => {
1114
- let r = _.status >= 200 && _.status < 300, i = _.transportError !== void 0, o = _.encodeError !== void 0, s = (t, n) => Ue(e.store, a, t, n);
1168
+ let r = _.status >= 200 && _.status < 300, i = _.transportError !== void 0, o = _.encodeError !== void 0, s = _.status === 410, c = (t, n) => pt(e.store, a, t, n, /* @__PURE__ */ new Date(), !t && s);
1115
1169
  if (r) {
1116
- await e.store.update("_voltro_webhook_deliveries", f, {
1170
+ await e.store.update("_voltro_webhook_deliveries", u, {
1117
1171
  status: "succeeded",
1118
1172
  responseStatus: _.status,
1119
1173
  responseBody: _.body,
1120
1174
  latencyMs: _.latencyMs,
1121
1175
  updatedAt: /* @__PURE__ */ new Date()
1122
1176
  });
1123
- let t = await s(!0, "");
1177
+ let t = await c(!0, "");
1124
1178
  return {
1125
1179
  outcome: "succeeded",
1126
1180
  delayMs: void 0,
@@ -1129,13 +1183,13 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
1129
1183
  consecutiveFailures: t.consecutiveFailures
1130
1184
  };
1131
1185
  }
1132
- let c = o ? null : M(p, t, {
1186
+ let l = o ? null : L(d, t, {
1133
1187
  ...i ? {} : { status: _.status },
1134
1188
  ..._.retryAfterSec === void 0 ? {} : { retryAfterSeconds: _.retryAfterSec }
1135
1189
  });
1136
- if (c === null) {
1190
+ if (l === null) {
1137
1191
  let t = o ? `encode (${n.format}): ${_.encodeError}` : i ? `transport: ${_.transportError}` : `http ${_.status}: ${_.body.slice(0, 200)}`;
1138
- await e.store.update("_voltro_webhook_deliveries", f, {
1192
+ await e.store.update("_voltro_webhook_deliveries", u, {
1139
1193
  status: "failed",
1140
1194
  responseStatus: i || o ? null : _.status,
1141
1195
  responseBody: i || o ? null : _.body,
@@ -1143,7 +1197,7 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
1143
1197
  latencyMs: _.latencyMs,
1144
1198
  updatedAt: /* @__PURE__ */ new Date()
1145
1199
  });
1146
- let r = await s(!1, t);
1200
+ let r = await c(!1, t);
1147
1201
  return {
1148
1202
  outcome: "failed",
1149
1203
  delayMs: void 0,
@@ -1152,33 +1206,33 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
1152
1206
  consecutiveFailures: r.consecutiveFailures
1153
1207
  };
1154
1208
  }
1155
- return await e.store.update("_voltro_webhook_deliveries", f, {
1209
+ return await e.store.update("_voltro_webhook_deliveries", u, {
1156
1210
  status: "retryScheduled",
1157
1211
  responseStatus: i ? null : _.status,
1158
1212
  responseBody: i ? null : _.body,
1159
1213
  errorMessage: _.transportError ?? null,
1160
1214
  latencyMs: _.latencyMs,
1161
- nextAttemptAt: new Date(Date.now() + c.delayMs),
1215
+ nextAttemptAt: new Date(Date.now() + l.delayMs),
1162
1216
  updatedAt: /* @__PURE__ */ new Date()
1163
1217
  }), {
1164
1218
  outcome: "retry",
1165
- delayMs: c.delayMs,
1219
+ delayMs: l.delayMs,
1166
1220
  reason: void 0,
1167
1221
  autoDisabled: void 0,
1168
1222
  consecutiveFailures: void 0
1169
1223
  };
1170
1224
  },
1171
- catch: (e) => (u.debug("classify-and-record raw error", {
1225
+ catch: (e) => (l.debug("classify-and-record raw error", {
1172
1226
  targetId: a,
1173
- event: s,
1227
+ event: o,
1174
1228
  attempt: t,
1175
1229
  cause: String(e)
1176
1230
  }), /* @__PURE__ */ Error(`classify-and-record failed: ${e.message}`))
1177
- }).pipe(x.orDie)
1231
+ }).pipe(T.orDie)
1178
1232
  });
1179
- if (y.autoDisabled === !0 && u.warn("target auto-disabled after consecutive failures", {
1233
+ if (y.autoDisabled === !0 && l.warn("target auto-disabled after consecutive failures", {
1180
1234
  targetId: a,
1181
- event: s,
1235
+ event: o,
1182
1236
  consecutiveFailures: y.consecutiveFailures ?? null,
1183
1237
  reason: y.reason ?? null
1184
1238
  }), y.outcome === "succeeded") return {
@@ -1189,25 +1243,25 @@ var ae = (e) => e.webhook !== void 0, k = (e) => {
1189
1243
  finalStatus: "failed",
1190
1244
  attempts: t
1191
1245
  };
1192
- y.delayMs !== void 0 && (yield* O.sleep({
1246
+ y.delayMs !== void 0 && (yield* M.sleep({
1193
1247
  name: `retry-sleep-${t}`,
1194
1248
  duration: `${y.delayMs} millis`
1195
1249
  }));
1196
1250
  }
1197
1251
  return {
1198
1252
  finalStatus: "failed",
1199
- attempts: p.maxAttempts
1253
+ attempts: d.maxAttempts
1200
1254
  };
1201
1255
  });
1202
- }, $ = "voltro.webhook.emit", Ye = (e) => typeof e.event == "string", Xe = (e) => ie({
1256
+ }, $ = "voltro.webhook.emit", xt = (e) => typeof e.event == "string", St = (e) => ve({
1203
1257
  effect: $,
1204
1258
  maxAttempts: 1,
1205
1259
  handler: async ({ payload: t }) => {
1206
- if (!Ye(t)) throw Error(`${$}: row payload has no \`event\` name — cannot resolve a descriptor. Got keys: ${Object.keys(t).join(", ") || "(none)"}`);
1260
+ if (!xt(t)) throw Error(`${$}: row payload has no \`event\` name — cannot resolve a descriptor. Got keys: ${Object.keys(t).join(", ") || "(none)"}`);
1207
1261
  let n = e();
1208
1262
  if (n === void 0) throw Error(`${$}: the outgoing-webhooks service is not available in this process. An emit was enqueued by a build that had the plugin registered; this one does not.`);
1209
1263
  await n.emit(t.event, t.payload, { tenantId: t.tenantId });
1210
1264
  }
1211
1265
  });
1212
1266
  //#endregion
1213
- export { W as IdempotencyCache, De as RATE_WINDOW_MS, Ee as RATE_WINDOW_TABLE, Be as TARGETS_TABLE, $ as WEBHOOK_EMIT_EFFECT, l as WebhookDeliveryNotFound, u as WebhookPayloadInvalid, d as WebhookPayloadUnrepresentable, f as WebhookPayloadVersionInvalid, p as WebhookSubscribeInvalid, N as WebhooksService, m as _voltroWebhookDeliveriesTable, h as _voltroWebhookEventStatsTable, g as _voltroWebhookRateWindowsTable, _ as _voltroWebhookTargetsTable, Me as acquireRateSlots, k as asOutgoingEvent, Je as buildDeliverWebhookExecute, be as buildWebhooksService, me as compareVersions, Ae as consumeRateSlot, Te as defaultIncomingPath, c as defaultOutgoingSignature, se as defaultRetryPolicy, s as defineIncomingWebhook, t as defineWebhookProvider, qe as deliverWebhookWorkflow, Ne as encodePayload, I as eventsOf, ce as fastRetryPolicy, F as generateSecret, K as getIdempotencyCache, i as githubSignature, ae as hasWebhookAudience, r as isWebhookDescriptor, Xe as makeDeferredEmitHandler, he as matchesFilter, we as mountIncomingWebhook, M as nextRetry, A as parseDuration, J as parseTtl, Ue as recordDeliveryOutcome, je as releaseRateSlot, ue as resolveSubscribe, o as signPayload, n as slackSignature, e as stripeSignature, Se as useWebhooks, xe as useWebhooksEffect, L as validateSubscribe, a as verifySignature, v as webhookTables };
1267
+ export { Ve as IdempotencyCache, Ze as RATE_WINDOW_MS, Xe as RATE_WINDOW_TABLE, p as STANDARD_WEBHOOKS_DEFAULT_TOLERANCE_SECONDS, ee as STANDARD_WEBHOOKS_ID_HEADER, c as STANDARD_WEBHOOKS_MAX_KEY_BYTES, l as STANDARD_WEBHOOKS_MIN_KEY_BYTES, _ as STANDARD_WEBHOOKS_SECRET_PREFIX, m as STANDARD_WEBHOOKS_SIGNATURE_HEADER, d as STANDARD_WEBHOOKS_TIMESTAMP_HEADER, u as STANDARD_WEBHOOKS_VERSION, ut as TARGETS_TABLE, Ge as UnverifiedIncomingWebhook, N as WEBHOOKS_PLUGIN_PERMISSIONS, $ as WEBHOOK_EMIT_EFFECT, We as WEBHOOK_VERIFICATION_PROPERTY, ae as WebhookDeliveryNotFound, x as WebhookPayloadInvalid, S as WebhookPayloadUnrepresentable, C as WebhookPayloadVersionInvalid, w as WebhookSubscribeInvalid, Ce as WebhooksService, oe as _voltroWebhookDeliveriesTable, se as _voltroWebhookEventStatsTable, ce as _voltroWebhookRateWindowsTable, le as _voltroWebhookTargetsTable, nt as acquireRateSlots, P as asOutgoingEvent, bt as buildDeliverWebhookExecute, Le as buildWebhooksService, ke as compareVersions, et as consumeRateSlot, Ye as defaultIncomingPath, b as defaultOutgoingSignature, R as defaultRetryPolicy, ne as defineIncomingWebhook, r as defineWebhookProvider, _t as deliverWebhookWorkflow, rt as encodePayload, B as eventsOf, Se as fastRetryPolicy, z as generateSecret, i as generateStandardWebhooksSecret, h as genericHmacSignature, He as getIdempotencyCache, v as githubSignature, be as hasWebhookAudience, qe as incomingWebhookVerification, te as isStandardWebhooksSecret, t as isWebhookDescriptor, St as makeDeferredEmitHandler, Ae as matchesFilter, Je as mountIncomingWebhook, L as nextRetry, F as parseDuration, Ue as parseTtl, pt as recordDeliveryOutcome, tt as releaseRateSlot, Ee as resolveSubscribe, f as signRequest, a as slackSignature, ie as standardWebhooksHeaders, o as standardWebhooksKey, g as standardWebhooksSignature, re as standardWebhooksSignatureToken, n as standardWebhooksSignedContent, y as stripeSignature, ze as useWebhooks, Re as useWebhooksEffect, V as validateSubscribe, s as verifyRequest, e as verifyStandardWebhooks, ue as webhookTables, ye as webhooksPlugin };