@mack1ch/fingerprint-js
v0.2.0
Published
Browser-only fingerprinting library for antifraud and risk scoring.
Maintainers
Readme
@1payment/fingerprint
TypeScript SDK для device/browser fingerprinting в антифрод-сценариях.
Пакет помогает:
- собирать браузерные сигналы,
- вычислять устойчивые идентификаторы среды,
- сравнивать fingerprint-снимки,
- строить вероятностный matching-контур (vNext),
- безопасно раскатывать решения через shadow/compare/assist/enforcement.
1. Установка
npm i @1payment/fingerprintТребования:
- Node.js
>= 18 - для браузерной части нужен реальный browser context
2. Быстрый старт (Browser)
import { createFingerprint } from "@1payment/fingerprint";
const fp = await createFingerprint({
mode: "balanced",
includeRaw: false,
includeDebug: false
});
console.log(fp);Вы получаете:
fingerprintId— полный fingerprint,stableId— более устойчивый идентификатор,environmentId— идентификатор среды,confidenceScore— качество сигналов,riskScore— эвристический риск,flags— признаки нестабильности/анома
3. Основной публичный API
Базовые функции
createFingerprint(options?) => Promise<FingerprintResult>getFingerprint(options?) => Promise<FingerprintResult>(алиас)hashComponents(components, salt?) => stringcompareFingerprints(a, b, options?) => FingerprintComparisontoFingerprintPayload(result, requestId?) => FingerprintPayload
Стратегии сравнения
strict— более жесткое сравнениеresilient— устойчивое сравнение при частичных изменениях сигналов
Пример:
import { compareFingerprints } from "@1payment/fingerprint";
const result = compareFingerprints(fpA, fpB, { strategy: "resilient" });
console.log(result.similarity, result.confidenceLabel);4. Опции createFingerprint
Ключевые опции:
mode:fast | balanced | stricttimeoutMs: таймаут на коллекторincludeRaw: включать сырые компонентыincludeDebug: отладочная информация по коллекторамincludePerformance: тайминги коллекторовcollectPermissions,collectCanvas,collectWebGL,collectAudio,collectFonts,collectStorageSignalssalt: соль для хэшированияcomponentWeights: веса компонентcustomComponents: свои асинхронные коллекторы
Рекомендация по режимам:
fast— для раннего этапа страницы,balanced— рабочий дефолт,strict— для high-risk сценариев.
5. Namespace v2 (browser + server flow)
В пакете есть namespace v2:
v2.BrowserFingerprintSessionv2.FingerprintServerSDKv2.migrateV1PayloadToV2v2.validateEnvelopeV2v2.hashPIIv2.similarityScore
Browser (v2)
import { v2 } from "@1payment/fingerprint";
const session = new v2.BrowserFingerprintSession();
const envelope = await session.collectStage({
requestId: "req-1",
stage: "pre_submit",
mode: "balanced"
});Server (v2)
import { v2 } from "@1payment/fingerprint";
const sdk = new v2.FingerprintServerSDK({ shadowMode: true });
const ingest = await sdk.ingestEnvelope(envelope, { country: "RU", asn: "AS12345" });
const match = await sdk.matchProfiles(ingest.eventId);
const risk = await sdk.calculateRisk(ingest.eventId);6. Namespace vNext (matching platform)
vNext — это production-контур для candidate retrieval + pairwise matching.
Что доступно:
- versioned contracts и compatibility validation,
- retrieval и
recall@K, - pairwise feature builder,
- baseline/prod модели,
- calibration layer,
- decision output (
same_device | likely_same | review | different), - rollout runtime (
shadow | compare | assist | enforcement), - logging/storage/labeling helpers,
- мониторинг (cohorts, drift).
Пример vNext runtime
import { vNext } from "@1payment/fingerprint";
const versions = vNext.buildVersionSet({
collectorVersion: "collector-v1",
featureSchemaVersion: "feature-v1",
modelVersion: "model-v1",
calibrationVersion: "cal-v1",
thresholdPolicyVersion: "thr-v1"
});Подробности:
docs/VNEXT_PHASE2.mddocs/threshold-policy.mddocs/rollout-checklist.md
7. Offline ML (опционально)
Если вы используете оффлайн обучение:
- скрипты в
offline_ml/ - baseline: Logistic Regression
- production candidate: HistGradientBoosting/XGBoost
- калибровка: sigmoid/isotonic
- экспорт model/calibration/threshold artifacts
Запуск:
python -m venv .venv
source .venv/bin/activate
pip install -r offline_ml/requirements.txt
python offline_ml/train.py --input "/path/to/pairwise.jsonl" --output-dir offline_ml/out --model-kind both --calibration sigmoidПодробный процесс:
offline_ml/README.mdoffline_ml/runbook.md
8. Демо для ручного тестирования
npm run demo:serveОткройте:
http://localhost:4173/demo/
В demo есть русскоязычный test harness:
- сценарные прогоны (
Balanced x5,Strict x5,Mixed x6), - быстрый compare последних результатов,
- ручное сравнение JSON A/B,
- экспорт истории прогонов.
9. Проверка качества перед релизом
npm run typecheck
npm run lint
npm test
npm run build10. Ограничения и важные замечания
- Fingerprinting — вероятностный сигнал, не абсолютная идентификация.
- Не принимайте финальные антифрод-решения только по одному hash/id.
- Для прод-решений используйте:
- candidate retrieval,
- pairwise scoring,
- calibration,
- threshold policy,
- мониторинг cohort/drift.
- Synthetic-only данные подходят для bootstrap/sanity, но не для финальных порогов production.
11. Документация
docs/API.mddocs/ARCHITECTURE.mddocs/SECURITY_PRIVACY.mddocs/TESTING.mddocs/UPGRADE_V2.mddocs/BROWSER_SDK_V2.mddocs/SERVER_SDK_V2.mddocs/PAYMENT_FLOW_MAPPING_V2.mddocs/VNEXT_PHASE2.mddocs/threshold-policy.mddocs/rollout-checklist.md
12. Лицензия
MIT
@1payment/fingerprint
TypeScript SDK для device/browser fingerprinting в платежных сценариях 1PAYMENT.
SDK ориентирован на antifraud/risk scoring и состоит из browser + server контуров:
- сбор клиентских сигналов,
- probabilistic matching,
- profile linking (device/payer/instrument),
- explainable risk.
Важные ограничения
- Библиотека не обещает 100% идентификацию пользователя и идеальную склейку между браузерами.
- Результат нужно использовать как вероятностный сигнал для antifraud/risk систем.
- По умолчанию библиотека не делает сетевых запросов.
- Библиотека не вызывает permission prompts.
Установка
npm i @1payment/fingerprintБыстрый старт (Browser)
<script type="module">
import { createFingerprint } from "https://esm.sh/@1payment/fingerprint";
const fp = await createFingerprint({
mode: "fast",
includeRaw: false,
includeDebug: false
});
console.log(fp);
</script>Что SDK возвращает
fingerprintId— полный session/browser fingerprint.stableId— более устойчивый fingerprint (device-centric subset).environmentId— fingerprint среды (браузер/платформа/рендер).confidenceScore— качество доступных сигналов.riskScore— риск по клиентским эвристикам.flags— tamper/anomaly/privacy-индикаторы.
Публичный API
v1/v2 base API
createFingerprint(options?) => Promise<FingerprintResult>getFingerprint(options?) => Promise<FingerprintResult>hashComponents(components, salt?) => stringcompareFingerprints(a, b, options?) => FingerprintComparisontoFingerprintPayload(result, requestId?) => FingerprintPayload
V2 APIs
В @1payment/fingerprint доступен namespace v2:
v2.BrowserFingerprintSessionv2.FingerprintServerSDKv2.migrateV1PayloadToV2v2.validateEnvelopeV2v2.hashPIIv2.similarityScore
vNext APIs
В @1payment/fingerprint доступен namespace vNext:
- retrieval + pairwise feature builder
- baseline/production model interfaces
- calibration layer
- rollout runtime (
shadow/compare/assist/enforcement) - versioned artifact compatibility validation
- labeling and monitoring helpers
Production contracts описаны в docs/VNEXT_PHASE2.md.
Как теперь работает vNext (Phase 2)
vNext теперь разделен на runtime matching-контур и offline ML lifecycle.
1) Browser snapshot (сбор сигналов)
Browser SDK собирает multi-signal fingerprint (navigator/locale/screen/canvas/webgl/audio/fonts/storage/permissions), а также:
fingerprintId,stableId,environmentId- component quality metadata (present/missing/unstable/privacy_reduced/error)
- top-level flags (webdriver/automation/incognito/spoofing hints)
Важно: fingerprintId/stableId/environmentId больше не трактуются как финальное решение, а используются как retrieval/diagnostic keys.
2) Runtime matching pipeline (server-side)
vNext runtime работает как двухстадийный matching:
- candidate retrieval / blocking
- pairwise scoring + calibration + threshold decision
Пайплайн:
- retrieval находит кандидатов (stable/environment/buckets/context);
- pairwise feature builder строит comparison vector;
- model выдает
rawScore; - calibration превращает его в
calibratedProbability; - threshold policy выдает решение:
same_devicelikely_samereviewdifferent
Decision содержит:
rawScorecalibratedProbabilitydecisionreasonscandidateSnapshotIdmodelVersioncalibrationVersionthresholdPolicyVersion
3) Versioned contracts и артефакты
Контракты versioned и валидируются до инференса:
collector_versionfeature_schema_versionmodel_versioncalibration_versionthreshold_policy_version
Артефакты загружаются независимо:
- model artifact
- calibration artifact
- threshold artifact
Если версии несовместимы — runtime отклоняет запуск инференса.
4) Logging и storage для обучения
Runtime логирует:
- snapshot-level события
- retrieval-level события
- pairwise-level события
Логи содержат versions + business anchors и используются для offline dataset/label enrichment.
Минимальный storage-модуль хранит:
- snapshots
- retrieval logs
- pairwise logs
- match decisions
- device profile history
5) Labeling pipeline
Pair labels строятся offline job’ом из production-like логов и anchors:
- positives: confirmed/verified same-entity anchors
- negatives: easy/medium/hard
- hard negatives: near-miss/high-score label=0 и конфликтные сценарии
6) Offline training lifecycle
Offline stack находится в offline_ml/ и не зависит от runtime:
- baseline: Logistic Regression
- production candidate: XGBoost (или HistGradientBoosting fallback)
- calibration: sigmoid/isotonic
- leak-safe split policy
- evaluation reports + artifact export
7) Rollout modes
Поддерживаются безопасные режимы:
shadow— считается, но не влияет на финальный actioncompare— сравнение с предыдущим контуромassist— сигнал для review/adminenforcement— участие в финальном decisioning
8) Monitoring и drift
Доступны helpers для:
- PR/ROC/LogLoss/Brier
- cohort breakdown
- retrieval recall@K
- distribution drift (PSI-like)
Как потестировать vNext
Полная проверка (рекомендуется)
npm run typecheck
npm testТолько vNext тесты
npm run test -- test/vnext.pipeline.test.ts test/vnext.retrieval.test.ts test/vnext.phase2.test.tsBrowser smoke (демо)
npm run demo:serveОткройте http://localhost:4173/demo/ и сравните несколько сборов/режимов.
Быстрый ручной чеклист в demo:
- Нажмите
Run Balanced x5:- проверьте
stable transitions(должен быть высоким); - посмотрите
last similarityмежду соседними запусками.
- проверьте
- Нажмите
Run Mixed x6:- оцените, как меняется similarity между
fast/balanced/strict; - сравните
Compare Last Two.
- оцените, как меняется similarity между
- Используйте
Use Last as A/B+Compare JSONsиCompare Strict:resilientобычно устойчивее при частичных изменениях;strictполезен для same-browser проверки.
- Нажмите
Download History:- сохраните историю прогона в JSON для последующего анализа/репортов.
- Нажмите
Clear Historyи повторите сценарий в incognito/private режиме.
Offline trainer
python -m venv .venv
source .venv/bin/activate
pip install -r offline_ml/requirements.txt
python offline_ml/train.py --input pairwise_training_rows.jsonl --output-dir offline_ml/out --model-kind both --calibration sigmoidПроверьте в offline_ml/out:
model-*.jsoncalibration-*.jsonthreshold-*.jsonevaluation-report.jsonevaluation-report.md
Режимы сбора (Browser)
fast— минимальная задержка для initial render.balanced— режим по умолчанию для pre-submit.strict— максимальный сбор для high-risk сценариев.
Рекомендуемый lifecycle:
page_open->fastpre_submit->balancedpost_init/подозрительные кейсы ->strict
Сравнение отпечатков
compareFingerprints() поддерживает стратегии:
strict— жесткое сравнение (подходит для same-browser проверок).resilient— устойчивое сравнение (лучше для cross-browser и частичных изменений).
Пример:
import { compareFingerprints } from "@1payment/fingerprint";
const cmp = compareFingerprints(a, b, { strategy: "resilient" });
console.log(cmp.similarity, cmp.confidenceLabel, cmp.matchedComponents);Browser SDK v2 (multi-stage)
import { v2 } from "@1payment/fingerprint";
const session = new v2.BrowserFingerprintSession();
const pageOpen = await session.collectStage({
requestId: "req-1",
stage: "page_open",
mode: "fast",
paymentContext: {
partnerId: "partner-1",
projectId: "project-1",
flowType: "card_form",
paymentType: "card",
userId: "u-123",
userData: "crm-42",
shopUrl: "https://merchant.example",
lang: "ru"
}
});
session.registerSubmitAttempt();
const preSubmit = await session.collectStage({
requestId: "req-1",
stage: "pre_submit",
mode: "balanced"
});Server SDK v2 (ingestion/enrichment/scoring)
import { v2 } from "@1payment/fingerprint";
const server = new v2.FingerprintServerSDK({ shadowMode: true });
const ingest = await server.ingestEnvelope(preSubmit, {
ip: "203.0.113.10",
asn: "AS12345",
country: "RU",
origin: "https://merchant.example"
});
await server.enrichWithPaymentInit({
requestId: "req-1",
orderId: "order-1001",
status: "init",
paymentType: "card"
});
await server.enrichWithCallback({
orderId: "order-1001",
status: "success",
token: "tok_abc",
accountMask: "4111****1111"
});
const match = await server.matchProfiles(ingest.eventId);
const risk = await server.calculateRisk(ingest.eventId);
const admin = await server.buildAdminView(ingest.eventId);Что возвращает server-контур:
- match probabilities (
sameDeviceProbability,samePayerProbability,sameInstrumentProbability) profileDecision- explainability (
topRiskReasons,topTrustReasons) - admin-ready view model
Какие данные прокидывать для максимальной точности
Чтобы повысить качество идентификации, передавайте:
partnerId,projectId,flowType,paymentTypeuserId,userDataorderId(когда появляется)tokenHash/token(для recurring/card linkage)phoneHash,emailHash,nameHash(где применимо)- request metadata на сервере:
ip,asn,country,origin/referrer
Важно: точность повышается не за счет одного “супер-хэша”, а за счет мультисигнального match + server enrichment.
Как считается fingerprint (формула)
Browser SDK собирает набор компонент:
components = { navigator, locale, screen, canvas, webgl, audio, fonts, storage, permissions?, ...customComponents }
Дальше применяется канонизация (стабильный порядок ключей/значений):
C = canonicalize(components)
Если веса не заданы, базовый идентификатор считается как:
fingerprintId = SHA-256(salt + ":" + JSON.stringify(C))
Если заданы componentWeights, используется взвешенное хэширование:
fingerprintId = SHA-256(salt + ":" + join("|", repeat(path=value, weight(path))))
где:
path=value— leaf-пара компоненты (например,navigator.userAgent="...");weight(path)— вес для пути (navigator.userAgent) или его top-level ключа (navigator);- веса нормализуются в диапазон
1..10; - вес
<= 0исключает параметр из финального хэша.
Дополнительно считаются:
stableId = hash(weightedStableSubset(C))environmentId = hash(weightedEnvironmentSubset(C))confidenceScore,riskScore,flags— на основе качества/аномалий сигналов.
Что можно менять самостоятельно
Через createFingerprint(options) можно гибко управлять расчетом:
- включать/выключать коллекторы:
collectCanvas,collectWebGL,collectAudio,collectFonts,collectStorageSignals,collectPermissions;
- задавать
mode(fast | balanced | strict) иtimeoutMs; - добавлять свои сигналы через
customComponents; - менять вклад каждого сигнала через
componentWeights; - задавать
saltдля изоляции хэш-пространства.
Пример:
const fp = await createFingerprint({
mode: "balanced",
salt: "merchant-v1",
collectPermissions: true,
componentWeights: {
navigator: 2,
"navigator.userAgent": 4,
screen: 1,
"fonts.availableCount": 3,
"audio.baseLatency": 0
},
customComponents: {
appBuild: () => "web-2026.03.20"
}
});Важно: изменение весов и состава компонент изменяет распределение fingerprintId/stableId/environmentId. Для production рекомендуем фиксировать конфиг по версии (signalsVersion/ваша версия профиля).
Совместимость с v1
- Принимается старый payload через migration layer:
v2.migrateV1PayloadToV2(...)
- В
ingestEnvelopeдоступен флагmigratedFromV1иmissingFields.
Demo
Запуск:
npm run demo:serveОткройте:
http://localhost:4173/demo/
В demo доступны:
Collect Fast/Balanced/Strict- сравнение двух JSON (Safari ↔ Chrome)
Compare JSONs(resilient)Compare StrictCopy Last JSON,Use Last as A/B
Скрипты
npm run lintnpm run typechecknpm run testnpm run test:browsernpm run buildnpm run size
Документация
docs/API.mddocs/ARCHITECTURE.mddocs/SECURITY_PRIVACY.mddocs/TESTING.mddocs/UPGRADE_V2.mddocs/BROWSER_SDK_V2.mddocs/SERVER_SDK_V2.mddocs/PAYMENT_FLOW_MAPPING_V2.mddocs/VNEXT_PHASE2.mddocs/threshold-policy.mddocs/rollout-checklist.mdoffline_ml/runbook.md
