Skip to content

feat(roles): jc roles command group [Phase 1] - #96

Merged
jklaassenjc merged 4 commits into
mainfrom
juergen/roles-cmd
Jul 31, 2026
Merged

feat(roles): jc roles command group [Phase 1]#96
jklaassenjc merged 4 commits into
mainfrom
juergen/roles-cmd

Conversation

@jklaassenjc

@jklaassenjc jklaassenjc commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Phase 1 continued — closes the Roles gap. Stacked on #95 (service-accounts); merge #94#95 → this in order.

Roles (V2) had no CLI presence. A role is a named set of API scopes gating what an admin or service account can do — synergistic with jc service-accounts create --role, which already resolves a role via the /roles endpoint wired in #95.

Commands

jc roles list | get | create | update | delete

  • create: --name, --scopes (comma-separated), --description.
  • update: read-modify-write — the role PUT is a full-object replace (name+scopes required), so a partial change preserves the rest and strips the server-managed id (same guard as KLA-484).
  • delete: confirmation-gated.

Wire contracts — verified live (2026-07-24)

/roles list wrapped in {results} (ResponseKey); single GET bare; id in id.

Testing

  • Live-verified: list, get-by-name (Administrator, 69 scopes).
  • Unit-tested: create body, --scopes split/trim + empty-scope validation, the RMW update preserving scopes/description on a name-only change (+ id stripped), delete path. Full go test -race ./... + go vet green.
  • Also hardens the service-accounts tests to disable the resolve cache (a dev-populated on-disk cache entry could otherwise leak into name resolution — surfaced here).

Coverage

Scorecard: 73% → 74% area-level (gap 171 → 166 ops).

Tracked under KLA-485.

🤖 Generated with Claude Code


Note

Medium Risk
New destructive RBAC commands can remove roles and strip scopes from admins/service accounts; update/delete paths are guarded with confirmation, plan mode, and RMW tests, but mistakes still have real access impact.

Overview
Adds a new jc roles command group under Security & Policies for JumpCloud V2 RBAC roles (named API scope sets used by admins and service accounts).

list, get, create, update, and delete call /roles with list pagination via results, name-or-ID resolution, and shell completion. Create takes --name, comma-separated --scopes, and optional --description. Update does read-modify-write because the API PUT replaces the whole object—partial flags preserve other fields and drop server id. Delete supports batch sources, --plan, and interactive confirmation (with --force).

Registers mutation classes for all role subcommands, maps Roles in api-coverage.py, and refreshes the scorecard (73% → 74% area coverage). Adds HTTP tests for list/create/update/delete and --plan no-mutation; service-account tests now disable the resolve cache to avoid flaky name resolution.

Reviewed by Cursor Bugbot for commit 85e0509. Bugbot is set up for automated code reviews on this repo. Configure here.

Closes the Roles gap (V2): RBAC scope sets that gate what admins and
service accounts can do. Synergistic with service-accounts, which already
resolves a role via /roles (RoleConfig).

Commands: list, get, create, update, delete.
  - create: --name, --scopes (comma-separated), --description.
  - update: read-modify-write (the role PUT is a full-object replace with
    name+scopes required), so a partial change preserves the rest and
    strips the server-managed id — same guard as KLA-484.
  - delete: confirmation-gated.

Wire contracts verified live (2026-07-24): /roles list is wrapped in
{results} (ResponseKey), single GET is bare, id in "id". list + get-by-name
live-verified (Administrator, 69 scopes); create/update/delete unit-tested
against the confirmed shapes, incl. the RMW preserving scopes/description on
a name-only update.

Also hardens the service-accounts tests to disable the resolve cache so
name resolution can't pick up a dev-populated on-disk cache entry
(surfaced when live-verifying roles).

Coverage scorecard: 73% → 74% area-level (gap 171 → 166 ops).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit abc1c78. Configure here.

Comment thread internal/cmd/roles.go
jklaassenjc pushed a commit that referenced this pull request Jul 24, 2026
…gbot, #96 finding applies here too)

Bugbot flagged this on roles; the same bug is in service-accounts — I
mirrored iplists but dropped its plan-mode blocks. create/delete/rotate/
revoke never checked viper "plan", so --plan (and the dangerous
--force --plan) executed for real instead of previewing. Each mutation now
returns a plan.Plan preview under --plan, matching iplists. Regression test
asserts create --plan makes no POST and returns ExitError(10).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jklaassenjc pushed a commit that referenced this pull request Jul 24, 2026
…gbot, #96 finding applies here too)

Bugbot flagged this on roles; the same bug is in service-accounts — I
mirrored iplists but dropped its plan-mode blocks. create/delete/rotate/
revoke never checked viper "plan", so --plan (and the dangerous
--force --plan) executed for real instead of previewing. Each mutation now
returns a plan.Plan preview under --plan, matching iplists. Regression test
asserts create --plan makes no POST and returns ExitError(10).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
juergen-kc and others added 2 commits July 24, 2026 16:19
runRolesCreate/Update/Delete never checked viper "plan", so --plan (and
--force --plan) executed instead of previewing — with delete removing the
role. Each mutation now returns a plan.Plan preview under --plan, matching
iplists. Regression test asserts create --plan makes no POST and returns
ExitError(10).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jtaylorjc
jtaylorjc previously approved these changes Jul 24, 2026
Base automatically changed from juergen/service-accounts-cmd to main July 26, 2026 19:08
@jklaassenjc
jklaassenjc dismissed jtaylorjc’s stale review July 26, 2026 19:08

The base branch was changed.

@jklaassenjc jklaassenjc reopened this Jul 26, 2026
@jklaassenjc
jklaassenjc merged commit d58bd49 into main Jul 31, 2026
8 checks passed
@jklaassenjc
jklaassenjc deleted the juergen/roles-cmd branch July 31, 2026 15:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

4 participants