The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Bouncer listing page.
Static compliance-controls checker — the controls a regulation requires, verified in your code.
nugehs.github.io/bouncer-web (site)

bouncer verifies that the controls a regulation requires actually exist in your code — UK Online Safety Act, ICO Children's Code (AADC), and Nigeria (NDPC, FCCPC, FIRS) — expressed as deterministic rule packs. It runs in CI, exits non-zero when a required control is missing, and needs no LLM.
It checks IDs at the door so non-compliant code doesn't get in.
bouncer is an engineering aid, not legal advice. A green report means the coded controls a rule looks for were found — it is not a substitute for a compliance / DPO review.
Regulators now expect demonstrable controls: age assurance, high-privacy defaults for children, report/block affordances on user-generated content, a DPIA, a risk assessment. Those are concrete things that either exist in a codebase or don't. bouncer turns a regulation into a set of static checks over your repo, the same way tieline turns an API contract into drift checks — the engine knows nothing about the law; the rule packs do.
Scanners like semgrep, CodeQL, or Snyk answer "is there bad code here?" — they
hunt for vulnerabilities and dangerous patterns that shouldn't exist. bouncer
answers the opposite question: "does the code the regulation requires actually
exist?" — age assurance on sign-up, report/block on UGC surfaces, high-privacy
defaults for children. A repo can be vulnerability-free and still fail every one
of those obligations. Policy-as-code tools (OPA/Rego, Conftest) gate configs and
infrastructure against policy; bouncer gates application source against
regulatory rule packs, with file:line evidence for every control and an honest
unknown when a surface can't be located. In short: semgrep finds
vulnerabilities; bouncer proves required controls exist. They complement each
other — run both.
Or clone and run with plain Node (zero runtime dependencies, Node ≥ 18).
| Verdict | Meaning |
|---|---|
| pass | the required control was found (evidence: file:line) |
| fail | the surface exists, but no evidence of the control was found |
| unknown | the surface could not be located in this repo — can't determine, not a pass |
unknown is deliberate: bouncer never reports a green pass for a surface it could
not find. Missing surface → honest "can't determine".
bouncer.config.json:
adapter — how regulation surfaces (sign-up, profile, chat, livestream…) map
onto files for your stack.Adapters shipped today:
next(App Router) andreact-native. That's it — if your stack isn't covered, an adapter is a single small file mapping surface aliases to file globs (seesrc/lib/adapters/next.js). Adapter PRs are very welcome —nuxt,sveltekit,remix,flutter,djangoare all natural candidates.
packs — which rule packs to run. Built-ins: uk-osa, uk-aadc, ng-ndpc, ng-fccpc, ng-firs.packDirs — extra directories of your own *.json packs.ignore — rule ids to skip.failOn — which buckets make check exit non-zero (default ["fail"]).A pack is JSON. Each rule maps a legal standard to a static assertion over a surface:
Assertion nodes:
{ "find": "<regex>", "in": "<surface|glob>", "expect": "present|absent" }{ "allOf": [ … ] } · { "anyOf": [ … ] } · { "not": … }in accepts a surface alias (resolved by the adapter), an array of aliases/globs,
or a raw glob. expect: "absent" flips the meaning — a match is a violation
(used for nudge patterns, self-declared age checkboxes, etc.).
any, signup, auth, profile, chat, livestream, ugc, governance.
For a platform operating in Nigeria, three packs ship built-in:
ng-ndpc — Nigeria Data Protection Act 2023 (NDPC): privacy notice, opt-in
& granular consent, data-subject rights, encryption, retention/erasure, NDPA
localization, DPO designation, 72-hour breach plan, cross-border safeguards.ng-fccpc — consumer protection (FCCPC): blanket "no refund / all sales
final" clauses flagged as void — and high-precision, so a tiered or
conditional refund policy doesn't trip it — plus refund-policy present, no drip
pricing, explicit terms acceptance, terms of service present.ng-firs — tax (FIRS): 7.5% VAT rate, VAT on commission, WHT on payouts,
VAT tax invoice.Some obligations are process, not code — NDPC registration, signed cross-border
DPAs, the WHT remittance itself. Those rules surface as gaps to track (add
them to ignore with a note), not things a static scan can prove.
bouncer is also an MCP server (stdio), so an agent can pull the same deterministic results:
| Tool | Purpose |
|---|---|
compliance_check | run packs, return per-control verdicts + evidence |
list_rules | list rules the configured packs apply |
explain_rule | a rule's standard, intent, fix, and how it is checked |
list_packs | available rule packs |
Fails the build when a required control goes missing — e.g. someone removes an age-gate or a report button from a UGC surface.
The suite runs on Node's built-in test runner against throwaway fixture repos:
glob/brace expansion, every assertion probe (find, allOf/anyOf/not,
allInFile + within windows, expect: "absent"), the pass/fail/unknown
verdict semantics, and pack loading. CI runs it on Node 18, 20, and 22.
MIT
bouncer is one of four tools that form a deterministic trust layer for AI-assisted development. Each answers a question people keep handing to an LLM — with static analysis instead.
More at segunolumbe.com. static analysis, never the model.