Skip to content

feat(#131): R7 — adopt-and-backfill the live in-cluster client instead of minting an orphan#132

Merged
saadqbal merged 1 commit into
developfrom
feat/cli-131-r7-adopt-backfill
Jul 6, 2026
Merged

feat(#131): R7 — adopt-and-backfill the live in-cluster client instead of minting an orphan#132
saadqbal merged 1 commit into
developfrom
feat/cli-131-r7-adopt-backfill

Conversation

@saadqbal

@saadqbal saadqbal commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Closes #131.

The proper fix for the orphaned-mint bug (the band-aid was tracebloc/client#303 / PR #305). On an existing-fleet box, a live client whose backend cluster_id is null (installed before the anchor shipped) was re-provisioned as a fresh mint — the kube-system UID matched nothing, so the backend minted a new client and stranded the live one.

Backend already ships the whole contract (backend#883/#893, merged to master ee247ee4): cluster_id get-or-create + PATCH /edge-device/{id}/ adopt-backfill. This is the CLI half:

  • apiPatchClientClusterIDPATCH /edge-device/{id}/ {cluster_id}; 409/403 → typed APIError.
  • clusterDiscoverInClusterClient reads the live CLIENT_ID from the chart's <release>-secrets Secret (located by chart labels in the jobs-manager namespace; best-effort, time-bounded like ClusterID).
  • client create — before minting: if a client is live here and the anchor is readable, confirm the signed-in account owns it (by UUID username), PATCH-backfill the anchor onto it, and adopt it — no mint. Not in the account → refuse (cross-account, R6). Ownership unverifiable (list failed) → fail closed, never mint over a live client.

Fresh machines and already-anchored re-runs are unchanged.

Follow-ups (separate):

  • Retire the installer band-aid (client#303 / PR #305) once this ships.
  • Gate release on confirming dev/prod run a backend build with #893 (prod deploy is manual).

Tests: PatchClientClusterID (200 + 409); DiscoverInClusterClientID (happy / no-release / release-without-secret, incl. ignoring the node-agents mirror); create-flow R7 (adopt-backfill, already-anchored, cross-account refuse).

🤖 Generated with Claude Code


Note

Medium Risk
Changes core client provisioning and identity binding; mistakes could mint duplicates or mishandle cross-account clusters, though the new path is fail-closed and covered by targeted tests.

Overview
Fixes orphaned mint on legacy fleets: when a tracebloc client is already running but the backend cluster_id is empty, tracebloc client create now adopts that client instead of POSTing a duplicate.

API adds authenticated PATCH (bodyRequest shared with POST) and PatchClientClusterID to stamp cluster_id on /edge-device/{id}/, with 409/403 as typed APIErrors.

Cluster adds DiscoverInClusterClient: find the jobs-manager namespace via chart labels, read CLIENT_ID from the release secrets (ignoring node-agents mirrors).

client create runs R7 before mint: discover live client, fail closed if a client is live but account list fails, refuse cross-account adopt, PATCH backfill when anchor is null, or adopt when already anchored; only then fall through to the existing mint/get-or-create path. Adopt output still uses TRACEBLOC_CLIENT_ADOPTED and no new password.

Reviewed by Cursor Bugbot for commit 73d6155. Bugbot is set up for automated code reviews on this repo. Configure here.

…n't mint an orphan

On an existing-fleet box a live tracebloc client whose backend cluster_id is
still null (installed before the anchor shipped) was re-provisioned by
`client create` as a fresh mint: the freshly-read kube-system UID matched no
client, so the backend minted a new one and stamped the anchor on it, stranding
the live client. This is the RFC-0001 §7.2 / R7 case the create flow explicitly
deferred; it's the root cause behind the installer band-aid in
tracebloc/client#303 (PR #305).

The backend already ships everything (backend#883/#893): cluster_id get-or-create
and a PATCH adopt-backfill. This wires the CLI half:

- api: PatchClientClusterID → PATCH /edge-device/{id}/ {cluster_id}; 409/403
  surface as typed APIError.
- cluster: DiscoverInClusterClient(ID) reads the live CLIENT_ID from the chart's
  <release>-secrets Secret, located by the chart labels in the jobs-manager
  namespace (best-effort, time-bounded like ClusterID).
- client create: before minting, if a client is live on this cluster and the
  anchor is readable, confirm the signed-in account owns it (by UUID username),
  PATCH-backfill the anchor onto it, and adopt it — no mint. A live client not in
  the account is refused (cross-account, R6); ownership that can't be verified
  (list failed) fails closed rather than mint over it.

Fresh machines and already-anchored re-runs are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor

👋 Heads-up — Code review queue is at 34 / 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.)

@saadqbal saadqbal self-assigned this Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants