Bid Request Auditor
OpenRTB 2.6 validator
A validator for OpenRTB 2.6 bid requests. Paste a request, drop a
.json file on the page, or load one of five samples, and
it reports spec violations, invalid AdCOM 1.0 enum values, internal
contradictions, and privacy signals contradicted by the identifiers the
request actually carries — a COPPA or DNT flag asserted while
device IDs, user IDs and ten-metre geo are still being sent. It runs
21 checks across four categories, each citing the spec
section it came from and graded by severity. The same rules run three
ways: a CLI that exits non-zero on errors so it drops into CI, a
browser page, and a Claude Code skill.
Stack
TypeScript, run directly on Node using native type stripping: no
compiler, no bundler, no package.json, zero runtime
dependencies. The page is plain HTML, CSS and vanilla JavaScript; its
one script is generated from src/ by a small Node script
using node:module's stripTypeScriptTypes, so
the browser runs the real rules rather than a copy of them. Tests are
node --test.
What I decided, and why
- Deterministic rules, no LLM at runtime. Results are reproducible, need no network and cost nothing per run. I used AI heavily to build it and not at all to run it — “the spec says X” has to trace to a line of code and a section number, not to a model's judgment.
- ERROR only where a spec table literally says “required.” “Recommended” caps at WARNING. Unknown fields and unrecognised enum values cap at INFO, because §2.6 requires implementers to tolerate them. The three privacy contradictions are the one deliberate exception, promoted to ERROR.
- One engine, two front doors. The CLI and the page import the same modules, so no rule is duplicated, and a test fails if the generated browser bundle drifts from the source.
- No backend. The audit runs entirely in the browser, so a bid request pasted into the page never leaves the analyst's machine.
- Cut a check the spec supports. §3.2.19 says city should use UN/LOCODE, but effectively nobody sends it that way. Flagging “Tel Aviv” would have been inventing a problem, so it's out.