@hookflo/tern 2.2.10 → 3.0.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.
@@ -7,274 +7,307 @@ exports.getPlatformsUsingAlgorithm = getPlatformsUsingAlgorithm;
7
7
  exports.validateSignatureConfig = validateSignatureConfig;
8
8
  exports.platformAlgorithmConfigs = {
9
9
  github: {
10
- platform: "github",
10
+ platform: 'github',
11
11
  signatureConfig: {
12
- algorithm: "hmac-sha256",
13
- headerName: "x-hub-signature-256",
14
- headerFormat: "prefixed",
15
- prefix: "sha256=",
12
+ algorithm: 'hmac-sha256',
13
+ headerName: 'x-hub-signature-256',
14
+ headerFormat: 'prefixed',
15
+ prefix: 'sha256=',
16
16
  timestampHeader: undefined,
17
- payloadFormat: "raw",
17
+ payloadFormat: 'raw',
18
18
  },
19
- description: "GitHub webhooks use HMAC-SHA256 with sha256= prefix",
19
+ description: 'GitHub webhooks use HMAC-SHA256 with sha256= prefix',
20
20
  },
21
21
  stripe: {
22
- platform: "stripe",
22
+ platform: 'stripe',
23
23
  signatureConfig: {
24
- algorithm: "hmac-sha256",
25
- headerName: "stripe-signature",
26
- headerFormat: "comma-separated",
24
+ algorithm: 'hmac-sha256',
25
+ headerName: 'stripe-signature',
26
+ headerFormat: 'comma-separated',
27
27
  timestampHeader: undefined,
28
- payloadFormat: "timestamped",
28
+ payloadFormat: 'timestamped',
29
29
  customConfig: {
30
- signatureFormat: "t={timestamp},v1={signature}",
30
+ signatureFormat: 't={timestamp},v1={signature}',
31
31
  },
32
32
  },
33
- description: "Stripe webhooks use HMAC-SHA256 with comma-separated format",
33
+ description: 'Stripe webhooks use HMAC-SHA256 with comma-separated format',
34
34
  },
35
35
  clerk: {
36
- platform: "clerk",
36
+ platform: 'clerk',
37
37
  signatureConfig: {
38
- algorithm: "hmac-sha256",
39
- headerName: "svix-signature",
40
- headerFormat: "raw",
41
- timestampHeader: "svix-timestamp",
42
- timestampFormat: "unix",
43
- payloadFormat: "custom",
38
+ algorithm: 'hmac-sha256',
39
+ headerName: 'svix-signature',
40
+ headerFormat: 'raw',
41
+ timestampHeader: 'svix-timestamp',
42
+ timestampFormat: 'unix',
43
+ payloadFormat: 'custom',
44
44
  customConfig: {
45
- signatureFormat: "v1={signature}",
46
- payloadFormat: "{id}.{timestamp}.{body}",
47
- encoding: "base64",
48
- secretEncoding: "base64",
49
- idHeader: "svix-id",
45
+ signatureFormat: 'v1={signature}',
46
+ payloadFormat: '{id}.{timestamp}.{body}',
47
+ encoding: 'base64',
48
+ secretEncoding: 'base64',
49
+ idHeader: 'svix-id',
50
50
  },
51
51
  },
52
- description: "Clerk webhooks use HMAC-SHA256 with base64 encoding",
52
+ description: 'Clerk webhooks use HMAC-SHA256 with base64 encoding',
53
53
  },
54
54
  dodopayments: {
55
- platform: "dodopayments",
55
+ platform: 'dodopayments',
56
56
  signatureConfig: {
57
- algorithm: "hmac-sha256",
58
- headerName: "webhook-signature",
59
- headerFormat: "raw",
60
- timestampHeader: "webhook-timestamp",
61
- timestampFormat: "unix",
62
- payloadFormat: "custom",
57
+ algorithm: 'hmac-sha256',
58
+ headerName: 'webhook-signature',
59
+ headerFormat: 'raw',
60
+ timestampHeader: 'webhook-timestamp',
61
+ timestampFormat: 'unix',
62
+ payloadFormat: 'custom',
63
63
  customConfig: {
64
- signatureFormat: "v1={signature}",
65
- payloadFormat: "{id}.{timestamp}.{body}",
66
- encoding: "base64",
67
- secretEncoding: "base64",
68
- idHeader: "webhook-id",
64
+ signatureFormat: 'v1={signature}',
65
+ payloadFormat: '{id}.{timestamp}.{body}',
66
+ encoding: 'base64',
67
+ secretEncoding: 'base64',
68
+ idHeader: 'webhook-id',
69
69
  },
70
70
  },
71
- description: "Dodo Payments webhooks use HMAC-SHA256 with svix-style format (Standard Webhooks)",
71
+ description: 'Dodo Payments webhooks use HMAC-SHA256 with svix-style format (Standard Webhooks)',
72
72
  },
73
73
  shopify: {
74
- platform: "shopify",
74
+ platform: 'shopify',
75
75
  signatureConfig: {
76
- algorithm: "hmac-sha256",
77
- headerName: "x-shopify-hmac-sha256",
78
- headerFormat: "raw",
79
- payloadFormat: "raw",
76
+ algorithm: 'hmac-sha256',
77
+ headerName: 'x-shopify-hmac-sha256',
78
+ headerFormat: 'raw',
79
+ payloadFormat: 'raw',
80
80
  customConfig: {
81
- encoding: "base64",
82
- secretEncoding: "utf8",
81
+ encoding: 'base64',
82
+ secretEncoding: 'utf8',
83
83
  },
84
84
  },
85
- description: "Shopify webhooks use HMAC-SHA256 with base64 encoded signature",
85
+ description: 'Shopify webhooks use HMAC-SHA256 with base64 encoded signature',
86
86
  },
87
87
  vercel: {
88
- platform: "vercel",
88
+ platform: 'vercel',
89
89
  signatureConfig: {
90
- algorithm: "hmac-sha256",
91
- headerName: "x-vercel-signature",
92
- headerFormat: "raw",
93
- timestampHeader: "x-vercel-timestamp",
94
- timestampFormat: "unix",
95
- payloadFormat: "raw",
90
+ algorithm: 'hmac-sha256',
91
+ headerName: 'x-vercel-signature',
92
+ headerFormat: 'raw',
93
+ timestampHeader: 'x-vercel-timestamp',
94
+ timestampFormat: 'unix',
95
+ payloadFormat: 'raw',
96
96
  },
97
- description: "Vercel webhooks use HMAC-SHA256",
97
+ description: 'Vercel webhooks use HMAC-SHA256',
98
98
  },
99
99
  polar: {
100
- platform: "polar",
100
+ platform: 'polar',
101
101
  signatureConfig: {
102
- algorithm: "hmac-sha256",
103
- headerName: "webhook-signature",
104
- headerFormat: "raw",
105
- timestampHeader: "webhook-timestamp",
106
- timestampFormat: "unix",
107
- payloadFormat: "custom",
102
+ algorithm: 'hmac-sha256',
103
+ headerName: 'webhook-signature',
104
+ headerFormat: 'raw',
105
+ timestampHeader: 'webhook-timestamp',
106
+ timestampFormat: 'unix',
107
+ payloadFormat: 'custom',
108
108
  customConfig: {
109
- signatureFormat: "v1={signature}",
110
- payloadFormat: "{id}.{timestamp}.{body}",
111
- encoding: "base64",
112
- secretEncoding: "utf8",
113
- idHeader: "webhook-id",
109
+ signatureFormat: 'v1={signature}',
110
+ payloadFormat: '{id}.{timestamp}.{body}',
111
+ encoding: 'base64',
112
+ secretEncoding: 'base64',
113
+ idHeader: 'webhook-id',
114
114
  },
115
115
  },
116
- description: "Polar webhooks use HMAC-SHA256 with Standard Webhooks format",
117
- },
118
- supabase: {
119
- platform: "supabase",
120
- signatureConfig: {
121
- algorithm: "custom",
122
- headerName: "x-supabase-token",
123
- headerFormat: "raw",
124
- payloadFormat: "raw",
125
- customConfig: {
126
- type: "token-based",
127
- idHeader: "x-supabase-token",
128
- },
129
- },
130
- description: "Supabase webhooks use token-based authentication",
116
+ description: 'Polar webhooks use HMAC-SHA256 with Standard Webhooks format',
131
117
  },
132
118
  gitlab: {
133
- platform: "gitlab",
119
+ platform: 'gitlab',
134
120
  signatureConfig: {
135
- algorithm: "custom",
136
- headerName: "X-Gitlab-Token",
137
- headerFormat: "raw",
138
- payloadFormat: "raw",
121
+ algorithm: 'custom',
122
+ headerName: 'X-Gitlab-Token',
123
+ headerFormat: 'raw',
124
+ payloadFormat: 'raw',
139
125
  customConfig: {
140
- type: "token-based",
141
- idHeader: "X-Gitlab-Token",
126
+ type: 'token-based',
127
+ idHeader: 'X-Gitlab-Token',
142
128
  },
143
129
  },
144
- description: "GitLab webhooks use HMAC-SHA256 with X-Gitlab-Token header",
130
+ description: 'GitLab webhooks use token-based authentication via X-Gitlab-Token header',
145
131
  },
146
132
  paddle: {
147
- platform: "paddle",
133
+ platform: 'paddle',
148
134
  signatureConfig: {
149
- algorithm: "hmac-sha256",
150
- headerName: "paddle-signature",
151
- headerFormat: "comma-separated",
152
- payloadFormat: "custom",
135
+ algorithm: 'hmac-sha256',
136
+ headerName: 'paddle-signature',
137
+ headerFormat: 'comma-separated',
138
+ payloadFormat: 'custom',
153
139
  customConfig: {
154
- timestampKey: "ts",
155
- signatureKey: "h1",
156
- payloadFormat: "{timestamp}:{body}",
140
+ timestampKey: 'ts',
141
+ signatureKey: 'h1',
142
+ payloadFormat: '{timestamp}:{body}',
157
143
  },
158
144
  },
159
- description: "Paddle webhooks use HMAC-SHA256 with Paddle-Signature (ts/h1) header format",
145
+ description: 'Paddle webhooks use HMAC-SHA256 with Paddle-Signature (ts/h1) header format',
160
146
  },
161
147
  razorpay: {
162
- platform: "razorpay",
148
+ platform: 'razorpay',
163
149
  signatureConfig: {
164
- algorithm: "hmac-sha256",
165
- headerName: "x-razorpay-signature",
166
- headerFormat: "raw",
167
- payloadFormat: "raw",
150
+ algorithm: 'hmac-sha256',
151
+ headerName: 'x-razorpay-signature',
152
+ headerFormat: 'raw',
153
+ payloadFormat: 'raw',
168
154
  },
169
- description: "Razorpay webhooks use HMAC-SHA256 with X-Razorpay-Signature header",
155
+ description: 'Razorpay webhooks use HMAC-SHA256 with X-Razorpay-Signature header',
170
156
  },
171
157
  lemonsqueezy: {
172
- platform: "lemonsqueezy",
158
+ platform: 'lemonsqueezy',
173
159
  signatureConfig: {
174
- algorithm: "hmac-sha256",
175
- headerName: "x-signature",
176
- headerFormat: "raw",
177
- payloadFormat: "raw",
160
+ algorithm: 'hmac-sha256',
161
+ headerName: 'x-signature',
162
+ headerFormat: 'raw',
163
+ payloadFormat: 'raw',
178
164
  },
179
- description: "Lemon Squeezy webhooks use HMAC-SHA256 with X-Signature header",
180
- },
181
- auth0: {
182
- platform: "auth0",
183
- signatureConfig: {
184
- algorithm: "hmac-sha256",
185
- headerName: "x-auth0-signature",
186
- headerFormat: "raw",
187
- payloadFormat: "raw",
188
- },
189
- description: "Auth0 webhooks use HMAC-SHA256 with X-Auth0-Signature header",
165
+ description: 'Lemon Squeezy webhooks use HMAC-SHA256 with X-Signature header',
190
166
  },
191
167
  workos: {
192
- platform: "workos",
168
+ platform: 'workos',
193
169
  signatureConfig: {
194
- algorithm: "hmac-sha256",
195
- headerName: "workos-signature",
196
- headerFormat: "comma-separated",
197
- payloadFormat: "custom",
170
+ algorithm: 'hmac-sha256',
171
+ headerName: 'workos-signature',
172
+ headerFormat: 'comma-separated',
173
+ payloadFormat: 'custom',
198
174
  customConfig: {
199
- timestampKey: "t",
200
- signatureKey: "v1",
201
- payloadFormat: "{timestamp}.{body}",
175
+ timestampKey: 't',
176
+ signatureKey: 'v1',
177
+ payloadFormat: '{timestamp}.{body}',
202
178
  },
203
179
  },
204
- description: "WorkOS webhooks use HMAC-SHA256 with WorkOS-Signature (t/v1) format",
180
+ description: 'WorkOS webhooks use HMAC-SHA256 with WorkOS-Signature (t/v1) format',
205
181
  },
206
182
  woocommerce: {
207
- platform: "woocommerce",
183
+ platform: 'woocommerce',
208
184
  signatureConfig: {
209
- algorithm: "hmac-sha256",
210
- headerName: "x-wc-webhook-signature",
211
- headerFormat: "raw",
212
- payloadFormat: "raw",
185
+ algorithm: 'hmac-sha256',
186
+ headerName: 'x-wc-webhook-signature',
187
+ headerFormat: 'raw',
188
+ payloadFormat: 'raw',
213
189
  customConfig: {
214
- encoding: "base64",
215
- secretEncoding: "utf8",
190
+ encoding: 'base64',
191
+ secretEncoding: 'utf8',
216
192
  },
217
193
  },
218
- description: "WooCommerce webhooks use HMAC-SHA256 with base64 encoded signature",
194
+ description: 'WooCommerce webhooks use HMAC-SHA256 with base64 encoded signature',
219
195
  },
220
196
  replicateai: {
221
- platform: "replicateai",
197
+ platform: 'replicateai',
222
198
  signatureConfig: {
223
- algorithm: "hmac-sha256",
224
- headerName: "webhook-signature",
225
- headerFormat: "raw",
226
- timestampHeader: "webhook-timestamp",
227
- timestampFormat: "unix",
228
- payloadFormat: "custom",
199
+ algorithm: 'hmac-sha256',
200
+ headerName: 'webhook-signature',
201
+ headerFormat: 'raw',
202
+ timestampHeader: 'webhook-timestamp',
203
+ timestampFormat: 'unix',
204
+ payloadFormat: 'custom',
229
205
  customConfig: {
230
- signatureFormat: "v1={signature}",
231
- payloadFormat: "{id}.{timestamp}.{body}",
232
- encoding: "base64",
233
- secretEncoding: "base64",
234
- idHeader: "webhook-id",
206
+ signatureFormat: 'v1={signature}',
207
+ payloadFormat: '{id}.{timestamp}.{body}',
208
+ encoding: 'base64',
209
+ secretEncoding: 'base64',
210
+ idHeader: 'webhook-id',
235
211
  },
236
212
  },
237
- description: "Replicate webhooks use HMAC-SHA256 with Standard Webhooks (svix-style) format",
213
+ description: 'Replicate webhooks use HMAC-SHA256 with Standard Webhooks (svix-style) format',
238
214
  },
239
215
  falai: {
240
- platform: "falai",
216
+ platform: 'falai',
217
+ signatureConfig: {
218
+ algorithm: 'ed25519',
219
+ headerName: 'x-fal-webhook-signature',
220
+ headerFormat: 'raw',
221
+ payloadFormat: 'custom',
222
+ customConfig: {
223
+ requestIdHeader: 'x-fal-webhook-request-id',
224
+ userIdHeader: 'x-fal-webhook-user-id',
225
+ timestampHeader: 'x-fal-webhook-timestamp',
226
+ jwksUrl: 'https://rest.alpha.fal.ai/.well-known/jwks.json',
227
+ },
228
+ },
229
+ description: 'fal.ai webhooks use ED25519 with JWKS key verification. No secret required — pass empty string.',
230
+ },
231
+ sentry: {
232
+ platform: 'sentry',
233
+ signatureConfig: {
234
+ algorithm: 'hmac-sha256',
235
+ headerName: 'sentry-hook-signature',
236
+ headerFormat: 'raw',
237
+ timestampHeader: 'sentry-hook-timestamp',
238
+ timestampFormat: 'unix',
239
+ payloadFormat: 'json-stringified',
240
+ idHeader: 'request-id',
241
+ customConfig: {
242
+ issueAlertPayloadPath: 'data.issue_alert',
243
+ },
244
+ },
245
+ description: 'Sentry webhooks use HMAC-SHA256 with JSON stringified body and Request-ID idempotency key',
246
+ },
247
+ grafana: {
248
+ platform: 'grafana',
249
+ signatureConfig: {
250
+ algorithm: 'hmac-sha256',
251
+ headerName: 'x-grafana-alerting-signature',
252
+ headerFormat: 'raw',
253
+ timestampHeader: 'x-grafana-alerting-timestamp',
254
+ timestampFormat: 'unix',
255
+ payloadFormat: 'timestamped',
256
+ },
257
+ description: 'Grafana 12+ webhooks support HMAC-SHA256 with optional timestamped payload format',
258
+ },
259
+ doppler: {
260
+ platform: 'doppler',
261
+ signatureConfig: {
262
+ algorithm: 'hmac-sha256',
263
+ headerName: 'x-doppler-signature',
264
+ headerFormat: 'prefixed',
265
+ prefix: 'sha256=',
266
+ payloadFormat: 'raw',
267
+ customConfig: {
268
+ dedupHashAlgorithm: 'sha256',
269
+ },
270
+ },
271
+ description: 'Doppler webhooks use HMAC-SHA256 with sha256= signature prefix and raw payload signing',
272
+ },
273
+ sanity: {
274
+ platform: 'sanity',
241
275
  signatureConfig: {
242
- algorithm: "ed25519",
243
- headerName: "x-fal-webhook-signature",
244
- headerFormat: "raw",
245
- payloadFormat: "custom",
276
+ algorithm: 'hmac-sha256',
277
+ headerName: 'sanity-webhook-signature',
278
+ headerFormat: 'comma-separated',
279
+ payloadFormat: 'timestamped',
246
280
  customConfig: {
247
- requestIdHeader: "x-fal-webhook-request-id",
248
- userIdHeader: "x-fal-webhook-user-id",
249
- timestampHeader: "x-fal-webhook-timestamp",
250
- jwksUrl: "https://rest.alpha.fal.ai/.well-known/jwks.json",
281
+ timestampKey: 't',
282
+ signatureKey: 'v1',
251
283
  },
284
+ idHeader: 'idempotency-key',
252
285
  },
253
- description: "fal.ai webhooks use ED25519 with JWKS key verification. No secret required — pass empty string.",
286
+ description: 'Sanity webhooks use Stripe-compatible signatures with timestamp/body payload and idempotency key header',
254
287
  },
255
288
  custom: {
256
- platform: "custom",
289
+ platform: 'custom',
257
290
  signatureConfig: {
258
- algorithm: "hmac-sha256",
259
- headerName: "x-webhook-token",
260
- headerFormat: "raw",
261
- payloadFormat: "raw",
291
+ algorithm: 'hmac-sha256',
292
+ headerName: 'x-webhook-signature',
293
+ headerFormat: 'raw',
294
+ payloadFormat: 'raw',
262
295
  customConfig: {
263
- type: "token-based",
264
- idHeader: "x-webhook-id",
296
+ type: 'token-based',
297
+ idHeader: 'x-webhook-id',
265
298
  },
266
299
  },
267
- description: "Custom webhook configuration",
300
+ description: 'Custom webhook configuration (supports token-based overrides via customConfig)',
268
301
  },
269
302
  unknown: {
270
- platform: "unknown",
303
+ platform: 'unknown',
271
304
  signatureConfig: {
272
- algorithm: "hmac-sha256",
273
- headerName: "x-webhook-signature",
274
- headerFormat: "raw",
275
- payloadFormat: "raw",
305
+ algorithm: 'hmac-sha256',
306
+ headerName: 'x-webhook-signature',
307
+ headerFormat: 'raw',
308
+ payloadFormat: 'raw',
276
309
  },
277
- description: "Unknown platform - using default HMAC-SHA256",
310
+ description: 'Unknown platform - using default HMAC-SHA256',
278
311
  },
279
312
  };
280
313
  function getPlatformAlgorithmConfig(platform) {
@@ -286,23 +319,23 @@ function platformUsesAlgorithm(platform, algorithm) {
286
319
  }
287
320
  function getPlatformsUsingAlgorithm(algorithm) {
288
321
  return Object.entries(exports.platformAlgorithmConfigs)
289
- .filter(([_, config]) => config.signatureConfig.algorithm === algorithm)
290
- .map(([platform, _]) => platform);
322
+ .filter(([, config]) => config.signatureConfig.algorithm === algorithm)
323
+ .map(([platform]) => platform);
291
324
  }
292
325
  function validateSignatureConfig(config) {
293
326
  if (!config.algorithm || !config.headerName) {
294
327
  return false;
295
328
  }
296
329
  switch (config.algorithm) {
297
- case "hmac-sha256":
298
- case "hmac-sha1":
299
- case "hmac-sha512":
330
+ case 'hmac-sha256':
331
+ case 'hmac-sha1':
332
+ case 'hmac-sha512':
300
333
  return true;
301
- case "rsa-sha256":
334
+ case 'rsa-sha256':
302
335
  return !!config.customConfig?.publicKey;
303
- case "ed25519":
336
+ case 'ed25519':
304
337
  return !!config.customConfig?.publicKey || !!config.customConfig?.jwksUrl;
305
- case "custom":
338
+ case 'custom':
306
339
  return !!config.customConfig;
307
340
  default:
308
341
  return false;