From 5a811a3695579551623ff3fa5d0d0da321fe9d3c Mon Sep 17 00:00:00 2001 From: Dai Ha Date: Mon, 31 Aug 2026 22:17:22 +0700 Subject: [PATCH] #199: GET /members returns its rows under "members", with "workers" kept as an alias The endpoint became /members in the CB-634 rename but the body key stayed "workers", so a caller that read "members" saw an empty fleet and reported no members at all. Emit the canonical "members" key. Keep "workers" as a deprecated alias so an existing REST consumer keeps working - the out-of-band path a lead falls back to when its MCP mount drops reads this endpoint. The test now pins both keys and asserts they carry the same rows, so the alias cannot silently drift. Watched failing without the fix: "GET /members must return its rows under \"members\" ==> expected: not " --- .../main/java/dev/ltms/fleet/rest/FleetApp.java | 6 ++++++ .../java/dev/ltms/fleet/rest/FleetAppTest.java | 14 +++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/fleetd/src/main/java/dev/ltms/fleet/rest/FleetApp.java b/fleetd/src/main/java/dev/ltms/fleet/rest/FleetApp.java index 5e479f1..d78abf1 100644 --- a/fleetd/src/main/java/dev/ltms/fleet/rest/FleetApp.java +++ b/fleetd/src/main/java/dev/ltms/fleet/rest/FleetApp.java @@ -319,6 +319,12 @@ public final class FleetApp { .map(s -> SessionManager.rosterView(s, live.get(s.terminalId()))) .toList(); Map body = new LinkedHashMap<>(); + // fleetd #199: the endpoint became /members in the CB-634 rename but the body key stayed + // "workers", so a caller that read "members" saw an empty fleet and reported no members at + // all. "members" is the canonical key; "workers" stays as a deprecated alias so an existing + // REST consumer keeps working — the out-of-band path a lead falls back to when its MCP mount + // drops reads this endpoint. Drop the alias once nothing reads it. + body.put("members", out); body.put("workers", out); // CB-586: operator visibility for the refs/wip snapshot store without shelling into the // repo — how many snapshot refs exist and roughly what they cost. Present only once a diff --git a/fleetd/src/test/java/dev/ltms/fleet/rest/FleetAppTest.java b/fleetd/src/test/java/dev/ltms/fleet/rest/FleetAppTest.java index aef96bf..a0a5768 100644 --- a/fleetd/src/test/java/dev/ltms/fleet/rest/FleetAppTest.java +++ b/fleetd/src/test/java/dev/ltms/fleet/rest/FleetAppTest.java @@ -218,9 +218,17 @@ class FleetAppTest { HttpResponse res = req(port, "GET", "/members"); assertEquals(200, res.statusCode()); - JsonNode workers = mapper.readTree(res.body()).get("workers"); - assertEquals(1, workers.size()); - JsonNode w = workers.get(0); + JsonNode body = mapper.readTree(res.body()); + // fleetd #199: "members" is the canonical key. The endpoint is /members, so a caller that + // reads "members" must not see an empty fleet. "workers" is kept only as a deprecated alias + // and must carry the same rows — assert both, or the alias can silently drift. + JsonNode members = body.get("members"); + assertNotNull(members, "GET /members must return its rows under \"members\""); + assertEquals(1, members.size()); + JsonNode workers = body.get("workers"); + assertNotNull(workers, "the deprecated \"workers\" alias is still emitted"); + assertEquals(members, workers, "the alias must carry the same rows as \"members\""); + JsonNode w = members.get(0); assertEquals(spawned.get("terminalId").asText(), w.get("sessionId").asText()); assertEquals(paneId, w.get("paneId").asText()); assertEquals("ltms-local", w.get("profile").asText());