Plugin System
Extend the risk scoring engine with custom logic.
Plugins run after the built-in scoring engine. Each plugin receives the full verification context and returns a score adjustment.
Safety guarantees
Adjustments are clamped to ±50 per plugin. Errors are caught and logged — plugins never block verification. Async plugins are fully supported.
Writing a plugin
import type { RiskPlugin } from './plugins/risk-plugin.interface';
const ipBlocklistPlugin: RiskPlugin = {
name: 'ip-blocklist',
description: 'Check IP against internal blocklist',
priority: 10,
async evaluate(ctx) {
const blocked = await myDatabase.isBlocked(ctx.ipAddress);
return blocked
? { scoreAdjustment: 40, anomalies: ['ip_blocklisted'] }
: { scoreAdjustment: 0 };
},
};Registering
Runs on every verification across all sites:
import { PluginRegistryService } from './plugins';
@Injectable()
export class MyPlugins implements OnModuleInit {
constructor(private readonly registry: PluginRegistryService) {}
onModuleInit() {
this.registry.registerGlobal(ipBlocklistPlugin);
}
}Runs only for a specific site:
this.registry.registerForSite('site-uuid', geoFencingPlugin);Plugin context
Prop
Type
Built-in plugins
rate-abuse-detector
Compounds penalty when datacenter IP + high score (≥60), or 3+ anomalies + high score (≥70). Priority: 50.
time-of-day
Adds +5 risk during off-peak hours (2-6am UTC) when bot traffic typically spikes. Priority: 90.
Plugin execution order
Built-in scoring engine
PoW, fingerprint, behavior, GeoIP signals → base score
Global plugins (by priority)
Lower priority number runs first. Each plugin sees updated score from previous.
Site-scoped plugins (by priority)
Only plugins registered for this specific site.
Clamp and return
Final score clamped to 0-100. Action determined by site thresholds.