Hulo Global
Plugins Roadmap

Fraud Prevention

Signal-based risk scoring on every order, monitor/enforce modes, review queue with customisable customer comms, alerts to Slack/Discord/Teams/Telegram, daily threat feeds — chargebacks stopped before fulfilment.

2,130 npm downloads last monthListed in the Vendure plugin directoryVendure 3.5 – 3.7MySQL · MariaDB · PostgreSQLAGPL source + commercial licence

What it does

Built for production from day one.

Every placed order is risk-scored server-side the moment it lands — no storefront integration required. Weighted signals (order velocity per IP and per canonical email identity, disposable email domains, block/allow lists with CIDR range matching, high-risk countries, failed-payment patterns, card AVS postcode/address mismatch, plus-addressing abuse, first-order value) roll up to a 0-100 score. Your per-channel thresholds decide what happens: log it, hold it for review, or hold it and tell the customer it is being verified. Digital-goods aware: fulfilment (licence keys, downloads) waits for approval, so one reviewer click is the difference between a sale and a chargeback.

Server-side enforcement

Assessment runs on OrderPlacedEvent inside Vendure — fraudsters can't bypass it by skipping your storefront JS. No checkout integration needed.

Weighted signal scoring

Velocity (IP/hour, IP/day, email/day, daily value), order value ceilings, disposable emails, list hits, high-risk countries, failed payments, identity fan-out (many emails from one IP = card testing), VPN/proxy/datacentre IPs, IP vs billing-country mismatch, MX-less email domains, billing vs shipping postcode. Every weight overridable per channel.

Card AVS mismatch

The card issuer's own verdict on the billing postcode and street address — the strongest address signal there is. Read automatically from Stripe for orders paid through Vendure's StripePlugin (no extra config), from payment metadata for custom handlers, or from a one-line avsResolver hook for any other gateway. Only an explicit fail scores; fails open. AVS fails stand out as red card chips in the review queue and on the order page, and an AVS-fails filter on both the review queue and the activity log shows only those orders — so a reviewer sees the bank's verdict before anything else.

Monitor → enforce rollout

Start in monitor mode: everything is scored and logged, nothing is held. Watch the Activity tab, tune thresholds, then flip to enforce.

"Off" never means blind

Even with protection disabled the engine still scores every order and records a shadow assessment. Risky shadow-scored orders warn in the server log, fan out to your ops channels and can email the admin — so you keep the full risk picture while protection is paused, and turning it back on starts from evidence, not guesswork.

Risk score on the order page

Every paid order's detail page shows the risk score out of 100, level, contributing signals and review-case status — colour-coded, light + dark theme. Your team sees the risk where they already work.

Manual review queue

Held orders wait for a human. Approve releases fulfilment; reject cancels — and each can be done silently (no customer email) or, on reject, with a one-click silent blocklist of the email + IP so the fraudster is turned away next time and never tipped off. Alerts fan out to Slack, Discord, Microsoft Teams, Telegram and an HMAC-signed webhook; a per-channel auto-approve timer means nothing strands over a weekend. Full audit trail on every decision.

Fulfilment hold hook

One-line host integration: ask pendingOrderIds() before releasing licence keys or shipping. Approval is the gate, not an afterthought.

Daily threat feeds + one-click presets

FireHOL Level 1, Spamhaus DROP (CIDR ranges matched properly), Tor exit nodes and ~3,500 disposable-email domains synced nightly — plus seven curated add-with-one-click presets (IPsum L3+, blocklist.de, FireHOL L2/L3, Emerging Threats compromised, CINS Army, StopForumSpam toxic domains). No URL hunting.

Email canonicalisation

[email protected], [email protected] and [email protected] all count as ONE identity for velocity — the plus-addressing trick stops working.

Trust works both ways

Returning customers earn NEGATIVE points — a real repeat buyer rarely trips a hold. Allowlisted identities (test accounts, key B2B customers, office IPs) skip every check entirely.

Customer messages in your voice

Every gating outcome — held, approved, rejected — is a per-channel editable template with variables, live preview and thoughtful defaults: a held order reads as 'a quick security check' with a stated turnaround, never an accusation, and rejections carry a refund timeline plus a human-appeal path. Each shows a default / customised badge; reset any selection or all of them in one click. You choose when — and whether — customers are told: never, block-level only, or always.

"What-if" simulator

Run a hypothetical order (email, IP, value, country, billing / shipping postcodes, card AVS results) against live data and see the exact signal-by-signal score breakdown — without logging or holding anything.

Multi-tab admin dashboard

Overview KPIs + daily chart, Rules, Review queue with count badge, Lists, Simulate, customer Lookup dossier (orders, spend, failed payments, case history, one-click allow/block), filterable Activity log with CSV export, Settings. WCAG AA in light and dark themes.

MySQL, MariaDB & PostgreSQL

The plugin follows whatever database your Vendure `dbConnectionOptions` use — no configuration. Verified against PostgreSQL 17; MySQL/MariaDB installs are unchanged.

Buy & activate from the admin

Start the 14-day free trial, subscribe or buy lifetime from the plugin's admin page — checkout opens in a new tab and the key installs itself within a minute, renewals included. The same card shows your plan, first-charge date and a <strong>Manage billing</strong> link to the Stripe portal (update card, cancel, switch plan). Already have a key? Paste it into the same banner. No `.env` edit, no redeploy; environment keys still take precedence for infrastructure-as-code setups.

One-click in-app updates

When a new version ships, an update banner shows current → latest with a What's-new link to the changelog. "Update now" installs the registry-verified release via your project's own package manager (yarn/npm/pnpm auto-detected) and gracefully restarts under pm2/systemd. Disable with `HULO_SELF_UPDATE=off`.

Install

Three steps, five minutes.

Add the package

Or run the one-line installer that does steps 1–3 for you:

curl -sSL https://huloglobal.com/vendure-plugins/fraud-prevention/install.sh | bash

Prefer to do it by hand?

yarn add @huloglobal/vendure-plugin-fraud-prevention # or npm install @huloglobal/vendure-plugin-fraud-prevention # or pnpm add @huloglobal/vendure-plugin-fraud-prevention

Register it

In your vendure-config.ts:

# vendure-config.ts import { FraudPreventionPlugin } from '@huloglobal/vendure-plugin-fraud-prevention'; export const config: VendureConfig = { plugins: [ FraudPreventionPlugin.init({ publicBaseUrl: 'https://shop.example.com', licenceKey: process.env.HULO_LICENCE_KEY_FRAUD_PREVENTION, }), // ... your other plugins ], };

Compile the admin UI

Add the extension to your compileUiExtensions call so the plugin's page appears in the admin:

// compile-admin-ui.ts import { compileUiExtensions } from '@vendure/ui-devkit/compiler'; import { FraudPreventionPlugin } from '@huloglobal/vendure-plugin-fraud-prevention'; compileUiExtensions({ outputPath: path.join(__dirname, 'admin-ui'), extensions: [FraudPreventionPlugin.uiExtensions], });
No migration to run. The plugin creates its tables on first boot and upgrades them in place on later versions.

That's it. Restart Vendure and the plugin's page is in the admin. Without a key it runs in the free tier; open the page and click Start 14-day free trial to switch everything on — the key installs itself, no .env edit, no redeploy.

Free tier vs licensed

Try the whole thing, keep the core for free.

Install without a key and everything on the left works indefinitely. The 14-day trial switches the right-hand column on with your real traffic; a licence keeps it on.

Free, no key

  • Monitor mode: every order scored and logged
  • Manual allow / block lists
  • Simulate a rule change before enforcing it

Trial + licensed

  • Enforce mode and review-queue holds
  • Threat-feed sync (FireHOL, Spamhaus, Tor, disposable email)
  • Email alerts
Start 14-day free trial →

HTTP endpoints

Every route exposed.

POST/fraud-prevention/checkPublic: storefront pre-check (rate limited, minimal shape)
GET/fraud-prevention/configAdmin: per-channel config
POST/fraud-prevention/configAdmin: save config
GET/fraud-prevention/statsAdmin: KPIs + daily series + top IPs
GET/fraud-prevention/casesAdmin: review queue
POST/fraud-prevention/cases/:id/approveAdmin: release + notify customer
POST/fraud-prevention/cases/:id/rejectAdmin: cancel + notify customer
POST/fraud-prevention/simulateAdmin: dry-run with full signal breakdown
GET/fraud-prevention/logAdmin: filterable audit log
POST/fraud-prevention/lists/syncAdmin: threat-feed sync (licensed)
GET/fraud-prevention/order-assessment/:orderIdAdmin: score + signals for the order-page panel
GET/fraud-prevention/feeds/presetsAdmin: curated threat-feed presets
GET/fraud-prevention/licence/statusAdmin: licence + evaluation + update status
POST/fraud-prevention/licence/activateAdmin: activate a licence key from the admin UI
POST/fraud-prevention/update/runAdmin: one-click in-app update + graceful restart

FAQ

Common questions.

How do I get a licence key?

Buy here — Stripe Checkout — monthly, annual (two months free) or lifetime. You'll receive the JWT key by email. Paste it into the plugin's admin settings (Activate) — no redeploy — or set it as HULO_LICENCE_KEY_FRAUD_PREVENTION in your .env if you prefer config-as-code; the env key wins when both are present.

Does it work without a key?

Yes — every subscription starts with a 14-day free trial. Install the plugin, open its admin page and click Start 14-day free trial: a card is required, nothing is charged until day 15, and you can cancel any time before then. The licence installs itself and every premium feature is on for the whole trial with your real traffic.

Which databases are supported?

MySQL, MariaDB and PostgreSQL (verified against PostgreSQL 17). The plugin follows your Vendure dbConnectionOptions automatically — there is nothing to configure.

How do updates work?

The plugin checks the npm registry daily. When a newer version exists, the admin dashboard shows an update banner with a What's-new link to the changelog and an "Update now" button that installs the registry-verified release via your own package manager and gracefully restarts under your process supervisor. Prefer manual control? Copy the install command instead, or set HULO_SELF_UPDATE=off.

Where is data stored?

In your Vendure database. The plugin adds its own tables (created on boot, or via a migration for the plugins that register entities) — your data never leaves your server.

Will it survive a Vendure upgrade?

Tested against Vendure >=3.5.0 <4.0.0 — 3.5, 3.6 and 3.7 are all covered by CI. A boot-time compatibility check emits a non-fatal warning if @vendure/core is outside that range, so upgrades to a future 3.x are safe to try. The 4.0 line will be tested and re-declared once its changelog lands.

Ready to ship?

Install in five minutes, run the trial on real traffic, keep it if it earns its place.