Fraud scoring, as scripts see it. The division of labour is deliberate, and follows anomaly detection: this side owns the score arithmetic, the band decision and the persisted record, because those want unit tests and must behave identically whichever app asked, while the app side owns the rule definitions and their queries, because that is where the criteria builders and the app providers already live and because a rule's query belongs with the app that owns the data. Scoring is additive, not averaged: a rule's weight is a number of risk points, and the score is the sum of value times weight, capped at 100 - averaging was the obvious alternative and is wrong here, because with ten rules configured, two strong signals firing at full strength would average to 20 and could never reach a block threshold no matter how damning they were, whereas adding points keeps each rule's contribution stable as rules are added. A rule that throws contributes a failed signal, worth no points, and is reported on the event; it is never treated as a rule that fired.

Group: Managers


Properties

PropertyReturnsDescription
anonymousProxybooleanWhether the current request's IP is a known anonymising proxy. Indexed on every web hit by MaxMind, so this costs nothing extra to ask.
storeFraudPolicyStoreWhere this account's rule overrides, custom rules and thresholds live.

Methods

getStore() · newContextBuilder() · newSignalBuilder() · newSignalList() · decide(FraudContext context, List<FraudSignal> signals) · decide(FraudContext context, List<FraudSignal> signals, FraudThresholds thresholds) · recordDecision(FraudContext context, FraudDecision decision) · calcSummary(FraudDecision decision) · findCurrentLocation() · findCurrentCountryCode() · isAnonymousProxy() · findCurrentIp()

getStore()

Returns: FraudPolicyStore

Where this account's rule overrides, custom rules and thresholds live.

newContextBuilder()

Returns: Builder

Start building the operation to be scored.

newSignalBuilder()

Returns: Builder

Start building one rule's contribution to a score.

newSignalList()

Returns: List<FraudSignal>

A fresh mutable list for a script to accumulate signals into, since building a Java list from script is awkward.

decide(FraudContext context, List<FraudSignal> signals)

Returns: FraudDecision

Score an operation using this account's stored thresholds.

ParameterDescription
contextthe operation being scored. Must not be null
signalswhat the rules found. Must not be null, but may be empty

decide(FraudContext context, List<FraudSignal> signals, FraudThresholds thresholds)

Returns: FraudDecision

Score an operation against given thresholds. Pure computation: no queries, no persistence, no events - that is what makes the arithmetic testable independently of everything around it.

ParameterDescription
contextthe operation being scored. Must not be null
signalswhat the rules found. Must not be null, but may be empty
thresholdswhere the band boundaries sit. Must not be null

recordDecision(FraudContext context, FraudDecision decision)

Returns: FraudEvent

Persist a decision and announce it, if it is worth recording. A clear score is neither stored nor announced: recording every checkout that was fine would be a great deal of noise for no information. Everything from the watch band up is stored and announced, including scores that reached the block band while blocking was switched off - which is precisely the data calibration needs.

ParameterDescription
contextthe operation that was scored. Must not be null
decisionwhat was decided. Must not be null

calcSummary(FraudDecision decision)

Returns: String

A short human-readable account of which rules fired and by how much, strongest first.

ParameterDescription
decisionthe decision to describe. Must not be null

findCurrentLocation()

Returns: CityResponse

The current request's client location, for a rule that needs to know where this operation came from.

findCurrentCountryCode()

Returns: String

The two-letter country code the current request came from.

isAnonymousProxy()

Returns: boolean

Whether the current request's IP is a known anonymising proxy. Indexed on every web hit by MaxMind, so this costs nothing extra to ask.

findCurrentIp()

Returns: String

The client IP for the current request, as the fraud rules should see it.

To get full access to the Kademi Hub existing customers can login here, or new customers can register here.