diff --git a/fleetd/src/main/java/dev/ltms/fleet/mcp/ConnectionIdentity.java b/fleetd/src/main/java/dev/ltms/fleet/mcp/ConnectionIdentity.java index 8f9e453..3813e12 100644 --- a/fleetd/src/main/java/dev/ltms/fleet/mcp/ConnectionIdentity.java +++ b/fleetd/src/main/java/dev/ltms/fleet/mcp/ConnectionIdentity.java @@ -90,13 +90,27 @@ public final class ConnectionIdentity { * {@code 127.0.0.1:8765} with a source address of {@code 127.0.0.2} — measured on the Linux * fleet host, where binding that source succeeds. * - *

Being strict here does not make the daemon safer; it makes it unsafe. - * That reads backwards, so it is worth stating plainly. This predicate does not decide whether - * a caller is trusted — it decides whether the caller's identity is resolved at all. - * Returning false means {@link #resolve} answers "no terminal", and downstream a caller with no - * terminal is treated as the primary under loopback-trust. So every address excluded here is an - * address on which a worker silently becomes the lead. Widening a check normally weakens it; - * widening this one is what closes the hole. + *

What excluding an address costs, stated as it is today. This paragraph + * used to say that narrowing this range turned a worker into the lead, and that widening the + * check was what closed the hole. That was true only while there were two definitions + * that disagreed: {@code ConnectionIdentity} skipped the identity lookup for {@code 127.0.0.2} + * while {@code CallerResolver} read the same address as loopback and granted the primary role. + * #305 removed the second copy, and with one shared definition the old sentence no longer holds. + * + *

Measured on 2026-09-04 by narrowing this method back to exactly {@code 127.0.0.1} and + * running {@code CallerResolverTest} and {@code ConnectionIdentityTest}: a caller from + * {@code 127.0.0.2} then resolves to {@code ANONYMOUS}, not {@code PRIMARY} — for a worker + * ({@code aWorkerOnAnyLoopbackSourceAddressIsStillAWorkerNotThePrimary}) and for a non-worker + * ({@code aNonWorkerOnAnyLoopbackSourceAddressIsStillThePrimary}) alike. Excluding an address + * now refuses its caller; it does not promote one. + * + *

So keep the whole range, but for the plain reason: a genuine worker or primary that + * connects from {@code 127.0.0.2} must be identifiable at all, and narrowing this predicate + * locks it out. That is an outage, and an outage is the direction to fail in — which is exactly + * why the range must not be narrowed casually and also why doing so is no longer a security + * hole. This predicate still does not decide whether a caller is trusted; it decides whether the + * caller's identity is resolved at all. What makes an unresolved caller safe is + * {@link Caller#resolved()} (#317), not this method. */ public static boolean isLoopback(String addr) { if (addr == null) {