bbas-devicer - v0.2.1
    Preparing search index...

    bbas-devicer - v0.2.1

    bbas-devicer

    Bot Blocking & Anti-Scrape Middleware for the FP-Devicer Intelligence Suite.
    Developed by Gateway Corporate Solutions.


    bbas-devicer enriches every DeviceManager.identify() call with a bot score and action decision — classifying each request as a real browser, a headless browser, a scraper, or a known crawler, and emitting an allow / challenge / block decision based on a configurable rule engine.

    Step Description
    UA analysis Classifies the User-Agent string against 38 known patterns: headless browsers, scrapers, HTTP clients, and legitimate crawlers.
    Header analysis Checks for missing required browser headers (accept, accept-language, accept-encoding), scraper debug headers, absent sec-fetch-* headers, and suspicious header ordering.
    Velocity Computes a sliding-window request rate and flags devices that exceed the configured threshold.
    Cross-plugin enrichment On Pro/Enterprise, reads ip-devicer (Tor, VPN, proxy, hosting, AI agent) and tls-devicer / peer-devicer signals to augment the score.
    Scoring Produces a composite bot score (0–100) from up to 13 named factors.
    Rule engine Evaluates a priority-sorted rule list; first match wins. Ships with sensible defaults and supports fully custom rules.

    Install bbas-devicer as a standalone package:

    npm install bbas-devicer
    

    Install bbas-devicer with FP-Devicer:

    npm install devicer.js bbas-devicer
    

    Install the full Devicer Intelligence Suite meta-package:

    npm install @gatewaycorporate/devicer-intel
    

    Optional peer dependencies (install the ones matching your storage choice):

    npm install better-sqlite3   # SQLite adapter
    npm install ioredis # Redis adapter
    npm install pg # PostgreSQL adapter

    import { DeviceManager }  from 'devicer.js';
    import { IpManager } from 'ip-devicer';
    import { TlsManager } from 'tls-devicer';
    import {
    BbasManager,
    createBbasMiddleware,
    } from 'bbas-devicer';

    // ── Initialise plugins ──────────────────────────────────────
    const deviceManager = new DeviceManager({ /* … */ });

    const ipManager = new IpManager({ licenseKey: process.env.DEVICER_LICENSE_KEY });
    const tlsManager = new TlsManager({ licenseKey: process.env.DEVICER_LICENSE_KEY });
    const bbasManager = new BbasManager({ licenseKey: process.env.DEVICER_LICENSE_KEY });

    // Register ip-devicer and tls-devicer FIRST so their enrichmentInfo
    // is available when bbas-devicer runs (post-processor ordering matters).
    ipManager.registerWith(deviceManager);
    tlsManager.registerWith(deviceManager);
    bbasManager.registerWith(deviceManager); // ← bbas runs last

    await Promise.all([
    ipManager.init(),
    tlsManager.init(),
    bbasManager.init(),
    ]);

    // ── Express middleware ──────────────────────────────────────
    app.use(createBbasMiddleware(bbasManager, { mode: 'observe' }));

    // ── In your route handler ────────────────────────────────────
    app.post('/identify', async (req, res) => {
    const result = await deviceManager.identify(req.body, req.bbasContext);
    // result.bbasEnrichment — full enrichment payload
    // result.bbasDecision — 'allow' | 'challenge' | 'block'
    res.json(result);
    });

    Adapter Import Use case
    In-memory (default) built-in Dev / testing / single-process
    SQLite createSqliteBbasStorage Single-process production
    PostgreSQL createPostgresBbasStorage Multi-process / HA
    Redis createRedisBbasStorage Distributed / low-latency
    import { createSqliteBbasStorage } from 'bbas-devicer';

    const bbasManager = new BbasManager({
    licenseKey: process.env.DEVICER_LICENSE_KEY,
    storage: createSqliteBbasStorage('/data/bbas.db'),
    });

    The bot score is an additive sum capped at 100:

    Factor Points Tier
    headless_browser 45 Free
    known_scraper_ua 40 Free
    missing_browser_headers 30 Free
    velocity_exceeded 25 Free
    suspicious_header_order 15 Free
    known_crawler 5 Free
    tor_exit_node 40 Pro+
    tls_mismatch 25 Pro+
    vpn_proxy 20 Pro+
    hosting_ip 15 Pro+
    ai_agent 15 Pro+
    high_peer_taint 15 Pro+
    rdap_suspect 10 Pro+

    Rules are evaluated in ascending priority order; first match wins.

    Rule name Priority Condition Action
    tor_block 100 isTor === true block
    headless_block 200 headless_browser factor present block
    velocity_block 300 velocity_exceeded factor present block
    scraper_ua_challenge 400 known_scraper_ua factor present challenge
    high_score_block 500 botScore >= 75 block
    mid_score_challenge 600 botScore >= 50 challenge

    Custom rules with priority < 100 run before all defaults.

    import { BbasManager, mergeRules, DEFAULT_RULES } from 'bbas-devicer';

    const bbasManager = new BbasManager({
    rules: mergeRules(
    [
    {
    name: 'block_my_bad_asn',
    priority: 50,
    condition: (e) => e.crossPluginSignals?.rdapAsnOrg?.includes('BadASN') ?? false,
    action: 'block',
    },
    ],
    DEFAULT_RULES,
    ),
    });

    bbas-devicer registers as a DeviceManager post-processor named 'bbas'. It should run after ip-devicer, tls-devicer, and peer-devicer so it can read their cached enrichment data for the cross-plugin scoring factors:

    identify(payload, context)

    ├─ network bundle reference
    │ ├─ 'ip' post-processor (ip-devicer)
    │ │ └─> enrichmentInfo.details.ip.isTor / isVpn / riskScore / …
    │ └─ 'tls' post-processor (tls-devicer)
    │ └─> enrichmentInfo.details.tls.consistencyScore / factors

    ├─ 'peer' post-processor (peer-devicer)
    │ └─> enrichmentInfo.details.peer.taintScore

    └─ 'bbas' post-processor (bbas-devicer) ← register last
    ├─ analyzes UA, headers, velocity
    ├─ reads cross-plugin signals (Pro+)
    ├─ computes bot score + runs rule engine
    └─> result.bbasEnrichment + result.bbasDecision

    {
    bbasDecision: 'allow' | 'challenge' | 'block',

    bbasEnrichment: {
    botScore: number; // 0–100, higher = more likely a bot
    botFactors: string[]; // fired factor keys
    decision: BotDecision;
    uaClassification: {
    isBot: boolean;
    isHeadless: boolean;
    isCrawler: boolean;
    botKind?: 'headless' | 'scraper' | 'http-client' | 'crawler';
    uaString: string;
    };
    headerAnomalies: {
    missingBrowserHeaders: boolean;
    suspiciousHeaderOrder: boolean;
    anomalyFactors: string[];
    };
    velocitySignals: {
    requestCount: number;
    windowMs: number;
    requestsPerMinute: number;
    exceedsThreshold: boolean;
    };
    crossPluginSignals?: { // Pro/Enterprise only
    isTor?: boolean;
    isVpn?: boolean;
    isProxy?: boolean;
    isHosting?: boolean;
    isAiAgent?: boolean;
    aiAgentProvider?: string;
    tlsConsistencyScore?: number;
    peerTaintScore?: number;
    rdapAsnOrg?: string;
    };
    consistencyScore: number; // 0–100
    },
    }

    createBbasMiddleware(manager, {
    mode: 'observe' | 'block', // default: 'observe'
    })

    In 'observe' mode the middleware only attaches req.bbasContext and defers the decision to after identify(). In 'block' mode the same context is attached — the actual block/challenge response is applied at the application layer using result.bbasDecision.


    Tier Price Devices Scoring factors
    Free $0 10,000 UA, headers, velocity
    Pro $49 / mo Unlimited All 13 factors incl. cross-plugin
    Enterprise $299 / mo Unlimited All 13 factors incl. cross-plugin

    You can obtain a license key through polar.sh here.

    Without a key the library runs on the free tier automatically and logs a warning at startup.


    This project uses TypeDoc and publishes documentation at gatewaycorporate.github.io/bbas-devicer.


    Business Source License 1.1 — see license.txt.