41d1b478b0
## Summary - Stop the related-person path walker from traversing system objects while deriving timeline people. - Keep direct `person` terminal paths valid so CRM relations still resolve. - Add a regression test covering the bad Opportunity owner -> workspace member -> message participant path. ## Root Cause PR #21684 introduced generic relation traversal for email and calendar timelines. That traversal walks relation paths from the current record to `person`, then the Emails tab loads message threads for those derived people. For Opportunities, the traversal was too broad because it could enter internal/system objects. In particular, it could follow: `opportunity.owner -> workspaceMember.messageParticipants -> messageParticipant.person` That path does not describe people related to the Opportunity. It describes people who appeared in messages involving the Opportunity owner. As a result, an Opportunity owned by Josh could show threads from Josh's broader mailbox activity, which matches the customer report: recently communicated people appeared in the Opportunity Emails tab even though they were not specifically related to that Opportunity. ## Behavior Before On an Opportunity record, the Emails tab could include message threads for: - the Opportunity point of contact; - people related through the Opportunity company; - people reached through internal/system relations, including the owner workspace member's message participants. The last category was the regression. It made the Opportunity Emails tab look like a broad inbox for the owner instead of a timeline for people related to the CRM record. ## Behavior After The traversal still allows valid CRM person paths, including: `opportunity.pointOfContact -> person` and non-system CRM paths such as: `opportunity.company -> company.people -> person` But it now stops before traversing system objects such as `workspaceMember` and `messageParticipant`. This blocks the bad owner-mailbox expansion path: `opportunity.owner -> workspaceMember.messageParticipants -> messageParticipant.person` Email sync is unchanged. This only changes which synced emails are displayed on a record timeline. ## Video https://github.com/user-attachments/assets/26de4cee-06d9-4f42-b91e-32e60a260b5b ## Validation - `yarn nx jest twenty-server src/engine/core-modules/related-person-ids/utils/__tests__/find-relation-paths-to-person.util.spec.ts --runInBand` - Focused `oxlint` and `oxfmt` on the touched files. - GitHub `server-lint-typecheck` passes on the updated branch. - Browser verification on local Apple seed workspace: fixed relation set renders `Inbox 280`; the excluded owner-derived path would have resolved `300` threads.