Scoring Rules

MAIN Score Generators

Overview

Score Generators are a functional module of the anti-fraud system — a rule-based constructor for transaction scoring. The system works on the principle of cumulative risk: each check is assigned a weight, points are summed, and based on the total value a decision of PASS or REJECT is made.

The system contains two categories of generators:

CharacteristicBASICMAIN
LogicBinary: 0 or scoreValueBranching: multiple outcomes
ExecutionParallel (Basic Batch)Sequential with early-exit
Data sourceInternal (Redis, PostgreSQL)External providers (HTTP, Graph DB)
ScopePer-gate (separate for each gate)Per-transaction (once per transaction)
Count22 types4 types

All generators (BASIC and MAIN) are stored in a single ScoreGenerators table, differentiated by the generatorCategory column (BASIC / MAIN).

When MAIN generators are enabled, the following 3 BASIC generators should be disabled:

  • System Black/White List
  • Client's Black/White List
  • VPN usage

MAIN Generator Types

There are 4 MAIN Score Generators, defined in PGScoreGeneratorTypeEnum with category PGScoreGeneratorCategoryEnum.MAIN:

TypePurposeProviderRequired inputs
TRUSTLAYER_SPCard reputation check via TrustLayer (trusted / fraud)providerTrustLayercardToken
TRUSTLAYER_EMAIL_CHECK_SPEmail reputation check via TrustLayer (trusted / not found / fraud)providerTrustLayer (requestType: email)email
THREEFP_CHECKFingerprint check via TigerGraph graph DB (trusted device / fraud)providerTigerGraphFpfingerprint
GENERATED_CARD_CHECK_SPGenerated card detection via Smart Payments (valid / generated)providerSmartPaymentsgccCardToken, gccSessionId

TRUSTLAYER_SP and TRUSTLAYER_EMAIL_CHECK_SP are separate database entries and separate steps in the scoring chain, but they share the same external TrustLayer API and common ENV variables for mode/mocks.

Each MAIN SG is created with a config containing a set of outcomes — a mapping from provider result to scoring action:

  • NO_SCORE — do not add points
  • SCORE_VALUE — add scoreValue points
  • THRESHOLD — set the threshold value (badScoreBorder), guaranteeing REJECT

Each outcome also has an earlyExit flag — whether to interrupt the chain.

They are registered in the SCORE_GENERATOR_CREATE_TYPE_OBJ template.

Execution Flow

Sequential Execution and Early-Exit

MAIN generators execute strictly sequentially in the order defined by executionOrder. If a generator returns a specific result (e.g. trusted or fraud), the chain is interrupted (early-exit) — subsequent generators are not called.

Default execution order (from utils-sg-template.ts):

const MAIN_SG_DEFAULT_EXECUTION_ORDERS: Record<string, number> = {
  [PGScoreGeneratorTypeEnum.TRUSTLAYER_SP]: 1,
  [PGScoreGeneratorTypeEnum.TRUSTLAYER_EMAIL_CHECK_SP]: 2,
  [PGScoreGeneratorTypeEnum.THREEFP_CHECK]: 3,
  [PGScoreGeneratorTypeEnum.GENERATED_CARD_CHECK_SP]: 4,
};

That is, by default: TrustLayer (card) -> TrustLayer (email) -> 3FP Check -> Generated Card Check.

Early-exit logic per step:

1. TRUSTLAYER_SP          -> trusted? exit : fraud? exit(scoreValue) : continue
2. TRUSTLAYER_EMAIL_CHECK -> trusted? exit : fraud? exit(scoreValue) : continue
3. THREEFP_CHECK          -> trusted? exit : fraud? exit(scoreValue) : continue
4. GENERATED_CARD_CHECK   -> valid?   exit : generated? exit(>=threshold)

If a transaction is missing a required input (e.g. email for TRUSTLAYER_EMAIL_CHECK_SP), the orchestrator does not call the provider for that step and returns an error of the kind "missing required input".

Transaction Scope

All MAIN generators operate in the scope of a transaction:

  • Called once per transaction (not per gate)
  • Result is cached and applied to all gates in the cascade
  • No repeated provider calls when switching between gateways

Parallel Execution with Basic Batch

The MAIN pipeline and Basic Batch pipeline run in parallel (Promise.all). Basic Batch does not wait for MAIN and vice versa. After both pipelines complete, results are merged per-gate:

totalScore = MAIN.totalScore + BasicBatch[gateId].totalScore

SLA Timeline

0ms       500ms      800ms              2800ms
|---------|----------|------------------|
| Trust   | FP Check |   SP Card        |
| Layer   | (Graph)  |   Check          |
| <=500ms | <=300ms  |   <=2000ms       |
|         |          |                  |
|====================================== | Basic Batch (<=500ms, parallel)
|         |          |                  |
|------------------- Total MAIN: <=2800ms (worst case, no earlyExit)
|                    Total Basic Batch: <=500ms (finishes before MAIN)
|                    Total scoring: max(MAIN, BasicBatch) ~ <=2800ms worst case

With earlyExit at Phase 1 (Trust Layer) — total time ~ 500ms.

Card Block (Blocked Cards Cache)

Concept

When a provider returns a specific negative result (FRAUD_MATCH from Trust Layer, GENERATED from Smart Payments), the card is written to the global ScoringCardBlocks table. On subsequent checks, the system first checks this table — if the card is found, the provider is not called, saving time and resources.

Characteristics

ParameterValue
ScopeGlobal (not tied to a company)
UniquenessBy pair (cardToken, sourceType)
Supported generatorsTRUSTLAYER_SP, GENERATED_CARD_CHECK_SP
Not supportedTHREEFP_CHECK (checks device, not card)

Check-Before-Call Flow

Before calling external providers (Trust Layer, Smart Payments) for TRUSTLAYER_SP and GENERATED_CARD_CHECK_SP, a preliminary check of the local blocked cards cache (ScoringCardBlocks) is performed by the pair (cardToken, sourceType). If the card is already blocked, the provider call is skipped and the block reason and result are used from cache. This optimization does not apply to THREEFP_CHECK (it works with fingerprint, not card). The check-before-call logic executes at the beginning of each supported MAIN check in the Main Orchestrator.

1. Start MAIN generator phase
2. Does the generator support card-block? (TRUSTLAYER_SP / GENERATED_CARD_CHECK_SP)
   - No (THREEFP_CHECK) -> call provider directly
   - Yes -> check cardBlockCheck(cardToken)
3. Card found in ScoringCardBlocks?
   - Yes -> provider is NOT called, saved reason is used
   - No  -> call provider
4. Provider result = FRAUD_MATCH / GENERATED?
   - Yes -> side-effect: write to ScoringCardBlocks
5. scoreEvaluate(result, config) -> scoreValue + earlyExit

Architecture (Module Responsibilities)

The key principle: Score Generator is responsible only for scoring. Provider interaction logic and blocked card cache logic are outside the scoring operation.

Four Modules

ModuleLocationResponsibility
Main Orchestratortransaction-score/main/Execution sequence, early-exit, caching
Score Evaluatortransaction-score/main/Pure mapping: outcome -> scoreValue (no side-effects)
Card Blocktransaction-score/card-block/Check and write to ScoringCardBlockModel
Provider Adaptersscoring-providers/HTTP / TigerGraph calls to external services

Module Relationship

transactionScore() --- entry point
├── Basic Batch Pipeline (22 BASIC, parallel)
└── Main Orchestrator
    ├── Card Block       -> ScoringCardBlockModel (PostgreSQL)
    ├── Provider Adapters -> External Services (Trust Layer, TigerGraph, Smart Payments)
    └── Score Evaluator  -> pure function: outcome -> scoreValue

Score Evaluator (Pure Function)

Score Evaluator has no knowledge of providers, HTTP, database, or card-block. It receives a result and configuration — returns a score:

Input:  providerResult + outcomeList + scoreValue + badScoreBorder
Output: { scoreValue, earlyExit, flagValue }

scoreAction mapping:
  NO_SCORE    -> scoreValue: 0
  SCORE_VALUE -> scoreValue: sg.scoreValue (configured weight)
  THRESHOLD   -> scoreValue: badScoreBorder (guaranteed REJECT)

Data Models

ScoreGenerators (existing table, extended)

New column added:

ColumnTypeDescription
generatorCategoryENUM (BASIC / MAIN)Generator category. Default: BASIC

New values in PGScoreGeneratorTypeEnum: TRUSTLAYER_SP, TRUSTLAYER_EMAIL_CHECK_SP, THREEFP_CHECK, GENERATED_CARD_CHECK_SP.

Full table schema:

┌──────────────────────────────────────────┐
│           ScoreGenerators                │
├──────────────────────────────────────────┤
│ id                UUID PK                │
│ createdAt         TIMESTAMP              │
│ type              ENUM (25 values)       │
│ createType        ENUM (SYSTEM/MANUAL)   │
│ generatorCategory ENUM (BASIC/MAIN)      │  <-- NEW
│ title             STRING                 │
│ scoreValue        INTEGER                │
│ actionNoParam     ENUM                   │
│ isPriority        BOOLEAN                │
│ isActive          BOOLEAN                │
│ optCount          INTEGER nullable        │
│ optPercent        INTEGER nullable        │
│ optPeriodSec      INTEGER nullable        │
│ companyId         UUID FK -> Companies   │
└──────────────────┬───────────────────────┘
                   │ 1:1 (MAIN only)
                   ▼
┌──────────────────────────────────────────┐
│        ScoreGeneratorConfigs             │  <-- NEW
├──────────────────────────────────────────┤
│ id                UUID PK                │
│ scoreGeneratorId  UUID FK UNIQUE         │
│                   -> ScoreGenerators.id   │
│                   ON DELETE CASCADE       │
│ executionOrder    INTEGER NOT NULL        │
│ config            JSONB NOT NULL          │
│ createdAt         TIMESTAMP              │
│ updatedAt         TIMESTAMP              │
└──────────────────────────────────────────┘

┌──────────────────────────────────────────┐
│         ScoringCardBlocks                │  <-- NEW
├──────────────────────────────────────────┤
│ id                UUID PK                │
│ cardToken         STRING NOT NULL        │
│ blockReason       ENUM (FRAUD_MATCH /    │
│                   GENERATED) NOT NULL    │
│ sourceType        ENUM (TRUSTLAYER_SP /  │
│                   GENERATED_CARD_CHECK_SP)│
│                   NOT NULL               │
│ createdAt         TIMESTAMP              │
│                                          │
│ UNIQUE(cardToken, sourceType)            │
│ Scope: global (no companyId)             │
└──────────────────────────────────────────┘

ScoreGeneratorConfigs (new table)

Extended configuration for MAIN generators. 1:1 relationship with ScoreGeneratorModel:

ColumnTypeDescription
idUUID, PKPrimary key
scoreGeneratorIdUUID, FK, UNIQUELink to ScoreGenerators.id, ON DELETE CASCADE
executionOrderINTEGER, NOT NULLExecution order (1, 2, 3...)
configJSONB, NOT NULLConfiguration: outcomes, timeoutMs, fallbackOnError
createdAtTIMESTAMPCreated date
updatedAtTIMESTAMPUpdated date

ScoringCardBlocks (new table)

Global blocked cards cache:

ColumnTypeDescription
idUUID, PKPrimary key
cardTokenSTRING, NOT NULLCard token
blockReasonENUM (FRAUD_MATCH / GENERATED)Block reason
sourceTypeENUM (TRUSTLAYER_SP / GENERATED_CARD_CHECK_SP)Source generator
createdAtTIMESTAMPBlock date

Config JSONB Structure

Example for TRUSTLAYER_SP:

{
  "timeoutMs": 500,
  "outcomes": [
    { "result": "TRUSTED",     "scoreAction": "NO_SCORE",    "earlyExit": true  },
    { "result": "NOT_FOUND",   "scoreAction": "SCORE_VALUE", "earlyExit": false },
    { "result": "FRAUD_MATCH", "scoreAction": "THRESHOLD",   "earlyExit": true  }
  ],
  "fallbackOnError": "NO_SCORE"
}

Example for TRUSTLAYER_EMAIL_CHECK_SP (same structure as TRUSTLAYER_SP):

{
  "timeoutMs": 500,
  "outcomes": [
    { "result": "TRUSTED",     "scoreAction": "NO_SCORE",    "earlyExit": true  },
    { "result": "NOT_FOUND",   "scoreAction": "SCORE_VALUE", "earlyExit": false },
    { "result": "FRAUD_MATCH", "scoreAction": "THRESHOLD",   "earlyExit": true  }
  ],
  "fallbackOnError": "NO_SCORE"
}

Example for THREEFP_CHECK:

{
  "timeoutMs": 300,
  "outcomes": [
    { "result": "TRUSTED_DEVICE", "scoreAction": "NO_SCORE",    "earlyExit": true  },
    { "result": "UNTRUSTED",      "scoreAction": "SCORE_VALUE", "earlyExit": false }
  ],
  "fallbackOnError": "NO_SCORE"
}

Example for GENERATED_CARD_CHECK_SP:

{
  "timeoutMs": 2000,
  "outcomes": [
    { "result": "VALID",     "scoreAction": "NO_SCORE",  "earlyExit": true },
    { "result": "GENERATED", "scoreAction": "THRESHOLD", "earlyExit": true }
  ],
  "fallbackOnError": "NO_SCORE"
}

API Endpoints

Extended Existing Endpoints

EndpointChanges
GET /type-listAdds generatorCategory for each type + defaultConfig for MAIN
POST /get-listResponse includes generatorCategory and scoreGeneratorConfig (for MAIN)
POST /get-oneResponse includes generatorCategory and scoreGeneratorConfig (for MAIN)
POST /createFor MAIN: automatic creation of ScoreGeneratorConfigModel
POST /removeFor MAIN: cascading config deletion + recalculation of executionOrder
POST /toggle-activeSets isActive field on ScoreGeneratorModel

New Endpoint: Update MAIN Order

Atomic update of the execution order for all MAIN generators of a company in a single transaction. Designed for drag-and-drop on the frontend.

POST /api/v1/client/score-generators/update-main-order

Request body:

{
  "orderList": [
    { "scoreGeneratorId": "uuid-1", "executionOrder": 1 },
    { "scoreGeneratorId": "uuid-2", "executionOrder": 2 },
    { "scoreGeneratorId": "uuid-3", "executionOrder": 3 },
    { "scoreGeneratorId": "uuid-4", "executionOrder": 4 }
  ]
}

Validations:

  1. All scoreGeneratorId belong to the current company
  2. All have generatorCategory = MAIN
  3. executionOrder values are unique (no duplicates)
  4. executionOrder values are contiguous starting from 1 (i.e. 1, 2, 3, 4 — no gaps for four MAIN generators)

Setup and Provisioning

Creation

MAIN SG are created automatically when a company is created via sgCreateFromTemplateTransaction. For each MAIN SG a record is created in ScoreGeneratorModel + a linked record in ScoreGeneratorConfigModel with default config and execution order.

A migration has been added that also creates these generators for existing companies with default values (isActive=true). A separate migration adds the TRUSTLAYER_EMAIL_CHECK_SP type to the enum and ScoreGenerator / config rows for existing companies (following the same pattern as other MAIN generators).

Enabling / Disabling

Via API endpoint POST /toggle-active — sets the isActive field on the ScoreGeneratorModel.

Environment Variables

All variables are defined in src/utils/utils-env-config.ts.

Common (affect all MAIN SG)

ENVTypeDefaultDescription
MAIN_SG_STUB_RANDOMbooleanfalseIn stub mode — return random outcome instead of deterministic

TRUSTLAYER_SP

ENVTypeDefaultDescription
MAIN_SG_TRUSTLAYER_PROVIDER_MODEstring'real'Provider mode: real / stub / mock_service
MAIN_SG_TRUSTLAYER_HOSTstring''TrustLayer API host
MAIN_SG_TRUSTLAYER_API_KEYstring''TrustLayer API key (Bearer token)
MAIN_SG_TRUSTLAYER_MOCK_SCENARIOstring''Fixed mock scenario: trusted / not_found / fraud_match / timeout / http_500 / invalid_json
MAIN_SG_TRUSTLAYER_TIMEOUT_MSnumber500Request timeout to TrustLayer (ms)

TRUSTLAYER_EMAIL_CHECK_SP

A separate MAIN SG in the database and in the scoring chain, but uses the same variables as TRUSTLAYER_SP: host, key, MAIN_SG_TRUSTLAYER_PROVIDER_MODE, MAIN_SG_TRUSTLAYER_MOCK_SCENARIO, MAIN_SG_TRUSTLAYER_TIMEOUT_MS. There is no separate ENV for email timeout — both types use resolveMainSgTimeoutMs -> MAIN_SG_TRUSTLAYER_TIMEOUT_MS.

THREEFP_CHECK

ENVTypeDefaultDescription
MAIN_SG_THREEFP_TIMEOUT_MSnumber300Request timeout to TigerGraph (ms)

Additionally, depthLevel and minSuccessCount parameters are taken from the SG config in the database (not from ENV). Defaults (from utils-main-types.ts):

export const THREEFP_CHECK_CONFIG_DEFAULTS = {
  depthLevel: 1,
  minSuccessCount: 3,
} as const;

GENERATED_CARD_CHECK_SP

ENVTypeDefaultDescription
MAIN_SG_GCC_PROVIDER_MODEstring'real'Provider mode: real / stub / mock_service
MAIN_SG_GCC_HOSTstring''SmartPayments API host
MAIN_SG_GCC_SECRETstring''Secret key (x-af-secret header)
MAIN_SG_GCC_CONFIG_IDstring''Configuration ID on SmartPayments side
MAIN_SG_GCC_MOCK_SCENARIOstring''Fixed mock scenario: valid / generated / in_process / timeout / http_500 / invalid_json
MAIN_SG_GENERATED_CARD_TIMEOUT_MSnumber10000Request timeout (ms)

Default Timeouts Summary

SGENVDefault
TRUSTLAYER_SPMAIN_SG_TRUSTLAYER_TIMEOUT_MS500 ms
TRUSTLAYER_EMAIL_CHECK_SPMAIN_SG_TRUSTLAYER_TIMEOUT_MS500 ms (same as card)
THREEFP_CHECKMAIN_SG_THREEFP_TIMEOUT_MS300 ms
GENERATED_CARD_CHECK_SPMAIN_SG_GENERATED_CARD_TIMEOUT_MS10 000 ms

Default timeouts (from utils-main-types.ts):

const MAIN_SG_TRUSTLAYER_TIMEOUT_MS_DEFAULT = 500;
const MAIN_SG_THREEFP_TIMEOUT_MS_DEFAULT = 300;
const MAIN_SG_GENERATED_CARD_TIMEOUT_MS_DEFAULT = 10000;

ENV Summary for Mocks

ENVDescriptionDefault
MAIN_SG_TRUSTLAYER_PROVIDER_MODETrustLayer modereal
MAIN_SG_GCC_PROVIDER_MODEGCC modereal
MAIN_SG_TRUSTLAYER_MOCK_SCENARIOGlobal TrustLayer scenario(empty)
MAIN_SG_GCC_MOCK_SCENARIOGlobal GCC scenario(empty)
MAIN_SG_STUB_RANDOMRandom result in stub modefalse

Mock and Stub Modes

MAIN SG providers (TrustLayer and GCC/SmartPayments) support three operating modes, controlled via ENV. THREEFP_CHECK has no mock mode — it always calls TigerGraph directly. For emulation, a local TigerGraph (Docker) or data in a test environment is needed.

Provider Modes

ModeENV valueBehavior
ProductionrealReal HTTP request to provider
StubstubInstant response without network, fixed result
Mock servicemock_serviceLocal emulation with scenario selection

Setting the Mode

MAIN_SG_TRUSTLAYER_PROVIDER_MODE=mock_service
MAIN_SG_GCC_PROVIDER_MODE=mock_service

Stub Mode

The simplest option — instantly returns a default result without network calls:

  • TrustLayer (card and email): always NOT_FOUND
  • GCC: always VALID

If MAIN_SG_STUB_RANDOM=true, the result will be random from the allowed values.

Mock Service Mode

Full-featured emulation, allowing any provider response including errors and timeouts.

The scenario is selected in two ways (by priority):

1. Globally via ENV (one scenario for all requests)

MAIN_SG_TRUSTLAYER_MOCK_SCENARIO=trusted
MAIN_SG_GCC_MOCK_SCENARIO=generated

If these variables are set, they override any prefixes in tokens. All requests will return the same result.

2. Per-transaction via token prefix

Leave MAIN_SG_TRUSTLAYER_MOCK_SCENARIO and MAIN_SG_GCC_MOCK_SCENARIO empty. The scenario is determined by a prefix in the cardToken / email (TrustLayer) and gccCardToken (GCC) fields.

TrustLayer Mock Scenarios

Defined in TrustLayerMockScenarioEnum:

ScenarioEmulates
trustedfound: true — card/email found, trusted
not_foundfound: false — card/email not found
fraud_matchfound: true, has_chargeback: true — fraud
timeoutTimeout (sleep > timeoutMs)
http_500HTTP 500 from provider
invalid_jsonInvalid JSON response (missing found field)

Per-transaction prefix selection (for TRUSTLAYER_SP uses cardToken, for TRUSTLAYER_EMAIL_CHECK_SP uses email — same prefixes):

PrefixScenarioResult
tl_mock_trusted_trustedCard/email trusted
tl_mock_not_found_not_foundCard/email not found
tl_mock_fraud_match_fraud_matchFraud
tl_mock_timeout_timeoutProvider timeout
tl_mock_http_500_http_500HTTP 500
tl_mock_invalid_json_invalid_jsonInvalid response
(no prefix)NOT_FOUND (default)

Example for card: cardToken = "tl_mock_fraud_match_card123" -> provider returns FRAUD_MATCH.

Example for email: email = "[email protected]" -> scenario fraud_match.

Or globally: MAIN_SG_TRUSTLAYER_MOCK_SCENARIO=trusted (applies to all TrustLayer calls — both card and email).

GCC (SmartPayments) Mock Scenarios

Defined in GccMockScenarioEnum:

ScenarioEmulates
validstatus: 2 (COMPLETE) — card is valid
generatedstatus: -1 (ERROR) — card is generated
in_processstatus: 1 — check not completed (indeterminate)
timeoutTimeout
http_500HTTP 500
invalid_jsonResponse without status field

Per-transaction prefix selection (by gccCardToken field):

PrefixScenarioResult
gcc_mock_valid_validCard is valid
gcc_mock_generated_generatedCard is generated
gcc_mock_in_process_in_processCheck not completed
gcc_mock_timeout_timeoutProvider timeout
gcc_mock_http_500_http_500HTTP 500
gcc_mock_invalid_json_invalid_jsonInvalid response
(no prefix)VALID (default)

Example: gccCardToken = "gcc_mock_generated_token456" -> provider returns GENERATED.

Or globally: MAIN_SG_GCC_MOCK_SCENARIO=generated.

Typical Usage Scenarios

Check happy path (all trusted, early exit):

cardToken = "tl_mock_trusted_test1"

Check email happy path (with empty global MAIN_SG_TRUSTLAYER_MOCK_SCENARIO):

Check fraud blocking:

cardToken = "tl_mock_fraud_match_test2"
gccCardToken = "gcc_mock_generated_test2"

Check behavior when provider is unavailable:

cardToken = "tl_mock_timeout_test3"
gccCardToken = "gcc_mock_http_500_test3"

Check different transactions with different scenarios in one test:

Transaction 1: cardToken = "tl_mock_trusted_aaa"       -> TRUSTED, earlyExit
Transaction 2: cardToken = "tl_mock_not_found_bbb"     -> NOT_FOUND, scoring continues
Transaction 3: cardToken = "tl_mock_fraud_match_ccc"   -> FRAUD_MATCH, blocked

Scoring Outcomes and EarlyExit Reference

Default execution order: TRUSTLAYER_SP (1) -> TRUSTLAYER_EMAIL_CHECK_SP (2) -> THREEFP_CHECK (3) -> GENERATED_CARD_CHECK_SP (4).

GeneratorProvider outcomeActionScoreEarlyExitDescription
TRUSTLAYER_SPTRUSTEDNO_SCORE0trueCard trusted, skip remaining
TRUSTLAYER_SPNOT_FOUNDSCORE_VALUEscoreValuefalseCard not found, add points
TRUSTLAYER_SPFRAUD_MATCHTHRESHOLDbadScoreBordertrueFraud, block
TRUSTLAYER_SPprovider errorSCORE_VALUEscoreValuefalseProvider unavailable, add points
TRUSTLAYER_EMAIL_CHECK_SPTRUSTEDNO_SCORE0trueEmail trusted, skip remaining
TRUSTLAYER_EMAIL_CHECK_SPNOT_FOUNDSCORE_VALUEscoreValuefalseEmail not found, add points
TRUSTLAYER_EMAIL_CHECK_SPFRAUD_MATCHTHRESHOLDbadScoreBordertrueFraud, block
TRUSTLAYER_EMAIL_CHECK_SPprovider errorSCORE_VALUEscoreValuefalseProvider unavailable, add points
THREEFP_CHECKTRUSTEDNO_SCORE0trueFingerprint trusted
THREEFP_CHECKTRUSTED_DEVICENO_SCORE0trueDevice trusted
THREEFP_CHECKUNTRUSTEDSCORE_VALUEscoreValuefalseDevice unknown, add points
THREEFP_CHECKFRAUDTHRESHOLDbadScoreBordertrueFraud, block
THREEFP_CHECKprovider errorNO_SCORE0falseTigerGraph unavailable, no penalty
GENERATED_CARD_CHECK_SPVALIDNO_SCORE0trueCard is genuine, skip
GENERATED_CARD_CHECK_SPGENERATEDTHRESHOLDbadScoreBordertrueCard is generated, block
GENERATED_CARD_CHECK_SPprovider errorSCORE_VALUEscoreValuefalseProvider unavailable, add points

Error Handling

At the base level, each MAIN generator has a timeout (timeoutMs in the config JSONB). If a response is not received in time or the provider returns an error, fallbackOnError from the configuration is applied:

fallbackOnErrorBehaviorPurpose
NO_SCOREscoreValue = 0, earlyExit = falseMaximum conversion (Flexible Mode)

In the transaction notes the following is logged: "Provider Timeout. Applied default score: 0".

Module Structure in Code

src/utils/
├── transaction-score/
│   ├── utils-transaction-score.ts       # EXISTING: entry point + basic batch
│   ├── utils-scoring-constants.ts       # EXISTING: Redis keys
│   ├── utils-scoring-read.ts            # EXISTING: Redis ZSET read
│   ├── utils-scoring-write.ts           # EXISTING: Redis ZSET write
│   ├── sql/postgres/                    # EXISTING: SQL queries
│   │
│   ├── main/                            # NEW: MAIN generators
│   │   ├── utils-main-types.ts          #   Types for MAIN pipeline
│   │   ├── utils-main-orchestrator.ts   #   Orchestrator: sequential execution, early-exit
│   │   └── utils-main-score-evaluator.ts #  Pure mapping: outcome -> scoreValue
│   │
│   └── card-block/                      # NEW: Local block-list
│       └── utils-card-block.ts          #   check(cardToken) / create(cardToken, reason)
│
└── scoring-providers/                   # NEW: Provider adapters
    ├── utils-provider-trustlayer.ts     #   HTTP -> Trust Layer
    ├── utils-provider-tigergraph-fp.ts  #   Query -> TigerGraph (fingerprint)
    └── utils-provider-smartpayments.ts  #   HTTP -> Smart Payments

Did this page help you?