CRD Overview
The primary CRD is ApplicationPersona, which describes a single application’s desired operational profile and the Operator’s observed state. ClusterPersona captures cluster-level context. The remaining three are the self-healing loop’s memory — see Self-healing.
Ownership Model
The spec and status of an ApplicationPersona are owned by different actors. This separation is fundamental to Dorgu’s design.
The CLI and GitOps tools define the desired state in the spec. The Operator observes the cluster and writes its findings to the status.
The one exception is remediation: when you approve a
RemediationAction, the Operator applies that action’s JSON merge patch to the ApplicationPersona spec. That is a change you explicitly authorized, scoped to the fields in the proposal you reviewed. Nothing else lets the Operator write a spec.
If you manage personas through GitOps, an approved remediation’s patch will show as drift on the next sync — mirror the change back into your repo so your pipeline does not revert the fix.
dorgu remediation approve --no-heal does not avoid this: it skips the Deployment patch only, and the persona is still updated by the Operator once the action is Approved.The one case where the persona is not updated is a refusal: on a workload something else owns, approve writes nothing at all, neither the Deployment patch nor the status patch that would trigger the persona write. See the ownership model.API Group and Scope
All CRDs belong to thedorgu.io/v1 API group.
ApplicationPersonas live in the same namespace as the workloads they describe. ClusterPersona is cluster-scoped since it represents the entire cluster.
ApplicationPersona Spec Fields
The spec defines the desired operational profile for an application.ApplicationPersona Status Fields
The status is populated entirely by the Operator and reflects the observed state of the application.Full ApplicationPersona Example
A complete ApplicationPersona for a critical API service:ClusterPersona
ClusterPersona is a cluster-scoped resource that captures the overall cluster context. The Operator’s ClusterPersona controller automatically discovers and populates its status.ClusterPersona Spec Fields
ClusterPersona Status Fields
The ClusterPersona controller reconciles every 5 minutes, scanning nodes, namespaces, and well-known add-on namespaces to keep the status current.
Self-healing policy
spec.policies.selfHealing configures how the cluster heals.
mode is enforced by the proposer: observe records the incident and proposes nothing, propose proposes with approval required, and auto-approve is not implemented — it is accepted but degraded to propose with a warning. maxRemediationsPerHour and excludeNamespaces are enforced by the safety checker. enabled and trustLevel are not enforced: trustLevel is only fed to the AI planner as context, and detection/diagnosis/proposal run regardless of enabled — use mode: observe to stop at diagnosis. The operator’s auto-created persona uses mode: propose.IncidentMemory
IncidentMemory is the record of a detected problem: what was seen, what caused it, and how it ended. It is created and maintained by the operator’s health-check reconciler. Read them with dorgu incidents.
Spec Fields
rootCause.provider is rule-based or ai-enhanced. resolution.outcome is resolved, partial, failed, or rollback — written by the remediation controller when the loop finishes.
Status Fields
Attribution
spec.attribution records how confidently the incident was tied to an application, and is mirrored to the label dorgu.io/attribution so it is one query:
An unattributed incident closes once an attributed one is tracking the same workload, and its
resolution.action says handover rather than recovery, because nothing observed the workload.
Resolution
An incident auto-resolves only on positive evidence of recovery: its signal absent for a 5-minute grace period, and its pods observedReady, restart-free, and out of any waiting state for a 6-minute stability window. Anything else, including any failure to read the cluster, leaves it open. spec.resolution.action records the evidence as auto-resolved: <what was observed>.
attribution and evidence-based resolution are new in operator v0.10.0. In v0.9.0 an incident resolved on the absence of a signal alone, which a crash loop in backoff could produce while still completely dead. See self-healing.RemediationAction
RemediationAction is a proposed fix. The operator creates it, you approve or reject it, and the operator records what happened. Work with them via dorgu remediation.
Spec Fields
action.type is one of persona-update, notification, or git-pr. action.patch is a JSON merge patch applied to the Persona spec — never to a workload.
workloadRef Fields
The operator populates this from the live Deployment at proposal time. It exists because the persona is a point-in-time import that drifts from the running workload, so every stated fact and every blast-radius cap is grounded here rather than in the persona.
Step Fields
Each entry insteps[]:
On an owned workload, steps are reshaped before they are persisted. Where
workloadRef.managedBy is anything but unmanaged, the operator drops the command from any step whose command writes to the cluster, rewrites description as what to change at the source (chart values for a Helm release, the Git manifests for an ArgoCD application), and appends one line to rationale on what a direct patch would have broken. Read-only commands such as kubectl logs survive. persona-update steps are never reshaped. See what changes about the plan.Step Safety Fields
New in operator v0.11.0. Each entry insteps[].safety is one guardrail’s verdict on one field of that step.
rule
verdict
Optional and additive, so nothing has to migrate.
safety is absent on every object an operator older than v0.11.0 wrote, and absent means no guardrail ruled. A client that does not know the field renders exactly as it did before and gains no safety key in JSON output. There is no version pinning between the CLI and the operator on account of it: see guardrail verdicts.A step with no patch is removed from the plan; a step whose patch a guardrail emptied is kept. The difference is what the object is for. A
persona-update step carrying no patch applies nothing and instructs nobody, since updating the ApplicationPersona is Dorgu’s own job, and it is what used to render as (no changes) underneath a plan that read like a fix. A step a guardrail emptied carries the record of which field was refused and why, which is the difference between a step that explains an absence and a step that is one.Status Fields
steps[] is populated, validated, and rendered by the CLI, and currentStep / stepStatuses[] exist in the schema — but the controller currently executes the single spec.action patch rather than walking the plan step by step. autoApproveRule is likewise present in the CRD and ignored by controllers: auto-approve graduation is not implemented.DorguEvent
DorguEvent is a write-once, classified Kubernetes event record. The event pipeline watches core Kubernetes events, classifies them by severity and category, correlates them to a persona and incident where it can, and stores them. There is no status subresource, so the record is immutable.
Records are bounded by age and by count: dorguEvents.retention (default 24h) and dorguEvents.maxRecords (default 2000, oldest pruned first). A per-record spec.ttl overrides the age bound for that record. See DorguEvent retention.
Stream them live with
dorgu watch events.