Control-plane CLI: org/project get+delete, repo grant list+remove#1499
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the generated Core API client (internal/coreapi) to consume newly added v1 endpoints (org/project get+delete, repo grant list+revoke) and wires new CLI verbs under the hidden control-plane command groups (entire org, entire project, entire grant repo). It also introduces typed/validated grant role enums (reader/writer/admin) and adds unit tests for the new resolver/flag-validation helpers.
Changes:
- Regenerate
internal/coreapifrom an updated OpenAPI spec, adding org/project get+delete and repo grant list/revoke operations, plus typed role enums. - Add new CLI verbs:
entire org get|delete,entire project get|delete,entire grant repo list|remove, and validate/cast--rolefor project/repo grants. - Add repo-name resolution helper (
resolveRepoRef) gated by--project, plus unit tests for repo picking and grant-role/grantee-mode parsing.
Reviewed changes
Copilot reviewed 8 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| internal/coreapi/spec/core.openapi.json | OpenAPI spec update adding new endpoints and role enums. |
| internal/coreapi/spec/core.gen.json | Generated schema update reflecting enum roles and new response shapes. |
| internal/coreapi/oas_validators_gen.go | Generated validators updated for typed role enums + new output bodies. |
| internal/coreapi/oas_security_gen.go | Generated auth/role maps updated for new operations. |
| internal/coreapi/oas_schemas_gen.go | Generated Go types updated (typed roles; new request/response structs). |
| internal/coreapi/oas_response_decoders_gen.go | Generated HTTP response decoders added for new endpoints. |
| internal/coreapi/oas_parameters_gen.go | Generated parameter structs added for new endpoints. |
| internal/coreapi/oas_operations_gen.go | Generated operation constants added for new endpoints. |
| internal/coreapi/oas_json_gen.go | Generated JSON encode/decode updated for typed roles and new schemas. |
| cmd/entire/cli/resolveref.go | Add resolveRepoRef/pickRepo to resolve repo names with --project scope. |
| cmd/entire/cli/resolveref_test.go | Unit tests for pickRepo (plus existing resolver helper coverage). |
| cmd/entire/cli/repo.go | Repo get/delete now accept name-or-ULID with optional --project for name resolution. |
| cmd/entire/cli/project.go | Add project get and project delete commands using name/ULID resolution. |
| cmd/entire/cli/org.go | Add org get and org delete commands using name/ULID resolution. |
| cmd/entire/cli/grant.go | Validate/cast grant roles; add grant repo list/remove; reuse repo resolution with --project. |
| cmd/entire/cli/grant_test.go | Unit tests for validateGrantRole and parseGranteeMode rename/behavior. |
Files not reviewed (7)
- internal/coreapi/oas_json_gen.go: Generated file
- internal/coreapi/oas_operations_gen.go: Generated file
- internal/coreapi/oas_parameters_gen.go: Generated file
- internal/coreapi/oas_response_decoders_gen.go: Generated file
- internal/coreapi/oas_schemas_gen.go: Generated file
- internal/coreapi/oas_security_gen.go: Generated file
- internal/coreapi/oas_validators_gen.go: Generated file
7dc26c0 to
41bc806
Compare
d08809d to
789678d
Compare
2749cb4 to
2d4b58a
Compare
415781c to
d7a7ef2
Compare
2d4b58a to
d2eac6d
Compare
d7a7ef2 to
7144c12
Compare
#2122 made the v1 grant role a validated enum (reader/writer/admin), so the regenerated client types GrantProjectAccess/GrantRepoAccess Role fields as enums rather than string. Validate --role at the CLI boundary and cast to the typed value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: e9918e472c9d
…emove Consume the v1 CRUD-gap endpoints (entiredb #2122): - entire org get|delete <name|ULID> - entire project get|delete <name|ULID> - entire grant repo list <repo> - entire grant repo remove <repo> (--provider/--provider-user-id or --grantee-type/--grantee-id) Org/project args resolve friendly names via the shared resolveref helpers. The grantee-mode helper (renamed parseGranteeMode) and the provider/by-id remove form are now shared by project and repo. Repo args stay ULID-only for now — resolving a repo by name needs a project scope. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: a995fb3417fb
repo get/delete and grant repo add/list/remove now accept a repo name (not just a ULID) when --project <name|ULID> is given to scope the lookup — repo names are unique only within a project. A ULID still passes through unchanged and ignores --project. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: ab8e423ff72f
entire-core's v1 list endpoints now return keyset pages (limit/cursor +
nextCursor) and cap page size at 50, and orgs/repos gained O(1) ?name=
lookups. Regenerate the client against the refreshed spec and update the
consumers:
- fetchAllPages: a cursor-following helper; every list command (org/
project/repo list, grant org/project/repo list) now walks all pages
instead of silently showing only the first 50.
- resolveOrgRef/resolveRepoRef: resolve names via the server's O(1)
?name= lookup (single org/repo response) rather than listing+scanning,
which would now miss a target past page 1.
- resolveProjectRef and `project list --name`: read the single `project`
field the ?name= response actually returns (was reading the empty
`projects` list — a latent miss).
- drop the now-unused client-side pickOrg/pickProject/pickRepo matchers.
Spec refreshed from entiredb main (also narrows grant granteeType to
account-only, already enforced server-side).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
entire-core renamed the v1 list pagination params to match the data-plane convention (cursor → pageToken, nextCursor → nextPageToken). Regenerate the client and follow suit in the page-walking call sites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
COR-583 paginates the remaining v1 list endpoints on the same PageInput/PageMeta dialect. Of those, the CLI consumes only ListMirrors: wrap `repo mirror list` in fetchAllPages so it walks every page instead of showing the first 50. Regenerate the client against the refreshed spec (audit/oidc-providers/service-accounts/bindings/lookup-resources gain pagination too, but no CLI command consumes them yet). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…, parallel tests)
- grant {project,repo} add: the control plane (and the regenerated client
enum) accept only granteeType=account now (org/team granting was dropped
server-side, COR-561). Validate --grantee-type at the CLI with a clear
message instead of an opaque enum-encoding error, and correct the
flag/Long help that still advertised org/team (add + revoke).
- fetchAllPages: drop the hard-coded "max 200" from the doc comment; the
server caps page size and may cap further, so phrase it generically.
- resolver tests: add t.Parallel() to match the file's convention (each
builds its own httptest server; no shared global state).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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> Entire-Checkpoint: c14749e12a9d
org/project/repo delete called the destructive API immediately after resolving the ref — a name typo that resolves to a real resource (or a wrong-but-valid ULID) deleted silently. Gate each behind a confirmation prompt (the existing trail-delete pattern) with a --force/-f bypass and --yes/-y alias; non-interactive runs refuse without --force rather than deleting unprompted. Shared body extracted to runControlPlaneDelete. Addresses trail #642 finding. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 5201fa5dc67c
- org/project/repo delete now treat a 404 from the delete call as the desired end state (already gone), printing "<noun> <label> not found; nothing to delete" instead of surfacing a raw 404. - Add command-level tests driving each delete command through cobra against a fake control plane: --force issues DELETE on the right path, an already-gone resource is idempotent, and a non-interactive run without --force refuses rather than deleting unprompted. Addresses trail #642 findings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: 416181183067
…solver Rebased onto feat/control-plane-friendly-names, which had independently reworked name resolution to the client-side pickOrg/pickProject design. Kept that resolver and dropped crud-gaps' server-side ?name= variant; this pass adapts the seams: - resolveOrgRef walks all pages (ListOrgs is now paginated) then pickOrg - restore isNotFound + resolvedRefLabel helpers used by the delete commands - writeNotFoundProblem test helper (friendly-names' resolver tests lack it) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Entire-Checkpoint: ae2378c10239
Entire-Checkpoint: ccbb08235fc2
Two gaps in the grant revoke surface:
- Revoking an already-revoked grantee surfaced a raw 404. RemoveOrgMember,
RevokeProjectAccess(ByProvider), and RevokeRepoAccess(ByProvider) now route
through a shared revokeGrant helper that treats 404 as a no-op ("no such
grant; nothing to revoke"), matching runControlPlaneDelete's idempotency.
- The grantee-mode -> route selection had no command-level coverage (only pure
helpers were tested). Add TestGrantRemove_RouteWiring asserting
--provider/--provider-user-id hits the by-provider route and
--grantee-type/--grantee-id hits the typed-id route, across org/project/repo;
plus TestGrantRemove_Idempotent for the 404-as-no-op behavior.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 7504c7424c52
ae3b21b to
827fc6c
Compare
Soph
approved these changes
Jun 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
https://entire.io/gh/entireio/cli/trails/642
Fill the control-plane CLI CRUD gaps (COR-561) and page through the v1 list endpoints (COR-580/583). Stacked on
feat/control-plane-friendly-names— merge that first.New verbs
entire org get|delete <name|ULID>entire project get|delete <name|ULID>entire grant repo list <repo>entire grant repo remove <repo>—--provider/--provider-user-idor--grantee-type/--grantee-idSafer deletes
org|project|repo deleteprompt before deleting (skip with--force/-f, alias--yes/-y); non-interactive runs refuse without--forceinstead of deleting unprompted. Deleting an already-gone resource is a no-op, not a raw 404. Success messages name the resolved ULID, e.g.Deleted org acme (01J…).Pagination
List commands walk every page instead of returning only the first:
org/project/repo list, thegrant … listcommands, andrepo mirror list(COR-583).Friendly-name resolution
org,project, andrepoargs accept a name or a ULID. Names resolve through the base branch's server-side, O(1), case-insensitive by-name lookups; a ULID passes through with no network call. Repo names require--project <name|ULID>scope (repo names are unique only within a project). Applies torepo get/deleteandgrant repo add/list/remove.Grant roles
grant org addvalidates--role(owner/admin/member);grant project|repo addvalidates--role(reader/writer/admin) against the typed enum from the base branch. The Core API client itself is regenerated on the base branch, so there is nointernal/coreapichurn here.Verified:
mise run fmt/lintclean;cmd/entire/cliunit tests green (integration + E2E canary via CI).