npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

markerlayer

v0.2.3

Published

Deterministic reference implementation of the EN 18144:2025 behavioural markers of harm for online gambling

Readme

MarkerLayer

npm license standard

The player-protection layer for your gambling platform — a deterministic reference implementation of the EN 18144:2025 behavioural markers of harm, verified against the full standard text (SR EN 18144:2025, CEN/TC 456). Self-host the open-source engine, or send your events to the managed cloud.

A Duomind product · markerlayer.com

MarkerLayer Cloud console on the synthetic demo dataset The demo console (demo/dashboard.html) on a deterministic synthetic operator — 78 players, 74k events, scored by this engine. Run npx tsx demo/generate.ts to reproduce it.

Operators send seven kinds of behavioural events they already have (wagers, deposits, withdrawals, sessions, support contacts, safety-tool changes, bonuses); the engine returns the nine standardized markers per player, each with named features, an attention state, and plain-language evidence for every flag.

events in ──► daily aggregates ──► robust self-baselines ──► 9 markers out
             (median/MAD z-scores, 90-day baseline, 7-day scrutiny window)

Why this design

  • Deterministic & explainable. Same events in → same markers out. Every non-normal state carries evidence naming the exact feature, value, and rule ("declinedDepositCountWeek=4 ≥ 3"). No ML in the scoring path — this is what makes the output auditable by a regulator.
  • Self-referential baselines. Markers compare a player's recent behaviour against their own 90-day history (robust median/MAD z-scores), because the research shows change and trajectory predict harm better than absolute thresholds. New players fall back to configurable population references.
  • Composite = review pressure, not diagnosis. Per §4.2 the markers are considered together in a point-based composite with explicit interaction terms (losses × depositing, escalation × weakened protections, …). The breakdown always sums to the score, coverage gaps are listed, and bands are operator policy — an identification aid, never a clinical measure.
  • No PII. Pseudonymous player IDs, amounts in minor units, categorical fields only. Nothing in the schema can identify a person.

Quick start

npm install
npm test
import { computePlayerMarkers } from 'markerlayer';

const result = computePlayerMarkers(events, 'player-123', {
  asOf: '2026-07-10T00:00:00Z',
});

console.log(result.attention);
// e.g. ['M3_depositing_behaviour', 'M1_volume_of_stakes']
console.log(result.markers.M3_depositing_behaviour.evidence);
// ['declinedDepositCountWeek=3 ≥ 3']
console.log(result.composite);
// { score: 6, band: 'high', points: [...], coverageGaps: [...] }

Run the demo (a synthetic escalating player):

npx tsx examples/demo.ts

Run the ingestion API (auth required; storage is append-only JSONL):

MARKERLAYER_API_KEYS=your-key-min-16-chars npm run serve

curl -X POST localhost:3200/v1/events \
  -H "Authorization: Bearer your-key-min-16-chars" \
  -H "content-type: application/json" -d @events.json

curl "localhost:3200/v1/players/op-4711/markers" \
  -H "Authorization: Bearer your-key-min-16-chars"

Or with Docker (persists events in the markers-data volume):

docker build -t markerlayer .
docker run -p 3200:3200 -v markers-data:/data \
  -e MARKERLAYER_API_KEYS=your-key-min-16-chars markerlayer

The API is described in openapi.yaml (OpenAPI 3.1, validated) — import it into Postman/Insomnia or hand it to an integrating operator as the contract.

The nine markers (EN 18144:2025 §5.1–§5.9)

| ID | Standard clause | Key absolute rules (defaults) | |---|---|---| | M1 Volume of Stakes | §5.1 | stake trajectory ≥ 50%/week, 2 weeks | | M2 Speed of Play | §5.2 | ≥3 in-session top-ups twice in 7d; 2× speed-up | | M3 Depositing Behaviour | §5.3 | ≥3 declined or chase deposits in 7d | | M4 Cancelled Withdrawals | §5.4 | cancel ratio ≥ 0.25 / cancel→wager <1h twice | | M5 Player Initiated Contact | §5.5 | any responsible-gambling contact | | M6 Gambling Time | §5.6 | session ≥ 6h; sustained night play | | M7 Gambling Products | §5.7 | ≥4 verticals or ≥2 new adoptions | | M8 Responsible Gambling Tools | §5.8 | play ≤24h after exclusion ends; near-limit weakening | | M9 Losses | §5.9 | 30d losses ≥2× prior norm and rising |

Each marker computes the standard's required measurements over its required time spans (day/week/month, plus 90/180 days for stakes, deposits, and losses); sessions follow the §3.6 definition (a 5-minute gap without a bet ends the session) and gambling time follows both §5.6.2 methods (day-split session minutes + hour slots with activity).

Everything else is robust z-scores against the player's own baseline, sustained over ≥2 of the last 7 days. All thresholds are operator policy configuration (EngineConfig), shipped with documented conservative defaults — they are not clinical claims.

Full specification: SPEC.md.

Status & caveats

  • Marker names, measurements, time spans, and the session definition are verified against the full text of SR EN 18144:2025 (see SPEC.md §1 for the requirement-by-requirement mapping and §3 for documented deviations).
  • Flag thresholds remain operator policy: the standard deliberately prescribes no trigger points or interventions (§1) and notes any prescribed limit yields false positives (§4.1).
  • Single-currency per player is assumed (amounts are summed in minor units).
  • Losses use §5.9.2 Method 2 (stakes − winnings − bonuses, settled bets only).
  • This library identifies patterns; deciding interventions is the operator's regulated responsibility. Nothing here diagnoses or screens for gambling disorder — the standard itself states it "cannot serve as a clinical assessment of gambling disorder" (§4.1).

License

MIT