Skip to content

fix(validator): keep an inactive boolean branch out of schemas - #69

Merged
David Chicaiza (david0723) merged 2 commits into
mainfrom
fix/inactive-boolean-branch-leaks-into-schemas
Sep 2, 2026
Merged

fix(validator): keep an inactive boolean branch out of schemas#69
David Chicaiza (david0723) merged 2 commits into
mainfrom
fix/inactive-boolean-branch-leaks-into-schemas

Conversation

@david0723

@david0723 David Chicaiza (david0723) commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #65.

What breaks

A single-branch boolean (nested: [...], applies when true) with the toggle at false is still walked since 1.18.0 so stale values keep their type rules. That walk also pushed the branch's fields into schemas, flattened, with required: true intact.

Consumers persist schemas as the module's resolved form and validate runtime bundles against it. Those validators never see the toggle, so a required field from the inactive branch gets demanded at run time, e.g. Missing value of required parameter 'fallbackConnectionId' on a module whose fallback toggle is false.

Why it surfaced now

Before #65 an absent toggle failed as mandatory and never reached the walk, so the leak only fired when the caller sent false explicitly. With fillDefaults: 'requiredOnly' the toggle fills to false and the inactive walk runs on every module that predates the toggle, which is most of them. The fill was correct; what it exposed was this.

The fix

suppressRequired has exactly one setter, the inactive single-branch walk, so both schemaFields.push sites now skip when it is set: the nested site (same-domain branches) and the domain-root site (a single-branch nested: { domain, store } pointing at another domain). The two-branch form already stayed out of schemas via registerOnly; a test now pins that.

Validation itself is unchanged: stale values in the inactive branch are still type-checked, strict mode still knows their names, and an active branch still lands in schemas exactly as before.

Tests

Five cases in boolean-nested.spec.ts: explicit false leaves the branch out, true keeps it in, a false that fillDefaults filled leaves it out, a cross-domain inactive branch stays out of the other domain's schemas, and the two-branch form reports only its active side (the last one is a pin, it passed before). The first four go red on main. 508/508 green, tsc and build clean.

Not in this PR

  • states for the inactive branch is untouched. It carries labels for stale values, nothing a runtime validator reads. Happy to align it in a follow-up if you'd rather the inactive branch contribute nothing at all.
  • schemas spreads an rpc:// string sitting inside a collection spec into an indexed-character object ({"0":"r","1":"p",...}). Separate defect in the same output, I'll file it rather than widen this one.

The suppressed walk of a single-branch boolean's inactive branch pushed the
branch's fields into `schemas`, flattened and still `required: true`. Consumers
persist that list as the module's resolved form and validate runtime bundles
against it without ever seeing the toggle, so the leaked field was demanded at
run time. With `fillDefaults` filling the toggle to `false` this hit every
module that predates the toggle.
@david0723
David Chicaiza (david0723) requested a review from a team as a code owner September 2, 2026 09:54
Copilot AI lite review requested due to automatic review settings September 2, 2026 09:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The behavioral change for two-branch boolean nested (registerOnly) affecting schemas isn’t covered by a regression test, and one newly added test name is unclear/grammatically incorrect.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Fixes validateForman(..., { schemas: true }) so fields from an inactive boolean nested branch are no longer emitted into the flattened schemas output, preventing downstream validators (that don’t see the toggle value) from incorrectly requiring fields from an inactive branch.

Changes:

  • Skip pushing fields into roots[domain].schemaFields when walking under suppressRequired (inactive single-branch boolean) and registerOnly (inactive two-branch boolean) contexts.
  • Add regression tests for single-branch boolean nested to ensure inactive branches don’t leak into schemas, including when fillDefaults fills the toggle to false.
File summaries
File Description
src/validator.ts Prevents inactive boolean nested branches from contributing fields to schemas by gating schema-field collection on registerOnly / suppressRequired.
test/boolean-nested.spec.ts Adds regression coverage for schemas output under single-branch boolean nested, including a fillDefaults scenario.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/validator.ts
Comment thread test/boolean-nested.spec.ts Outdated
…hable guard

The two-branch object form carries no per-branch domain, so the domain-root
push site is only reached under `suppressRequired`; the `registerOnly` check
there was dead. Pins: two-branch reports only the active branch, and a
cross-domain single-branch inactive side stays out of that domain's schemas.
@david0723
David Chicaiza (david0723) merged commit 5f7922f into main Sep 2, 2026
4 checks passed
@david0723
David Chicaiza (david0723) deleted the fix/inactive-boolean-branch-leaks-into-schemas branch September 2, 2026 10:12
David Chicaiza (david0723) added a commit that referenced this pull request Sep 2, 2026
Version bump to **2.0.1**.

Includes:
- #69: the inactive branch of a boolean toggle no longer leaks into
`schemas` / `resolvedSchemas`. Those fields came out flat with
`required: true`, and a consumer persisting that list as the module's
resolved form then had the field demanded at run time by validators that
never see the toggle. With `fillDefaults` filling the toggle to `false`,
this was hitting every module that predates the toggle. Validation
outcomes are unchanged.
- #66: an RPC-backed option list that cannot see a reference value warns
instead of failing.

Patch, not minor: no new surface, two fixes. README carries the note.

Once merged, creating the `v2.0.1` GitHub release triggers the npm + JSR
publish workflows.
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.

3 participants