Skip to content

Teach the Platform CR walker the list-map uniqueness rule - #202

Merged
stxkxs merged 1 commit into
mainfrom
gate-list-map-uniqueness
Aug 10, 2026
Merged

Teach the Platform CR walker the list-map uniqueness rule#202
stxkxs merged 1 commit into
mainfrom
gate-list-map-uniqueness

Conversation

@stxkxs

@stxkxs stxkxs commented Aug 10, 2026

Copy link
Copy Markdown
Member

The walker checked two of the three things the API server checks: required properties present, excess properties caught as pruned. x-kubernetes-list-type was read as documentation rather than as the validation rule it is.

A Platform declaring two datastores both named main passed every gate in the org green. Every property was present, none was excess — and the API server refused the whole object:

spec.datastores: Duplicate value

Not a warning, not a merge of the two entries. A hard rejection, so nothing is applied and the Application never reaches Healthy.

What changed

check_list_uniqueness runs wherever the walker meets an array, before it descends:

  • map — an entry is identified by its listMapKeys tuple
  • set — a scalar entry is identified by itself
  • atomic / unannotated — no uniqueness imposed, left alone. Flagging these would be a false positive that teaches an operator to work around the gate.

Two details the rule turns on:

  • Uniqueness is per listMapKeys, not per whole entry. Two datastores named main with different kind values collide, because kind is not a key.
  • An unset key is a value. Under keys [group, name], two entries that both omit name collide on the same identity, so reading only the fields that happen to be set would miss it.

The operator CRDs carry sixteen of these arrays across nine kinds, so this was not a narrow case.

Proof

The self-test grew nine cases covering both list types, composite keys, the unset-key identity, and atomic's permissiveness — all sixteen pass. That is the part that matters: a walker that silently descends into nothing passes every catalog it is ever pointed at.

Against the real catalog: ok: 4 platform CR(s) admissible against operator chart 0.6.5.

The walker checked two of the three things the API server checks. Required
properties had to be present, excess properties were caught as pruned — and
`x-kubernetes-list-type` was read as documentation rather than as the
validation rule it is.

A Platform declaring two datastores both named `main` therefore passed every
gate in the org green. Every property was present, none was excess, and the
CRD's `x-kubernetes-list-type: map` with `listMapKeys: [name]` meant the API
server refused the whole object:

    spec.datastores: Duplicate value

Not a warning and not a merge of the two entries — a hard rejection, so
nothing is applied and the Application never reaches Healthy.

WHAT CHANGED

`check_list_uniqueness` runs wherever the walker meets an array, before it
descends. `map` identifies an entry by its listMapKeys tuple; `set` identifies
a scalar entry by itself; `atomic` and unannotated arrays impose no uniqueness
and are left alone, because flagging them would be a false positive that
teaches an operator to work around the gate.

Two details the rule turns on:

  - Uniqueness is per listMapKeys, not per whole entry. Two datastores named
    `main` with different `kind` values collide, because `kind` is not a key.
  - An unset key is a value. Under keys [group, name], two entries that both
    omit `name` collide on the same identity, so reading only the fields that
    happen to be set would miss it.

The operator CRDs carry sixteen of these arrays across nine kinds, so this was
not a narrow case.

The self-test grew nine cases covering both list types, composite keys, the
unset-key identity, and atomic's permissiveness. It is the part that matters:
a walker that silently descends into nothing passes every catalog it is ever
pointed at.
@github-actions

Copy link
Copy Markdown

CI Results

Check Status
Zero-placeholder gate ✅ success
YAML Lint ✅ success
Dashboard gate (live grafana.com ids + AMG-saveable) ✅ success
Kyverno policy tests (+ verify-images contract) ✅ success
Fork-safety gate (no hardcoded org, blocking) ✅ success
Helm-render (every addon × every env) ✅ success
Policy-admission (Enforce-tier Kyverno vs the fleet) ✅ success
ApplicationSet schema + sync waves ✅ success
Appset render (Karpenter subnet selector) ✅ success
Secret scan (gitleaks) ✅ success
Render + assert + schema + misconfig (all environments) ✅ success

All checks passed.

@stxkxs
stxkxs merged commit 3f8431d into main Aug 10, 2026
23 checks passed
@stxkxs
stxkxs deleted the gate-list-map-uniqueness branch August 11, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant