fix(cli): home heartbeat fetches one client, not the whole account (#338)#339
Open
saadqbal wants to merge 4 commits into
Open
fix(cli): home heartbeat fetches one client, not the whole account (#338)#339saadqbal wants to merge 4 commits into
saadqbal wants to merge 4 commits into
Conversation
) The bare-CLI home screen showed a false "running — couldn't confirm it's connected to tracebloc" while `tb doctor` was fully green. Root cause: realHeartbeat → lookupClientStatus called api.Client.ListClients, which pages through EVERY client in the account (GET /edge-device/, up to maxListPages=100) just to read one client's status — all under the ~1.2s home-probe budget. On accounts with enough clients to need multiple pages, the list can't finish in time → context deadline → beatUnknown → the false "couldn't confirm". doctor is green because its Backend-auth check is a single GET /userinfo/ with no leash. Add api.Client.GetClient (GET /edge-device/{id}/ — the detail route PatchClientClusterID/RevokeClient already use) and switch lookupClientStatus to fetch the single active client directly (404 → not-found, not an error). One O(1) round-trip fits comfortably in the budget → honest Online/not-online. Removes the now-unused findClientByID (blocking deadcode gate). ListClients still backs list / use / create-collision. Fixes #338. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
|
👋 Heads-up — Code review queue is at 40 / 30 Above the WIP limit. The team convention is to review existing PRs before opening new work. Open PRs currently in Code review (oldest first):
Pull from review before opening new work. (This is a nudge from the kanban WIP check, not a block.) |
… route
lookupClientStatus now fetches the single client (GetClient) instead of
ListClients, so the TestClientStatus_* backend stubs must serve
GET /edge-device/5/ (single object) rather than GET /edge-device/ (array).
Without this the status path decoded an empty body ('unexpected end of JSON
input') and the --wait fail-fast tests (426/401/missing) looped to the 10m
test timeout. Create/list stubs are unchanged — ListClients still backs those.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
delete's offboard guard also checks the client via lookupClientStatus, which
now fetches GET /edge-device/{id}/. The TestDelete_* status stubs served the
list route → the guard hit an unhandled path (empty body / 'unexpected GET
/edge-device/5/') and the online/426/401 guards stopped firing. Redirect the
status-guard GETs to /edge-device/5/ (single object). The --force revoke-fail
tests skip the guard and only stub /revoke/, so they're untouched.
Full internal/cli package green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4d633c7. Configure here.
…error (Bugbot #338) lookupClientStatus returned a permanent error when ActiveClientID wasn't numeric. --wait only fail-fasts on 401/403/426/404, so it treated that parse error as transient and polled to the timeout — a regression vs the old ListClients+match path, which returned found=false (a non-numeric id can never match). Return (0, false, nil) so --wait fail-fasts on the missing client. Adds TestClientStatus_WaitFailsFastOnNonNumericID. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Symptom
Bare
tracebloc/tbhome screen shows a false negative:…while
tb doctoris fully green (Backend auth ✔, egress ✔, active client resolved). The backend IS reachable — the home probe just can't confirm it in time.Root cause
realHeartbeat→lookupClientStatus→api.Client.ListClients, which doesGET /edge-device/and paginates through every client in the account (up tomaxListPages=100), then filters client-side for the active id — all underhomeProbeTimeout=1200ms/homeDetectBudget=1500ms. Enough clients to need multiple pages (or slow prod round-trips) → context deadline →beatUnknown→ "couldn't confirm".tb doctoris green because its Backend-auth check is a singleGET /userinfo/with no tight timeout.Fix
api.Client.GetClient(ctx, id) → GET /edge-device/{id}/— the O(1) detail route (same onePatchClientClusterID/RevokeClientuse);PatchClientClusterIDalready decodes a singleProvisionedClientfrom it. 404 →(nil, nil)(not-found, not an error).lookupClientStatusto fetch the single active client directly instead of listing the whole account.findClientByID(blocking deadcode gate).ListClientsstill backsclient list/use/ create-collision.One fast round-trip fits comfortably in the 1.2s budget → the heartbeat returns the honest Online / not-online instead of spurious "couldn't confirm".
Verification
go build/go vet/gofmtclean;GetClientcontract test (2xx decode / 404→nil,nil / 500→APIError, pins the detail path) + the heartbeat/home tests pass. Fullinternal/clisuite left to CI.Fixes #338.
🤖 Generated with Claude Code
Note
Medium Risk
Touches the shared status lookup used by home heartbeat, client status --wait, and delete guards; behavior is intended to match prior semantics with a different API shape, backed by broad test updates.
Overview
Fixes false “couldn't confirm it's connected” on the bare home screen when the backend is fine but the probe times out (~1.2s).
lookupClientStatus(home heartbeat,client status, delete pre-offboard guard) no longer callsListClientsand scan the account. It uses a newapi.Client.GetClient—GET /edge-device/{id}/— for one round-trip.findClientByIDis removed.ListClientsis unchanged forclient list, create collision, and adopt flows.GetClientdecodes a singleProvisionedClient; 404 →(nil, nil)(missing client, not an error). A non-numeric active client id is treated as not found (no API call) so--waitfails fast instead of polling to timeout.Tests add
TestGetClientandTestClientStatus_WaitFailsFastOnNonNumericID; status/delete stubs expect/edge-device/5/and object JSON instead of list payloads.Reviewed by Cursor Bugbot for commit c1f50ea. Bugbot is set up for automated code reviews on this repo. Configure here.