Protected main@3f61c8242b9c02dec307a7396e83e28f7cdd9f3d still has a buyer-visible Customer Master loss mode in frontend/src/App.tsx.
Current buildCustomerEntityTree() first assigns every entity whose visible parent exists into childrenByParent, then derives roots only from entities with no visible parent. It recursively maps children with no visited/cycle guard. Therefore:
- a pure two-or-more-entity visible parent cycle yields
roots=[] and silently renders zero customer entities;
- a self-parent entity is also non-root and disappears;
- a cycle reachable after any future root-producing normalization would recurse without a path/visited guard;
- missing/invisible parents are already promoted to roots, which must remain preserved rather than converted into authorization evidence.
This is presentation/read-model integrity, not permission authority. Do not infer or repair corporate hierarchy facts in persistence merely to make the tree drawable.
TDD acceptance
- RED on current protected main: pure cycle
A.parent=B, B.parent=A must prove both authorized visible entities are currently omitted; self-parent must likewise fail.
- Implement a deterministic cycle-safe forest that emits every input entity exactly once. Break only the presentation parent edge needed to establish a root; never mutate the entity DTO or persist a repaired hierarchy.
- Preserve ordinary hierarchy order deterministically and preserve the existing missing/invisible-parent-as-root behavior.
- Surface unresolved presentation ancestry explicitly in the Customer Master UI (cycle/self-parent/missing-or-invisible-parent as applicable) instead of silently pretending the hierarchy is authoritative.
- Add malformed-state Storybook/browser evidence covering pure cycle, self-parent, missing parent, and an ordinary tree at desktop/mobile/intermediate widths.
- Tree interaction must retain WAI-ARIA semantics, keyboard navigation/visible focus, no entity duplication/loss, and no document-level overflow.
- Re-fetch current main/open PRs first and fold into an existing Customer Master owner PR if one already implements the same repair; do not create a duplicate implementation.
No cross-tenant edge may be synthesized. An invisible parent remains absent evidence, not a grant to expose it.
Protected
main@3f61c8242b9c02dec307a7396e83e28f7cdd9f3dstill has a buyer-visible Customer Master loss mode infrontend/src/App.tsx.Current
buildCustomerEntityTree()first assigns every entity whose visible parent exists intochildrenByParent, then derives roots only from entities with no visible parent. It recursively maps children with no visited/cycle guard. Therefore:roots=[]and silently renders zero customer entities;This is presentation/read-model integrity, not permission authority. Do not infer or repair corporate hierarchy facts in persistence merely to make the tree drawable.
TDD acceptance
A.parent=B,B.parent=Amust prove both authorized visible entities are currently omitted; self-parent must likewise fail.No cross-tenant edge may be synthesized. An invisible parent remains absent evidence, not a grant to expose it.