+54
−0
Loading
Felis pins player-info-forwarding-mode = "modern", and Velocity's HandshakeSessionHandler#handleLogin refuses anything below 1.13 outright: it reads handshake.getProtocolVersion() and disconnects with velocity.error.modern-forwarding-needs-new-client before the backend is ever contacted. A player pinned to 1.8.9 never reaches the login gate, never sees the onboarding link, and gets an error string that tells them to upgrade their client. install_via_plugins now stages ViaVersion, ViaBackwards and ViaRewind into /opt/felis/velocity/plugins alongside felis-velocity.jar. Nothing else moves: same forwarding mode, same secret, no backend patched and no backend downgraded. The 1.13 floor turns out to be a property of the unassisted proxy pipeline rather than of the forwarding protocol, so lifting it costs three jars and no source change. This was measured, not assumed. Felis-Legacy's FL-007 probe stands a protocol-47 client in front of a stock Paper 1.21.11 backend behind a modern-forwarding proxy and watches it join. The proof is the join itself rather than the log line: that backend runs velocity.enabled with a shared secret, and Paper in that state rejects any login not carrying forwarding data signed with a matching HMAC. The control cell without Via is rejected before the backend is contacted, so Via is the only difference. A second cell re-runs the same join with force-key-authentication = true, the way Felis sets it, because a result that only holds under a config Felis does not run is not a result about Felis; the 1.19+ signed chat key a protocol-47 client cannot produce is never demanded, and it cannot be, since the pre-1.19 wire format has no player-key field to decode. The jars are pinned by sha256 and not by a moving tag. They sit in front of every packet on the proxy and they are the exact bytes FL-007 measured; "latest" would quietly make this an unmeasured configuration. The digests come from the GitHub releases FL-006 locked, which is deliberate — Hangar's VELOCITY/download endpoint serves different bytes for the same version numbers, so an installer that only checked for HTTP 200 would ship artifacts nothing has tested. A version bump means a digest bump here. Two limits are worth writing down. Only protocol 47 was measured; the rest of Via's documented 1.7-1.12 range is inference from that one point. And the probe runs online-mode = false because it has no Mojang account, so Felis's online-mode = true is untested — the untested part is the Mojang auth handshake specifically, which puts the residual in Via's own login handling rather than in forwarding or in the hasJoined multiplexer, whose request is protocol-independent. Checks: a fresh install lands all three jars at the pinned digests and sizes with no temp files left behind; a re-run downloads nothing; a tampered jar is restored to the pinned bytes; and a deliberately wrong digest aborts without installing anything. Existing installs pick this up by re-running bootstrap, which re-enters install_velocity because bootstrap.done is written but never read as an early exit.