@vesant-sdk/fraud 0.1.1-next.f2f4e87 → 0.1.2-next.02b7e78

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/README.md CHANGED
@@ -13,7 +13,7 @@ Requires `@vesant-sdk/core` (installed automatically as a dependency).
13
13
  ## Quick start
14
14
 
15
15
  ```typescript
16
- import { FraudClient, TransactionType } from '@vesant-sdk/fraud';
16
+ import { FraudClient, TransactionType, TransactionStatus } from '@vesant-sdk/fraud';
17
17
 
18
18
  const fraud = new FraudClient({
19
19
  baseURL: process.env.VESANT_API_URL!,
@@ -22,13 +22,20 @@ const fraud = new FraudClient({
22
22
  });
23
23
 
24
24
  const result = await fraud.scoreEvent({
25
- customer_id: 'customer-uuid',
26
- sift_user_id: 'stable-sift-user-id',
25
+ customer_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
26
+ sift_user_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
27
27
  event_type: '$transaction',
28
- transaction_id: 'TX-001',
29
- amount: 99.99,
28
+ transaction_id: '674a1b2c3d4e5f6789012345',
29
+ transaction_type: TransactionType.Deposit,
30
+ amount: 50.0,
30
31
  currency: 'USD',
31
- transaction_type: TransactionType.Sale,
32
+ session_id: 'sess_deposit_001',
33
+ ip_address: '192.168.1.10',
34
+ device_id: 'device_abcd1234',
35
+ payment_method: '$credit_card',
36
+ is_first_deposit: true,
37
+ deposit_count: 4,
38
+ transaction_status: TransactionStatus.Success,
32
39
  });
33
40
  ```
34
41
 
@@ -36,22 +43,303 @@ const result = await fraud.scoreEvent({
36
43
 
37
44
  | Category | `event_type` values |
38
45
  |----------|---------------------|
39
- | Scored | `$create_account`, `$login`, `$logout`, `$update_account`, `$update_password`, `$transaction`, `$wager` |
46
+ | Scored | `$create_account`, `$create_order`, `$login`, `$logout`, `$update_account`, `$update_password`, `$transaction`, `$wager` |
40
47
  | Feedback | `$chargeback` (no meaningful score/decision) |
41
48
 
42
49
  Types such as `$verification` appear in the Vesant dashboard but are **not** accepted by `scoreEvent` (SDK rejects them before HTTP).
43
50
 
44
- ## Migration from 0.1.x
51
+ ## Request fields
45
52
 
46
- 1. **Transactions** — add required `amount` (> 0) and `currency`.
47
- 2. **Wagers** — add `wager_type`, `wager_status`, `amount`, `currency`; `transaction_id` is the wager id.
48
- 3. **Password updates** — add `password_reason` and `password_status` (use `PasswordUpdateReason` / `PasswordUpdateStatus` constants).
49
- 4. **Chargebacks** — use `event_type: '$chargeback'` with `transaction_id` or `order_id`.
50
- 5. **Metadata** — do not put `$`-prefixed Sift keys in `metadata`; use typed request fields.
53
+ ### Base (all events)
51
54
 
52
- ## API normalization
55
+ | Field | Wire | Notes |
56
+ |-------|------|-------|
57
+ | `customer_id` | top-level | Required |
58
+ | `sift_user_id` | top-level | Required, stable and case-sensitive |
59
+ | `session_id` | `metadata.$session_id` | Strongly recommended on every event |
60
+ | `user_email` | `metadata.$user_email` | Account/login/transaction flows |
61
+ | `name` | `metadata.$name` | Account create/update baseline |
62
+ | `phone` | `metadata.$phone` | Account create/update baseline |
63
+ | `payment_methods` | `metadata.$payment_methods` | Account baseline (array); SDK normalizes tenant-friendly shapes before wire |
64
+ | `sift_payment_method` | `metadata.$payment_method` | Sift payment object on transactions |
65
+ | `billing_address` | `metadata.$billing_address` | Nested keys prefixed with `$` on the wire |
66
+ | `app` | `metadata.$app` | Mobile clients |
67
+ | `ip_address`, `device_id`, `user_agent` | top-level | Optional |
68
+ | `metadata` | `metadata` | Plain Vesant rule signals and optional `$…` Sift pass-through |
53
69
 
54
- Until the fraud-service maps all Sift fields at the top level, the client copies some typed fields into `metadata` on the wire (e.g. `password_reason` `metadata.$reason`). Use `buildScoreRequestPreview(request)` to inspect the JSON body sent to the API.
70
+ Prefer typed fields for common Sift keys. Typed fields win if the same key appears in `metadata`.
71
+
72
+ ### Rule signals (SDK-supplied)
73
+
74
+ | Event | Fields |
75
+ |-------|--------|
76
+ | `$login` | `ip_country_mismatch` (device/session signals are server-side — send `device_id` + `session_id`) |
77
+ | `$update_account` | `two_fa_enabled`, `two_fa_disabled`, `two_fa_method_changed`; send current `user_email`, `name`, `phone`, `billing_address`, `payment_methods` for server-side diff |
78
+ | `$transaction` | `payment_method`, deposit/withdrawal counters, timing fields — see `TransactionRuleSignals` |
79
+
80
+ Do **not** send `new_device_added`, `email_changed`, `customer_age_years`, or `kyc_status` — Vesant derives or ignores these server-side.
81
+
82
+ ### Event-specific Sift fields
83
+
84
+ Typed on the request and normalized into `metadata.$*` on the wire:
85
+
86
+ - `$login` — `login_status`, `login_failure_reason`
87
+ - `$update_password` — `password_reason`, `password_status` (optional; default `$user_update` / `$success`)
88
+ - `$create_order` — `verification_phone_number`, `order_id`, `shipping_address`, `shipping_method`, `shipping_carrier`, `shipping_tracking_numbers`, `browser`, `brand_name`, `site_country`, `site_domain`, `ip`, plus required `$amount`/`$currency_code` metadata mapping from typed fields
89
+ - `$update_account` — `verification_phone_number` (E.164, maps to `metadata.$verification_phone_number`)
90
+ - `$transaction` — `transaction_status`, `decline_category`, `transfer_recipient_user_id`
91
+ - `$wager` — `wager_type`, `wager_status`, `wager_event_type`, `wager_event_name`, `wager_event_id`
92
+
93
+ Inspect the wire body with `buildScoreRequestPreview(request)`.
94
+
95
+ ## Examples by event
96
+
97
+ ### `$create_account`
98
+
99
+ ```typescript
100
+ await fraud.scoreEvent({
101
+ customer_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
102
+ sift_user_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
103
+ event_type: '$create_account',
104
+ ip_address: '198.51.100.101',
105
+ user_agent:
106
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
107
+ device_id: 'device_abcd1234',
108
+ session_id: 'sess_signup_001',
109
+ user_email: 'new@example.com',
110
+ name: 'Jane Doe',
111
+ phone: '+14155550123',
112
+ billing_address: {
113
+ name: 'Jane Doe',
114
+ address_1: '1 Main St',
115
+ city: 'SF',
116
+ region: 'CA',
117
+ country: 'US',
118
+ zipcode: '94105',
119
+ },
120
+ payment_methods: [{ payment_type: '$credit_card', card_bin: '424242' }],
121
+ metadata: {
122
+ country: 'US',
123
+ channel: 'web',
124
+ $referrer_user_id: '2a85f4c7-9b1e-4e2d-a6f0-8c7d5e4b3a21',
125
+ },
126
+ });
127
+ ```
128
+
129
+ ### `$login`
130
+
131
+ ```typescript
132
+ await fraud.scoreEvent({
133
+ customer_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
134
+ sift_user_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
135
+ event_type: '$login',
136
+ ip_address: '192.168.1.10',
137
+ device_id: 'device_abcd1234',
138
+ user_agent:
139
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
140
+ session_id: 'sess_login_001',
141
+ ip_country_mismatch: false,
142
+ metadata: {
143
+ channel: 'web',
144
+ country: 'US',
145
+ },
146
+ });
147
+ ```
148
+
149
+ ### `$update_account`
150
+
151
+ Bank account linked (e.g. ACH / open banking):
152
+
153
+ ```typescript
154
+ await fraud.scoreEvent({
155
+ customer_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
156
+ sift_user_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
157
+ event_type: '$update_account',
158
+ session_id: 'sess_update_001',
159
+ user_email: 'user@example.com',
160
+ name: 'Jane Doe',
161
+ phone: '+14155550123',
162
+ payment_methods: [
163
+ {
164
+ // SDK accepts tenant-friendly shapes and normalizes before wire:
165
+ payment_type: '$bank_account', // → $electronic_fund_transfer
166
+ account_number_last4: '1111', // → account_number_last5: '01111'
167
+ bank_name: 'FinBank',
168
+ account_id: '30025494',
169
+ },
170
+ ],
171
+ payment_method_updated: true,
172
+ metadata: { source: 'bank_link_webhook' },
173
+ });
174
+ ```
175
+
176
+ Crypto wallet updated:
177
+
178
+ ```typescript
179
+ await fraud.scoreEvent({
180
+ customer_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
181
+ sift_user_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
182
+ event_type: '$update_account',
183
+ payment_methods: [
184
+ {
185
+ payment_type: '$crypto_currency',
186
+ wallet_address: '0xabc123...',
187
+ wallet_type: '$crypto',
188
+ },
189
+ ],
190
+ metadata: {
191
+ crypto_currency: 'USDT',
192
+ network: 'TRC20',
193
+ wallet_address_last4: 'c123',
194
+ },
195
+ });
196
+ ```
197
+
198
+ ### Payment method normalization
199
+
200
+ The SDK normalizes `payment_methods` and `sift_payment_method` before wire emit (on by default). Tenants can send internal shapes; invalid Sift keys are mapped or moved to plain metadata.
201
+
202
+ | Mistake | Sift error | SDK fix |
203
+ |---------|------------|---------|
204
+ | `payment_type: '$bank_account'` | Invalid `$payment_type` | Auto-mapped to `$electronic_fund_transfer` |
205
+ | `account_number_last4` | Unknown field | Auto-mapped to `account_number_last5` |
206
+ | `account_id` on payment_method | Unknown field | Moved to `metadata.linkmoney_account_id` |
207
+ | `wallet_address_last4` on payment_method | Unknown field | Moved to metadata |
208
+
209
+ Inspect wire output before production:
210
+
211
+ ```typescript
212
+ import { buildScoreRequestPreview } from '@vesant-sdk/fraud';
213
+
214
+ const preview = buildScoreRequestPreview(request);
215
+ console.log(preview.metadata?.$payment_methods);
216
+ ```
217
+
218
+ Pre-normalize yourself? Set `skip_payment_method_normalization: true` on the request. Import helpers for custom pipelines:
219
+
220
+ ```typescript
221
+ import {
222
+ normalizeSiftPaymentMethods,
223
+ normalizeSiftPaymentType,
224
+ toSiftAccountNumberLast5,
225
+ } from '@vesant-sdk/fraud';
226
+ ```
227
+
228
+ ### `$transaction` (deposit)
229
+
230
+ ```typescript
231
+ await fraud.scoreEvent({
232
+ customer_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
233
+ sift_user_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
234
+ event_type: '$transaction',
235
+ transaction_id: '674a1b2c3d4e5f6789012345',
236
+ transaction_type: TransactionType.Deposit,
237
+ amount: 50.0,
238
+ currency: 'USD',
239
+ session_id: 'sess_deposit_001',
240
+ ip_address: '192.168.1.10',
241
+ device_id: 'device_abcd1234',
242
+ payment_method: '$credit_card',
243
+ is_first_deposit: true,
244
+ cumulative_deposit_amount: 12000,
245
+ deposit_count: 4,
246
+ transaction_status: TransactionStatus.Success,
247
+ metadata: {
248
+ channel: 'web',
249
+ country: 'US',
250
+ },
251
+ });
252
+ ```
253
+
254
+ ### `$create_order`
255
+
256
+ ```typescript
257
+ await fraud.scoreEvent({
258
+ customer_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
259
+ sift_user_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
260
+ event_type: '$create_order',
261
+ amount: 1230000,
262
+ currency_code: 'USD',
263
+ order_id: 'ORD-1001',
264
+ session_id: 'sess_order_001',
265
+ user_email: 'buyer@example.com',
266
+ verification_phone_number: '+14155550123',
267
+ billing_address: {
268
+ name: 'Jane Doe',
269
+ address_1: '1 Main St',
270
+ city: 'SF',
271
+ region: 'CA',
272
+ country: 'US',
273
+ zipcode: '94105',
274
+ },
275
+ shipping_address: {
276
+ name: 'Jane Doe',
277
+ address_1: '1 Main St',
278
+ city: 'SF',
279
+ region: 'CA',
280
+ country: 'US',
281
+ zipcode: '94105',
282
+ },
283
+ payment_methods: [{ payment_type: '$credit_card', card_last4: '4242' }],
284
+ shipping_method: '$physical',
285
+ shipping_carrier: 'UPS',
286
+ shipping_tracking_numbers: ['1Z999999'],
287
+ metadata: {
288
+ $items: [{ $item_id: 'SKU-1', $item_price: 1230000 }],
289
+ $promotions: [{ $promotion_id: 'PROMO-1' }],
290
+ },
291
+ });
292
+ ```
293
+
294
+ ### `$wager`
295
+
296
+ ```typescript
297
+ import { WagerStatus } from '@vesant-sdk/fraud';
298
+
299
+ await fraud.scoreEvent({
300
+ customer_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
301
+ sift_user_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
302
+ event_type: '$wager',
303
+ transaction_id: '674a1b2c3d4e5f6789012346',
304
+ wager_type: 'spread',
305
+ wager_status: WagerStatus.Accept,
306
+ amount: 50,
307
+ currency: 'USD',
308
+ wager_event_type: 'Sportsbook',
309
+ session_id: 'sess_wager_001',
310
+ ip_address: '192.168.1.10',
311
+ device_id: 'device_abcd1234',
312
+ });
313
+ ```
314
+
315
+ ### `$chargeback`
316
+
317
+ Feedback-only event for ACH returns and card chargebacks. Returns a reference; `score` and `decision` are not meaningful for tenant policy.
318
+
319
+ ```typescript
320
+ import { ChargebackReason, ChargebackState } from '@vesant-sdk/fraud';
321
+
322
+ await fraud.scoreEvent({
323
+ customer_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
324
+ sift_user_id: '0b54b190-1dc7-232d-b80e-0d2eb573ff47',
325
+ event_type: '$chargeback',
326
+ transaction_id: '674a1b2c3d4e5f6789012345',
327
+ order_id: 'LM-ORD-20240519-88421',
328
+ chargeback_state: ChargebackState.Received,
329
+ chargeback_reason: ChargebackReason.AchReturn,
330
+ ach_return_code: 'R01',
331
+ ip_address: '192.168.1.10',
332
+ device_id: 'device_abcd1234',
333
+ user_agent:
334
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
335
+ metadata: {
336
+ channel: 'web',
337
+ country: 'US',
338
+ },
339
+ });
340
+ ```
341
+
342
+ Use `buildScoreRequestPreview(request)` to inspect the normalized wire body before sending.
55
343
 
56
344
  ## Validation
57
345
 
package/dist/index.d.mts CHANGED
@@ -4,7 +4,7 @@ import { RiskLevel, Timestamp, BaseClient, RequestOptions } from '@vesant-sdk/co
4
4
  * Fraud event type unions aligned with fraud-service support matrix.
5
5
  */
6
6
  /** Events that run Sift scoring + rule engine */
7
- type ScoredFraudEventType = '$create_account' | '$login' | '$logout' | '$update_account' | '$update_password' | '$transaction' | '$wager';
7
+ type ScoredFraudEventType = '$create_account' | '$create_order' | '$login' | '$logout' | '$update_account' | '$update_password' | '$transaction' | '$wager';
8
8
  /** Feedback-only; no meaningful fraud score in response */
9
9
  type ChargebackFraudEventType = '$chargeback';
10
10
  /** Union accepted by scoreEvent / scoreEventsBulk */
@@ -12,7 +12,7 @@ type SupportedFraudEventType = ScoredFraudEventType | ChargebackFraudEventType;
12
12
  declare const SCORED_FRAUD_EVENT_TYPES: readonly ScoredFraudEventType[];
13
13
  declare const CHARGEBACK_FRAUD_EVENT_TYPE: "$chargeback";
14
14
  declare const SUPPORTED_FRAUD_EVENT_TYPES: readonly SupportedFraudEventType[];
15
- declare const PLANNED_FRAUD_EVENT_TYPES: readonly ["$verification", "$link_session_to_user", "$security_notification", "$create_order", "$update_order", "$order_status", "$add_promotion"];
15
+ declare const PLANNED_FRAUD_EVENT_TYPES: readonly ["$verification", "$link_session_to_user", "$security_notification", "$update_order", "$order_status", "$add_promotion"];
16
16
  /**
17
17
  * Listed in Vesant dashboard / future API — NOT valid for scoreEvent today.
18
18
  * @deprecated Not supported by POST /api/v1/fraud/score
@@ -104,13 +104,175 @@ declare const TransactionStatus: {
104
104
  readonly Failure: "$failure";
105
105
  readonly Pending: "$pending";
106
106
  };
107
+ type SiftPaymentType = '$cash' | '$check' | '$credit_card' | '$crypto_currency' | '$debit_card' | '$digital_wallet' | '$electronic_fund_transfer' | '$financing' | '$gift_card' | '$invoice' | '$in_app_purchase' | '$money_order' | '$points' | '$prepaid_card' | '$store_credit' | '$third_party_processor' | '$voucher' | '$sepa_credit' | '$sepa_instant_credit' | '$sepa_direct_debit' | '$ach_credit' | '$ach_debit' | '$wire_credit' | '$wire_debit';
108
+ declare const SiftPaymentTypeValues: readonly ["$cash", "$check", "$credit_card", "$crypto_currency", "$debit_card", "$digital_wallet", "$electronic_fund_transfer", "$financing", "$gift_card", "$invoice", "$in_app_purchase", "$money_order", "$points", "$prepaid_card", "$store_credit", "$third_party_processor", "$voucher", "$sepa_credit", "$sepa_instant_credit", "$sepa_direct_debit", "$ach_credit", "$ach_debit", "$wire_credit", "$wire_debit"];
109
+ declare const PaymentType: {
110
+ readonly Cash: "$cash";
111
+ readonly Check: "$check";
112
+ readonly CreditCard: "$credit_card";
113
+ readonly CryptoCurrency: "$crypto_currency";
114
+ readonly DebitCard: "$debit_card";
115
+ readonly DigitalWallet: "$digital_wallet";
116
+ readonly ElectronicFundTransfer: "$electronic_fund_transfer";
117
+ readonly Financing: "$financing";
118
+ readonly GiftCard: "$gift_card";
119
+ readonly Invoice: "$invoice";
120
+ readonly InAppPurchase: "$in_app_purchase";
121
+ readonly MoneyOrder: "$money_order";
122
+ readonly Points: "$points";
123
+ readonly PrepaidCard: "$prepaid_card";
124
+ readonly StoreCredit: "$store_credit";
125
+ readonly ThirdPartyProcessor: "$third_party_processor";
126
+ readonly Voucher: "$voucher";
127
+ readonly SepaCredit: "$sepa_credit";
128
+ readonly SepaInstantCredit: "$sepa_instant_credit";
129
+ readonly SepaDirectDebit: "$sepa_direct_debit";
130
+ readonly AchCredit: "$ach_credit";
131
+ readonly AchDebit: "$ach_debit";
132
+ readonly WireCredit: "$wire_credit";
133
+ readonly WireDebit: "$wire_debit";
134
+ };
135
+ type SiftWalletType = '$crypto' | '$digital' | '$fiat';
136
+ declare const SiftWalletTypeValues: readonly ["$crypto", "$digital", "$fiat"];
137
+ declare const WalletType: {
138
+ readonly Crypto: "$crypto";
139
+ readonly Digital: "$digital";
140
+ readonly Fiat: "$fiat";
141
+ };
107
142
  type FraudRiskLevel = 'low' | 'medium' | 'high' | 'critical';
108
143
 
109
144
  /**
110
- * Custom metadata for fraud score requests (non-Sift reserved keys).
145
+ * Metadata for fraud score requests.
146
+ * Plain keys are Vesant rule signals; $-prefixed keys are Sift pass-through (or set via typed fields).
111
147
  */
112
- type FraudCustomMetadata = Record<string, unknown>;
113
- declare function hasReservedMetadataKey(metadata: FraudCustomMetadata): string | undefined;
148
+ interface FraudRuleSignalMetadata {
149
+ /** Rule signal payment method (e.g. "$credit_card"), not Sift $payment_method object */
150
+ payment_method?: string;
151
+ country?: string;
152
+ /** Customer date of birth, ISO 8601 (YYYY-MM-DD). Useful on onboarding ($create_account). */
153
+ date_of_birth?: string;
154
+ two_fa_enabled?: boolean;
155
+ two_fa_disabled?: boolean;
156
+ two_fa_method_changed?: boolean;
157
+ ip_country_mismatch?: boolean;
158
+ is_first_deposit?: boolean;
159
+ cumulative_deposit_amount?: number;
160
+ deposit_count?: number;
161
+ failed_deposit_count?: number;
162
+ is_first_withdrawal?: boolean;
163
+ withdrawal_method_differs?: boolean;
164
+ cumulative_withdrawal_amount?: number;
165
+ withdrawal_count?: number;
166
+ hours_since_last_deposit?: number;
167
+ days_since_last_activity?: number;
168
+ hours_since_account_creation?: number;
169
+ }
170
+ /** Extra Sift fields forwarded verbatim in metadata (e.g. $referrer_user_id, $promotions). */
171
+ type SiftPassThroughMetadata = Record<`$${string}`, unknown>;
172
+ type FraudCustomMetadata = FraudRuleSignalMetadata & SiftPassThroughMetadata & Record<string, unknown>;
173
+ /** Maps typed request fields to metadata keys they populate (typed values win on normalize). */
174
+ declare const TYPED_SIFT_METADATA_KEYS: Readonly<Record<string, string>>;
175
+ declare function findMetadataConflictWithTypedFields(metadata: FraudCustomMetadata, request: Record<string, unknown>): string | undefined;
176
+
177
+ /**
178
+ * Optional top-level rule-signal fields copied into plain metadata on the wire.
179
+ */
180
+ interface LoginRuleSignals {
181
+ ip_country_mismatch?: boolean;
182
+ }
183
+ interface UpdateAccountRuleSignals {
184
+ two_fa_enabled?: boolean;
185
+ two_fa_disabled?: boolean;
186
+ two_fa_method_changed?: boolean;
187
+ }
188
+ interface TransactionRuleSignals {
189
+ payment_method?: string;
190
+ is_first_deposit?: boolean;
191
+ cumulative_deposit_amount?: number;
192
+ deposit_count?: number;
193
+ failed_deposit_count?: number;
194
+ is_first_withdrawal?: boolean;
195
+ withdrawal_method_differs?: boolean;
196
+ cumulative_withdrawal_amount?: number;
197
+ withdrawal_count?: number;
198
+ hours_since_last_deposit?: number;
199
+ days_since_last_activity?: number;
200
+ hours_since_account_creation?: number;
201
+ }
202
+ declare const LOGIN_RULE_SIGNAL_KEYS: readonly ["ip_country_mismatch"];
203
+ declare const UPDATE_ACCOUNT_RULE_SIGNAL_KEYS: readonly ["two_fa_enabled", "two_fa_disabled", "two_fa_method_changed"];
204
+ declare const TRANSACTION_RULE_SIGNAL_KEYS: readonly ["payment_method", "is_first_deposit", "cumulative_deposit_amount", "deposit_count", "failed_deposit_count", "is_first_withdrawal", "withdrawal_method_differs", "cumulative_withdrawal_amount", "withdrawal_count", "hours_since_last_deposit", "days_since_last_activity", "hours_since_account_creation"];
205
+
206
+ /**
207
+ * Sift-aligned structured fields normalized into metadata.$* on the wire.
208
+ */
209
+ interface SiftBillingAddress {
210
+ name?: string;
211
+ phone?: string;
212
+ address_1?: string;
213
+ address_2?: string;
214
+ city?: string;
215
+ region?: string;
216
+ country?: string;
217
+ zipcode?: string;
218
+ [key: string]: unknown;
219
+ }
220
+ interface SiftPaymentMethod {
221
+ payment_type?: string;
222
+ payment_gateway?: string;
223
+ card_bin?: string;
224
+ card_last4?: string;
225
+ avs_result_code?: string;
226
+ cvv_result_code?: string;
227
+ verification_status?: string;
228
+ routing_number?: string;
229
+ account_holder_name?: string;
230
+ account_number_last5?: string;
231
+ bank_name?: string;
232
+ bank_country?: string;
233
+ wallet_address?: string;
234
+ wallet_type?: '$crypto' | '$digital' | '$fiat' | string;
235
+ paypal_payer_id?: string;
236
+ paypal_payer_email?: string;
237
+ /**
238
+ * @deprecated Not a Sift field — use account_number_last5. Stripped by normalizeSiftPaymentMethod.
239
+ */
240
+ account_number_last4?: string;
241
+ /**
242
+ * @deprecated Not a Sift field — moved to metadata by normalizeSiftPaymentMethod.
243
+ */
244
+ account_id?: string | number;
245
+ /**
246
+ * @deprecated Not a Sift field — moved to metadata by normalizeSiftPaymentMethod.
247
+ */
248
+ wallet_address_last4?: string;
249
+ /**
250
+ * @deprecated Not a Sift field — moved to metadata by normalizeSiftPaymentMethod.
251
+ */
252
+ crypto_currency?: string;
253
+ /**
254
+ * @deprecated Not a Sift field — moved to metadata by normalizeSiftPaymentMethod.
255
+ */
256
+ network?: string;
257
+ [key: string]: unknown;
258
+ }
259
+ interface SiftApp {
260
+ os?: string;
261
+ os_version?: string;
262
+ device_manufacturer?: string;
263
+ device_model?: string;
264
+ device_unique_id?: string;
265
+ app_name?: string;
266
+ app_version?: string;
267
+ client_language?: string;
268
+ [key: string]: unknown;
269
+ }
270
+ interface SiftBrowser {
271
+ user_agent?: string;
272
+ accept_language?: string;
273
+ content_language?: string;
274
+ [key: string]: unknown;
275
+ }
114
276
 
115
277
  /**
116
278
  * Discriminated fraud score request types keyed on event_type.
@@ -124,16 +286,37 @@ interface FraudScoreRequestBase {
124
286
  ip_address?: string;
125
287
  device_id?: string;
126
288
  user_agent?: string;
289
+ /** Maps to metadata.$session_id */
290
+ session_id?: string;
291
+ /** Maps to metadata.$user_email */
292
+ user_email?: string;
293
+ /** Maps to metadata.$name */
294
+ name?: string;
295
+ /** Maps to metadata.$phone */
296
+ phone?: string;
297
+ /** Maps to metadata.$payment_method (Sift object) — typically on transactions */
298
+ sift_payment_method?: SiftPaymentMethod;
299
+ /** Maps to metadata.$payment_methods (Sift array) — account create/update baseline */
300
+ payment_methods?: SiftPaymentMethod[];
301
+ /** Maps to metadata.$billing_address */
302
+ billing_address?: SiftBillingAddress;
303
+ /** Maps to metadata.$app */
304
+ app?: SiftApp;
127
305
  /**
128
- * Custom fields only keys must NOT start with '$'.
129
- * Sift reserved fields belong on typed request fields.
306
+ * Plain Vesant rule signals and optional $-prefixed Sift pass-through keys.
307
+ * Prefer typed fields for common Sift keys ($session_id, $user_email, etc.).
130
308
  */
131
309
  metadata?: FraudCustomMetadata;
310
+ /**
311
+ * When true, payment_methods / sift_payment_method are passed through without
312
+ * Sift field normalization (for tenants sending pre-normalized wire keys).
313
+ */
314
+ skip_payment_method_normalization?: boolean;
132
315
  }
133
316
  interface CreateAccountScoreRequest extends FraudScoreRequestBase {
134
317
  event_type: '$create_account';
135
318
  }
136
- interface LoginScoreRequest extends FraudScoreRequestBase {
319
+ interface LoginScoreRequest extends FraudScoreRequestBase, LoginRuleSignals {
137
320
  event_type: '$login';
138
321
  login_status?: SiftLoginStatus;
139
322
  login_failure_reason?: SiftLoginFailureReason;
@@ -141,15 +324,19 @@ interface LoginScoreRequest extends FraudScoreRequestBase {
141
324
  interface LogoutScoreRequest extends FraudScoreRequestBase {
142
325
  event_type: '$logout';
143
326
  }
144
- interface UpdateAccountScoreRequest extends FraudScoreRequestBase {
327
+ interface UpdateAccountScoreRequest extends FraudScoreRequestBase, UpdateAccountRuleSignals {
145
328
  event_type: '$update_account';
329
+ /** Maps to metadata.$verification_phone_number */
330
+ verification_phone_number?: string;
146
331
  }
147
332
  interface UpdatePasswordScoreRequest extends FraudScoreRequestBase {
148
333
  event_type: '$update_password';
149
- password_reason: SiftPasswordUpdateReason;
150
- password_status: SiftPasswordUpdateStatus;
334
+ /** Defaults to $user_update on the wire when omitted */
335
+ password_reason?: SiftPasswordUpdateReason;
336
+ /** Defaults to $success on the wire when omitted */
337
+ password_status?: SiftPasswordUpdateStatus;
151
338
  }
152
- interface TransactionScoreRequest extends FraudScoreRequestBase {
339
+ interface TransactionScoreRequest extends FraudScoreRequestBase, TransactionRuleSignals {
153
340
  event_type: '$transaction';
154
341
  amount: number;
155
342
  currency: string;
@@ -159,6 +346,29 @@ interface TransactionScoreRequest extends FraudScoreRequestBase {
159
346
  decline_category?: string;
160
347
  transfer_recipient_user_id?: string;
161
348
  }
349
+ interface CreateOrderScoreRequest extends FraudScoreRequestBase {
350
+ event_type: '$create_order';
351
+ session_id?: string;
352
+ user_email?: string;
353
+ verification_phone_number?: string;
354
+ order_id?: string;
355
+ amount: number;
356
+ currency_code: string;
357
+ exchange_rate?: unknown;
358
+ payment_methods?: SiftPaymentMethod[];
359
+ billing_address?: SiftBillingAddress;
360
+ shipping_address?: SiftBillingAddress;
361
+ expedited_shipping?: boolean;
362
+ shipping_method?: '$electronic' | '$physical' | (string & Record<string, never>);
363
+ shipping_carrier?: string;
364
+ shipping_tracking_numbers?: string[];
365
+ brand_name?: string;
366
+ site_country?: string;
367
+ site_domain?: string;
368
+ ip?: string;
369
+ browser?: SiftBrowser;
370
+ app?: SiftApp;
371
+ }
162
372
  interface WagerScoreRequest extends FraudScoreRequestBase {
163
373
  event_type: '$wager';
164
374
  transaction_id: string;
@@ -178,7 +388,7 @@ interface ChargebackScoreRequest extends FraudScoreRequestBase {
178
388
  chargeback_reason?: SiftChargebackReason;
179
389
  ach_return_code?: string;
180
390
  }
181
- type FraudScoreRequest = CreateAccountScoreRequest | LoginScoreRequest | LogoutScoreRequest | UpdateAccountScoreRequest | UpdatePasswordScoreRequest | TransactionScoreRequest | WagerScoreRequest | ChargebackScoreRequest;
391
+ type FraudScoreRequest = CreateAccountScoreRequest | LoginScoreRequest | LogoutScoreRequest | UpdateAccountScoreRequest | UpdatePasswordScoreRequest | TransactionScoreRequest | CreateOrderScoreRequest | WagerScoreRequest | ChargebackScoreRequest;
182
392
  type ScoredFraudScoreRequest = Extract<FraudScoreRequest, {
183
393
  event_type: ScoredFraudEventType;
184
394
  }>;
@@ -246,4 +456,29 @@ declare function normalizeScoreRequestForApi(request: FraudScoreRequest): Record
246
456
  */
247
457
  declare function buildScoreRequestPreview(request: FraudScoreRequest): Record<string, unknown>;
248
458
 
249
- export { CHARGEBACK_FRAUD_EVENT_TYPE, type ChargebackFraudEventType, ChargebackReason, type ChargebackScoreRequest, type ChargebackScoreResponseData, ChargebackState, type CreateAccountScoreRequest, FraudClient, type FraudCustomMetadata, type FraudDecision, type FraudEventType, type FraudReactionType, type FraudRiskLevel, type FraudScoreRequest, type FraudScoreRequestBase, type FraudScoreResponseData, type FraudScoreResponseEnvelope, type FraudScoreResponseMetadata, type LoginScoreRequest, LoginStatus, type LogoutScoreRequest, PLANNED_FRAUD_EVENT_TYPES, PasswordUpdateReason, PasswordUpdateStatus, type PlannedFraudEventType, SCORED_FRAUD_EVENT_TYPES, SUPPORTED_FRAUD_EVENT_TYPES, type ScoredFraudEventType, type ScoredFraudScoreRequest, type SiftChargebackReason, SiftChargebackReasonValues, type SiftChargebackState, SiftChargebackStateValues, type SiftLoginFailureReason, SiftLoginFailureReasonValues, type SiftLoginStatus, SiftLoginStatusValues, type SiftPasswordUpdateReason, SiftPasswordUpdateReasonValues, type SiftPasswordUpdateStatus, SiftPasswordUpdateStatusValues, type SiftTransactionStatus, SiftTransactionStatusValues, type SiftTransactionType, SiftTransactionTypeValues, type SiftWagerStatus, SiftWagerStatusValues, type SupportedFraudEventType, type TenantAction, type TransactionScoreRequest, TransactionStatus, TransactionType, type UpdateAccountScoreRequest, type UpdatePasswordScoreRequest, type WagerScoreRequest, WagerStatus, buildScoreRequestPreview, hasReservedMetadataKey, isPlannedFraudEventType, isSupportedFraudEventType, normalizeScoreRequestForApi, validateScoreRequest };
459
+ /**
460
+ * Maps tenant-internal payment type signals to Sift-valid $payment_type values.
461
+ * Returns undefined when the value cannot be mapped.
462
+ */
463
+ declare function normalizeSiftPaymentType(value: string | undefined): SiftPaymentType | undefined;
464
+ /**
465
+ * Normalizes last-4/last-5 account digits for Sift $account_number_last5.
466
+ */
467
+ declare function toSiftAccountNumberLast5(value: unknown): string | undefined;
468
+ type NormalizePaymentMethodResult = {
469
+ method: SiftPaymentMethod;
470
+ metadataExtras?: Record<string, unknown>;
471
+ };
472
+ /**
473
+ * Normalizes a single payment method object for Sift wire format.
474
+ */
475
+ declare function normalizeSiftPaymentMethod(raw: Record<string, unknown>): NormalizePaymentMethodResult | null;
476
+ /**
477
+ * Normalizes payment method arrays and aggregates stripped metadata.
478
+ */
479
+ declare function normalizeSiftPaymentMethods(methods: SiftPaymentMethod[] | undefined): {
480
+ payment_methods?: SiftPaymentMethod[];
481
+ metadata?: Record<string, unknown>;
482
+ };
483
+
484
+ export { CHARGEBACK_FRAUD_EVENT_TYPE, type ChargebackFraudEventType, ChargebackReason, type ChargebackScoreRequest, type ChargebackScoreResponseData, ChargebackState, type CreateAccountScoreRequest, type CreateOrderScoreRequest, FraudClient, type FraudCustomMetadata, type FraudDecision, type FraudEventType, type FraudReactionType, type FraudRiskLevel, type FraudRuleSignalMetadata, type FraudScoreRequest, type FraudScoreRequestBase, type FraudScoreResponseData, type FraudScoreResponseEnvelope, type FraudScoreResponseMetadata, LOGIN_RULE_SIGNAL_KEYS, type LoginRuleSignals, type LoginScoreRequest, LoginStatus, type LogoutScoreRequest, PLANNED_FRAUD_EVENT_TYPES, PasswordUpdateReason, PasswordUpdateStatus, PaymentType, type PlannedFraudEventType, SCORED_FRAUD_EVENT_TYPES, SUPPORTED_FRAUD_EVENT_TYPES, type ScoredFraudEventType, type ScoredFraudScoreRequest, type SiftApp, type SiftBillingAddress, type SiftBrowser, type SiftChargebackReason, SiftChargebackReasonValues, type SiftChargebackState, SiftChargebackStateValues, type SiftLoginFailureReason, SiftLoginFailureReasonValues, type SiftLoginStatus, SiftLoginStatusValues, type SiftPassThroughMetadata, type SiftPasswordUpdateReason, SiftPasswordUpdateReasonValues, type SiftPasswordUpdateStatus, SiftPasswordUpdateStatusValues, type SiftPaymentMethod, type SiftPaymentType, SiftPaymentTypeValues, type SiftTransactionStatus, SiftTransactionStatusValues, type SiftTransactionType, SiftTransactionTypeValues, type SiftWagerStatus, SiftWagerStatusValues, type SiftWalletType, SiftWalletTypeValues, type SupportedFraudEventType, TRANSACTION_RULE_SIGNAL_KEYS, TYPED_SIFT_METADATA_KEYS, type TenantAction, type TransactionRuleSignals, type TransactionScoreRequest, TransactionStatus, TransactionType, UPDATE_ACCOUNT_RULE_SIGNAL_KEYS, type UpdateAccountRuleSignals, type UpdateAccountScoreRequest, type UpdatePasswordScoreRequest, type WagerScoreRequest, WagerStatus, WalletType, buildScoreRequestPreview, findMetadataConflictWithTypedFields, isPlannedFraudEventType, isSupportedFraudEventType, normalizeScoreRequestForApi, normalizeSiftPaymentMethod, normalizeSiftPaymentMethods, normalizeSiftPaymentType, toSiftAccountNumberLast5, validateScoreRequest };