Skip to content

Transform, Align, Object Properties and Live Shape Properties: a boolean given as text is refused - #3289

Open
dotCooCoo wants to merge 1 commit into
storytold:mainfrom
dotCooCoo:fix/object-commands-refuse-booleans-as-text
Open

dotCooCoo wants to merge 1 commit into
storytold:mainfrom
dotCooCoo:fix/object-commands-refuse-booleans-as-text

Conversation

@dotCooCoo

@dotCooCoo dotCooCoo commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What and why

On main, the transform commands read their on/off options with bool_or, which falls back to a default for a value that is not true or false. With Scale Strokes & Effects on, object.scale {"sx": 200, "strokes": "false"} scales the stroke as well, and object.move {"dx": 5, "copy": "true"} moves the object without a copy. object.transformAgain drops such a value and uses the one the repeated transform had. object.setProps reads {"visible": "false"} as a key left out, and object.setLiveShape reads {"invertPie": "true"} as false. Each call reports success.

  • object.transform, move, nudge, rotate, scale, reflect, shear, transformAgain and setBounds fail with "<key> must be true or false" for a copy, strokes, corners, patterns, objects or typeAreas that is not true, false or null, the message the grid and overprint commands give (crates/engine/src/cmd/create.rs:423, overprint.rs:124). So do anchors in object.transform, big in object.nudge, absolute in object.rotate and proportional in object.setBounds.
  • object.align, object.distribute and object.distributeSpacing refuse such a patterns. object.setProps refuses such a visible, locked, isolate or knockoutShape, and object.setLiveShape refuses such an invertPie or makeSidesEqual.
  • The document and the undo history stay as they were. A null is read as a key left out. Each command checks its keys with a new check_switches, which works as check_numbers does (crates/engine/src/cmd/mod.rs:323), before it changes anything; apply_transform, scaling, transform_patterns and transforms_objects keep their signatures.
  • docs/mcp.md lists the keys, and docs/target-app-parity.md has one line for the change. The true-or-false message already has a row in every complete catalog. The change adds no new message text and no catalog rows.

How it was tested

New tests in vectorcraft-engine, each failing on main, where the first call succeeds:

  • tests::a_boolean_given_as_text_for_a_transform_is_an_error makes 13 calls across the nine transform commands, each giving one option as a string, a number or an array, with Scale Strokes & Effects on; the object keeps its bounds and stroke width, no copy is made and no undo step is added, and strokes: false with corners: null then scales the object and leaves its stroke width.
  • tests::align_and_distribute_refuse_a_boolean_given_as_text gives patterns as "true", "false" and 1; nothing moves and no undo step is added, and the three commands then run with null, false and true, the first aligning the objects.
  • tests::object_properties_refuse_a_boolean_given_as_text gives each of the four keys as a string, a number or an array; the object and the undo history stay, and true, false and null then set or keep each value.
  • tests_livecorners::invert_pie_and_make_sides_equal_refuse_a_boolean_given_as_text gives both keys as a string, a number or an array; the pie and the polygon stay, false and null leave them, and true inverts the pie and makes the sides equal.

Targeted checks while building: cargo clippy -p vectorcraft-engine --all-targets -- -D warnings; the new tests and cargo test -p vectorcraft-engine --lib; cargo fmt --all -- --check; cargo test -p vectorcraft-ui-egui --lib i18n; cargo xtask brands, layers and assets.

On Windows 11 (x86-64) with rustc 1.99.1, on top of main at bc1ae08:

  • CRAFT_FONTS_DIR=<craft-fonts checkout> cargo xtask ci passes its 10 steps: 8,574 tests passed, 0 failed, 13 ignored.

git merge-tree reports no conflicts with main at bc1ae08. #3262, #3206, #3204, #3181, #3091, #3014, #2841, #2671 and #2595 also change crates/engine/src/cmd/object.rs or tests.rs and merge with this branch. The branch merged with all of them but #3204 builds (cargo check -p vectorcraft-engine --tests), and so does the branch merged with #3204, which conflicts with #3206. The conflicts of #2734, #1987, #1906 and #1281 with main in object.rs are the same with or without this branch.

Checklist

  • cargo xtask ci passes (fmt, clippy, tests, assets, brands, layers, wasm).
  • No panics in shipped code: no unwrap(), expect(), panic!, unreachable!, todo! or
    unimplemented! outside tests, and no unchecked indexing on data from files, parameters or
    messages. Errors are returned as Result and shown to the user
    (why and how).
  • Clean-room: nothing copied from Adobe products or GPL/AGPL code (AGENTS.md).
  • Every new asset has a row in ASSETS.md.

Summary by CodeRabbit

  • Bug Fixes

    • Commands now reject invalid non-boolean values for transform, alignment, object property, and live shape options.
    • Rejected values leave the document, object state, and undo history unchanged.
    • Boolean values continue to work as expected, while null is treated as omitted.
  • Documentation

    • Updated command documentation to describe boolean validation and rejection behavior.

…ean given as text is refused

The transform commands read their on/off options with bool_or, which
falls back to a default for a value that is not true or false. With
Scale Strokes & Effects on, object.scale {"strokes": "false"} scaled
the stroke as well, and object.move {"copy": "true"} moved the object
without a copy. Transform Again dropped such a value and used the one
the repeated transform had. Object Properties read visible, locked,
isolate and knockoutShape given as text as not given, and Live Shape
Properties read invertPie and makeSidesEqual given as text as false.
Each call reported success.

object.transform, move, nudge, rotate, scale, reflect, shear,
transformAgain and setBounds now fail with "`<key>` must be true or
false" for a copy, strokes, corners, patterns, objects or typeAreas
that is not true, false or null, with the message the grid and
overprint commands give. So do anchors in object.transform, big in
object.nudge, absolute in object.rotate, proportional in
object.setBounds, patterns in object.align, distribute and
distributeSpacing, visible, locked, isolate and knockoutShape in
object.setProps, and invertPie and makeSidesEqual in
object.setLiveShape. The document and its undo history stay as they
were. A null is read as a key left out.

Docs: docs/mcp.md, docs/target-app-parity.md.
@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: storytold/vectorcraft/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7035e779-e134-4450-93e0-c39bfec53988
📥 Commits

Reviewing files that changed from the base of the PR and between bc1ae08 and 78a2d34.

📒 Files selected for processing: 5
  • crates/engine/src/cmd/object.rs
  • crates/engine/src/tests.rs
  • crates/engine/src/tests_livecorners.rs
  • docs/mcp.md
  • docs/target-app-parity.md

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.

📝 Walkthrough

Object commands now reject supplied non-boolean values for boolean options while accepting missing and null values. Regression tests check errors and unchanged state on rejection. Documentation describes these validation rules.

Changes: Object Command Boolean Validation

Layer / File(s) Summary
Transform option validation
crates/engine/src/cmd/object.rs, crates/engine/src/tests.rs
A shared validator accepts missing, null, or boolean values. Transform commands validate their options before processing. Tests cover rejection and unchanged object state.
Other object option validation
crates/engine/src/cmd/object.rs, crates/engine/src/tests.rs, crates/engine/src/tests_livecorners.rs, docs/mcp.md, docs/target-app-parity.md
Property, alignment, distribution, and live-shape commands validate supplied boolean options. Tests cover invalid and accepted values. Documentation describes the validation rules.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: bflatastic

Merge Risk: ⚪ Minimal · up to 78a2d

The affected object commands reject invalid boolean options without an identified document or undo-history regression. No actionable merge-blocking risk remains after normal checks.

Security architecture risk: ⚪ Minimal · up to 78a2d

The change rejects malformed boolean options before editing documents. Existing valid inputs, command authority, and undo behavior remain intact. No material security risk was found introduced or worsened by this change.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The changed control governs existing object-editing outcomes in the session document, including transforms, duplication, visibility, locking, and live-shape changes. Source comparison found no expansion of target resolution or mutation authority.

Trust Boundaries and Controls

  • observed — Caller-controlled strings, numbers, arrays, and objects supplied for checked boolean switches are rejected with the existing parameter error before reaching editing sinks. The helper accepts only omission, null, or an actual JSON boolean.

Resilience and Maintainability Implications

  • observed — Existing interaction recovery prevents failed previews from becoming committed edits: previews reset to their snapshot, failed previews clear pending work, successful commits update history and repeat state, and cancellation restores the snapshot. These lifecycle mechanisms are unchanged by the PR.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 55.17% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 3 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description check Passed The description includes the required What and why, How it was tested, and Checklist sections. It clearly explains the behavior change, affected commands, validation, documentation updates, test cover…
Title check Passed The title clearly identifies the main change: affected object command groups now refuse boolean values supplied as text. It is concise, specific, and related to the changeset.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description includes the required What and why, How it was tested, and Checklist sections. It clearly explains the behavior change, affected commands, validation, documentation updates, test coverage, and completed checks.

Full details: Docstring Coverage

Explanation

Docstring coverage is 55.17% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 3 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 LanguageTool
docs/target-app-parity.md

LanguageTool checks are incomplete because the per-file request limit of 5 was reached. Remaining text was skipped; findings from completed checks are retained.

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
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