refactor(control-plane): resolve names server-side, drop client-side filtering · Entire
refactor(control-plane): resolve names server-side, drop client-side filtering
7144c12→main·
toothbrush·3w ago·3 files·+111 added/-215 removed
The control plane now does O(1), case-insensitive by-name lookups for orgs, projects, and org-scoped projects (lower(name) indexes). Delegate to it and delete the CLI's "list everything then filter" code.
- regenerate coreapi client: ListOrgs gains a name param + singular
orgin its response; GET /orgs/{orgId}/projects gains a name param + singularproject(spec hand-authored ahead of deploy; idempotent on real refresh) - resolveOrgRef/resolveProjectRef read the singular match the server returns and map 404 to a friendly "no X named" error
- project list --org --name now filters server-side instead of client-side
- drop pickOrg, pickProject, filterProjectsByName
Also fixes a latent bug: the name paths read out.Projects, but the server returns a name match under the singular out.Project, so an existing project resolved as "not found". Now reads the correct field.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Sessions
bb17fef4a163View transcript
Changes
3
cmd/entire/cli
Mproject.go+23/-7
Mresolveref.go+48/-76
Mresolveref_test.go+40/-132
92 unmodified lines
1 unmodified line
Code Block
// many places (repo create --project, project create --owner, grant org/project
// <id>, …). ULIDs are unfriendly to type, so these refs also accept a human
// name: looksLikeULID decides which form was given, and the resolveXRef helpers
// turn a name into its ULID via a list lookup. A ULID is always passed straight
// through with no network call, preserving the original behavior exactly.
// turn a name into its ULID. A ULID is always passed straight through with no
// network call. A name is resolved by the control plane's O(1), case-insensitive
// by-name lookup (the server matches on lower(name) and returns the single match
// under the response's singular `org`/`project` field, or 404) — the CLI never
// lists everything and filters client-side.
Function Definitions
isCoreNotFound
// isCoreNotFound reports whether err is a control-plane 404. The by-name lookups
// (ListOrgs/ListProjects/ListOrgProjects with ?name=) return 404 when nothing
// matches; callers turn that into a friendly "no X named" message.
func isCoreNotFound(err error) bool {
var se *coreapi.ErrorModelStatusCode
return errors.As(err, &se) && se.StatusCode == http.StatusNotFound
}
resolveOrgRef
// resolveOrgRef turns an org reference (ULID or name) into its ULID. A ULID is
// returned unchanged; a name is looked up against the caller's visible orgs.
// returned unchanged; a name is resolved via the server's case-insensitive
// by-name lookup.
func resolveOrgRef(ctx context.Context, c *coreapi.Client, ref string) (string, error) {
if looksLikeULID(ref) {
return ref, nil
}
out, err := c.ListOrgs(ctx)
out, err := c.ListOrgs(ctx, coreapi.ListOrgsParams{Name: coreapi.NewOptString(ref)})
if err != nil {
if isCoreNotFound(err) {
return "", noOrgNamedErr(ref)
}
return "", err
}
return pickOrg(out.Orgs, ref)
org, ok := out.Org.Get()
if !ok {
return "", noOrgNamedErr(ref)
}
return org.ID, nil
}
resolveProjectRef
// resolveProjectRef turns a project reference (ULID or name) into its ULID. A
// ULID is returned unchanged; a name is looked up via the server's name filter
// (the same call `entire project list --name` uses). Name matching is
// case-insensitive end to end: the server enforces lower(name) uniqueness and
// pickProject re-checks with EqualFold, so case-only differences resolve.
func resolveProjectRef(ctx context.Context, c *coreapi.Client, ref string) (string, error) {
if looksLikeULID(ref) {
return ref, nil
}
out, err := c.ListProjects(ctx, coreapi.ListProjectsParams{Name: coreapi.NewOptString(ref)})
if err != nil {
if isCoreNotFound(err) {
return "", noProjectNamedErr(ref)
}
return "", err
}
return pickProject(out.Projects, ref)
project, ok := out.Project.Get()
if !ok {
return "", noProjectNamedErr(ref)
}
return project.ID, nil
}
Testing Functions
// TestResolveOrgRef tests the resolveOrgRef function
func TestResolveOrgRef(t *testing.T) {
// Test implementation
}
// TestResolveProjectRef tests the resolveProjectRef function
func TestResolveProjectRef(t *testing.T) {
// Test implementation
}