@fraud-intercept/sdk 0.1.0 → 0.2.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/README.md CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  Typed Node.js client for the Fraud Intercept **Submit Event** API (`POST /api/v1/events`).
4
4
 
5
- > **Note:** npm publish is not live yet. Install from this monorepo path or wait for the public registry release.
5
+ Published on npm as [`@fraud-intercept/sdk`](https://www.npmjs.com/package/@fraud-intercept/sdk). API reference: [fraud-intercept.com/api-docs](https://fraud-intercept.com/api-docs/introduction).
6
6
 
7
7
  ## Requirements
8
8
 
9
9
  - Node.js 18+ (uses global `fetch`)
10
+ - A Fraud Intercept API key from your brand dashboard (see [authentication](https://fraud-intercept.com/api-docs/authentication))
10
11
 
11
12
  ## Install
12
13
 
@@ -85,7 +86,52 @@ The client returns the API `data` object, including:
85
86
  - `AuthenticationError` — invalid or missing API key (401)
86
87
  - `RateLimitError` — rate limit exceeded (429)
87
88
 
88
- Client-side validation runs before any HTTP call (missing `eventId`, invalid `eventType`, no identifiers).
89
+ Client-side validation runs before any HTTP call (missing `eventId`, invalid `eventType`, no identifiers, invalid `creditCardHash` format).
90
+
91
+ ## Payment network matching
92
+
93
+ Cross-brand payment linking requires **FI Payment Fingerprint v1** — the same 64-character hash for the same funding PAN across all brands on the network.
94
+
95
+ ### Algorithm
96
+
97
+ 1. Use the **funding PAN** (primary account number) only — not wallet DPANs or processor tokens.
98
+ 2. Strip all non-digit characters from the PAN string.
99
+ 3. Validate the result is **13–19** digits.
100
+ 4. Compute `SHA-256` over the **UTF-8** encoding of that digit string.
101
+ 5. Send the digest as **lowercase hexadecimal**, exactly **64** characters, in `creditCardHash`.
102
+
103
+ Do **not** include expiry, CVV, cardholder name, billing ZIP, or merchant-specific salts.
104
+
105
+ ### Reference vector
106
+
107
+ | Input PAN (digits only) | Fingerprint v1 |
108
+ |-------------------------|----------------|
109
+ | `4111111111111111` | `9bbef19476623ca56c17da75fd57734dbf82530686043a6e491c6d71befe8f6e` |
110
+
111
+ Use the SDK helpers to compute or validate hashes:
112
+
113
+ ```typescript
114
+ import {
115
+ hashCreditCardPan,
116
+ FI_PAYMENT_FINGERPRINT_V1_REFERENCE_HASH,
117
+ validateCreditCardHash,
118
+ } from '@fraud-intercept/sdk'
119
+
120
+ const fingerprint = hashCreditCardPan('4111 1111 1111 1111')
121
+ // → 9bbef19476623ca56c17da75fd57734dbf82530686043a6e491c6d71befe8f6e
122
+ ```
123
+
124
+ ### Anti-patterns (will not network-match)
125
+
126
+ These identifiers **will not** correlate with other brands in the identity graph:
127
+
128
+ - Payment processor tokens / network tokens
129
+ - Apple Pay / Google Pay device account numbers (DPANs)
130
+ - `HMAC-SHA256(PAN, merchant_secret)` or other per-merchant salted hashes
131
+ - BIN + last4 only (ambiguous, not a PAN fingerprint)
132
+ - Prefixed digests such as `sha256:...` (rejected by the API)
133
+
134
+ Full contract: [Payment fingerprint — API docs](https://fraud-intercept.com/api-docs/endpoints/events#payment-fingerprint-v1).
89
135
 
90
136
  ## Development
91
137
 
package/dist/client.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FraudIntercept = void 0;
4
4
  const types_1 = require("./types");
5
5
  const errors_1 = require("./errors");
6
+ const credit_card_fingerprint_1 = require("./credit-card-fingerprint");
6
7
  const DEFAULT_BASE_URL = 'https://fraud-intercept.com';
7
8
  const DEFAULT_TIMEOUT = 10000;
8
9
  const DEFAULT_RETRIES = 2;
@@ -43,6 +44,12 @@ class FraudIntercept {
43
44
  if (!request.email && !request.phone && !request.creditCardHash) {
44
45
  throw new errors_1.FraudInterceptError('At least one identifier (email, phone, or creditCardHash) is required', 400, 'VALIDATION_ERROR');
45
46
  }
47
+ if (request.creditCardHash) {
48
+ const cc = (0, credit_card_fingerprint_1.parseCreditCardHashField)(request.creditCardHash, 'creditCardHash');
49
+ if (cc.error) {
50
+ throw new errors_1.FraudInterceptError(cc.error, 400, 'VALIDATION_ERROR');
51
+ }
52
+ }
46
53
  }
47
54
  async requestWithRetry(path, body, idempotencyKey, attempt = 0) {
48
55
  try {
@@ -0,0 +1,12 @@
1
+ export declare const FI_PAYMENT_FINGERPRINT_VERSION: "v1";
2
+ /** SHA-256("4111111111111111") — use in docs and tests */
3
+ export declare const FI_PAYMENT_FINGERPRINT_V1_REFERENCE_HASH = "9bbef19476623ca56c17da75fd57734dbf82530686043a6e491c6d71befe8f6e";
4
+ export declare function normalizePanDigits(pan: string): string;
5
+ export declare function hashCreditCardPan(pan: string): string;
6
+ export declare function normalizeCreditCardHash(input: string | null | undefined): string | null;
7
+ export declare function validateCreditCardHash(hash: string): boolean;
8
+ export declare function creditCardHashFieldError(fieldName: 'creditCardHash' | 'credit_card_hash'): string;
9
+ export declare function parseCreditCardHashField(input: unknown, fieldName?: 'creditCardHash' | 'credit_card_hash'): {
10
+ value: string | null;
11
+ error?: string;
12
+ };
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FI_PAYMENT_FINGERPRINT_V1_REFERENCE_HASH = exports.FI_PAYMENT_FINGERPRINT_VERSION = void 0;
4
+ exports.normalizePanDigits = normalizePanDigits;
5
+ exports.hashCreditCardPan = hashCreditCardPan;
6
+ exports.normalizeCreditCardHash = normalizeCreditCardHash;
7
+ exports.validateCreditCardHash = validateCreditCardHash;
8
+ exports.creditCardHashFieldError = creditCardHashFieldError;
9
+ exports.parseCreditCardHashField = parseCreditCardHashField;
10
+ const crypto_1 = require("crypto");
11
+ exports.FI_PAYMENT_FINGERPRINT_VERSION = 'v1';
12
+ /** SHA-256("4111111111111111") — use in docs and tests */
13
+ exports.FI_PAYMENT_FINGERPRINT_V1_REFERENCE_HASH = '9bbef19476623ca56c17da75fd57734dbf82530686043a6e491c6d71befe8f6e';
14
+ const PAN_DIGITS_REGEX = /^[0-9]{13,19}$/;
15
+ const FINGERPRINT_REGEX = /^[a-f0-9]{64}$/;
16
+ const SHA256_PREFIX_REGEX = /^sha256:/i;
17
+ function normalizePanDigits(pan) {
18
+ return pan.replace(/\D/g, '');
19
+ }
20
+ function hashCreditCardPan(pan) {
21
+ const digits = normalizePanDigits(pan);
22
+ if (!PAN_DIGITS_REGEX.test(digits)) {
23
+ throw new Error('PAN must be 13–19 digits after removing non-digits');
24
+ }
25
+ return (0, crypto_1.createHash)('sha256').update(digits, 'utf8').digest('hex');
26
+ }
27
+ function normalizeCreditCardHash(input) {
28
+ if (input == null)
29
+ return null;
30
+ const trimmed = String(input).trim();
31
+ if (!trimmed)
32
+ return null;
33
+ if (SHA256_PREFIX_REGEX.test(trimmed))
34
+ return null;
35
+ return trimmed.replace(/\s+/g, '').toLowerCase();
36
+ }
37
+ function validateCreditCardHash(hash) {
38
+ return FINGERPRINT_REGEX.test(hash);
39
+ }
40
+ function creditCardHashFieldError(fieldName) {
41
+ return `${fieldName} must be a 64-character lowercase SHA-256 hex fingerprint (FI Payment Fingerprint v1). See API docs: Payment fingerprint.`;
42
+ }
43
+ function parseCreditCardHashField(input, fieldName = 'creditCardHash') {
44
+ if (input == null)
45
+ return { value: null };
46
+ const raw = String(input).trim();
47
+ if (!raw)
48
+ return { value: null };
49
+ if (SHA256_PREFIX_REGEX.test(raw)) {
50
+ return { value: null, error: creditCardHashFieldError(fieldName) };
51
+ }
52
+ const normalized = normalizeCreditCardHash(raw);
53
+ if (!normalized || !validateCreditCardHash(normalized)) {
54
+ return { value: null, error: creditCardHashFieldError(fieldName) };
55
+ }
56
+ return { value: normalized };
57
+ }
package/dist/index.d.ts CHANGED
@@ -2,4 +2,5 @@ export { FraudIntercept } from './client';
2
2
  export { FraudInterceptError, AuthenticationError, RateLimitError } from './errors';
3
3
  export type { EventType, SubmitEventRequest, SubmitEventOptions, SubmitEventResponse, MultiAccountMetadata, EventHelperRequest, FraudInterceptConfig, CheckRegistrationRequest, CheckRegistrationResponse, CheckLoginRequest, CheckLoginResponse, CheckDepositRequest, CheckDepositResponse, CheckWithdrawalRequest, CheckWithdrawalResponse, Flag, TriggeredRule, MatchedThreat, MatchedFraudster, AthleteMatch, DeviceInfo, MultiAccountInfo, DetectionCoverage, ResponseNote, } from './types';
4
4
  export { EVENT_TYPES } from './types';
5
+ export { FI_PAYMENT_FINGERPRINT_VERSION, FI_PAYMENT_FINGERPRINT_V1_REFERENCE_HASH, hashCreditCardPan, normalizeCreditCardHash, validateCreditCardHash, parseCreditCardHashField, } from './credit-card-fingerprint';
5
6
  export { FraudIntercept as default } from './client';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = exports.EVENT_TYPES = exports.RateLimitError = exports.AuthenticationError = exports.FraudInterceptError = exports.FraudIntercept = void 0;
3
+ exports.default = exports.parseCreditCardHashField = exports.validateCreditCardHash = exports.normalizeCreditCardHash = exports.hashCreditCardPan = exports.FI_PAYMENT_FINGERPRINT_V1_REFERENCE_HASH = exports.FI_PAYMENT_FINGERPRINT_VERSION = exports.EVENT_TYPES = exports.RateLimitError = exports.AuthenticationError = exports.FraudInterceptError = exports.FraudIntercept = void 0;
4
4
  var client_1 = require("./client");
5
5
  Object.defineProperty(exports, "FraudIntercept", { enumerable: true, get: function () { return client_1.FraudIntercept; } });
6
6
  var errors_1 = require("./errors");
@@ -9,5 +9,12 @@ Object.defineProperty(exports, "AuthenticationError", { enumerable: true, get: f
9
9
  Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_1.RateLimitError; } });
10
10
  var types_1 = require("./types");
11
11
  Object.defineProperty(exports, "EVENT_TYPES", { enumerable: true, get: function () { return types_1.EVENT_TYPES; } });
12
+ var credit_card_fingerprint_1 = require("./credit-card-fingerprint");
13
+ Object.defineProperty(exports, "FI_PAYMENT_FINGERPRINT_VERSION", { enumerable: true, get: function () { return credit_card_fingerprint_1.FI_PAYMENT_FINGERPRINT_VERSION; } });
14
+ Object.defineProperty(exports, "FI_PAYMENT_FINGERPRINT_V1_REFERENCE_HASH", { enumerable: true, get: function () { return credit_card_fingerprint_1.FI_PAYMENT_FINGERPRINT_V1_REFERENCE_HASH; } });
15
+ Object.defineProperty(exports, "hashCreditCardPan", { enumerable: true, get: function () { return credit_card_fingerprint_1.hashCreditCardPan; } });
16
+ Object.defineProperty(exports, "normalizeCreditCardHash", { enumerable: true, get: function () { return credit_card_fingerprint_1.normalizeCreditCardHash; } });
17
+ Object.defineProperty(exports, "validateCreditCardHash", { enumerable: true, get: function () { return credit_card_fingerprint_1.validateCreditCardHash; } });
18
+ Object.defineProperty(exports, "parseCreditCardHashField", { enumerable: true, get: function () { return credit_card_fingerprint_1.parseCreditCardHashField; } });
12
19
  var client_2 = require("./client");
13
20
  Object.defineProperty(exports, "default", { enumerable: true, get: function () { return client_2.FraudIntercept; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fraud-intercept/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Fraud Intercept SDK for real-time Digital Trust event scoring",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,6 +10,18 @@
10
10
  "test": "vitest run",
11
11
  "prepublishOnly": "npm run build"
12
12
  },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/petrovpetkov01-web/fraud-intercept.git",
16
+ "directory": "packages/sdk"
17
+ },
18
+ "homepage": "https://fraud-intercept.com/api-docs/introduction",
19
+ "bugs": {
20
+ "url": "https://github.com/petrovpetkov01-web/fraud-intercept/issues"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
13
25
  "keywords": ["fraud", "digital-trust", "risk-scoring", "device-intelligence"],
14
26
  "license": "MIT",
15
27
  "devDependencies": {