Merge #467: listFleet's callerIsPrimary default fails closed (fleetd #463)
CI / contract (push) Successful in 56s
CI / build (push) Successful in 1m38s

A wrapper overload that is called with no callerIsPrimary argument used to
default it to true, so a forgotten argument silently handed out the lead's
coordination state. It now defaults to false: a missing identity fails closed.

Verified on the merge commit, not the branch:

- The funnel is real. FleetMcp has 7 listFleet declarations and 7 real calls
  (an 8th 'listFleet(' match is a javadoc {@link}). Exactly one call writes a
  literal for the new boolean, and it writes false; exactly one writes the real
  predicate, coordinatorVisibleTo(principal(exchange)) in the MCP handler. No
  call writes true.
- Control battery on the merge: 1584 tests green unmutated.
- M1, the fix reverted at the one line that writes the default (false -> true):
  KILLED by listCompatOverloadWithNoCallerIsPrimaryArgumentOmitsTheCoordinatorKey.
- M2, the half this round weakened. The worker rewrote
  listIsByteForByteUnchangedForThePrimaryCaller and dropped its byte-for-byte
  equality assertion, which was correct because that comparison ran against the
  implicit-default overload -- now the path #463 closes. So: does anything still
  notice if the primary's coordinator row silently loses a field? Dropped
  heldCount: KILLED by two tests, that same test and
  listReportsAnHonestHeldCountAndDurabilityNotJustPendingZero.
- M3, a regression check on #439's own gate, 'if (callerIsPrimary)' -> 'if (true)':
  KILLED by three tests.

What is no longer pinned, stated plainly: the primary's output is now checked
field by field, not as a whole string. A field that no test names could
disappear without failing anything. Every field the tests do name is pinned,
proven by M2. The whole-output answer belongs to fleetd #460.

One control in my own battery was wrong and is worth recording: I labelled
', true);' in FleetMcp.java 'must be 0' and it is 2 -- row.put("configured",
true) and m.put("self", true), neither a listFleet delegation. The pattern was
too wide. The count above comes from a walk over each declaration and call
instead.
This commit is contained in:
Dai Ha
2026-09-10 19:04:51 +07:00
2 changed files with 58 additions and 30 deletions
@@ -1362,10 +1362,12 @@ public final class FleetMcp {
/** /**
* As above, plus fleetd #176 lead-seat facts (see {@link LeadSeatSource}). * As above, plus fleetd #176 lead-seat facts (see {@link LeadSeatSource}).
* *
* <p>Assumes the caller is the primary — every wrapper overload above delegates here without * <p>Assumes the caller is <strong>not</strong> the primary (fleetd #463) — every wrapper
* carrying a caller identity, which is exactly right for them: they exist for call sites (and * overload above delegates here without carrying a caller identity, which is exactly right for
* unit tests) that have no {@link Principal} to hand over, and this preserves their pre-#439 * them: they exist for call sites (and unit tests) that have no {@link Principal} to hand over,
* behavior unchanged. The one call site that has a real caller ({@code fleet_list}'s MCP * and a missing identity should fail closed rather than fail open onto lead-to-lead state. A
* test that wants the {@code coordinator} row must call the canonical overload below with an
* explicit {@code true}. The one call site that has a real caller ({@code fleet_list}'s MCP
* handler) uses {@link #listFleet(PeerLauncher, SessionManager, MessageService, CapacitySource, * handler) uses {@link #listFleet(PeerLauncher, SessionManager, MessageService, CapacitySource,
* HealthCoverageSource, QuarantineSource, OutageSource, LeadSeatSource, Map, String, * HealthCoverageSource, QuarantineSource, OutageSource, LeadSeatSource, Map, String,
* CoordinationSource, boolean)} instead, so it can pass the true answer. * CoordinationSource, boolean)} instead, so it can pass the true answer.
@@ -1376,7 +1378,7 @@ public final class FleetMcp {
LeadSeatSource leadSeats, Map<String, String> leads, String selfTerm, LeadSeatSource leadSeats, Map<String, String> leads, String selfTerm,
CoordinationSource coordination) { CoordinationSource coordination) {
return listFleet(workers, sessions, messages, capacity, healthCoverage, quarantine, outage, return listFleet(workers, sessions, messages, capacity, healthCoverage, quarantine, outage,
leadSeats, leads, selfTerm, coordination, true); leadSeats, leads, selfTerm, coordination, false);
} }
/** /**
@@ -1390,7 +1392,9 @@ public final class FleetMcp {
* @param callerIsPrimary whether the {@code fleet_list} caller is the primary; only the MCP * @param callerIsPrimary whether the {@code fleet_list} caller is the primary; only the MCP
* handler computes this from the real connection (see * handler computes this from the real connection (see
* {@code Principal#isPrimary()}) — every other overload passes * {@code Principal#isPrimary()}) — every other overload passes
* {@code true} * {@code false} (fleetd #463: a forgotten argument fails closed, not
* open), so a test that wants the {@code coordinator} row must pass
* an explicit {@code true}
*/ */
static McpSchema.CallToolResult listFleet(PeerLauncher workers, SessionManager sessions, MessageService messages, static McpSchema.CallToolResult listFleet(PeerLauncher workers, SessionManager sessions, MessageService messages,
CapacitySource capacity, HealthCoverageSource healthCoverage, CapacitySource capacity, HealthCoverageSource healthCoverage,
@@ -626,8 +626,8 @@ class FleetMcpTest {
McpSchema.CallToolResult res = FleetMcp.listFleet( McpSchema.CallToolResult res = FleetMcp.listFleet(
workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null, workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null,
FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"), FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"),
FleetMcp.QuarantineSource.none(), Map.of(), "", FleetMcp.QuarantineSource.none(), FleetMcp.OutageSource.none(), FleetMcp.LeadSeatSource.none(),
new FleetMcp.CoordinationSource(channel, List.of())); Map.of(), "", new FleetMcp.CoordinationSource(channel, List.of()), true);
String out = textOf(res); String out = textOf(res);
// fleetd #361: reports both which coord-id a peer must use to reach ME, and this daemon's // fleetd #361: reports both which coord-id a peer must use to reach ME, and this daemon's
@@ -655,8 +655,8 @@ class FleetMcpTest {
McpSchema.CallToolResult res = FleetMcp.listFleet( McpSchema.CallToolResult res = FleetMcp.listFleet(
workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null, workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null,
FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"), FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"),
FleetMcp.QuarantineSource.none(), Map.of(), "", FleetMcp.QuarantineSource.none(), FleetMcp.OutageSource.none(), FleetMcp.LeadSeatSource.none(),
new FleetMcp.CoordinationSource(channel, List.of())); Map.of(), "", new FleetMcp.CoordinationSource(channel, List.of()), true);
String out = textOf(res); String out = textOf(res);
assertTrue(out.contains("\"mailbox\":{\"status\":\"unknown\"}"), out); assertTrue(out.contains("\"mailbox\":{\"status\":\"unknown\"}"), out);
@@ -676,6 +676,32 @@ class FleetMcpTest {
"an ordinary fleet's output must be unchanged by this feature"); "an ordinary fleet's output must be unchanged by this feature");
} }
/**
* fleetd #463: a compat overload called with no {@code callerIsPrimary} argument at all must
* fail closed, not open. Before this fix the hidden default was {@code true}, so a caller that
* forgot the argument silently got lead-to-lead coordination state. Lead coordination is fully
* configured here (a real channel, a real mailbox) specifically so this is not conflated with
* {@link #listOmitsTheCoordinatorRowWhenLeadCoordinationIsOff} -- the row is capable of being
* assembled, and the missing argument is the only reason it is not.
*/
@Test
void listCompatOverloadWithNoCallerIsPrimaryArgumentOmitsTheCoordinatorKey() {
FakeHerdr h = new FakeHerdr();
SessionManager sessions = new SessionManager(workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")));
FakeLeadChannel channel = new FakeLeadChannel("mac-opus")
.withMailbox("mac-opus", LeadChannel.MailboxState.exists("mac-opus", 0, 1));
McpSchema.CallToolResult res = FleetMcp.listFleet(
workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null,
FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"),
FleetMcp.QuarantineSource.none(), Map.of(), "",
new FleetMcp.CoordinationSource(channel, List.of()));
String out = textOf(res);
assertFalse(out.contains("\"coordinator\""),
"no callerIsPrimary argument must fail closed (absent), not open (present): " + out);
}
/** /**
* fleetd #439: a worker calling {@code fleet_list} must get a result with the {@code * fleetd #439: a worker calling {@code fleet_list} must get a result with the {@code
* coordinator} key <strong>absent</strong> -- not an empty object, not a redacted one -- even * coordinator} key <strong>absent</strong> -- not an empty object, not a redacted one -- even
@@ -730,11 +756,15 @@ class FleetMcpTest {
} }
/** /**
* fleetd #439 acceptance criterion 3: the primary's {@code fleet_list} is byte-for-byte * fleetd #439 acceptance criterion 3: an explicitly-primary caller sees the coordinator row
* unchanged by this fix. Proven by comparing the new gated overload (with {@code * fully assembled, with the same content #439 always produced for a primary.
* callerIsPrimary=true}, exactly what the MCP handler passes for the primary) against the *
* pre-#439 overload that always assembled the row -- if the gate changed anything for a * <p>fleetd #463 flipped the compat overloads' hidden default from {@code true} to
* primary caller, these two strings would differ. * {@code false} (fail closed), so the old "pre-#439 overload" this test used to compare
* against no longer stands in for a primary caller -- it is now exactly the implicit-default
* path #463 closes. Verifying the primary path means calling the canonical overload with an
* explicit {@code callerIsPrimary=true} directly, as the production {@code fleet_list} handler
* does.
*/ */
@Test @Test
void listIsByteForByteUnchangedForThePrimaryCaller() { void listIsByteForByteUnchangedForThePrimaryCaller() {
@@ -743,19 +773,12 @@ class FleetMcpTest {
FakeLeadChannel channel = new FakeLeadChannel("mac-opus") FakeLeadChannel channel = new FakeLeadChannel("mac-opus")
.withMailbox("mac-opus", LeadChannel.MailboxState.exists("mac-opus", 0, 1)); .withMailbox("mac-opus", LeadChannel.MailboxState.exists("mac-opus", 0, 1));
String preExisting = textOf(FleetMcp.listFleet(
workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null,
FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"),
FleetMcp.QuarantineSource.none(), Map.of(), "",
new FleetMcp.CoordinationSource(channel, List.of())));
String gatedAsPrimary = textOf(FleetMcp.listFleet( String gatedAsPrimary = textOf(FleetMcp.listFleet(
workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null, workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null,
FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"), FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"),
FleetMcp.QuarantineSource.none(), FleetMcp.OutageSource.none(), FleetMcp.LeadSeatSource.none(), FleetMcp.QuarantineSource.none(), FleetMcp.OutageSource.none(), FleetMcp.LeadSeatSource.none(),
Map.of(), "", new FleetMcp.CoordinationSource(channel, List.of()), true)); Map.of(), "", new FleetMcp.CoordinationSource(channel, List.of()), true));
assertEquals(preExisting, gatedAsPrimary,
"a primary caller must see byte-for-byte the same result as before this fix");
assertTrue(gatedAsPrimary.contains("\"coordinator\""), gatedAsPrimary); assertTrue(gatedAsPrimary.contains("\"coordinator\""), gatedAsPrimary);
assertTrue(gatedAsPrimary.contains("\"selfId\":\"mac-opus\""), gatedAsPrimary); assertTrue(gatedAsPrimary.contains("\"selfId\":\"mac-opus\""), gatedAsPrimary);
assertTrue(gatedAsPrimary.contains("\"mailbox\""), gatedAsPrimary); assertTrue(gatedAsPrimary.contains("\"mailbox\""), gatedAsPrimary);
@@ -780,8 +803,8 @@ class FleetMcpTest {
McpSchema.CallToolResult res = FleetMcp.listFleet( McpSchema.CallToolResult res = FleetMcp.listFleet(
workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null, workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null,
FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"), FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"),
FleetMcp.QuarantineSource.none(), Map.of(), "", FleetMcp.QuarantineSource.none(), FleetMcp.OutageSource.none(), FleetMcp.LeadSeatSource.none(),
new FleetMcp.CoordinationSource(channel, List.of())); Map.of(), "", new FleetMcp.CoordinationSource(channel, List.of()), true);
String out = textOf(res); String out = textOf(res);
assertTrue(out.contains("\"msgId\":\"m1\""), out); assertTrue(out.contains("\"msgId\":\"m1\""), out);
@@ -812,8 +835,8 @@ class FleetMcpTest {
McpSchema.CallToolResult res = FleetMcp.listFleet( McpSchema.CallToolResult res = FleetMcp.listFleet(
workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null, workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null,
FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"), FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"),
FleetMcp.QuarantineSource.none(), Map.of(), "", FleetMcp.QuarantineSource.none(), FleetMcp.OutageSource.none(), FleetMcp.LeadSeatSource.none(),
new FleetMcp.CoordinationSource(channel, List.of())); Map.of(), "", new FleetMcp.CoordinationSource(channel, List.of()), true);
String out = textOf(res); String out = textOf(res);
assertTrue(out.contains("\"pending\":0"), out); assertTrue(out.contains("\"pending\":0"), out);
@@ -841,8 +864,8 @@ class FleetMcpTest {
McpSchema.CallToolResult res = FleetMcp.listFleet( McpSchema.CallToolResult res = FleetMcp.listFleet(
workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null, workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null,
FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"), FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"),
FleetMcp.QuarantineSource.none(), Map.of(), "", FleetMcp.QuarantineSource.none(), FleetMcp.OutageSource.none(), FleetMcp.LeadSeatSource.none(),
new FleetMcp.CoordinationSource(channel, List.of())); Map.of(), "", new FleetMcp.CoordinationSource(channel, List.of()), true);
String out = textOf(res); String out = textOf(res);
assertTrue(out.contains("\"heldDurable\":false"), assertTrue(out.contains("\"heldDurable\":false"),
@@ -909,8 +932,9 @@ class FleetMcpTest {
McpSchema.CallToolResult res = FleetMcp.listFleet( McpSchema.CallToolResult res = FleetMcp.listFleet(
workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null, workerService(h, "http://gx00.gw:8000", Set.of("gx00.gw")), sessions, null,
FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"), FleetMcp.CapacitySource.none(), new FleetMcp.HealthCoverageSource(() -> "off"),
FleetMcp.QuarantineSource.none(), Map.of(), "", FleetMcp.QuarantineSource.none(), FleetMcp.OutageSource.none(), FleetMcp.LeadSeatSource.none(),
new FleetMcp.CoordinationSource(channel, List.of("fleet01-lead", "fleet02-lead", "fleet03-lead"))); Map.of(), "",
new FleetMcp.CoordinationSource(channel, List.of("fleet01-lead", "fleet02-lead", "fleet03-lead")), true);
String out = textOf(res); String out = textOf(res);
assertTrue(out.contains("\"coordId\":\"fleet01-lead\",\"status\":\"exists\",\"pending\":2,\"consumers\":1"), out); assertTrue(out.contains("\"coordId\":\"fleet01-lead\",\"status\":\"exists\",\"pending\":2,\"consumers\":1"), out);