Skip to content

Refactor: validate build-time override file with a zod schema#234

Merged
twschiller merged 1 commit into
mainfrom
zod-validate-overrides
Jun 9, 2026
Merged

Refactor: validate build-time override file with a zod schema#234
twschiller merged 1 commit into
mainfrom
zod-validate-overrides

Conversation

@twschiller

Copy link
Copy Markdown
Contributor

Summary

  • Replaces the hand-rolled recursive walker in extension/scripts/load-default-overrides.ts with a strict zod schema built dynamically from RULE_DEFAULTS + RULE_OPTION_DEFAULTS. zod was already a devDep (used by extension/data/site-rules.schema.ts); no runtime bundle impact.
  • Behavioral contracts from ADR-0016 / ADR-0017 / spec 0011 FR-4 preserved: unknown top-level keys, unknown sub-rule paths, object values for rules without declared options, and mistyped leaves all fail the build with a path-qualified message. Bare-boolean shorthand at { enabled, ... } sub-rule positions still normalizes to { enabled: <boolean> }.
  • Error format moves from the bucketed unknown keys: …; non-boolean values for: … summary to one issue per line ( - <path>: <message>), with the underlying ZodError attached as cause. The union-aware flattener prefers the branch whose deepest leaf reaches furthest into the tree, so the actionable object-shape error wins over the boolean-branch "expected boolean" noise.

End-to-end with a deliberately-broken file:

error: Defaults file /tmp/bad-overrides.json failed validation:
  - optionsButton: Invalid input: expected boolean, received string
  - encoded-payload-redact.subRules.hex.minLength: Invalid input: expected number, received string
  - encoded-payload-redact.subRules.bogus: unrecognized key
  - bogus-rule: unrecognized key

No ADR / spec / install-doc changes — every reference to the validator describes behavior we preserve. ADR-0016 §"Decision Outcome" still applies verbatim: the validator walks the declared option-shape tree recursively rather than hard-coding subRules, so future rules can declare other option groups without touching the loader.

Test plan

  • bun run jest scripts/__tests__/load-default-overrides.test.ts — 32 / 32 pass (assertions updated to the new format).
  • bun run jest — full extension suite, 1954 / 1954 pass.
  • bun run check (biome + eslint) — clean.
  • bun run typecheck — clean.
  • bun run knip — clean.
  • bun run build --defaults data/defaults-overrides.example.json — committed example file still loads, "Applying 9 build-time default override(s)" message intact.
  • Deliberately broken override file — fails with the path-qualified per-issue format above.

🤖 Generated with Claude Code

Replaces the hand-rolled recursive walker in
extension/scripts/load-default-overrides.ts with a strict zod schema
built dynamically from RULE_DEFAULTS + RULE_OPTION_DEFAULTS. Behavioral
contracts from ADR-0016 / ADR-0017 / spec 0011 FR-4 are preserved:
unknown top-level keys, unknown sub-rule paths, object values for rules
without declared options, and mistyped leaves all fail the build with a
path-qualified message.

Error format moves from the bucketed "unknown keys: …; non-boolean
values for: …" summary to one issue per line ("  - <path>: <message>"),
with the underlying ZodError attached as the thrown Error's cause. Each
issue carries a precise dotted path (e.g.
encoded-payload-redact.subRules.hex.minLength), and the union-aware
flattener prefers the branch whose deepest leaf reaches furthest into
the tree so the object-shape error wins over the boolean-branch
"expected boolean" noise.

zod was already a devDep (used by data/site-rules.schema.ts); no
runtime bundle impact.
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agent-browser-shield-demo-site Ready Ready Preview, Comment Jun 9, 2026 4:33pm

Request Review

@twschiller twschiller merged commit e97cbc5 into main Jun 9, 2026
7 checks passed
@twschiller twschiller deleted the zod-validate-overrides branch June 9, 2026 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant