The ceiling shipped in 1.0.3.0 did the opposite of its job. Jellyfin throws
MediaBrowser.Controller.Net.SecurityException when a user is at their session
limit, and the catch that was meant to handle it named System.Security's type of
the same name, so it never matched. The exception fell through to the failure
path, which marks the record failed and runs cleanup, which deletes the guest
account. Live result with the ceiling at 3: the fourth viewer got a dead-link
page, the three already watching were kicked out, and the link was gone.
Rather than swap one exception type for another and trust it, the over-the-ceiling
viewer is now turned away before anything is written at all: no tag work, no
status change, the guest account untouched. The check mirrors what Jellyfin does
when it creates a session, counting sessions for the guest against the ceiling.
The typed catch stays as a backstop for the race between the check and the call,
and it now names the right type.
A link that has never been redeemed has no guest yet, so it can never be at a
ceiling, and 0 still means no limit.