Peer admission required the remote ticket's subject to equal the local
account on both sides, so only devices of one account could pair. That
made the product multi-device sync rather than collaboration.
The subject equality was the authorization, so it is replaced rather than
deleted. `PeerIdentityPolicy` states which accounts a peer may belong to,
and the two sides get different answers because they do not have the same
ability to tell who the peer is:
- The owner accepting a guest admits any issued account. Nothing at this
layer decides whether the guest joins — a human does, from the approval
prompt, which is shown the verified identity and which the admission
state machine makes unskippable (`Active` is reachable only through
`OwnerAuthorized`).
- A guest joining by invite or relay admits any issued account, because
the invite's signed locator already pinned the owner's Noise static key
and that pin is checked before admission runs. The device is
authenticated whatever account is behind it, which is what makes joining
a stranger's session safe.
- A guest joining over an unpinned LAN discovery still requires the same
account. A guest has no approval prompt — whatever it accepts, it
accepts silently — and nothing else names the peer there: mDNS is
spoofable and no key is known in advance. Relaxing it would let anyone
on the segment holding any valid ticket pose as the owner, undetected.
Opening this needs a way for the guest to confirm who it is joining,
which is a user-facing decision, not a protocol change.
Relaxing the account relaxes nothing else: issuer, expiry, and the binding
to the observed Noise static key are unchanged, and renewal still refuses
any mid-session change of issuer, subject, device id, or key. Tests cover
that a foreign subject is admitted while each of those still rejects, and
the unpinned-LAN case has its own regression guard.
Also fixes two things this uncovered. The live MCP tests in op-host-desktop
drove the endpoint with raw HTTP and no token, so they failed with 401
after bc75c765b authenticated it — they now send the instance token, which
is also a live check that the authentication works. And two constant
relations in the transport config were runtime asserts that clippy rejects
as constant-valued; they are compile-time asserts now, which is what a
relation between constants should have been.