Skip to main content

CLI

verdictan control

You can keep organization resources in one YAML file, the control manifest. Use verdictan control export to write the current resources to a file. Use verdictan control plan to see the changes that the file causes. Use verdictan control apply to make the changes.

The control manifest is not the gateway policy config. For providers, routes, and the policy chain, use policy-config.yaml.

Before you start​

You need:

  • An API credential. Set VERDICTAN_API_TOKEN, or run verdictan auth login. The CLI does not accept a token flag.
  • Permission to read each resource group for export and plan, and permission to change it for apply.
  • For each manifest secret: the environment variable that the secret names, set in the shell that runs apply.

Start from your saved settings​

  1. Write the current resources to a file:

    verdictan control export --file control-manifest.yaml

    The command prints exported to control-manifest.yaml. An Export summary: line on standard error gives the number of resource groups that exported.

  2. Make a plan for the file:

    verdictan control plan --file control-manifest.yaml

    Some resource types always show as a create or an update, also when nothing changed. Examine the resource groups table for these types. Find the cause of each other create or update before you continue.

  3. Edit one IAM policy in the file. For example, change its description. Then make the plan again. The output is similar to this:

    plan: 0 create(s)  1 update(s)  0 delete(s)  3 no-op(s)
    
    ~ iam.policy  evidence-read
        ~ description
    
    (dry-run — no changes applied; run `verdictan control apply` to reconcile)
  4. When the plan contains only the changes you want, apply the file:

    verdictan control apply --file control-manifest.yaml

    The command prints the plan and asks for confirmation. Type yes. It prints applied <n> operation(s) and control-plane reconciled successfully.

  5. Make the plan again to confirm the result. For an IAM policy, the line moves to the no-op count.

Manifest format​

A manifest has version: "1" and a resources object. The CLI rejects other versions and unknown resource groups. The CLI reads .json files as JSON and all other files as YAML.

version: "1"
resources:
  secrets:
    - name: openai-production-key
      env: VERDICTAN_OPENAI_API_KEY
      description: Production provider credential
  iam:
    policies:
      - name: evidence-read
        description: Read governance evidence
        statements:
          - Effect: Allow
            Action:
              - events:read
              - exports:read
            Resource:
              - "*"
    roles:
      - name: evidence-reviewer
        policies:
          - evidence-read
  teams:
    - name: security-review
      description: Governance evidence reviewers

Names identify resources. Keep each name stable and unique in its resource type. Budgets refer to a team, user, or agent by name or email. A role refers to IAM policies by name, and each name must be a policy in the same manifest.

A manifest secret has name, env, and an optional description. It has no value field. At apply time, the CLI reads the value from the environment variable in env. The API stores the value as a secret record. A gateway does not use these records as provider keys. See Manage Secrets and Credentials.

The CLI checks the manifest before it contacts the API. These checks include the version, empty names, empty env values, and role references to unknown policies.

This table shows how plan compares each resource group with the remote state:

GroupPlan result for a resource that existsDeleted by --prune
secretsAlways an update. The value can change in the environment.Yes
iam.policiesAn update when description or statements changesYes
iam.rolesAlways a no-op. Changes are not applied.Yes
teamsAlways a no-op. Each listed member is always a create.Yes, teams only
usersAdd the listed roles and team memberships. With neither list, a no-op.Remove organization membership
platform_provider_bundlesAn update when a field changesArchived
agentsAn update when a field changesYes
budgetsAn update when a field changesYes
regulated_execution_profilesAlways an updateYes
approval_policyUpdate the one organization approval policyNo
prompt_evaluation_suitesAn update when a field changesYes
hosted_gateway_bindingsAlways an updateNo
auth_org_policyUpdate organization SSO and password sign-in settingsNo

Users and organization settings​

For a new user, the CLI creates an invitation. Set exactly one role and, optionally, one team:

version: "1"
resources:
  users:
    - email: developer@example.com
      roles: [evidence-reviewer]
      teams: [security-review]

The role and team must exist when the invitation runs. Use their names from verdictan role list and verdictan team list. For an existing user, listed roles and teams are added. Omitted memberships are not removed. With --prune, removal affects organization membership, not the user's account.

The API has one approval policy per organization. Use approval_policy, not a named approval_policies list:

version: "1"
resources:
  approval_policy:
    required_actions:
      destructive_actions: true
      high_cost_requests: false
      sensitive_data_access: true
    required_approvals: 1
    timeout_hours: 24
    break_glass:
      enabled: false
      allow_requester_override: false
      post_review_required: false
      review_window_hours: 24
      reviewer_subject_ref: ""
  auth_org_policy:
    required_sso: false
    local_auth_allowed: true

The approval count must be 1 or 2. Time limits must be positive. If break-glass access and post-review are enabled, supply reviewer_subject_ref. Approval settings use the org:settings permission. Authentication settings use sso:read to plan and sso:write to apply.

The CLI rejects approval_policies, collaboration_defaults, and hosted_gateway_policy before it contacts the API. For auth_org_policy, only required_sso and local_auth_allowed are supported. Legacy domain, JIT, invite-only, and popup-origin fields also stop validation before any changes. Use the SSO API for domain and identity-provider settings.

verdictan control export​

verdictan control export reads the resources of the authenticated organization and writes them as a manifest. The export does not contain secret values, team members, or user teams and roles.

Usage​

verdictan control export [OPTIONS]

Options​

FlagDescription
--file <path>Write the manifest to this file. Without this flag, the command prints the manifest to standard output.
--include-secret-stubsInclude one entry for each secret, with env: <SET_ENV_VAR>. Without this flag, the export has no secrets list.
--jsonWrite JSON, not YAML.
--allow-partialWrite the manifest when one or more resource groups fail.
--config <path>Use this CLI config file.
--api-url <url>Use this API URL.
--profile <name>Use this profile. The default is default.
--region <region>Send the API calls to this region.

Examples​

# Print the manifest as YAML
verdictan control export

# Write a file that includes secret entries
verdictan control export --file control-manifest.yaml --include-secret-stubs

After an export with --include-secret-stubs, replace each <SET_ENV_VAR> with the name of a variable that holds the secret in the apply environment. Do not put the secret value in the file.

When a resource group fails, the command stops with <n> resource type(s) failed to export; rerun with --allow-partial to emit a partial manifest. The Export summary: line lists the failed groups with their HTTP status. With --allow-partial, the command writes the manifest without the failed groups. A route that returns 404 does not count as a failure. The command exports that group as empty.

verdictan control plan​

verdictan control plan calculates the operations that apply runs for the same file. It does not change remote resources.

Usage​

verdictan control plan [OPTIONS]

Options​

FlagDescription
--file <path>Manifest file. The default is control-manifest.yaml.
--pruneInclude delete operations for remote resources that are not in the manifest.
--jsonPrint the plan as one JSON object.
--config <path>, --api-url <url>, --profile <name>, --region <region>The same as for export.

Examples​

# Plan for the default file
verdictan control plan

# Plan that includes deletions, as JSON
verdictan control plan --file control-manifest.yaml --prune --json

In text mode, the first line is plan: <n> create(s) <n> update(s) <n> delete(s) <n> no-op(s). Each change follows on one line: + for a create, ~ for an update, and - for a delete, then the resource type and the name. The command does not print no-op lines. When there are no changes, it prints no changes — control-plane is up to date.

In JSON mode, the object has dry_run: true, prune, a summary object with creates, updates, deletes, and no_ops, and the ops array.

verdictan control apply​

verdictan control apply calculates the plan again and then runs the operations. It runs creates and updates first, in the order of the resource groups table. Then it runs deletes in the opposite order.

Usage​

verdictan control apply [OPTIONS]

Options​

FlagDescription
--file <path>Manifest file. The default is control-manifest.yaml.
--pruneDelete remote resources that are not in the manifest.
--yesDo not ask for confirmation.
--jsonPrint the result as one JSON object. JSON mode does not ask for confirmation.
--config <path>, --api-url <url>, --profile <name>, --region <region>The same as for export.

Examples​

# Apply after confirmation
verdictan control apply --file control-manifest.yaml

# Apply in CI, without a prompt
verdictan control apply --file control-manifest.yaml --yes --json

In text mode, the command prints the plan and then Type 'yes' to continue:. Other answers stop the command with aborted — no changes applied and exit code 0.

In JSON mode, the object has applied, prune, summary, successful, and failed. applied is true only when failed is empty.

Delete resources that are missing from the file​

--prune deletes each remote resource that the manifest does not list, in each group that supports it. An empty or missing list counts as a list with no entries. For example, a manifest without secrets deletes all secrets. Only a missing iam block is skipped.

Use --prune only when the manifest declares all resources that you manage. Do not use it with an export that has missing groups, or with an export made without --include-secret-stubs.

  1. Make the deletion plan:

    verdictan control plan --file control-manifest.yaml --prune --json
  2. Examine each operation with "action": "delete".

  3. Apply with the same file and flag:

    verdictan control apply --file control-manifest.yaml --prune

    The prompt says This will create, update, AND DELETE resources listed above.

Limits and failure behavior​

  • apply stops at the first failed operation. The operations that completed before it stay applied. Make the plan again to see the remaining changes.
  • In text mode, a failure prints error: <type> <name> — <message> and the command exits with code 4. In JSON mode, the command exits with code 0. Read applied and failed in automation.
  • A manifest error, such as unsupported manifest version "2" (expected "1"), exits with code 2. A missing credential exits with code 3 and missing api token (set VERDICTAN_API_TOKEN or run `verdictan auth login`).
  • apply calculates the plan again. Changes made by other operators after your plan change the result.
  • A new role is created without its policies. The CLI ignores the attach failure. Attach the policies after apply.
  • The CLI adds team members by email only. It does not send member roles. For a user, teams and roles add memberships.
  • An existing team keeps its description. The manifest description applies only when the CLI creates the team.
  • --prune does not remove team members, agent gateway links, hosted gateway bindings, or the organization settings.

Next steps​