Skip to main content

Permissions

Permission for CLI-hosted work is not a local setting. It is carried by the lease the server issues when a run is claimed, and the CLI turns that lease into constraints the executor cannot talk its way past.

The three axes​

AxisMeaningValues
TierHow autonomously the seat may actautonomous, supervised, propose_only. Missing or unrecognised leaves the seat unarmed.
ScopesWhere the run may actA list of scopes (files, services, tables...). Empty means unrestricted.
ToolsWhat the run may executenone, or an explicit allowlist. Absent means none.

The CLI materialises these from the verified lease into an act envelope and reports them (envelope.tier, envelope.actScopes, envelope.actTools) in the vagaris dev output. The envelope is derived, never recomputed, and any parsing problem refuses the spawn.

Tools: deny by default​

  • A tool policy of none refuses the spawn before any process starts.
  • A lease with no tool policy is treated as none. Nothing about the CLI path defaults to "all tools".
  • An explicit allowlist becomes the executor's own allowlist argument: claude --allowedTools ... for Claude Code, codex --tool ... for Codex. The CLI never uses claude --dangerously-skip-permissions.

For Claude Code, a tool barred by the lease is refused by Claude Code's own permission hook when the agent tries to call it, not by prompt instruction.

Scope: asking for more​

An executor that needs an entity outside its scope asks the server, which weighs relevance, authority coverage and risk:

vagaris runctl scope-request --run-id <run-id> --lease-id <lease-id> \
--entity src/billing/ --entity-kind file \
--reason "the fix touches the invoice model" \
--current-scope src/api/

--run-id, --lease-id, --entity, --entity-kind and --reason are required; --current-scope may repeat. Approved scopes are added to the original ones, never replacing them. A denied request leaves the run bounded and still running — the command exits 0 with decision=denied; only a transport failure is non-zero. The request is recorded in the run's evidence.

Privileged acts: brokered, never local​

Six classes of act are never performed on the machine. The CLI sends the request to the server, which executes it, creates an approval, parks it, or denies it, and the CLI receives a structured verdict:

git_push_main, deployment, production_db_write, infrastructure_mutation, secret_access, billing_mutation
vagaris runctl privileged --act-class deployment --run-id <run-id> --lease-id <lease-id> \
--reason "release 1.4.2 to staging" --payload '{"environment":"staging"}'

The output carries the server verdict (executed, approved, parked, denied or error) and requiresOperatorApproval for the class. Exit code is 0 only for executed or approved; anything else — including parked, which means an operator must decide — is a refusal (2). An unknown --act-class is refused with the known classes listed; --payload must be valid JSON. No local credential exists for any of these acts.

Who may pause or cancel​

vagaris runctl pause and vagaris runctl cancel go through the server's governance chain, which validates the caller's authority; the CLI never stops a process directly. Cancellation is subject to the kill-switch integrity gate: a run whose process survived the kill attempt is reported as still running.

Board and instance permissions​

Commands that manage companies, agents, plugins and secrets are authorised by the identity behind your credential. A 403 whose message says instance-admin is required triggers an inline login (or exit code 3 non-interactively); vagaris auth login --instance-admin checks the requirement up front. vagaris auth whoami shows the roles you hold. Agent API keys act as the agent, with the agent's permissions.

  • Approvals — the operator side of parked and approved.
  • Security Model — why the CLI holds no authority of its own.