Skip to main content
assess() is imported from ribaunt and called server-side to turn application-provided risk signals into a recommended action: allow, challenge, or block. When the action is challenge, the result includes a Workload you can pass straight to createChallenge(). The risk engine is an optional, stateless policy layer. All signals are caller-supplied and treated as untrusted. Ribaunt does not observe IPs, fingerprint devices, or track request velocity itself. Your application decides what to send.

Import

Signature

assess() is asynchronous so a custom scorer can call a remote model or service. Always await it.

Parameters

RiskSignals
required
Signals your application collected about the request. All fields are optional. An empty object succeeds and scores risk: 0. Known keys are ip, userAgent, accountAgeSeconds, and requestVelocity. Unknown keys are ignored by the default scorer but are available to custom scorers.
RiskScorer
Optional custom scorer. When you provide one, the default scorer is not executed. The scorer must return a finite number from 0 to 100 or assess() rejects.
RiskThresholds
Optional decision boundaries. Defaults to DEFAULT_RISK_THRESHOLDS ({ challenge: 40, block: 80 }). Validation requires 0 <= challenge < block <= 100. Invalid thresholds throw Challenge threshold must be less than block threshold (or a related message) rather than being silently repaired.
AssessWorkloadOptions
Optional bounds for the challenge workload: minDifficulty, maxDifficulty, minAmount, maxAmount, targetDurationMs, calibration, algorithm, and argonProfile. Used only when the action is challenge, but validated on every call, so an invalid workload throws even when the action would be allow or block.

Return value

Returns Promise<RiskAssessment>:
The risk value is a bounded heuristic score, not a fraud probability. Actions follow the threshold semantics:
  • risk < challengeallow
  • challenge <= risk < blockchallenge
  • risk >= blockblock

Example

Default scorer

If you do not pass scorer, Ribaunt uses a transparent, deterministic heuristic. It runs on the CPU only, performs no I/O, and is deliberately small so you can inspect it. The contributions are summed and clamped to 0–100. Negative, NaN, and Infinity values are ignored rather than crashing, very large values saturate instead of dominating, and unknown keys score 0.

Custom scorer

Provide a RiskScorer to replace the default heuristic. The score() method may be async, so you can call a remote model without changing callers:
Scorer failures propagate. If score() throws, assess() rejects instead of inventing a fallback score. Invalid outputs (NaN, Infinity, negative values, values above 100, non-numbers) are rejected with Scorer must return a finite number between 0 and 100 rather than clamped, so a broken policy stays visible.

Custom thresholds

The defaults are policy defaults, not a calibrated fraud model. Tune them to your application. DEFAULT_RISK_THRESHOLDS is frozen, and assess() copies thresholds internally, so mutating the exported object does not change behavior.

Challenge workload

When action is challenge, assessment.workload is generated by the same selectWorkload() engine used for adaptive difficulty, with the assessed risk as its riskScore. Pass your own bounds through workload:
Calibration keeps its raise-only semantics: a fast client benchmark can only increase work up to your maximums, never lower the server-owned baseline. If a riskScore sneaks into workload, the assessed risk overrides it. To produce a memory-hard workload, pass algorithm and argonProfile through workload. The returned Workload carries the algorithm and Argon2id parameters, so you can pass it straight to createChallenge():
See Argon2id opt-in for how the algorithms differ.

Compatibility

The risk engine is additive and opt-in. Existing riskScore usage on createChallenge() is unchanged:
createChallenge() never calls assess() implicitly. You can also chain the two flows manually:

Limitations and trust model

  • Signals are caller-supplied, not verified facts. Ribaunt does not independently observe IP, user agent, or account age. Do not treat signals.ip as authenticated.
  • The score is a heuristic, not a probability. Do not present risk as a probability of fraud or confidence that the user is a bot.
  • No reputation, fingerprinting, or external feeds. There is no IP reputation database, device fingerprint, or ML model. Custom scorers are the escape hatch for richer policy.
  • No automatic enforcement. assess() returns a recommendation. It does not block requests, send 403 responses, or ban IPs. Your application enforces the action.
See the Types reference for RiskSignals, RiskScorer, RiskThresholds, AssessOptions, and RiskAssessment.