# Execution: provider health checks Plan: [docs/plans/2026-09-11-1526-provider-health-checks.md](../plans/2026-09-11-1526-provider-health-checks.md) - [x] Step 0 — Save the plan - [x] Step 1 — ProviderHealth API and CRD - [ ] Step 2 — Contract plus the kubernetes and GCP checks - [ ] Step 3 — KVM check - [ ] Step 4 — Monitor - [ ] Step 5 — Metrics and wiring - [ ] Step 6 — Docs - [ ] Step 7 — Validate, record, push, open the PR ## Step 0 — Save the plan Branched off `main` (at the PR #5 merge, `eb8f075`). The plan was copied out of `~/.claude/plans/` and committed on its own, before any code, as the repo's plan rules require: ```bash git checkout -b feat/provider-health main cp ~/.claude/plans/now-i-would-like-flickering-wall.md docs/plans/2026-09-11-1526-provider-health-checks.md ``` The uncommitted `.claude/settings.json` change was left unstaged and stays out of this branch. ## Step 1 — ProviderHealth API and CRD `kubebuilder` isn't installed here (only `bin/controller-gen`, `bin/kustomize` and `bin/setup-envtest` are), so `api/v1alpha1/providerhealth_types.go` and the `PROJECT` entry were written by hand instead of with `kubebuilder create api`. For a cluster-scoped resource `PROJECT` simply omits `namespaced`, which is what kubebuilder itself writes. The new types are registered in the existing `AddKnownTypes` call in `proxy_types.go`, not in a second `init()`. The deepcopy code, the CRD and the RBAC come from the usual generators: ```bash make generate manifests go build ./... && go vet ./api/... && go test -short ./api/... ``` To confirm the new CRD and the viewer role actually reach the rendered install, I built the kustomization and grepped for them: ```bash bin/kustomize build config/default | grep -n providerhealth # providerhealths.crawl.example.com (scope: Cluster, shortName ph) # egress-proxies-operator-providerhealth-viewer-role ``` Worth noting: - The only role added is the viewer role. The operator is the object's only writer, so the admin and editor roles kubebuilder scaffolds for Proxy were not added. - The type file has no unit test, since it has no logic. The schema, including the required `ready`/`lastTransitionTime` and the list-map keys, is proven by the envtest round-trip in Step 4. - `config/rbac/role.yaml` is unchanged so far. The manager's own permissions arrive in Step 4 with the Monitor's RBAC markers.