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,341 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVerificationGuidance = getVerificationGuidance;
4
+ exports.getSetupGuidance = getSetupGuidance;
5
+ exports.getProviderDetail = getProviderDetail;
6
+ exports.isVerificationCode = isVerificationCode;
7
+ exports.isSetupCode = isSetupCode;
8
+ const VERIFICATION_GUIDANCE = {
9
+ 'missing-signature': {
10
+ summary: 'The provider signature header was not present in the request.',
11
+ possibleCauses: [
12
+ 'A proxy, load balancer, or middleware stripped the signature header.',
13
+ 'The request was not actually sent by the provider.',
14
+ 'The request was modified in transit.',
15
+ ],
16
+ suggestions: [
17
+ 'Check that no intermediary removes the signature header.',
18
+ 'Verify the request originates from the provider documented IP ranges.',
19
+ 'Compare expected header names with your middleware configuration.',
20
+ ],
21
+ },
22
+ 'malformed-signature': {
23
+ summary: 'Required signing headers were malformed or conflicted.',
24
+ possibleCauses: [
25
+ 'The header value was truncated or altered by an intermediary.',
26
+ 'The provider changed its header format.',
27
+ 'The request was not actually sent by the provider.',
28
+ ],
29
+ suggestions: [
30
+ 'Compare the raw header value against the provider documentation.',
31
+ 'Check for header-combining proxies that may merge or split values.',
32
+ 'Use synthetic requests to compare header grammar without recording sensitive values.',
33
+ ],
34
+ },
35
+ 'unsupported-scheme': {
36
+ summary: 'Only unsupported or legacy signature schemes were present.',
37
+ possibleCauses: [
38
+ 'The provider sent a legacy signature format (e.g. SHA-1).',
39
+ 'The signature scheme version is not supported by this release.',
40
+ 'The request was not actually sent by the provider.',
41
+ ],
42
+ suggestions: [
43
+ 'Check the provider documentation for supported signature schemes.',
44
+ 'Ensure the provider is configured to send the current scheme version.',
45
+ 'Update the SDK when a new scheme is required.',
46
+ ],
47
+ },
48
+ 'invalid-signature': {
49
+ summary: 'The signature was well-formed but did not authenticate.',
50
+ possibleCauses: [
51
+ 'The configured secret does not match the provider endpoint secret.',
52
+ 'A secret rotation is in progress and the old secret is still active at the provider.',
53
+ 'The body was modified in transit, compressed, or re-serialized.',
54
+ 'The wrong provider was selected for this request.',
55
+ 'The request was not actually sent by the provider.',
56
+ ],
57
+ suggestions: [
58
+ 'Verify the configured secret matches the provider endpoint secret.',
59
+ 'Check whether a secret rotation is in progress and include all active secrets.',
60
+ 'Ensure the raw body is captured before any JSON parsing or re-serialization.',
61
+ 'Confirm the correct provider is selected for this endpoint.',
62
+ ],
63
+ },
64
+ 'missing-identity': {
65
+ summary: 'A required identity metadata header was absent.',
66
+ possibleCauses: [
67
+ 'The request was not actually sent by the provider.',
68
+ 'An intermediary stripped the header.',
69
+ 'The provider changed its header format.',
70
+ ],
71
+ suggestions: [
72
+ 'Compare the incoming headers with the provider documentation.',
73
+ 'Check that no proxy or middleware removes the header.',
74
+ 'Verify the request originates from the provider.',
75
+ ],
76
+ },
77
+ 'missing-timestamp': {
78
+ summary: 'A required signed timestamp header was absent.',
79
+ possibleCauses: [
80
+ 'The request was not actually sent by the provider.',
81
+ 'An intermediary stripped the header.',
82
+ 'The provider changed its header format.',
83
+ ],
84
+ suggestions: [
85
+ 'Compare the incoming headers with the provider documentation.',
86
+ 'Check that no proxy or middleware removes the header.',
87
+ 'Verify the request originates from the provider.',
88
+ ],
89
+ },
90
+ 'timestamp-expired': {
91
+ summary: 'The signed timestamp is older than the configured tolerance.',
92
+ possibleCauses: [
93
+ 'The request is a replay of an older delivery.',
94
+ 'Clock skew exists between the provider and this host.',
95
+ 'The body was delayed by a queue or retry mechanism.',
96
+ ],
97
+ suggestions: [
98
+ 'Check clock synchronization between provider and host.',
99
+ 'Review provider delivery timing before changing the configured tolerance.',
100
+ 'Investigate whether the request is a replay attack.',
101
+ ],
102
+ },
103
+ 'timestamp-future': {
104
+ summary: 'The signed timestamp is newer than the configured tolerance.',
105
+ possibleCauses: [
106
+ 'Clock skew exists between the provider and this host.',
107
+ 'The provider clock is ahead of this host.',
108
+ ],
109
+ suggestions: [
110
+ 'Check clock synchronization between provider and host.',
111
+ 'Review provider clock behavior before changing the configured tolerance.',
112
+ ],
113
+ },
114
+ 'body-too-large': {
115
+ summary: 'The request body exceeded the configured size limit.',
116
+ possibleCauses: [
117
+ 'The legitimate payload exceeds the configured maxBodyBytes.',
118
+ 'The body was inflated by compression middleware.',
119
+ 'A malicious or malformed request sent an oversized body.',
120
+ ],
121
+ suggestions: [
122
+ 'Increase maxBodyBytes if the provider legitimately sends larger payloads.',
123
+ 'Check for compression middleware that may inflate the body.',
124
+ 'Reject the request if the size is unexpected for this provider.',
125
+ ],
126
+ },
127
+ };
128
+ /** Static guidance for setup/runtime error codes. */
129
+ const SETUP_GUIDANCE = {
130
+ 'unknown-provider': {
131
+ summary: 'The specified provider is not supported.',
132
+ possibleCauses: [
133
+ 'The provider name contains a typo.',
134
+ 'The provider has not been added to the SDK yet.',
135
+ ],
136
+ suggestions: [
137
+ 'Check the provider name against the supported list.',
138
+ 'Update the SDK to a version that supports the provider.',
139
+ ],
140
+ },
141
+ 'missing-secrets': {
142
+ summary: 'No signing secrets were configured.',
143
+ possibleCauses: [
144
+ 'The secrets option was omitted.',
145
+ 'The secrets array was empty.',
146
+ ],
147
+ suggestions: [
148
+ 'Provide at least one active signing secret.',
149
+ 'Load secrets from environment variables or a secrets manager.',
150
+ ],
151
+ },
152
+ 'invalid-secret': {
153
+ summary: 'A configured secret failed validation.',
154
+ possibleCauses: [
155
+ 'The secret is empty or contains only whitespace.',
156
+ 'The secret format does not match the provider requirements.',
157
+ 'The secret was copied incorrectly from the provider dashboard.',
158
+ ],
159
+ suggestions: [
160
+ 'Verify the secret matches the provider documentation format.',
161
+ 'Check for trailing whitespace or newline characters.',
162
+ 'Regenerate the secret at the provider if necessary.',
163
+ ],
164
+ },
165
+ 'invalid-options': {
166
+ summary: 'The verification options were malformed.',
167
+ possibleCauses: [
168
+ 'toleranceSeconds is negative or non-finite.',
169
+ 'maxBodyBytes is not a positive safe integer.',
170
+ 'The now function is not callable.',
171
+ ],
172
+ suggestions: [
173
+ 'Check toleranceSeconds is a non-negative finite number.',
174
+ 'Check maxBodyBytes is a positive safe integer.',
175
+ 'Check that now is a function returning epoch seconds.',
176
+ ],
177
+ },
178
+ 'invalid-input': {
179
+ summary: 'The request or header input was malformed.',
180
+ possibleCauses: [
181
+ 'The header input was not a Headers, tuple list, or record.',
182
+ 'A header value contained illegal characters.',
183
+ 'The input object was null or undefined.',
184
+ ],
185
+ suggestions: [
186
+ 'Ensure headers are provided as a Headers, tuple list, or plain record.',
187
+ 'Check for null or undefined header values.',
188
+ 'Validate header input before calling verify.',
189
+ ],
190
+ },
191
+ 'body-consumed': {
192
+ summary: 'The Request body was already read before verification.',
193
+ possibleCauses: [
194
+ 'A middleware or handler read the body before calling verifyRequest.',
195
+ 'The same Request object was processed twice.',
196
+ ],
197
+ suggestions: [
198
+ 'Call verifyRequest before any other body reads.',
199
+ 'Use createVerifier with captured raw bytes for multi-stage processing.',
200
+ 'Clone the Request if multiple consumers need the body.',
201
+ ],
202
+ },
203
+ 'body-read-failed': {
204
+ summary: 'The request body stream could not be read.',
205
+ possibleCauses: [
206
+ 'The client disconnected mid-body.',
207
+ 'A platform streaming error occurred.',
208
+ 'The body was locked by another consumer.',
209
+ ],
210
+ suggestions: [
211
+ 'Check client connection stability.',
212
+ 'Retry the request if the failure is transient.',
213
+ 'Inspect platform logs for streaming errors.',
214
+ ],
215
+ },
216
+ 'crypto-unavailable': {
217
+ summary: 'Web Crypto is not available in this environment.',
218
+ possibleCauses: [
219
+ 'The runtime does not provide globalThis.crypto.subtle.',
220
+ 'The environment is not Node 22+ or a compatible Workers runtime.',
221
+ ],
222
+ suggestions: [
223
+ 'Ensure the runtime is Node 22+ or a Workers-compatible environment.',
224
+ 'Check that crypto.subtle is available at global scope.',
225
+ 'Update the runtime if it is below the minimum supported version.',
226
+ ],
227
+ },
228
+ 'internal': {
229
+ summary: 'An unexpected internal error occurred.',
230
+ possibleCauses: [
231
+ 'An unhandled exception in the verification pipeline.',
232
+ 'A platform-specific failure in cryptographic operations.',
233
+ ],
234
+ suggestions: [
235
+ 'Report this issue with the SDK version and runtime details.',
236
+ 'Retry the request if the failure may be transient.',
237
+ 'Check for known issues in the SDK release notes.',
238
+ ],
239
+ },
240
+ };
241
+ const PROVIDER_DETAIL = {
242
+ vercel: {
243
+ expectedHeaders: ['x-vercel-signature'],
244
+ grammar: 'Exactly 40 hexadecimal digits encoding HMAC-SHA1 over exact raw body bytes; no timestamp or identity extraction.',
245
+ },
246
+ fal: {
247
+ expectedHeaders: ['x-fal-webhook-signature', 'x-fal-webhook-request-id', 'x-fal-webhook-user-id', 'x-fal-webhook-timestamp'],
248
+ grammar: 'Exactly 128 hexadecimal signature digits; visible ASCII request and user IDs excluding commas; canonical nonnegative integer seconds. Ed25519 authenticates request ID, user ID, timestamp and the lowercase SHA256 raw-body digest. Static trusted raw public keys and exact expected user ID are required.',
249
+ },
250
+ stripe: {
251
+ expectedHeaders: ['Stripe-Signature'],
252
+ grammar: 'Comma-separated key=value pairs: t=<unix-seconds>,v1=<hex-signature>[,v1=<hex-signature>]',
253
+ },
254
+ github: {
255
+ expectedHeaders: ['X-Hub-Signature-256'],
256
+ grammar: 'sha256=<64 hexadecimal digits; letter case is ignored>',
257
+ },
258
+ shopify: {
259
+ expectedHeaders: ['X-Shopify-Hmac-Sha256'],
260
+ grammar: 'Canonical Base64-encoded HMAC-SHA256 signature',
261
+ },
262
+ 'standard-webhooks': {
263
+ expectedHeaders: ['webhook-id', 'webhook-timestamp', 'webhook-signature'],
264
+ grammar: 'Space-delimited list of v1,<base64-signature> tokens',
265
+ },
266
+ clerk: {
267
+ expectedHeaders: ['svix-id', 'svix-timestamp', 'svix-signature'],
268
+ grammar: 'Space-delimited list of v1,<base64-signature> tokens',
269
+ },
270
+ svix: {
271
+ expectedHeaders: ['svix-id', 'svix-timestamp', 'svix-signature', 'webhook-id', 'webhook-timestamp', 'webhook-signature'],
272
+ grammar: 'Space-delimited list of v1,<base64-signature> tokens (branded or canonical family)',
273
+ },
274
+ razorpay: {
275
+ expectedHeaders: ['X-Razorpay-Signature'],
276
+ grammar: 'A single 64-digit hexadecimal HMAC-SHA256 signature over the raw body',
277
+ },
278
+ paddle: {
279
+ expectedHeaders: ['Paddle-Signature'],
280
+ grammar: 'Semicolon-separated ts=<unix-seconds>;h1=<64 hexadecimal digits>, with repeated h1 allowed',
281
+ },
282
+ 'lemon-squeezy': {
283
+ expectedHeaders: ['X-Signature'],
284
+ grammar: 'A single 64-digit hexadecimal HMAC-SHA256 signature over the raw body',
285
+ },
286
+ 'dodo-payments': {
287
+ expectedHeaders: ['webhook-id', 'webhook-timestamp', 'webhook-signature'],
288
+ grammar: 'Space-delimited list of v1,<base64-signature> tokens over id.timestamp.body',
289
+ },
290
+ gitlab: {
291
+ expectedHeaders: ['webhook-id', 'webhook-timestamp', 'webhook-signature'],
292
+ grammar: 'Signing-token mode: space-delimited v1,<base64-signature> tokens; no X-Gitlab-Token fallback',
293
+ },
294
+ replicate: {
295
+ expectedHeaders: ['webhook-id', 'webhook-timestamp', 'webhook-signature'],
296
+ grammar: 'Space-delimited list of v1,<base64-signature> tokens over id.timestamp.body',
297
+ },
298
+ workos: {
299
+ expectedHeaders: ['WorkOS-Signature'],
300
+ grammar: 'Comma-separated t=<unix-milliseconds>,v1=<64 hexadecimal digits>; one t, repeated valid v1 allowed',
301
+ },
302
+ sentry: {
303
+ expectedHeaders: ['Sentry-Hook-Signature'],
304
+ grammar: 'Sentry App mode: a single bare 64-digit hexadecimal HMAC-SHA256 signature over the raw body',
305
+ },
306
+ doppler: {
307
+ expectedHeaders: ['X-Doppler-Signature'],
308
+ grammar: 'Signed mode: sha256=<64 hexadecimal digits> over the raw body; no Basic/Bearer fallback',
309
+ },
310
+ linear: {
311
+ expectedHeaders: ['Linear-Signature'],
312
+ grammar: 'A single bare 64-digit hexadecimal HMAC-SHA256 signature over exact raw body bytes. Signature authentication only: body claims are not extracted and unsigned header timestamps do not establish freshness.',
313
+ },
314
+ sanity: {
315
+ expectedHeaders: ['sanity-webhook-signature'],
316
+ grammar: 'Exactly t=<unix-milliseconds>,v1=<43 canonical unpadded Base64url characters>; one of each field, no whitespace',
317
+ },
318
+ grafana: {
319
+ expectedHeaders: [],
320
+ grammar: 'Configured signature header: 64 hexadecimal digits. Body mode signs raw bytes; timestamped mode also requires the configured timestamp header with canonical Unix seconds and signs timestamp:body.',
321
+ },
322
+ polar: {
323
+ expectedHeaders: ['webhook-id', 'webhook-timestamp', 'webhook-signature'],
324
+ grammar: 'Space-delimited v1,<base64-signature> tokens over id.timestamp.body; current or legacy secretMode is trusted application configuration, never detected from a request.',
325
+ },
326
+ };
327
+ function getVerificationGuidance(reason) {
328
+ return VERIFICATION_GUIDANCE[reason];
329
+ }
330
+ function getSetupGuidance(code) {
331
+ return SETUP_GUIDANCE[code];
332
+ }
333
+ function getProviderDetail(provider) {
334
+ return PROVIDER_DETAIL[provider];
335
+ }
336
+ function isVerificationCode(code) {
337
+ return typeof code === 'string' && Object.hasOwn(VERIFICATION_GUIDANCE, code);
338
+ }
339
+ function isSetupCode(code) {
340
+ return typeof code === 'string' && Object.hasOwn(SETUP_GUIDANCE, code);
341
+ }
@@ -0,0 +1,19 @@
1
+ import type { HooklatchErrorCode, Provider, VerificationFailureReason } from '../types.cjs';
2
+ import type { DiagnosticCode } from './types.cjs';
3
+ /** Static guidance for verification failure reasons. */
4
+ interface Guidance {
5
+ readonly summary: string;
6
+ readonly possibleCauses: readonly string[];
7
+ readonly suggestions: readonly string[];
8
+ }
9
+ /** Provider-specific verbose detail: expected headers and grammar. */
10
+ interface ProviderDetail {
11
+ readonly expectedHeaders: readonly string[];
12
+ readonly grammar: string;
13
+ }
14
+ export declare function getVerificationGuidance(reason: VerificationFailureReason): Guidance;
15
+ export declare function getSetupGuidance(code: HooklatchErrorCode): Guidance;
16
+ export declare function getProviderDetail(provider: Provider): ProviderDetail | undefined;
17
+ export declare function isVerificationCode(code: DiagnosticCode): code is VerificationFailureReason;
18
+ export declare function isSetupCode(code: DiagnosticCode): code is HooklatchErrorCode;
19
+ export {};
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.diagnose = diagnose;
4
+ const errors_js_1 = require("../errors.cjs");
5
+ const index_js_1 = require("../providers/index.cjs");
6
+ const catalog_js_1 = require("./catalog.cjs");
7
+ function isRecord(value) {
8
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
9
+ return false;
10
+ const prototype = Object.getPrototypeOf(value);
11
+ return prototype === null || prototype === Object.prototype;
12
+ }
13
+ function isProvider(value) {
14
+ return typeof value === 'string' && index_js_1.SUPPORTED_PROVIDERS.some((provider) => provider === value);
15
+ }
16
+ function isBoolean(value) { return typeof value === 'boolean'; }
17
+ function validateProvider(provider) {
18
+ if (provider === undefined)
19
+ return undefined;
20
+ if (isProvider(provider)) {
21
+ return provider;
22
+ }
23
+ throw new errors_js_1.HooklatchError('invalid-input', 'Invalid provider name.');
24
+ }
25
+ function normalizeOptions(options) {
26
+ if (!isRecord(options) || (options.verbose !== undefined && !isBoolean(options.verbose))) {
27
+ throw new errors_js_1.HooklatchError('invalid-input', 'Invalid diagnostic options.');
28
+ }
29
+ const provider = validateProvider(options.provider);
30
+ return provider !== undefined
31
+ ? { provider, verbose: options.verbose === true }
32
+ : { verbose: options.verbose === true };
33
+ }
34
+ function buildDiagnostic(code, kind, guidance, provider, detail) {
35
+ const result = {
36
+ code,
37
+ kind,
38
+ summary: guidance.summary,
39
+ possibleCauses: [...guidance.possibleCauses],
40
+ suggestions: [...guidance.suggestions],
41
+ };
42
+ if (provider !== undefined) {
43
+ Object.assign(result, { provider });
44
+ }
45
+ if (detail !== undefined) {
46
+ Object.assign(result, { detail: { expectedHeaders: [...detail.expectedHeaders], grammar: detail.grammar } });
47
+ }
48
+ return result;
49
+ }
50
+ function diagnoseValidated(input, options) {
51
+ if (input instanceof errors_js_1.HooklatchError) {
52
+ const code = input.code;
53
+ if (!(0, catalog_js_1.isSetupCode)(code))
54
+ throw new errors_js_1.HooklatchError('invalid-input', 'Invalid diagnostic input.');
55
+ const normalized = options !== undefined ? normalizeOptions(options) : undefined;
56
+ const provider = normalized?.provider;
57
+ const verbose = normalized?.verbose;
58
+ const guidance = (0, catalog_js_1.getSetupGuidance)(code);
59
+ if (guidance === undefined) {
60
+ throw new errors_js_1.HooklatchError('invalid-input', 'Invalid diagnostic input.');
61
+ }
62
+ const detail = provider !== undefined && verbose === true ? (0, catalog_js_1.getProviderDetail)(provider) : undefined;
63
+ return buildDiagnostic(code, 'setup', guidance, provider, detail);
64
+ }
65
+ if (!isRecord(input)) {
66
+ throw new errors_js_1.HooklatchError('invalid-input', 'Invalid diagnostic input.');
67
+ }
68
+ const { ok, reason: code, provider: failureProvider } = input;
69
+ if (ok !== false || !(0, catalog_js_1.isVerificationCode)(code) || !isProvider(failureProvider)) {
70
+ throw new errors_js_1.HooklatchError('invalid-input', 'Invalid diagnostic input.');
71
+ }
72
+ const normalized = options !== undefined ? normalizeOptions(options) : undefined;
73
+ if (normalized?.provider !== undefined && normalized.provider !== failureProvider) {
74
+ throw new errors_js_1.HooklatchError('invalid-input', 'Provider mismatch.');
75
+ }
76
+ const provider = failureProvider ?? normalized?.provider;
77
+ const verbose = normalized?.verbose;
78
+ const guidance = (0, catalog_js_1.getVerificationGuidance)(code);
79
+ const detail = provider !== undefined && verbose === true ? (0, catalog_js_1.getProviderDetail)(provider) : undefined;
80
+ return buildDiagnostic(code, 'verification', guidance, provider, detail);
81
+ }
82
+ function diagnose(input, options) {
83
+ try {
84
+ return diagnoseValidated(input, options);
85
+ }
86
+ catch {
87
+ // Untrusted accessors/proxies may throw; their messages must not escape.
88
+ throw new errors_js_1.HooklatchError('invalid-input', 'Invalid diagnostic input.');
89
+ }
90
+ }
@@ -0,0 +1,5 @@
1
+ import { HooklatchError } from '../errors.cjs';
2
+ import type { VerificationFailure } from '../types.cjs';
3
+ import type { Diagnostic, DiagnosticOptions } from './types.cjs';
4
+ export declare function diagnose(input: VerificationFailure | HooklatchError, options?: DiagnosticOptions): Diagnostic;
5
+ export type { Diagnostic, DiagnosticOptions, DiagnosticCode } from './types.cjs';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,20 @@
1
+ import type { HooklatchErrorCode, Provider, VerificationFailureReason } from '../types.cjs';
2
+ /** Stable diagnostic codes; guidance text is intended for people. */
3
+ export type DiagnosticCode = VerificationFailureReason | HooklatchErrorCode;
4
+ export interface DiagnosticOptions {
5
+ readonly provider?: Provider;
6
+ readonly verbose?: boolean;
7
+ }
8
+ /** Only allowlisted guidance and validated provider names enter this output. */
9
+ export interface Diagnostic {
10
+ readonly code: DiagnosticCode;
11
+ readonly kind: 'verification' | 'setup';
12
+ readonly provider?: Provider;
13
+ readonly summary: string;
14
+ readonly possibleCauses: readonly string[];
15
+ readonly suggestions: readonly string[];
16
+ readonly detail?: {
17
+ readonly expectedHeaders: readonly string[];
18
+ readonly grammar: string;
19
+ };
20
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HooklatchError = void 0;
4
+ /** Operational error. Messages deliberately exclude request and credential data. */
5
+ class HooklatchError extends Error {
6
+ code;
7
+ constructor(code, message) {
8
+ super(message);
9
+ this.name = 'HooklatchError';
10
+ this.code = code;
11
+ }
12
+ }
13
+ exports.HooklatchError = HooklatchError;
@@ -0,0 +1,6 @@
1
+ import type { HooklatchErrorCode } from './types.cjs';
2
+ /** Operational error. Messages deliberately exclude request and credential data. */
3
+ export declare class HooklatchError extends Error {
4
+ readonly code: HooklatchErrorCode;
5
+ constructor(code: HooklatchErrorCode, message: string);
6
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HooklatchError = exports.createVerifier = exports.verifyRequest = exports.verify = void 0;
4
+ var core_js_1 = require("./core.cjs");
5
+ Object.defineProperty(exports, "verify", { enumerable: true, get: function () { return core_js_1.verify; } });
6
+ Object.defineProperty(exports, "verifyRequest", { enumerable: true, get: function () { return core_js_1.verifyRequest; } });
7
+ Object.defineProperty(exports, "createVerifier", { enumerable: true, get: function () { return core_js_1.createVerifier; } });
8
+ var errors_js_1 = require("./errors.cjs");
9
+ Object.defineProperty(exports, "HooklatchError", { enumerable: true, get: function () { return errors_js_1.HooklatchError; } });
@@ -0,0 +1,3 @@
1
+ export { verify, verifyRequest, createVerifier } from './core.cjs';
2
+ export { HooklatchError } from './errors.cjs';
3
+ export type { Provider, HeaderInput, WebhookRequest, VerifyOptions, FalVerifyOptions, GrafanaOptions, PolarOptions, IdentityField, EventIdentity, VerificationFailureReason, VerificationSuccess, VerificationFailure, VerificationResult, HooklatchErrorCode, FailureDetails, } from './types.cjs';
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readBody = readBody;
4
+ const errors_js_1 = require("../errors.cjs");
5
+ /** null means size limit exceeded. Reads actual chunks, not trusted length claims. */
6
+ async function readBody(request, maxBodyBytes) {
7
+ if (request.bodyUsed || request.body?.locked)
8
+ throw new errors_js_1.HooklatchError('body-consumed', 'Request body has already been consumed.');
9
+ if (!request.body)
10
+ return new Uint8Array();
11
+ let reader;
12
+ try {
13
+ reader = request.body.getReader();
14
+ }
15
+ catch {
16
+ throw new errors_js_1.HooklatchError('body-read-failed', 'Unable to read request body.');
17
+ }
18
+ // Bound bookkeeping as well as byte storage: a chunk array can grow very
19
+ // large even for a tiny body, and spreading it exceeds JS argument limits.
20
+ let output = new Uint8Array(Math.min(maxBodyBytes, 8192));
21
+ let size = 0;
22
+ try {
23
+ while (true) {
24
+ const chunk = await reader.read();
25
+ if (chunk.done)
26
+ break;
27
+ if (!(chunk.value instanceof Uint8Array))
28
+ throw new Error('Invalid byte stream');
29
+ size += chunk.value.byteLength;
30
+ if (size > maxBodyBytes) {
31
+ // Cancellation must not hold the response hostage to a stalled producer.
32
+ void reader.cancel().catch(() => undefined);
33
+ return null;
34
+ }
35
+ if (size > output.byteLength) {
36
+ const grown = new Uint8Array(Math.min(maxBodyBytes, Math.max(size, output.byteLength * 2)));
37
+ grown.set(output);
38
+ output = grown;
39
+ }
40
+ output.set(chunk.value, size - chunk.value.byteLength);
41
+ }
42
+ return output.slice(0, size);
43
+ }
44
+ catch {
45
+ throw new errors_js_1.HooklatchError('body-read-failed', 'Unable to read request body.');
46
+ }
47
+ finally {
48
+ reader.releaseLock();
49
+ }
50
+ }
@@ -0,0 +1,2 @@
1
+ /** null means size limit exceeded. Reads actual chunks, not trusted length claims. */
2
+ export declare function readBody(request: Request, maxBodyBytes: number): Promise<Uint8Array | null>;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.utf8 = utf8;
4
+ exports.concatBytes = concatBytes;
5
+ exports.decodeHex = decodeHex;
6
+ exports.decodeBase64 = decodeBase64;
7
+ function utf8(value) { return new TextEncoder().encode(value); }
8
+ function concatBytes(...chunks) {
9
+ const output = new Uint8Array(chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0));
10
+ let offset = 0;
11
+ for (const chunk of chunks) {
12
+ output.set(chunk, offset);
13
+ offset += chunk.byteLength;
14
+ }
15
+ return output;
16
+ }
17
+ function decodeHex(value) {
18
+ if (value.length % 2 !== 0 || !/^[\da-f]*$/i.test(value))
19
+ return null;
20
+ const output = new Uint8Array(value.length / 2);
21
+ for (let i = 0; i < output.length; i += 1)
22
+ output[i] = Number.parseInt(value.slice(i * 2, i * 2 + 2), 16);
23
+ return output;
24
+ }
25
+ function decodeBase64(value) {
26
+ if (!/^[A-Za-z0-9+/]*={0,2}$/.test(value))
27
+ return null;
28
+ const unpadded = value.replace(/=+$/, '');
29
+ if (unpadded.length % 4 === 1)
30
+ return null;
31
+ const padded = unpadded + '='.repeat((4 - unpadded.length % 4) % 4);
32
+ if (value.includes('=') && value !== padded)
33
+ return null;
34
+ try {
35
+ const binary = atob(padded);
36
+ if (btoa(binary) !== padded)
37
+ return null;
38
+ return Uint8Array.from(binary, (char) => char.charCodeAt(0));
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
@@ -0,0 +1,4 @@
1
+ export declare function utf8(value: string): Uint8Array;
2
+ export declare function concatBytes(...chunks: Uint8Array[]): Uint8Array;
3
+ export declare function decodeHex(value: string): Uint8Array | null;
4
+ export declare function decodeBase64(value: string): Uint8Array | null;