@siglo/crypto 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +123 -2
  3. package/dist/cipher/aes-gcm.d.ts +43 -0
  4. package/dist/cipher/aes-gcm.d.ts.map +1 -0
  5. package/dist/cipher/aes-gcm.js +152 -0
  6. package/dist/cipher/aes-gcm.js.map +1 -0
  7. package/dist/cipher/decrypt-step.d.ts +13 -0
  8. package/dist/cipher/decrypt-step.d.ts.map +1 -0
  9. package/dist/cipher/decrypt-step.js +113 -0
  10. package/dist/cipher/decrypt-step.js.map +1 -0
  11. package/dist/cipher/encrypt-step.d.ts +13 -0
  12. package/dist/cipher/encrypt-step.d.ts.map +1 -0
  13. package/dist/cipher/encrypt-step.js +84 -0
  14. package/dist/cipher/encrypt-step.js.map +1 -0
  15. package/dist/cipher/key-ring.d.ts +24 -0
  16. package/dist/cipher/key-ring.d.ts.map +1 -0
  17. package/dist/cipher/key-ring.js +67 -0
  18. package/dist/cipher/key-ring.js.map +1 -0
  19. package/dist/index.d.ts +19 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +35 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/redaction/mask-step.d.ts +28 -0
  24. package/dist/redaction/mask-step.d.ts.map +1 -0
  25. package/dist/redaction/mask-step.js +85 -0
  26. package/dist/redaction/mask-step.js.map +1 -0
  27. package/dist/redaction/paths.d.ts +28 -0
  28. package/dist/redaction/paths.d.ts.map +1 -0
  29. package/dist/redaction/paths.js +149 -0
  30. package/dist/redaction/paths.js.map +1 -0
  31. package/dist/registry.d.ts +14 -0
  32. package/dist/registry.d.ts.map +1 -0
  33. package/dist/registry.js +44 -0
  34. package/dist/registry.js.map +1 -0
  35. package/dist/types.d.ts +115 -0
  36. package/dist/types.d.ts.map +1 -0
  37. package/dist/types.js +3 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/webhooks/dedup.d.ts +24 -0
  40. package/dist/webhooks/dedup.d.ts.map +1 -0
  41. package/dist/webhooks/dedup.js +69 -0
  42. package/dist/webhooks/dedup.js.map +1 -0
  43. package/dist/webhooks/protocols/base.d.ts +15 -0
  44. package/dist/webhooks/protocols/base.d.ts.map +1 -0
  45. package/dist/webhooks/protocols/base.js +42 -0
  46. package/dist/webhooks/protocols/base.js.map +1 -0
  47. package/dist/webhooks/protocols/generic-hmac.d.ts +16 -0
  48. package/dist/webhooks/protocols/generic-hmac.d.ts.map +1 -0
  49. package/dist/webhooks/protocols/generic-hmac.js +68 -0
  50. package/dist/webhooks/protocols/generic-hmac.js.map +1 -0
  51. package/dist/webhooks/protocols/github.d.ts +9 -0
  52. package/dist/webhooks/protocols/github.d.ts.map +1 -0
  53. package/dist/webhooks/protocols/github.js +49 -0
  54. package/dist/webhooks/protocols/github.js.map +1 -0
  55. package/dist/webhooks/protocols/shopify.d.ts +9 -0
  56. package/dist/webhooks/protocols/shopify.d.ts.map +1 -0
  57. package/dist/webhooks/protocols/shopify.js +37 -0
  58. package/dist/webhooks/protocols/shopify.js.map +1 -0
  59. package/dist/webhooks/protocols/slack.d.ts +9 -0
  60. package/dist/webhooks/protocols/slack.d.ts.map +1 -0
  61. package/dist/webhooks/protocols/slack.js +52 -0
  62. package/dist/webhooks/protocols/slack.js.map +1 -0
  63. package/dist/webhooks/protocols/stripe.d.ts +9 -0
  64. package/dist/webhooks/protocols/stripe.d.ts.map +1 -0
  65. package/dist/webhooks/protocols/stripe.js +56 -0
  66. package/dist/webhooks/protocols/stripe.js.map +1 -0
  67. package/dist/webhooks/protocols/svix.d.ts +9 -0
  68. package/dist/webhooks/protocols/svix.d.ts.map +1 -0
  69. package/dist/webhooks/protocols/svix.js +85 -0
  70. package/dist/webhooks/protocols/svix.js.map +1 -0
  71. package/dist/webhooks/timing.d.ts +6 -0
  72. package/dist/webhooks/timing.d.ts.map +1 -0
  73. package/dist/webhooks/timing.js +25 -0
  74. package/dist/webhooks/timing.js.map +1 -0
  75. package/dist/webhooks/verify-step.d.ts +25 -0
  76. package/dist/webhooks/verify-step.d.ts.map +1 -0
  77. package/dist/webhooks/verify-step.js +351 -0
  78. package/dist/webhooks/verify-step.js.map +1 -0
  79. package/package.json +52 -4
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { WebhookDedupStore } from '../types';
2
+ /**
3
+ * Computes a deterministic SHA-256 deduplication key for a webhook delivery attempt.
4
+ */
5
+ export declare function createDedupKey(provider: string, signature: string, timestamp?: number): string;
6
+ /**
7
+ * High-performance in-memory bucketed ring buffer for intra-window webhook deduplication.
8
+ * Eliminates per-key eviction sweeps by grouping keys into sliding time buckets with O(1) pruning.
9
+ */
10
+ export declare class InMemoryNonceStore implements WebhookDedupStore {
11
+ private buckets;
12
+ private allKeys;
13
+ private bucketDurationMs;
14
+ constructor(bucketDurationSeconds?: number);
15
+ private pruneExpired;
16
+ /**
17
+ * Atomically checks and records a nonce/signature key.
18
+ * Returns true if successfully claimed (first time seen), or false if already seen within TTL.
19
+ */
20
+ claim(key: string, ttlSeconds: number): boolean;
21
+ clear(): void;
22
+ get size(): number;
23
+ }
24
+ //# sourceMappingURL=dedup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedup.d.ts","sourceRoot":"","sources":["../../src/webhooks/dedup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAKR;AAOD;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,iBAAiB;IAC1D,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,gBAAgB,CAAS;gBAErB,qBAAqB,GAAE,MAAW;IAI9C,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO;IAuB/C,KAAK,IAAI,IAAI;IAKb,IAAI,IAAI,IAAI,MAAM,CAGjB;CACF"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.InMemoryNonceStore = void 0;
7
+ exports.createDedupKey = createDedupKey;
8
+ const node_crypto_1 = __importDefault(require("node:crypto"));
9
+ /**
10
+ * Computes a deterministic SHA-256 deduplication key for a webhook delivery attempt.
11
+ */
12
+ function createDedupKey(provider, signature, timestamp) {
13
+ return node_crypto_1.default
14
+ .createHash('sha256')
15
+ .update(`${provider}:${timestamp ?? ''}:${signature}`)
16
+ .digest('hex');
17
+ }
18
+ /**
19
+ * High-performance in-memory bucketed ring buffer for intra-window webhook deduplication.
20
+ * Eliminates per-key eviction sweeps by grouping keys into sliding time buckets with O(1) pruning.
21
+ */
22
+ class InMemoryNonceStore {
23
+ buckets = [];
24
+ allKeys = new Set();
25
+ bucketDurationMs;
26
+ constructor(bucketDurationSeconds = 60) {
27
+ this.bucketDurationMs = bucketDurationSeconds * 1000;
28
+ }
29
+ pruneExpired(now) {
30
+ while (this.buckets.length > 0 && this.buckets[0].expiresAt <= now) {
31
+ const expired = this.buckets.shift();
32
+ for (const k of expired.keys) {
33
+ this.allKeys.delete(k);
34
+ }
35
+ }
36
+ }
37
+ /**
38
+ * Atomically checks and records a nonce/signature key.
39
+ * Returns true if successfully claimed (first time seen), or false if already seen within TTL.
40
+ */
41
+ claim(key, ttlSeconds) {
42
+ const now = Date.now();
43
+ this.pruneExpired(now);
44
+ if (this.allKeys.has(key)) {
45
+ return false; // Duplicate / replay within TTL
46
+ }
47
+ const expiresAt = now + ttlSeconds * 1000;
48
+ this.allKeys.add(key);
49
+ // Find bucket within duration window or insert a new one
50
+ let bucket = this.buckets.find(b => Math.abs(b.expiresAt - expiresAt) < this.bucketDurationMs);
51
+ if (!bucket) {
52
+ bucket = { expiresAt, keys: new Set() };
53
+ this.buckets.push(bucket);
54
+ this.buckets.sort((a, b) => a.expiresAt - b.expiresAt);
55
+ }
56
+ bucket.keys.add(key);
57
+ return true;
58
+ }
59
+ clear() {
60
+ this.buckets = [];
61
+ this.allKeys.clear();
62
+ }
63
+ get size() {
64
+ this.pruneExpired(Date.now());
65
+ return this.allKeys.size;
66
+ }
67
+ }
68
+ exports.InMemoryNonceStore = InMemoryNonceStore;
69
+ //# sourceMappingURL=dedup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedup.js","sourceRoot":"","sources":["../../src/webhooks/dedup.ts"],"names":[],"mappings":";;;;;;AAMA,wCASC;AAfD,8DAAiC;AAGjC;;GAEG;AACH,SAAgB,cAAc,CAC5B,QAAgB,EAChB,SAAiB,EACjB,SAAkB;IAElB,OAAO,qBAAM;SACV,UAAU,CAAC,QAAQ,CAAC;SACpB,MAAM,CAAC,GAAG,QAAQ,IAAI,SAAS,IAAI,EAAE,IAAI,SAAS,EAAE,CAAC;SACrD,MAAM,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC;AAOD;;;GAGG;AACH,MAAa,kBAAkB;IACrB,OAAO,GAAa,EAAE,CAAC;IACvB,OAAO,GAAgB,IAAI,GAAG,EAAE,CAAC;IACjC,gBAAgB,CAAS;IAEjC,YAAY,wBAAgC,EAAE;QAC5C,IAAI,CAAC,gBAAgB,GAAG,qBAAqB,GAAG,IAAI,CAAC;IACvD,CAAC;IAEO,YAAY,CAAC,GAAW;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,EAAE,CAAC;YACnE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAG,CAAC;YACtC,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAW,EAAE,UAAkB;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAEvB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,KAAK,CAAC,CAAC,gCAAgC;QAChD,CAAC;QAED,MAAM,SAAS,GAAG,GAAG,GAAG,UAAU,GAAG,IAAI,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtB,yDAAyD;QACzD,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC/F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAErB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAED,IAAI,IAAI;QACN,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF;AAtDD,gDAsDC"}
@@ -0,0 +1,15 @@
1
+ import { WebhookProtocol, WebhookProtocolVerificationParams, ParsedWebhookHeaders } from '../../types';
2
+ export { WebhookProtocol, WebhookProtocolVerificationParams, ParsedWebhookHeaders };
3
+ /**
4
+ * Normalizes headers record by converting all keys to lowercase.
5
+ */
6
+ export declare function normalizeHeaders(headers?: Record<string, string | string[] | undefined>): Record<string, string>;
7
+ /**
8
+ * Asserts whether a timestamp is within the allowed clock drift tolerance.
9
+ */
10
+ export declare function isTimestampValid(timestamp: number | undefined, toleranceSeconds?: number, nowSeconds?: number): boolean;
11
+ /**
12
+ * Extracts payload as UTF-8 string.
13
+ */
14
+ export declare function payloadToString(payload: string | Buffer): string;
15
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/webhooks/protocols/base.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,eAAe,EACf,iCAAiC,EACjC,oBAAoB,EACrB,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAM,GAC1D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,gBAAgB,GAAE,MAAY,EAC9B,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAaT;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAKhE"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeHeaders = normalizeHeaders;
4
+ exports.isTimestampValid = isTimestampValid;
5
+ exports.payloadToString = payloadToString;
6
+ /**
7
+ * Normalizes headers record by converting all keys to lowercase.
8
+ */
9
+ function normalizeHeaders(headers = {}) {
10
+ const normalized = {};
11
+ for (const [key, val] of Object.entries(headers)) {
12
+ if (val !== undefined && val !== null) {
13
+ normalized[key.toLowerCase()] = Array.isArray(val) ? val.join(',') : String(val);
14
+ }
15
+ }
16
+ return normalized;
17
+ }
18
+ /**
19
+ * Asserts whether a timestamp is within the allowed clock drift tolerance.
20
+ */
21
+ function isTimestampValid(timestamp, toleranceSeconds = 300, nowSeconds) {
22
+ if (timestamp === undefined || Number.isNaN(timestamp) || toleranceSeconds <= 0) {
23
+ return true;
24
+ }
25
+ // Normalize millisecond timestamp to seconds if needed
26
+ let ts = timestamp;
27
+ if (ts > 1e11) {
28
+ ts = Math.floor(ts / 1000);
29
+ }
30
+ const now = nowSeconds !== undefined ? nowSeconds : Math.floor(Date.now() / 1000);
31
+ return Math.abs(now - ts) <= toleranceSeconds;
32
+ }
33
+ /**
34
+ * Extracts payload as UTF-8 string.
35
+ */
36
+ function payloadToString(payload) {
37
+ if (typeof payload === 'string') {
38
+ return payload;
39
+ }
40
+ return payload.toString('utf8');
41
+ }
42
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/webhooks/protocols/base.ts"],"names":[],"mappings":";;AAeA,4CAUC;AAKD,4CAiBC;AAKD,0CAKC;AA7CD;;GAEG;AACH,SAAgB,gBAAgB,CAC9B,UAAyD,EAAE;IAE3D,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACtC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAC9B,SAA6B,EAC7B,mBAA2B,GAAG,EAC9B,UAAmB;IAEnB,IAAI,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,gBAAgB,IAAI,CAAC,EAAE,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uDAAuD;IACvD,IAAI,EAAE,GAAG,SAAS,CAAC;IACnB,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;QACd,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAClF,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,IAAI,gBAAgB,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,OAAwB;IACtD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { WebhookProtocol, WebhookProtocolVerificationParams, ParsedWebhookHeaders } from '../../types';
2
+ export interface GenericHmacProtocolOptions {
3
+ algorithm?: 'sha256' | 'sha512' | 'sha1';
4
+ encoding?: 'hex' | 'base64';
5
+ }
6
+ export declare class GenericHmacWebhookProtocol implements WebhookProtocol {
7
+ readonly name = "generic-hmac";
8
+ private defaultAlgorithm;
9
+ private defaultEncoding?;
10
+ constructor(options?: GenericHmacProtocolOptions);
11
+ parseHeaders(headers?: Record<string, string | string[] | undefined>, signatureHeader?: string): ParsedWebhookHeaders;
12
+ formatSignedPayload(rawBody: string | Buffer, timestamp?: number): string | Buffer;
13
+ verify({ secret, rawPayload, headers, signatureHeader, toleranceSeconds, clock, algorithm: paramAlgorithm }: WebhookProtocolVerificationParams): boolean;
14
+ }
15
+ export declare const genericHmacProtocol: GenericHmacWebhookProtocol;
16
+ //# sourceMappingURL=generic-hmac.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generic-hmac.d.ts","sourceRoot":"","sources":["../../../src/webhooks/protocols/generic-hmac.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAIrB,MAAM,WAAW,0BAA0B;IACzC,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACzC,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;CAC7B;AAED,qBAAa,0BAA2B,YAAW,eAAe;IAChE,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,eAAe,CAAC,CAAmB;gBAE/B,OAAO,GAAE,0BAA+B;IAKpD,YAAY,CACV,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAM,EAC3D,eAAe,GAAE,MAAW,GAC3B,oBAAoB;IAmBvB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;IAOlF,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EACf,gBAAsB,EACtB,KAAK,EACL,SAAS,EAAE,cAAc,EAC1B,EAAE,iCAAiC,GAAG,OAAO;CAkC/C;AAED,eAAO,MAAM,mBAAmB,4BAAmC,CAAC"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.genericHmacProtocol = exports.GenericHmacWebhookProtocol = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const timing_1 = require("../timing");
9
+ const base_1 = require("./base");
10
+ class GenericHmacWebhookProtocol {
11
+ name = 'generic-hmac';
12
+ defaultAlgorithm;
13
+ defaultEncoding;
14
+ constructor(options = {}) {
15
+ this.defaultAlgorithm = options.algorithm || 'sha256';
16
+ this.defaultEncoding = options.encoding;
17
+ }
18
+ parseHeaders(headers = {}, signatureHeader = '') {
19
+ const normalized = (0, base_1.normalizeHeaders)(headers);
20
+ const signature = (signatureHeader ||
21
+ normalized['x-signature'] ||
22
+ normalized['signature'] ||
23
+ normalized['x-hub-signature-256'] ||
24
+ '').trim();
25
+ const rawTimestamp = normalized['x-timestamp'] || normalized['timestamp'];
26
+ const timestamp = rawTimestamp ? Number(rawTimestamp) : undefined;
27
+ return {
28
+ timestamp: !Number.isNaN(timestamp) ? timestamp : undefined,
29
+ signatures: signature ? [signature] : []
30
+ };
31
+ }
32
+ formatSignedPayload(rawBody, timestamp) {
33
+ if (timestamp !== undefined) {
34
+ return `${timestamp}.${(0, base_1.payloadToString)(rawBody)}`;
35
+ }
36
+ return rawBody;
37
+ }
38
+ verify({ secret, rawPayload, headers, signatureHeader, toleranceSeconds = 300, clock, algorithm: paramAlgorithm }) {
39
+ const parsed = this.parseHeaders(headers, signatureHeader);
40
+ if (parsed.signatures.length === 0) {
41
+ return false;
42
+ }
43
+ if (parsed.timestamp !== undefined) {
44
+ const nowSec = clock ? Math.floor(clock.now() / 1000) : Math.floor(Date.now() / 1000);
45
+ if (!(0, base_1.isTimestampValid)(parsed.timestamp, toleranceSeconds, nowSec)) {
46
+ return false;
47
+ }
48
+ }
49
+ const algorithm = paramAlgorithm || headers?.$algorithm || this.defaultAlgorithm;
50
+ const signedPayload = this.formatSignedPayload(rawPayload, parsed.timestamp);
51
+ const expectedHex = node_crypto_1.default.createHmac(algorithm, secret).update(signedPayload).digest('hex');
52
+ const expectedBase64 = node_crypto_1.default.createHmac(algorithm, secret).update(signedPayload).digest('base64');
53
+ return parsed.signatures.some(sig => {
54
+ if (this.defaultEncoding === 'base64') {
55
+ return (0, timing_1.timingSafeCompare)(expectedBase64, sig, 'base64');
56
+ }
57
+ if (this.defaultEncoding === 'hex') {
58
+ return (0, timing_1.timingSafeCompare)(expectedHex, sig, 'hex');
59
+ }
60
+ // Auto-detect hex vs base64
61
+ return ((0, timing_1.timingSafeCompare)(expectedHex, sig, 'hex') ||
62
+ (0, timing_1.timingSafeCompare)(expectedBase64, sig, 'base64'));
63
+ });
64
+ }
65
+ }
66
+ exports.GenericHmacWebhookProtocol = GenericHmacWebhookProtocol;
67
+ exports.genericHmacProtocol = new GenericHmacWebhookProtocol();
68
+ //# sourceMappingURL=generic-hmac.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generic-hmac.js","sourceRoot":"","sources":["../../../src/webhooks/protocols/generic-hmac.ts"],"names":[],"mappings":";;;;;;AAAA,8DAAiC;AAMjC,sCAA8C;AAC9C,iCAA6E;AAO7E,MAAa,0BAA0B;IAC5B,IAAI,GAAG,cAAc,CAAC;IACvB,gBAAgB,CAA+B;IAC/C,eAAe,CAAoB;IAE3C,YAAY,UAAsC,EAAE;QAClD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,SAAS,IAAI,QAAQ,CAAC;QACtD,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC;IAC1C,CAAC;IAED,YAAY,CACV,UAAyD,EAAE,EAC3D,kBAA0B,EAAE;QAE5B,MAAM,UAAU,GAAG,IAAA,uBAAgB,EAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,CAChB,eAAe;YACf,UAAU,CAAC,aAAa,CAAC;YACzB,UAAU,CAAC,WAAW,CAAC;YACvB,UAAU,CAAC,qBAAqB,CAAC;YACjC,EAAE,CACH,CAAC,IAAI,EAAE,CAAC;QAET,MAAM,YAAY,GAAG,UAAU,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAElE,OAAO;YACL,SAAS,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YAC3D,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;SACzC,CAAC;IACJ,CAAC;IAED,mBAAmB,CAAC,OAAwB,EAAE,SAAkB;QAC9D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,GAAG,SAAS,IAAI,IAAA,sBAAe,EAAC,OAAO,CAAC,EAAE,CAAC;QACpD,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EACf,gBAAgB,GAAG,GAAG,EACtB,KAAK,EACL,SAAS,EAAE,cAAc,EACS;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAE3D,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YACtF,IAAI,CAAC,IAAA,uBAAgB,EAAC,MAAM,CAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,CAAC;gBAClE,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,cAAc,IAAK,OAAe,EAAE,UAAU,IAAI,IAAI,CAAC,gBAAgB,CAAC;QAC1F,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QAE7E,MAAM,WAAW,GAAG,qBAAM,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7F,MAAM,cAAc,GAAG,qBAAM,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEnG,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAClC,IAAI,IAAI,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;gBACtC,OAAO,IAAA,0BAAiB,EAAC,cAAc,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,IAAI,CAAC,eAAe,KAAK,KAAK,EAAE,CAAC;gBACnC,OAAO,IAAA,0BAAiB,EAAC,WAAW,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;YACpD,CAAC;YACD,4BAA4B;YAC5B,OAAO,CACL,IAAA,0BAAiB,EAAC,WAAW,EAAE,GAAG,EAAE,KAAK,CAAC;gBAC1C,IAAA,0BAAiB,EAAC,cAAc,EAAE,GAAG,EAAE,QAAQ,CAAC,CACjD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAjFD,gEAiFC;AAEY,QAAA,mBAAmB,GAAG,IAAI,0BAA0B,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { WebhookProtocol, WebhookProtocolVerificationParams, ParsedWebhookHeaders } from '../../types';
2
+ export declare class GitHubWebhookProtocol implements WebhookProtocol {
3
+ readonly name = "github";
4
+ parseHeaders(headers?: Record<string, string | string[] | undefined>, signatureHeader?: string): ParsedWebhookHeaders;
5
+ formatSignedPayload(rawBody: string | Buffer): string | Buffer;
6
+ verify({ secret, rawPayload, headers, signatureHeader }: WebhookProtocolVerificationParams): boolean;
7
+ }
8
+ export declare const gitHubProtocol: GitHubWebhookProtocol;
9
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../../src/webhooks/protocols/github.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAIrB,qBAAa,qBAAsB,YAAW,eAAe;IAC3D,QAAQ,CAAC,IAAI,YAAY;IAEzB,YAAY,CACV,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAM,EAC3D,eAAe,GAAE,MAAW,GAC3B,oBAAoB;IAwBvB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM;IAI9D,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EAChB,EAAE,iCAAiC,GAAG,OAAO;CAa/C;AAED,eAAO,MAAM,cAAc,uBAA8B,CAAC"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.gitHubProtocol = exports.GitHubWebhookProtocol = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const timing_1 = require("../timing");
9
+ const base_1 = require("./base");
10
+ class GitHubWebhookProtocol {
11
+ name = 'github';
12
+ parseHeaders(headers = {}, signatureHeader = '') {
13
+ const normalized = (0, base_1.normalizeHeaders)(headers);
14
+ const rawHeader = signatureHeader ||
15
+ normalized['x-hub-signature-256'] ||
16
+ normalized['x-hub-signature'] ||
17
+ '';
18
+ let version = 'sha256';
19
+ let signature = rawHeader.trim();
20
+ if (signature.startsWith('sha256=')) {
21
+ version = 'sha256';
22
+ signature = signature.slice(7);
23
+ }
24
+ else if (signature.startsWith('sha1=')) {
25
+ version = 'sha1';
26
+ signature = signature.slice(5);
27
+ }
28
+ return {
29
+ signatures: signature ? [signature] : [],
30
+ version
31
+ };
32
+ }
33
+ formatSignedPayload(rawBody) {
34
+ return rawBody;
35
+ }
36
+ verify({ secret, rawPayload, headers, signatureHeader }) {
37
+ const parsed = this.parseHeaders(headers, signatureHeader);
38
+ if (parsed.signatures.length === 0) {
39
+ return false;
40
+ }
41
+ const algorithm = parsed.version === 'sha1' ? 'sha1' : 'sha256';
42
+ const payload = this.formatSignedPayload(rawPayload);
43
+ const expected = node_crypto_1.default.createHmac(algorithm, secret).update(payload).digest('hex');
44
+ return parsed.signatures.some(sig => (0, timing_1.timingSafeCompare)(expected, sig, 'hex'));
45
+ }
46
+ }
47
+ exports.GitHubWebhookProtocol = GitHubWebhookProtocol;
48
+ exports.gitHubProtocol = new GitHubWebhookProtocol();
49
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.js","sourceRoot":"","sources":["../../../src/webhooks/protocols/github.ts"],"names":[],"mappings":";;;;;;AAAA,8DAAiC;AAMjC,sCAA8C;AAC9C,iCAA0C;AAE1C,MAAa,qBAAqB;IACvB,IAAI,GAAG,QAAQ,CAAC;IAEzB,YAAY,CACV,UAAyD,EAAE,EAC3D,kBAA0B,EAAE;QAE5B,MAAM,UAAU,GAAG,IAAA,uBAAgB,EAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,eAAe;YAC/B,UAAU,CAAC,qBAAqB,CAAC;YACjC,UAAU,CAAC,iBAAiB,CAAC;YAC7B,EAAE,CAAC;QAEL,IAAI,OAAO,GAAG,QAAQ,CAAC;QACvB,IAAI,SAAS,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;QAEjC,IAAI,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACpC,OAAO,GAAG,QAAQ,CAAC;YACnB,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;aAAM,IAAI,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACzC,OAAO,GAAG,MAAM,CAAC;YACjB,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;QAED,OAAO;YACL,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;YACxC,OAAO;SACR,CAAC;IACJ,CAAC;IAED,mBAAmB,CAAC,OAAwB;QAC1C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EACmB;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAE3D,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,qBAAM,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEpF,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAA,0BAAiB,EAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAChF,CAAC;CACF;AApDD,sDAoDC;AAEY,QAAA,cAAc,GAAG,IAAI,qBAAqB,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { WebhookProtocol, WebhookProtocolVerificationParams, ParsedWebhookHeaders } from '../../types';
2
+ export declare class ShopifyWebhookProtocol implements WebhookProtocol {
3
+ readonly name = "shopify";
4
+ parseHeaders(headers?: Record<string, string | string[] | undefined>, signatureHeader?: string): ParsedWebhookHeaders;
5
+ formatSignedPayload(rawBody: string | Buffer): string | Buffer;
6
+ verify({ secret, rawPayload, headers, signatureHeader }: WebhookProtocolVerificationParams): boolean;
7
+ }
8
+ export declare const shopifyProtocol: ShopifyWebhookProtocol;
9
+ //# sourceMappingURL=shopify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shopify.d.ts","sourceRoot":"","sources":["../../../src/webhooks/protocols/shopify.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAIrB,qBAAa,sBAAuB,YAAW,eAAe;IAC5D,QAAQ,CAAC,IAAI,aAAa;IAE1B,YAAY,CACV,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAM,EAC3D,eAAe,GAAE,MAAW,GAC3B,oBAAoB;IAcvB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM;IAI9D,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EAChB,EAAE,iCAAiC,GAAG,OAAO;CAY/C;AAED,eAAO,MAAM,eAAe,wBAA+B,CAAC"}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.shopifyProtocol = exports.ShopifyWebhookProtocol = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const timing_1 = require("../timing");
9
+ const base_1 = require("./base");
10
+ class ShopifyWebhookProtocol {
11
+ name = 'shopify';
12
+ parseHeaders(headers = {}, signatureHeader = '') {
13
+ const normalized = (0, base_1.normalizeHeaders)(headers);
14
+ const signature = (signatureHeader ||
15
+ normalized['x-shopify-hmac-sha256'] ||
16
+ '').trim();
17
+ return {
18
+ signatures: signature ? [signature] : [],
19
+ version: 'sha256'
20
+ };
21
+ }
22
+ formatSignedPayload(rawBody) {
23
+ return rawBody;
24
+ }
25
+ verify({ secret, rawPayload, headers, signatureHeader }) {
26
+ const parsed = this.parseHeaders(headers, signatureHeader);
27
+ if (parsed.signatures.length === 0) {
28
+ return false;
29
+ }
30
+ const payload = this.formatSignedPayload(rawPayload);
31
+ const expected = node_crypto_1.default.createHmac('sha256', secret).update(payload).digest('base64');
32
+ return parsed.signatures.some(sig => (0, timing_1.timingSafeCompare)(expected, sig, 'base64'));
33
+ }
34
+ }
35
+ exports.ShopifyWebhookProtocol = ShopifyWebhookProtocol;
36
+ exports.shopifyProtocol = new ShopifyWebhookProtocol();
37
+ //# sourceMappingURL=shopify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shopify.js","sourceRoot":"","sources":["../../../src/webhooks/protocols/shopify.ts"],"names":[],"mappings":";;;;;;AAAA,8DAAiC;AAMjC,sCAA8C;AAC9C,iCAA0C;AAE1C,MAAa,sBAAsB;IACxB,IAAI,GAAG,SAAS,CAAC;IAE1B,YAAY,CACV,UAAyD,EAAE,EAC3D,kBAA0B,EAAE;QAE5B,MAAM,UAAU,GAAG,IAAA,uBAAgB,EAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,CAChB,eAAe;YACf,UAAU,CAAC,uBAAuB,CAAC;YACnC,EAAE,CACH,CAAC,IAAI,EAAE,CAAC;QAET,OAAO;YACL,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;YACxC,OAAO,EAAE,QAAQ;SAClB,CAAC;IACJ,CAAC;IAED,mBAAmB,CAAC,OAAwB;QAC1C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EACmB;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAE3D,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,qBAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEtF,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAA,0BAAiB,EAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnF,CAAC;CACF;AAzCD,wDAyCC;AAEY,QAAA,eAAe,GAAG,IAAI,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { WebhookProtocol, WebhookProtocolVerificationParams, ParsedWebhookHeaders } from '../../types';
2
+ export declare class SlackWebhookProtocol implements WebhookProtocol {
3
+ readonly name = "slack";
4
+ parseHeaders(headers?: Record<string, string | string[] | undefined>, signatureHeader?: string): ParsedWebhookHeaders;
5
+ formatSignedPayload(rawBody: string | Buffer, timestamp?: number): string;
6
+ verify({ secret, rawPayload, headers, signatureHeader, toleranceSeconds, clock }: WebhookProtocolVerificationParams): boolean;
7
+ }
8
+ export declare const slackProtocol: SlackWebhookProtocol;
9
+ //# sourceMappingURL=slack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../../src/webhooks/protocols/slack.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAIrB,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,QAAQ,CAAC,IAAI,WAAW;IAExB,YAAY,CACV,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAM,EAC3D,eAAe,GAAE,MAAW,GAC3B,oBAAoB;IAkBvB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAKzE,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EACf,gBAAsB,EACtB,KAAK,EACN,EAAE,iCAAiC,GAAG,OAAO;CAwB/C;AAED,eAAO,MAAM,aAAa,sBAA6B,CAAC"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.slackProtocol = exports.SlackWebhookProtocol = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const timing_1 = require("../timing");
9
+ const base_1 = require("./base");
10
+ class SlackWebhookProtocol {
11
+ name = 'slack';
12
+ parseHeaders(headers = {}, signatureHeader = '') {
13
+ const normalized = (0, base_1.normalizeHeaders)(headers);
14
+ const rawSignature = (signatureHeader ||
15
+ normalized['x-slack-signature'] ||
16
+ '').trim();
17
+ const rawTimestamp = normalized['x-slack-request-timestamp'];
18
+ const timestamp = rawTimestamp ? Number(rawTimestamp) : undefined;
19
+ return {
20
+ timestamp: !Number.isNaN(timestamp) ? timestamp : undefined,
21
+ signatures: rawSignature ? [rawSignature] : [],
22
+ version: 'v0'
23
+ };
24
+ }
25
+ formatSignedPayload(rawBody, timestamp) {
26
+ const bodyStr = (0, base_1.payloadToString)(rawBody);
27
+ return `v0:${timestamp !== undefined ? timestamp : ''}:${bodyStr}`;
28
+ }
29
+ verify({ secret, rawPayload, headers, signatureHeader, toleranceSeconds = 300, clock }) {
30
+ const parsed = this.parseHeaders(headers, signatureHeader);
31
+ if (parsed.timestamp === undefined || parsed.signatures.length === 0) {
32
+ return false;
33
+ }
34
+ const nowSec = clock ? Math.floor(clock.now() / 1000) : Math.floor(Date.now() / 1000);
35
+ if (!(0, base_1.isTimestampValid)(parsed.timestamp, toleranceSeconds, nowSec)) {
36
+ return false;
37
+ }
38
+ const signedPayload = this.formatSignedPayload(rawPayload, parsed.timestamp);
39
+ const hmacHex = node_crypto_1.default.createHmac('sha256', secret).update(signedPayload).digest('hex');
40
+ const expected = `v0=${hmacHex}`;
41
+ return parsed.signatures.some(sig => {
42
+ // Compare both with v0= prefix or without
43
+ if (sig.startsWith('v0=')) {
44
+ return (0, timing_1.timingSafeCompare)(expected, sig, 'utf8');
45
+ }
46
+ return (0, timing_1.timingSafeCompare)(hmacHex, sig, 'hex');
47
+ });
48
+ }
49
+ }
50
+ exports.SlackWebhookProtocol = SlackWebhookProtocol;
51
+ exports.slackProtocol = new SlackWebhookProtocol();
52
+ //# sourceMappingURL=slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.js","sourceRoot":"","sources":["../../../src/webhooks/protocols/slack.ts"],"names":[],"mappings":";;;;;;AAAA,8DAAiC;AAMjC,sCAA8C;AAC9C,iCAA6E;AAE7E,MAAa,oBAAoB;IACtB,IAAI,GAAG,OAAO,CAAC;IAExB,YAAY,CACV,UAAyD,EAAE,EAC3D,kBAA0B,EAAE;QAE5B,MAAM,UAAU,GAAG,IAAA,uBAAgB,EAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,YAAY,GAAG,CACnB,eAAe;YACf,UAAU,CAAC,mBAAmB,CAAC;YAC/B,EAAE,CACH,CAAC,IAAI,EAAE,CAAC;QAET,MAAM,YAAY,GAAG,UAAU,CAAC,2BAA2B,CAAC,CAAC;QAC7D,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAElE,OAAO;YACL,SAAS,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YAC3D,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE;YAC9C,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,mBAAmB,CAAC,OAAwB,EAAE,SAAkB;QAC9D,MAAM,OAAO,GAAG,IAAA,sBAAe,EAAC,OAAO,CAAC,CAAC;QACzC,OAAO,MAAM,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,OAAO,EAAE,CAAC;IACrE,CAAC;IAED,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EACf,gBAAgB,GAAG,GAAG,EACtB,KAAK,EAC6B;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAE3D,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QACtF,IAAI,CAAC,IAAA,uBAAgB,EAAC,MAAM,CAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,CAAC;YAClE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7E,MAAM,OAAO,GAAG,qBAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACxF,MAAM,QAAQ,GAAG,MAAM,OAAO,EAAE,CAAC;QAEjC,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAClC,0CAA0C;YAC1C,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO,IAAA,0BAAiB,EAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YAClD,CAAC;YACD,OAAO,IAAA,0BAAiB,EAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AA5DD,oDA4DC;AAEY,QAAA,aAAa,GAAG,IAAI,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { WebhookProtocol, WebhookProtocolVerificationParams, ParsedWebhookHeaders } from '../../types';
2
+ export declare class StripeWebhookProtocol implements WebhookProtocol {
3
+ readonly name = "stripe";
4
+ parseHeaders(headers?: Record<string, string | string[] | undefined>, signatureHeader?: string): ParsedWebhookHeaders;
5
+ formatSignedPayload(rawBody: string | Buffer, timestamp?: number): string;
6
+ verify({ secret, rawPayload, headers, signatureHeader, toleranceSeconds, clock }: WebhookProtocolVerificationParams): boolean;
7
+ }
8
+ export declare const stripeProtocol: StripeWebhookProtocol;
9
+ //# sourceMappingURL=stripe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.d.ts","sourceRoot":"","sources":["../../../src/webhooks/protocols/stripe.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAIrB,qBAAa,qBAAsB,YAAW,eAAe;IAC3D,QAAQ,CAAC,IAAI,YAAY;IAEzB,YAAY,CACV,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAM,EAC3D,eAAe,GAAE,MAAW,GAC3B,oBAAoB;IA2BvB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAKzE,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EACf,gBAAsB,EACtB,KAAK,EACN,EAAE,iCAAiC,GAAG,OAAO;CAiB/C;AAED,eAAO,MAAM,cAAc,uBAA8B,CAAC"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.stripeProtocol = exports.StripeWebhookProtocol = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const timing_1 = require("../timing");
9
+ const base_1 = require("./base");
10
+ class StripeWebhookProtocol {
11
+ name = 'stripe';
12
+ parseHeaders(headers = {}, signatureHeader = '') {
13
+ const normalized = (0, base_1.normalizeHeaders)(headers);
14
+ const rawHeader = signatureHeader || normalized['stripe-signature'] || '';
15
+ let timestamp;
16
+ const signatures = [];
17
+ const elements = rawHeader.split(',');
18
+ for (const element of elements) {
19
+ const [key, value] = element.trim().split('=');
20
+ if (key === 't') {
21
+ const num = Number(value);
22
+ if (!Number.isNaN(num)) {
23
+ timestamp = num;
24
+ }
25
+ }
26
+ else if (key === 'v1' && value) {
27
+ signatures.push(value);
28
+ }
29
+ }
30
+ return {
31
+ timestamp,
32
+ signatures,
33
+ version: 'v1'
34
+ };
35
+ }
36
+ formatSignedPayload(rawBody, timestamp) {
37
+ const bodyStr = (0, base_1.payloadToString)(rawBody);
38
+ return timestamp !== undefined ? `${timestamp}.${bodyStr}` : bodyStr;
39
+ }
40
+ verify({ secret, rawPayload, headers, signatureHeader, toleranceSeconds = 300, clock }) {
41
+ const parsed = this.parseHeaders(headers, signatureHeader);
42
+ if (parsed.timestamp === undefined || parsed.signatures.length === 0) {
43
+ return false;
44
+ }
45
+ const nowSec = clock ? Math.floor(clock.now() / 1000) : Math.floor(Date.now() / 1000);
46
+ if (!(0, base_1.isTimestampValid)(parsed.timestamp, toleranceSeconds, nowSec)) {
47
+ return false;
48
+ }
49
+ const signedPayload = this.formatSignedPayload(rawPayload, parsed.timestamp);
50
+ const expected = node_crypto_1.default.createHmac('sha256', secret).update(signedPayload).digest('hex');
51
+ return parsed.signatures.some(sig => (0, timing_1.timingSafeCompare)(expected, sig, 'hex'));
52
+ }
53
+ }
54
+ exports.StripeWebhookProtocol = StripeWebhookProtocol;
55
+ exports.stripeProtocol = new StripeWebhookProtocol();
56
+ //# sourceMappingURL=stripe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../../src/webhooks/protocols/stripe.ts"],"names":[],"mappings":";;;;;;AAAA,8DAAiC;AAMjC,sCAA8C;AAC9C,iCAA6E;AAE7E,MAAa,qBAAqB;IACvB,IAAI,GAAG,QAAQ,CAAC;IAEzB,YAAY,CACV,UAAyD,EAAE,EAC3D,kBAA0B,EAAE;QAE5B,MAAM,UAAU,GAAG,IAAA,uBAAgB,EAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,eAAe,IAAI,UAAU,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;QAE1E,IAAI,SAA6B,CAAC;QAClC,MAAM,UAAU,GAAa,EAAE,CAAC;QAEhC,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACtC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/C,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;gBAChB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvB,SAAS,GAAG,GAAG,CAAC;gBAClB,CAAC;YACH,CAAC;iBAAM,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,EAAE,CAAC;gBACjC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QAED,OAAO;YACL,SAAS;YACT,UAAU;YACV,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,mBAAmB,CAAC,OAAwB,EAAE,SAAkB;QAC9D,MAAM,OAAO,GAAG,IAAA,sBAAe,EAAC,OAAO,CAAC,CAAC;QACzC,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IACvE,CAAC;IAED,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EACf,gBAAgB,GAAG,GAAG,EACtB,KAAK,EAC6B;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAE3D,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QACtF,IAAI,CAAC,IAAA,uBAAgB,EAAC,MAAM,CAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,CAAC;YAClE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7E,MAAM,QAAQ,GAAG,qBAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAEzF,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAA,0BAAiB,EAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAChF,CAAC;CACF;AA9DD,sDA8DC;AAEY,QAAA,cAAc,GAAG,IAAI,qBAAqB,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { WebhookProtocol, WebhookProtocolVerificationParams, ParsedWebhookHeaders } from '../../types';
2
+ export declare class SvixWebhookProtocol implements WebhookProtocol {
3
+ readonly name = "svix";
4
+ parseHeaders(headers?: Record<string, string | string[] | undefined>, signatureHeader?: string): ParsedWebhookHeaders;
5
+ formatSignedPayload(rawBody: string | Buffer, timestamp?: number, svixId?: string): string;
6
+ verify({ secret, rawPayload, headers, signatureHeader, toleranceSeconds, clock }: WebhookProtocolVerificationParams): boolean;
7
+ }
8
+ export declare const svixProtocol: SvixWebhookProtocol;
9
+ //# sourceMappingURL=svix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svix.d.ts","sourceRoot":"","sources":["../../../src/webhooks/protocols/svix.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,iCAAiC,EACjC,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAIrB,qBAAa,mBAAoB,YAAW,eAAe;IACzD,QAAQ,CAAC,IAAI,UAAU;IAEvB,YAAY,CACV,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAM,EAC3D,eAAe,GAAE,MAAW,GAC3B,oBAAoB;IA6BvB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;IAK1F,MAAM,CAAC,EACL,MAAM,EACN,UAAU,EACV,OAAO,EACP,eAAe,EACf,gBAAsB,EACtB,KAAK,EACN,EAAE,iCAAiC,GAAG,OAAO;CA2C/C;AAED,eAAO,MAAM,YAAY,qBAA4B,CAAC"}