Skip to content

feat: manage permissions and organization roles from the CLI - #356

Merged
Bccorb merged 1 commit into
mainfrom
feat/permission-commands
Nov 7, 2026
Merged

Bccorb merged 1 commit into
mainfrom
feat/permission-commands

Conversation

@Bccorb

@Bccorb Bccorb commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Needs auth API v0.23. Every command here calls routes that first ship in seamless-auth-api v0.23.0, which is not released yet. Against v0.22 and earlier each command exits 1 with "This instance has no permission catalogue. Permissions and organization roles need Seamless Auth API v0.23 or later." Merge before or after the API release; publishing the CLI first is safe for that reason.

Part of #343 (roles and permissions; webhooks and hooks are still open there).

What

Two new instance-management commands, both with --json:

seamless permissions list | create <name> [--description] | update <name> (--description | --no-description) | delete <name> [--force]
seamless roles list [--kind instance|organization]
seamless roles set <instance|organization> <role> (<permission>... | --none) [--force]
seamless roles create <name> [--description] [--permissions a,b]   # organization role
seamless roles update <name> (--description | --no-description)
seamless roles delete <name> [--force]

Routes: GET/POST /admin/permissions, PATCH/DELETE /admin/permissions/:permissionName, GET /admin/roles, PUT /admin/roles/:kind/:roleName/permissions, POST /admin/organization-roles, PATCH/DELETE /admin/organization-roles/:roleName.

How

  • The client functions live in src/core/admin.ts, next to the other admin wrappers. They use call(), so writes get the existing step-up retry and a 403 still goes through forbidden(). Responses are parsed with loosened @seamless-auth/types 0.38.0 schemas/permission schemas.
  • Telling v0.22 apart from a missing record. An instance without these routes answers with the app's catch-all { "error": "Not Found" }. A missing permission or role on v0.23 is also a 404, but it names what was missing (Permission not found, Role not found). Collection routes treat any 404 as a missing route; per-name routes look at the body.
  • roles set replaces the whole mapping, like the API. It reads the current mapping first and asks before taking a permission away (non-interactive runs need --force). Adding permissions does not ask.
  • The details on a 400 or 409 are added to the error message, for example Could not delete permission invoices:write (409: Permission is still granted by a role), roles: organization role billing.
  • Names are checked against PermissionNameSchema before the request, with a readable message instead of the raw regex.
  • fail, positionals and validate are moved into adminShared.ts for the new commands. resources.ts keeps its own copies for now.
  • Help topics (seamless help permissions, seamless help roles), README, the AGENTS.md command list, and a minor changeset are included. No config keys changed, so WRITABLE_KEYS is untouched.

Verification

  • npm run coverage (the pre-commit hook): 1994 passed, 28 skipped. Lines 99.24%, branches 96.54%, above the floor. npm run build passes.
  • Live against seamless-auth-api origin/main (bed4994), built into an image and run with its docker-compose.yml. I registered an owner, enrolled TOTP, signed in with the CLI's own completeLogin, then ran the real runPermissions and runRoles. Every write needed a step-up through SEAMLESS_TOTP_CODE and passed. Checked: create, the duplicate 409, update and its 404, list, organization role create, roles set on both kinds, an unknown role 404, an unknown permission 400, delete refused while a role grants it (names the role), the built-in role refusal, delete, and --json output.
  • Live against the published ghcr.io/fells-code/seamless-auth-api:v0.22.0: all nine subcommands exit 1 with the v0.23 message above.

Not covered: there is no committed e2e test for these commands. The live run was a one-off harness, because the admin and TOTP bootstrap it needs is not in the repo's gated e2e.

…ions and seamless roles

Wraps the auth API v0.23 permission catalogue, organization role catalogue
and role to permission mappings. roles set replaces a role's whole mapping
and asks before taking a permission away. An instance before v0.23 answers
with a message naming the release it needs.

Part of #343
@Bccorb Bccorb added this to the v0.23 milestone Nov 7, 2026
@Bccorb
Bccorb merged commit 2eb878e into main Nov 7, 2026
6 checks passed
@Bccorb
Bccorb deleted the feat/permission-commands branch November 8, 2026 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant