#141532·Kubernetes

[Declarative Validation] Track beta→stable graduation of validation rules

Author: krishhna24Created Aug 22, 2026Updated Sep 28, 2026
Labelskind/cleanupsig/api-machinerytriage/acceptedarea/api-validation

What would you like to be added?

A tracking issue for the beta→stable graduation of declarative validation rules, per KEP-5073.

Every DV rule currently at beta carries since: "1.37", and there are no older ones, so nothing was eligible until v1.37 shipped. It has, which opens the wave.

Scope

Settled in this comment:

  • One API type per PR, not one group. The type is the kind: a nested struct such as IPBlock goes with NetworkPolicy, not in a PR of its own. Deleting handwritten validation has no per-rule rollback and costs the mismatch comparison its baseline, so diffs stay small enough to read line by line.
  • +k8s:beta to stable only. Dropping the prefix. +k8s:alpha promotion is out of scope and handled separately.
  • meta / ObjectMeta is out of scope and tracked separately. This catches whole rows: lifecycle's two rules are both on the embedded metav1.ObjectMeta (lifecycle/v1alpha1/types.go:59 and :251), so that group is not claimable here.

The group rows below size the backlog. The unit of work, and of claiming, is a single API type inside one of them.

Backlog

Regenerated at 451ab1d9b7c:

API group beta rules Status Owner PR
resource 410 unclaimed
flowcontrol 40 unclaimed
rbac 21 in review @itzPranshul #141605
networking 20 partly claimed @liyuerich NetworkPolicy (6). IngressClass (6) and IPAddress (8) unclaimed
storage 12 in review @itzPranshul #142056 (VolumeAttachment). #141967 (StorageClass) merged 2026-09-15
certificates 12 in review @antcybersec #142333 (CertificateSigningRequest)
autoscaling 12 in review @datayurei #142151 (HorizontalPodAutoscaler, 10). The other 2 are Scale, see apps
extensions 8 not workable no pkg/apis/extensions/validation/ exists, so there is nothing to delete; extensions/v1beta1 is the one entry in coverage-allowlist.yaml, "Not served by kube-apiserver"
admissionregistration 6 in review @alinaqvi1129 #142222 (ValidatingAdmissionPolicyBinding)
apps 4 unclaimed all four are ScaleSpec.replicas in v1beta1/v1beta2. They graduate together with autoscaling/v1 Scale as one PR: 6 rules, one handwritten check in ValidateScale
core 2 out of scope @yongruilin #141564 (ReplicationControllerSpec, merged). The remaining 2 are on ReplicationController's metav1.ObjectMeta
lifecycle 2 out of scope both rules are on metav1.ObjectMeta, see Scope
node 0 done @krishhna24 #142119 (RuntimeClass, merged 2026-09-16)
discovery 0 done @krishhna24 #141533 (EndpointSlice, merged 2026-09-03)
batch 0 done @alinaqvi1129 #141677 (CronJob, merged 2026-09-14)
total 549

authorization, scheduling, policy and storagemigration carry alpha rules only, so they have nothing to graduate here.

Counts move as the wave lands. The total was 592 at filing, then 588, then 574 after #141533 (discovery) and #141677 (batch), and is 549 now: #141967 took storage 28 to 12 and #142119 took node 9 to 0. Only types.go carries the markers, so this returns the same number:

grep -rho --include='*.go' '+k8s:beta(since:' staging/src/k8s.io/api | wc -l

Claiming

Comment here naming the API type you are taking, then open one PR for it. I will keep the table current.

On sourcing Owner from the tag's owner: field: that field does not exist. +k8s:alpha and +k8s:beta accept at most one argument and it has to be since, matching a version regex, so anything else is a generator error (staging/src/k8s.io/code-generator/cmd/validation-gen/validators/levels.go:64-74). A grep -rho 'owner:' staging/src/k8s.io/api returns nothing. So Owner comes from claims in this thread instead, unless you would rather the tag grew the field.

Why is this needed?

The KEP's criteria for beta→stable are ">=1 release at Beta, zero mismatch/panic metrics, reviewers agree the safety switch is no longer needed", and "the same PR removes the matching handwritten validation".

The first two are checkable in-tree. pkg/api/testing/validation.go already asserts apiserver_validation_declarative_validation_mismatch_total == 0 under both gate configurations, so a graduation can be verified locally rather than from production dashboards.

The third is a reviewer judgement, which is why this is an issue and not just a series of PRs.

Worth writing down

Dropping the wrapper and deleting the handwritten check are not separable. FilterCoveredHandwrittenErrors only suppresses a handwritten error when a matching beta declarative error is enforced, so a graduated rule that still has its handwritten twin reports the same violation twice and trips the mismatch metric. Demonstrated in #141533.

/sig api-machinery /area api-validation /kind cleanup