npm package: @sentineld/browser
Description: Browser SDK for Sentinel fraud detection and device fingerprinting
Author: DigitalSurge SARL
Latest version: 1.3.2

# @sentinel-sdk/browser

Browser SDK for Sentinel fraud detection and device fingerprinting. Identify visitors, detect bots, and assess fraud risk in real-time.

## Installation

```bash
npm install @sentinel-sdk/browser
```

Or via CDN:

```html
<script src="https://unpkg.com/@sentinel-sdk/browser@latest/dist/sentinel.min.js"></script>
```

## Quick Start

### ES Modules

```typescript
import Sentinel from '@sentinel-sdk/browser';

// Initialize with your API key
Sentinel.init({
  endpoint: 'https://sentinel.yourdomain.com/api',
  apiKey: 'pk_live_xxxxxxxxxxxxx',
});

// Identify the current visitor
const result = await Sentinel.identify();

console.log(result.visitor_id);    // Unique visitor ID
console.log(result.is_new);       // First time seeing this visitor

// Send visitor_id to your backend -- fetch risk scores
// server-side using the sk_live_* secret key API
```

### Script Tag

```html
<script src="https://unpkg.com/@sentinel-sdk/browser@latest/dist/sentinel.min.js"></script>
<script>
  Sentinel.init({
    endpoint: 'https://sentinel.yourdomain.com/api',
    apiKey: 'pk_live_xxxxxxxxxxxxx',
  });

  Sentinel.identify().then(function(result) {
    console.log('Visitor ID:', result.visitor_id);
  });
</script>
```

## Configuration

```typescript
Sentinel.init({
  endpoint: string,   // Your Sentinel API endpoint
  apiKey: string,      // Your public API key (pk_live_xxx)
});
```

| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `endpoint` | `string` | Yes | Your Sentinel API base URL |
| `apiKey` | `string` | Yes | Public API key (`pk_live_` prefix). Used for request signing, encryption, and Proof-of-Work authentication. |

## API Reference

### `Sentinel.init(config)`

Initialize the SDK. Must be called before other methods.

Calling `init()` eagerly starts background work so that `identify()` is fast:
- Fingerprint collection (canvas, WebGL, audio, fonts)
- WebRTC network signal gathering
- WASM crypto module loading (signing, encryption, PoW solver)
- Anti-debug monitoring

### `Sentinel.identify(params?)`

Identify the current visitor and get risk assessment.

A single call handles the full pipeline: collecting signals, fetching and solving a Proof-of-Work challenge, encrypting and signing the payload, and sending it to the server. No separate setup steps are needed.

```typescript
const result = await Sentinel.identify({
  sessionId: 'optional-session-id',  // Auto-generated if not provided
  accountId: 'user-123',             // Optional: link to your user ID
});

// Returns:
{
  visitor_id: string,     // Stable visitor identifier
  confidence: number,     // Fingerprint confidence (0-1)
  method: string,         // Resolution method ("fingerprint")
  is_new: boolean,        // First time seeing this visitor
  visit_count: number,    // Total visits from this device
}

// Risk and automation scores are NOT returned to the browser.
// Fetch them server-side using your sk_live_* key:
// GET /api/v1/visitors/{visitor_id}/events
```

### `Sentinel.track(params)`

Track a custom event (e.g., login, purchase, signup).

```typescript
const result = await Sentinel.track({
  type: 'login',                // Event type
  accountId: 'user-123',        // Optional: your user ID
  metadata: {                   // Optional: custom data
    method: 'password',
    success: true,
  },
});
```

### `Sentinel.getVisitorId()`

Get the current visitor's fingerprint hash without making an API call.

```typescript
const visitorId = await Sentinel.getVisitorId();
```

### `Sentinel.detectIncognito()`

Detect if the browser is in incognito/private mode.

```typescript
const isIncognito = await Sentinel.detectIncognito();
```

## What Happens Under the Hood

When you call `identify()` or `track()`, the SDK performs these steps in parallel for minimal latency:

1. **Collect signals** — fingerprint (canvas, WebGL, audio, fonts), network (WebRTC), behavior (mouse/keyboard patterns), integrity (headless/stealth/VM/extension detection), and validation signals (UA, screen, timezone, languages).

2. **Fetch & solve Proof-of-Work** — requests a challenge from `GET /v1/challenge` and solves it using a native WASM SHA-256 loop. The solution is attached as `X-Pow-Id` and `X-Pow-Nonce` headers. This runs concurrently with signal collection so it adds zero extra latency.

3. **Encrypt & sign** — the payload is AES-GCM encrypted and HMAC-SHA256 signed using the `pk_live_` API key. Both operations use the WASM crypto module when available.

4. **POST** — sends the encrypted, signed payload with PoW headers. The server decrypts, verifies the signature, validates the PoW solution, cross-references HTTP headers against SDK-reported values, and returns the risk assessment.

```
init()                      identify()
  │                            │
  ├─ Load WASM crypto          ├─ Collect signals ──────┐
  ├─ Start fingerprinting      ├─ Fetch PoW challenge ──┤ (parallel)
  ├─ Start network probes      │                        │
  ├─ Start anti-debug          │  Solve PoW (WASM) ─────┘
  │                            │
  │                            ├─ Sign + Encrypt payload
  │                            ├─ POST /v1/identify
  │                            └─ Return risk result
```

## Security Features

### Proof-of-Work

Every `identify()` and `track()` call requires solving a SHA-256 Proof-of-Work challenge before the server accepts it. This raises the cost of automation — a bot farm must burn real CPU per request.

- Default difficulty: 16 leading zero bits (~65K SHA-256 hashes, ~30-50ms)
- Adaptive difficulty: repeated failures from the same IP increase difficulty (up to +8 bits, making it 256x harder)
- The solver runs inside a compiled WASM binary with integrity verification — there is no JavaScript fallback to reverse-engineer

### Payload Encryption & Signing

All request bodies are AES-GCM encrypted and HMAC-SHA256 signed. The server decrypts and verifies signatures before processing. Replay attacks are prevented by unique nonces and timestamps.

### HTTP Header Validation

The server cross-references actual HTTP headers against SDK-reported values:

| Check | What it catches |
|-------|----------------|
| User-Agent mismatch | `curl` with spoofed payload |
| Accept-Language mismatch | Forged language signals |
| Sec-CH-UA mismatch | Wrong browser family claims |
| Missing Sec-Fetch-Site | Non-browser HTTP clients |
| Missing Sec-CH-UA | Automation tools omitting client hints |
| Connection: keep-alive | HTTP/1.1 libraries pretending to be browsers |

### Anti-Debug & Anti-Tampering

The SDK detects and deters reverse engineering:

- **Passive detection** — timing API integrity checks, Image.id getter traps for DevTools, native function code-length monitoring, requestAnimationFrame cadence analysis, stack depth anomaly detection
- **Active deterrence** — `debugger` statement bombing only activates after high-confidence detection (score-based system with threshold)
- **Anti-tampering** — self-defending function wrappers, environment verification, code integrity checks, prototype modification detection
- **Stealth detection** — catches puppeteer-stealth, playwright-stealth, and similar plugins through Function.toString anomalies, iframe isolation checks, Chrome runtime inconsistencies, and Proxy wrapper detection

### Bot & Automation Detection

Signals collected and scored server-side:

- WebDriver / navigator.webdriver flag
- Headless browser indicators (missing plugins, languages, WebGL, Chrome runtime)
- CDP markers (Puppeteer, Playwright, Selenium, ChromeDriver)
- VM detection (VMware, VirtualBox, Parallels, QEMU)
- Canvas and WebGL manipulation detection
- Privacy/automation extension detection
- VPN, proxy, and datacenter IP detection (MaxMind GeoIP + datacenter CIDR lists)

## Risk Scores

| Score Range | Risk Level | Description |
|-------------|------------|-------------|
| 0-20 | Low | Likely legitimate user |
| 21-50 | Medium | Some suspicious signals |
| 51-80 | High | Likely fraudulent |
| 81-100 | Critical | Strong fraud indicators |

## Common Risk Reason Codes

| Code | Description |
|------|-------------|
| `BOT_WEBDRIVER` | WebDriver/automation detected |
| `BOT_HEADLESS` | Headless browser detected |
| `BOT_CDP` | Chrome DevTools Protocol automation |
| `BOT_STEALTH` | Stealth plugin detected |
| `VPN_DETECTED` | VPN/proxy detected |
| `DATACENTER_IP` | IP from datacenter range |
| `TZ_MISMATCH` | Timezone doesn't match IP location |
| `INCOGNITO` | Private browsing mode |
| `HTTP_UA_MISMATCH` | HTTP User-Agent doesn't match SDK-reported UA |
| `MISSING_CLIENT_HINTS` | Browser should send Sec-CH-UA but it's missing |
| `MISSING_SEC_FETCH` | Browser should send Sec-Fetch-Site but it's missing |
| `SIGNAL_INCONSISTENCY` | Multiple signal cross-validation failures |

## Server Configuration

The Sentinel API server is configured via environment variables:

| Variable | Default | Description |
|----------|---------|-------------|
| `SENTINEL_PORT` | `8080` | API server port |
| `SENTINEL_POSTGRES_DSN` | — | PostgreSQL connection string (required) |
| `SENTINEL_REDIS_ADDR` | `localhost:6379` | Redis address |
| `SENTINEL_HMAC_SECRET` | — | Server-side HMAC secret (required) |
| `SENTINEL_ALLOWED_ORIGINS` | `localhost` | CORS allowed origins |
| `SENTINEL_POW_ENABLED` | `true` | Enable Proof-of-Work challenges |
| `SENTINEL_POW_DIFFICULTY` | `16` | PoW difficulty (leading zero bits) |
| `SENTINEL_REQUIRE_API_KEY` | `false` | Require API keys on SDK routes |
| `SENTINEL_MAXMIND_CITY_PATH` | — | Path to GeoLite2-City.mmdb |
| `SENTINEL_MAXMIND_ASN_PATH` | — | Path to GeoLite2-ASN.mmdb |
| `SENTINEL_ENABLE_PROXY_DETECTION` | `true` | Enable VPN/proxy risk scoring |

## TypeScript

Full TypeScript support is included. Import types:

```typescript
import Sentinel, {
  SentinelConfig,
  IdentifyResponse,
  EventResponse,
} from '@sentinel-sdk/browser';
```

## Browser Support

Requires WebAssembly support (all modern browsers):

- Chrome 57+
- Firefox 52+
- Safari 11+
- Edge 16+

## License

MIT