coss 0.2.0 → 0.3.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/device.d.ts +11 -0
- package/dist/device.js +71 -0
- package/dist/index.d.ts +328 -9
- package/dist/index.js +135 -2
- package/package.json +2 -1
package/dist/device.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/device.d.ts
|
|
2
|
+
export interface CollectDeviceOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Where the device id is kept: `local` (default) remembers it in `localStorage`; `memory`
|
|
5
|
+
* keeps it only for this page (for example until the user consents to storage).
|
|
6
|
+
*/
|
|
7
|
+
storage?: "local" | "memory";
|
|
8
|
+
}
|
|
9
|
+
/** Returns a token for `device.token` in `coss.risk.assess()`. Make a new one per submission. */
|
|
10
|
+
export declare function collectDevice(options?: CollectDeviceOptions): string;
|
|
11
|
+
//#endregion
|
package/dist/device.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//#region src/device.ts
|
|
2
|
+
/**
|
|
3
|
+
* `coss/device`: recognizes the browser behind risk events. Call `collectDevice()` in the browser
|
|
4
|
+
* when the user submits a form, send the token to your server with it, and pass it to
|
|
5
|
+
* `coss.risk.assess({ device: { token } })`.
|
|
6
|
+
*
|
|
7
|
+
* The token carries a random id this browser keeps in `localStorage` (`coss_device_id`, no
|
|
8
|
+
* cookies) and coarse facts: time zone, languages, platform, screen size, touch support, and
|
|
9
|
+
* whether the browser is automated (WebDriver, headless). No canvas, WebGL, font or audio
|
|
10
|
+
* fingerprinting: a browser whose storage is cleared looks like a new one. COSS keeps only a keyed
|
|
11
|
+
* hash of the id.
|
|
12
|
+
*
|
|
13
|
+
* Collects nothing until called, and never throws: outside a browser the token simply carries
|
|
14
|
+
* fewer facts.
|
|
15
|
+
*/
|
|
16
|
+
/** The token format version, checked by the API. */
|
|
17
|
+
const TOKEN_PREFIX = "cd1.";
|
|
18
|
+
const STORAGE_KEY = "coss_device_id";
|
|
19
|
+
const HEADLESS = /HeadlessChrome|PhantomJS|SlimerJS/;
|
|
20
|
+
let memoryId;
|
|
21
|
+
function randomId() {
|
|
22
|
+
const bytes = /* @__PURE__ */ new Uint8Array(16);
|
|
23
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
24
|
+
return base64Url(bytes);
|
|
25
|
+
}
|
|
26
|
+
function base64Url(bytes) {
|
|
27
|
+
let binary = "";
|
|
28
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
29
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
30
|
+
}
|
|
31
|
+
function deviceId(storage) {
|
|
32
|
+
if (storage === "local") try {
|
|
33
|
+
const store = globalThis.localStorage;
|
|
34
|
+
if (store) {
|
|
35
|
+
const stored = store.getItem(STORAGE_KEY);
|
|
36
|
+
if (stored && /^[A-Za-z0-9_-]{16,64}$/.test(stored)) return stored;
|
|
37
|
+
const id = randomId();
|
|
38
|
+
store.setItem(STORAGE_KEY, id);
|
|
39
|
+
return id;
|
|
40
|
+
}
|
|
41
|
+
} catch {}
|
|
42
|
+
memoryId ??= randomId();
|
|
43
|
+
return memoryId;
|
|
44
|
+
}
|
|
45
|
+
function safely(read, fallback) {
|
|
46
|
+
try {
|
|
47
|
+
return read() ?? fallback;
|
|
48
|
+
} catch {
|
|
49
|
+
return fallback;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Returns a token for `device.token` in `coss.risk.assess()`. Make a new one per submission. */
|
|
53
|
+
function collectDevice(options = {}) {
|
|
54
|
+
const nav = globalThis.navigator;
|
|
55
|
+
const screen = globalThis.screen;
|
|
56
|
+
const userAgent = safely(() => nav?.userAgent ?? "", "");
|
|
57
|
+
const payload = {
|
|
58
|
+
id: deviceId(options.storage ?? "local"),
|
|
59
|
+
t: Date.now(),
|
|
60
|
+
tz: safely(() => Intl.DateTimeFormat().resolvedOptions().timeZone.slice(0, 64) || null, null),
|
|
61
|
+
l: safely(() => [...nav?.languages ?? []].slice(0, 10).map((l) => l.slice(0, 35)), []),
|
|
62
|
+
p: safely(() => (nav?.userAgentData?.platform || nav?.platform || "").slice(0, 64) || null, null),
|
|
63
|
+
s: safely(() => screen ? [Math.round(screen.width), Math.round(screen.height)] : null, null),
|
|
64
|
+
tp: safely(() => typeof nav?.maxTouchPoints === "number" ? Math.round(nav.maxTouchPoints) : null, null),
|
|
65
|
+
wd: safely(() => nav?.webdriver === true, false),
|
|
66
|
+
hl: HEADLESS.test(userAgent)
|
|
67
|
+
};
|
|
68
|
+
return `${TOKEN_PREFIX}${base64Url(new TextEncoder().encode(JSON.stringify(payload)))}`;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { collectDevice };
|
package/dist/index.d.ts
CHANGED
|
@@ -437,6 +437,15 @@ interface EmailLink {
|
|
|
437
437
|
first_clicked_at: string | null;
|
|
438
438
|
last_clicked_at: string | null;
|
|
439
439
|
}
|
|
440
|
+
/** Why an email failed as a whole. */
|
|
441
|
+
interface EmailFailure {
|
|
442
|
+
/**
|
|
443
|
+
* E.g. `all_recipients_suppressed`, `domain_not_verified`, `content_rejected`,
|
|
444
|
+
* `attachments_unavailable`, `dispatch_failed` or `provider_error`.
|
|
445
|
+
*/
|
|
446
|
+
code: string;
|
|
447
|
+
message: string;
|
|
448
|
+
}
|
|
440
449
|
/** An email as returned by the API. Recipient fields are always arrays. */
|
|
441
450
|
interface Email {
|
|
442
451
|
object: "email";
|
|
@@ -454,6 +463,8 @@ interface Email {
|
|
|
454
463
|
tags: EmailTag[];
|
|
455
464
|
category: string | null;
|
|
456
465
|
status: EmailStatus;
|
|
466
|
+
/** Why the email failed; `null` unless `status` is `"failed"`. */
|
|
467
|
+
failure: EmailFailure | null;
|
|
457
468
|
/** Every distinct recipient across `to`, `cc` and `bcc`, with its delivery status. */
|
|
458
469
|
recipients: EmailRecipient[];
|
|
459
470
|
/** Attachment metadata; the content is discarded once the email is sent. */
|
|
@@ -470,6 +481,31 @@ interface Email {
|
|
|
470
481
|
/** The batch that sent the email (`coss.email.sendBatch`), or `null` if it was sent alone. */
|
|
471
482
|
batch_id: string | null;
|
|
472
483
|
}
|
|
484
|
+
/** An email in a list (`coss.email.list`): everything but its content. */
|
|
485
|
+
type EmailSummary = Omit<Email, "html" | "text" | "headers" | "attachments">;
|
|
486
|
+
/** Filters of `coss.email.list`. Emails are returned newest first. */
|
|
487
|
+
interface ListEmailsParams {
|
|
488
|
+
/** Only emails with this recipient (in `to`, `cc` or `bcc`; the bare address, any case). */
|
|
489
|
+
to?: string;
|
|
490
|
+
/** Only emails with a recipient in one of these statuses (with `to`, that recipient's). */
|
|
491
|
+
recipient_status?: EmailRecipientStatus[];
|
|
492
|
+
/** Only emails in these statuses. */
|
|
493
|
+
status?: EmailStatus[];
|
|
494
|
+
/** Free text, matched against the subject and the `to` addresses. */
|
|
495
|
+
q?: string;
|
|
496
|
+
/** Only emails of this category. */
|
|
497
|
+
category?: string;
|
|
498
|
+
/** Only the emails of this batch. */
|
|
499
|
+
batch_id?: string;
|
|
500
|
+
/** Only emails created at or after this time. */
|
|
501
|
+
created_after?: Date | string;
|
|
502
|
+
/** Only emails created before this time. */
|
|
503
|
+
created_before?: Date | string;
|
|
504
|
+
/** 1-100, default 20. */
|
|
505
|
+
limit?: number;
|
|
506
|
+
/** Cursor: the `id` of the last email of the previous page. */
|
|
507
|
+
after?: string;
|
|
508
|
+
}
|
|
473
509
|
/** Emails sent together by `coss.email.sendBatch`. */
|
|
474
510
|
interface EmailBatch {
|
|
475
511
|
object: "email_batch";
|
|
@@ -1199,6 +1235,12 @@ declare class EmailResource {
|
|
|
1199
1235
|
sendBatch(emails: SendEmailParams[], options?: RequestOptions): Promise<CossResult<EmailBatch>>;
|
|
1200
1236
|
/** Retrieves an email sent from the same environment as the API key. */
|
|
1201
1237
|
get(id: string, options?: Pick<RequestOptions, "signal">): Promise<CossResult<Email>>;
|
|
1238
|
+
/**
|
|
1239
|
+
* Lists emails sent from the same environment as the API key, newest first and without their
|
|
1240
|
+
* content (`get` one for `html`, `text`, `headers` and `attachments`). Pass the last `id` as
|
|
1241
|
+
* `after` while `has_more` is true.
|
|
1242
|
+
*/
|
|
1243
|
+
list(params?: ListEmailsParams, options?: Pick<RequestOptions, "signal">): Promise<CossResult<List<EmailSummary>>>;
|
|
1202
1244
|
/**
|
|
1203
1245
|
* Cancels a scheduled email. Canceling an already canceled email returns it; any other email
|
|
1204
1246
|
* fails with `email_not_cancelable`.
|
|
@@ -1896,9 +1938,16 @@ type RiskList = "allow" | "block";
|
|
|
1896
1938
|
*/
|
|
1897
1939
|
type RiskListEntryType = "email" | "domain" | "ip" | "asn" | "country" | "user";
|
|
1898
1940
|
/** Signal groups an assessment was made without (a lookup failed or timed out). */
|
|
1899
|
-
type RiskDegradedSignal = "email_dns" | "domain_age" | "ip_data" | "velocity" | "captcha";
|
|
1941
|
+
type RiskDegradedSignal = "email_dns" | "domain_age" | "ip_data" | "velocity" | "captcha" | "content" | "ip_privacy";
|
|
1942
|
+
/** What content classification scores. */
|
|
1943
|
+
type RiskContentCategory = "spam" | "phishing" | "malware" | "fraud";
|
|
1944
|
+
/**
|
|
1945
|
+
* Per category, the model's probability (0-1) that the content belongs to it. Not calibrated:
|
|
1946
|
+
* pick thresholds by looking at your own traffic.
|
|
1947
|
+
*/
|
|
1948
|
+
type RiskContentScores = Record<RiskContentCategory, number>;
|
|
1900
1949
|
/** Every reason an assessment can give (see the reason catalog in the docs). */
|
|
1901
|
-
type RiskReasonCode = "email.invalid" | "email.disposable" | "email.undeliverable" | "email.role_account" | "email.typo" | "email.domain_new" | "ip.tor" | "ip.vpn_network" | "ip.hosting_provider" | "ip.private" | "velocity.signups_per_ip_1h" | "velocity.signups_per_ip_24h" | "velocity.signups_per_subnet_1h" | "velocity.signups_per_email_domain_1h" | "velocity.signups_per_mailbox_24h" | "velocity.logins_per_ip_1h" | "velocity.logins_per_user_1h" | "velocity.events_per_ip_1h" | "velocity.events_per_user_1h" | "duplicate.canonical_mailbox" | "history.fraud_mailbox" | "history.fraud_user" | "history.fraud_ip" | "history.fraud_subnet" | "login.new_country" | "login.new_network" | "captcha.failed" | "captcha.missing" | "rule.matched" | "list.blocked" | "list.allowed";
|
|
1950
|
+
type RiskReasonCode = "email.invalid" | "email.disposable" | "email.undeliverable" | "email.role_account" | "email.typo" | "email.domain_new" | "ip.tor" | "ip.vpn_network" | "ip.hosting_provider" | "ip.vpn" | "ip.proxy" | "ip.relay" | "ip.private" | "velocity.signups_per_ip_1h" | "velocity.signups_per_ip_24h" | "velocity.signups_per_subnet_1h" | "velocity.signups_per_email_domain_1h" | "velocity.signups_per_mailbox_24h" | "velocity.signups_per_device_24h" | "velocity.checkouts_per_ip_1h" | "velocity.checkouts_per_user_1h" | "velocity.checkouts_per_card_24h" | "velocity.logins_per_ip_1h" | "velocity.logins_per_user_1h" | "velocity.events_per_ip_1h" | "velocity.events_per_user_1h" | "duplicate.canonical_mailbox" | "duplicate.device" | "history.fraud_mailbox" | "history.fraud_user" | "history.fraud_ip" | "history.fraud_subnet" | "history.fraud_card" | "history.fraud_device" | "checkout.card_country_mismatch" | "checkout.billing_country_mismatch" | "checkout.prepaid_card" | "device.automation" | "device.invalid" | "login.new_country" | "login.new_network" | "captcha.failed" | "captcha.missing" | "content.spam" | "content.phishing" | "content.malware" | "content.fraud" | "rule.matched" | "list.blocked" | "list.allowed";
|
|
1902
1951
|
/** Why an assessment decided what it did. Never show reasons to the person being assessed. */
|
|
1903
1952
|
interface RiskReason {
|
|
1904
1953
|
code: RiskReasonCode;
|
|
@@ -1911,11 +1960,11 @@ interface RiskReason {
|
|
|
1911
1960
|
window?: "1h" | "24h";
|
|
1912
1961
|
/** `email.typo`: the likely domain, which you may show the user ("Did you mean …?"). */
|
|
1913
1962
|
suggestion?: string;
|
|
1914
|
-
/** `ip.hosting_provider`, `ip.vpn_network`: the network's operator. */
|
|
1963
|
+
/** `ip.hosting_provider`, `ip.vpn_network`: the network's operator; `ip.vpn`: the VPN service. */
|
|
1915
1964
|
provider?: string;
|
|
1916
|
-
/** `duplicate
|
|
1965
|
+
/** `duplicate.*`: your id of the user who has the mailbox or device, if known. */
|
|
1917
1966
|
previous_user?: string | null;
|
|
1918
|
-
/** `duplicate
|
|
1967
|
+
/** `duplicate.*`: the assessment that first saw the mailbox or device. */
|
|
1919
1968
|
previous_assessment?: string;
|
|
1920
1969
|
/** `list.*`: the matching list entry. */
|
|
1921
1970
|
entry?: string;
|
|
@@ -1963,6 +2012,45 @@ interface RiskIpSignals {
|
|
|
1963
2012
|
as_name: string | null;
|
|
1964
2013
|
/** ISO 3166-1 alpha-2. */
|
|
1965
2014
|
country: string | null;
|
|
2015
|
+
/**
|
|
2016
|
+
* From COSS's IP privacy data provider; `null` when it isn't available or was not asked
|
|
2017
|
+
* (private addresses).
|
|
2018
|
+
*/
|
|
2019
|
+
privacy: RiskIpPrivacy | null;
|
|
2020
|
+
}
|
|
2021
|
+
/** Whether an address is a VPN exit, a proxy or a privacy relay (iCloud Private Relay…). */
|
|
2022
|
+
interface RiskIpPrivacy {
|
|
2023
|
+
vpn: boolean;
|
|
2024
|
+
proxy: boolean;
|
|
2025
|
+
relay: boolean;
|
|
2026
|
+
/** The VPN or proxy service. */
|
|
2027
|
+
service: string | null;
|
|
2028
|
+
}
|
|
2029
|
+
/** How a card is funded, as your payment processor reports it. */
|
|
2030
|
+
type RiskCardFunding = "credit" | "debit" | "prepaid" | "unknown";
|
|
2031
|
+
/** What you sent in `checkout` (never the card). */
|
|
2032
|
+
interface RiskCheckoutSignals {
|
|
2033
|
+
amount: number;
|
|
2034
|
+
currency: string;
|
|
2035
|
+
card_country: string | null;
|
|
2036
|
+
card_funding: RiskCardFunding | null;
|
|
2037
|
+
billing_country: string | null;
|
|
2038
|
+
shipping_country: string | null;
|
|
2039
|
+
}
|
|
2040
|
+
/** What the browser reported through `coss/device` (its device id is only kept as a keyed hash). */
|
|
2041
|
+
interface RiskDeviceSignals {
|
|
2042
|
+
/** `false`: the token was malformed or too old. */
|
|
2043
|
+
valid: boolean;
|
|
2044
|
+
/** WebDriver control or a headless browser. */
|
|
2045
|
+
automation: boolean;
|
|
2046
|
+
/** IANA time zone (`Europe/London`). */
|
|
2047
|
+
timezone: string | null;
|
|
2048
|
+
/** The browser's first language. */
|
|
2049
|
+
language: string | null;
|
|
2050
|
+
platform: string | null;
|
|
2051
|
+
/** `<width>x<height>` in CSS pixels. */
|
|
2052
|
+
screen: string | null;
|
|
2053
|
+
touch: boolean | null;
|
|
1966
2054
|
}
|
|
1967
2055
|
/** An assessment of one event. */
|
|
1968
2056
|
interface RiskAssessment {
|
|
@@ -1985,6 +2073,10 @@ interface RiskAssessment {
|
|
|
1985
2073
|
velocity: Record<string, number> | null;
|
|
1986
2074
|
captcha: RiskCaptchaSignals | null;
|
|
1987
2075
|
login: RiskLoginSignals | null;
|
|
2076
|
+
/** `null` when no content was given or it couldn't be classified. */
|
|
2077
|
+
content: RiskContentScores | null;
|
|
2078
|
+
checkout: RiskCheckoutSignals | null;
|
|
2079
|
+
device: RiskDeviceSignals | null;
|
|
1988
2080
|
};
|
|
1989
2081
|
user: {
|
|
1990
2082
|
id: string | null;
|
|
@@ -2022,6 +2114,38 @@ interface AssessRiskParams {
|
|
|
2022
2114
|
captcha?: {
|
|
2023
2115
|
token: string;
|
|
2024
2116
|
};
|
|
2117
|
+
/**
|
|
2118
|
+
* Text the user wrote (a bio, a message, a listing), classified with the event and never
|
|
2119
|
+
* stored: its scores go in `signals.content`, and `content.*` reasons fire only at thresholds
|
|
2120
|
+
* you set.
|
|
2121
|
+
*/
|
|
2122
|
+
content?: {
|
|
2123
|
+
text: string;
|
|
2124
|
+
};
|
|
2125
|
+
/** Only with `checkout` events: what is being paid for, and with which card. */
|
|
2126
|
+
checkout?: {
|
|
2127
|
+
/** In the currency's minor unit (cents for USD: 1999 is $19.99). */
|
|
2128
|
+
amount: number;
|
|
2129
|
+
/** ISO 4217, upper-case (`USD`). */
|
|
2130
|
+
currency: string;
|
|
2131
|
+
/** What your payment processor tells you about the card. */
|
|
2132
|
+
card?: {
|
|
2133
|
+
/**
|
|
2134
|
+
* Your processor's fingerprint of the card number (Stripe: `card.fingerprint`), kept as a
|
|
2135
|
+
* keyed hash only. Never send the card number.
|
|
2136
|
+
*/
|
|
2137
|
+
fingerprint?: string;
|
|
2138
|
+
/** Where the card was issued (ISO 3166-1 alpha-2, upper-case). */
|
|
2139
|
+
country?: string;
|
|
2140
|
+
funding?: RiskCardFunding;
|
|
2141
|
+
};
|
|
2142
|
+
billing_country?: string;
|
|
2143
|
+
shipping_country?: string;
|
|
2144
|
+
};
|
|
2145
|
+
/** What `collectDevice()` from `coss/device` returned in the user's browser. */
|
|
2146
|
+
device?: {
|
|
2147
|
+
token: string;
|
|
2148
|
+
};
|
|
2025
2149
|
}
|
|
2026
2150
|
/** Query of `GET /v1/risk/assessments`. */
|
|
2027
2151
|
interface ListRiskAssessmentsParams {
|
|
@@ -2114,6 +2238,10 @@ interface RiskSettings {
|
|
|
2114
2238
|
provider: RiskCaptchaProvider;
|
|
2115
2239
|
required: boolean;
|
|
2116
2240
|
} | null;
|
|
2241
|
+
/** Per content category, the score at which `content.<category>` fires; `null`: never. */
|
|
2242
|
+
content_thresholds: Record<RiskContentCategory, number | null>;
|
|
2243
|
+
/** Reasons whose weight this environment changed; the rest weigh what the catalog says. */
|
|
2244
|
+
reason_weights: Partial<Record<RiskReasonCode, number>>;
|
|
2117
2245
|
/** ISO 8601 timestamp; `null` while on the defaults. */
|
|
2118
2246
|
updated_at: string | null;
|
|
2119
2247
|
}
|
|
@@ -2130,9 +2258,48 @@ interface UpdateRiskSettingsParams {
|
|
|
2130
2258
|
/** Assessments without a token get `captcha.missing`. */
|
|
2131
2259
|
required?: boolean;
|
|
2132
2260
|
} | null;
|
|
2261
|
+
/** Changes the categories given: a score in (0, 1] sets the threshold, `null` removes it. */
|
|
2262
|
+
content_thresholds?: Partial<Record<RiskContentCategory, number | null>>;
|
|
2263
|
+
/**
|
|
2264
|
+
* Changes the reasons given: a weight in [0, 0.99] replaces the default (for example
|
|
2265
|
+
* calibration's `suggested_weight`), `null` restores it. Not `list.*` or `rule.matched`.
|
|
2266
|
+
*/
|
|
2267
|
+
reason_weights?: Partial<Record<RiskReasonCode, number | null>>;
|
|
2268
|
+
}
|
|
2269
|
+
/** Feedback counted against one reason or rule (`fraud` includes `abuse`). */
|
|
2270
|
+
interface RiskCalibrationCounts {
|
|
2271
|
+
fraud: number;
|
|
2272
|
+
legitimate: number;
|
|
2273
|
+
/** `fraud / (fraud + legitimate)`; `null` without feedback. */
|
|
2274
|
+
precision: number | null;
|
|
2275
|
+
}
|
|
2276
|
+
/** How often each reason and rule was right over the last 90 days, by your feedback. */
|
|
2277
|
+
interface RiskCalibration {
|
|
2278
|
+
object: "risk_calibration";
|
|
2279
|
+
window_days: number;
|
|
2280
|
+
/** Assessments in the window. */
|
|
2281
|
+
assessments: number;
|
|
2282
|
+
/** Of those, with feedback. */
|
|
2283
|
+
labeled: number;
|
|
2284
|
+
reasons: (RiskCalibrationCounts & {
|
|
2285
|
+
code: RiskReasonCode;
|
|
2286
|
+
/** Assessments it fired in. */
|
|
2287
|
+
fired: number;
|
|
2288
|
+
default_weight: number;
|
|
2289
|
+
/** Its weight in this environment now. */
|
|
2290
|
+
weight: number;
|
|
2291
|
+
/** What feedback supports; `null` with fewer than 20 assessments with feedback. */
|
|
2292
|
+
suggested_weight: number | null;
|
|
2293
|
+
})[];
|
|
2294
|
+
rules: (RiskCalibrationCounts & {
|
|
2295
|
+
rule: string;
|
|
2296
|
+
name: string;
|
|
2297
|
+
/** Assessments it decided. */
|
|
2298
|
+
matched: number;
|
|
2299
|
+
})[];
|
|
2133
2300
|
}
|
|
2134
2301
|
/** A field a rule condition can test (see the rules guide). */
|
|
2135
|
-
type RiskRuleField = "email.valid" | "email.disposable" | "email.undeliverable" | "email.role_account" | "email.free_provider" | "email.typo" | "email.domain_new" | "email.domain" | "email.domain_age_days" | "ip.tor" | "ip.hosting" | "ip.vpn" | "ip.private" | "ip.country" | "ip.asn" | "ip.hosting_provider" | "captcha.passed" | "duplicate.canonical_mailbox" | "history.fraud" | "login.new_country" | "login.new_network" | "score" | "velocity.ip_1h" | "velocity.ip_24h" | "velocity.subnet_1h" | "velocity.subnet_24h" | "velocity.email_domain_1h" | "velocity.email_domain_24h" | "velocity.mailbox_1h" | "velocity.mailbox_24h" | "velocity.user_1h" | "velocity.user_24h";
|
|
2302
|
+
type RiskRuleField = "email.valid" | "email.disposable" | "email.undeliverable" | "email.role_account" | "email.free_provider" | "email.typo" | "email.domain_new" | "email.domain" | "email.domain_age_days" | "ip.tor" | "ip.hosting" | "ip.vpn" | "ip.proxy" | "ip.relay" | "ip.private" | "ip.country" | "ip.asn" | "ip.hosting_provider" | "captcha.passed" | "duplicate.canonical_mailbox" | "duplicate.device" | "history.fraud" | "login.new_country" | "login.new_network" | "content.spam" | "content.phishing" | "content.malware" | "content.fraud" | "checkout.amount" | "checkout.currency" | "checkout.card_country" | "checkout.card_funding" | "checkout.billing_country" | "checkout.shipping_country" | "device.automation" | "device.timezone" | "device.language" | "score" | "velocity.ip_1h" | "velocity.ip_24h" | "velocity.subnet_1h" | "velocity.subnet_24h" | "velocity.email_domain_1h" | "velocity.email_domain_24h" | "velocity.mailbox_1h" | "velocity.mailbox_24h" | "velocity.user_1h" | "velocity.user_24h" | "velocity.card_1h" | "velocity.card_24h" | "velocity.device_1h" | "velocity.device_24h";
|
|
2136
2303
|
/** A test of one field. A field without a value (no IP, no email…) never matches. */
|
|
2137
2304
|
interface RiskRuleCondition {
|
|
2138
2305
|
field: RiskRuleField;
|
|
@@ -2179,6 +2346,107 @@ interface DeletedRiskRule {
|
|
|
2179
2346
|
id: string;
|
|
2180
2347
|
deleted: true;
|
|
2181
2348
|
}
|
|
2349
|
+
/** Result of `coss.risk.checkEmail()`: what COSS knows about an address. Nothing is stored. */
|
|
2350
|
+
interface RiskEmailCheck {
|
|
2351
|
+
object: "risk_email_check";
|
|
2352
|
+
email: string;
|
|
2353
|
+
valid: boolean;
|
|
2354
|
+
domain: string | null;
|
|
2355
|
+
/** The mailbox with the provider's aliasing folded (dots and `+tags` at Gmail…). */
|
|
2356
|
+
canonical: string | null;
|
|
2357
|
+
disposable: boolean;
|
|
2358
|
+
/** From DNS (MX, A, AAAA). `unknown` when the lookup failed or timed out. */
|
|
2359
|
+
deliverability: "deliverable" | "undeliverable" | "unknown";
|
|
2360
|
+
role_account: boolean;
|
|
2361
|
+
free_provider: boolean;
|
|
2362
|
+
/** The likely intended domain when this one looks like a typo of a popular one. */
|
|
2363
|
+
suggestion: string | null;
|
|
2364
|
+
/** Days since the domain was registered (RDAP); `null` when unknown or not looked up. */
|
|
2365
|
+
domain_age_days: number | null;
|
|
2366
|
+
/** Lookups that failed or timed out. */
|
|
2367
|
+
degraded: ("email_dns" | "domain_age")[];
|
|
2368
|
+
}
|
|
2369
|
+
/** Result of `coss.risk.checkIp()`. Nothing is stored. */
|
|
2370
|
+
interface RiskIpCheck extends RiskIpSignals {
|
|
2371
|
+
object: "risk_ip_check";
|
|
2372
|
+
ip: string;
|
|
2373
|
+
/**
|
|
2374
|
+
* `ip_data` when some IP data is unavailable at the moment; `ip_privacy` when the privacy data
|
|
2375
|
+
* provider failed or timed out.
|
|
2376
|
+
*/
|
|
2377
|
+
degraded: ("ip_data" | "ip_privacy")[];
|
|
2378
|
+
}
|
|
2379
|
+
/** Result of `coss.risk.classify()`: scores only, neither stored nor logged. */
|
|
2380
|
+
interface RiskContentClassification {
|
|
2381
|
+
object: "risk_content_classification";
|
|
2382
|
+
scores: RiskContentScores;
|
|
2383
|
+
/** The text was longer than the model reads (8,000 characters): only its beginning counted. */
|
|
2384
|
+
truncated: boolean;
|
|
2385
|
+
}
|
|
2386
|
+
/** What `on_failure` answers while COSS can't count. */
|
|
2387
|
+
type RiskLimitFailureMode = "allow" | "deny";
|
|
2388
|
+
/** One of your rate limit buckets: each key gets `burst` tokens, refilling `limit` per period. */
|
|
2389
|
+
interface RiskLimitBucket {
|
|
2390
|
+
object: "risk_limit_bucket";
|
|
2391
|
+
id: string;
|
|
2392
|
+
/** What `coss.risk.limit({ bucket })` names it by. */
|
|
2393
|
+
name: string;
|
|
2394
|
+
/** Tokens added per `period_seconds`. */
|
|
2395
|
+
limit: number;
|
|
2396
|
+
period_seconds: number;
|
|
2397
|
+
/** How many requests a key can make at once. */
|
|
2398
|
+
burst: number;
|
|
2399
|
+
on_failure: RiskLimitFailureMode;
|
|
2400
|
+
/** ISO 8601 timestamp. */
|
|
2401
|
+
created_at: string;
|
|
2402
|
+
/** ISO 8601 timestamp. */
|
|
2403
|
+
updated_at: string;
|
|
2404
|
+
}
|
|
2405
|
+
/** Body of `POST /v1/risk/limit_buckets`. */
|
|
2406
|
+
interface CreateRiskLimitBucketParams {
|
|
2407
|
+
/** 1-64 lower-case letters, digits, `.`, `_` or `-`; unique in the environment. */
|
|
2408
|
+
name: string;
|
|
2409
|
+
limit: number;
|
|
2410
|
+
/** 1 second to 1 day. */
|
|
2411
|
+
period_seconds: number;
|
|
2412
|
+
/** Defaults to `limit`. */
|
|
2413
|
+
burst?: number;
|
|
2414
|
+
/** Defaults to `allow`. */
|
|
2415
|
+
on_failure?: RiskLimitFailureMode;
|
|
2416
|
+
}
|
|
2417
|
+
/** Body of `PATCH /v1/risk/limit_buckets/{id}` (the name can't change). */
|
|
2418
|
+
type UpdateRiskLimitBucketParams = Partial<Omit<CreateRiskLimitBucketParams, "name">>;
|
|
2419
|
+
interface DeletedRiskLimitBucket {
|
|
2420
|
+
object: "risk_limit_bucket";
|
|
2421
|
+
id: string;
|
|
2422
|
+
deleted: true;
|
|
2423
|
+
}
|
|
2424
|
+
/** Body of `POST /v1/risk/limits`. */
|
|
2425
|
+
interface CheckRiskLimitParams {
|
|
2426
|
+
/** The bucket's name. */
|
|
2427
|
+
bucket: string;
|
|
2428
|
+
/** Who or what is limited (a user id, an email or IP address…); COSS keeps only a hash. */
|
|
2429
|
+
key: string;
|
|
2430
|
+
/** Tokens this request takes. Default 1. */
|
|
2431
|
+
cost?: number;
|
|
2432
|
+
}
|
|
2433
|
+
/** Result of `coss.risk.limit()`. */
|
|
2434
|
+
interface RiskLimit {
|
|
2435
|
+
object: "risk_limit";
|
|
2436
|
+
bucket: string;
|
|
2437
|
+
/** Whether to let the request through. Denied requests take no tokens. */
|
|
2438
|
+
allowed: boolean;
|
|
2439
|
+
/** The bucket's size (`burst`). */
|
|
2440
|
+
limit: number;
|
|
2441
|
+
/** Tokens left for this key. */
|
|
2442
|
+
remaining: number;
|
|
2443
|
+
/** Milliseconds until the key's bucket is full again. */
|
|
2444
|
+
reset_ms: number;
|
|
2445
|
+
/** When denied: milliseconds until the same request would fit; `null` if it never would. */
|
|
2446
|
+
retry_after_ms: number | null;
|
|
2447
|
+
/** COSS couldn't count: `allowed` is the bucket's `on_failure`. */
|
|
2448
|
+
degraded: boolean;
|
|
2449
|
+
}
|
|
2182
2450
|
//#endregion
|
|
2183
2451
|
//#region src/resources/risk.d.ts
|
|
2184
2452
|
type ReadOptions$2 = Pick<RequestOptions, "signal">;
|
|
@@ -2241,6 +2509,22 @@ declare class RiskRulesResource {
|
|
|
2241
2509
|
update(id: string, params: UpdateRiskRuleParams, options?: ReadOptions$2): Promise<CossResult<RiskRule>>;
|
|
2242
2510
|
delete(id: string, options?: ReadOptions$2): Promise<CossResult<DeletedRiskRule>>;
|
|
2243
2511
|
}
|
|
2512
|
+
/**
|
|
2513
|
+
* `coss.risk.limitBuckets`: your rate limit buckets, which `coss.risk.limit()` charges per key.
|
|
2514
|
+
*/
|
|
2515
|
+
declare class RiskLimitBucketsResource {
|
|
2516
|
+
#private;
|
|
2517
|
+
/** @internal Use `new Coss().risk.limitBuckets`. */
|
|
2518
|
+
constructor(http: HttpClient);
|
|
2519
|
+
/** Creates a bucket. Not retried automatically: a retry would find its name taken. */
|
|
2520
|
+
create(params: CreateRiskLimitBucketParams, options?: ReadOptions$2): Promise<CossResult<RiskLimitBucket>>;
|
|
2521
|
+
/** Every bucket, by name. */
|
|
2522
|
+
list(options?: ReadOptions$2): Promise<CossResult<List<RiskLimitBucket>>>;
|
|
2523
|
+
get(id: string, options?: ReadOptions$2): Promise<CossResult<RiskLimitBucket>>;
|
|
2524
|
+
/** Changes the fields given; the next check uses them. */
|
|
2525
|
+
update(id: string, params: UpdateRiskLimitBucketParams, options?: ReadOptions$2): Promise<CossResult<RiskLimitBucket>>;
|
|
2526
|
+
delete(id: string, options?: ReadOptions$2): Promise<CossResult<DeletedRiskLimitBucket>>;
|
|
2527
|
+
}
|
|
2244
2528
|
/** `coss.risk.users`: what COSS remembers about your users. */
|
|
2245
2529
|
declare class RiskUsersResource {
|
|
2246
2530
|
#private;
|
|
@@ -2273,6 +2557,8 @@ declare class RiskResource {
|
|
|
2273
2557
|
readonly settings: RiskSettingsResource;
|
|
2274
2558
|
/** Rules (`create`, `list`, `get`, `update`, `delete`). */
|
|
2275
2559
|
readonly rules: RiskRulesResource;
|
|
2560
|
+
/** Your rate limit buckets (`create`, `list`, `get`, `update`, `delete`). */
|
|
2561
|
+
readonly limitBuckets: RiskLimitBucketsResource;
|
|
2276
2562
|
/** @internal Use `new Coss().risk`. */
|
|
2277
2563
|
constructor(http: HttpClient);
|
|
2278
2564
|
/**
|
|
@@ -2282,9 +2568,42 @@ declare class RiskResource {
|
|
|
2282
2568
|
assess(params: AssessRiskParams, options?: RequestOptions): Promise<CossResult<RiskAssessment>>;
|
|
2283
2569
|
/**
|
|
2284
2570
|
* Reports what an assessed user turned out to be: `fraud` and `abuse` teach later assessments to
|
|
2285
|
-
* flag the same mailbox, user, IP and subnet; `legitimate` takes that back.
|
|
2571
|
+
* flag the same mailbox, user, card, device, IP and subnet; `legitimate` takes that back.
|
|
2572
|
+
* Resolves a review, and counts in `calibration()`.
|
|
2286
2573
|
*/
|
|
2287
2574
|
feedback(id: string, params: RiskFeedbackParams, options?: RequestOptions): Promise<CossResult<RiskAssessment>>;
|
|
2575
|
+
/**
|
|
2576
|
+
* How often each reason and rule was right over the last 90 days, by your feedback, and the
|
|
2577
|
+
* reason weights that supports. Apply them with `settings.update({ reason_weights })`.
|
|
2578
|
+
*/
|
|
2579
|
+
calibration(options?: ReadOptions$2): Promise<CossResult<RiskCalibration>>;
|
|
2580
|
+
/**
|
|
2581
|
+
* Checks an email address on its own: syntax, disposable domains, deliverability, role
|
|
2582
|
+
* accounts, free providers, the canonical mailbox, typos and domain age. Nothing is stored.
|
|
2583
|
+
*/
|
|
2584
|
+
checkEmail(email: string, options?: ReadOptions$2): Promise<CossResult<RiskEmailCheck>>;
|
|
2585
|
+
/**
|
|
2586
|
+
* Checks an IP address on its own: Tor, cloud, hosting and VPN networks, ASN and country, and
|
|
2587
|
+
* VPN, proxy and relay exits when COSS's privacy data is available.
|
|
2588
|
+
*/
|
|
2589
|
+
checkIp(ip: string, options?: ReadOptions$2): Promise<CossResult<RiskIpCheck>>;
|
|
2590
|
+
/**
|
|
2591
|
+
* Scores text for spam, phishing, malware and fraud. Scores only, never a verdict: you choose
|
|
2592
|
+
* the thresholds. The text is neither stored nor logged.
|
|
2593
|
+
*/
|
|
2594
|
+
classify(params: {
|
|
2595
|
+
text: string;
|
|
2596
|
+
}, options?: ReadOptions$2): Promise<CossResult<RiskContentClassification>>;
|
|
2597
|
+
/**
|
|
2598
|
+
* Takes `cost` tokens (default 1) from `key`'s share of one of your buckets
|
|
2599
|
+
* (`coss.risk.limitBuckets`). Retries reuse one `Idempotency-Key`, so they are charged once.
|
|
2600
|
+
*
|
|
2601
|
+
* ```ts
|
|
2602
|
+
* const { data } = await coss.risk.limit({ bucket: "password_reset", key: email });
|
|
2603
|
+
* if (data && !data.allowed) return tooManyRequests(data.retry_after_ms);
|
|
2604
|
+
* ```
|
|
2605
|
+
*/
|
|
2606
|
+
limit(params: CheckRiskLimitParams, options?: RequestOptions): Promise<CossResult<RiskLimit>>;
|
|
2288
2607
|
}
|
|
2289
2608
|
//#endregion
|
|
2290
2609
|
//#region src/types/webhook.d.ts
|
|
@@ -2779,7 +3098,7 @@ export declare class Coss {
|
|
|
2779
3098
|
//#endregion
|
|
2780
3099
|
//#region src/version.d.ts
|
|
2781
3100
|
/** SDK version, sent in the User-Agent. A test keeps it equal to package.json's `version`. */
|
|
2782
|
-
export declare const VERSION = "0.
|
|
3101
|
+
export declare const VERSION = "0.3.0";
|
|
2783
3102
|
//#endregion
|
|
2784
3103
|
//#region src/webhooks.d.ts
|
|
2785
3104
|
/** A webhook request failed verification: reject it (e.g. respond 400). */
|
|
@@ -2820,4 +3139,4 @@ export declare function verifyWebhook<T = WebhookEvent>(payload: string, headers
|
|
|
2820
3139
|
*/
|
|
2821
3140
|
export declare function verifyLogDrainBatch(payload: string, headers: WebhookHeaders, secret: string, options?: VerifyWebhookOptions): Promise<LogDrainLine[]>;
|
|
2822
3141
|
//#endregion
|
|
2823
|
-
export type { AccountEventType, AccountWebhookEvent, AccountWebhookEventData, ApiVersion, AssessRiskParams, AuditActorType, AuditEvent, AuditEventsResource, Billing, BillingCreditsResource, BillingEventType, BillingHoldReason, BillingInvoicesResource, BillingResource, BillingWebhookEvent, CheckSuppressionParams, CossError, CossErrorIssue, CossErrorType, CossOptions, CossResult, CreateDomainParams, CreateHookApplicationParams, CreateHookEndpointParams, CreateHookEventTypeParams, CreateHookPortalSessionParams, CreateLogDrainParams, CreateReceivingDomainParams, CreateRiskListEntryParams, CreateRiskRuleParams, CreateSuppressionParams, CreateTrackingDomainParams, CreateWebhookEndpointParams, Credit, DeletedDomain, DeletedHookApplication, DeletedHookEndpoint, DeletedLogDrain, DeletedReceivedEmail, DeletedRiskListEntry, DeletedRiskRule, DeletedSuppression, DeletedTrackingRule, DeletedWebhookEndpoint, Domain, DomainRecord, DomainRecordPurpose, DomainRecordStatus, DomainStatus, DomainsResource, Email, EmailAttachment, EmailAttachmentParams, EmailBatch, EmailEvent, EmailEventData, EmailEventType, EmailLink, EmailRecipient, EmailRecipientStatus, EmailResource, EmailStatus, EmailTag, EmailTracking, EmailWebhookEvent, EmailWebhookEventData, ExportSuppressionsParams, FetchLike, ForgottenRiskUser, HookApplication, HookApplicationsResource, HookAttempt, HookDeliveriesResource, HookDelivery, HookDeliveryStatus, HookEndpoint, HookEndpointDisabledReason, HookEndpointRecovery, HookEndpointSecret, HookEndpointWebhookEvent, HookEndpointWebhookEventData, HookEndpointWithSecret, HookEndpointsResource, HookEventType, HookEventTypesResource, HookMessage, HookMessagesResource, HookOperationalEventType, HookPortalResource, HookPortalSession, HooksResource, ImportSuppressionEntry, ImportSuppressionsParams, InboundAddress, Invoice, InvoiceLine, InvoiceLineKind, InvoiceStatus, InvoiceSummary, List, ListAuditEventsParams, ListCreditsParams, ListHookApplicationsParams, ListHookDeliveriesParams, ListHookEventTypesParams, ListHookMessagesParams, ListInvoicesParams, ListLogDrainBatchesParams, ListLogsParams, ListReceivedEmailsParams, ListRiskAssessmentsParams, ListRiskListEntriesParams, ListSuppressionsParams, ListUsageParams, ListWebhookDeliveriesParams, Log, LogDrain, LogDrainAttempt, LogDrainBatch, LogDrainBatchStatus, LogDrainBatchesResource, LogDrainLine, LogDrainSource, LogDrainWithSecret, LogDrainsResource, LogLevel, LogSource, LogsResource, MailFromStatus, Meter, PlanKey, ReceivedEmail, ReceivedEmailAttachment, ReceivedEmailEventType, ReceivedEmailStatus, ReceivedEmailSummary, ReceivedEmailVerdicts, ReceivedEmailWebhookEvent, ReceivedEmailWebhookEventData, ReceivedEmailsResource, ReceivingDomain, ReceivingDomainRecord, ReceivingDomainsResource, RecoverHookEndpointParams, RecoverWebhookEndpointParams, Reputation, ReputationCheck, ReputationCheckSeverity, ReputationResource, ReputationStatus, RequestOptions, RescheduleEmailParams, RiskAssessment, RiskAssessmentsResource, RiskCaptchaProvider, RiskCaptchaSignals, RiskDecision, RiskDegradedSignal, RiskEmailSignals, RiskEvent, RiskEventType, RiskFeedbackParams, RiskIpSignals, RiskList, RiskListEntry, RiskListEntryType, RiskListEntryValue, RiskListsResource, RiskLoginSignals, RiskOutcome, RiskReason, RiskReasonCode, RiskResource, RiskRule, RiskRuleCondition, RiskRuleField, RiskRulesResource, RiskSettings, RiskSettingsResource, RiskUsersResource, RiskWebhookEvent, RiskWebhookEventData, RollHookEndpointSecretParams, RollWebhookEndpointSecretParams, SendEmailParams, SendHookMessageParams, SendHookTestParams, Suppression, SuppressionCheck, SuppressionImport, SuppressionReason, SuppressionResource, TrackingDomain, TrackingDomainRecord, TrackingDomainStatus, TrackingDomainsResource, TrackingOptions, TrackingResource, TrackingRule, TrackingSettings, UpdateHookApplicationParams, UpdateHookEndpointParams, UpdateHookEventTypeParams, UpdateLogDrainParams, UpdateRiskRuleParams, UpdateRiskSettingsParams, UpdateTrackingRuleParams, UpdateWebhookEndpointParams, Usage, VerdictStatus, VerifyWebhookOptions, WebhookAttempt, WebhookDeliveriesResource, WebhookDelivery, WebhookDeliveryStatus, WebhookEndpoint, WebhookEndpointDisabledReason, WebhookEndpointRecovery, WebhookEndpointWithSecret, WebhookEndpointsResource, WebhookEvent, WebhookEventType, WebhookHeaders };
|
|
3142
|
+
export type { AccountEventType, AccountWebhookEvent, AccountWebhookEventData, ApiVersion, AssessRiskParams, AuditActorType, AuditEvent, AuditEventsResource, Billing, BillingCreditsResource, BillingEventType, BillingHoldReason, BillingInvoicesResource, BillingResource, BillingWebhookEvent, CheckRiskLimitParams, CheckSuppressionParams, CossError, CossErrorIssue, CossErrorType, CossOptions, CossResult, CreateDomainParams, CreateHookApplicationParams, CreateHookEndpointParams, CreateHookEventTypeParams, CreateHookPortalSessionParams, CreateLogDrainParams, CreateReceivingDomainParams, CreateRiskLimitBucketParams, CreateRiskListEntryParams, CreateRiskRuleParams, CreateSuppressionParams, CreateTrackingDomainParams, CreateWebhookEndpointParams, Credit, DeletedDomain, DeletedHookApplication, DeletedHookEndpoint, DeletedLogDrain, DeletedReceivedEmail, DeletedRiskLimitBucket, DeletedRiskListEntry, DeletedRiskRule, DeletedSuppression, DeletedTrackingRule, DeletedWebhookEndpoint, Domain, DomainRecord, DomainRecordPurpose, DomainRecordStatus, DomainStatus, DomainsResource, Email, EmailAttachment, EmailAttachmentParams, EmailBatch, EmailEvent, EmailEventData, EmailEventType, EmailFailure, EmailLink, EmailRecipient, EmailRecipientStatus, EmailResource, EmailStatus, EmailSummary, EmailTag, EmailTracking, EmailWebhookEvent, EmailWebhookEventData, ExportSuppressionsParams, FetchLike, ForgottenRiskUser, HookApplication, HookApplicationsResource, HookAttempt, HookDeliveriesResource, HookDelivery, HookDeliveryStatus, HookEndpoint, HookEndpointDisabledReason, HookEndpointRecovery, HookEndpointSecret, HookEndpointWebhookEvent, HookEndpointWebhookEventData, HookEndpointWithSecret, HookEndpointsResource, HookEventType, HookEventTypesResource, HookMessage, HookMessagesResource, HookOperationalEventType, HookPortalResource, HookPortalSession, HooksResource, ImportSuppressionEntry, ImportSuppressionsParams, InboundAddress, Invoice, InvoiceLine, InvoiceLineKind, InvoiceStatus, InvoiceSummary, List, ListAuditEventsParams, ListCreditsParams, ListEmailsParams, ListHookApplicationsParams, ListHookDeliveriesParams, ListHookEventTypesParams, ListHookMessagesParams, ListInvoicesParams, ListLogDrainBatchesParams, ListLogsParams, ListReceivedEmailsParams, ListRiskAssessmentsParams, ListRiskListEntriesParams, ListSuppressionsParams, ListUsageParams, ListWebhookDeliveriesParams, Log, LogDrain, LogDrainAttempt, LogDrainBatch, LogDrainBatchStatus, LogDrainBatchesResource, LogDrainLine, LogDrainSource, LogDrainWithSecret, LogDrainsResource, LogLevel, LogSource, LogsResource, MailFromStatus, Meter, PlanKey, ReceivedEmail, ReceivedEmailAttachment, ReceivedEmailEventType, ReceivedEmailStatus, ReceivedEmailSummary, ReceivedEmailVerdicts, ReceivedEmailWebhookEvent, ReceivedEmailWebhookEventData, ReceivedEmailsResource, ReceivingDomain, ReceivingDomainRecord, ReceivingDomainsResource, RecoverHookEndpointParams, RecoverWebhookEndpointParams, Reputation, ReputationCheck, ReputationCheckSeverity, ReputationResource, ReputationStatus, RequestOptions, RescheduleEmailParams, RiskAssessment, RiskAssessmentsResource, RiskCalibration, RiskCaptchaProvider, RiskCaptchaSignals, RiskCardFunding, RiskCheckoutSignals, RiskContentCategory, RiskContentClassification, RiskContentScores, RiskDecision, RiskDegradedSignal, RiskDeviceSignals, RiskEmailCheck, RiskEmailSignals, RiskEvent, RiskEventType, RiskFeedbackParams, RiskIpCheck, RiskIpPrivacy, RiskIpSignals, RiskLimit, RiskLimitBucket, RiskLimitBucketsResource, RiskLimitFailureMode, RiskList, RiskListEntry, RiskListEntryType, RiskListEntryValue, RiskListsResource, RiskLoginSignals, RiskOutcome, RiskReason, RiskReasonCode, RiskResource, RiskRule, RiskRuleCondition, RiskRuleField, RiskRulesResource, RiskSettings, RiskSettingsResource, RiskUsersResource, RiskWebhookEvent, RiskWebhookEventData, RollHookEndpointSecretParams, RollWebhookEndpointSecretParams, SendEmailParams, SendHookMessageParams, SendHookTestParams, Suppression, SuppressionCheck, SuppressionImport, SuppressionReason, SuppressionResource, TrackingDomain, TrackingDomainRecord, TrackingDomainStatus, TrackingDomainsResource, TrackingOptions, TrackingResource, TrackingRule, TrackingSettings, UpdateHookApplicationParams, UpdateHookEndpointParams, UpdateHookEventTypeParams, UpdateLogDrainParams, UpdateRiskLimitBucketParams, UpdateRiskRuleParams, UpdateRiskSettingsParams, UpdateTrackingRuleParams, UpdateWebhookEndpointParams, Usage, VerdictStatus, VerifyWebhookOptions, WebhookAttempt, WebhookDeliveriesResource, WebhookDelivery, WebhookDeliveryStatus, WebhookEndpoint, WebhookEndpointDisabledReason, WebhookEndpointRecovery, WebhookEndpointWithSecret, WebhookEndpointsResource, WebhookEvent, WebhookEventType, WebhookHeaders };
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ const API_VERSION = "2026-10-10";
|
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/version.ts
|
|
11
11
|
/** SDK version, sent in the User-Agent. A test keeps it equal to package.json's `version`. */
|
|
12
|
-
const VERSION = "0.
|
|
12
|
+
const VERSION = "0.3.0";
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region src/core/errors.ts
|
|
15
15
|
const API_ERROR_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -826,6 +826,19 @@ var EmailResource = class {
|
|
|
826
826
|
});
|
|
827
827
|
}
|
|
828
828
|
/**
|
|
829
|
+
* Lists emails sent from the same environment as the API key, newest first and without their
|
|
830
|
+
* content (`get` one for `html`, `text`, `headers` and `attachments`). Pass the last `id` as
|
|
831
|
+
* `after` while `has_more` is true.
|
|
832
|
+
*/
|
|
833
|
+
list(params = {}, options) {
|
|
834
|
+
return this.#http.request({
|
|
835
|
+
method: "GET",
|
|
836
|
+
path: "/v1/emails",
|
|
837
|
+
query: listQuery(params),
|
|
838
|
+
signal: options?.signal
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
829
842
|
* Cancels a scheduled email. Canceling an already canceled email returns it; any other email
|
|
830
843
|
* fails with `email_not_cancelable`.
|
|
831
844
|
*/
|
|
@@ -1521,6 +1534,57 @@ var RiskRulesResource = class {
|
|
|
1521
1534
|
});
|
|
1522
1535
|
}
|
|
1523
1536
|
};
|
|
1537
|
+
/**
|
|
1538
|
+
* `coss.risk.limitBuckets`: your rate limit buckets, which `coss.risk.limit()` charges per key.
|
|
1539
|
+
*/
|
|
1540
|
+
var RiskLimitBucketsResource = class {
|
|
1541
|
+
#http;
|
|
1542
|
+
/** @internal Use `new Coss().risk.limitBuckets`. */
|
|
1543
|
+
constructor(http) {
|
|
1544
|
+
this.#http = http;
|
|
1545
|
+
}
|
|
1546
|
+
/** Creates a bucket. Not retried automatically: a retry would find its name taken. */
|
|
1547
|
+
create(params, options) {
|
|
1548
|
+
return this.#http.request({
|
|
1549
|
+
method: "POST",
|
|
1550
|
+
path: "/v1/risk/limit_buckets",
|
|
1551
|
+
body: params,
|
|
1552
|
+
retry: false,
|
|
1553
|
+
signal: options?.signal
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
/** Every bucket, by name. */
|
|
1557
|
+
list(options) {
|
|
1558
|
+
return this.#http.request({
|
|
1559
|
+
method: "GET",
|
|
1560
|
+
path: "/v1/risk/limit_buckets",
|
|
1561
|
+
signal: options?.signal
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
get(id, options) {
|
|
1565
|
+
return this.#http.request({
|
|
1566
|
+
method: "GET",
|
|
1567
|
+
path: `/v1/risk/limit_buckets/${encodeURIComponent(id)}`,
|
|
1568
|
+
signal: options?.signal
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
/** Changes the fields given; the next check uses them. */
|
|
1572
|
+
update(id, params, options) {
|
|
1573
|
+
return this.#http.request({
|
|
1574
|
+
method: "PATCH",
|
|
1575
|
+
path: `/v1/risk/limit_buckets/${encodeURIComponent(id)}`,
|
|
1576
|
+
body: params,
|
|
1577
|
+
signal: options?.signal
|
|
1578
|
+
});
|
|
1579
|
+
}
|
|
1580
|
+
delete(id, options) {
|
|
1581
|
+
return this.#http.request({
|
|
1582
|
+
method: "DELETE",
|
|
1583
|
+
path: `/v1/risk/limit_buckets/${encodeURIComponent(id)}`,
|
|
1584
|
+
signal: options?.signal
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
};
|
|
1524
1588
|
/** `coss.risk.users`: what COSS remembers about your users. */
|
|
1525
1589
|
var RiskUsersResource = class {
|
|
1526
1590
|
#http;
|
|
@@ -1560,6 +1624,8 @@ var RiskResource = class {
|
|
|
1560
1624
|
settings;
|
|
1561
1625
|
/** Rules (`create`, `list`, `get`, `update`, `delete`). */
|
|
1562
1626
|
rules;
|
|
1627
|
+
/** Your rate limit buckets (`create`, `list`, `get`, `update`, `delete`). */
|
|
1628
|
+
limitBuckets;
|
|
1563
1629
|
#http;
|
|
1564
1630
|
/** @internal Use `new Coss().risk`. */
|
|
1565
1631
|
constructor(http) {
|
|
@@ -1569,6 +1635,7 @@ var RiskResource = class {
|
|
|
1569
1635
|
this.users = new RiskUsersResource(http);
|
|
1570
1636
|
this.settings = new RiskSettingsResource(http);
|
|
1571
1637
|
this.rules = new RiskRulesResource(http);
|
|
1638
|
+
this.limitBuckets = new RiskLimitBucketsResource(http);
|
|
1572
1639
|
}
|
|
1573
1640
|
/**
|
|
1574
1641
|
* Assesses an event and returns the decision with its score and reasons. Retries reuse one
|
|
@@ -1585,7 +1652,8 @@ var RiskResource = class {
|
|
|
1585
1652
|
}
|
|
1586
1653
|
/**
|
|
1587
1654
|
* Reports what an assessed user turned out to be: `fraud` and `abuse` teach later assessments to
|
|
1588
|
-
* flag the same mailbox, user, IP and subnet; `legitimate` takes that back.
|
|
1655
|
+
* flag the same mailbox, user, card, device, IP and subnet; `legitimate` takes that back.
|
|
1656
|
+
* Resolves a review, and counts in `calibration()`.
|
|
1589
1657
|
*/
|
|
1590
1658
|
feedback(id, params, options) {
|
|
1591
1659
|
return this.#http.request({
|
|
@@ -1596,6 +1664,71 @@ var RiskResource = class {
|
|
|
1596
1664
|
signal: options?.signal
|
|
1597
1665
|
});
|
|
1598
1666
|
}
|
|
1667
|
+
/**
|
|
1668
|
+
* How often each reason and rule was right over the last 90 days, by your feedback, and the
|
|
1669
|
+
* reason weights that supports. Apply them with `settings.update({ reason_weights })`.
|
|
1670
|
+
*/
|
|
1671
|
+
calibration(options) {
|
|
1672
|
+
return this.#http.request({
|
|
1673
|
+
method: "GET",
|
|
1674
|
+
path: "/v1/risk/calibration",
|
|
1675
|
+
signal: options?.signal
|
|
1676
|
+
});
|
|
1677
|
+
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Checks an email address on its own: syntax, disposable domains, deliverability, role
|
|
1680
|
+
* accounts, free providers, the canonical mailbox, typos and domain age. Nothing is stored.
|
|
1681
|
+
*/
|
|
1682
|
+
checkEmail(email, options) {
|
|
1683
|
+
return this.#http.request({
|
|
1684
|
+
method: "POST",
|
|
1685
|
+
path: "/v1/risk/email/check",
|
|
1686
|
+
body: { email },
|
|
1687
|
+
signal: options?.signal
|
|
1688
|
+
});
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Checks an IP address on its own: Tor, cloud, hosting and VPN networks, ASN and country, and
|
|
1692
|
+
* VPN, proxy and relay exits when COSS's privacy data is available.
|
|
1693
|
+
*/
|
|
1694
|
+
checkIp(ip, options) {
|
|
1695
|
+
return this.#http.request({
|
|
1696
|
+
method: "POST",
|
|
1697
|
+
path: "/v1/risk/ip/check",
|
|
1698
|
+
body: { ip },
|
|
1699
|
+
signal: options?.signal
|
|
1700
|
+
});
|
|
1701
|
+
}
|
|
1702
|
+
/**
|
|
1703
|
+
* Scores text for spam, phishing, malware and fraud. Scores only, never a verdict: you choose
|
|
1704
|
+
* the thresholds. The text is neither stored nor logged.
|
|
1705
|
+
*/
|
|
1706
|
+
classify(params, options) {
|
|
1707
|
+
return this.#http.request({
|
|
1708
|
+
method: "POST",
|
|
1709
|
+
path: "/v1/risk/content/classify",
|
|
1710
|
+
body: params,
|
|
1711
|
+
signal: options?.signal
|
|
1712
|
+
});
|
|
1713
|
+
}
|
|
1714
|
+
/**
|
|
1715
|
+
* Takes `cost` tokens (default 1) from `key`'s share of one of your buckets
|
|
1716
|
+
* (`coss.risk.limitBuckets`). Retries reuse one `Idempotency-Key`, so they are charged once.
|
|
1717
|
+
*
|
|
1718
|
+
* ```ts
|
|
1719
|
+
* const { data } = await coss.risk.limit({ bucket: "password_reset", key: email });
|
|
1720
|
+
* if (data && !data.allowed) return tooManyRequests(data.retry_after_ms);
|
|
1721
|
+
* ```
|
|
1722
|
+
*/
|
|
1723
|
+
limit(params, options) {
|
|
1724
|
+
return this.#http.request({
|
|
1725
|
+
method: "POST",
|
|
1726
|
+
path: "/v1/risk/limits",
|
|
1727
|
+
body: params,
|
|
1728
|
+
idempotencyKey: options?.idempotencyKey,
|
|
1729
|
+
signal: options?.signal
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1599
1732
|
};
|
|
1600
1733
|
//#endregion
|
|
1601
1734
|
//#region src/resources/webhook-deliveries.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coss",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The official TypeScript SDK for COSS: email, SMS, video, scheduling and more behind one API key.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://coss.com/docs",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"types": "./dist/index.d.ts",
|
|
24
24
|
"exports": {
|
|
25
25
|
".": "./dist/index.js",
|
|
26
|
+
"./device": "./dist/device.js",
|
|
26
27
|
"./package.json": "./package.json"
|
|
27
28
|
},
|
|
28
29
|
"scripts": {
|