npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mack1ch/fingerprint-js

v0.2.0

Published

Browser-only fingerprinting library for antifraud and risk scoring.

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?) => string
  • compareFingerprints(a, b, options?) => FingerprintComparison
  • toFingerprintPayload(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 | strict
  • timeoutMs: таймаут на коллектор
  • includeRaw: включать сырые компоненты
  • includeDebug: отладочная информация по коллекторам
  • includePerformance: тайминги коллекторов
  • collectPermissions, collectCanvas, collectWebGL, collectAudio, collectFonts, collectStorageSignals
  • salt: соль для хэширования
  • componentWeights: веса компонент
  • customComponents: свои асинхронные коллекторы

Рекомендация по режимам:

  • fast — для раннего этапа страницы,
  • balanced — рабочий дефолт,
  • strict — для high-risk сценариев.

5. Namespace v2 (browser + server flow)

В пакете есть namespace v2:

  • v2.BrowserFingerprintSession
  • v2.FingerprintServerSDK
  • v2.migrateV1PayloadToV2
  • v2.validateEnvelopeV2
  • v2.hashPII
  • v2.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.md
  • docs/threshold-policy.md
  • docs/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.md
  • offline_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 build

10. Ограничения и важные замечания

  • Fingerprinting — вероятностный сигнал, не абсолютная идентификация.
  • Не принимайте финальные антифрод-решения только по одному hash/id.
  • Для прод-решений используйте:
    • candidate retrieval,
    • pairwise scoring,
    • calibration,
    • threshold policy,
    • мониторинг cohort/drift.
  • Synthetic-only данные подходят для bootstrap/sanity, но не для финальных порогов production.

11. Документация

  • docs/API.md
  • docs/ARCHITECTURE.md
  • docs/SECURITY_PRIVACY.md
  • docs/TESTING.md
  • docs/UPGRADE_V2.md
  • docs/BROWSER_SDK_V2.md
  • docs/SERVER_SDK_V2.md
  • docs/PAYMENT_FLOW_MAPPING_V2.md
  • docs/VNEXT_PHASE2.md
  • docs/threshold-policy.md
  • docs/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?) => string
  • compareFingerprints(a, b, options?) => FingerprintComparison
  • toFingerprintPayload(result, requestId?) => FingerprintPayload

V2 APIs

В @1payment/fingerprint доступен namespace v2:

  • v2.BrowserFingerprintSession
  • v2.FingerprintServerSDK
  • v2.migrateV1PayloadToV2
  • v2.validateEnvelopeV2
  • v2.hashPII
  • v2.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:

  1. candidate retrieval / blocking
  2. pairwise scoring + calibration + threshold decision

Пайплайн:

  • retrieval находит кандидатов (stable/environment/buckets/context);
  • pairwise feature builder строит comparison vector;
  • model выдает rawScore;
  • calibration превращает его в calibratedProbability;
  • threshold policy выдает решение:
    • same_device
    • likely_same
    • review
    • different

Decision содержит:

  • rawScore
  • calibratedProbability
  • decision
  • reasons
  • candidateSnapshotId
  • modelVersion
  • calibrationVersion
  • thresholdPolicyVersion

3) Versioned contracts и артефакты

Контракты versioned и валидируются до инференса:

  • collector_version
  • feature_schema_version
  • model_version
  • calibration_version
  • threshold_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 — считается, но не влияет на финальный action
  • compare — сравнение с предыдущим контуром
  • assist — сигнал для review/admin
  • enforcement — участие в финальном 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.ts

Browser smoke (демо)

npm run demo:serve

Откройте http://localhost:4173/demo/ и сравните несколько сборов/режимов.

Быстрый ручной чеклист в demo:

  1. Нажмите Run Balanced x5:
    • проверьте stable transitions (должен быть высоким);
    • посмотрите last similarity между соседними запусками.
  2. Нажмите Run Mixed x6:
    • оцените, как меняется similarity между fast/balanced/strict;
    • сравните Compare Last Two.
  3. Используйте Use Last as A/B + Compare JSONs и Compare Strict:
    • resilient обычно устойчивее при частичных изменениях;
    • strict полезен для same-browser проверки.
  4. Нажмите Download History:
    • сохраните историю прогона в JSON для последующего анализа/репортов.
  5. Нажмите 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-*.json
  • calibration-*.json
  • threshold-*.json
  • evaluation-report.json
  • evaluation-report.md

Режимы сбора (Browser)

  • fast — минимальная задержка для initial render.
  • balanced — режим по умолчанию для pre-submit.
  • strict — максимальный сбор для high-risk сценариев.

Рекомендуемый lifecycle:

  • page_open -> fast
  • pre_submit -> balanced
  • post_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, paymentType
  • userId, userData
  • orderId (когда появляется)
  • 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 Strict
  • Copy Last JSON, Use Last as A/B

Скрипты

  • npm run lint
  • npm run typecheck
  • npm run test
  • npm run test:browser
  • npm run build
  • npm run size

Документация

  • docs/API.md
  • docs/ARCHITECTURE.md
  • docs/SECURITY_PRIVACY.md
  • docs/TESTING.md
  • docs/UPGRADE_V2.md
  • docs/BROWSER_SDK_V2.md
  • docs/SERVER_SDK_V2.md
  • docs/PAYMENT_FLOW_MAPPING_V2.md
  • docs/VNEXT_PHASE2.md
  • docs/threshold-policy.md
  • docs/rollout-checklist.md
  • offline_ml/runbook.md