@shieldlabs-ai/node 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.
- package/CHANGELOG.md +72 -0
- package/LICENSE +21 -0
- package/README.md +486 -2
- package/dist/edge.cjs +1595 -0
- package/dist/edge.cjs.map +1 -0
- package/dist/edge.js +1569 -0
- package/dist/edge.js.map +1 -0
- package/dist/index.cjs +1585 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +594 -0
- package/dist/index.d.ts +594 -0
- package/dist/index.js +1559 -0
- package/dist/index.js.map +1 -0
- package/package.json +138 -4
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error hierarchy of the SDK.
|
|
3
|
+
*
|
|
4
|
+
* ShieldLabsError
|
|
5
|
+
* ApiError (the server answered with an error status or an unusable body)
|
|
6
|
+
* BadRequestError (400), AuthenticationError (401, 403), QuotaExceededError (402),
|
|
7
|
+
* NotFoundError (404), RateLimitError (429), ServerError (5xx)
|
|
8
|
+
* ConnectionError (network failure), TimeoutError (per-attempt timeout)
|
|
9
|
+
* SignatureVerificationError, WebhookParseError
|
|
10
|
+
* ValidationError (invalid arguments, detected before any HTTP request)
|
|
11
|
+
*/
|
|
12
|
+
/** Minimal view of response headers (a `Headers` object satisfies it). */
|
|
13
|
+
interface HeadersLike {
|
|
14
|
+
get(name: string): string | null;
|
|
15
|
+
}
|
|
16
|
+
/** Base class of every error thrown by this SDK. */
|
|
17
|
+
declare class ShieldLabsError extends Error {
|
|
18
|
+
name: string;
|
|
19
|
+
constructor(message: string, options?: {
|
|
20
|
+
cause?: unknown;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
interface ApiErrorOptions {
|
|
24
|
+
status: number;
|
|
25
|
+
/** Parsed response body: a JSON value when the body parses as JSON, the raw text otherwise, null when empty. */
|
|
26
|
+
body?: unknown;
|
|
27
|
+
headers?: HeadersLike | undefined;
|
|
28
|
+
cause?: unknown;
|
|
29
|
+
}
|
|
30
|
+
/** The server answered with an error status (or a success status with an unusable body). */
|
|
31
|
+
declare class ApiError extends ShieldLabsError {
|
|
32
|
+
name: string;
|
|
33
|
+
/** HTTP status code. */
|
|
34
|
+
readonly status: number;
|
|
35
|
+
/** Parsed response body: JSON value, raw text, or null when the body was empty. */
|
|
36
|
+
readonly body: unknown;
|
|
37
|
+
/** Response headers. */
|
|
38
|
+
readonly headers: HeadersLike;
|
|
39
|
+
constructor(message: string, options: ApiErrorOptions);
|
|
40
|
+
}
|
|
41
|
+
/** HTTP 400. */
|
|
42
|
+
declare class BadRequestError extends ApiError {
|
|
43
|
+
name: string;
|
|
44
|
+
}
|
|
45
|
+
/** HTTP 401 or 403: the key, secret or domain is wrong, or the domain is disabled. */
|
|
46
|
+
declare class AuthenticationError extends ApiError {
|
|
47
|
+
name: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* HTTP 402. Neither the History API nor the Management API returns it today: an account over its
|
|
51
|
+
* included volume keeps working and its profile shows a negative remaining count.
|
|
52
|
+
*/
|
|
53
|
+
declare class QuotaExceededError extends ApiError {
|
|
54
|
+
name: string;
|
|
55
|
+
}
|
|
56
|
+
/** HTTP 404: usually a wrong base URL or path. */
|
|
57
|
+
declare class NotFoundError extends ApiError {
|
|
58
|
+
name: string;
|
|
59
|
+
}
|
|
60
|
+
/** HTTP 429. */
|
|
61
|
+
declare class RateLimitError extends ApiError {
|
|
62
|
+
name: string;
|
|
63
|
+
/** Seconds to wait, from the Retry-After header, when the server sent one. */
|
|
64
|
+
readonly retryAfter: number | undefined;
|
|
65
|
+
constructor(message: string, options: ApiErrorOptions & {
|
|
66
|
+
retryAfter?: number | undefined;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/** HTTP 5xx, including gateway errors from edge proxies. */
|
|
70
|
+
declare class ServerError extends ApiError {
|
|
71
|
+
name: string;
|
|
72
|
+
}
|
|
73
|
+
/** The request never produced an HTTP response (DNS, TLS, connection reset, and so on). */
|
|
74
|
+
declare class ConnectionError extends ShieldLabsError {
|
|
75
|
+
name: string;
|
|
76
|
+
}
|
|
77
|
+
/** A request attempt took longer than the configured timeout. */
|
|
78
|
+
declare class TimeoutError extends ShieldLabsError {
|
|
79
|
+
name: string;
|
|
80
|
+
}
|
|
81
|
+
/** The X-Shield-Signature header is missing, malformed or does not match the body. */
|
|
82
|
+
declare class SignatureVerificationError extends ShieldLabsError {
|
|
83
|
+
name: string;
|
|
84
|
+
}
|
|
85
|
+
/** The webhook body is authentic but is not a usable ShieldLabs event. */
|
|
86
|
+
declare class WebhookParseError extends ShieldLabsError {
|
|
87
|
+
name: string;
|
|
88
|
+
}
|
|
89
|
+
/** An argument is invalid. Thrown before any HTTP request is sent. */
|
|
90
|
+
declare class ValidationError extends ShieldLabsError {
|
|
91
|
+
name: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Identifier types the History API can search by. */
|
|
95
|
+
type LookupType = 'ip' | 'user_hid' | 'visitor_id' | 'request_id' | 'device_id' | 'session_id' | 'cookie_id';
|
|
96
|
+
/** The three risk bands: trusted 0-29, suspicious 30-59, dangerous 60-100. */
|
|
97
|
+
type RiskBand = 'trusted' | 'suspicious' | 'dangerous';
|
|
98
|
+
/**
|
|
99
|
+
* Connection type of an identification. Known values are listed; unknown strings are kept as sent.
|
|
100
|
+
*/
|
|
101
|
+
type ConnectionType = 'direct' | 'mobile' | 'vpn' | 'proxy' | 'tor' | 'privacy_relay' | 'browser_vpn_proxy' | 'unknown' | (string & {});
|
|
102
|
+
/** An IP address with its country. */
|
|
103
|
+
interface IpInfo {
|
|
104
|
+
/** Dotted IPv4 address, or "" when none is known. */
|
|
105
|
+
ip: string;
|
|
106
|
+
/** English country name (for example "Germany"), or "" when unknown. */
|
|
107
|
+
country: string;
|
|
108
|
+
}
|
|
109
|
+
/** Where the visit came from. Every value is a string, "" when absent. */
|
|
110
|
+
interface TrafficSource {
|
|
111
|
+
channel: string;
|
|
112
|
+
referrer_domain: string;
|
|
113
|
+
landing_url: string;
|
|
114
|
+
click_id_type: string;
|
|
115
|
+
utm_source: string;
|
|
116
|
+
utm_medium: string;
|
|
117
|
+
utm_campaign: string;
|
|
118
|
+
utm_content: string;
|
|
119
|
+
utm_term: string;
|
|
120
|
+
}
|
|
121
|
+
/** One weighted risk signal behind the Risk Score. Display and log these; branch on detection_flags. */
|
|
122
|
+
interface IdentificationSignal {
|
|
123
|
+
/** Signal slug, for example "vpn" or "antidetect_browser". An open set: see SIGNALS for known values. */
|
|
124
|
+
name: string;
|
|
125
|
+
/** Weight of the signal. Can be negative. Never sum weights yourself. */
|
|
126
|
+
weight: number;
|
|
127
|
+
/** Server description of the signal (History API rows only; null for webhooks). */
|
|
128
|
+
description: string | null;
|
|
129
|
+
}
|
|
130
|
+
/** The 19 stable detection flags. A flag the server did not send is false. */
|
|
131
|
+
interface DetectionFlags {
|
|
132
|
+
vpn: boolean;
|
|
133
|
+
privacy_relay: boolean;
|
|
134
|
+
browser_vpn_proxy: boolean;
|
|
135
|
+
tor: boolean;
|
|
136
|
+
proxy: boolean;
|
|
137
|
+
datacenter_ip: boolean;
|
|
138
|
+
abuser: boolean;
|
|
139
|
+
os_mismatch: boolean;
|
|
140
|
+
os_not_detected: boolean;
|
|
141
|
+
timezone_mismatch: boolean;
|
|
142
|
+
anti_detect_browser: boolean;
|
|
143
|
+
browser_automation: boolean;
|
|
144
|
+
ip_mismatch: boolean;
|
|
145
|
+
incognito: boolean;
|
|
146
|
+
search_bot: boolean;
|
|
147
|
+
suspicious_paid_click: boolean;
|
|
148
|
+
javascript_disabled: boolean;
|
|
149
|
+
stun_not_checked: boolean;
|
|
150
|
+
check_incomplete: boolean;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* One identification (one run of the ShieldLabs agent in one browser), normalized from a
|
|
154
|
+
* webhook `data` object or a History API row. Property names follow the webhook JSON.
|
|
155
|
+
*/
|
|
156
|
+
interface Identification {
|
|
157
|
+
/** UUID of the identification, created in the browser. */
|
|
158
|
+
request_id: string;
|
|
159
|
+
/** Server-side visitor identifier (sticky to the device). */
|
|
160
|
+
visitor_id: string;
|
|
161
|
+
/** Server-side device identifier. The all-zero UUID means no usable device signals. */
|
|
162
|
+
device_id: string;
|
|
163
|
+
/** One visit on one origin. */
|
|
164
|
+
session_id: string;
|
|
165
|
+
/** First-party browser identifier kept by the agent. */
|
|
166
|
+
cookie_id: string;
|
|
167
|
+
/** Your User HID as sent by the browser: "anonymous" for anonymous checks, null when it was empty. */
|
|
168
|
+
user_hid: string | null;
|
|
169
|
+
/** Registered domain of the site. */
|
|
170
|
+
domain: string;
|
|
171
|
+
public_ip: IpInfo;
|
|
172
|
+
local_ip: IpInfo;
|
|
173
|
+
connection_type: ConnectionType;
|
|
174
|
+
os: string;
|
|
175
|
+
browser: string;
|
|
176
|
+
/** "desktop", "mobile", "tablet" or "unknown". */
|
|
177
|
+
device_type: string;
|
|
178
|
+
traffic_source: TrafficSource;
|
|
179
|
+
/** Integer 0-100. A value above 100 (999) is a rate-limit marker, never a score. */
|
|
180
|
+
risk_score: number;
|
|
181
|
+
signals: IdentificationSignal[];
|
|
182
|
+
detection_flags: DetectionFlags;
|
|
183
|
+
/**
|
|
184
|
+
* When the identification was observed, as an RFC 3339 UTC string with milliseconds
|
|
185
|
+
* (for example "2026-09-30T12:34:56.123Z"). null only when the server sent a timestamp
|
|
186
|
+
* that could not be parsed.
|
|
187
|
+
*/
|
|
188
|
+
observed_at: string | null;
|
|
189
|
+
/** Which payload this identification was built from. */
|
|
190
|
+
source: 'webhook' | 'history';
|
|
191
|
+
/** The original webhook `data` object or History row, including fields this model omits. */
|
|
192
|
+
raw: Record<string, unknown>;
|
|
193
|
+
}
|
|
194
|
+
/** One page of History API results. */
|
|
195
|
+
interface HistoryPage {
|
|
196
|
+
/** Identifications, newest first. */
|
|
197
|
+
data: Identification[];
|
|
198
|
+
/** Total number of identifications that match the lookup. */
|
|
199
|
+
total: number;
|
|
200
|
+
}
|
|
201
|
+
/** Domain profile from the Management API. */
|
|
202
|
+
interface DomainProfile {
|
|
203
|
+
/** The registered domain. */
|
|
204
|
+
domain: string;
|
|
205
|
+
/** Remaining included identifications. Negative when the account is over its included volume. */
|
|
206
|
+
remaining_identifications: number;
|
|
207
|
+
/** Public Key with every character except the last 4 replaced by "*". */
|
|
208
|
+
public_key_masked: string;
|
|
209
|
+
/** Secret Key with every character except the last 4 replaced by "*". */
|
|
210
|
+
secret_key_masked: string;
|
|
211
|
+
/** When the domain was created, as an RFC 3339 UTC string with milliseconds, or null. */
|
|
212
|
+
created_at: string | null;
|
|
213
|
+
/** The original response object. */
|
|
214
|
+
raw: Record<string, unknown>;
|
|
215
|
+
}
|
|
216
|
+
declare enum UnknownEventTypeMarker {
|
|
217
|
+
/** Placeholder member. Never compare against it. */
|
|
218
|
+
Unknown = "unknown"
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Type of `event_type` for an event this SDK version does not model. At runtime the value is the
|
|
222
|
+
* plain string the server sent (for example "identification.refined"). This type only exists so
|
|
223
|
+
* that `switch (event.event_type)` narrows the known event types exactly; it is assignable to
|
|
224
|
+
* `string`, and `String(event.event_type)` compares it with other strings. A type only: there is
|
|
225
|
+
* no runtime value to import.
|
|
226
|
+
*/
|
|
227
|
+
type UnknownEventType = UnknownEventTypeMarker;
|
|
228
|
+
/** A verified `identification.scored` delivery. */
|
|
229
|
+
interface IdentificationScoredEvent {
|
|
230
|
+
event_type: 'identification.scored';
|
|
231
|
+
schema_version: string;
|
|
232
|
+
/** Envelope timestamp as sent (RFC 3339). */
|
|
233
|
+
created_at: string;
|
|
234
|
+
data: Identification;
|
|
235
|
+
/** The parsed envelope as received. */
|
|
236
|
+
raw: Record<string, unknown>;
|
|
237
|
+
}
|
|
238
|
+
/** A verified `webhook.ping` delivery (sent by Verify in the analytics dashboard). */
|
|
239
|
+
interface WebhookPingEvent {
|
|
240
|
+
event_type: 'webhook.ping';
|
|
241
|
+
schema_version: string;
|
|
242
|
+
created_at: string;
|
|
243
|
+
raw: Record<string, unknown>;
|
|
244
|
+
}
|
|
245
|
+
/** A verified delivery with an event type this SDK version does not model. */
|
|
246
|
+
interface UnknownWebhookEvent {
|
|
247
|
+
event_type: UnknownEventType;
|
|
248
|
+
schema_version: string;
|
|
249
|
+
created_at: string;
|
|
250
|
+
raw: Record<string, unknown>;
|
|
251
|
+
}
|
|
252
|
+
/** Every event `webhooks.constructEvent` can return. */
|
|
253
|
+
type WebhookEvent = IdentificationScoredEvent | WebhookPingEvent | UnknownWebhookEvent;
|
|
254
|
+
/** Raw webhook body: the exact bytes received, or the same bytes decoded as UTF-8. */
|
|
255
|
+
type WebhookPayload = string | Uint8Array | ArrayBuffer;
|
|
256
|
+
/** Value of the X-Shield-Signature header, as your framework exposes it. */
|
|
257
|
+
type SignatureHeader = string | readonly string[] | null | undefined;
|
|
258
|
+
/** One endpoint signing secret, or several while you rotate secrets. */
|
|
259
|
+
type WebhookSecret = string | readonly string[];
|
|
260
|
+
/** Minimal response shape the SDK needs from a fetch implementation. */
|
|
261
|
+
interface FetchResponseLike {
|
|
262
|
+
status: number;
|
|
263
|
+
ok: boolean;
|
|
264
|
+
headers: {
|
|
265
|
+
get(name: string): string | null;
|
|
266
|
+
};
|
|
267
|
+
text(): Promise<string>;
|
|
268
|
+
}
|
|
269
|
+
/** Request options the SDK passes to a fetch implementation. */
|
|
270
|
+
interface FetchRequestInit {
|
|
271
|
+
method: 'GET';
|
|
272
|
+
headers: Record<string, string>;
|
|
273
|
+
signal: AbortSignal;
|
|
274
|
+
}
|
|
275
|
+
/** A fetch-compatible function (the global `fetch` satisfies it). */
|
|
276
|
+
type FetchLike = (url: string, init: FetchRequestInit) => Promise<FetchResponseLike>;
|
|
277
|
+
|
|
278
|
+
/** Webhook signature verification and typed event parsing. */
|
|
279
|
+
interface Webhooks {
|
|
280
|
+
/**
|
|
281
|
+
* True when `signatureHeader` (X-Shield-Signature) is a valid signature of `payload` for any
|
|
282
|
+
* of the given secrets. Returns false for a malformed header, an empty secret or a payload that
|
|
283
|
+
* is not raw bytes or a string. Needs node:crypto: in edge runtimes use `verifySignatureAsync`.
|
|
284
|
+
*/
|
|
285
|
+
verifySignature(payload: WebhookPayload, signatureHeader: SignatureHeader, secret: WebhookSecret): boolean;
|
|
286
|
+
/**
|
|
287
|
+
* Verifies the signature, then parses the body into a typed event.
|
|
288
|
+
* Throws SignatureVerificationError or WebhookParseError.
|
|
289
|
+
* Needs node:crypto: in edge runtimes use `constructEventAsync`.
|
|
290
|
+
*/
|
|
291
|
+
constructEvent(payload: WebhookPayload, signatureHeader: SignatureHeader, secret: WebhookSecret): WebhookEvent;
|
|
292
|
+
/** Same as `verifySignature`, using WebCrypto where node:crypto is not available. */
|
|
293
|
+
verifySignatureAsync(payload: WebhookPayload, signatureHeader: SignatureHeader, secret: WebhookSecret): Promise<boolean>;
|
|
294
|
+
/** Same as `constructEvent`, using WebCrypto where node:crypto is not available. */
|
|
295
|
+
constructEventAsync(payload: WebhookPayload, signatureHeader: SignatureHeader, secret: WebhookSecret): Promise<WebhookEvent>;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
type ApiName = 'History API' | 'Management API';
|
|
299
|
+
interface TransportOptions {
|
|
300
|
+
apiName: ApiName;
|
|
301
|
+
/** Normalized base URL without a trailing slash. */
|
|
302
|
+
baseUrl: string;
|
|
303
|
+
/** Credential headers sent with every request. */
|
|
304
|
+
headers: Record<string, string>;
|
|
305
|
+
/** Credentials that must never appear in an error message or cause. */
|
|
306
|
+
secrets: readonly string[];
|
|
307
|
+
/** Per-attempt timeout in milliseconds. */
|
|
308
|
+
timeout: number;
|
|
309
|
+
maxRetries: number;
|
|
310
|
+
/** False for the Management API: a 429 there starts a 10-minute block, so it is never retried. */
|
|
311
|
+
retryRateLimited: boolean;
|
|
312
|
+
fetch: FetchLike | undefined;
|
|
313
|
+
}
|
|
314
|
+
interface RequestOptions {
|
|
315
|
+
query?: Record<string, string> | undefined;
|
|
316
|
+
signal?: AbortSignal | undefined;
|
|
317
|
+
/** Overrides the transport's maxRetries for this call. */
|
|
318
|
+
maxRetries?: number | undefined;
|
|
319
|
+
/** Caps the attempt timeout of this call in milliseconds; the client timeout still applies. */
|
|
320
|
+
timeout?: number | undefined;
|
|
321
|
+
}
|
|
322
|
+
interface JsonResponse {
|
|
323
|
+
body: unknown;
|
|
324
|
+
status: number;
|
|
325
|
+
headers: HeadersLike;
|
|
326
|
+
}
|
|
327
|
+
/** Sends GET requests with timeouts, retries and error mapping. Safe for concurrent use. */
|
|
328
|
+
declare class Transport {
|
|
329
|
+
#private;
|
|
330
|
+
constructor(options: TransportOptions);
|
|
331
|
+
/** The client's per-attempt timeout in milliseconds. */
|
|
332
|
+
get timeout(): number;
|
|
333
|
+
getJson(path: string, options?: RequestOptions): Promise<JsonResponse>;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** Options of the History API client. */
|
|
337
|
+
interface ShieldLabsOptions {
|
|
338
|
+
/** Private API Key of the domain (sec_...). Keep it on your server. */
|
|
339
|
+
apiKey: string;
|
|
340
|
+
/** Origin of the History API. Default https://account.shieldlabs.ai. A trailing /api is removed. */
|
|
341
|
+
baseUrl?: string | undefined;
|
|
342
|
+
/** Timeout of one HTTP attempt in milliseconds. Default 10 000. */
|
|
343
|
+
timeout?: number | undefined;
|
|
344
|
+
/** Retries for connection errors, timeouts, 429 and 5xx. Default 2. */
|
|
345
|
+
maxRetries?: number | undefined;
|
|
346
|
+
/** Custom fetch implementation. Default: the global fetch. */
|
|
347
|
+
fetch?: FetchLike | undefined;
|
|
348
|
+
/**
|
|
349
|
+
* Accept a plain http `baseUrl` on a host other than localhost, 127.0.0.1 or [::1], for a test
|
|
350
|
+
* server. The key then travels unencrypted. Default false.
|
|
351
|
+
*/
|
|
352
|
+
allowInsecureHttp?: boolean | undefined;
|
|
353
|
+
}
|
|
354
|
+
/** Options of `history.search`. */
|
|
355
|
+
interface SearchOptions {
|
|
356
|
+
/** Page size from 1 to 100. Default 20. */
|
|
357
|
+
limit?: number | undefined;
|
|
358
|
+
/** Number of rows to skip. Default 0. */
|
|
359
|
+
offset?: number | undefined;
|
|
360
|
+
signal?: AbortSignal | undefined;
|
|
361
|
+
}
|
|
362
|
+
/** Options of `history.iterate`. */
|
|
363
|
+
interface IterateOptions {
|
|
364
|
+
/** Rows per request from 1 to 100. Default 100. */
|
|
365
|
+
pageSize?: number | undefined;
|
|
366
|
+
/** Stop after this many identifications. Default: no limit. */
|
|
367
|
+
maxItems?: number | undefined;
|
|
368
|
+
signal?: AbortSignal | undefined;
|
|
369
|
+
}
|
|
370
|
+
/** Options of `identifications.get`. */
|
|
371
|
+
interface GetIdentificationOptions {
|
|
372
|
+
/** Poll until the identification appears (true) or read once (false). Default true. */
|
|
373
|
+
wait?: boolean | undefined;
|
|
374
|
+
/**
|
|
375
|
+
* Total time budget of the wait in milliseconds, counted from the call. Default 10 000. The
|
|
376
|
+
* last poll runs at this deadline. Each poll is one HTTP attempt whose timeout is the client
|
|
377
|
+
* timeout, shortened to the time left but never below 1 second, so the last poll can end up
|
|
378
|
+
* to 1 second after the deadline. Pass `signal` (for example `AbortSignal.timeout(11_000)`)
|
|
379
|
+
* for a hard limit that also cancels a request in flight.
|
|
380
|
+
*/
|
|
381
|
+
timeout?: number | undefined;
|
|
382
|
+
/**
|
|
383
|
+
* Base wait between polls in milliseconds. The waits are 1, 2, 4 and 6 times this value, then 8
|
|
384
|
+
* times it for every later wait, each capped at 2 000 or at this value when it is longer.
|
|
385
|
+
* Default 250, which gives waits of 250, 500, 1 000, 1 500 and then 2 000; 1 000 gives 1 000
|
|
386
|
+
* and then 2 000; 3 000 gives 3 000 every time.
|
|
387
|
+
*/
|
|
388
|
+
pollInterval?: number | undefined;
|
|
389
|
+
signal?: AbortSignal | undefined;
|
|
390
|
+
}
|
|
391
|
+
/** Reads identifications from the History API. */
|
|
392
|
+
declare class HistoryResource {
|
|
393
|
+
#private;
|
|
394
|
+
constructor(transport: Transport);
|
|
395
|
+
/**
|
|
396
|
+
* One page of identifications for one identifier, newest first.
|
|
397
|
+
* `GET /api/v1/history/{type}/{value}`.
|
|
398
|
+
*/
|
|
399
|
+
search(type: LookupType, value: string, options?: SearchOptions): Promise<HistoryPage>;
|
|
400
|
+
/**
|
|
401
|
+
* Every identification for one identifier, newest first, fetched page by page. Rows repeated
|
|
402
|
+
* across pages (new rows can shift offsets) are skipped by request ID. Stops at `total`, at an
|
|
403
|
+
* empty page or after `maxItems`.
|
|
404
|
+
*/
|
|
405
|
+
iterate(type: LookupType, value: string, options?: IterateOptions): AsyncGenerator<Identification, void, undefined>;
|
|
406
|
+
}
|
|
407
|
+
/** Reads single identifications by request ID. */
|
|
408
|
+
declare class IdentificationsResource {
|
|
409
|
+
#private;
|
|
410
|
+
constructor(transport: Transport);
|
|
411
|
+
/**
|
|
412
|
+
* The identification with this request ID, or null when none is found.
|
|
413
|
+
*
|
|
414
|
+
* Scoring is asynchronous: the row appears about 1 to 3 seconds after the browser call and can
|
|
415
|
+
* be refined for up to about 10 seconds while follow-up checks finish; this returns the first
|
|
416
|
+
* version it sees. With `wait` (the default), `timeout` is the total budget of the call:
|
|
417
|
+
*
|
|
418
|
+
* - The first poll runs at once. The waits between polls are `pollInterval` times 1, 2, 4 and 6,
|
|
419
|
+
* then 8 times it for every later wait, each capped at max(2 s, `pollInterval`): 250 ms,
|
|
420
|
+
* 500 ms, 1 s, 1.5 s and then every 2 s by default, and every 3 s for a `pollInterval` of
|
|
421
|
+
* 3 s. A wait that would pass the deadline is cut short, so the last poll runs at the
|
|
422
|
+
* deadline.
|
|
423
|
+
* - Each poll is one HTTP attempt without retries, with the timeout
|
|
424
|
+
* min(client timeout, max(time left, 1 s)).
|
|
425
|
+
* - 429, 5xx, connection errors and timeouts do not end the wait. After a 429 the next wait is
|
|
426
|
+
* the longest of the scheduled wait, 1 s and the Retry-After capped at 10 s (a missing
|
|
427
|
+
* Retry-After, 0 or a past date counts as 0), cut short at the deadline like any other wait.
|
|
428
|
+
* When the capped Retry-After is longer than the time left, that RateLimitError is thrown at
|
|
429
|
+
* once.
|
|
430
|
+
* - At the deadline, the error of the last poll is thrown if it failed; otherwise the result
|
|
431
|
+
* is null.
|
|
432
|
+
* - 400, 401, 403 and 404 (and any other error that another poll cannot fix) are thrown at once.
|
|
433
|
+
*/
|
|
434
|
+
get(requestId: string, options?: GetIdentificationOptions): Promise<Identification | null>;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Client for the History API (`https://account.shieldlabs.ai`), authenticated with the Private
|
|
438
|
+
* API Key of one domain. Stateless apart from its configuration, so one instance can be shared
|
|
439
|
+
* by concurrent requests.
|
|
440
|
+
*/
|
|
441
|
+
declare class ShieldLabs {
|
|
442
|
+
/** Single identifications by request ID, with wait-for-verdict polling. */
|
|
443
|
+
readonly identifications: IdentificationsResource;
|
|
444
|
+
/** History lookups by identifier. */
|
|
445
|
+
readonly history: HistoryResource;
|
|
446
|
+
constructor(options: ShieldLabsOptions);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/** Options of the Management API client. */
|
|
450
|
+
interface ShieldLabsManagementOptions {
|
|
451
|
+
/** Secret Key of the domain. Keep it on your server. */
|
|
452
|
+
secretKey: string;
|
|
453
|
+
/** The registered domain, for example "example.com". Normalized before it is sent. */
|
|
454
|
+
domain: string;
|
|
455
|
+
/** Origin of the Management API. Default https://api.shieldlabs.ai. */
|
|
456
|
+
baseUrl?: string | undefined;
|
|
457
|
+
/** Timeout of one HTTP attempt in milliseconds. Default 10 000. */
|
|
458
|
+
timeout?: number | undefined;
|
|
459
|
+
/** Retries for connection errors, timeouts and 5xx (never for 429). Default 2. */
|
|
460
|
+
maxRetries?: number | undefined;
|
|
461
|
+
/** Custom fetch implementation. Default: the global fetch. */
|
|
462
|
+
fetch?: FetchLike | undefined;
|
|
463
|
+
/**
|
|
464
|
+
* Accept a plain http `baseUrl` on a host other than localhost, 127.0.0.1 or [::1], for a test
|
|
465
|
+
* server. The Secret Key then travels unencrypted. Default false.
|
|
466
|
+
*/
|
|
467
|
+
allowInsecureHttp?: boolean | undefined;
|
|
468
|
+
}
|
|
469
|
+
/** Options of `getProfile`. */
|
|
470
|
+
interface GetProfileOptions {
|
|
471
|
+
signal?: AbortSignal | undefined;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Client for the Management API (`https://api.shieldlabs.ai`), authenticated with the Secret Key
|
|
475
|
+
* and the registered domain. The API allows about 15 requests per minute per IP and then blocks
|
|
476
|
+
* the IP for 10 minutes, so this client never retries a 429: call it sparingly and cache results.
|
|
477
|
+
* Safe for concurrent use.
|
|
478
|
+
*/
|
|
479
|
+
declare class ShieldLabsManagement {
|
|
480
|
+
#private;
|
|
481
|
+
/** The normalized domain sent in X-Shield-Domain. */
|
|
482
|
+
readonly domain: string;
|
|
483
|
+
constructor(options: ShieldLabsManagementOptions);
|
|
484
|
+
/** The domain profile: remaining identifications and masked keys. `GET /v1/profile`. */
|
|
485
|
+
getProfile(options?: GetProfileOptions): Promise<DomainProfile>;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Risk band for a Risk Score: trusted 0-29, suspicious 30-59, dangerous 60-100.
|
|
490
|
+
* A score above 100 (the 999 marker) is not a score: it returns "rate_limited".
|
|
491
|
+
*/
|
|
492
|
+
declare function riskBand(score: number): RiskBand | 'rate_limited';
|
|
493
|
+
/** True for the rate-limit marker (a Risk Score above 100, sent as 999). */
|
|
494
|
+
declare function isRateLimited(score: number): boolean;
|
|
495
|
+
/** Why an identification did not pass `evaluateIdentification`. */
|
|
496
|
+
type EvaluationReason = 'missing' | 'replayed' | 'stale' | 'rate_limited' | 'no_device_signals' | 'blocked_flag' | 'blocked_band';
|
|
497
|
+
/** Result of `evaluateIdentification`. */
|
|
498
|
+
interface Evaluation {
|
|
499
|
+
/** True when every check passed. */
|
|
500
|
+
ok: boolean;
|
|
501
|
+
/** The first check that failed, or null when `ok` is true. */
|
|
502
|
+
reason: EvaluationReason | null;
|
|
503
|
+
/** Band of the Risk Score ("rate_limited" for the 999 marker), or null when the identification is missing. */
|
|
504
|
+
band: RiskBand | 'rate_limited' | null;
|
|
505
|
+
/** The detection flag that failed the check, when `reason` is "blocked_flag". */
|
|
506
|
+
flag?: keyof DetectionFlags;
|
|
507
|
+
}
|
|
508
|
+
/** Options of `evaluateIdentification`. The defaults are a starting point to tune. */
|
|
509
|
+
interface EvaluateOptions {
|
|
510
|
+
/**
|
|
511
|
+
* Maximum age of the identification in milliseconds, measured from `observed_at`. Default
|
|
512
|
+
* 300 000 (5 minutes). `Infinity` skips the freshness check.
|
|
513
|
+
*/
|
|
514
|
+
maxAge?: number | undefined;
|
|
515
|
+
/** Current time (Date or epoch milliseconds). Default: now. */
|
|
516
|
+
now?: Date | number | undefined;
|
|
517
|
+
/** Bands that fail the check. Default ["dangerous"]. */
|
|
518
|
+
blockBands?: readonly RiskBand[] | undefined;
|
|
519
|
+
/** Detection flags that fail the check. Default ["browser_automation", "javascript_disabled"]. */
|
|
520
|
+
blockFlags?: readonly (keyof DetectionFlags)[] | undefined;
|
|
521
|
+
/**
|
|
522
|
+
* Returns true when this request ID was already used for a protected action. The SDK keeps
|
|
523
|
+
* no state: claim the request ID in your own store first (an atomic insert-if-absent) and
|
|
524
|
+
* return the result here. Must return a boolean synchronously.
|
|
525
|
+
*/
|
|
526
|
+
isReplay?: ((requestId: string) => boolean) | undefined;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Applies a reusable guard policy to an identification. Checks run in this order and the first
|
|
530
|
+
* failure wins: missing identification, replayed request ID (`isReplay`), older than `maxAge`,
|
|
531
|
+
* rate-limit marker, all-zero device ID, a flag in `blockFlags`, a band in `blockBands`.
|
|
532
|
+
*/
|
|
533
|
+
declare function evaluateIdentification(identification: Identification | null | undefined, options?: EvaluateOptions): Evaluation;
|
|
534
|
+
|
|
535
|
+
/** The all-zero UUID. As a device ID it means "no usable device signals". */
|
|
536
|
+
declare const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
537
|
+
/**
|
|
538
|
+
* Known risk signal slugs (`IdentificationSignal.name`). Signal names are an open set: new slugs
|
|
539
|
+
* can appear at any time, so compare against these constants and never treat them as exhaustive.
|
|
540
|
+
*/
|
|
541
|
+
declare const SIGNALS: Readonly<{
|
|
542
|
+
readonly TOR: "tor";
|
|
543
|
+
readonly JAVASCRIPT_DISABLED: "javascript_disabled";
|
|
544
|
+
readonly OS_MISMATCH: "os_mismatch";
|
|
545
|
+
readonly ANTIDETECT_BROWSER: "antidetect_browser";
|
|
546
|
+
readonly PROXY_ROUTED_ANTIDETECT: "proxy_routed_antidetect";
|
|
547
|
+
readonly PORT_SCAN_ROUTED_VIA_PROXY: "port_scan_routed_via_proxy";
|
|
548
|
+
readonly BROWSER_AUTOMATION: "browser_automation";
|
|
549
|
+
readonly STUN_NOT_CHECKED: "stun_not_checked";
|
|
550
|
+
readonly STUN_LATE_CORRECTION: "stun_late_correction";
|
|
551
|
+
readonly OS_NOT_DETECTED: "os_not_detected";
|
|
552
|
+
readonly BROWSER_VPN_PROXY: "browser_vpn_proxy";
|
|
553
|
+
readonly VPN: "vpn";
|
|
554
|
+
readonly PRIVACY_RELAY: "privacy_relay";
|
|
555
|
+
readonly PROXY: "proxy";
|
|
556
|
+
readonly DATACENTER_IP: "datacenter_ip";
|
|
557
|
+
readonly ABUSER: "abuser";
|
|
558
|
+
readonly TIMEZONE_MISMATCH: "timezone_mismatch";
|
|
559
|
+
readonly RATE_LIMITED: "rate_limited";
|
|
560
|
+
}>;
|
|
561
|
+
/** A known signal slug. */
|
|
562
|
+
type KnownSignal = (typeof SIGNALS)[keyof typeof SIGNALS];
|
|
563
|
+
/** Score ranges of the three risk bands (inclusive). */
|
|
564
|
+
declare const RISK_BANDS: Readonly<{
|
|
565
|
+
readonly trusted: Readonly<{
|
|
566
|
+
min: 0;
|
|
567
|
+
max: 29;
|
|
568
|
+
}>;
|
|
569
|
+
readonly suspicious: Readonly<{
|
|
570
|
+
min: 30;
|
|
571
|
+
max: 59;
|
|
572
|
+
}>;
|
|
573
|
+
readonly dangerous: Readonly<{
|
|
574
|
+
min: 60;
|
|
575
|
+
max: 100;
|
|
576
|
+
}>;
|
|
577
|
+
}>;
|
|
578
|
+
|
|
579
|
+
/** Version of this SDK. Sent in the User-Agent header of every request. */
|
|
580
|
+
declare const VERSION = "1.0.0";
|
|
581
|
+
|
|
582
|
+
/** Webhook signature verification (X-Shield-Signature) and typed event parsing. */
|
|
583
|
+
declare const webhooks: Webhooks;
|
|
584
|
+
/**
|
|
585
|
+
* A stable, irreversible User HID for one of your accounts: HMAC-SHA256 of `userId` keyed with
|
|
586
|
+
* `secret`, as 64 lowercase hex characters. Compute it on your server and pass it to the browser
|
|
587
|
+
* agent instead of a raw email address or account ID. Throws ValidationError on empty input.
|
|
588
|
+
* Needs node:crypto: in edge runtimes use `userHidAsync`.
|
|
589
|
+
*/
|
|
590
|
+
declare function userHid(userId: string, secret: string): string;
|
|
591
|
+
/** Same as `userHid`, as a promise (works in every runtime). */
|
|
592
|
+
declare function userHidAsync(userId: string, secret: string): Promise<string>;
|
|
593
|
+
|
|
594
|
+
export { ApiError, type ApiErrorOptions, AuthenticationError, BadRequestError, ConnectionError, type ConnectionType, type DetectionFlags, type DomainProfile, type EvaluateOptions, type Evaluation, type EvaluationReason, type FetchLike, type FetchRequestInit, type FetchResponseLike, type GetIdentificationOptions, type GetProfileOptions, type HeadersLike, type HistoryPage, type Identification, type IdentificationScoredEvent, type IdentificationSignal, type IpInfo, type IterateOptions, type KnownSignal, type LookupType, NIL_UUID, NotFoundError, QuotaExceededError, RISK_BANDS, RateLimitError, type RiskBand, SIGNALS, type SearchOptions, ServerError, ShieldLabs, ShieldLabsError, ShieldLabsManagement, type ShieldLabsManagementOptions, type ShieldLabsOptions, type SignatureHeader, SignatureVerificationError, TimeoutError, type TrafficSource, type UnknownEventType, type UnknownWebhookEvent, VERSION, ValidationError, type WebhookEvent, WebhookParseError, type WebhookPayload, type WebhookPingEvent, type WebhookSecret, type Webhooks, evaluateIdentification, isRateLimited, riskBand, userHid, userHidAsync, webhooks };
|