feat: align the CLI with the current cloud API and expose its full surface#85
Merged
Conversation
…rface
A route-by-route audit against the cloud /v1 API found silent breakage
and a season of server capabilities with no CLI exposure. This aligns
everything and verifies it call site by call site (70 total).
Fixes:
- org rules permissions get printed zero-valued garbage: the server
moved to the layered {defaults, byAgent} shape; the CLI now decodes
it (with a flat-shape fallback for older servers)
- apps configure only ever sent clientId/clientSecret, silently saving
nothing for github-app; it now sends arbitrary --field key=value
pairs (or --json), validated server-side per app
- rule actions manual_approval and allow were rejected client-side and
conditions could not be sent at all; both supported now
- rules update decoded {success:true} into an empty rule; it now
re-fetches and prints the real rule (incl. conditions and metadata)
- server error envelopes ({error:{message,type}}) were unreadable -
messages surfaced now; 403 maps to exit code 5 (documented)
- --project resolved nothing server-side: the CLI now resolves
slug->id and sends X-Project-Id (plus legacy ?projectId=); NOTE the
cloud only honors the header for org keys today - server follow-up
filed to honor it for project keys
- org rules create/update --agent-id was silently discarded by the
server (org rules are agent-less); the flags are gone and JSON
payloads carrying agentId fail loudly
- response decodes no longer drop fields agents need: rule metadata,
secret valueSource/opRef/scope, connection scope, project apiKey
(returned exactly once at create and previously lost), app config
settings, credential stubs, path-injection configs
Connections move to the top-level /v1/connections resource via a
probe-once fallback (older deployments keep working on the legacy
/v1/apps/connections paths); /v1/org/connections is used directly.
New commands: rules permissions get/set (with --agent-id and the
inherit setting), rules overlap (both scopes), apps
permission-definition, apps connections list/rename, apps config
get/toggle, apps configured/env-defaults, apps blocklist (both
scopes), agents set-default/granular-access/connections get/set,
org connections rename, org settings get/set, vaults list, counts,
auth update. The machine-readable help catalog covers all of them.
BREAKING (output shape): org rules permissions get now prints the
layered object; the previous output was unusable zero-values.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What
Aligns the CLI with the current cloud
/v1API — fixing every silent-breakage found by a deep drift audit — and exposes the full API surface as commands, verified route by route across all 70 call sites.Silent breakage fixed
org rules permissions getprinted zero-valued garbage — the server's layered{defaults, byAgent}shape is now decoded (with a flat-shape fallback so older servers are never silently empty either).apps configuresilently saved nothing forgithub-app— the hardcodedclientId/clientSecretstruct is replaced by repeatable--field key=value+--json(the old flags remain as OAuth sugar); dry-run previews mask all values.manual_approval/allowaccepted;--conditions(JSON array,keyfield included) on create/update,'[]'clears.rules updateprinted an all-empty rule — PATCH-then-re-fetch now prints the real rule.{error:{message,type}}envelope is parsed (then flat, then status text); 403 → exit code 5 = forbidden, documented in the agent-facing skill + CLAUDE.md.--projectwas a silent no-op — the CLI resolves slug→id via/v1/projectsand sendsX-Project-Id(keeping the legacy?projectId=for old/apiservers), passing values through as-is when unresolvable so bad selections fail loudly.org rules create/update --agent-idsilently discarded (org rules are agent-less server-side) — flags removed;--jsonpayloads carryingagentIdfail loudly with a pointer to the project command.metadata(distinguish app-permission rows), secretvalueSource/opRef/scope/metadata+ path-injection configs + 1Password fields in--jsoninputs, connectionscope(both scopes), appcredentialStubs, org configsettings, and projectapiKey— returned exactly once at create and previously lost unrecoverably.Connections migration (backward compatible)
Project connections move to the top-level
GET/PATCH/DELETE /v1/connections(?provider=filter, bare array) via a probe-once fallback mirroring the existing/v1-vs-/apiprefix probe — older deployments transparently keep using the byte-stable legacy paths. Org connections use/v1/org/connectionsdirectly (served by every deployed server).apps list/getadopt theconnections[]multi-account array.New capabilities (everything the API serves)
rules permissions get/set(project,--agent-id+inherit),rules overlap(both scopes),apps permission-definition(tool catalog),apps connections list/rename,apps config get/toggle,apps configured/env-defaults,apps blocklist×5 (both scopes),agents set-default/granular-access/connections get/set,org connections rename,org settings get/set,vaults list,counts,auth update. All follow the agent-first contract (--dry-run/--fields/--quiet, JSON-only stdout) and are in the machine-readableonecli helpcatalog (which also had its stale entries corrected).Deliberately excluded (with reason)
Browser OAuth flows (
authorize/callback/connect— popup redirects),gateway-url/gateway/ca(the CLI receives the CA insidecontainer-config), agentlesscredential-stubsvariant, and all cookie-gated web surfaces (session, billing, team, onboarding, partner, internal).Breaking (output shape)
org rules permissions getoutput changes from a flat map to the layered{defaults, byAgent}object. The previous output was unusable zero-values (silently broken since the server-side shape change), so this is a bug fix in contract clothing.Cloud-side follow-ups (filed, not in this repo)
X-Project-Idfor project keys: the cloud honors the header only for org keys; project keys always scope to their bound project. Until a small server change honors it (via the existingcanAccessProjectAsUsercheck),--projectis fully effective only for org-key callers — never silent, though: unresolvable selections now fail loudly.rules updatecannot clearmethod(schema accepts onlynull, whichomitemptycan't emit) — server should accept""like it does forpathPattern.Verification
go build/go vet/go test ./...(+-raceon api and cmd) /golangci-lint run→ all green, 0 lint issues.=-containing field values, both enum tables.auth update); (b) correctness — an exhaustive 70-call-site matrix, field-by-field against the zod schemas and response selects (including the untouched secrets/projects/user/run surfaces): 66 byte-exact, the rest fixed above.Review
Full pipeline (understand → plan approval → implement → review → route-by-route double-check). Skills: ~43 enumerated across both repos, 5 applied — the repo's own
agent-first-cli(help-catalog fix + dry-run/fields/quiet contracts),golang-patterns+golang-proread in full and walked as checklists (doc-comments fix; error-wrapping/context/receivers/zero-value/no-goroutine rules verified item by item),security-review(masked previews, no secret echo),simplify(shared blocklist runners, shared field builder). Process: three adversarial agents — deep drift audit (57 tool calls), Go-idioms + contract review (71 calls), and the final exhaustive alignment matrix (64 calls) — plus hunk-level self-review. Findings → fixes: 21 total across all passes. Gates green throughout.🤖 Generated with Claude Code