Several code paths assumed each user holds at most one subscription without anything enforcing it, and "has a subscription" ignored status (#3616778: Define and enforce single-active-subscription semantics (loadLocalSubscription() returns an arbitrary first match)). Three related changes:
One active subscription per user, enforced
SubscriptionEntity::preSave() now enforces a site-wide invariant: when a subscription is saved active, any other active subscription the same user holds is deactivated — newest save wins, mirroring the remote billing reality that the latest contract is the one in force. The superseded row's postSave() revokes its snapshotted roles as usual. Sites that intentionally relied on users holding several concurrent active subscriptions should not update without reviewing this: that state is no longer reachable through entity saves.
Deterministic selection
SubscriptionManagerService::loadLocalSubscription() previously returned whatever the storage happened to list first. It now selects deterministically: an active subscription first, then the most recently created, then the highest id. Callers such as the subscribe routing, the manage page, the portal redirect, and the drupalSettings payload inherit stable behavior.
Explicit active-only lookups
userHasLocalSubscriptionToAnyPlan() and getUserLocalSubscriptionToAnyPlan() gained a third parameter, bool $active_only = FALSE. The default keeps the previous meaning — lapsed subscriptions count, which is correct for manage-billing access and portal surfaces that serve lapsed subscribers for history and reactivation. Pass TRUE where the question is "is this user currently subscribed"; the module's own post-login subscribe redirect now does, so lapsed subscribers are redirected to the subscribe page again instead of being treated as subscribed.