@mack1ch/fingerprint-js 0.1.0 → 0.1.2

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
@@ -1,97 +1,252 @@
1
- # 1pay_risk — сбор данных о пользователе (браузер, отпечаток, бот-детекция)
1
+ # @mack1ch/fingerprint-js
2
2
 
3
- React + TypeScript + Vite + Tailwind + Ant Design. Сбор метрик без запроса разрешений, экспорт в CSV.
3
+ Библиотека браузерного фингерпринта для antifraud-задач:
4
4
 
5
- ## Запуск через Docker
5
+ - собирает device/browser/network сигналы,
6
+ - строит устойчивый `coreHash` и детальный `fullHash`,
7
+ - считает метрики качества (`confidenceScore`),
8
+ - сравнивает профили (`similarityScore`, `riskScore`, `verdict`).
6
9
 
7
- ```bash
8
- # Сборка и запуск (порт 3000)
9
- docker compose up --build
10
+ ## Установка
10
11
 
11
- # Или только сборка образа и запуск контейнера
12
- docker build -t 1pay_risk .
13
- docker run -p 3000:80 1pay_risk
12
+ ```bash
13
+ npm i @mack1ch/fingerprint-js
14
14
  ```
15
15
 
16
- Приложение будет доступно по адресу: http://localhost:3000
16
+ ## Быстрый старт
17
17
 
18
- ## Локальная разработка
18
+ ```ts
19
+ import { getFingerprint } from '@mack1ch/fingerprint-js';
19
20
 
20
- ```bash
21
- npm install
22
- npm run dev
23
- ```
21
+ const profile = await getFingerprint({
22
+ required: {
23
+ merchantId: 'merchant-1',
24
+ userId: 'u-42',
25
+ },
26
+ optional: {
27
+ accountAgeDays: 180,
28
+ abBucket: 'A',
29
+ },
30
+ performance: { mode: 'balanced' },
31
+ privacy: { includeRaw: true, maskSensitive: true },
32
+ });
24
33
 
25
- ---
34
+ console.log(profile.coreHash); // Устойчивый идентификатор
35
+ console.log(profile.fullHash); // Полный отпечаток с шумными сигналами
36
+ console.log(profile.meta.confidenceScore);
37
+ ```
26
38
 
27
- This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
39
+ ## Публичный API
40
+
41
+ - `getFingerprint(options): Promise<FingerprintResult>`
42
+ - полный сбор: sync + async сигналы.
43
+ - `getFingerprintQuick(options): Promise<FingerprintResult>`
44
+ - быстрый режим: только sync сигналы.
45
+ - `compareFingerprints(current, reference): FingerprintComparison`
46
+ - сравнение текущего профиля с эталоном.
47
+ - `compareFingerprintAgainstHistory(current, history): FingerprintHistoryComparison`
48
+ - сравнение с набором исторических профилей и выбор лучшего матча.
49
+ - `buildIdentityId(profile): string`
50
+ - возвращает стабильный identity ID (сейчас это `coreHash`).
51
+ - `startPaymentFingerprintSession(options): PaymentFingerprintSession`
52
+ - двухфазный сбор для формы оплаты: быстрый профиль сразу + полный профиль в фоне.
53
+ - `assessPaymentRisk(input): PaymentRiskAssessment`
54
+ - готовая оценка риска для payment flow с `allow/challenge/manual_review/deny`.
55
+
56
+ ## Опции `getFingerprint`
57
+
58
+ ```ts
59
+ type FingerprintOptions = {
60
+ required: Record<string, string | number | boolean | null | undefined>;
61
+ optional?: Record<string, string | number | boolean | null | undefined>;
62
+ collect?: Partial<{
63
+ network: boolean;
64
+ webrtc: boolean;
65
+ permissions: boolean;
66
+ mediaDevices: boolean;
67
+ battery: boolean;
68
+ uaHints: boolean;
69
+ keyboard: boolean;
70
+ adBlock: boolean;
71
+ screenDetails: boolean;
72
+ storageEstimate: boolean;
73
+ }>;
74
+ performance?: {
75
+ mode?: 'fast' | 'balanced' | 'accurate';
76
+ timeoutMs?: number;
77
+ maxConcurrency?: number;
78
+ cacheTtlMs?: number;
79
+ };
80
+ privacy?: {
81
+ includeRaw?: boolean;
82
+ maskSensitive?: boolean;
83
+ };
84
+ hash?: {
85
+ algorithm?: 'SHA-256' | 'MD5';
86
+ };
87
+ };
88
+ ```
28
89
 
29
- Currently, two official plugins are available:
90
+ ### Рекомендации по входам
91
+
92
+ - В `required` передавайте стабильные бизнес-идентификаторы (`merchantId`, `userId`).
93
+ - Не передавайте в `required` постоянно меняющиеся значения (`sessionId`, nonce), иначе устойчивость снизится.
94
+ - Если нужно использовать `sessionId`, лучше класть в `optional`.
95
+
96
+ ## Формат результата `FingerprintResult`
97
+
98
+ ```ts
99
+ type FingerprintResult = {
100
+ coreHash: string; // устойчивый hash
101
+ fullHash: string; // полный hash
102
+ hash: string; // compatibility alias = fullHash
103
+ hashVersion: 'fp_v1';
104
+ components: FingerprintComponent[];
105
+ requiredInputs: Record<string, string>;
106
+ optionalInputs: Record<string, string>;
107
+ deviceSignals: Record<string, string>;
108
+ raw: UserDataItem[];
109
+ meta: {
110
+ mode: 'fast' | 'balanced' | 'accurate';
111
+ digestAlgorithm: 'SHA-256' | 'MD5';
112
+ elapsedMs: number;
113
+ timedOutCollectors: string[];
114
+ failedCollectors: Array<{ collector: string; reason: string }>;
115
+ cacheHit: boolean;
116
+ confidenceScore: number; // 0..1
117
+ };
118
+ };
119
+ ```
30
120
 
31
- - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
32
- - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
121
+ ## Интерпретация результатов
33
122
 
34
- ## React Compiler
123
+ - `coreHash` стабилен между сессиями (если стабильные сигналы и входы).
124
+ - `fullHash` может меняться чаще, это нормально.
125
+ - `confidenceScore`:
126
+ - `>= 0.85`: высокая полнота сигнала,
127
+ - `0.6..0.85`: средняя,
128
+ - `< 0.6`: ограниченная полнота.
35
129
 
36
- The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
130
+ ## Сравнение профилей
37
131
 
38
- ## Expanding the ESLint configuration
132
+ ```ts
133
+ import {
134
+ getFingerprint,
135
+ compareFingerprints,
136
+ compareFingerprintAgainstHistory,
137
+ } from '@mack1ch/fingerprint-js';
39
138
 
40
- If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
139
+ const current = await getFingerprint({ required: { merchantId: 'm1', userId: 'u1' } });
140
+ const reference = await getFingerprint({ required: { merchantId: 'm1', userId: 'u1' } });
41
141
 
42
- ```js
43
- export default defineConfig([
44
- globalIgnores(['dist']),
45
- {
46
- files: ['**/*.{ts,tsx}'],
47
- extends: [
48
- // Other configs...
142
+ const oneToOne = compareFingerprints(current, reference);
143
+ // oneToOne.verdict: same_device | likely_same | suspicious | different_device
49
144
 
50
- // Remove tseslint.configs.recommended and replace with this
51
- tseslint.configs.recommendedTypeChecked,
52
- // Alternatively, use this for stricter rules
53
- tseslint.configs.strictTypeChecked,
54
- // Optionally, add this for stylistic rules
55
- tseslint.configs.stylisticTypeChecked,
145
+ const historyResult = compareFingerprintAgainstHistory(current, [reference]);
146
+ // historyResult.best - лучший матч из истории
147
+ ```
56
148
 
57
- // Other configs...
58
- ],
59
- languageOptions: {
60
- parserOptions: {
61
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
62
- tsconfigRootDir: import.meta.dirname,
63
- },
64
- // other options...
149
+ `FingerprintComparison` содержит:
150
+
151
+ - `similarityScore` (0..1),
152
+ - `riskScore` (0..1),
153
+ - `verdict`,
154
+ - `reasons[]`,
155
+ - `changedStableKeys[]`, `changedVolatileKeys[]`.
156
+
157
+ ## Практика для antifraud
158
+
159
+ - Используйте `coreHash` как identity ключ.
160
+ - Используйте `compareFingerprintAgainstHistory` для решений, а не только strict hash equality.
161
+ - Храните историю последних профилей на пользователя/устройство.
162
+ - Разделяйте действие по порогам:
163
+ - низкий риск + высокая похожесть -> allow,
164
+ - средние значения -> challenge,
165
+ - высокий риск/низкая похожесть -> review/deny.
166
+
167
+ ## Payment Form Integration (рекомендуемый сценарий)
168
+
169
+ ```ts
170
+ import {
171
+ assessPaymentRisk,
172
+ compareFingerprintAgainstHistory,
173
+ compareFingerprints,
174
+ startPaymentFingerprintSession,
175
+ } from '@mack1ch/fingerprint-js';
176
+
177
+ const fpSession = startPaymentFingerprintSession({
178
+ required: {
179
+ merchantId: 'm-1',
180
+ paymentId: 'pay-100500',
181
+ customerId: 'c-42',
182
+ },
183
+ optional: {
184
+ emailHash: '...',
185
+ accountAgeDays: 220,
186
+ },
187
+ performance: {
188
+ fullMode: 'balanced',
189
+ startFullOnIdle: true,
190
+ },
191
+ hooks: {
192
+ onQuick: (quickProfile) => {
193
+ // Отправить быстрый профиль сразу после открытия формы.
194
+ void fetch('/api/fingerprint/stage', {
195
+ method: 'POST',
196
+ headers: { 'content-type': 'application/json' },
197
+ body: JSON.stringify(fpSession.buildStagePayload('quick', quickProfile)),
198
+ });
199
+ },
200
+ onFull: (fullProfile) => {
201
+ // Отправить полный профиль до сабмита или вместе с сабмитом.
202
+ void fetch('/api/fingerprint/stage', {
203
+ method: 'POST',
204
+ headers: { 'content-type': 'application/json' },
205
+ body: JSON.stringify(fpSession.buildStagePayload('full', fullProfile)),
206
+ });
65
207
  },
66
208
  },
67
- ])
209
+ });
68
210
  ```
69
211
 
70
- You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
71
-
72
- ```js
73
- // eslint.config.js
74
- import reactX from 'eslint-plugin-react-x'
75
- import reactDom from 'eslint-plugin-react-dom'
76
-
77
- export default defineConfig([
78
- globalIgnores(['dist']),
79
- {
80
- files: ['**/*.{ts,tsx}'],
81
- extends: [
82
- // Other configs...
83
- // Enable lint rules for React
84
- reactX.configs['recommended-typescript'],
85
- // Enable lint rules for React DOM
86
- reactDom.configs.recommended,
87
- ],
88
- languageOptions: {
89
- parserOptions: {
90
- project: ['./tsconfig.node.json', './tsconfig.app.json'],
91
- tsconfigRootDir: import.meta.dirname,
92
- },
93
- // other options...
94
- },
95
- },
96
- ])
212
+ ### Рекомендуемый backend pipeline для оплаты
213
+
214
+ 1. На открытии формы принять `quick` профиль.
215
+ 2. До финального authorize принять `full` профиль (он стартует в фоне в idle, чтобы не мешать UI).
216
+ 3. Сравнить с историей профилей клиента:
217
+ - `compareFingerprintAgainstHistory(current, history)`
218
+ 4. Для лучшего матча получить risk-классификацию:
219
+ - `assessPaymentRisk(...)`
220
+ 5. Принять решение:
221
+ - `allow` -> платеж без friction,
222
+ - `challenge` -> 3DS / step-up,
223
+ - `manual_review` -> ручная верификация,
224
+ - `deny` -> отклонение.
225
+
226
+ ### Минимальные поля для решения antifraud
227
+
228
+ - `coreHash`, `fullHash`
229
+ - `meta.confidenceScore`
230
+ - `comparison.best.similarityScore`
231
+ - `comparison.best.riskScore`
232
+ - `comparison.best.verdict`
233
+ - `assessment.decision`, `assessment.score`, `assessment.reasons`
234
+
235
+ ## Ограничения
236
+
237
+ - Библиотека не гарантирует 100% идентификацию в вебе.
238
+ - Некоторые сигналы зависят от браузера, разрешений и сетевой среды.
239
+ - При частичной недоступности API часть сигналов деградирует, это отражается в `meta`.
240
+
241
+ ## Разработка библиотеки
242
+
243
+ ```bash
244
+ npm install
245
+ npm run build:lib
246
+ ```
247
+
248
+ Проверка упаковки:
249
+
250
+ ```bash
251
+ npm pack
97
252
  ```