@voltro/plugin-webhooks 0.86.0 → 0.88.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/CHANGELOG.md +5484 -0
- package/THIRD-PARTY-NOTICES.md +1511 -276
- package/dist/autoDisable.js +1 -2
- package/dist/deferredEmit.js +1 -2
- package/dist/deliverWorkflow.js +28 -15
- package/dist/dsl.js +1 -2
- package/dist/encode.js +1 -2
- package/dist/errors.js +1 -2
- package/dist/eventAudience.js +1 -2
- package/dist/idempotency.js +1 -2
- package/dist/incoming.js +1 -2
- package/dist/index.d.ts +46 -4
- package/dist/index.js +10 -10
- package/dist/mixin.d.ts +16 -2
- package/dist/mixin.js +3 -2
- package/dist/plugin.js +1 -2
- package/dist/providers/generic.js +1 -2
- package/dist/providers/github.js +1 -2
- package/dist/providers/slack.js +1 -2
- package/dist/providers/stripe.js +1 -2
- package/dist/rateLimit.js +1 -2
- package/dist/retry.js +1 -2
- package/dist/service.js +88 -53
- package/dist/signing.js +1 -2
- package/dist/standardWebhooks.js +1 -2
- package/package.json +8 -8
package/dist/service.js
CHANGED
|
@@ -7,13 +7,13 @@ import { Context as u, Effect as d, Result as f, Schema as p } from "effect";
|
|
|
7
7
|
import { randomBytes as m, randomUUID as h } from "node:crypto";
|
|
8
8
|
import { and as g, eq as _ } from "@voltro/database";
|
|
9
9
|
import { assertPublicUrl as v } from "@voltro/integration-http";
|
|
10
|
-
|
|
11
|
-
var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {},
|
|
10
|
+
// src/service.ts
|
|
11
|
+
var y = 2592e3, b = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, x = 32, S = 32, C = () => m(x).toString("hex"), w = (e) => e.events ?? (e.event === void 0 ? [] : [e.event]), T = (e, t) => {
|
|
12
12
|
if (e !== void 0 && t?._tag === "standardWebhooks" && !n(e)) throw new c({
|
|
13
13
|
field: "secret",
|
|
14
14
|
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. If the incompatible key is inherited, rotate the endpoint secret and update the receiver before adding the event"
|
|
15
15
|
});
|
|
16
|
-
},
|
|
16
|
+
}, E = (e) => {
|
|
17
17
|
let t;
|
|
18
18
|
try {
|
|
19
19
|
t = new URL(e.url);
|
|
@@ -35,7 +35,7 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
35
35
|
reason: e.message
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
let n =
|
|
38
|
+
let n = w(e);
|
|
39
39
|
if (n.length === 0) throw new c({
|
|
40
40
|
field: "event",
|
|
41
41
|
reason: "event id required"
|
|
@@ -52,11 +52,11 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
52
52
|
field: "events",
|
|
53
53
|
reason: "duplicate event — one row per event, so a repeat would deliver twice"
|
|
54
54
|
});
|
|
55
|
-
if (e.secret !== void 0 && e.secret.length <
|
|
55
|
+
if (e.secret !== void 0 && e.secret.length < S) throw new c({
|
|
56
56
|
field: "secret",
|
|
57
|
-
reason: `secret must be at least ${
|
|
57
|
+
reason: `secret must be at least ${S} chars`
|
|
58
58
|
});
|
|
59
|
-
if (
|
|
59
|
+
if (T(e.secret, e.signing), e.retry !== void 0) {
|
|
60
60
|
if (e.retry.maxAttempts < 1) throw new c({
|
|
61
61
|
field: "retry",
|
|
62
62
|
reason: "retry.maxAttempts must be ≥ 1"
|
|
@@ -74,9 +74,9 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
74
74
|
field: "autoDisableAfter",
|
|
75
75
|
reason: `autoDisableAfter must be a positive integer, got ${e.autoDisableAfter}`
|
|
76
76
|
});
|
|
77
|
-
},
|
|
78
|
-
let s = e.signing ?? n?.defaultSigning ?? r(), c = s._tag === "standardWebhooks" ? t :
|
|
79
|
-
return
|
|
77
|
+
}, D = (e, n, a, o) => {
|
|
78
|
+
let s = e.signing ?? n?.defaultSigning ?? r(), c = s._tag === "standardWebhooks" ? t : C, l = o ?? e.secret ?? c();
|
|
79
|
+
return T(l, s), {
|
|
80
80
|
id: h(),
|
|
81
81
|
tenantId: e.tenantId ?? null,
|
|
82
82
|
event: a ?? e.event ?? "",
|
|
@@ -97,14 +97,14 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
97
97
|
payloadVersion: e.payloadVersion ?? n?.version ?? 1,
|
|
98
98
|
description: e.description ?? null
|
|
99
99
|
};
|
|
100
|
-
},
|
|
100
|
+
}, O = (e) => e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : 0, k = (e) => e instanceof Date ? e.toISOString() : typeof e == "string" ? e : null, A = (e) => {
|
|
101
101
|
if (typeof e != "string") return e;
|
|
102
102
|
try {
|
|
103
103
|
return JSON.parse(e);
|
|
104
104
|
} catch {
|
|
105
105
|
return e;
|
|
106
106
|
}
|
|
107
|
-
},
|
|
107
|
+
}, j = (e) => ({
|
|
108
108
|
id: String(e.id),
|
|
109
109
|
deliveryId: String(e.deliveryId),
|
|
110
110
|
targetId: String(e.targetId),
|
|
@@ -115,28 +115,28 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
115
115
|
responseStatus: e.responseStatus ?? null,
|
|
116
116
|
errorMessage: e.errorMessage ?? null,
|
|
117
117
|
latencyMs: e.latencyMs ?? null,
|
|
118
|
-
scheduledAt:
|
|
119
|
-
nextAttemptAt:
|
|
120
|
-
createdAt:
|
|
121
|
-
}),
|
|
118
|
+
scheduledAt: k(e.scheduledAt),
|
|
119
|
+
nextAttemptAt: k(e.nextAttemptAt),
|
|
120
|
+
createdAt: k(e.createdAt)
|
|
121
|
+
}), M = (e, t) => e === t ? "current" : e < t ? "behind" : "ahead", N = (e, t) => {
|
|
122
122
|
if (e === null) return !0;
|
|
123
123
|
let n = { payload: t };
|
|
124
|
-
for (let [t, r] of Object.entries(e)) if (!
|
|
124
|
+
for (let [t, r] of Object.entries(e)) if (!I(P(n, t), r)) return !1;
|
|
125
125
|
return !0;
|
|
126
|
-
},
|
|
126
|
+
}, P = (e, t) => {
|
|
127
127
|
let n = t.split("."), r = e;
|
|
128
128
|
for (let e of n) {
|
|
129
129
|
if (typeof r != "object" || !r) return;
|
|
130
130
|
r = r[e];
|
|
131
131
|
}
|
|
132
132
|
return r;
|
|
133
|
-
},
|
|
133
|
+
}, F = (e, t) => {
|
|
134
134
|
if (typeof e == "number" && typeof t == "number") return e - t;
|
|
135
135
|
if (typeof e == "string" && typeof t == "string") return e < t ? -1 : +(e > t);
|
|
136
|
-
},
|
|
136
|
+
}, I = (e, t) => {
|
|
137
137
|
if (typeof t == "object" && t && !Array.isArray(t)) {
|
|
138
138
|
let n = t;
|
|
139
|
-
return "eq" in n && e !== n.eq || "in" in n && (!Array.isArray(n.in) || !n.in.includes(e)) || "gt" in n && !((
|
|
139
|
+
return "eq" in n && e !== n.eq || "in" in n && (!Array.isArray(n.in) || !n.in.includes(e)) || "gt" in n && !((F(e, n.gt) ?? 0) > 0) || "gte" in n && !((F(e, n.gte) ?? -1) >= 0) || "lt" in n && !((F(e, n.lt) ?? 0) < 0) || "lte" in n && !((F(e, n.lte) ?? 1) <= 0) ? !1 : [
|
|
140
140
|
"eq",
|
|
141
141
|
"in",
|
|
142
142
|
"gt",
|
|
@@ -146,9 +146,9 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
146
146
|
].some((e) => e in n);
|
|
147
147
|
}
|
|
148
148
|
return e === t;
|
|
149
|
-
},
|
|
149
|
+
}, L = (e, t) => e !== null && Object.entries(t).every(([t, n]) => e[t] === n), R = 500, z = 200, B = async (e, t) => {
|
|
150
150
|
let n = [];
|
|
151
|
-
for (let r = 0; r <
|
|
151
|
+
for (let r = 0; r < z; r += 1) {
|
|
152
152
|
let i = await e.store.query({
|
|
153
153
|
table: "_voltro_webhook_targets",
|
|
154
154
|
predicate: t,
|
|
@@ -156,20 +156,20 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
156
156
|
column: "id",
|
|
157
157
|
direction: "asc"
|
|
158
158
|
}],
|
|
159
|
-
take:
|
|
160
|
-
skip: r === 0 ? void 0 : r *
|
|
159
|
+
take: R,
|
|
160
|
+
skip: r === 0 ? void 0 : r * R,
|
|
161
161
|
projection: void 0
|
|
162
162
|
});
|
|
163
|
-
if (n.push(...i), i.length <
|
|
163
|
+
if (n.push(...i), i.length < R) return n;
|
|
164
164
|
}
|
|
165
|
-
throw Error(`webhooks: more than ${
|
|
166
|
-
},
|
|
167
|
-
let n = (await
|
|
165
|
+
throw Error(`webhooks: more than ${z * R} 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.`);
|
|
166
|
+
}, V = async (e, t) => {
|
|
167
|
+
let n = (await B(e)).filter((e) => L(e.scope, t));
|
|
168
168
|
if (n.length === 0) return;
|
|
169
169
|
let r = new Set(n.map((e) => e.secret));
|
|
170
170
|
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.`);
|
|
171
171
|
return [...r][0];
|
|
172
|
-
},
|
|
172
|
+
}, H = async (e, t) => {
|
|
173
173
|
try {
|
|
174
174
|
let n = await e.store.query({
|
|
175
175
|
table: "_voltro_webhook_event_stats",
|
|
@@ -195,11 +195,11 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
195
195
|
updatedAt: r
|
|
196
196
|
});
|
|
197
197
|
} catch {}
|
|
198
|
-
},
|
|
198
|
+
}, U = (n, r, i = {}) => {
|
|
199
199
|
let c = new Map((i.events ?? []).map((e) => [e.id, e])), u = {
|
|
200
200
|
subscribe: async (e) => {
|
|
201
|
-
|
|
202
|
-
let r =
|
|
201
|
+
E(e);
|
|
202
|
+
let r = w(e), i = e.secret === void 0 && e.scope !== void 0 ? await V(n, e.scope) : void 0, a = e.secret ?? i ?? t(), o = r.map((t) => D(e, c.get(t), t, a));
|
|
203
203
|
for (let e of o) await n.store.insert("_voltro_webhook_targets", {
|
|
204
204
|
...e,
|
|
205
205
|
createdAt: /* @__PURE__ */ new Date(),
|
|
@@ -228,9 +228,9 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
228
228
|
issues: e.failure.message
|
|
229
229
|
});
|
|
230
230
|
}
|
|
231
|
-
let d = a?.eventId ?? h(), m = a?.tenantId, v = await
|
|
232
|
-
await
|
|
233
|
-
let y = v.filter((e) =>
|
|
231
|
+
let d = a?.eventId ?? h(), m = a?.tenantId, v = await B(n, m == null ? _("event", u) : g(_("event", u), _("tenantId", m)));
|
|
232
|
+
await H(n, u);
|
|
233
|
+
let y = v.filter((e) => N(e.filter, i)), b = [], x = JSON.stringify(i), S = async (e, t) => {
|
|
234
234
|
let i = h();
|
|
235
235
|
e.active ? (await r({
|
|
236
236
|
deliveryId: i,
|
|
@@ -310,7 +310,7 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
310
310
|
})).length === 0) throw new l({ targetId: e });
|
|
311
311
|
return [e];
|
|
312
312
|
}
|
|
313
|
-
let t = (await
|
|
313
|
+
let t = (await B(n)).filter((t) => L(t.scope, e.scope)).map((e) => e.id);
|
|
314
314
|
if (t.length === 0) throw Error(`webhooks: no target matches scope ${JSON.stringify(e.scope)} — the operation would have silently done nothing`);
|
|
315
315
|
return t;
|
|
316
316
|
},
|
|
@@ -353,16 +353,52 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
353
353
|
deleteTarget: async (e) => {
|
|
354
354
|
for (let t of await u.resolveTargets(e)) await n.store.delete("_voltro_webhook_targets", t), await n.store.deleteMany("_voltro_webhook_deliveries", { where: g(_("targetId", t), _("status", "pending")) });
|
|
355
355
|
},
|
|
356
|
-
rotateSecret: async (e) => {
|
|
357
|
-
let
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
356
|
+
rotateSecret: async (e, r = {}) => {
|
|
357
|
+
let i = r.overlapSeconds ?? 2592e3;
|
|
358
|
+
if (!Number.isInteger(i) || i < 0 || i > 2592e3) throw Error(`rotateSecret: overlapSeconds must be an integer between 0 and ${y} (30 days), got ${String(i)}`);
|
|
359
|
+
let a = t(), o = i > 0 ? /* @__PURE__ */ new Date(Math.floor(Date.now() / 1e3) * 1e3 + i * 1e3) : null, s = o !== null;
|
|
360
|
+
for (let t of await u.resolveTargets(e)) {
|
|
361
|
+
let [e] = await n.store.query({
|
|
362
|
+
table: "_voltro_webhook_targets",
|
|
363
|
+
predicate: _("id", t),
|
|
364
|
+
order: [],
|
|
365
|
+
take: 1,
|
|
366
|
+
skip: void 0,
|
|
367
|
+
projection: void 0
|
|
368
|
+
}), r = typeof e?.signing == "string" ? JSON.parse(e.signing) : e?.signing, i = o !== null && e !== void 0 && r?._tag === "standardWebhooks";
|
|
369
|
+
i || (s = !1), await n.store.update("_voltro_webhook_targets", t, {
|
|
370
|
+
secret: a,
|
|
371
|
+
previousSecret: i ? e.secret : null,
|
|
372
|
+
previousSecretUntil: i ? o : null,
|
|
373
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
secret: a,
|
|
378
|
+
previousSignedUntil: s ? o : null
|
|
379
|
+
};
|
|
380
|
+
},
|
|
381
|
+
endSecretOverlap: async (e) => {
|
|
382
|
+
let t = 0;
|
|
383
|
+
for (let r of await u.resolveTargets(e)) {
|
|
384
|
+
let [e] = await n.store.query({
|
|
385
|
+
table: "_voltro_webhook_targets",
|
|
386
|
+
predicate: _("id", r),
|
|
387
|
+
order: [],
|
|
388
|
+
take: 1,
|
|
389
|
+
skip: void 0,
|
|
390
|
+
projection: void 0
|
|
391
|
+
});
|
|
392
|
+
e?.previousSecret != null && (await n.store.update("_voltro_webhook_targets", r, {
|
|
393
|
+
previousSecret: null,
|
|
394
|
+
previousSecretUntil: null,
|
|
395
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
396
|
+
}), t += 1);
|
|
397
|
+
}
|
|
398
|
+
return { ended: t };
|
|
363
399
|
},
|
|
364
400
|
updateTarget: async (e, t) => {
|
|
365
|
-
if (t.url !== void 0 &&
|
|
401
|
+
if (t.url !== void 0 && E({
|
|
366
402
|
event: "x",
|
|
367
403
|
url: t.url
|
|
368
404
|
}), t.rateLimitPerMinute !== void 0 && t.rateLimitPerMinute !== null && (!Number.isInteger(t.rateLimitPerMinute) || t.rateLimitPerMinute < 1)) throw Error("updateTarget: rateLimitPerMinute must be a positive integer or null");
|
|
@@ -427,7 +463,7 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
427
463
|
skip: void 0,
|
|
428
464
|
projection: void 0
|
|
429
465
|
}), i = e?.since?.getTime();
|
|
430
|
-
return r.filter((e) => t === void 0 || t.has(String(e.targetId))).filter((t) => e?.status === void 0 || t.status === e.status).filter((e) => i === void 0 ||
|
|
466
|
+
return r.filter((e) => t === void 0 || t.has(String(e.targetId))).filter((t) => e?.status === void 0 || t.status === e.status).filter((e) => i === void 0 || O(e.createdAt) >= i).slice(0, e?.limit ?? 200).map(j);
|
|
431
467
|
},
|
|
432
468
|
getDelivery: async (e) => {
|
|
433
469
|
let t = (await n.store.query({
|
|
@@ -439,8 +475,8 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
439
475
|
projection: void 0
|
|
440
476
|
}))[0];
|
|
441
477
|
return t === void 0 ? null : {
|
|
442
|
-
...
|
|
443
|
-
payload:
|
|
478
|
+
...j(t),
|
|
479
|
+
payload: A(t.payload),
|
|
444
480
|
responseBody: t.responseBody ?? null
|
|
445
481
|
};
|
|
446
482
|
},
|
|
@@ -481,11 +517,10 @@ var y = class extends u.Service()("@voltro/webhooks/WebhooksService") {}, b = 32
|
|
|
481
517
|
}
|
|
482
518
|
};
|
|
483
519
|
return u;
|
|
484
|
-
},
|
|
485
|
-
return yield*
|
|
486
|
-
}),
|
|
520
|
+
}, W = d.gen(function* () {
|
|
521
|
+
return yield* b;
|
|
522
|
+
}), G = (e) => {
|
|
487
523
|
if (e.webhooks === void 0) throw Error("useWebhooks: `ctx.webhooks` is not set. Declare an outgoing event with a `webhook:` block in a *.event.ts file, or an incoming endpoint in a *.webhook.tsx file — the service is wired the moment the app has either.");
|
|
488
524
|
return e.webhooks;
|
|
489
525
|
};
|
|
490
|
-
|
|
491
|
-
export { y as WebhooksService, H as buildWebhooksService, j as compareVersions, C as eventsOf, S as generateSecret, M as matchesFilter, E as resolveSubscribe, W as useWebhooks, U as useWebhooksEffect, T as validateSubscribe };
|
|
526
|
+
export { y as MAX_SECRET_OVERLAP_SECONDS, b as WebhooksService, U as buildWebhooksService, M as compareVersions, w as eventsOf, C as generateSecret, N as matchesFilter, D as resolveSubscribe, G as useWebhooks, W as useWebhooksEffect, E as validateSubscribe };
|
package/dist/signing.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { standardWebhooksHeaders as e, verifyStandardWebhooks as t } from "./standardWebhooks.js";
|
|
2
2
|
import { createHmac as n, timingSafeEqual as r } from "node:crypto";
|
|
3
|
-
|
|
3
|
+
// src/signing.ts
|
|
4
4
|
var i = (e) => e === "hmacSha256" ? "sha256" : "sha1", a = (e, t, r, a = "hex") => {
|
|
5
5
|
let o = n(i(e), t);
|
|
6
6
|
return o.update(r), o.digest(a);
|
|
@@ -141,5 +141,4 @@ var s = (t, n) => {
|
|
|
141
141
|
encoding: "hex",
|
|
142
142
|
versionPrefix: "v1="
|
|
143
143
|
});
|
|
144
|
-
//#endregion
|
|
145
144
|
export { m as defaultOutgoingSignature, h as genericHmacSignature, d as githubSignature, s as signRequest, f as slackSignature, p as standardWebhooksSignature, u as stripeSignature, c as verifyRequest };
|
package/dist/standardWebhooks.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHmac as e, randomBytes as t, timingSafeEqual as n } from "node:crypto";
|
|
2
|
-
|
|
2
|
+
// src/standardWebhooks.ts
|
|
3
3
|
var r = "webhook-id", i = "webhook-timestamp", a = "webhook-signature", o = "v1", s = "whsec_", c = 24, l = 64, u = 300, d = () => `${s}${t(32).toString("base64")}`, f = (e) => {
|
|
4
4
|
if (!e.startsWith("whsec_")) throw Error(`standard-webhooks: the signing secret must be the spec's serialization — "${s}" + base64(24..64 random bytes). Mint one with generateStandardWebhooksSecret(). (A hex secret is also valid base64, so accepting it would sign with the wrong key bytes and every conformant consumer would reject the delivery.)`);
|
|
5
5
|
let t = Buffer.from(e.slice(6), "base64");
|
|
@@ -84,5 +84,4 @@ var r = "webhook-id", i = "webhook-timestamp", a = "webhook-signature", o = "v1"
|
|
|
84
84
|
reason: "signature mismatch"
|
|
85
85
|
};
|
|
86
86
|
};
|
|
87
|
-
//#endregion
|
|
88
87
|
export { u as STANDARD_WEBHOOKS_DEFAULT_TOLERANCE_SECONDS, r as STANDARD_WEBHOOKS_ID_HEADER, l as STANDARD_WEBHOOKS_MAX_KEY_BYTES, c as STANDARD_WEBHOOKS_MIN_KEY_BYTES, s as STANDARD_WEBHOOKS_SECRET_PREFIX, a as STANDARD_WEBHOOKS_SIGNATURE_HEADER, i as STANDARD_WEBHOOKS_TIMESTAMP_HEADER, o as STANDARD_WEBHOOKS_VERSION, d as generateStandardWebhooksSecret, p as isStandardWebhooksSecret, _ as standardWebhooksHeaders, f as standardWebhooksKey, g as standardWebhooksSignatureToken, h as standardWebhooksSignedContent, y as verifyStandardWebhooks };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/plugin-webhooks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.88.0",
|
|
4
4
|
"description": "Webhooks plugin — first-class outgoing (multi-target, durable-workflow delivery, HMAC signing, retry policies, rate limits) + incoming (signature verification, idempotency, provider templates for Stripe / GitHub / Slack / generic).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -48,15 +48,15 @@
|
|
|
48
48
|
"node": ">=24.0.0"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@voltro/database": "0.
|
|
52
|
-
"@voltro/integration-http": "0.
|
|
53
|
-
"@voltro/logger": "0.
|
|
54
|
-
"@voltro/plugin-multitenancy": "0.
|
|
55
|
-
"@voltro/protocol": "0.
|
|
56
|
-
"@voltro/runtime": "0.
|
|
51
|
+
"@voltro/database": "0.88.0",
|
|
52
|
+
"@voltro/integration-http": "0.88.0",
|
|
53
|
+
"@voltro/logger": "0.88.0",
|
|
54
|
+
"@voltro/plugin-multitenancy": "0.88.0",
|
|
55
|
+
"@voltro/protocol": "0.88.0",
|
|
56
|
+
"@voltro/runtime": "0.88.0"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"effect": "4.0
|
|
59
|
+
"effect": "4.1.0"
|
|
60
60
|
},
|
|
61
61
|
"publishConfig": {
|
|
62
62
|
"access": "public"
|