get, list and patch on workloads in the namespaces you chose.
Three identities, kept apart
The execution role is always a different role from the read role (
read_write_not_separated is refused), and it is registered per (connection, environment). Reading is a standing, read-only grant you can revoke; writing is never standing at all.
Per-environment identity
Everything about execution carries the environment’s instance —<environment-slug>-<10 hex of a hash of tenant and environment>:
- the IAM role
ChangeGuardExecutor-<instance>(Cloud) or the ServiceAccountchangeguard-local-executor-<instance>(Local); - the Kubernetes group
changeguard:executor:<instance>; - the ClusterRole
changeguard-executor-<instance>and the RoleBindings of the same name in each granted namespace.
Permit environment = AWS execution identity environment = Kubernetes execution identity environmentA role bound to another environment, another tenant, or another account is refused even if its name matches. See Environment isolation.
What the Executor can never do
The ClusterRole only definesget, list and patch on apps/deployments, apps/statefulsets and apps/daemonsets; authority exists only where a RoleBinding grants it, in the namespaces you selected. kube-* namespaces are never granted. There is no delete, no create, no update (full replace), no pods/exec, no Secrets, no RBAC writes, no impersonation, no node access, no wildcard verbs or resources, and no cluster-admin — anywhere in the execution model.

Verify execution access proves the negatives, not just the positives: every verb the Executor must not hold is checked and must come back denied.
Verify execution access
Before an environment is execution-ready, and again every 12 hours, ChangeGuard runs Verify execution access. Nothing is read from or written to any workload — only access reviews and a signed probe Permit (use=verify, which can never execute).
A path verifies for 24 hours. A failed verification takes the path out of service and revokes its live Permits.
Two independent fences
Execution is bounded by two mechanisms that fail independently:- Authority (logical). No Permit, no action. The Permit binds the exact action, target, environment, executor and authority, expires in minutes, is consumed once, and is refused at consume if the approval, the policy version or the execution path changed.
- Identity (physical). Even a valid Permit can only be exercised through an identity that holds
get/list/patchin the granted namespaces. If the binding is gone, the Kubernetes API server refuses the write, full stop.
You hold the off switches
Every one of these is under your control, effective immediately, with no ChangeGuard involvement:- Delete the EKS access entry, the RoleBinding or the execution role — the Cloud Executor can no longer act in that environment.
- Scale the Local Executor to zero, delete its manifest, or revoke its API key — queued work holds; nothing executes.
- Shrink the RoleBindings — writes outside the new scope fail at the API server.
- Disable execution, revoke Permits, or set the mode back to Advise in ChangeGuard — nothing further is served.
The Executor is intentionally boring: verify, consume once, record pre-state, apply one patch, read back, report. Analysis, authorization, Permit issuance, verification and audit all live in the control plane, where they cannot widen cluster access. Executor liveness is monitored — a stale Executor is flagged in the product, so “nothing is happening” is always distinguishable from “nothing is wrong”.