@dregs/sdk 0.1.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.
@@ -0,0 +1,36 @@
1
+ 'use strict';
2
+
3
+ var chunkK63AUEQR_cjs = require('./chunk-K63AUEQR.cjs');
4
+
5
+
6
+
7
+ Object.defineProperty(exports, "DEFAULT_TOLERANCE_SECONDS", {
8
+ enumerable: true,
9
+ get: function () { return chunkK63AUEQR_cjs.DEFAULT_TOLERANCE_SECONDS; }
10
+ });
11
+ Object.defineProperty(exports, "EVENT_HEADER", {
12
+ enumerable: true,
13
+ get: function () { return chunkK63AUEQR_cjs.EVENT_HEADER; }
14
+ });
15
+ Object.defineProperty(exports, "SIGNATURE_HEADER", {
16
+ enumerable: true,
17
+ get: function () { return chunkK63AUEQR_cjs.SIGNATURE_HEADER; }
18
+ });
19
+ Object.defineProperty(exports, "TIMESTAMP_HEADER", {
20
+ enumerable: true,
21
+ get: function () { return chunkK63AUEQR_cjs.TIMESTAMP_HEADER; }
22
+ });
23
+ Object.defineProperty(exports, "computeWebhookSignature", {
24
+ enumerable: true,
25
+ get: function () { return chunkK63AUEQR_cjs.computeWebhookSignature; }
26
+ });
27
+ Object.defineProperty(exports, "verifyWebhook", {
28
+ enumerable: true,
29
+ get: function () { return chunkK63AUEQR_cjs.verifyWebhook; }
30
+ });
31
+ Object.defineProperty(exports, "verifyWebhookSignature", {
32
+ enumerable: true,
33
+ get: function () { return chunkK63AUEQR_cjs.verifyWebhookSignature; }
34
+ });
35
+ //# sourceMappingURL=webhooks.cjs.map
36
+ //# sourceMappingURL=webhooks.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"webhooks.cjs"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Verifying webhooks Dregs sends you.
3
+ *
4
+ * Dregs signs every webhook with the channel's signing secret: `X-Dregs-Signature` is the
5
+ * hex-encoded HMAC-SHA256 of the raw request body. Verify it before you act on the payload, and
6
+ * verify it against the bytes you received rather than a re-serialized object, because
7
+ * re-serializing changes key order and whitespace and will not match.
8
+ *
9
+ * ```ts
10
+ * import { verifyWebhook } from '@dregs/sdk/webhooks';
11
+ *
12
+ * app.post('/webhooks/dregs', express.raw({ type: 'application/json' }), (req, res) => {
13
+ * const event = verifyWebhook({
14
+ * payload: req.body, // the Buffer, not req.body parsed as JSON
15
+ * signature: req.header('X-Dregs-Signature') ?? '',
16
+ * secret: process.env.DREGS_WEBHOOK_SECRET!,
17
+ * });
18
+ *
19
+ * handle(event);
20
+ * });
21
+ * ```
22
+ *
23
+ * The signing secret is shown once, when you create the webhook channel. It is not your API
24
+ * secret key: one authenticates you to Dregs, the other proves a payload came from Dregs.
25
+ *
26
+ * @module
27
+ */
28
+ /** The header carrying the hex-encoded HMAC-SHA256 of the raw body. */
29
+ declare const SIGNATURE_HEADER = "X-Dregs-Signature";
30
+ /** The header carrying the delivery's timestamp. */
31
+ declare const TIMESTAMP_HEADER = "X-Dregs-Timestamp";
32
+ /** The header naming the event type. */
33
+ declare const EVENT_HEADER = "X-Dregs-Event";
34
+ /** How far out of date a webhook's timestamp may be before {@link verifyWebhook} rejects it. */
35
+ declare const DEFAULT_TOLERANCE_SECONDS = 300;
36
+ /**
37
+ * A raw webhook body.
38
+ *
39
+ * A `Buffer` or `Uint8Array` is what you want: the bytes exactly as received. A string is
40
+ * accepted for frameworks that hand you the raw text, and is hashed as UTF-8.
41
+ */
42
+ type WebhookPayload = string | Uint8Array;
43
+ /** A verified webhook body: `event`, `timestamp`, and the payload for that event. */
44
+ type WebhookEvent = Record<string, unknown>;
45
+ /** The arguments to {@link verifyWebhook}. */
46
+ interface VerifyWebhookOptions {
47
+ /** The raw request body, exactly as received. Not a parsed object. */
48
+ payload: WebhookPayload;
49
+ /** The `X-Dregs-Signature` header. */
50
+ signature: string;
51
+ /** The channel's signing secret. */
52
+ secret: string;
53
+ /**
54
+ * How many seconds out of date the payload's own `timestamp` may be before it is treated as a
55
+ * replay. Defaults to 300. Pass `null` to skip the check, which you should only do if you are
56
+ * deduplicating on the event id yourself.
57
+ *
58
+ * The timestamp is inside the signed body, so an attacker cannot alter it without breaking
59
+ * the signature.
60
+ */
61
+ tolerance?: number | null;
62
+ /** The current time. For tests. */
63
+ now?: Date;
64
+ }
65
+ /** Returns the hex-encoded HMAC-SHA256 of `payload` under `secret`. */
66
+ declare function computeWebhookSignature(payload: WebhookPayload, secret: string): string;
67
+ /**
68
+ * Returns whether `signature` matches `payload`.
69
+ *
70
+ * The comparison is constant-time. Prefer {@link verifyWebhook}, which also rejects replays and
71
+ * hands back the parsed event; reach for this one only when you need the boolean.
72
+ */
73
+ declare function verifyWebhookSignature(payload: WebhookPayload, signature: string, secret: string): boolean;
74
+ /**
75
+ * Verifies a webhook and returns its parsed body.
76
+ *
77
+ * @returns The parsed webhook body: `event`, `timestamp`, and the payload for that event.
78
+ * @throws {WebhookVerificationError} The signature did not match, the body was not a JSON
79
+ * object, or the payload is older than the tolerance. Answer 400 and do not act on it.
80
+ */
81
+ declare function verifyWebhook(options: VerifyWebhookOptions): WebhookEvent;
82
+
83
+ export { DEFAULT_TOLERANCE_SECONDS, EVENT_HEADER, SIGNATURE_HEADER, TIMESTAMP_HEADER, type VerifyWebhookOptions, type WebhookEvent, type WebhookPayload, computeWebhookSignature, verifyWebhook, verifyWebhookSignature };
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Verifying webhooks Dregs sends you.
3
+ *
4
+ * Dregs signs every webhook with the channel's signing secret: `X-Dregs-Signature` is the
5
+ * hex-encoded HMAC-SHA256 of the raw request body. Verify it before you act on the payload, and
6
+ * verify it against the bytes you received rather than a re-serialized object, because
7
+ * re-serializing changes key order and whitespace and will not match.
8
+ *
9
+ * ```ts
10
+ * import { verifyWebhook } from '@dregs/sdk/webhooks';
11
+ *
12
+ * app.post('/webhooks/dregs', express.raw({ type: 'application/json' }), (req, res) => {
13
+ * const event = verifyWebhook({
14
+ * payload: req.body, // the Buffer, not req.body parsed as JSON
15
+ * signature: req.header('X-Dregs-Signature') ?? '',
16
+ * secret: process.env.DREGS_WEBHOOK_SECRET!,
17
+ * });
18
+ *
19
+ * handle(event);
20
+ * });
21
+ * ```
22
+ *
23
+ * The signing secret is shown once, when you create the webhook channel. It is not your API
24
+ * secret key: one authenticates you to Dregs, the other proves a payload came from Dregs.
25
+ *
26
+ * @module
27
+ */
28
+ /** The header carrying the hex-encoded HMAC-SHA256 of the raw body. */
29
+ declare const SIGNATURE_HEADER = "X-Dregs-Signature";
30
+ /** The header carrying the delivery's timestamp. */
31
+ declare const TIMESTAMP_HEADER = "X-Dregs-Timestamp";
32
+ /** The header naming the event type. */
33
+ declare const EVENT_HEADER = "X-Dregs-Event";
34
+ /** How far out of date a webhook's timestamp may be before {@link verifyWebhook} rejects it. */
35
+ declare const DEFAULT_TOLERANCE_SECONDS = 300;
36
+ /**
37
+ * A raw webhook body.
38
+ *
39
+ * A `Buffer` or `Uint8Array` is what you want: the bytes exactly as received. A string is
40
+ * accepted for frameworks that hand you the raw text, and is hashed as UTF-8.
41
+ */
42
+ type WebhookPayload = string | Uint8Array;
43
+ /** A verified webhook body: `event`, `timestamp`, and the payload for that event. */
44
+ type WebhookEvent = Record<string, unknown>;
45
+ /** The arguments to {@link verifyWebhook}. */
46
+ interface VerifyWebhookOptions {
47
+ /** The raw request body, exactly as received. Not a parsed object. */
48
+ payload: WebhookPayload;
49
+ /** The `X-Dregs-Signature` header. */
50
+ signature: string;
51
+ /** The channel's signing secret. */
52
+ secret: string;
53
+ /**
54
+ * How many seconds out of date the payload's own `timestamp` may be before it is treated as a
55
+ * replay. Defaults to 300. Pass `null` to skip the check, which you should only do if you are
56
+ * deduplicating on the event id yourself.
57
+ *
58
+ * The timestamp is inside the signed body, so an attacker cannot alter it without breaking
59
+ * the signature.
60
+ */
61
+ tolerance?: number | null;
62
+ /** The current time. For tests. */
63
+ now?: Date;
64
+ }
65
+ /** Returns the hex-encoded HMAC-SHA256 of `payload` under `secret`. */
66
+ declare function computeWebhookSignature(payload: WebhookPayload, secret: string): string;
67
+ /**
68
+ * Returns whether `signature` matches `payload`.
69
+ *
70
+ * The comparison is constant-time. Prefer {@link verifyWebhook}, which also rejects replays and
71
+ * hands back the parsed event; reach for this one only when you need the boolean.
72
+ */
73
+ declare function verifyWebhookSignature(payload: WebhookPayload, signature: string, secret: string): boolean;
74
+ /**
75
+ * Verifies a webhook and returns its parsed body.
76
+ *
77
+ * @returns The parsed webhook body: `event`, `timestamp`, and the payload for that event.
78
+ * @throws {WebhookVerificationError} The signature did not match, the body was not a JSON
79
+ * object, or the payload is older than the tolerance. Answer 400 and do not act on it.
80
+ */
81
+ declare function verifyWebhook(options: VerifyWebhookOptions): WebhookEvent;
82
+
83
+ export { DEFAULT_TOLERANCE_SECONDS, EVENT_HEADER, SIGNATURE_HEADER, TIMESTAMP_HEADER, type VerifyWebhookOptions, type WebhookEvent, type WebhookPayload, computeWebhookSignature, verifyWebhook, verifyWebhookSignature };
@@ -0,0 +1,3 @@
1
+ export { DEFAULT_TOLERANCE_SECONDS, EVENT_HEADER, SIGNATURE_HEADER, TIMESTAMP_HEADER, computeWebhookSignature, verifyWebhook, verifyWebhookSignature } from './chunk-AIUWT3Z7.js';
2
+ //# sourceMappingURL=webhooks.js.map
3
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"webhooks.js"}
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "@dregs/sdk",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript SDK for Dregs, the fraud and abuse scoring service.",
5
+ "keywords": [
6
+ "dregs",
7
+ "fraud",
8
+ "abuse",
9
+ "fraud-detection",
10
+ "bot-detection",
11
+ "risk-scoring"
12
+ ],
13
+ "homepage": "https://dregs.com",
14
+ "bugs": "https://github.com/dregs-sdk/dregs-sdk-typescript/issues",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/dregs-sdk/dregs-sdk-typescript.git"
18
+ },
19
+ "license": "MIT",
20
+ "author": "Dregs <support@dregs.com>",
21
+ "type": "module",
22
+ "main": "./dist/index.cjs",
23
+ "module": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "import": {
28
+ "types": "./dist/index.d.ts",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "require": {
32
+ "types": "./dist/index.d.cts",
33
+ "default": "./dist/index.cjs"
34
+ }
35
+ },
36
+ "./webhooks": {
37
+ "import": {
38
+ "types": "./dist/webhooks.d.ts",
39
+ "default": "./dist/webhooks.js"
40
+ },
41
+ "require": {
42
+ "types": "./dist/webhooks.d.cts",
43
+ "default": "./dist/webhooks.cjs"
44
+ }
45
+ },
46
+ "./package.json": "./package.json"
47
+ },
48
+ "files": [
49
+ "dist",
50
+ "CHANGELOG.md"
51
+ ],
52
+ "sideEffects": false,
53
+ "scripts": {
54
+ "build": "tsup",
55
+ "clean": "rm -rf dist",
56
+ "format": "prettier --write .",
57
+ "format:check": "prettier --check .",
58
+ "lint": "eslint .",
59
+ "prepublishOnly": "npm run build",
60
+ "test": "vitest run",
61
+ "test:watch": "vitest",
62
+ "typecheck": "tsc --noEmit",
63
+ "verify:dist": "node scripts/smoke-dist.mjs",
64
+ "verify:package": "publint && attw --pack . --profile node16"
65
+ },
66
+ "devDependencies": {
67
+ "@arethetypeswrong/cli": "^0.18.2",
68
+ "@eslint/js": "^9.36.0",
69
+ "@types/node": "^22.20.4",
70
+ "eslint": "^9.36.0",
71
+ "eslint-config-prettier": "^10.1.8",
72
+ "prettier": "^3.6.2",
73
+ "publint": "^0.3.14",
74
+ "tsup": "^8.5.0",
75
+ "typescript": "^5.9.2",
76
+ "typescript-eslint": "^8.44.1",
77
+ "vitest": "^5.0.1"
78
+ },
79
+ "engines": {
80
+ "node": ">=20"
81
+ },
82
+ "publishConfig": {
83
+ "access": "public",
84
+ "provenance": true
85
+ }
86
+ }