Summary

Role
TODO: role
When
TODO: timeframe (ongoing)
Stack
TypeScript · Node.js · typescript-estree (AST) · npm workspaces · tsup · Changesets · GitHub Actions · SARIF
Links

Problem

Developers rarely read privacy regulation, and compliance officers don't review pull requests. Personal-data risks such as logging PII, storing unhashed passwords, or exposing unprotected export routes reach production because nothing checks for them where the code is written.

What I built

  • Parse each file into an AST with @typescript-eslint/typescript-estree and walk it once, calling each rule's visitors per node type.
  • Express each regulatory requirement as a rule that matches names, decorators and local syntax patterns in NestJS, Express, TypeORM and Sequelize code, then cite the legal context in the finding (e.g. GDPR Article 5(1)(c)).
  • Make everything a plugin: the built-in GDPR rules use the same plugin shape as third-party packs, and language adapters separate parsing from rules, so new regulations and languages don't touch the engine.
  • Key the result cache on tool version, plugins, rule ids and severities so a plugin upgrade or config change never serves stale results.
  • Report as console, JSON or SARIF 2.1.0, and use exit codes (0, 1 for errors, 2 for config, plugin or parse failures) so CI pipelines can gate on it.
  • Ship it as complinter on npm from an npm workspaces monorepo with enforced package boundaries, bundled into one package and released through Changesets and npm trusted publishing.

Results

  • Published to npm (v1.1.0) with provenance, released through an OIDC trusted-publishing pipeline.
  • 10 built-in GDPR rules plus 2 NestJS plugin rules.
  • 200 passing automated tests, including golden-output tests and a test that packs and installs the real tarball.
  • 3 output formats: console, JSON and SARIF for GitHub code scanning.

What I learned

  • Heuristic, name-based rules trade precision for reach. A clean scan can't prove compliance, so the tool has to say so, and false-positive rates need measuring, not assuming.
  • Golden-output tests made it safe to refactor from a hardcoded rule set to a plugin architecture without changing any user-visible behaviour.
  • Treating built-in rules as a plugin forced the plugin API to be real, and designing the language adapter early made future languages a plugin concern instead of an engine rewrite.