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
ReturnsPromise<RiskAssessment>:
risk value is a bounded heuristic score, not a fraud probability. Actions follow the threshold semantics:
risk < challenge→allowchallenge <= risk < block→challengerisk >= block→block
Example
Default scorer
If you do not passscorer, 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 aRiskScorer to replace the default heuristic. The score() method may be async, so you can call a remote model without changing callers:
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
DEFAULT_RISK_THRESHOLDS is frozen, and assess() copies thresholds internally, so mutating the exported object does not change behavior.
Challenge workload
Whenaction 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:
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():
Compatibility
The risk engine is additive and opt-in. ExistingriskScore 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.ipas authenticated. - The score is a heuristic, not a probability. Do not present
riskas 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, send403responses, or ban IPs. Your application enforces the action.
RiskSignals, RiskScorer, RiskThresholds, AssessOptions, and RiskAssessment.