Files
Aleksei Sviridkin 4996b9d8ef fix(api): publish open spec as x-kubernetes-preserve-unknown-fields, not additionalProperties:true (#2867)
## What this PR does

`cozystack-api` published the free-form `.spec` of aggregated
`apps.cozystack.io` resources (Tenant, Application, …) as the boolean
`additionalProperties: true`. The Kubernetes ValidatingAdmissionPolicy
**status type-checker** run by `kube-controller-manager`
nil-dereferences when it recurses into that node
(`k8s.io/apiserver/pkg/cel/openapi.isExtension`). As soon as a VAP
matches one of these resources — `cozystack-tenant-host-policy` matches
`tenants` — KCM `CrashLoopBackOff`s on every control-plane node, stalls
reconciliation, and times out the install (`kubectl wait hr --all` never
completes). With the 3× install retry removed, a single occurrence fails
E2E outright.

This emits `x-kubernetes-preserve-unknown-fields: true` instead, in
`pkg/cmd/server/openapi.go::patchSpec` (both the schemaless and
custom-schema branches, covering the OpenAPI v2 and v3 post-processors).
It is semantically equivalent — "arbitrary fields allowed" — and the
type-checker handles it safely. All managed-app custom schemas already
use the safe **object-form** `additionalProperties`, so `patchSpec` was
the only source of the boolean form.

### Regression test

`TestPatchedSpecDoesNotPanicVAPTypeChecker` reproduces the exact crash
through `k8s.io/apiserver/pkg/cel/openapi.SchemaDeclType` — the entry
point KCM's `validatingadmissionpolicystatus` controller uses. It
**panics on the pre-fix code and passes after the fix**. Companion
structural tests assert the published spec carries
`x-kubernetes-preserve-unknown-fields: true` and never the boolean
`additionalProperties: true`, and that genuine object-form maps are left
untouched.

Verified against the pristine vendored `k8s.io/apiserver@v0.34.1` (the
version cozystack-api builds against), which reproduces the panic, and
previously confirmed end-to-end on `kindest/node:v1.33.1`.

### Upstream

The underlying nil-dereference is a Kubernetes KCM bug — the VAP status
type-checker should treat `additionalProperties: true` as dynamic rather
than panic. A separate upstream report is being prepared; cozystack
fixes the symptom immediately with the schema change above.

Fixes #2863

### Release note

```release-note
fix(api): publish the free-form resource `.spec` as `x-kubernetes-preserve-unknown-fields` instead of `additionalProperties: true`, fixing a cluster-wide `kube-controller-manager` CrashLoopBackOff (nil-pointer panic in the ValidatingAdmissionPolicy status type-checker) that stalled installs.
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Ensured published OpenAPI schemas no longer contain boolean-form
additionalProperties anywhere; top-level and nested schemas now use
preserve-unknown-fields for free-form specs, preventing
validation/runtime issues.

* **Tests**
* Added regression tests that feed varied untrusted schemas and verify
boolean additionalProperties are removed and published schemas remain
valid for tooling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-15 20:46:15 +03:00
..