hooklatch 0.0.0-stage → 1.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.
Files changed (301) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +438 -2
  3. package/dist/adapters/cloudflare.d.ts +11 -0
  4. package/dist/adapters/cloudflare.d.ts.map +1 -0
  5. package/dist/adapters/cloudflare.js +27 -0
  6. package/dist/adapters/cloudflare.js.map +1 -0
  7. package/dist/adapters/express.d.ts +9 -0
  8. package/dist/adapters/express.d.ts.map +1 -0
  9. package/dist/adapters/express.js +63 -0
  10. package/dist/adapters/express.js.map +1 -0
  11. package/dist/adapters/hono.d.ts +12 -0
  12. package/dist/adapters/hono.d.ts.map +1 -0
  13. package/dist/adapters/hono.js +28 -0
  14. package/dist/adapters/hono.js.map +1 -0
  15. package/dist/adapters/nextjs.d.ts +6 -0
  16. package/dist/adapters/nextjs.d.ts.map +1 -0
  17. package/dist/adapters/nextjs.js +56 -0
  18. package/dist/adapters/nextjs.js.map +1 -0
  19. package/dist/adapters/shared.d.ts +8 -0
  20. package/dist/adapters/shared.d.ts.map +1 -0
  21. package/dist/adapters/shared.js +53 -0
  22. package/dist/adapters/shared.js.map +1 -0
  23. package/dist/cjs/adapters/cloudflare.cjs +29 -0
  24. package/dist/cjs/adapters/cloudflare.d.cts +10 -0
  25. package/dist/cjs/adapters/express.cjs +65 -0
  26. package/dist/cjs/adapters/express.d.cts +8 -0
  27. package/dist/cjs/adapters/hono.cjs +30 -0
  28. package/dist/cjs/adapters/hono.d.cts +11 -0
  29. package/dist/cjs/adapters/nextjs.cjs +58 -0
  30. package/dist/cjs/adapters/nextjs.d.cts +5 -0
  31. package/dist/cjs/adapters/shared.cjs +58 -0
  32. package/dist/cjs/adapters/shared.d.cts +7 -0
  33. package/dist/cjs/core.cjs +30 -0
  34. package/dist/cjs/core.d.cts +5 -0
  35. package/dist/cjs/diagnostics/catalog.cjs +341 -0
  36. package/dist/cjs/diagnostics/catalog.d.cts +19 -0
  37. package/dist/cjs/diagnostics/index.cjs +90 -0
  38. package/dist/cjs/diagnostics/index.d.cts +5 -0
  39. package/dist/cjs/diagnostics/types.cjs +2 -0
  40. package/dist/cjs/diagnostics/types.d.cts +20 -0
  41. package/dist/cjs/errors.cjs +13 -0
  42. package/dist/cjs/errors.d.cts +6 -0
  43. package/dist/cjs/index.cjs +9 -0
  44. package/dist/cjs/index.d.cts +3 -0
  45. package/dist/cjs/internal/body.cjs +50 -0
  46. package/dist/cjs/internal/body.d.cts +2 -0
  47. package/dist/cjs/internal/bytes.cjs +43 -0
  48. package/dist/cjs/internal/bytes.d.cts +4 -0
  49. package/dist/cjs/internal/crypto.cjs +52 -0
  50. package/dist/cjs/internal/crypto.d.cts +3 -0
  51. package/dist/cjs/internal/headers.cjs +72 -0
  52. package/dist/cjs/internal/headers.d.cts +2 -0
  53. package/dist/cjs/internal/options.cjs +130 -0
  54. package/dist/cjs/internal/options.d.cts +7 -0
  55. package/dist/cjs/internal/prepare.cjs +11 -0
  56. package/dist/cjs/internal/prepare.d.cts +4 -0
  57. package/dist/cjs/internal/provider-options.cjs +72 -0
  58. package/dist/cjs/internal/provider-options.d.cts +6 -0
  59. package/dist/cjs/internal/provider.cjs +2 -0
  60. package/dist/cjs/internal/provider.d.cts +39 -0
  61. package/dist/cjs/internal/verification.cjs +71 -0
  62. package/dist/cjs/internal/verification.d.cts +12 -0
  63. package/dist/cjs/providers/clerk.cjs +15 -0
  64. package/dist/cjs/providers/clerk.d.cts +9 -0
  65. package/dist/cjs/providers/dodo-payments.cjs +26 -0
  66. package/dist/cjs/providers/dodo-payments.d.cts +20 -0
  67. package/dist/cjs/providers/doppler.cjs +71 -0
  68. package/dist/cjs/providers/doppler.d.cts +37 -0
  69. package/dist/cjs/providers/fal.cjs +80 -0
  70. package/dist/cjs/providers/fal.d.cts +13 -0
  71. package/dist/cjs/providers/github.cjs +52 -0
  72. package/dist/cjs/providers/github.d.cts +7 -0
  73. package/dist/cjs/providers/gitlab.cjs +26 -0
  74. package/dist/cjs/providers/gitlab.d.cts +20 -0
  75. package/dist/cjs/providers/grafana.cjs +180 -0
  76. package/dist/cjs/providers/grafana.d.cts +35 -0
  77. package/dist/cjs/providers/index.cjs +110 -0
  78. package/dist/cjs/providers/index.d.cts +26 -0
  79. package/dist/cjs/providers/lemon-squeezy.cjs +36 -0
  80. package/dist/cjs/providers/lemon-squeezy.d.cts +15 -0
  81. package/dist/cjs/providers/linear.cjs +58 -0
  82. package/dist/cjs/providers/linear.d.cts +36 -0
  83. package/dist/cjs/providers/paddle.cjs +105 -0
  84. package/dist/cjs/providers/paddle.d.cts +14 -0
  85. package/dist/cjs/providers/polar.cjs +80 -0
  86. package/dist/cjs/providers/polar.d.cts +25 -0
  87. package/dist/cjs/providers/razorpay.cjs +43 -0
  88. package/dist/cjs/providers/razorpay.d.cts +19 -0
  89. package/dist/cjs/providers/replicate.cjs +25 -0
  90. package/dist/cjs/providers/replicate.d.cts +19 -0
  91. package/dist/cjs/providers/sanity.cjs +161 -0
  92. package/dist/cjs/providers/sanity.d.cts +38 -0
  93. package/dist/cjs/providers/sentry.cjs +47 -0
  94. package/dist/cjs/providers/sentry.d.cts +25 -0
  95. package/dist/cjs/providers/shared.cjs +49 -0
  96. package/dist/cjs/providers/shared.d.cts +14 -0
  97. package/dist/cjs/providers/shopify.cjs +40 -0
  98. package/dist/cjs/providers/shopify.d.cts +8 -0
  99. package/dist/cjs/providers/standard-webhooks-protocol.cjs +97 -0
  100. package/dist/cjs/providers/standard-webhooks-protocol.d.cts +14 -0
  101. package/dist/cjs/providers/standard-webhooks.cjs +15 -0
  102. package/dist/cjs/providers/standard-webhooks.d.cts +9 -0
  103. package/dist/cjs/providers/stripe.cjs +81 -0
  104. package/dist/cjs/providers/stripe.d.cts +7 -0
  105. package/dist/cjs/providers/svix.cjs +63 -0
  106. package/dist/cjs/providers/svix.d.cts +9 -0
  107. package/dist/cjs/providers/vercel.cjs +39 -0
  108. package/dist/cjs/providers/vercel.d.cts +15 -0
  109. package/dist/cjs/providers/workos.cjs +120 -0
  110. package/dist/cjs/providers/workos.d.cts +32 -0
  111. package/dist/cjs/types.cjs +2 -0
  112. package/dist/cjs/types.d.cts +68 -0
  113. package/dist/cli/args.d.ts +86 -0
  114. package/dist/cli/args.d.ts.map +1 -0
  115. package/dist/cli/args.js +358 -0
  116. package/dist/cli/args.js.map +1 -0
  117. package/dist/cli/filesystem.d.ts +15 -0
  118. package/dist/cli/filesystem.d.ts.map +1 -0
  119. package/dist/cli/filesystem.js +170 -0
  120. package/dist/cli/filesystem.js.map +1 -0
  121. package/dist/cli/index.d.ts +3 -0
  122. package/dist/cli/index.d.ts.map +1 -0
  123. package/dist/cli/index.js +64 -0
  124. package/dist/cli/index.js.map +1 -0
  125. package/dist/cli/templates.d.ts +13 -0
  126. package/dist/cli/templates.d.ts.map +1 -0
  127. package/dist/cli/templates.js +297 -0
  128. package/dist/cli/templates.js.map +1 -0
  129. package/dist/core.d.ts +6 -0
  130. package/dist/core.d.ts.map +1 -0
  131. package/dist/core.js +26 -0
  132. package/dist/core.js.map +1 -0
  133. package/dist/diagnostics/catalog.d.ts +20 -0
  134. package/dist/diagnostics/catalog.d.ts.map +1 -0
  135. package/dist/diagnostics/catalog.js +335 -0
  136. package/dist/diagnostics/catalog.js.map +1 -0
  137. package/dist/diagnostics/index.d.ts +6 -0
  138. package/dist/diagnostics/index.d.ts.map +1 -0
  139. package/dist/diagnostics/index.js +88 -0
  140. package/dist/diagnostics/index.js.map +1 -0
  141. package/dist/diagnostics/types.d.ts +21 -0
  142. package/dist/diagnostics/types.d.ts.map +1 -0
  143. package/dist/diagnostics/types.js +2 -0
  144. package/dist/diagnostics/types.js.map +1 -0
  145. package/dist/errors.d.ts +7 -0
  146. package/dist/errors.d.ts.map +1 -0
  147. package/dist/errors.js +10 -0
  148. package/dist/errors.js.map +1 -0
  149. package/dist/index.d.ts +4 -0
  150. package/dist/index.d.ts.map +1 -0
  151. package/dist/index.js +3 -0
  152. package/dist/index.js.map +1 -0
  153. package/dist/internal/body.d.ts +3 -0
  154. package/dist/internal/body.d.ts.map +1 -0
  155. package/dist/internal/body.js +48 -0
  156. package/dist/internal/body.js.map +1 -0
  157. package/dist/internal/bytes.d.ts +5 -0
  158. package/dist/internal/bytes.d.ts.map +1 -0
  159. package/dist/internal/bytes.js +38 -0
  160. package/dist/internal/bytes.js.map +1 -0
  161. package/dist/internal/crypto.d.ts +4 -0
  162. package/dist/internal/crypto.d.ts.map +1 -0
  163. package/dist/internal/crypto.js +49 -0
  164. package/dist/internal/crypto.js.map +1 -0
  165. package/dist/internal/headers.d.ts +3 -0
  166. package/dist/internal/headers.d.ts.map +1 -0
  167. package/dist/internal/headers.js +70 -0
  168. package/dist/internal/headers.js.map +1 -0
  169. package/dist/internal/options.d.ts +8 -0
  170. package/dist/internal/options.d.ts.map +1 -0
  171. package/dist/internal/options.js +128 -0
  172. package/dist/internal/options.js.map +1 -0
  173. package/dist/internal/prepare.d.ts +5 -0
  174. package/dist/internal/prepare.d.ts.map +1 -0
  175. package/dist/internal/prepare.js +9 -0
  176. package/dist/internal/prepare.js.map +1 -0
  177. package/dist/internal/provider-options.d.ts +7 -0
  178. package/dist/internal/provider-options.d.ts.map +1 -0
  179. package/dist/internal/provider-options.js +69 -0
  180. package/dist/internal/provider-options.js.map +1 -0
  181. package/dist/internal/provider.d.ts +40 -0
  182. package/dist/internal/provider.d.ts.map +1 -0
  183. package/dist/internal/provider.js +2 -0
  184. package/dist/internal/provider.js.map +1 -0
  185. package/dist/internal/verification.d.ts +13 -0
  186. package/dist/internal/verification.d.ts.map +1 -0
  187. package/dist/internal/verification.js +66 -0
  188. package/dist/internal/verification.js.map +1 -0
  189. package/dist/node/adapters/cloudflare.d.ts +1 -0
  190. package/dist/node/adapters/cloudflare.js +3 -0
  191. package/dist/node/adapters/express.d.ts +1 -0
  192. package/dist/node/adapters/express.js +3 -0
  193. package/dist/node/adapters/hono.d.ts +1 -0
  194. package/dist/node/adapters/hono.js +3 -0
  195. package/dist/node/adapters/nextjs.d.ts +1 -0
  196. package/dist/node/adapters/nextjs.js +3 -0
  197. package/dist/node/diagnostics/index.d.ts +1 -0
  198. package/dist/node/diagnostics/index.js +3 -0
  199. package/dist/node/index.d.ts +1 -0
  200. package/dist/node/index.js +6 -0
  201. package/dist/providers/clerk.d.ts +10 -0
  202. package/dist/providers/clerk.d.ts.map +1 -0
  203. package/dist/providers/clerk.js +13 -0
  204. package/dist/providers/clerk.js.map +1 -0
  205. package/dist/providers/dodo-payments.d.ts +21 -0
  206. package/dist/providers/dodo-payments.d.ts.map +1 -0
  207. package/dist/providers/dodo-payments.js +24 -0
  208. package/dist/providers/dodo-payments.js.map +1 -0
  209. package/dist/providers/doppler.d.ts +38 -0
  210. package/dist/providers/doppler.d.ts.map +1 -0
  211. package/dist/providers/doppler.js +69 -0
  212. package/dist/providers/doppler.js.map +1 -0
  213. package/dist/providers/fal.d.ts +14 -0
  214. package/dist/providers/fal.d.ts.map +1 -0
  215. package/dist/providers/fal.js +78 -0
  216. package/dist/providers/fal.js.map +1 -0
  217. package/dist/providers/github.d.ts +8 -0
  218. package/dist/providers/github.d.ts.map +1 -0
  219. package/dist/providers/github.js +50 -0
  220. package/dist/providers/github.js.map +1 -0
  221. package/dist/providers/gitlab.d.ts +21 -0
  222. package/dist/providers/gitlab.d.ts.map +1 -0
  223. package/dist/providers/gitlab.js +24 -0
  224. package/dist/providers/gitlab.js.map +1 -0
  225. package/dist/providers/grafana.d.ts +36 -0
  226. package/dist/providers/grafana.d.ts.map +1 -0
  227. package/dist/providers/grafana.js +178 -0
  228. package/dist/providers/grafana.js.map +1 -0
  229. package/dist/providers/index.d.ts +27 -0
  230. package/dist/providers/index.d.ts.map +1 -0
  231. package/dist/providers/index.js +89 -0
  232. package/dist/providers/index.js.map +1 -0
  233. package/dist/providers/lemon-squeezy.d.ts +16 -0
  234. package/dist/providers/lemon-squeezy.d.ts.map +1 -0
  235. package/dist/providers/lemon-squeezy.js +34 -0
  236. package/dist/providers/lemon-squeezy.js.map +1 -0
  237. package/dist/providers/linear.d.ts +37 -0
  238. package/dist/providers/linear.d.ts.map +1 -0
  239. package/dist/providers/linear.js +56 -0
  240. package/dist/providers/linear.js.map +1 -0
  241. package/dist/providers/paddle.d.ts +15 -0
  242. package/dist/providers/paddle.d.ts.map +1 -0
  243. package/dist/providers/paddle.js +103 -0
  244. package/dist/providers/paddle.js.map +1 -0
  245. package/dist/providers/polar.d.ts +26 -0
  246. package/dist/providers/polar.d.ts.map +1 -0
  247. package/dist/providers/polar.js +78 -0
  248. package/dist/providers/polar.js.map +1 -0
  249. package/dist/providers/razorpay.d.ts +20 -0
  250. package/dist/providers/razorpay.d.ts.map +1 -0
  251. package/dist/providers/razorpay.js +41 -0
  252. package/dist/providers/razorpay.js.map +1 -0
  253. package/dist/providers/replicate.d.ts +20 -0
  254. package/dist/providers/replicate.d.ts.map +1 -0
  255. package/dist/providers/replicate.js +23 -0
  256. package/dist/providers/replicate.js.map +1 -0
  257. package/dist/providers/sanity.d.ts +39 -0
  258. package/dist/providers/sanity.d.ts.map +1 -0
  259. package/dist/providers/sanity.js +159 -0
  260. package/dist/providers/sanity.js.map +1 -0
  261. package/dist/providers/sentry.d.ts +26 -0
  262. package/dist/providers/sentry.d.ts.map +1 -0
  263. package/dist/providers/sentry.js +45 -0
  264. package/dist/providers/sentry.js.map +1 -0
  265. package/dist/providers/shared.d.ts +15 -0
  266. package/dist/providers/shared.d.ts.map +1 -0
  267. package/dist/providers/shared.js +40 -0
  268. package/dist/providers/shared.js.map +1 -0
  269. package/dist/providers/shopify.d.ts +9 -0
  270. package/dist/providers/shopify.d.ts.map +1 -0
  271. package/dist/providers/shopify.js +38 -0
  272. package/dist/providers/shopify.js.map +1 -0
  273. package/dist/providers/standard-webhooks-protocol.d.ts +15 -0
  274. package/dist/providers/standard-webhooks-protocol.d.ts.map +1 -0
  275. package/dist/providers/standard-webhooks-protocol.js +95 -0
  276. package/dist/providers/standard-webhooks-protocol.js.map +1 -0
  277. package/dist/providers/standard-webhooks.d.ts +10 -0
  278. package/dist/providers/standard-webhooks.d.ts.map +1 -0
  279. package/dist/providers/standard-webhooks.js +13 -0
  280. package/dist/providers/standard-webhooks.js.map +1 -0
  281. package/dist/providers/stripe.d.ts +8 -0
  282. package/dist/providers/stripe.d.ts.map +1 -0
  283. package/dist/providers/stripe.js +79 -0
  284. package/dist/providers/stripe.js.map +1 -0
  285. package/dist/providers/svix.d.ts +10 -0
  286. package/dist/providers/svix.d.ts.map +1 -0
  287. package/dist/providers/svix.js +61 -0
  288. package/dist/providers/svix.js.map +1 -0
  289. package/dist/providers/vercel.d.ts +16 -0
  290. package/dist/providers/vercel.d.ts.map +1 -0
  291. package/dist/providers/vercel.js +37 -0
  292. package/dist/providers/vercel.js.map +1 -0
  293. package/dist/providers/workos.d.ts +33 -0
  294. package/dist/providers/workos.d.ts.map +1 -0
  295. package/dist/providers/workos.js +118 -0
  296. package/dist/providers/workos.js.map +1 -0
  297. package/dist/types.d.ts +69 -0
  298. package/dist/types.d.ts.map +1 -0
  299. package/dist/types.js +2 -0
  300. package/dist/types.js.map +1 -0
  301. package/package.json +200 -4
@@ -0,0 +1,78 @@
1
+ import { HooklatchError } from '../errors.js';
2
+ import { decodeLiteralSecret } from './shared.js';
3
+ import { createStandardWebhooksProtocol } from './standard-webhooks-protocol.js';
4
+ const CANONICAL_HEADERS = {
5
+ id: 'webhook-id',
6
+ timestamp: 'webhook-timestamp',
7
+ signature: 'webhook-signature',
8
+ };
9
+ const currentDescriptor = createStandardWebhooksProtocol('polar', 'Polar', CANONICAL_HEADERS);
10
+ const legacyDescriptor = {
11
+ provider: 'polar',
12
+ decodeSecret(secret) {
13
+ return decodeLiteralSecret(secret, 'Polar');
14
+ },
15
+ parse: currentDescriptor.parse,
16
+ };
17
+ function invalidOptions() {
18
+ throw new HooklatchError('invalid-options', 'Invalid Polar provider options.');
19
+ }
20
+ function isConfigObject(value) {
21
+ if (value === null || typeof value !== 'object')
22
+ return false;
23
+ try {
24
+ return !Array.isArray(value);
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
30
+ /**
31
+ * Read the selected mode as an own field and snapshot it before returning the
32
+ * descriptor. Inherited fields are not configuration; an own `secretMode:
33
+ * undefined` is invalid rather than an omitted optional field.
34
+ */
35
+ function snapshotSecretMode(options) {
36
+ if (options === undefined)
37
+ return 'current';
38
+ if (!isConfigObject(options))
39
+ invalidOptions();
40
+ let keys = [];
41
+ let hasMode = false;
42
+ let mode = undefined;
43
+ try {
44
+ keys = Reflect.ownKeys(options).filter((key) => Object.getOwnPropertyDescriptor(options, key)?.enumerable);
45
+ hasMode = Object.hasOwn(options, 'secretMode');
46
+ mode = hasMode ? options.secretMode : undefined;
47
+ }
48
+ catch {
49
+ invalidOptions();
50
+ }
51
+ if (keys.some((key) => key !== 'secretMode'))
52
+ invalidOptions();
53
+ if (!hasMode)
54
+ return 'current';
55
+ if (mode !== 'current' && mode !== 'legacy')
56
+ invalidOptions();
57
+ return mode;
58
+ }
59
+ /**
60
+ * Polar webhooks use the canonical Standard Webhooks headers and signed
61
+ * content: `${webhook-id}.${webhook-timestamp}.${rawBody}`.
62
+ *
63
+ * `current` (the default) keeps the shared Standard Webhooks decoder: an
64
+ * optional `whsec_` prefix is removed and the remainder must decode as
65
+ * canonical Base64 to 24..64 bytes. `legacy` treats the complete secret string
66
+ * as literal UTF-8 bytes, including any `whsec_` prefix, with only the shared
67
+ * nonempty policy. Exactly one mode applies to every secret configured for the
68
+ * descriptor; there is no prefix inference or cross-mode fallback.
69
+ *
70
+ * Polar's SDK tries both key interpretations and floors fractional timestamps.
71
+ * Hooklatch deliberately does neither, and does not decode opaque bodies as
72
+ * text. Source:
73
+ * https://raw.githubusercontent.com/polarsource/polar/89917ad4fe752b06ff84bd31c313d2a53a6085f1/sdk/typescript/src/webhooks.ts
74
+ */
75
+ export function createPolarDescriptor(options) {
76
+ return snapshotSecretMode(options) === 'current' ? currentDescriptor : legacyDescriptor;
77
+ }
78
+ //# sourceMappingURL=polar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"polar.js","sourceRoot":"","sources":["../../src/providers/polar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AAWjF,MAAM,iBAAiB,GAAG;IACxB,EAAE,EAAE,YAAY;IAChB,SAAS,EAAE,mBAAmB;IAC9B,SAAS,EAAE,mBAAmB;CACtB,CAAC;AAEX,MAAM,iBAAiB,GAAG,8BAA8B,CAAC,OAAO,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;AAE9F,MAAM,gBAAgB,GAAoB;IACxC,QAAQ,EAAE,OAAO;IAEjB,YAAY,CAAC,MAAc;QACzB,OAAO,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,KAAK,EAAE,iBAAiB,CAAC,KAAK;CAC/B,CAAC;AAEF,SAAS,cAAc;IACrB,MAAM,IAAI,cAAc,CAAC,iBAAiB,EAAE,iCAAiC,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,cAAc,CACrB,KAAgD;IAEhD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE9D,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,OAA2C;IACrE,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE5C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;QAAE,cAAc,EAAE,CAAC;IAE/C,IAAI,IAAI,GAAiC,EAAE,CAAC;IAC5C,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,IAAI,GAAyC,SAAS,CAAC;IAE3D,IAAI,CAAC;QACH,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CACpC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,wBAAwB,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,UAAU,CACnE,CAAC;QACF,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC/C,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,cAAc,EAAE,CAAC;IACnB,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,YAAY,CAAC;QAAE,cAAc,EAAE,CAAC;IAE/D,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAE/B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ;QAAE,cAAc,EAAE,CAAC;IAE9D,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgC;IACpE,OAAO,kBAAkB,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,gBAAgB,CAAC;AAC1F,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { NormalizedHeaders, ParseResult } from '../internal/provider.js';
2
+ /**
3
+ * Razorpay `X-Razorpay-Signature`: a single hex HMAC-SHA256 over the raw request
4
+ * body only, keyed with the literal dashboard webhook secret. A missing,
5
+ * blank, prefixed, non-hex, wrong-length or comma-combined value fails closed.
6
+ * The optional `x-razorpay-event-id` is unsigned metadata and never proves
7
+ * authenticity.
8
+ *
9
+ * Sources:
10
+ * - https://razorpay.com/docs/webhooks/validate-test/
11
+ * - https://github.com/razorpay/razorpay-node/blob/b9e8527225a7322ba2671a3bc0b848fd019d2d8c/lib/utils/razorpay-utils.js
12
+ *
13
+ * No Razorpay-published signature vector is claimed; test anchors are synthetic.
14
+ */
15
+ export declare const razorpayDescriptor: {
16
+ provider: "razorpay";
17
+ decodeSecret(secret: string): Uint8Array;
18
+ parse(headers: NormalizedHeaders, rawBody: Uint8Array): ParseResult;
19
+ };
20
+ //# sourceMappingURL=razorpay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"razorpay.d.ts","sourceRoot":"","sources":["../../src/providers/razorpay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAsB,MAAM,yBAAyB,CAAC;AAOlG;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB;;yBAGR,MAAM,GAAG,UAAU;mBAIzB,iBAAiB,WAAW,UAAU,GAAG,WAAW;CAwB6B,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { decodeHexSignature, decodeLiteralSecret, failure } from './shared.js';
2
+ const SIGNATURE_HEADER = 'x-razorpay-signature';
3
+ const EVENT_ID_HEADER = 'x-razorpay-event-id';
4
+ /**
5
+ * Razorpay `X-Razorpay-Signature`: a single hex HMAC-SHA256 over the raw request
6
+ * body only, keyed with the literal dashboard webhook secret. A missing,
7
+ * blank, prefixed, non-hex, wrong-length or comma-combined value fails closed.
8
+ * The optional `x-razorpay-event-id` is unsigned metadata and never proves
9
+ * authenticity.
10
+ *
11
+ * Sources:
12
+ * - https://razorpay.com/docs/webhooks/validate-test/
13
+ * - https://github.com/razorpay/razorpay-node/blob/b9e8527225a7322ba2671a3bc0b848fd019d2d8c/lib/utils/razorpay-utils.js
14
+ *
15
+ * No Razorpay-published signature vector is claimed; test anchors are synthetic.
16
+ */
17
+ export const razorpayDescriptor = {
18
+ provider: 'razorpay',
19
+ decodeSecret(secret) {
20
+ return decodeLiteralSecret(secret, 'Razorpay');
21
+ },
22
+ parse(headers, rawBody) {
23
+ const raw = headers.get(SIGNATURE_HEADER);
24
+ if (raw === undefined || raw.trim() === '') {
25
+ return failure('missing-signature', 'No Razorpay signature header was provided.');
26
+ }
27
+ const signature = decodeHexSignature(raw);
28
+ if (signature === null) {
29
+ return failure('malformed-signature', 'The Razorpay signature header is malformed.');
30
+ }
31
+ const eventId = headers.get(EVENT_ID_HEADER);
32
+ const identity = {
33
+ deliveryId: null,
34
+ eventId: eventId === undefined || eventId.trim() === '' ? null : eventId,
35
+ timestamp: null,
36
+ authenticatedFields: [],
37
+ };
38
+ return { ok: true, signatures: [signature], signedContent: rawBody, identity };
39
+ },
40
+ };
41
+ //# sourceMappingURL=razorpay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"razorpay.js","sourceRoot":"","sources":["../../src/providers/razorpay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE/E,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAChD,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,QAAQ,EAAE,UAAU;IAEpB,YAAY,CAAC,MAAc;QACzB,OAAO,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,OAA0B,EAAE,OAAmB;QACnD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAE1C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC3C,OAAO,OAAO,CAAC,mBAAmB,EAAE,4CAA4C,CAAC,CAAC;QACpF,CAAC;QAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,OAAO,CAAC,qBAAqB,EAAE,6CAA6C,CAAC,CAAC;QACvF,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAE7C,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO;YACxE,SAAS,EAAE,IAAI;YACf,mBAAmB,EAAE,EAAE;SACxB,CAAC;QAEF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IACjF,CAAC;CAC+F,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Replicate webhooks use the canonical Standard Webhooks `webhook-id`,
3
+ * `webhook-timestamp` and `webhook-signature` headers. The secret is
4
+ * Base64-decoded (an optional `whsec_` prefix is stripped) and must decode to
5
+ * 24-64 bytes; the signature covers the exact
6
+ * `${webhook-id}.${webhook-timestamp}.` bytes followed by the raw body.
7
+ *
8
+ * These headers authenticate protocol bytes, not a unique Replicate identity.
9
+ * A signature minted by another canonical alias verifies here when the same
10
+ * secret is configured, so use endpoint-specific secrets. No prediction or
11
+ * event payload is parsed and no resource id is inferred.
12
+ *
13
+ * No Replicate-published signature vector is claimed; the direct tests use
14
+ * synthetic anchors. Source:
15
+ * https://replicate.com/docs/topics/webhooks/verify-webhook
16
+ */
17
+ export declare const replicateDescriptor: {
18
+ readonly provider: "replicate";
19
+ } & Pick<import("../internal/provider.js").ProviderDescriptor, "decodeSecret" | "parse">;
20
+ //# sourceMappingURL=replicate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replicate.d.ts","sourceRoot":"","sources":["../../src/providers/replicate.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,mBAAmB;;wFAQ/B,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { createStandardWebhooksProtocol } from './standard-webhooks-protocol.js';
2
+ /**
3
+ * Replicate webhooks use the canonical Standard Webhooks `webhook-id`,
4
+ * `webhook-timestamp` and `webhook-signature` headers. The secret is
5
+ * Base64-decoded (an optional `whsec_` prefix is stripped) and must decode to
6
+ * 24-64 bytes; the signature covers the exact
7
+ * `${webhook-id}.${webhook-timestamp}.` bytes followed by the raw body.
8
+ *
9
+ * These headers authenticate protocol bytes, not a unique Replicate identity.
10
+ * A signature minted by another canonical alias verifies here when the same
11
+ * secret is configured, so use endpoint-specific secrets. No prediction or
12
+ * event payload is parsed and no resource id is inferred.
13
+ *
14
+ * No Replicate-published signature vector is claimed; the direct tests use
15
+ * synthetic anchors. Source:
16
+ * https://replicate.com/docs/topics/webhooks/verify-webhook
17
+ */
18
+ export const replicateDescriptor = createStandardWebhooksProtocol('replicate', 'Replicate', {
19
+ id: 'webhook-id',
20
+ timestamp: 'webhook-timestamp',
21
+ signature: 'webhook-signature',
22
+ });
23
+ //# sourceMappingURL=replicate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replicate.js","sourceRoot":"","sources":["../../src/providers/replicate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AAEjF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,8BAA8B,CAC/D,WAAW,EACX,WAAW,EACX;IACE,EAAE,EAAE,YAAY;IAChB,SAAS,EAAE,mBAAmB;IAC9B,SAAS,EAAE,mBAAmB;CAC/B,CACF,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { NormalizedHeaders, ParseResult } from '../internal/provider.js';
2
+ /**
3
+ * Sanity: `sanity-webhook-signature: t=<unix milliseconds>,v1=<base64url>`.
4
+ *
5
+ * The HMAC-SHA256 covers UTF8(the original `t` text + ".") concatenated with
6
+ * the exact raw body. The secret is the literal, untrimmed UTF-8 text; it is
7
+ * never Base64-decoded. The digest is canonical unpadded Base64url for exactly
8
+ * 32 bytes, decoded by a descriptor-local decoder so the shared standard
9
+ * Base64 handling stays unchanged.
10
+ *
11
+ * The accepted header is exactly `t=<ms>,v1=<digest>`: ordered fields, one
12
+ * each, no whitespace anywhere or outer trimming, no extra or duplicate
13
+ * fields, no semicolon separators, no padding, and no alternate versions. A
14
+ * missing or blank header is `missing-signature`; every other nonmatching
15
+ * structure is `malformed-signature`, with no alternate reason precedence.
16
+ *
17
+ * `t` must be a canonical nonnegative safe decimal integer of milliseconds
18
+ * with no leading zeros, at or after 2021-01-01T00:00:00.000Z. Identity is
19
+ * `timestamp = Number(t) / 1000` with no delivery or event id; freshness is
20
+ * enforced by core and is never evaluated here.
21
+ *
22
+ * The reference SDK verifies UTF-8 text and refuses to sign an empty payload.
23
+ * This descriptor accepts empty, NUL, invalid UTF-8, and non-JSON bodies as
24
+ * opaque bytes, so it extends rather than matches that behavior, and it does
25
+ * not claim exact SDK parity or live interoperability. The strict grammar
26
+ * is checked at parse time. The reference decoder regex accepts spaces and
27
+ * trimming, but full SDK verification compares the original header to canonical
28
+ * re-encoding and also rejects these noncanonical header variants.
29
+ *
30
+ * Sources:
31
+ * - https://www.sanity.io/docs/content-lake/webhook-best-practices
32
+ * - https://github.com/sanity-io/webhook-toolkit/blob/e0c211ed6cd80465a70829e335c9e219f37839ba/src/signature.ts
33
+ */
34
+ export declare const sanityDescriptor: {
35
+ provider: "sanity";
36
+ decodeSecret(secret: string): Uint8Array;
37
+ parse(headers: NormalizedHeaders, rawBody: Uint8Array): ParseResult;
38
+ };
39
+ //# sourceMappingURL=sanity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanity.d.ts","sourceRoot":"","sources":["../../src/providers/sanity.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAsB,MAAM,yBAAyB,CAAC;AA6GlG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,gBAAgB;;yBAGN,MAAM,GAAG,UAAU;mBAIzB,iBAAiB,WAAW,UAAU,GAAG,WAAW;CA2C2B,CAAC"}
@@ -0,0 +1,159 @@
1
+ import { concatBytes, utf8 } from '../internal/bytes.js';
2
+ import { decodeLiteralSecret, failure, isCanonicalTimestamp } from './shared.js';
3
+ const SIGNATURE_HEADER = 'sanity-webhook-signature';
4
+ const TIMESTAMP_FIELD = 't=';
5
+ const SIGNATURE_FIELD = 'v1=';
6
+ const DIGEST_CHARACTERS = 43;
7
+ const BASE64URL_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
8
+ /**
9
+ * Sanity does not send signed payloads before 2021-01-01T00:00:00.000Z, so a
10
+ * millisecond timestamp below this bound is not a Sanity delivery. The bound
11
+ * mirrors the reference toolkit; the failure code is Hooklatch policy.
12
+ */
13
+ const MINIMUM_TIMESTAMP_MS = 1609459200000;
14
+ /**
15
+ * Split the exact accepted header grammar `t=<ms>,v1=<digest>`.
16
+ *
17
+ * The fields are ordered, appear exactly once, and carry no whitespace, extra
18
+ * fields, duplicate fields, semicolon separators, or alternate versions. Any
19
+ * other structure is rejected instead of being repaired.
20
+ */
21
+ function splitHeader(raw) {
22
+ const separator = raw.indexOf(',');
23
+ if (separator < 0)
24
+ return null;
25
+ const timestampField = raw.slice(0, separator);
26
+ const signatureField = raw.slice(separator + 1);
27
+ if (!timestampField.startsWith(TIMESTAMP_FIELD))
28
+ return null;
29
+ if (!signatureField.startsWith(SIGNATURE_FIELD))
30
+ return null;
31
+ const timestampText = timestampField.slice(TIMESTAMP_FIELD.length);
32
+ const digest = signatureField.slice(SIGNATURE_FIELD.length);
33
+ if (timestampText.length === 0)
34
+ return null;
35
+ return { timestampText, digest };
36
+ }
37
+ /**
38
+ * Encode the 32 decoded digest bytes as canonical unpadded Base64url.
39
+ *
40
+ * 32 bytes are 256 bits: 42 characters carry 252 of them and the last four
41
+ * bits close the 43rd character.
42
+ */
43
+ function encodeBase64Url(bytes) {
44
+ let output = '';
45
+ let buffer = 0;
46
+ let bits = 0;
47
+ for (const byte of bytes) {
48
+ buffer = (buffer << 8) | byte;
49
+ bits += 8;
50
+ while (bits >= 6) {
51
+ bits -= 6;
52
+ output += BASE64URL_ALPHABET.charAt((buffer >>> bits) & 0x3f);
53
+ buffer &= (1 << bits) - 1;
54
+ }
55
+ }
56
+ return output + BASE64URL_ALPHABET.charAt((buffer << (6 - bits)) & 0x3f);
57
+ }
58
+ /**
59
+ * Decode exactly 43 canonical unpadded Base64url characters into 32 bytes.
60
+ *
61
+ * The 43 characters carry 258 bits, so 32 bytes consume 256 of them and the
62
+ * two remaining low bits of the final character are pad bits. Re-encoding the
63
+ * decoded bytes must reproduce the input exactly, which rejects a digest whose
64
+ * pad bits are not zero.
65
+ */
66
+ function decodeBase64UrlDigest(value) {
67
+ if (value.length !== DIGEST_CHARACTERS)
68
+ return null;
69
+ const bytes = new Uint8Array(32);
70
+ let buffer = 0;
71
+ let bits = 0;
72
+ let offset = 0;
73
+ for (let index = 0; index < value.length; index += 1) {
74
+ const digit = BASE64URL_ALPHABET.indexOf(value.charAt(index));
75
+ if (digit < 0)
76
+ return null;
77
+ buffer = (buffer << 6) | digit;
78
+ bits += 6;
79
+ if (bits < 8)
80
+ continue;
81
+ bits -= 8;
82
+ bytes[offset] = (buffer >>> bits) & 0xff;
83
+ offset += 1;
84
+ buffer &= (1 << bits) - 1;
85
+ }
86
+ return encodeBase64Url(bytes) === value ? bytes : null;
87
+ }
88
+ /**
89
+ * Sanity: `sanity-webhook-signature: t=<unix milliseconds>,v1=<base64url>`.
90
+ *
91
+ * The HMAC-SHA256 covers UTF8(the original `t` text + ".") concatenated with
92
+ * the exact raw body. The secret is the literal, untrimmed UTF-8 text; it is
93
+ * never Base64-decoded. The digest is canonical unpadded Base64url for exactly
94
+ * 32 bytes, decoded by a descriptor-local decoder so the shared standard
95
+ * Base64 handling stays unchanged.
96
+ *
97
+ * The accepted header is exactly `t=<ms>,v1=<digest>`: ordered fields, one
98
+ * each, no whitespace anywhere or outer trimming, no extra or duplicate
99
+ * fields, no semicolon separators, no padding, and no alternate versions. A
100
+ * missing or blank header is `missing-signature`; every other nonmatching
101
+ * structure is `malformed-signature`, with no alternate reason precedence.
102
+ *
103
+ * `t` must be a canonical nonnegative safe decimal integer of milliseconds
104
+ * with no leading zeros, at or after 2021-01-01T00:00:00.000Z. Identity is
105
+ * `timestamp = Number(t) / 1000` with no delivery or event id; freshness is
106
+ * enforced by core and is never evaluated here.
107
+ *
108
+ * The reference SDK verifies UTF-8 text and refuses to sign an empty payload.
109
+ * This descriptor accepts empty, NUL, invalid UTF-8, and non-JSON bodies as
110
+ * opaque bytes, so it extends rather than matches that behavior, and it does
111
+ * not claim exact SDK parity or live interoperability. The strict grammar
112
+ * is checked at parse time. The reference decoder regex accepts spaces and
113
+ * trimming, but full SDK verification compares the original header to canonical
114
+ * re-encoding and also rejects these noncanonical header variants.
115
+ *
116
+ * Sources:
117
+ * - https://www.sanity.io/docs/content-lake/webhook-best-practices
118
+ * - https://github.com/sanity-io/webhook-toolkit/blob/e0c211ed6cd80465a70829e335c9e219f37839ba/src/signature.ts
119
+ */
120
+ export const sanityDescriptor = {
121
+ provider: 'sanity',
122
+ decodeSecret(secret) {
123
+ return decodeLiteralSecret(secret, 'Sanity');
124
+ },
125
+ parse(headers, rawBody) {
126
+ const raw = headers.get(SIGNATURE_HEADER);
127
+ if (raw === undefined || raw.trim() === '') {
128
+ return failure('missing-signature', 'No Sanity signature header was provided.');
129
+ }
130
+ const fields = splitHeader(raw);
131
+ if (fields === null) {
132
+ return failure('malformed-signature', 'The Sanity signature header is malformed.');
133
+ }
134
+ if (!isCanonicalTimestamp(fields.timestampText)) {
135
+ return failure('malformed-signature', 'The Sanity signature header is malformed.');
136
+ }
137
+ const timestamp = Number(fields.timestampText);
138
+ if (timestamp < MINIMUM_TIMESTAMP_MS) {
139
+ return failure('malformed-signature', 'The Sanity signature header is malformed.');
140
+ }
141
+ const digest = decodeBase64UrlDigest(fields.digest);
142
+ if (digest === null) {
143
+ return failure('malformed-signature', 'The Sanity signature header is malformed.');
144
+ }
145
+ const identity = {
146
+ deliveryId: null,
147
+ eventId: null,
148
+ timestamp: timestamp / 1000,
149
+ authenticatedFields: ['timestamp'],
150
+ };
151
+ return {
152
+ ok: true,
153
+ signatures: [digest],
154
+ signedContent: concatBytes(utf8(`${fields.timestampText}.`), rawBody),
155
+ identity,
156
+ };
157
+ },
158
+ };
159
+ //# sourceMappingURL=sanity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanity.js","sourceRoot":"","sources":["../../src/providers/sanity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { NormalizedHeaders, ParseResult } from '../internal/provider.js';
2
+ /**
3
+ * Sentry App integration-platform webhooks: `Sentry-Hook-Signature` is a single
4
+ * 64-character hex HMAC-SHA256 over the exact raw request body, keyed with the
5
+ * literal app client secret. Missing or trim-blank -> missing-signature; every
6
+ * other nonconforming value (prefixes, whitespace, comma-combined duplicates,
7
+ * lists, wrong length or non-hex) fails closed.
8
+ *
9
+ * `Request-Id`, `Sentry-Hook-Timestamp` and `Sentry-Hook-Resource` are outside
10
+ * the MAC: they cannot establish freshness or trusted identity. Sentry's docs
11
+ * examples re-serialize the parsed body, which can change the signed bytes; this
12
+ * descriptor always returns the untouched `rawBody` as signed content.
13
+ *
14
+ * Scope is Sentry App integration-platform webhooks only, not every Sentry
15
+ * webhook product. Sources:
16
+ * - https://docs.sentry.io/integrations/integration-platform/webhooks/
17
+ * - https://github.com/getsentry/sentry/blob/72757dae9b6d527e564c81d4921dec0d62d7beca/src/sentry/sentry_apps/api/serializers/app_platform_event.py
18
+ *
19
+ * No Sentry-published signature vector is claimed; test anchors are synthetic.
20
+ */
21
+ export declare const sentryDescriptor: {
22
+ provider: "sentry";
23
+ decodeSecret(secret: string): Uint8Array;
24
+ parse(headers: NormalizedHeaders, rawBody: Uint8Array): ParseResult;
25
+ };
26
+ //# sourceMappingURL=sentry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentry.d.ts","sourceRoot":"","sources":["../../src/providers/sentry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAsB,MAAM,yBAAyB,CAAC;AAMlG;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,gBAAgB;;yBAGN,MAAM,GAAG,UAAU;mBAIzB,iBAAiB,WAAW,UAAU,GAAG,WAAW;CAsB2B,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { decodeHexSignature, decodeLiteralSecret, failure } from './shared.js';
2
+ const SIGNATURE_HEADER = 'sentry-hook-signature';
3
+ /**
4
+ * Sentry App integration-platform webhooks: `Sentry-Hook-Signature` is a single
5
+ * 64-character hex HMAC-SHA256 over the exact raw request body, keyed with the
6
+ * literal app client secret. Missing or trim-blank -> missing-signature; every
7
+ * other nonconforming value (prefixes, whitespace, comma-combined duplicates,
8
+ * lists, wrong length or non-hex) fails closed.
9
+ *
10
+ * `Request-Id`, `Sentry-Hook-Timestamp` and `Sentry-Hook-Resource` are outside
11
+ * the MAC: they cannot establish freshness or trusted identity. Sentry's docs
12
+ * examples re-serialize the parsed body, which can change the signed bytes; this
13
+ * descriptor always returns the untouched `rawBody` as signed content.
14
+ *
15
+ * Scope is Sentry App integration-platform webhooks only, not every Sentry
16
+ * webhook product. Sources:
17
+ * - https://docs.sentry.io/integrations/integration-platform/webhooks/
18
+ * - https://github.com/getsentry/sentry/blob/72757dae9b6d527e564c81d4921dec0d62d7beca/src/sentry/sentry_apps/api/serializers/app_platform_event.py
19
+ *
20
+ * No Sentry-published signature vector is claimed; test anchors are synthetic.
21
+ */
22
+ export const sentryDescriptor = {
23
+ provider: 'sentry',
24
+ decodeSecret(secret) {
25
+ return decodeLiteralSecret(secret, 'Sentry App');
26
+ },
27
+ parse(headers, rawBody) {
28
+ const raw = headers.get(SIGNATURE_HEADER);
29
+ if (raw === undefined || raw.trim() === '') {
30
+ return failure('missing-signature', 'No Sentry App signature header was provided.');
31
+ }
32
+ const signature = decodeHexSignature(raw);
33
+ if (signature === null) {
34
+ return failure('malformed-signature', 'The Sentry App signature header is malformed.');
35
+ }
36
+ const identity = {
37
+ deliveryId: null,
38
+ eventId: null,
39
+ timestamp: null,
40
+ authenticatedFields: [],
41
+ };
42
+ return { ok: true, signatures: [signature], signedContent: rawBody, identity };
43
+ },
44
+ };
45
+ //# sourceMappingURL=sentry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sentry.js","sourceRoot":"","sources":["../../src/providers/sentry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE/E,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,EAAE,QAAQ;IAElB,YAAY,CAAC,MAAc;QACzB,OAAO,mBAAmB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,OAA0B,EAAE,OAAmB;QACnD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAE1C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC3C,OAAO,OAAO,CAAC,mBAAmB,EAAE,8CAA8C,CAAC,CAAC;QACtF,CAAC;QAED,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,OAAO,CAAC,qBAAqB,EAAE,+CAA+C,CAAC,CAAC;QACzF,CAAC;QAED,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,IAAI;YACf,mBAAmB,EAAE,EAAE;SACxB,CAAC;QAEF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IACjF,CAAC;CAC6F,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { FailureDetails, VerificationFailureReason } from '../types.js';
2
+ /** HMAC-SHA256 signatures are always exactly 32 bytes. */
3
+ export declare const SIGNATURE_BYTES = 32;
4
+ export declare function failure(reason: VerificationFailureReason, message: string): FailureDetails;
5
+ export declare function isSchemeToken(value: string): boolean;
6
+ /** Canonical decimal integer: `0`, or a nonzero digit followed by digits. */
7
+ export declare function isCanonicalTimestamp(value: string): boolean;
8
+ /** Hex signature of exactly 32 bytes; accepts either hex case. */
9
+ export declare function decodeHexSignature(value: string): Uint8Array | null;
10
+ /** Canonical Base64 signature of exactly 32 bytes. */
11
+ export declare function decodeBase64Signature(value: string): Uint8Array | null;
12
+ export declare function isNonEmptySecret(secret: string): secret is string;
13
+ /** Literal, untrimmed UTF-8 secret bytes for Stripe/GitHub/Shopify. */
14
+ export declare function decodeLiteralSecret(secret: string, label: string): Uint8Array;
15
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/providers/shared.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAE7E,0DAA0D;AAC1D,eAAO,MAAM,eAAe,KAAK,CAAC;AAKlC,wBAAgB,OAAO,CACrB,MAAM,EAAE,yBAAyB,EACjC,OAAO,EAAE,MAAM,GACd,cAAc,CAEhB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAK3D;AAED,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAInE;AAED,sDAAsD;AACtD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAItE;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,MAAM,CAEjE;AAED,uEAAuE;AACvE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAM7E"}
@@ -0,0 +1,40 @@
1
+ import { HooklatchError } from '../errors.js';
2
+ import { decodeBase64, decodeHex, utf8 } from '../internal/bytes.js';
3
+ /** HMAC-SHA256 signatures are always exactly 32 bytes. */
4
+ export const SIGNATURE_BYTES = 32;
5
+ /** Scheme/key tokens accepted in provider signature headers (e.g. `v1`, `sha256`). */
6
+ const TOKEN = /^[A-Za-z0-9_-]+$/;
7
+ export function failure(reason, message) {
8
+ return { ok: false, reason, message };
9
+ }
10
+ export function isSchemeToken(value) {
11
+ return TOKEN.test(value);
12
+ }
13
+ /** Canonical decimal integer: `0`, or a nonzero digit followed by digits. */
14
+ export function isCanonicalTimestamp(value) {
15
+ if (!/^(?:0|[1-9]\d*)$/.test(value))
16
+ return false;
17
+ const numeric = Number(value);
18
+ return Number.isSafeInteger(numeric) && numeric >= 0;
19
+ }
20
+ /** Hex signature of exactly 32 bytes; accepts either hex case. */
21
+ export function decodeHexSignature(value) {
22
+ const bytes = decodeHex(value);
23
+ return bytes !== null && bytes.byteLength === SIGNATURE_BYTES ? bytes : null;
24
+ }
25
+ /** Canonical Base64 signature of exactly 32 bytes. */
26
+ export function decodeBase64Signature(value) {
27
+ const bytes = decodeBase64(value);
28
+ return bytes !== null && bytes.byteLength === SIGNATURE_BYTES ? bytes : null;
29
+ }
30
+ export function isNonEmptySecret(secret) {
31
+ return typeof secret === 'string' && secret.length > 0;
32
+ }
33
+ /** Literal, untrimmed UTF-8 secret bytes for Stripe/GitHub/Shopify. */
34
+ export function decodeLiteralSecret(secret, label) {
35
+ if (!isNonEmptySecret(secret)) {
36
+ throw new HooklatchError('invalid-secret', `Invalid ${label} signing secret.`);
37
+ }
38
+ return utf8(secret);
39
+ }
40
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/providers/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAGrE,0DAA0D;AAC1D,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC,sFAAsF;AACtF,MAAM,KAAK,GAAG,kBAAkB,CAAC;AAEjC,MAAM,UAAU,OAAO,CACrB,MAAiC,EACjC,OAAe;IAEf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAClD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE9B,OAAO,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,CAAC;AACvD,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAE/B,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/E,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAElC,OAAO,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;AACzD,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,KAAa;IAC/D,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,cAAc,CAAC,gBAAgB,EAAE,WAAW,KAAK,kBAAkB,CAAC,CAAC;IACjF,CAAC;IAED,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ProviderDescriptor } from '../internal/provider.js';
2
+ /**
3
+ * Shopify HTTPS `X-Shopify-Hmac-Sha256`: canonical Base64 HMAC-SHA256 over the
4
+ * raw body only, keyed with the app client secret. Delivery and event IDs are
5
+ * unsigned metadata. EventBridge/Pub/Sub deliveries carry no HMAC header and are
6
+ * therefore not verifiable by this descriptor.
7
+ */
8
+ export declare const shopifyDescriptor: ProviderDescriptor;
9
+ //# sourceMappingURL=shopify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shopify.d.ts","sourceRoot":"","sources":["../../src/providers/shopify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkC,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAclG;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,kBA6B/B,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { decodeBase64Signature, decodeLiteralSecret, failure } from './shared.js';
2
+ const SIGNATURE_HEADER = 'x-shopify-hmac-sha256';
3
+ const DELIVERY_HEADER = 'x-shopify-webhook-id';
4
+ const EVENT_HEADER = 'x-shopify-event-id';
5
+ function optionalHeader(headers, name) {
6
+ const value = headers.get(name);
7
+ return value === undefined || value === '' ? null : value;
8
+ }
9
+ /**
10
+ * Shopify HTTPS `X-Shopify-Hmac-Sha256`: canonical Base64 HMAC-SHA256 over the
11
+ * raw body only, keyed with the app client secret. Delivery and event IDs are
12
+ * unsigned metadata. EventBridge/Pub/Sub deliveries carry no HMAC header and are
13
+ * therefore not verifiable by this descriptor.
14
+ */
15
+ export const shopifyDescriptor = {
16
+ provider: 'shopify',
17
+ decodeSecret(secret) {
18
+ return decodeLiteralSecret(secret, 'Shopify');
19
+ },
20
+ parse(headers, rawBody) {
21
+ const raw = headers.get(SIGNATURE_HEADER);
22
+ if (raw === undefined || raw.trim() === '') {
23
+ return failure('missing-signature', 'No Shopify signature header was provided.');
24
+ }
25
+ const signature = decodeBase64Signature(raw);
26
+ if (signature === null) {
27
+ return failure('malformed-signature', 'The Shopify signature header is malformed.');
28
+ }
29
+ const identity = {
30
+ deliveryId: optionalHeader(headers, DELIVERY_HEADER),
31
+ eventId: optionalHeader(headers, EVENT_HEADER),
32
+ timestamp: null,
33
+ authenticatedFields: [],
34
+ };
35
+ return { ok: true, signatures: [signature], signedContent: rawBody, identity };
36
+ },
37
+ };
38
+ //# sourceMappingURL=shopify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shopify.js","sourceRoot":"","sources":["../../src/providers/shopify.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAElF,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AACjD,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAC/C,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAE1C,SAAS,cAAc,CAAC,OAA0B,EAAE,IAAY;IAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEhC,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAuB;IACnD,QAAQ,EAAE,SAAS;IAEnB,YAAY,CAAC,MAAc;QACzB,OAAO,mBAAmB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,OAA0B,EAAE,OAAmB;QACnD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAE1C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC3C,OAAO,OAAO,CAAC,mBAAmB,EAAE,2CAA2C,CAAC,CAAC;QACnF,CAAC;QAED,MAAM,SAAS,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAE7C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,OAAO,CAAC,qBAAqB,EAAE,4CAA4C,CAAC,CAAC;QACtF,CAAC;QAED,MAAM,QAAQ,GAAkB;YAC9B,UAAU,EAAE,cAAc,CAAC,OAAO,EAAE,eAAe,CAAC;YACpD,OAAO,EAAE,cAAc,CAAC,OAAO,EAAE,YAAY,CAAC;YAC9C,SAAS,EAAE,IAAI;YACf,mBAAmB,EAAE,EAAE;SACxB,CAAC;QAEF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IACjF,CAAC;CACF,CAAC"}