@voltro/plugin-webhooks 0.29.0 → 0.30.1
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 +448 -0
- package/dist/index.d.ts +170 -16
- package/dist/index.js +148 -109
- package/dist/mixin.d.ts +79 -2
- package/dist/mixin.js +11 -3
- package/dist/providers/index.d.ts +2 -6
- package/package.json +7 -7
package/dist/mixin.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export declare const _voltroWebhookDeliveriesTable: Table<"_voltro_webhook_deliv
|
|
|
32
32
|
readonly eventId: ColumnBuilder<string | null, "text", boolean>;
|
|
33
33
|
/** Attempt counter (1-indexed). */
|
|
34
34
|
readonly attempt: ColumnBuilder<number, "integer", boolean>;
|
|
35
|
-
readonly status: ColumnBuilder<"failed" | "succeeded" | "
|
|
35
|
+
readonly status: ColumnBuilder<"failed" | "succeeded" | "inFlight" | "pending" | "retryScheduled", "text", boolean>;
|
|
36
36
|
/** Payload as sent over the wire. Stored verbatim — re-rendering
|
|
37
37
|
* from a referenced event row would lose the snapshot if the
|
|
38
38
|
* source event was deleted. */
|
|
@@ -67,6 +67,60 @@ export declare const _voltroWebhookDeliveriesTable: Table<"_voltro_webhook_deliv
|
|
|
67
67
|
readonly updatedBy: ColumnDefinition<string | null, "reference", boolean>;
|
|
68
68
|
}, true, never>;
|
|
69
69
|
|
|
70
|
+
/**
|
|
71
|
+
* ONE row per declared event, stamped every time `emit` runs.
|
|
72
|
+
*
|
|
73
|
+
* **Why this is not derivable from `_voltro_webhook_deliveries`, which is the
|
|
74
|
+
* whole reason the table exists.** A delivery row is written when an emit MATCHES
|
|
75
|
+
* a target. So "no delivery rows" conflates three different facts:
|
|
76
|
+
*
|
|
77
|
+
* 1. no `emit(...)` call site exists, or none ever ran ← the defect
|
|
78
|
+
* 2. it ran, but nobody was subscribed yet
|
|
79
|
+
* 3. it ran, but every target's `filter` excluded the payload, or every
|
|
80
|
+
* target was paused
|
|
81
|
+
*
|
|
82
|
+
* Only (1) is a bug, and it is the one a consumer spent a week finding by hand:
|
|
83
|
+
* seven of eleven advertised events had no emit call site anywhere. Reading (2)
|
|
84
|
+
* or (3) as (1) turns a working integration into a false alarm; reading (1) as
|
|
85
|
+
* (2) hides it. Delivery history also ages out — `_voltro_webhook_deliveries`
|
|
86
|
+
* carries a 90-day retention — so an event emitted correctly and quietly can
|
|
87
|
+
* decay into looking dead.
|
|
88
|
+
*
|
|
89
|
+
* This row is written REGARDLESS of whether any target matched, which is
|
|
90
|
+
* precisely the axis history cannot see. The dashboard shows both, labelled,
|
|
91
|
+
* and their disagreement is itself the useful signal: emitted but never
|
|
92
|
+
* delivered means every target is paused, filtered out, or failing.
|
|
93
|
+
*
|
|
94
|
+
* Deliberately NOT tenant-scoped. The question is "does this event have a live
|
|
95
|
+
* call site in this deployment", which is a property of the CODE, not of a
|
|
96
|
+
* tenant's data — and scoping it per tenant would make an event look dead for
|
|
97
|
+
* every tenant that has not happened to trigger it yet.
|
|
98
|
+
*/
|
|
99
|
+
export declare const _voltroWebhookEventStatsTable: Table<"_voltro_webhook_event_stats", FieldDefinitions<{
|
|
100
|
+
/**
|
|
101
|
+
* A GENERATED id. The event name is the natural key and it is deliberately
|
|
102
|
+
* NOT reused here.
|
|
103
|
+
*
|
|
104
|
+
* An `id()` column is `VARCHAR(64)` on MySQL/MariaDB (`applier.ts`), while an
|
|
105
|
+
* event name is allowed 191. Using the name as the id would make a namespaced
|
|
106
|
+
* event longer than 64 characters fail its insert — and because the stats
|
|
107
|
+
* write is best-effort and swallows every error, it would fail SILENTLY and
|
|
108
|
+
* the dashboard would report "never emitted" for a live event. That is
|
|
109
|
+
* precisely the false positive this table exists to remove, reintroduced by
|
|
110
|
+
* its own primary key, on exactly the dialect that reported the original
|
|
111
|
+
* defect.
|
|
112
|
+
*/
|
|
113
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
114
|
+
/** The natural key. Unique, so a concurrent double-insert loses rather than
|
|
115
|
+
* duplicating the row. */
|
|
116
|
+
readonly event: ColumnBuilder<string, "text", boolean>;
|
|
117
|
+
/** Total emits seen, including those that matched no target. */
|
|
118
|
+
readonly emitCount: ColumnBuilder<number, "integer", true>;
|
|
119
|
+
readonly lastEmitAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
120
|
+
readonly createdAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
121
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
122
|
+
}>, true, never>;
|
|
123
|
+
|
|
70
124
|
/**
|
|
71
125
|
* Fixed-window rate-limit counters — one row per (scope, minute
|
|
72
126
|
* bucket), where scope is `target:<targetId>` (per-target
|
|
@@ -330,7 +384,7 @@ export declare const webhookTables: () => readonly [ Table<"_voltro_webhook_targ
|
|
|
330
384
|
readonly eventId: ColumnBuilder<string | null, "text", boolean>;
|
|
331
385
|
/** Attempt counter (1-indexed). */
|
|
332
386
|
readonly attempt: ColumnBuilder<number, "integer", boolean>;
|
|
333
|
-
readonly status: ColumnBuilder<"failed" | "succeeded" | "
|
|
387
|
+
readonly status: ColumnBuilder<"failed" | "succeeded" | "inFlight" | "pending" | "retryScheduled", "text", boolean>;
|
|
334
388
|
/** Payload as sent over the wire. Stored verbatim — re-rendering
|
|
335
389
|
* from a referenced event row would lose the snapshot if the
|
|
336
390
|
* source event was deleted. */
|
|
@@ -376,6 +430,29 @@ export declare const webhookTables: () => readonly [ Table<"_voltro_webhook_targ
|
|
|
376
430
|
readonly count: ColumnBuilder<number, "integer", true>;
|
|
377
431
|
readonly createdAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
378
432
|
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
433
|
+
}>, true, never>, Table<"_voltro_webhook_event_stats", FieldDefinitions<{
|
|
434
|
+
/**
|
|
435
|
+
* A GENERATED id. The event name is the natural key and it is deliberately
|
|
436
|
+
* NOT reused here.
|
|
437
|
+
*
|
|
438
|
+
* An `id()` column is `VARCHAR(64)` on MySQL/MariaDB (`applier.ts`), while an
|
|
439
|
+
* event name is allowed 191. Using the name as the id would make a namespaced
|
|
440
|
+
* event longer than 64 characters fail its insert — and because the stats
|
|
441
|
+
* write is best-effort and swallows every error, it would fail SILENTLY and
|
|
442
|
+
* the dashboard would report "never emitted" for a live event. That is
|
|
443
|
+
* precisely the false positive this table exists to remove, reintroduced by
|
|
444
|
+
* its own primary key, on exactly the dialect that reported the original
|
|
445
|
+
* defect.
|
|
446
|
+
*/
|
|
447
|
+
readonly id: ColumnBuilder<string, "id", boolean>;
|
|
448
|
+
/** The natural key. Unique, so a concurrent double-insert loses rather than
|
|
449
|
+
* duplicating the row. */
|
|
450
|
+
readonly event: ColumnBuilder<string, "text", boolean>;
|
|
451
|
+
/** Total emits seen, including those that matched no target. */
|
|
452
|
+
readonly emitCount: ColumnBuilder<number, "integer", true>;
|
|
453
|
+
readonly lastEmitAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
454
|
+
readonly createdAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
455
|
+
readonly updatedAt: ColumnBuilder<Date, "timestamp", boolean>;
|
|
379
456
|
}>, true, never>];
|
|
380
457
|
|
|
381
458
|
export { }
|
package/dist/mixin.js
CHANGED
|
@@ -52,7 +52,14 @@ var u = o("_voltro_webhook_targets", {
|
|
|
52
52
|
count: n().default(0),
|
|
53
53
|
createdAt: c(),
|
|
54
54
|
updatedAt: c()
|
|
55
|
-
}), p = (
|
|
55
|
+
}), p = o("_voltro_webhook_event_stats", {
|
|
56
|
+
id: t({ prefix: "whstat" }),
|
|
57
|
+
event: s().maxLength(191).unique(),
|
|
58
|
+
emitCount: n().default(0),
|
|
59
|
+
lastEmitAt: c(),
|
|
60
|
+
createdAt: c(),
|
|
61
|
+
updatedAt: c()
|
|
62
|
+
}), m = () => (i({
|
|
56
63
|
table: "_voltro_webhook_deliveries",
|
|
57
64
|
timeColumn: "createdAt",
|
|
58
65
|
ttlMs: a(process.env.VOLTRO_WEBHOOK_DELIVERIES_TTL_HOURS, 2160)
|
|
@@ -63,7 +70,8 @@ var u = o("_voltro_webhook_targets", {
|
|
|
63
70
|
}), [
|
|
64
71
|
u,
|
|
65
72
|
d,
|
|
66
|
-
f
|
|
73
|
+
f,
|
|
74
|
+
p
|
|
67
75
|
]);
|
|
68
76
|
//#endregion
|
|
69
|
-
export { d as _voltroWebhookDeliveriesTable, f as _voltroWebhookRateWindowsTable, u as _voltroWebhookTargetsTable,
|
|
77
|
+
export { d as _voltroWebhookDeliveriesTable, p as _voltroWebhookEventStatsTable, f as _voltroWebhookRateWindowsTable, u as _voltroWebhookTargetsTable, m as webhookTables };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Schema } from 'effect';
|
|
2
|
+
import { WorkflowRunHandle } from '@voltro/protocol';
|
|
2
3
|
|
|
3
4
|
declare interface CustomSignatureScheme {
|
|
4
5
|
readonly _tag: 'custom';
|
|
@@ -106,12 +107,7 @@ declare interface IncomingWebhookDescriptor<Body> {
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
declare interface IncomingWorkflowFacade {
|
|
109
|
-
start<Payload = unknown>(workflowName: string, payload: Payload): Promise<
|
|
110
|
-
readonly id: string;
|
|
111
|
-
readonly workflowName: string;
|
|
112
|
-
readonly executionId: string;
|
|
113
|
-
readonly status: 'running';
|
|
114
|
-
}>;
|
|
110
|
+
start<Payload = unknown>(workflowName: string, payload: Payload): Promise<WorkflowRunHandle>;
|
|
115
111
|
signal(target: {
|
|
116
112
|
readonly id?: string;
|
|
117
113
|
readonly executionId?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/plugin-webhooks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.1",
|
|
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,12 +48,12 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@effect/workflow": "^0.19.0",
|
|
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.30.1",
|
|
52
|
+
"@voltro/integration-http": "0.30.1",
|
|
53
|
+
"@voltro/logger": "0.30.1",
|
|
54
|
+
"@voltro/plugin-multitenancy": "0.30.1",
|
|
55
|
+
"@voltro/protocol": "0.30.1",
|
|
56
|
+
"@voltro/runtime": "0.30.1"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"effect": "^3.22.0"
|