On this page
Policy
What is Stado allowed to do on its own, and who decides? The autonomy policy is one versioned document that answers both questions, and every autonomous mutation is authorized against it fail-closed.
What it is
The policy (stado-rs/src/autonomy/policy/document/mod.rs) carries a schema
version, a
required policy_version string, a mode, the emergency-pause flag, and the
budgets, placement, idle, freshness, and safety blocks. The default policy is
default-report-only in report mode: a fleet that has configured nothing
gets a policy that mutates nothing.
Three modes:
| Mode | Meaning |
|---|---|
report |
Every mutation is denied; the plan is recorded instead of executed (operations). |
enforce-safe |
Reversible actions are allowed; destructive ones still require an explicit rule. |
enforce-owned |
Destructive actions are allowed only when a matching resource rule explicitly sets allow_destructive. |
Authorization is fail-closed, in order: read-only actions are always allowed;
the emergency pause denies everything else; report mode denies; an
incomplete inventory denies when require_complete_inventory is set; a
resource that is not owned or adopted is denied; a production or stateful
resource is protected unless a matching rule explicitly allows its mutation; a
cost estimate above max_single_action_usd is denied; and financial
commitments are always denied — they require an operator-approved immutable
plan, in every mode.
Budgets cap spend: hourly_usd, daily_usd, monthly_usd,
max_single_action_usd, max_commitment_usd, each optional and required to
be finite and non-negative.
Safety limits bound each tick: max_actions_per_tick and
max_actions_per_provider (must be positive), max_deleted_bytes_per_tick,
max_concurrent_mutations, require_complete_inventory,
protect_production, protect_stateful, the circuit breaker
(circuit_breaker_failures, circuit_breaker_cooldown_seconds), and
decision_ttl_seconds. Only a mutation that failed on a host feeds the
circuit breaker; refusals computed before any host command runs must not
starve the healthy repairs behind them (operations).
Freshness windows (inventory_max_age_seconds,
pricing_max_age_seconds) bound how old the evidence behind a decision may
be; both must be positive.
Resource rules match a resource by type, provider, account, region,
environment, and owner, and default to allowing nothing: allow_reversible,
allow_destructive, allow_production_mutation, and
allow_stateful_mutation are all false until written otherwise, and a rule
cannot allow a production or stateful mutation without allowing a mutation at
all.
Who declares it
An operator, atomically and with a version expectation:
stado optimize policy show
stado optimize policy apply --file policy.json --expect-version <version>
apply validates the document, then compare-and-swaps it against
--expect-version. The first policy is created only if absent; replacing an
existing policy without --expect-version is refused with
autonomy policy already exists; expected_version is required
(stado-rs/src/autonomy/storage/records/policy.rs). Two operators cannot
silently overwrite
each other's policy.
The emergency pause is separate from the mode and overrides every mode:
stado optimize pause "reason"
stado optimize resume
Who observes it
stado optimize status shows the mode, safety state, inventory freshness, and
latest decisions; stado optimize explain <decision-id> prints one immutable
decision (stado-rs/src/cli/autonomy_cmd.rs). Every stado optimize run and
scheduled autonomy tick loads the policy before acting, and enforcing modes
execute under the emergency pause, circuit breaker, action limit, and
per-service mutation lease (operations).
Where it lives
state/autonomy/policy.json in the configured canonical backend, versioned.
Every autonomy object is rooted under state/ because the object gateway
authorizes writes against the configured namespace prefix allowlist
(operations).
Commands
stado optimize status
stado optimize run
stado optimize policy show
stado optimize policy apply --file policy.json --expect-version <version>
stado optimize pause "reason"
stado optimize resume
Flag-by-flag detail lives in cli; what the autonomy layer does with an authorized action is the subject of autonomy.
Not to be confused with
- The emergency pause. The pause is control state, not policy: it denies autonomous mutation in every mode until resumed, and changing the mode does not clear it.
- A resource rule alone. A rule never grants by itself — the mode and the
rule combine, and a destructive action needs both
enforce-ownedand an explicitallow_destructiverule. - A grant. The policy bounds what Stado may do; a grant bounds what credentials a Stado process may read. Neither substitutes for the other.
Source: this website