Janus
Features

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.