Skip to content

fix(fleet): sidebar client-side peer visibility (#1363) - #1364

Merged
jeonghun-jj-lee merged 1 commit into
feature/free-tier-fleetfrom
fix/1363-sidebar-client-roster-visibility
Sep 21, 2026
Merged

jeonghun-jj-lee merged 1 commit into
feature/free-tier-fleetfrom
fix/1363-sidebar-client-roster-visibility

Conversation

@jeonghun-jj-lee

Copy link
Copy Markdown
Contributor

Closes #1363. Fixes the reported bug: on a client machine the sidebar fleet section shows only itself; the canonical server never appears (on the server, both do).

Root cause

The sidebar's readRoster seam unconditionally read the machine-local roster cache — empty on a client, because the roster is host-owned (written only on the server via POST /amicode/roster). The client-side proxy read was an explicit #1321 follow-up. Compounding it, the server is never a roster row — it appears only via the machine's own self-row synthesis, so a client had nothing to render for it.

Changes (sidebar-only)

  • readRoster is role-aware. SERVER/standalone read the local cache synchronously (unchanged); a CLIENT proxy-reads the host's authoritative roster over the existing GET /amicode/roster (forwarded by the local service). Any failure — no live endpoint, network error, non-200, malformed body — is the honest reachable:false state, never a fabricated or stale list. The seam returns a sync | Promise union, so every existing synchronous injection is untouched (no test churn).
  • Canonical-server synthesis. buildFleetSectionModel synthesizes the server node on a client (from fleet.json canonical), mirroring the existing self-row synthesis; shown as down when the host is unreachable, and never doubled (self-row / existing roster row de-dupe).
  • Live wiring. extension.ts passes a lazy service-endpoint getter (the service boots after sidebar construction → null until up ⇒ honest degrade).

Scope / non-goals

Testing

  • sidebar_fleet_section.test.ts: +4 pure-unit cases for the canonical-server synthesis (present / de-dupe / not-for-local / down-when-unreachable).
  • sidebar_view.test.ts: +5 deps cases (client proxy-read with credential; client degrade on throw / no-endpoint; server reads local & never fetches; readCanonicalServer client-vs-server) +1 provider-level async end-to-end (client posts a fleet-status including the synthesized server node).
  • Full extension suite green (3996 passed / 0 failed); tsc --noEmit clean.

Known follow-up (for the reviewer / ADR 0027)

If a server ever self-registers a roster row, its machine_id (hostname) may differ from the canonical host string used for synthesis — a de-dupe reconciliation that belongs with gap 3's roster-identity work.

HITL — do not merge on my account; human promotes. Base is feature/free-tier-fleet (not main).

…ter + synthesize canonical-server node (#1363)

On a client, the sidebar fleet section showed only itself: readRoster
unconditionally read the machine-local roster cache (empty on a client,
since the roster is host-owned), and nothing rendered the server (never a
roster row). Two sidebar-only changes:

- readRoster is now role-aware: SERVER/standalone read the local cache
  synchronously (unchanged); a CLIENT proxy-reads the host's authoritative
  roster over the existing GET /amicode/roster (forwarded by the local
  service). Any failure is the honest unreachable state, never a fabricated
  or stale list. The seam returns a sync|Promise union so every existing
  synchronous injection is untouched.
- buildFleetSectionModel synthesizes the canonical-server node on a client
  (from fleet.json canonical), mirroring the existing self-row synthesis, so
  the server is visible; shown as down when the host is unreachable.

Sidebar-only: enroll verb, roster schema, and guard are byte-unchanged. The
roster-row enrichment (friendly name + device_type) is deferred to ADR 0027
(#1340 / PR #1353), which owns the roster schema.

Closes #1363
@jeonghun-jj-lee jeonghun-jj-lee added the hitl Needs human review before merge label Sep 21, 2026
@coderabbitai

coderabbitai Bot commented Sep 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 2e2d1f8d-434d-484c-91c8-ce5078069731

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jeonghun-jj-lee
jeonghun-jj-lee merged commit 4526ec7 into feature/free-tier-fleet Sep 21, 2026
12 checks passed
@jeonghun-jj-lee
jeonghun-jj-lee deleted the fix/1363-sidebar-client-roster-visibility branch September 21, 2026 12:20
jeonghun-jj-lee added a commit that referenced this pull request Sep 23, 2026
…ter + synthesize canonical-server node (#1363) (#1364)

On a client, the sidebar fleet section showed only itself: readRoster
unconditionally read the machine-local roster cache (empty on a client,
since the roster is host-owned), and nothing rendered the server (never a
roster row). Two sidebar-only changes:

- readRoster is now role-aware: SERVER/standalone read the local cache
  synchronously (unchanged); a CLIENT proxy-reads the host's authoritative
  roster over the existing GET /amicode/roster (forwarded by the local
  service). Any failure is the honest unreachable state, never a fabricated
  or stale list. The seam returns a sync|Promise union so every existing
  synchronous injection is untouched.
- buildFleetSectionModel synthesizes the canonical-server node on a client
  (from fleet.json canonical), mirroring the existing self-row synthesis, so
  the server is visible; shown as down when the host is unreachable.

Sidebar-only: enroll verb, roster schema, and guard are byte-unchanged. The
roster-row enrichment (friendly name + device_type) is deferred to ADR 0027
(#1340 / PR #1353), which owns the roster schema.

Closes #1363
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hitl Needs human review before merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant