Partitioned
The member's transport link has dropped and its seat is held open until windowExpiresAt.
windowExpiresAt is non-null by construction — it is written at the same site and instant that sets this state, so a partitioned member whose window is unknown is not a state this type can represent. That is deliberate: it was previously reachable only by replaying a MembershipEvent.WindowOpened that some paths never emitted (#1723, #1724).
On a member watching another member, this deadline starts as a local estimate whenever that member's own detector fires first, and is then replaced by the host's authoritative AdmitMessage.Paused — in either arrival order, and without re-announcing the partition. The host is the only holder of the enforced window, so its number always wins. On a joiner watching its host, the joiner's own reconnect budget is the authority and no refinement occurs.
A refinement is announced. Moving this field emits a fresh MembershipEvent.WindowOpened carrying the new deadline, so the event stream and the roster cannot disagree — a silent move would leave the last announcement a consumer heard permanently false. The corollary for a consumer that does key on the event: a later WindowOpened for the same peer supersedes the earlier one; hold the latest, do not assume the first is final. Keying on this level avoids the question entirely, which is why it exists.
Beware that the two fields can then come from different clocks. markPartitioned derives both from the local clock, but the Paused path pairs a local since with the host's windowExpiresAt. So treat windowExpiresAt as a deadline to compare the local clock against — never as an interval to subtract from since, which host↔member skew would distort.
Properties
When this partition was first detected — preserved across an idempotent re-detection rather than advanced, so it agrees with the single MembershipEvent.Partitioned that was actually emitted (that event fires only on the first detection). Do not "simplify" this to overwrite on every detection: since would then drift forward while windowExpiresAt stayed pinned, and could eventually exceed it.