Rules engine
Before any ML scoring, Veritus consults the rules engine. If a rule matches, the rule decides the verdict and scoring is skipped entirely. This is how operators apply deterministic, explicit policy without waiting for the scorer to learn.
Order of evaluation per check
- Resolve form & thresholds (if form_id supplied)
- Check monthly quota — if over plan limit, return 402 Payment Required
- Evaluate rules — customer-scoped + global. Highest priority match wins.
- If a rule matched: skip vendors, return rule verdict, log as
rules_v1+rule_match - If no rule matched: run vendors (email, phone, IP, password) in parallel
- Sum reason weights, compute score, compare to thresholds → verdict
- Persist the check, return JSON
Why rules-first
Three reasons:
- Deterministic: if you say "block this email domain", you don't want the ML overruling you
- Cheap: rules evaluate in microseconds; skipping vendors saves you money on the ones you pay per-call (Twilio, ZeroBounce)
- Fast: a rule-matched check returns in <50ms vs <500ms for a full scoring run
Priority resolution
Multiple rules can match the same signup. We pick the winner in this order:
- Customer-scoped beats global (your rules beat the platform's)
- Within same scope:
block>review>allow(safer default)
So if a customer-scoped allow rule and a global block rule both match,
the allow wins (customer overrides platform). But if both are customer-scoped, the block wins.
Hit tracking
Every match increments rules.hits and updates
last_hit_at. You see these in the rules list so you can
spot dead rules and noisy ones.