- Shipped
- 4 Septemba 2026, 23:33 UTC
- Author
- Kamo
- Commit
- 29941ff
One rule, in one place, for the three endpoints that write a USER account: the profile's member update, the profile's personal address, and the platform Users tab. They govern the same data and had drifted into three different answers. UserAccountEditPolicy: the person themselves, a god-eligible operator, the System User, or a platform administrator holding MANAGE_USERS / SYSTEM_USER — the Users tab on /account. The top-level-organization precondition rides along free, since PlatformRightsResolver resolves nothing for a session in a tenant. Two things it deliberately drops. MANAGE_MEMBERS and MANAGE_MEMBER_SECURITY no longer reach the legal name, the preferred name or the date of birth. Those are TENANT rights over an account every organization the person belongs to shares, and a tenant administrator can edit their own organization's security models — so a tenant could grant itself the ability to rewrite the identity everyone else sees. The same reasoning has always kept them off the password. This was also the only rule the endpoint enforced, so it is now stricter than before rather than merely different. "The current organization owns the account" is gone. It reads like the natural safeguard and was a dead end: the platform provides the account for 77 of 141 memberships, and 37 of those people are not members of the organization that owns their account at all — so no workspace existed in which they could ever edit their own name, preferred name or personal address. It also answered the wrong question for the owner, who is a PERSON, not an organization. Proof of the mailbox is untouched and is the safeguard that actually matters for the address. The policy resolves its operator arms even when the target account cannot be read. Refusing everybody on an unknown target sounds like failing closed and is really failing wrong: it would leave an account nobody could correct, which is the state an operator exists to get out of. `isSelf` on the member update stays by MEMBER id: an impersonating session has had its memberID swapped to the target, and a sudo session is meant to act as that member would.