Skip to main content

CLI

IAM, Members, Teams, and Roles

Use these commands to control what each person and team in your organization can do. An IAM policy lists allowed or denied actions. A role groups policies. You give a role to a user or a team.

Command groupManagesAPI path
verdictan iam policyIAM policies with one statement each/v1/policies
verdictan roleRoles and the policies attached to them/v1/roles
verdictan userOrganization members, invitations, and user role assignments/v1/users, /v1/invitations
verdictan teamTeams, team members, and team role assignments/v1/teams

Give a role to a team when two or more people need the same access. Give a role to a user for individual access. For a complete design example, read Roles and IAM Policies.

Before you start​

  • Set VERDICTAN_API_TOKEN, or sign in with verdictan auth login.

  • Get the permissions for the commands you run:

    CommandsPermissions
    iam policy list, iam policy getpolicies:read
    role list, get, show-actions, show-assignmentsroles:read
    role create, update, delete, attach-policy, detach-policyroles:write
    user list, user getusers:read
    user inviteusers:invite
    user update, suspend, reactivate, remove-membershipusers:manage
    user assign-role, user detach-roleroles:assign and users:manage
    team list, team get, team list-membersteams:read
    team create, update, delete, add-member, remove-memberteams:manage
    team assign-role, team detach-roleroles:assign and teams:manage
  • user and team changes need a credential that belongs to a user. A credential without a user gets HTTP 403 with auth.user_required.

  • Policy, role, user, and team IDs are UUIDs. Copy them from the list commands.

Each command accepts --json, --config <path>, --api-url <url>, --profile <name> (default default), and --region <region>. The option tables below list only the command-specific flags. Commands that delete or detach do not prompt. They stop with pass --yes to confirm ... and change nothing unless you pass --yes.

verdictan iam policy​

verdictan iam policy creates and manages IAM policies. The CLI writes one statement for each policy: an effect, one or more actions, one or more resources, and optional conditions.

Usage​

verdictan iam policy list [--json]
verdictan iam policy get --policy-id <id> [--json]
verdictan iam policy create --name <name> --action <action> --resource <resource> [OPTIONS]
verdictan iam policy update --policy-id <id> [OPTIONS]
verdictan iam policy delete --policy-id <id> --yes

Options​

FlagApplies toDescription
--policy-id <id>get, update, deleteRequired. The policy ID.
--name <name>create, updatePolicy name. It must be unique in the organization. Required for create.
--description <text>create, updateDescription.
--effect <allow|deny>create, updateStatement effect. The default for create is allow.
--action <action>create, updateOne action. Repeat the flag for more actions. create needs at least one. For update, the values replace the saved list.
--resource <resource>create, updateOne resource. Repeat the flag for more resources. create needs at least one. For update, the values replace the saved list.
--conditions-json <json>create, updateConditions as one JSON object. For update, pass {} to remove all conditions.
--yesdeleteConfirm the deletion.

The API validates each statement:

  • An action is *, a known action such as events:read, or a namespace pattern such as events:*. Find the action names in the Permissions Reference.
  • A resource is * or a VDT pattern that starts with vdt:verdictan:.
  • The condition keys must be operators: StringEquals, StringLike, StringNotEquals, Bool, Null, NumericLessThanEquals, NumericGreaterThanEquals, or ForAnyValue:StringEquals. The snake-case forms such as string_equals are also accepted.

A statement that fails validation returns HTTP 422. The CLI prints api validation failed (422).

update without --effect, --action, --resource, or --conditions-json changes only the name or description. With one of those flags, the CLI reads the first saved statement, applies your changes, and sends one statement. If the policy has more than one statement, the update keeps only the first. Each statement change creates a new policy version.

Text output for list prints <policy_id> <name> <statement_count>, system policies first. get prints the ID, name, description, statement count, role count, and timestamps. Use get --json to read the statements and the roles that use the policy.

Examples​

# Create a read-only evidence policy
verdictan iam policy create \
  --name "Evidence Reader" \
  --description "Read governance events and exported evidence" \
  --action events:read \
  --action exports:read \
  --resource '*'

# Examine a policy before you change it
POLICY_ID="replace-with-a-policy-id"
verdictan iam policy get --policy-id "$POLICY_ID" --json

# Replace the action list and keep the resources
verdictan iam policy update --policy-id "$POLICY_ID" --action events:read

# Delete a policy that no role uses
verdictan iam policy delete --policy-id "$POLICY_ID" --yes

A * resource is broad. When a narrower scope is available, use a reviewed vdt:verdictan: pattern. System policies are read-only. A change to one returns HTTP 403 with policies.read_only.

verdictan role​

verdictan role creates roles, attaches policies to them, and shows the resulting actions and assignments.

Usage​

verdictan role list [--json]
verdictan role get --role-id <id> [--json]
verdictan role create --name <name> [--description <text>]
verdictan role update --role-id <id> [--name <name>] [--description <text>]
verdictan role delete --role-id <id> --yes
verdictan role attach-policy --role-id <id> --policy-id <id>
verdictan role detach-policy --role-id <id> --policy-id <id> --yes
verdictan role show-actions --role-id <id> [--json]
verdictan role show-assignments --role-id <id> [--json]

Options​

FlagApplies toDescription
--role-id <id>All except list and createRequired. The role ID.
--name <name>create, updateRole name. It must be unique in the organization. Required for create.
--description <text>create, updateDescription.
--policy-id <id>attach-policy, detach-policyRequired. The IAM policy ID.
--yesdelete, detach-policyConfirm the change.

The subcommands print:

  • list: one line for each role, <role_id> <name> <description>.
  • get: the ID, name, description, and timestamps. With --json, the role object also has policies, user_count, team_count, and token_count.
  • show-actions: one line for each effective action, <effect> <action> <resource> <source_policy>.
  • show-assignments: the users, teams, and tokens that hold the role.

attach-policy succeeds when the policy is already attached. The JSON response is then {"attached": false}. System roles are read-only. A change to one returns HTTP 403 with roles.read_only.

show-actions reads both stored statement lists and policy document objects with a Statement array. It includes actions from policies that you create with verdictan iam policy. The output identifies each source policy.

Examples​

# Create a role and attach the evidence policy
verdictan role create \
  --name "Evidence Reviewer" \
  --description "Reviews events and evidence exports"

ROLE_ID="replace-with-the-role-id"
verdictan role attach-policy --role-id "$ROLE_ID" --policy-id "$POLICY_ID"

# Confirm the attachment and find the holders of the role
verdictan role get --role-id "$ROLE_ID" --json
verdictan role show-assignments --role-id "$ROLE_ID"

verdictan user​

verdictan user invites people, changes member state, and gives roles to one user.

Usage​

verdictan user list [--status <status>] [--json]
verdictan user get --user-id <id> [--json]
verdictan user invite --email <email> --role-id <id> [--assignment-level <org|team>] [--assignment-target-id <id>]
verdictan user update --user-id <id> [--name <name>] [--org-role <role>]
verdictan user suspend --user-id <id> --yes
verdictan user reactivate --user-id <id>
verdictan user remove-membership --user-id <id> --yes
verdictan user assign-role --user-id <id> --role-id <id>
verdictan user detach-role --user-id <id> --role-id <id> --yes

Options​

FlagApplies toDescription
--user-id <id>All except list and inviteRequired. The user ID.
--status <status>listPrint only users with this status, such as active or suspended. The CLI filters the list.
--email <email>inviteRequired. The email address of the person to invite.
--role-id <id>invite, assign-role, detach-roleRequired. The role ID. For invite, the role applies when the person accepts.
--assignment-level <org|team>inviteScope of the invitation role. The API default is org.
--assignment-target-id <id>inviteTeam ID. Required when --assignment-level is team. The team must be in your organization.
--name <name>updateNew display name.
--org-role <role>updateNew organization role. The API rejects an empty value.
--yessuspend, remove-membership, detach-roleConfirm the change.

assign-role and detach-role also accept --assignment-level and --assignment-target-id. The API ignores them. assign-role always gives the role to the user at organization level, and detach-role removes that assignment. To give a role at team scope, use verdictan team assign-role, or invite the person with --assignment-level team.

list prints <user_id> <email> <status>. get prints the ID, email, name, status, organization role, and creation time.

When the email belongs to a member of the organization, invite creates no invitation. The API returns {"status": "already_member"} and the text output shows invitation - sent to <email>. Use --json to see the difference.

Examples​

# Invite a member with an organization-level role
verdictan user invite \
  --email reviewer@example.com \
  --role-id "$ROLE_ID"

# Invite a member with a team-level role
TEAM_ID="replace-with-a-team-id"
verdictan user invite \
  --email analyst@example.com \
  --role-id "$ROLE_ID" \
  --assignment-level team \
  --assignment-target-id "$TEAM_ID"

# Give a role to an existing member
USER_ID="replace-with-a-user-id"
verdictan user assign-role --user-id "$USER_ID" --role-id "$ROLE_ID"

Suspend a member​

To remove access for a period, suspend the member. Then confirm the status:

verdictan user suspend --user-id "$USER_ID" --yes
verdictan user list --status suspended

The suspended member is in the list. Run verdictan user reactivate --user-id "$USER_ID" to restore access. You cannot suspend or remove yourself. The API returns HTTP 422 with users.cannot_suspend_self or users.cannot_remove_self.

remove-membership removes the person from the organization. Before you run it, examine the tokens that the user owns, the team memberships, open work, usage attribution, and evidence ownership.

verdictan team​

verdictan team creates teams, manages their members, and gives roles at team scope.

Usage​

verdictan team list [--json]
verdictan team get --team-id <id> [--json]
verdictan team create --name <name> [--description <text>]
verdictan team update --team-id <id> [--name <name>] [--description <text>]
verdictan team delete --team-id <id> --yes
verdictan team add-member --team-id <id> --email <email> [--role <role>]
verdictan team remove-member --team-id <id> --user-id <id> --yes
verdictan team assign-role --team-id <id> --role-id <id>
verdictan team detach-role --team-id <id> --role-id <id> --yes
verdictan team list-members --team-id <id> [--json]

Options​

FlagApplies toDescription
--team-id <id>All except list and createRequired. The team ID.
--name <name>create, updateTeam name. The API makes a slug from the name, and the slug must be unique. Required for create.
--description <text>create, updateDescription.
--email <email>add-memberRequired. The email address of a person who is a member of the organization.
--role <role>add-memberTeam role for the member. The default is member. The API stores it in lowercase.
--user-id <id>remove-memberRequired. The user ID to remove.
--role-id <id>assign-role, detach-roleRequired. The role ID.
--yesdelete, remove-member, detach-roleConfirm the change.

list prints <team_id> <name> <description>. get prints the ID, name, slug, description, member count, and role count. list-members prints <user_id> <email> <name>. With --json, get also returns the members with their team_role, the inherited_roles, and the assigned_resources.

add-member returns HTTP 404 with users.not_found when the email does not belong to an organization member. Invite the person first with verdictan user invite.

Examples​

# Create a team, add a member, and give the team a role
verdictan team create \
  --name "Security Review" \
  --description "Governance evidence reviewers"

verdictan team add-member --team-id "$TEAM_ID" --email reviewer@example.com
verdictan team assign-role --team-id "$TEAM_ID" --role-id "$ROLE_ID"

# Confirm the members and the role
verdictan team list-members --team-id "$TEAM_ID"
verdictan team get --team-id "$TEAM_ID" --json

Limits and failure behavior​

  • A role that users, teams, tokens, or pending invitations still hold cannot be deleted. The API returns HTTP 409 with roles.in_use and the counts in the error details. Use role show-assignments to find the holders.
  • A policy that is attached to a role cannot be deleted. The API returns HTTP 409 with policies.in_use and the roles in the error details. Detach it with role detach-policy first.
  • A duplicate policy name returns 409 with policies.name_conflict. A duplicate role name returns roles.name_conflict. A team name with a slug that is already in use returns teams.slug_conflict. The CLI prints api conflict (409) for each.
  • iam policy update keeps only the first statement when it changes statements.
  • user assign-role and user detach-role work only at organization level.
  • A team deletion removes only the access that comes through that team. Direct user roles and other teams stay.
  • To confirm an access change, test it with a non-owner account that has the role. Owner access can hide a missing grant.

Troubleshooting​

SymptomCauseFix
missing api token (set VERDICTAN_API_TOKEN or run `verdictan auth login`)No token in the environment or the profile.Set VERDICTAN_API_TOKEN, or run verdictan auth login.
api authorization failed (403)The credential does not have the permission for the command, or a user or team change came from a credential without a user (auth.user_required).Check the permission table in Before you start. Sign in as a user.
api validation failed (422)An ID is not a UUID, or a policy statement has an unknown action, a resource that is not * or vdt:verdictan:..., or an unsupported condition operator.Copy IDs from the list commands. Correct the statement.
api conflict (409)A name is already in use, or the role or policy is still in use.Choose a different name, or remove the assignments first.
api request failed with status 404The policy, role, user, or team does not exist in your organization.Check the ID and the profile.
policy creation requires at least one --action and one --resourceiam policy create has no --action or no --resource.Add both flags.
nothing to update: provide ...An update command has no field to change.Add --name, --description, or another update flag.
--assignment-target-id is required when --assignment-level teamA team-level invitation has no team ID.Add --assignment-target-id <team-id>.
role show-actions prints no effective actionsThe role has no attached policy statements with actions.Check role get --json and iam policy get --json.

Next steps​