#3591971: Tighten component tree UUID validation: reject parent cycles, name duplicate-UUID offenders, require lowercase canonical form
Tightens ComponentTreeStructureConstraintValidator with three rules, each introduced as a failing-test commit followed by its fix:
- Parent-reference cycles (A→B→A, or longer) are rejected. Previously they passed validation and every cycle member was silently omitted at render. Descendants hanging off a cycle are not flagged; they render again once the cycle is broken.
- Duplicate-UUID violations are reported per component instance, at each offender's
uuidproperty path, naming the UUID — replacing the single anonymous collection-level message. uuidandparent_uuidmust use the lowercase canonical form. The database columns compare case-insensitively but parent lookups and rendering match exactly, so case-variant spellings collide in storage yet never resolve each other.
No update path: dr canvas:doctor reports pre-existing violations through its existing checks.
Testing instructions
- The first commit alone fails CI: the cycle test cases expect violations the validator does not yet emit.
-
composer run phpunit -- tests/src/Kernel/Plugin/Validation/ComponentTreeStructureConstraintValidatorTest.php -
composer run phpunit -- tests/src/Kernel/Plugin/Field/FieldType/ComponentTreeItemTest.php --filter testInvalidField -
composer run phpunit -- tests/src/Kernel/Config/DefaultFieldValueTest.php -
composer run phpunit -- tests/src/Kernel/Plugin/Canvas/ComponentSource/JsonSchemaPropsComponentInstanceUpdaterTest.php
AI disclosure
Written with AI assistance (Claude Fable 5), per the policy on AI use. All code and text reviewed by a human before posting.
Closes #3591971 (closed)