diff --git a/internal/cli/client.go b/internal/cli/client.go index 4277bb0..cbbbc42 100644 --- a/internal/cli/client.go +++ b/internal/cli/client.go @@ -64,7 +64,14 @@ func newClientCreateCmd() *cobra.Command { cmd := &cobra.Command{ Use: "create", Short: "Provision a tracebloc client for this machine (auto-named; no flags required)", - Args: cobra.NoArgs, + // HIDDEN: provisioning is the installer's job — provision.sh calls this with + // zero flags (cli#137). It stays fully callable (including `--help`, so the + // installer's capability probe still works), but is kept off the user-facing + // surface: a human running `client create` STANDALONE mints a client the + // installer never deploys — an orphaned "phantom" (backend#970). Mirrors the + // hidden `list`; leaves `tracebloc client` showing only the user-useful `status`. + Hidden: true, + Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { return runClientCreate(cmd.Context(), printerFor(cmd), clientPrompter(), clientCreateOpts{name: name, location: location, kubeconfigPath: kubeconfigPath, contextOverride: contextOverride, credentialFile: credentialFile, yes: yes}) diff --git a/internal/cli/client_test.go b/internal/cli/client_test.go index a721d84..eb5718d 100644 --- a/internal/cli/client_test.go +++ b/internal/cli/client_test.go @@ -1338,3 +1338,29 @@ func TestClientStatus_WaitCtrlCIsSilent(t *testing.T) { t.Errorf("Ctrl-C should exit silently (nil-inner exitError), got: %v", err) } } + +func TestClientSubcommandVisibility(t *testing.T) { + // `create` and `list` are installer-internal — Hidden so a user isn't invited to + // run them (a standalone `tracebloc client create` mints a client the installer + // never deploys, i.e. an orphaned phantom, backend#970). `status` stays + // user-visible. Hidden != disabled: all remain runnable (the installer still + // invokes create/list). + hidden := map[string]bool{} + runnable := map[string]bool{} + for _, c := range newClientCmd().Commands() { + hidden[c.Name()] = c.Hidden + runnable[c.Name()] = c.RunE != nil + } + if !hidden["create"] { + t.Error("client create must be Hidden (installer-internal; standalone mints a phantom)") + } + if !hidden["list"] { + t.Error("client list must stay Hidden") + } + if hidden["status"] { + t.Error("client status must stay user-visible") + } + if !runnable["create"] { + t.Error("hidden create must still be runnable (the installer invokes it)") + } +}