- The operator cannot write workloads. It has no
create,update, orpatchon Deployments. Kubernetes enforces that, not Dorgu’s code. - The CLI will not write workloads you have not handed it. It runs as you, so RBAC cannot stop it. What stops it is the ownership guard: it refuses to patch a Deployment that Helm, ArgoCD, or Flux reconciles. Those three stamp what they reconcile, so their ownership is detectable; kustomize is not, and the docs say so rather than implying a protection Dorgu cannot deliver.
What the operator cannot do
These are the permissions the ClusterRole does not grant. Every one of them fails with a403 Forbidden from the API server if the operator ever tried.
Verify it yourself on any cluster. Adjust the namespace and name if you installed with a different release name or
kubectl auth can-i answers as the operator’s service account:serviceAccount.name. The full list is kubectl auth can-i --list --as="$SA".What the operator can do
Everything the operator is permitted to do falls into three buckets: read cluster state, write its own CRDs, and record events.
Note the shape of it. Every write verb in that table targets a
dorgu.io CRD, a Kubernetes Event, or a leader-election Lease. Nothing else in the cluster is writable.
The full ClusterRole
This ischarts/dorgu-operator/templates/rbac.yaml as it ships, rendered with argocd.enabled=true so the optional rule is visible. Read your own cluster’s copy with kubectl get clusterrole dorgu-operator-manager -o yaml.
The
apps rule is the one to read twice. verbs: ["get", "list", "watch"] on deployments is what makes “the operator never writes workloads” a fact about your API server rather than a promise about Dorgu’s source code. Even a bug, a malicious plan from the AI planner, or a compromised operator pod cannot patch a Deployment through this service account.Why the operator can delete DorguEvents
This ClusterRole is a trust artifact, so a new verb in it deserves an explanation rather than a silent diff.delete on dorguevents.dorgu.io is new in operator v0.10.0. Without it the retention cleaner had no permission to act: it ran every cycle, failed, logged the failure, and removed nothing, while DorguEvent records accumulated in etcd. A five-app clean-room cluster produced 187 records in 100 minutes with no bound on the count. See dorguEvents.retention and dorguEvents.maxRecords.
The grant is scoped to Dorgu’s own CRD and to no workload kind, so “the operator never writes workloads” is unchanged. Two tests in the operator repo hold that line, one asserting the new verb and one asserting the operator still cannot create, update, patch, or delete Deployments, ReplicaSets, Pods, Nodes, or Namespaces. Check both halves on your own cluster rather than taking either on trust:
How the AI API key reaches the operator
The operator has no permission to read Secrets, which raises a fair question: how does it get your Anthropic key? The key is injected as an environment variable viasecretKeyRef in the pod spec. The kubelet reads the Secret and materialises it into the container’s environment; the operator’s ServiceAccount is never involved and never needs get secrets.
- The operator can read exactly one secret value, the one you explicitly wired into its pod spec. It cannot enumerate or read any other Secret in the cluster.
- Rotating the key means updating the Secret and restarting the pod. There is no live re-read, because there is no read.
- In production, create the Secret out of band and set
llm.existingSecret. Passingllm.apiKeythrough Helm values means the raw key stays visible tohelm get valuesandhelm template.
What the CLI can do, and with whose credentials
The CLI is the other half of the story, and its permissions are not Dorgu’s to grant.dorgu shells out to kubectl using your kubeconfig and your current context. It has exactly the access you have. If you can patch a Deployment, so can it; RBAC will never stop the CLI on your behalf.
That is why the ownership guard is in the CLI rather than in RBAC. It is not a permission boundary, it is a judgment about whether writing is correct:
Guardrails on the remediation path
RBAC bounds what is possible. These bound what Dorgu will propose, and they run before anyRemediationAction is created.
Hardening notes
Next steps
Ownership model
Why Dorgu refuses to patch a Helm or ArgoCD-owned workload
Trust model
The progressive trust levels and what is actually implemented
Helm values
Every chart option, including webhook mode and leader election
AI setup
Key handling, what is sent to Anthropic, and how to turn it off