@surbee/cipher 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.
- package/dist/index.d.mts +341 -0
- package/dist/index.d.ts +341 -0
- package/dist/index.js +202 -0
- package/dist/index.mjs +174 -0
- package/package.json +45 -0
- package/src/checks/behavioral.ts +527 -0
- package/src/checks/content.ts +372 -0
- package/src/checks/device.ts +384 -0
- package/src/checks/index.ts +59 -0
- package/src/checks/timing.ts +256 -0
- package/src/cipher.ts +225 -0
- package/src/index.ts +75 -0
- package/src/tiers.ts +507 -0
- package/src/types.ts +366 -0
- package/test/cipher.test.ts +245 -0
- package/test/fixtures.ts +627 -0
- package/tsconfig.json +20 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Cipher: () => Cipher,
|
|
24
|
+
VERSION: () => VERSION
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/cipher.ts
|
|
29
|
+
var DEFAULT_CONFIG = {
|
|
30
|
+
tier: 3,
|
|
31
|
+
thresholds: {
|
|
32
|
+
fail: 0.4,
|
|
33
|
+
review: 0.7
|
|
34
|
+
},
|
|
35
|
+
debug: false,
|
|
36
|
+
endpoint: "https://api.surbee.com/v1/cipher"
|
|
37
|
+
};
|
|
38
|
+
var TIER_INFO = {
|
|
39
|
+
1: {
|
|
40
|
+
name: "Basic",
|
|
41
|
+
description: "Essential fraud detection with behavioral heuristics",
|
|
42
|
+
checksCount: 6
|
|
43
|
+
},
|
|
44
|
+
2: {
|
|
45
|
+
name: "Standard",
|
|
46
|
+
description: "Adds device fingerprinting and automation detection",
|
|
47
|
+
checksCount: 15
|
|
48
|
+
},
|
|
49
|
+
3: {
|
|
50
|
+
name: "Enhanced",
|
|
51
|
+
description: "Adds AI-powered content quality analysis",
|
|
52
|
+
checksCount: 22
|
|
53
|
+
},
|
|
54
|
+
4: {
|
|
55
|
+
name: "Advanced",
|
|
56
|
+
description: "Full behavioral analysis with network validation",
|
|
57
|
+
checksCount: 30
|
|
58
|
+
},
|
|
59
|
+
5: {
|
|
60
|
+
name: "Maximum",
|
|
61
|
+
description: "All 43 checks with cross-respondent fraud detection",
|
|
62
|
+
checksCount: 43
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var Cipher = class {
|
|
66
|
+
config;
|
|
67
|
+
constructor(config) {
|
|
68
|
+
if (!config.apiKey) {
|
|
69
|
+
throw new Error("API key is required. Get one from Settings > API Keys in your Surbee dashboard.");
|
|
70
|
+
}
|
|
71
|
+
if (!config.apiKey.startsWith("cipher_sk_") && !config.apiKey.startsWith("cipher_pk_")) {
|
|
72
|
+
throw new Error("Invalid API key format. Keys should start with cipher_sk_ or cipher_pk_");
|
|
73
|
+
}
|
|
74
|
+
this.config = {
|
|
75
|
+
apiKey: config.apiKey,
|
|
76
|
+
tier: config.tier ?? DEFAULT_CONFIG.tier,
|
|
77
|
+
thresholds: {
|
|
78
|
+
fail: config.thresholds?.fail ?? DEFAULT_CONFIG.thresholds.fail,
|
|
79
|
+
review: config.thresholds?.review ?? DEFAULT_CONFIG.thresholds.review
|
|
80
|
+
},
|
|
81
|
+
debug: config.debug ?? DEFAULT_CONFIG.debug,
|
|
82
|
+
endpoint: config.endpoint ?? DEFAULT_CONFIG.endpoint
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Validate a single response
|
|
87
|
+
*/
|
|
88
|
+
async validate(input) {
|
|
89
|
+
const response = await this.request("/validate", {
|
|
90
|
+
tier: this.config.tier,
|
|
91
|
+
thresholds: this.config.thresholds,
|
|
92
|
+
input
|
|
93
|
+
});
|
|
94
|
+
return response;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Validate multiple responses in batch
|
|
98
|
+
*/
|
|
99
|
+
async validateBatch(input) {
|
|
100
|
+
const response = await this.request("/validate/batch", {
|
|
101
|
+
tier: this.config.tier,
|
|
102
|
+
thresholds: this.config.thresholds,
|
|
103
|
+
submissions: input.submissions,
|
|
104
|
+
crossAnalysis: input.crossAnalysis ?? this.config.tier === 5
|
|
105
|
+
});
|
|
106
|
+
return response;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get tier information
|
|
110
|
+
*/
|
|
111
|
+
getTierInfo(tier) {
|
|
112
|
+
const t = tier ?? this.config.tier;
|
|
113
|
+
return TIER_INFO[t];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get all available tiers
|
|
117
|
+
*/
|
|
118
|
+
getAllTiers() {
|
|
119
|
+
return Object.entries(TIER_INFO).map(([tier, info]) => ({
|
|
120
|
+
tier: Number(tier),
|
|
121
|
+
...info
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Check API key validity and credits
|
|
126
|
+
*/
|
|
127
|
+
async checkStatus() {
|
|
128
|
+
const response = await this.request("/status", {});
|
|
129
|
+
return response;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Make API request to Surbee
|
|
133
|
+
*/
|
|
134
|
+
async request(path, body) {
|
|
135
|
+
const url = `${this.config.endpoint}${path}`;
|
|
136
|
+
if (this.config.debug) {
|
|
137
|
+
console.log(`[Cipher] POST ${url}`);
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const response = await fetch(url, {
|
|
141
|
+
method: "POST",
|
|
142
|
+
headers: {
|
|
143
|
+
"Content-Type": "application/json",
|
|
144
|
+
"Authorization": `Bearer ${this.config.apiKey}`,
|
|
145
|
+
"X-Cipher-SDK": "0.1.0"
|
|
146
|
+
},
|
|
147
|
+
body: JSON.stringify(body)
|
|
148
|
+
});
|
|
149
|
+
if (!response.ok) {
|
|
150
|
+
const errorData = await response.json().catch(() => ({}));
|
|
151
|
+
throw this.createError(response.status, errorData);
|
|
152
|
+
}
|
|
153
|
+
return response.json();
|
|
154
|
+
} catch (error) {
|
|
155
|
+
if (error && typeof error === "object" && "code" in error) {
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
throw this.createError(0, { message: error instanceof Error ? error.message : "Unknown error" });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Create a typed error
|
|
163
|
+
*/
|
|
164
|
+
createError(status, data) {
|
|
165
|
+
let code;
|
|
166
|
+
let message;
|
|
167
|
+
switch (status) {
|
|
168
|
+
case 401:
|
|
169
|
+
code = "INVALID_API_KEY";
|
|
170
|
+
message = "Invalid API key. Check your key in Settings > API Keys.";
|
|
171
|
+
break;
|
|
172
|
+
case 402:
|
|
173
|
+
code = "INSUFFICIENT_CREDITS";
|
|
174
|
+
message = "Insufficient credits. Add more credits in your Surbee dashboard.";
|
|
175
|
+
break;
|
|
176
|
+
case 429:
|
|
177
|
+
code = "RATE_LIMITED";
|
|
178
|
+
message = "Rate limited. Please slow down your requests.";
|
|
179
|
+
break;
|
|
180
|
+
case 400:
|
|
181
|
+
code = "INVALID_INPUT";
|
|
182
|
+
message = data.message || "Invalid input data.";
|
|
183
|
+
break;
|
|
184
|
+
case 403:
|
|
185
|
+
code = "TIER_NOT_AVAILABLE";
|
|
186
|
+
message = "This tier is not available on your plan. Upgrade to access higher tiers.";
|
|
187
|
+
break;
|
|
188
|
+
default:
|
|
189
|
+
code = status === 0 ? "NETWORK_ERROR" : "SERVER_ERROR";
|
|
190
|
+
message = data.message || "An error occurred.";
|
|
191
|
+
}
|
|
192
|
+
return { code, message, details: data };
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// src/index.ts
|
|
197
|
+
var VERSION = "0.1.0";
|
|
198
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
199
|
+
0 && (module.exports = {
|
|
200
|
+
Cipher,
|
|
201
|
+
VERSION
|
|
202
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// src/cipher.ts
|
|
2
|
+
var DEFAULT_CONFIG = {
|
|
3
|
+
tier: 3,
|
|
4
|
+
thresholds: {
|
|
5
|
+
fail: 0.4,
|
|
6
|
+
review: 0.7
|
|
7
|
+
},
|
|
8
|
+
debug: false,
|
|
9
|
+
endpoint: "https://api.surbee.com/v1/cipher"
|
|
10
|
+
};
|
|
11
|
+
var TIER_INFO = {
|
|
12
|
+
1: {
|
|
13
|
+
name: "Basic",
|
|
14
|
+
description: "Essential fraud detection with behavioral heuristics",
|
|
15
|
+
checksCount: 6
|
|
16
|
+
},
|
|
17
|
+
2: {
|
|
18
|
+
name: "Standard",
|
|
19
|
+
description: "Adds device fingerprinting and automation detection",
|
|
20
|
+
checksCount: 15
|
|
21
|
+
},
|
|
22
|
+
3: {
|
|
23
|
+
name: "Enhanced",
|
|
24
|
+
description: "Adds AI-powered content quality analysis",
|
|
25
|
+
checksCount: 22
|
|
26
|
+
},
|
|
27
|
+
4: {
|
|
28
|
+
name: "Advanced",
|
|
29
|
+
description: "Full behavioral analysis with network validation",
|
|
30
|
+
checksCount: 30
|
|
31
|
+
},
|
|
32
|
+
5: {
|
|
33
|
+
name: "Maximum",
|
|
34
|
+
description: "All 43 checks with cross-respondent fraud detection",
|
|
35
|
+
checksCount: 43
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var Cipher = class {
|
|
39
|
+
config;
|
|
40
|
+
constructor(config) {
|
|
41
|
+
if (!config.apiKey) {
|
|
42
|
+
throw new Error("API key is required. Get one from Settings > API Keys in your Surbee dashboard.");
|
|
43
|
+
}
|
|
44
|
+
if (!config.apiKey.startsWith("cipher_sk_") && !config.apiKey.startsWith("cipher_pk_")) {
|
|
45
|
+
throw new Error("Invalid API key format. Keys should start with cipher_sk_ or cipher_pk_");
|
|
46
|
+
}
|
|
47
|
+
this.config = {
|
|
48
|
+
apiKey: config.apiKey,
|
|
49
|
+
tier: config.tier ?? DEFAULT_CONFIG.tier,
|
|
50
|
+
thresholds: {
|
|
51
|
+
fail: config.thresholds?.fail ?? DEFAULT_CONFIG.thresholds.fail,
|
|
52
|
+
review: config.thresholds?.review ?? DEFAULT_CONFIG.thresholds.review
|
|
53
|
+
},
|
|
54
|
+
debug: config.debug ?? DEFAULT_CONFIG.debug,
|
|
55
|
+
endpoint: config.endpoint ?? DEFAULT_CONFIG.endpoint
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Validate a single response
|
|
60
|
+
*/
|
|
61
|
+
async validate(input) {
|
|
62
|
+
const response = await this.request("/validate", {
|
|
63
|
+
tier: this.config.tier,
|
|
64
|
+
thresholds: this.config.thresholds,
|
|
65
|
+
input
|
|
66
|
+
});
|
|
67
|
+
return response;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validate multiple responses in batch
|
|
71
|
+
*/
|
|
72
|
+
async validateBatch(input) {
|
|
73
|
+
const response = await this.request("/validate/batch", {
|
|
74
|
+
tier: this.config.tier,
|
|
75
|
+
thresholds: this.config.thresholds,
|
|
76
|
+
submissions: input.submissions,
|
|
77
|
+
crossAnalysis: input.crossAnalysis ?? this.config.tier === 5
|
|
78
|
+
});
|
|
79
|
+
return response;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get tier information
|
|
83
|
+
*/
|
|
84
|
+
getTierInfo(tier) {
|
|
85
|
+
const t = tier ?? this.config.tier;
|
|
86
|
+
return TIER_INFO[t];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get all available tiers
|
|
90
|
+
*/
|
|
91
|
+
getAllTiers() {
|
|
92
|
+
return Object.entries(TIER_INFO).map(([tier, info]) => ({
|
|
93
|
+
tier: Number(tier),
|
|
94
|
+
...info
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Check API key validity and credits
|
|
99
|
+
*/
|
|
100
|
+
async checkStatus() {
|
|
101
|
+
const response = await this.request("/status", {});
|
|
102
|
+
return response;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Make API request to Surbee
|
|
106
|
+
*/
|
|
107
|
+
async request(path, body) {
|
|
108
|
+
const url = `${this.config.endpoint}${path}`;
|
|
109
|
+
if (this.config.debug) {
|
|
110
|
+
console.log(`[Cipher] POST ${url}`);
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
const response = await fetch(url, {
|
|
114
|
+
method: "POST",
|
|
115
|
+
headers: {
|
|
116
|
+
"Content-Type": "application/json",
|
|
117
|
+
"Authorization": `Bearer ${this.config.apiKey}`,
|
|
118
|
+
"X-Cipher-SDK": "0.1.0"
|
|
119
|
+
},
|
|
120
|
+
body: JSON.stringify(body)
|
|
121
|
+
});
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
const errorData = await response.json().catch(() => ({}));
|
|
124
|
+
throw this.createError(response.status, errorData);
|
|
125
|
+
}
|
|
126
|
+
return response.json();
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error && typeof error === "object" && "code" in error) {
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
throw this.createError(0, { message: error instanceof Error ? error.message : "Unknown error" });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Create a typed error
|
|
136
|
+
*/
|
|
137
|
+
createError(status, data) {
|
|
138
|
+
let code;
|
|
139
|
+
let message;
|
|
140
|
+
switch (status) {
|
|
141
|
+
case 401:
|
|
142
|
+
code = "INVALID_API_KEY";
|
|
143
|
+
message = "Invalid API key. Check your key in Settings > API Keys.";
|
|
144
|
+
break;
|
|
145
|
+
case 402:
|
|
146
|
+
code = "INSUFFICIENT_CREDITS";
|
|
147
|
+
message = "Insufficient credits. Add more credits in your Surbee dashboard.";
|
|
148
|
+
break;
|
|
149
|
+
case 429:
|
|
150
|
+
code = "RATE_LIMITED";
|
|
151
|
+
message = "Rate limited. Please slow down your requests.";
|
|
152
|
+
break;
|
|
153
|
+
case 400:
|
|
154
|
+
code = "INVALID_INPUT";
|
|
155
|
+
message = data.message || "Invalid input data.";
|
|
156
|
+
break;
|
|
157
|
+
case 403:
|
|
158
|
+
code = "TIER_NOT_AVAILABLE";
|
|
159
|
+
message = "This tier is not available on your plan. Upgrade to access higher tiers.";
|
|
160
|
+
break;
|
|
161
|
+
default:
|
|
162
|
+
code = status === 0 ? "NETWORK_ERROR" : "SERVER_ERROR";
|
|
163
|
+
message = data.message || "An error occurred.";
|
|
164
|
+
}
|
|
165
|
+
return { code, message, details: data };
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// src/index.ts
|
|
170
|
+
var VERSION = "0.1.0";
|
|
171
|
+
export {
|
|
172
|
+
Cipher,
|
|
173
|
+
VERSION
|
|
174
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@surbee/cipher",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AI-powered survey response validation - detect fraud, bots, and low-quality responses",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
17
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
18
|
+
"lint": "eslint src/",
|
|
19
|
+
"typecheck": "tsc --noEmit"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"survey",
|
|
23
|
+
"fraud-detection",
|
|
24
|
+
"response-validation",
|
|
25
|
+
"quality-assurance",
|
|
26
|
+
"bot-detection",
|
|
27
|
+
"cipher",
|
|
28
|
+
"surbee"
|
|
29
|
+
],
|
|
30
|
+
"author": "Surbee",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/surbee/cipher-sdk"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://surbee.com/docs/cipher",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^20.0.0",
|
|
39
|
+
"tsup": "^8.0.0",
|
|
40
|
+
"typescript": "^5.0.0"
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18.0.0"
|
|
44
|
+
}
|
|
45
|
+
}
|