Skip to content

fix(#303): refuse a second client before minting, so we don't orphan one#306

Merged
saadqbal merged 4 commits into
developfrom
fix/client-303-preflight-ownership
Jul 6, 2026
Merged

fix(#303): refuse a second client before minting, so we don't orphan one#306
saadqbal merged 4 commits into
developfrom
fix/client-303-preflight-ownership

Conversation

@saadqbal

@saadqbal saadqbal commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Closes #303.

On the browser path, client create mints a fresh client whenever the backend can't match this cluster to a client in the signed-in account (pre-anchor null cluster_id, or a different account owns it). The one-client guard only ran later in the Helm step, so it refused after a new client was already registered on the dashboard — an orphan that never installs.

Adds a pre-flight in provision_client, after sign-in and before the mint: if a client is already installed here (shared detect_installed_client probe, now also backing the Helm guard) and the signed-in account demonstrably does not own its namespace (via client list), refuse before calling create.

Namespace is the only stable join key (local Helm stores the UUID clientId; client list shows the numeric id). Fires only on a positive "not yours" — a fresh machine, an owned local client (create adopts), or an inconclusive list read all fall through to create's own idempotent adopt/conflict handling, so the same-account re-run/upgrade path is unchanged.

Tests: 3 new provision.bats cases (refuse foreign / adopt same-account / fall-through on unreadable list); guard refactor keeps install-client-helm.bats green.

Note: the proper root-cause fix is the deferred R7 "existing-fleet reconcile" (backfill the null cluster_id and adopt the live in-cluster client instead of minting) — this PR stops the orphan without that larger CLI+backend change.

🤖 Generated with Claude Code


Note

Medium Risk
Changes browser provisioning order and ownership heuristics (namespace vs legacy tracebloc); wrong refusal or fall-through could block valid reinstalls or still allow orphans, though bats cover the main paths.

Overview
Stops orphan dashboard clients when someone signs into a different account on a machine that already has a tracebloc Helm client. The browser path used to call client create before the Helm one-client guard, so a new client could be registered even though install would later refuse.

Shared local probe: detect_installed_client in install-client-helm.sh centralizes jq-free Helm enumeration; both the new pre-flight and the existing Helm guard use it so they agree on what is installed.

Pre-provision check in provision_client (after login, before mint): _account_owns_namespace matches the local release namespace against tracebloc client list. It refuses only when the list read succeeds and the namespace is missing—except for the legacy fixed tracebloc namespace, where list skew defers to client create and the Helm clientId guard. Fresh machines, owned clients, and failed list reads still fall through to create as before.

Tests: provision.bats stubs the probe and adds cases for foreign-client refusal, same-account adopt, inconclusive list, and legacy namespace deferral. Manifest checksums updated.

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

…rphan one

On the browser path, `tracebloc client create` mints a fresh client whenever
the backend can't match this cluster to a client in the signed-in account —
e.g. a pre-anchor client whose cluster_id is still null, or one owned by a
different account. The one-client-per-machine guard only ran later, in the
Helm step, so by the time it refused, a brand-new client was already
registered on the dashboard and would never install — an orphan (#303).

Add a pre-flight in provision_client, after sign-in and before the mint: if a
client is already installed locally (shared detect_installed_client probe,
now also used by the Helm guard) and the signed-in account demonstrably does
NOT own its namespace (via `client list`), refuse before calling create.

Namespace is the only stable join key — the local Helm release stores the UUID
clientId, `client list` shows the numeric id. The pre-flight fires only on a
positive "not yours"; a fresh machine, an owned local client (create adopts),
or an inconclusive list read all fall through to create's own idempotent
adopt/conflict handling, so the same-account re-run/upgrade path is unchanged.

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

Copy link
Copy Markdown
Contributor

👋 Heads-up — Code review queue is at 33 / 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 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

This is the interim band-aid; the real fix is R7 in tracebloc/cli#132, now merged to CLI develop but not yet released. The installer pulls the latest CLI release (still v0.5.1, pre-R7), so orphans are still possible until an R7 release ships — keep this merged as protection until then. Follow-up: drop this pre-flight once the R7 CLI is released and dev/prod run backend #893. The install-client-helm one-client guard stays as the backstop regardless.

…pre-flight

install-client-helm.sh + provision.sh changed; refresh the R8 signed-manifest
checksums so gen-manifest.sh --check passes.

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

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ef1560a. Configure here.

Comment thread scripts/lib/provision.sh
aptracebloc
aptracebloc previously approved these changes Jul 6, 2026
… account owns (Bugbot)

The pre-flight keyed ownership on the local Helm release namespace via
`client list`. But a client installed under the legacy fixed `tracebloc`
namespace is listed on the dashboard under its minted slug, so `client list`
never shows `tracebloc` even for the account's OWN older client — a skew
install_client_helm reconciles by clientId (the reliable key `client list`
doesn't expose). The namespace-only check wrongly refused that valid re-run.

Refuse only when the absent namespace is a non-legacy slug (confident foreign);
for `tracebloc`, defer to `client create` (adopts if it's yours, 409s if truly
cross-account) and the Helm-step one-client guard, which both key on clientId.

Regenerates manifest.sha256 for the provision.sh change (R8).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…flight-ownership

# Conflicts:
#	scripts/manifest.sha256
@saadqbal saadqbal self-assigned this Jul 6, 2026
@saadqbal saadqbal merged commit cb59910 into develop Jul 6, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants