# fix(control-plane): show resolved ULID in delete success messages

`fc2ac04`  
  
toothbrush·3w ago·5 files·+45 added/-3 removed

org/project/repo delete echoed the user-supplied arg, so a name-based delete confirmed a name while the operation used the resolved ULID — ambiguous where names are reused. Add resolvedRefLabel to render "name (ULID)" for names and the bare ULID otherwise.

Addresses trail #642 finding.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

## Sessions

c14749e12a9d View transcript

## Changes

5

- cmd/entire/cli

- Morg.go +1/-1

- Mproject.go +1/-1

- Mrepo.go +1/-1

- Mresolveref.go +21

- Mresolveref_test.go +21

```
106 unmodified lines

107
108
109
110
110
111
112
113

106 unmodified lines

if err := c.DeleteOrg(ctx, coreapi.DeleteOrgParams{OrgId: orgID}); err != nil {
                    return err
                }
                cmd.Printf("Deleted org %s\n", args[0])
                cmd.Printf("Deleted org %s\n", resolvedRefLabel(args[0], orgID))
                return nil
            })
        },
```

Mcmd/entire/cli/org.go +1/-1

```
184 unmodified lines

185
186
187
188
188
189
190
191

184 unmodified lines

if err := c.DeleteProject(ctx, coreapi.DeleteProjectParams{ProjectId: projID}); err != nil {
                    return err
                }
                cmd.Printf("Deleted project %s\n", args[0])
                cmd.Printf("Deleted project %s\n", resolvedRefLabel(args[0], projID))
                return nil
            })
        },
```

Mcmd/entire/cli/project.go +1/-1

```
190 unmodified lines

191
192
193
194
194
195
196
197

190 unmodified lines

if err := c.DeleteRepo(ctx, coreapi.DeleteRepoParams{RepoId: repoID}); err != nil {
                    return err
                }
                cmd.Printf("Deleted repo %s\n", args[0])
                cmd.Printf("Deleted repo %s\n", resolvedRefLabel(args[0], repoID))
                return nil
            })
        },
```

Mcmd/entire/cli/repo.go +1/-1

```
1 unmodified line

2
3
4
5
6
7
8
9
10
196 unmodified lines

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

1 unmodified line

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"strings"

"github.com/entireio/cli/internal/coreapi"
196 unmodified lines

}
}

// resolvedRefLabel formats a reference for a success message so it always
// names the resolved ULID. When the user passed a ULID (ref == id) it returns
// the id alone; when they passed a name it returns "name (id)" so the message
// is unambiguous in environments where names can be reused across orgs/projects.
func resolvedRefLabel(ref, id string) string {
	if ref == id {
		return id
	}
	return fmt.Sprintf("%s (%s)", ref, id)
}

// isNotFound reports whether err is a control-plane 404. Used to make
// destructive deletes idempotent (an already-gone resource is the desired end
// state, not an error) rather than surfacing the raw problem detail.
func isNotFound(err error) bool {
	var se *coreapi.ErrorModelStatusCode
	return errors.As(err, &se) && se.StatusCode == http.StatusNotFound
}

// filterProjectsByName narrows projects to name matches, returning all of them
// when name is empty. Used by `project list --org` to apply --name client-side,
// since the org-scoped list endpoint has no name parameter. Matching is
```

Mcmd/entire/cli/resolveref.go +21

```
437 unmodified lines

438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461

437 unmodified lines

}
}

func TestResolvedRefLabel(t *testing.T) {

t.Parallel()

const id = "01J0REPO000000000000000001"

t.Run("ulid passes through", func(t *testing.T) {
		t.Parallel()
		if got := resolvedRefLabel(id, id); got != id {
				t.Errorf("got %q, want %q", got, id)
		}
	})

t.Run("name includes resolved id", func(t *testing.T) {
		t.Parallel()
		want := fmt.Sprintf("acme (%%s)", id)
		if got := resolvedRefLabel("acme", id); got != want {
				t.Errorf("got %q, want %q", got, want)
		}
	})
}
```

Mcmd/entire/cli/resolveref_test.go +21
