Istio runs on this cluster in ambient mode, and ambient "does not and will never bypass Kubernetes NetworkPolicy enforcement" — so until now no chart in this repository could put a pod into the mesh at all. This adds the named switch networkPolicy.ingress.ambientMesh, switched off by default, to all 30 chart directories (29 real charts plus template-chart, so the next new chart does not inherit the gap), and gives assertion 2 of ci/run-networkpolicy-test.sh the one exception it needs — an exception that is itself checked.
Implements design C of #143 and the approved plan in its comment. One commit per chart, 32 in total.
One object under one enabled, not two sibling values: two values can drift apart, which is the failure this design exists to prevent.
Both numbers are Istio constants, not standards, and that is why they are values with documented defaults rather than template literals — a vendor constant can change, and an operator should be able to correct it without waiting for a chart release. Their provenance is written on each one, in every chart:
15008 is Istio's HBONE port: not registered with IANA for this, prescribed by no protocol, unknown to Kubernetes.
169.254.7.127 is vendor magic, recognisable three ways: link-local169.254.0.0/16 (RFC 3927, never routed — the range one picks a magic address from); Istio's IPv6 counterpart fd16:9254:7127:1337:ffff:ffff:ffff:ffff carries the same digits plus 1337; and Kubernetes knows it in neither the NetworkPolicy API nor the kubelet — only Istio's data plane rewrites the probe source onto it.
Both read for ztunnel 1.30.6. A change in either fails silently, and what to re-check is named next to each.
redirectedProbeSources is a list because a dual-stack cluster needs both of Istio's addresses at once; it is named apart from networkPolicy.probeSources (yours, empty, means open) because the confusion risk between the two is the larger one. Deleting the object is safe (#99) — every read falls back to the chart's declared defaults, and both guards were proven load-bearing by removing them.
What it renders, and why it is one value and not two
The HBONE port inbound — where every inbound mesh connection arrives.
And the redirected probe source as an additional peer in the samefrom list, wherever the rule restricts sources at all (i.e. probeSources is non-empty). Inside the mesh the kubelet's probes are redirected by Istio and no longer arrive from the worker node's address.
The second half is the one nobody thinks of, and that is the whole argument for a named switch. An operator who adds 15008 to a port list by hand writes a policy that passes every review — and the first time probeSources is narrowed, every probe is dropped, the pod never becomes Ready, and the symptom reads as a broken application rather than as a policy. That is assertion 4 of the same script, re-created one value further along. A switch whose halves can only be had together cannot be set halfway.
Five charts render the port half only: samba, satisfactory, teamspeak-server, minecraft-server, valkey offer no networkPolicy.probeSources at all, so their probe rule is never source-restricted — and an unrestricted rule needs no probe address. An ipBlock for one would match nothing while making the rule read as if it did something, which is exactly the strict-looking empty rule this script exists to catch. The CI ties that exemption to the absence of probeSources, not to a chart name.
The CI exception, and why it is narrow
Assertion 2 holds every ingress port against the selected pod spec's containerPorts, and 15008 is deliberately none of them — ztunnel terminates it, not the application. The obvious implementation (a free ingress.extraPorts, design A) would have had to exempt operator-supplied ports, opening the assertion for all 30 charts, NodePort mistake included. So:
one named exception, one port number, gated on one value;
not granted in the main loop at all, which renders every chart with the value at its default — so there the port stays an ordinary failure, and the negative half costs nothing;
pinned in the test, not read from the chart. Since both constants are values, checking the exception against the rendered number would permit whatever the value said — design A's hole under design C's name, with a typo riding in through the configurable field. AMBIENT_PORT and AMBIENT_CIDR state what we believe Istio's numbers to be, and assertion 7 asserts both that the render at chart defaults produces exactly them and that every chart declares them (read back through ci/yaml2json, typed, not by regex). A chart that drifts is red, and changing a constant takes 30 values files and those two lines — which are what force someone to look. The renders set only enabled=true, never a port override: the pin is about the defaults we ship, not about what a release may choose;
assertion 7 holds the exception to six things on two renders of every chart plus the declared defaults: defaults match the pin; off ⇒ neither the port nor the ipBlock; on ⇒ the pinned port present, still the only non-containerPort ingress port, and a source-restricted carrier rule also carries the ipBlock. The policy is found by the <release>-<chart>- name convention, because an exception must not be granted to an object the test could not identify. The probe-source half is conditional on the chart offering probeSources — the five charts that render no ipBlock must omit the key, and that absence is asserted.
Built into the existing script rather than a new one, as for #136 — and here the reason is stronger than convenience: the exception weakens assertion 2, so it belongs beside it. A separate script can be green while the exception it is paired with is wrong, and nothing would connect the two. Everything else was already there: the job runs over every chart on every PR (no path filter can skip it), Helm is already the parser via ci/yaml2json, and the verdict/summary plumbing is shared.
Fail paths executed, not described
Path
Result
a second, different port under the exception
rejected — the exception covers exactly one number
the port rendered ungated
caught by assertion 2 in the main loop
the ipBlock rendered ungated
caught by assertion 7 only — assertion 2 never looks at from peers
the ipBlock half deleted while the port stayed, with probeSources filled
rejected — the half-set switch the design exists to prevent
the policy's name off the <release>-<chart>-<kind> convention
rejected
the object in the schema but absent from values.yaml
rejected — a --set render alone would have accepted it
a chart whose declared default port deviates
rejected — three independent checks fire at once
a port-only chart declaring redirectedProbeSources
rejected — the key reaches no rule there
a deleted object, and one with only enabled: true
both render on the chart's defaults; each guard shown load-bearing by removing it (nil pointer evaluating interface {}.enabled, and port: 0)
a release-level port override
renders, and the pinned exception demonstrably does not stretch to cover it
The name check earned its keep on the first run rather than in a rehearsal: it read the directory name, and template-chart's chart is called xxx.
Scope and proof
Minor per chart — additive value, unchanged default, unchanged render. The byte-identity was diffed per chart against origin/main, not asserted: every chart renders identically at its defaults (and, for the three with a ci/networkpolicy overlay, identically with the overlay too), and the switched-on render differs by exactly the HBONE port — plus the ipBlock for template-chart and gotenberg, the two whose overlay fills probeSources.
Local: 30 charts, 333 assertions held, 0 failed, ~25s. run-quantity-render-test.sh, run-selector-match-test.sh, run-httproute-match-test.sh, run-yaml-scalar-render-test.sh, run-bump-level-test.sh all pass as well.
Also carried: ten different key shapes under networkPolicy meant there was no single shape to insert; three charts had no egress key (homeassistant, valkey, satisfactory — satisfactory had only enabled), where networkPolicy.ingress is the first sub-object at all; and additionalProperties: false in 30 of 30 means schema and template had to land together per chart — a forgotten schema is a red chart, not an ignored key. All reasoning is in {{/* */}} comments; the rendered manifests carry no # comment, which assertion 5 checks.
ingress vs ingressController is now written down in README, in every chart's values.yaml and in every template, because the two sit side by side after this round and ingressController is no part of ingress: it is the source selector for the controller's pods. A search for ingress matches all three names including the top-level Ingress object, and one search run during this work reported ingressController as an inbound escape hatch on the strength of the substring alone.
Two limits that are part of this change, not footnotes
The 169.254.7.127/32 half is unreachable today.probeSources is empty in every chart (stalwart sets it to [] explicitly), so no release reaches that branch. Its effect goes into operation unproven; what is proven is its render, through the ci/networkpolicy overlays.
That the HBONE port alone suffices is unproven. It comes from Istio's documentation; what is measured on this cluster is only which listeners ztunnel opens. Provable at the first namespace to join the mesh — and none carries istio.io/dataplane-mode (measured 2026-10-19: 0 of 97 namespaces), so there is no path on which either could be measured end to end.
Measured while verifying the plan, and it shrinks the largest open question of the issue body rather than leaving it: ztunnel does not run in the host network. No hostNetwork on the DaemonSet, pods with their own pod IPs in istio-system (10.42.5.51 among others), Istio 1.30.6. So if a source selector turns out to be needed, it is expressible as a namespaceSelector plus podSelector — not as an unknowable node-IP ipBlock like probeSources. Assertion 3 is deliberately not taught a third justification for the open rule 15008 sits in while probeSources is empty: that would be a rule written against a guess, and it is named as a limit in the script's own header instead.
Consumer side — a note, not work in this PR
jk-cluster-config is untouched by design. Switching this on for a release there is a value key and a chart version in one PR, because Fleet does not retry a failed apply — and with additionalProperties: false in all 30 charts an unknown key does not get ignored, it fails the render.
Wiki updated in the same round: Chart-Style-Guide §15, CI-CD, the touched chart pages, and Lessons-Learned for the transferable lesson — a check that blocks a real necessity is not weakened; it gets an exception that is itself checked.
Fixes #143.
Istio runs on this cluster in ambient mode, and ambient *"does not and will never bypass Kubernetes `NetworkPolicy` enforcement"* — so until now **no chart in this repository could put a pod into the mesh at all**. This adds the named switch `networkPolicy.ingress.ambientMesh`, switched off by default, to **all 30 chart directories** (29 real charts plus `template-chart`, so the next new chart does not inherit the gap), and gives assertion 2 of `ci/run-networkpolicy-test.sh` the one exception it needs — an exception that is itself checked.
Implements design **C** of #143 and the approved plan in its comment. One commit per chart, 32 in total.
## The shape
```yaml
networkPolicy:
ingress:
ambientMesh:
enabled: false
port: 15008
redirectedProbeSources:
- 169.254.7.127/32
```
**One object under one `enabled`**, not two sibling values: two values can drift apart, which is the failure this design exists to prevent.
**Both numbers are Istio *constants*, not standards**, and that is why they are values with documented defaults rather than template literals — a vendor constant can change, and an operator should be able to correct it without waiting for a chart release. Their provenance is written on each one, in every chart:
- **`15008`** is Istio's HBONE port: not registered with IANA for this, prescribed by no protocol, **unknown to Kubernetes**.
- **`169.254.7.127`** is vendor magic, recognisable three ways: **link-local** `169.254.0.0/16` (RFC 3927, never routed — the range one picks a magic address from); Istio's IPv6 counterpart `fd16:9254:7127:1337:ffff:ffff:ffff:ffff` carries the **same digits** plus `1337`; and **Kubernetes knows it in neither the NetworkPolicy API nor the kubelet** — only Istio's data plane rewrites the probe source onto it.
- **Both read for ztunnel 1.30.6.** A change in either **fails silently**, and what to re-check is named next to each.
`redirectedProbeSources` is a **list** because a **dual-stack** cluster needs both of Istio's addresses at once; it is named apart from `networkPolicy.probeSources` (yours, empty, means *open*) because the confusion risk between the two is the larger one. **Deleting the object is safe** (#99) — every read falls back to the chart's declared defaults, and both guards were proven load-bearing by removing them.
## What it renders, and why it is one value and not two
- **The HBONE port inbound** — where every inbound mesh connection arrives.
- **And the redirected probe source** as an additional peer in the **same** `from` list, wherever the rule restricts sources at all (i.e. `probeSources` is non-empty). Inside the mesh the kubelet's probes are **redirected by Istio** and no longer arrive from the worker node's address.
The second half is the one nobody thinks of, and that is the whole argument for a named switch. An operator who adds `15008` to a port list by hand writes a policy that passes every review — and the first time `probeSources` is narrowed, **every probe is dropped, the pod never becomes `Ready`, and the symptom reads as a broken application rather than as a policy**. That is assertion 4 of the same script, re-created one value further along. A switch whose halves can only be had together cannot be set halfway.
Five charts render the **port half only**: `samba`, `satisfactory`, `teamspeak-server`, `minecraft-server`, `valkey` offer no `networkPolicy.probeSources` at all, so their probe rule is never source-restricted — and an unrestricted rule needs no probe address. An `ipBlock` for one would match nothing while making the rule read as if it did something, which is exactly the strict-looking empty rule this script exists to catch. The CI ties that exemption to **the absence of `probeSources`**, not to a chart name.
## The CI exception, and why it is narrow
Assertion 2 holds every ingress port against the selected pod spec's `containerPort`s, and `15008` is deliberately none of them — ztunnel terminates it, not the application. The obvious implementation (a free `ingress.extraPorts`, design A) would have had to exempt *operator-supplied ports*, opening the assertion for **all 30 charts**, NodePort mistake included. So:
- **one named exception, one port number, gated on one value**;
- **not granted in the main loop at all**, which renders every chart with the value at its default — so there the port stays an ordinary failure, and the negative half costs nothing;
- **pinned in the test, not read from the chart.** Since both constants are values, checking the exception against the *rendered* number would permit whatever the value said — design A's hole under design C's name, with a typo riding in through the configurable field. `AMBIENT_PORT` and `AMBIENT_CIDR` state what we believe Istio's numbers to be, and assertion 7 asserts both that the render **at chart defaults** produces exactly them **and** that **every chart declares** them (read back through `ci/yaml2json`, typed, not by regex). A chart that drifts is red, and changing a constant takes 30 values files *and* those two lines — which are what force someone to look. The renders set only `enabled=true`, never a port override: the pin is about the defaults *we ship*, not about what a release may choose;
- **assertion 7** holds the exception to six things on **two renders of every chart** plus the declared defaults: defaults match the pin; off ⇒ neither the port nor the `ipBlock`; on ⇒ the pinned port present, still the **only** non-`containerPort` ingress port, and a source-restricted carrier rule also carries the `ipBlock`. The policy is found by the `<release>-<chart>-` name convention, because an exception must not be granted to an object the test could not identify. The probe-source half is conditional on the chart offering `probeSources` — the five charts that render no `ipBlock` must **omit** the key, and that absence is asserted.
**Built into the existing script rather than a new one**, as for #136 — and here the reason is stronger than convenience: the exception **weakens assertion 2, so it belongs beside it**. A separate script can be green while the exception it is paired with is wrong, and nothing would connect the two. Everything else was already there: the job runs over every chart on every PR (no path filter can skip it), Helm is already the parser via `ci/yaml2json`, and the verdict/summary plumbing is shared.
### Fail paths executed, not described
| Path | Result |
|---|---|
| a second, different port under the exception | rejected — the exception covers exactly one number |
| the port rendered ungated | caught by **assertion 2** in the main loop |
| the `ipBlock` rendered ungated | caught by **assertion 7 only** — assertion 2 never looks at `from` peers |
| the `ipBlock` half deleted while the port stayed, with `probeSources` filled | rejected — the half-set switch the design exists to prevent |
| the policy's name off the `<release>-<chart>-<kind>` convention | rejected |
| the object in the schema but absent from `values.yaml` | rejected — a `--set` render alone would have accepted it |
| a chart whose **declared default port deviates** | rejected — three independent checks fire at once |
| a port-only chart **declaring `redirectedProbeSources`** | rejected — the key reaches no rule there |
| a **deleted object**, and one with only `enabled: true` | both **render** on the chart's defaults; each guard shown load-bearing by removing it (`nil pointer evaluating interface {}.enabled`, and `port: 0`) |
| a **release-level port override** | renders, and the pinned exception demonstrably does **not** stretch to cover it |
The name check earned its keep on the first run rather than in a rehearsal: it read the **directory** name, and `template-chart`'s chart is called `xxx`.
## Scope and proof
**Minor per chart** — additive value, unchanged default, unchanged render. The byte-identity was **diffed per chart against `origin/main`**, not asserted: every chart renders identically at its defaults (and, for the three with a `ci/networkpolicy` overlay, identically with the overlay too), and the switched-on render differs by exactly the HBONE port — plus the `ipBlock` for `template-chart` and `gotenberg`, the two whose overlay fills `probeSources`.
Local: `30 charts, 333 assertions held, 0 failed`, ~25s. `run-quantity-render-test.sh`, `run-selector-match-test.sh`, `run-httproute-match-test.sh`, `run-yaml-scalar-render-test.sh`, `run-bump-level-test.sh` all pass as well.
Also carried: **ten different key shapes** under `networkPolicy` meant there was no single shape to insert; **three charts had no `egress` key** (`homeassistant`, `valkey`, `satisfactory` — `satisfactory` had only `enabled`), where `networkPolicy.ingress` is the first sub-object at all; and `additionalProperties: false` in **30 of 30** means schema and template had to land together per chart — a forgotten schema is a red chart, not an ignored key. All reasoning is in `{{/* */}}` comments; the rendered manifests carry no `#` comment, which assertion 5 checks.
`ingress` vs `ingressController` is now written down in README, in every chart's `values.yaml` and in every template, because the two sit side by side after this round and **`ingressController` is no part of `ingress`**: it is the source selector for the controller's pods. A search for `ingress` matches all three names including the top-level Ingress object, and one search run during this work reported `ingressController` as an inbound escape hatch on the strength of the substring alone.
## Two limits that are part of this change, not footnotes
- **The `169.254.7.127/32` half is unreachable today.** `probeSources` is empty in every chart (`stalwart` sets it to `[]` explicitly), so no release reaches that branch. Its **effect goes into operation unproven**; what is proven is its render, through the `ci/networkpolicy` overlays.
- **That the HBONE port alone suffices is unproven.** It comes from Istio's documentation; what is measured on this cluster is only which listeners ztunnel opens. Provable at the first namespace to join the mesh — and **none carries `istio.io/dataplane-mode`** (measured 2026-10-19: 0 of 97 namespaces), so there is no path on which either could be measured end to end.
Measured while verifying the plan, and it **shrinks** the largest open question of the issue body rather than leaving it: **ztunnel does not run in the host network.** No `hostNetwork` on the DaemonSet, pods with their own pod IPs in `istio-system` (`10.42.5.51` among others), Istio **1.30.6**. So *if* a source selector turns out to be needed, it is expressible as a `namespaceSelector` plus `podSelector` — not as an unknowable node-IP `ipBlock` like `probeSources`. Assertion 3 is deliberately **not** taught a third justification for the open rule `15008` sits in while `probeSources` is empty: that would be a rule written against a guess, and it is named as a limit in the script's own header instead.
## Consumer side — a note, not work in this PR
`jk-cluster-config` is untouched by design. Switching this on for a release there is a **value key and a chart version in one PR**, because Fleet does not retry a failed apply — and with `additionalProperties: false` in all 30 charts an unknown key does not get ignored, it fails the render.
Wiki updated in the same round: `Chart-Style-Guide` §15, `CI-CD`, the touched chart pages, and `Lessons-Learned` for the transferable lesson — *a check that blocks a real necessity is not weakened; it gets an exception that is itself checked.*
Rebased onto main after two Renovate merges, and how the two version conflicts were resolved
Renovate merged gotenberg → 8.38.1 and rallly → 4.15.5 into main while this branch was being built, both touching the same Chart.yamlversion: lines this change bumps. Rebased onto the new main (32 commits, all re-signed, 0 32 against origin/main); the two resolutions are a judgement call each and are worth stating rather than leaving in a rebase:
Chart
main
this branch before
resolved
why
gotenberg
9.1.0+up8.38.1
9.1.0+up8.37.0
9.2.0+up8.38.1
Renovate had already taken 9.1.0 for the app bump, so the same number could not carry this feature as well — the minor goes on top ofmain, with main's app version
rallly
9.0.1+up4.15.5
9.1.0+up4.15.4
9.1.0+up4.15.5
a minor from 9.0.0 already outranks main's patch 9.0.1, so only the +up suffix and appVersion had to follow main
Both charts were then re-proven against the new main: renders byte-identical at their defaults (gotenberg also with its ci/networkpolicy overlay), and the switched-on render differing by exactly 15008 — plus the ipBlock for gotenberg, whose overlay fills probeSources. ci/run-bump-level-test.sh passes, which is the check that would have caught a version that no longer matches the change class.
Local after the rebase, all six repo-wide render tests: run-quantity-render-test.sh, run-selector-match-test.sh, run-httproute-match-test.sh, run-yaml-scalar-render-test.sh, run-networkpolicy-test.sh (30 charts, 333 assertions held, 0 failed), run-bump-level-test.sh — all pass.
Wiki landed in the same round, one commit: all 30 chart pages (five with the port-half-only row), Chart-Style-Guide §15, CI-CD, Lessons-Learned.
## Rebased onto `main` after two Renovate merges, and how the two version conflicts were resolved
Renovate merged `gotenberg` → `8.38.1` and `rallly` → `4.15.5` into `main` while this branch was being built, both touching the same `Chart.yaml` `version:` lines this change bumps. Rebased onto the new `main` (32 commits, all re-signed, `0 32` against `origin/main`); the two resolutions are a judgement call each and are worth stating rather than leaving in a rebase:
| Chart | `main` | this branch before | resolved | why |
| --- | --- | --- | --- | --- |
| `gotenberg` | `9.1.0+up8.38.1` | `9.1.0+up8.37.0` | **`9.2.0+up8.38.1`** | Renovate had already taken `9.1.0` for the app bump, so the same number could not carry this feature as well — the minor goes **on top of** `main`, with `main`'s app version |
| `rallly` | `9.0.1+up4.15.5` | `9.1.0+up4.15.4` | **`9.1.0+up4.15.5`** | a minor from `9.0.0` already outranks `main`'s patch `9.0.1`, so only the `+up` suffix and `appVersion` had to follow `main` |
Both charts were then **re-proven against the new `main`**: renders byte-identical at their defaults (`gotenberg` also with its `ci/networkpolicy` overlay), and the switched-on render differing by exactly `15008` — plus the `ipBlock` for `gotenberg`, whose overlay fills `probeSources`. `ci/run-bump-level-test.sh` passes, which is the check that would have caught a version that no longer matches the change class.
Local after the rebase, all six repo-wide render tests: `run-quantity-render-test.sh`, `run-selector-match-test.sh`, `run-httproute-match-test.sh`, `run-yaml-scalar-render-test.sh`, `run-networkpolicy-test.sh` (`30 charts, 333 assertions held, 0 failed`), `run-bump-level-test.sh` — all pass.
Wiki landed in the same round, one commit: all 30 chart pages (five with the port-half-only row), `Chart-Style-Guide` §15, `CI-CD`, `Lessons-Learned`.
Run 1226: 50 of 50 jobs success, combined commit status success, including the required validate-charts context and all 28 install-tests (Validate Helm Charts / Install-test, successful in 38m26s).
The NetworkPolicy job's own output, from the runner rather than from my machine:
— the same figures as locally, and ambient-mesh <chart>: ok for all 30. The four lines assertion 7 contributes per chart are in the job log, e.g. for apache-tika:
with networkPolicy.ingress.ambientMesh at its default the policy allows neither port 15008 nor the ipBlock 169.254.7.127/32 — the negative half of assertion 2's named exception, without which the exception would be a hole
One red run that is not this change, recorded so nobody has to re-derive it
Run 1225 on the pre-rebase head 3c2dc5d ended in failure, and it is worth naming rather than leaving as an unexplained red: the single failing job was Install-test / Install-test matrix-synapse, failing after 35s — far too fast for the rollout timeout a policy mistake produces. On the current head the same chart is successful in 1m17s, and that run is superseded in any case (it predates the rebase onto the two Renovate merges). Treated as a runner-side flake, not as a finding; the evidence for that reading is the 35s and the clean re-run of the identical chart.
## CI green on `fb27593` — 62 contexts, all success
Run [1226](https://git.jk-dev.de/jlab-cluster/helm-charts/actions/runs/1226): **50 of 50 jobs success**, combined commit status `success`, including the required `validate-charts` context and all 28 install-tests (`Validate Helm Charts / Install-test`, successful in 38m26s).
The NetworkPolicy job's own output, from the runner rather than from my machine:
```
checked: 30 - apache-tika bentopdf bulwark calibre-web-automated cyberchef
freesailarr garage gotenberg homeassistant keycloak
matrix-synapse minecraft-router minecraft-server outline
paperless-ngx patchmon rallly rss-bridge samba satisfactory
searxng stalwart sure teamspeak-server template-chart
urlaubsverwaltung valkey voucher-vault ytdlp-web-player zipline
failed: 0
assertions held: 333
```
— the same figures as locally, and `ambient-mesh <chart>: ok` for all 30. The four lines assertion 7 contributes per chart are in the job log, e.g. for `apache-tika`:
> `with networkPolicy.ingress.ambientMesh at its default the policy allows neither port 15008 nor the ipBlock 169.254.7.127/32 — the negative half of assertion 2's named exception, without which the exception would be a hole`
### One red run that is not this change, recorded so nobody has to re-derive it
Run **1225** on the pre-rebase head `3c2dc5d` ended in **failure**, and it is worth naming rather than leaving as an unexplained red: the single failing job was `Install-test / Install-test matrix-synapse`, **failing after 35s** — far too fast for the rollout timeout a policy mistake produces. On the current head the same chart is **successful in 1m17s**, and that run is superseded in any case (it predates the rebase onto the two Renovate merges). Treated as a runner-side flake, not as a finding; the evidence for that reading is the 35s and the clean re-run of the identical chart.
Gitea #143. A pod cannot be reached inside Istio's ambient mesh unless its
NetworkPolicy lets ztunnel's HBONE tunnel in - ambient explicitly does not
bypass policy enforcement - and 15008 is deliberately no containerPort of the
application, so assertion 2 of ci/run-networkpolicy-test.sh rejected it.
The switch is a named intention rather than a free port list, and it renders
two things that cannot be had separately: 15008/TCP inbound, and - where
probeSources is non-empty - 169.254.7.127/32 as an additional peer, because
inside the mesh the kubelet's probes are redirected away from the worker
node's address. Whoever opens 15008 by hand has not added the probe address,
and the first narrowed probeSources then drops every probe: the pod never
becomes Ready and the symptom reads as a broken application. That is
assertion 4 of the same script, one value further along.
Assertion 2 keeps its edge. It gets ONE named exception for ONE port number,
gated on one value, and it is not granted in the main loop at all - which
renders every chart with the value at its default, so 15008 stays an ordinary
failure there. The free-port variant was design A of #143 and would have
opened the assertion for all 30 charts.
Assertion 7 holds the exception to five things on two renders per chart:
the port and the ipBlock are absent while the switch is off, 15008 is present
while it is on, 15008 is still the ONLY ingress port that is not a
containerPort, and wherever the rule carrying it restricts sources it also
carries the ipBlock. The last one is reachable because these renders apply
ci/networkpolicy/<chart>.yaml, where probeSources is non-empty.
Built into the existing script, as for #136: the exception weakens assertion 2
and belongs beside it - a separate script could go green while the exception
it is paired with is wrong, with nothing connecting the two. The job already
runs over every chart on every pull request.
Found by running it: the policy's name comes from Chart.yaml's name, not from
the directory - template-chart is called "xxx".
Not proven, and said so in values.yaml, the template header and the script's
header: that 15008 alone suffices comes from Istio's documentation, and the
probe-source half reaches no release, because probeSources is empty in every
chart here. No namespace of this cluster carries istio.io/dataplane-mode, so
there is no path on which either could be measured. What is proven is the
render and the assertions.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders rather than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. The two halves are one value because the second is the one nobody
thinks of: 15008 added by hand leaves a policy that passes review and drops
every probe the first time probeSources is narrowed.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Five charts offer no networkPolicy.probeSources - their probes are
exec probes and put no packet on the network - so for them 169.254.7.127/32
would be an ipBlock that matches nothing, which is exactly the strict-looking
empty rule this script exists to catch. Assertion 7 now exempts them on the
absence of that value, the same conditionality assertion 4 and the overlay
guard already use, and records the exemption as a held assertion rather than
as silence.
Also names two limits of assertion 7 in its header: assertions 1, 3, 4 and 5
are not re-run on the switched-on render, and assertion 3's omission is the
interesting one - with probeSources empty, 15008 sits in a rule with no
"from" that neither of assertion 3's two justifications covers. Teaching it a
third would mean writing a rule against a guess, because where ztunnel dials
from cannot be settled until a namespace joins the mesh.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Port half only: this chart offers no networkPolicy.probeSources - its probes
put no packet on the network - so there is no redirected probe to allow and an
ipBlock for one would match nothing while making the rule look like it did
something. ci/run-networkpolicy-test.sh ties that exemption to the absence of
probeSources, not to a chart name.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Port half only: this chart offers no networkPolicy.probeSources - its probes
put no packet on the network - so there is no redirected probe to allow and an
ipBlock for one would match nothing while making the rule look like it did
something. ci/run-networkpolicy-test.sh ties that exemption to the absence of
probeSources, not to a chart name.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Port half only: this chart offers no networkPolicy.probeSources - its probes
put no packet on the network - so there is no redirected probe to allow and an
ipBlock for one would match nothing while making the rule look like it did
something. ci/run-networkpolicy-test.sh ties that exemption to the absence of
probeSources, not to a chart name.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Port half only: this chart offers no networkPolicy.probeSources - its probes
put no packet on the network - so there is no redirected probe to allow and an
ipBlock for one would match nothing while making the rule look like it did
something. ci/run-networkpolicy-test.sh ties that exemption to the absence of
probeSources, not to a chart name.
Gitea #143. Additive, default false, so the render is byte-identical to the
previous release - proven by diffing both renders against origin/main rather
than asserted.
Switched on it adds 15008/TCP, ztunnel's HBONE tunnel, to the rule carrying
the probe port, and - inside that rule's source-restricted branch -
169.254.7.127/32, the address the kubelet's probes arrive from once the pod is
in the mesh. Ambient does not bypass NetworkPolicy enforcement, so without the
port a pod whose namespace has joined the mesh is unreachable.
The two halves are one value because the second is the one nobody thinks of:
15008 added by hand leaves a policy that passes review and drops every probe
the first time probeSources is narrowed, and a pod that never becomes Ready
reads as a broken application rather than as a policy.
Minor, not major: additive value, unchanged default, unchanged render.
Port half only: this chart offers no networkPolicy.probeSources - its probes
put no packet on the network - so there is no redirected probe to allow and an
ipBlock for one would match nothing while making the rule look like it did
something. ci/run-networkpolicy-test.sh ties that exemption to the absence of
probeSources, not to a chart name.
Gitea #143. Section 15 gets the switch itself - what it renders, why its two
halves are one value, and the two things it does not prove - plus the three
names that overlap as substrings (ingress, networkPolicy.ingress,
networkPolicy.ingressController), because a search for "ingress" matches all
three and one run during this work mistook the third for an inbound escape
hatch on that basis alone.
The render-test section gets assertion 7 as a table row, the re-measured
figures (30 charts, 333 assertions, ~25s), and the six fail paths that were
executed - including the two that are only visible to it: an ungated ipBlock,
which assertion 2 cannot see because it never looks at "from" peers, and a
value declared in the schema but missing from values.yaml, which a --set
render alone would accept.
Gitea #143, maintainer's instruction. Both numbers this switch renders are
ISTIO CONSTANTS rather than standards, and a value with a documented default
is the better home for a vendor constant than a template literal: an operator
can correct it when Istio changes the number, without waiting for a chart
release.
networkPolicy:
ingress:
ambientMesh:
enabled: false
port: 15008
redirectedProbeSources:
- 169.254.7.127/32
One object under one switch, so the coupling argument survives the change
instead of being undermined by it - two separate values could drift apart,
which is the thing this design exists to prevent. redirectedProbeSources is a
LIST because a dual-stack cluster needs BOTH of Istio's addresses at once, not
one of two; that is a nameable case rather than speculation, so it does not
contradict reason 4 of the issue. Istio's IPv6 counterpart is documented as the
dual-stack addition, with the reason it is absent today unchanged: SingleStack
IPv4, and an ipBlock of the wrong family is accepted and matches nothing.
Named redirectedProbeSources, not probeSources, because the confusion risk with
networkPolicy.probeSources one level up is larger than the ingress/
ingressController one: that value holds YOUR worker node CIDRs, is empty by
default and means OPEN when empty; this one holds ISTIO's rewrite address and
ships filled, because unlike the node IPs it is a constant the chart can know.
The distinction is written where both appear.
PROVENANCE, which the previous round explained the coupling of but never
attributed. 15008 is Istio's HBONE port - not IANA-registered for this, not
prescribed by any protocol, unknown to Kubernetes. 169.254.7.127 is link-local
(169.254.0.0/16, RFC 3927, never routed - the range one picks vendor magic out
of); Istio's IPv6 counterpart fd16:9254:7127:1337:ffff:ffff:ffff:ffff carries
the same digits plus 1337, which is what vendor constants look like; and
Kubernetes knows the address in neither the NetworkPolicy API nor the kubelet -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6. If either changes, the failure is SILENT: a pod unreachable in
the mesh, or probes dropped where probeSources is non-empty, which is nowhere
today.
NULL-SAFE, per #99 and because #136 shipped this exact defect one value away
(its NOTES.txt branch dereferenced .networkPolicy.egress directly): every read
goes through a fallback reproducing the chart's own declared defaults, so a
deleted object or one carrying only "enabled: true" renders the defaults rather
than failing. Clearing the probe-source list restores the constant instead of
removing the ipBlock, deliberately - the halves are not separable, and
enabled: false is how you open nothing.
THE CONSEQUENCE, and it is the point of the CI half. With the port
configurable, the exception can no longer be checked against the rendered
value: "whatever the value says" is design A's hole wearing design C's name,
and a mistyped port would pass by sitting in the configurable field. So the
expectation is PINNED IN THE TEST - AMBIENT_PORT and AMBIENT_CIDR - and
assertion 7 now checks two things instead of one: that the render at chart
defaults produces exactly that port and that ipBlock, and that every chart's
values.yaml DECLARES the same defaults, read back through ci/yaml2json rather
than by regex. A chart that drifts is red. Changing an Istio constant means
touching 30 values files AND the pinned lines, and the pinned lines are what
force someone to look.
That block is therefore also the single place saying what we hold Istio's
numbers to be, so it carries the provenance too. The renders set only
enabled=true and never a port override, on purpose: the pin is a statement
about the defaults we ship, not about what a release may choose - an operator
overriding a value is outside this test's reach, as for every value here.
The declared-defaults check is conditional on the chart offering probeSources,
like the inseparability check and assertion 4: the five charts whose probe rule
is never source-restricted render no ipBlock, so for them the key must be
ABSENT - a value reaching no rule reads as a control that does nothing - and
that absence is asserted rather than tolerated. Their schemas drop it too.
No version change: nothing of this is published, the switch stays additive with
its default off, and the render at defaults is byte-identical - re-diffed per
chart against origin/main, not assumed.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
No redirectedProbeSources here, in neither values.yaml nor the schema: this
chart offers no networkPolicy.probeSources, so its probe rule is never
source-restricted and no ipBlock is ever rendered. The key would reach no rule
and read as a control that does nothing, which is worse than one that is
absent. ci/run-networkpolicy-test.sh asserts that absence rather than
tolerating it.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
No redirectedProbeSources here, in neither values.yaml nor the schema: this
chart offers no networkPolicy.probeSources, so its probe rule is never
source-restricted and no ipBlock is ever rendered. The key would reach no rule
and read as a control that does nothing, which is worse than one that is
absent. ci/run-networkpolicy-test.sh asserts that absence rather than
tolerating it.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
No redirectedProbeSources here, in neither values.yaml nor the schema: this
chart offers no networkPolicy.probeSources, so its probe rule is never
source-restricted and no ipBlock is ever rendered. The key would reach no rule
and read as a control that does nothing, which is worse than one that is
absent. ci/run-networkpolicy-test.sh asserts that absence rather than
tolerating it.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
No redirectedProbeSources here, in neither values.yaml nor the schema: this
chart offers no networkPolicy.probeSources, so its probe rule is never
source-restricted and no ipBlock is ever rendered. The key would reach no rule
and read as a control that does nothing, which is worse than one that is
absent. ci/run-networkpolicy-test.sh asserts that absence rather than
tolerating it.
Gitea #143, maintainer's instruction. The HBONE port and the redirected probe
source are ISTIO CONSTANTS, not standards, so they move from template literals
into values with documented defaults - an operator can then correct them when
Istio changes a number, without waiting for a chart release.
One object under one "enabled", so the two halves still cannot be set
separately; two values could drift apart, which is what this design exists to
prevent. Every read is null-safe (#99), so a deleted object or one carrying
only "enabled: true" falls back to the defaults declared here rather than
dereferencing nil - the defect #136 shipped one value away.
Provenance now written on each constant: 15008 is Istio's HBONE port, not
IANA-registered for this and unknown to Kubernetes; 169.254.7.127 is link-local
(RFC 3927, never routed), its IPv6 counterpart carries the same digits plus
1337, and neither the NetworkPolicy API nor the kubelet knows the address -
only Istio's data plane rewrites the probe source onto it. Both read for
ztunnel 1.30.6, and a change in either fails silently.
The exception in ci/run-networkpolicy-test.sh stays pinned to the numbers that
test names, and additionally asserts this chart declares the same defaults -
never "whatever the value says", which would let a mistyped port in through a
configurable field.
No version change: nothing is published yet, the default is still off, and the
render at defaults is byte-identical - re-diffed against origin/main.
No redirectedProbeSources here, in neither values.yaml nor the schema: this
chart offers no networkPolicy.probeSources, so its probe rule is never
source-restricted and no ipBlock is ever rendered. The key would reach no rule
and read as a control that does nothing, which is worse than one that is
absent. ci/run-networkpolicy-test.sh asserts that absence rather than
tolerating it.
Gitea #143. Section 15 gains the object shape and - the part the previous
round explained the coupling of but never attributed - where both numbers come
from: 15008 is Istio's HBONE port, not IANA-registered for this and unknown to
Kubernetes; 169.254.7.127 is link-local (RFC 3927, never routed), Istio's IPv6
counterpart carries the same digits plus 1337, and neither the NetworkPolicy
API nor the kubelet knows the address. Both read for ztunnel 1.30.6, with the
silent failure mode and what to re-check spelled out.
The render-test section gains the pinned expectation and why it is pinned: once
the port is configurable, checking the exception against the rendered value
permits whatever the value says, which is design A's hole under design C's
name. Six things on two renders plus the declared defaults, ten fail paths
executed.
And a fourth name joins the substring table, whose confusion risk is the
larger one: networkPolicy.probeSources holds YOUR node CIDRs and means OPEN
when empty, while ambientMesh.redirectedProbeSources holds ISTIO's rewrite
address and ships filled.
Reshaped on the maintainer's instruction: ambientMesh is an object, and the CI exception now carries a pinned expectation
Two changes, and the second has a consequence that had to be handled rather than inherited.
1. The provenance of both constants is written down
The previous round explained the coupling of the two halves well and never said where the numbers come from. It read generically — "the kubelet's probes are redirected… they arrive from 169.254.7.127" — rather than "inside Istio's ambient mesh, by Istio's choice". Now, in every chart's values.yaml, every template, the schema, the test, README and the wiki:
15008 is Istio's HBONE port. Not registered with IANA for this, prescribed by no protocol, and unknown to Kubernetes. A constant Istio picked and Istio can change.
169.254.7.127 is recognisable as vendor magic rather than protocol three ways: it is link-local, 169.254.0.0/16 (RFC 3927) — reserved for node-local use and never routed, exactly the range one picks a magic address out of; Istio's IPv6 counterpart fd16:9254:7127:1337:ffff:ffff:ffff:ffff carries the same digits (9254:7127is169.254.7.127) plus 1337, which is what vendor constants look like; and Kubernetes knows the address in neither the NetworkPolicy API nor the kubelet — only Istio's own data plane rewrites the probe source onto it.
Both read for ztunnel 1.30.6, with the failure mode stated: if Istio changes either, it fails silently — a pod unreachable in the mesh, or probes dropped and only where probeSources is non-empty, which is nowhere today. Nothing here and nothing in Kubernetes would report it. What to re-check is named too: Istio's release notes, the defaults in all 30 charts, and the pinned expectation in the test.
One object under one enabled, not two sibling values — two values can drift apart, which is the failure this whole design exists to prevent, so the shape supports the coupling argument rather than undermining it.
redirectedProbeSources is a list, because a dual-stack cluster needs both of Istio's addresses at once, not one of two — a nameable case, so it does not contradict reason 4 of the issue. The IPv6 counterpart is documented as the dual-stack addition, with the reason it is absent unchanged: SingleStack IPv4, and an ipBlock of the wrong family is accepted and matches nothing. It goes alongside, never instead.
Named redirectedProbeSources, not probeSources, and the distinction is written where both appear (README, the style guide, every chart's values.yaml, the schema):
Name
Whose addresses
Default
Empty means
networkPolicy.probeSources
yours — the worker node CIDRs, which no chart can know
[]
the probe rule is open
…ambientMesh.redirectedProbeSources
Istio's — its rewrite address
[169.254.7.127/32], shipped filled, because unlike node IPs it is a constant the chart can know
n/a — clearing it restores the default, deliberately
Null-safe per #99, and both guards proven load-bearing by removing them — not asserted:
the direct chained read $npIngress.ambientMesh.enabled on a deleted object fails with nil pointer evaluating interface {}.enabled, which is the shape of the defect #136 shipped one value away (its NOTES.txt branch dereferenced .networkPolicy.egress directly);
without the port fallback, a nilled port renders port: 0 — accepted by the API server and silently wrong.
With the guards in place: ambientMesh: null renders with the switch off and no port; an object carrying only enabled: true with the other two nilled renders 15008 and the ipBlock from the fallbacks.
The five charts that render no ipBlock (samba, satisfactory, teamspeak-server, minecraft-server, valkey) omit redirectedProbeSources from bothvalues.yaml and the schema: there it would reach no rule, and a value that silently does nothing reads as a control. That absence is asserted, not tolerated.
The consequence, handled: the exception is pinned in the test
Once the port is configurable, the "exactly one port number" tightening can no longer check against the rendered value. An exception permitting whatever the value says is design A's hole wearing design C's name — a mistyped port would pass simply by sitting in the configurable field, which is the single reason design A was rejected.
So the expectation is pinned in ci/run-networkpolicy-test.sh (AMBIENT_PORT, AMBIENT_CIDR), and assertion 7 now checks two things against that statement:
the render at chart defaults produces exactly that port and that ipBlock, and
every chart's values.yaml declares the same defaults — read back through ci/yaml2json, typed, not by regex (a substring test over a commented file is how the probeSources check was once fooled by a deleted key whose comment survived).
A chart that drifts is red. If Istio changes a constant it takes 30 values files and the two pinned lines — and the pinned lines are what force someone to look. That block is consequently the one place in the repository stating what we hold Istio's numbers to be, which makes it the answer to the provenance question as well, so it carries that text.
The delicate part — a release-level override — resolved explicitly. The renders set onlyenabled=true, never a port override, on purpose: the pin is a statement about the defaults we ship, not about what a release may choose. An operator override is outside the test's reach, as is true of every value here. Both halves were executed: the override renders (operator freedom intact), and forcing the test to render it shows the pinned exception does not stretch to cover it — so there is no path on which a non-pinned port is silently blessed.
Ten fail paths executed
Path
Outcome
a second, different port under the exception
rejected
the port rendered ungated
caught by assertion 2 in the main loop
the ipBlock rendered ungated
caught by assertion 7 only — assertion 2 never looks at from peers
the ipBlock half deleted while the port stayed
rejected — the half-set switch
policy name off the <release>-<chart>-<kind> convention
rejected
object in the schema, absent from values.yaml
rejected
a chart whose declared default port deviates (15009)
rejected — three independent checks fire: the declared-defaults comparison, the pinned port missing from the render, and 15009 not being covered by the exception
a port-only chart declaring redirectedProbeSources
rejected — reaches no rule there
a deleted object, and one with only enabled: true
both render on the chart's defaults; each guard shown load-bearing by removal
a release-level port override
renders, and the pin demonstrably does not cover it
Scope, versions, proof
All 30 charts. Versions unchanged from where they were — the switch is still additive with its default off, the render at defaults is still byte-identical, and nothing here is published, so boolean → object costs no extra step.
Re-proven, not carried over: all 30 renders byte-identical at defaults against origin/main (byte counts unchanged from the previous round; the three charts with a ci/networkpolicy overlay proven with and without it), and all 30 non-empty with the switch on. Locally: 30 charts, 333 assertions held, 0 failed, and all six repo-wide render tests pass.
Rebased again
main moved once more: Renovate's Update Helm release valkey to v2, which took a major on both parents. Resolved by keeping main's side wholesale — the dependency bump and the major — and putting this change's minor on top: paperless-ngx 15.0.0 → 15.1.0+up3.3.1, stalwart 3.0.0 → 3.1.0+upv0.16.26. The valkey dependency pin stays at main's published 2.0.0+up9.1.2.alpine; raising it to the 2.1.0 this PR produces is Renovate's job after that version publishes, and pinning it here would reference a version the registry does not have yet and break helm dependency update. Both charts re-proven against the new main afterwards; run-bump-level-test.sh passes.
## Reshaped on the maintainer's instruction: `ambientMesh` is an object, and the CI exception now carries a **pinned** expectation
Two changes, and the second has a consequence that had to be handled rather than inherited.
### 1. The provenance of both constants is written down
The previous round explained the *coupling* of the two halves well and never said **where the numbers come from**. It read generically — *"the kubelet's probes are redirected… they arrive from 169.254.7.127"* — rather than "inside **Istio's** ambient mesh, **by Istio's choice**". Now, in every chart's `values.yaml`, every template, the schema, the test, README and the wiki:
- **`15008`** is Istio's **HBONE port**. Not registered with IANA for this, prescribed by no protocol, and **unknown to Kubernetes**. A constant Istio picked and Istio can change.
- **`169.254.7.127`** is recognisable as vendor magic rather than protocol three ways: it is **link-local**, `169.254.0.0/16` (RFC 3927) — reserved for node-local use and **never routed**, exactly the range one picks a magic address out of; Istio's IPv6 counterpart `fd16:9254:7127:1337:ffff:ffff:ffff:ffff` carries the **same digits** (`9254:7127` *is* `169.254.7.127`) plus `1337`, which is what vendor constants look like; and **Kubernetes knows the address in neither the NetworkPolicy API nor the kubelet** — only Istio's own data plane rewrites the probe source onto it.
- **Both read for ztunnel 1.30.6**, with the failure mode stated: if Istio changes either, **it fails silently** — a pod unreachable in the mesh, or probes dropped and only where `probeSources` is non-empty, which is nowhere today. Nothing here and nothing in Kubernetes would report it. What to re-check is named too: Istio's release notes, the defaults in all 30 charts, **and** the pinned expectation in the test.
### 2. Both numbers became values
```yaml
networkPolicy:
ingress:
ambientMesh:
enabled: false
port: 15008
redirectedProbeSources:
- 169.254.7.127/32
```
**One object under one `enabled`**, not two sibling values — two values can drift apart, which is the failure this whole design exists to prevent, so the shape supports the coupling argument rather than undermining it.
**`redirectedProbeSources` is a list**, because a **dual-stack** cluster needs *both* of Istio's addresses at once, not one of two — a nameable case, so it does not contradict reason 4 of the issue. The IPv6 counterpart is documented as the dual-stack addition, with the reason it is absent unchanged: SingleStack IPv4, and an `ipBlock` of the wrong family is accepted and matches nothing. It goes *alongside*, never *instead*.
**Named `redirectedProbeSources`, not `probeSources`**, and the distinction is written where both appear (README, the style guide, every chart's `values.yaml`, the schema):
| Name | Whose addresses | Default | Empty means |
| --- | --- | --- | --- |
| `networkPolicy.probeSources` | **yours** — the worker node CIDRs, which no chart can know | `[]` | the probe rule is **open** |
| `…ambientMesh.redirectedProbeSources` | **Istio's** — its rewrite address | `[169.254.7.127/32]`, shipped *filled*, because unlike node IPs it is a constant the chart **can** know | n/a — clearing it restores the default, deliberately |
**Null-safe per #99, and both guards proven load-bearing by removing them** — not asserted:
- the direct chained read `$npIngress.ambientMesh.enabled` on a deleted object fails with `nil pointer evaluating interface {}.enabled`, which is the shape of the defect **#136 shipped one value away** (its `NOTES.txt` branch dereferenced `.networkPolicy.egress` directly);
- without the port fallback, a nilled `port` renders **`port: 0`** — accepted by the API server and silently wrong.
With the guards in place: `ambientMesh: null` renders with the switch off and no port; an object carrying only `enabled: true` with the other two nilled renders **15008 and the ipBlock** from the fallbacks.
The five charts that render no `ipBlock` (`samba`, `satisfactory`, `teamspeak-server`, `minecraft-server`, `valkey`) omit `redirectedProbeSources` from **both** `values.yaml` and the schema: there it would reach no rule, and a value that silently does nothing reads as a control. That absence is **asserted**, not tolerated.
### The consequence, handled: the exception is pinned in the test
**Once the port is configurable, the "exactly one port number" tightening can no longer check against the rendered value.** An exception permitting *whatever the value says* is **design A's hole wearing design C's name** — a mistyped port would pass simply by sitting in the configurable field, which is the single reason design A was rejected.
So the expectation is **pinned in `ci/run-networkpolicy-test.sh`** (`AMBIENT_PORT`, `AMBIENT_CIDR`), and assertion 7 now checks **two** things against that statement:
1. the render **at chart defaults** produces exactly that port and that `ipBlock`, **and**
2. **every chart's `values.yaml` declares the same defaults** — read back through `ci/yaml2json`, typed, not by regex (a substring test over a commented file is how the `probeSources` check was once fooled by a deleted key whose comment survived).
**A chart that drifts is red.** If Istio changes a constant it takes 30 values files **and** the two pinned lines — and the pinned lines are what force someone to look. That block is consequently the one place in the repository stating what we hold Istio's numbers to be, which makes it the answer to the provenance question as well, so it carries that text.
**The delicate part — a release-level override — resolved explicitly.** The renders set **only** `enabled=true`, never a port override, on purpose: the pin is a statement about the defaults *we ship*, not about what a release may choose. An operator override is outside the test's reach, as is true of every value here. Both halves were executed: the override **renders** (operator freedom intact), and forcing the test to render it shows the pinned exception **does not stretch to cover it** — so there is no path on which a non-pinned port is silently blessed.
### Ten fail paths executed
| Path | Outcome |
|---|---|
| a second, different port under the exception | rejected |
| the port rendered ungated | caught by **assertion 2** in the main loop |
| the `ipBlock` rendered ungated | caught by **assertion 7 only** — assertion 2 never looks at `from` peers |
| the `ipBlock` half deleted while the port stayed | rejected — the half-set switch |
| policy name off the `<release>-<chart>-<kind>` convention | rejected |
| object in the schema, absent from `values.yaml` | rejected |
| **a chart whose declared default port deviates (15009)** | rejected — **three** independent checks fire: the declared-defaults comparison, the pinned port missing from the render, and 15009 not being covered by the exception |
| **a port-only chart declaring `redirectedProbeSources`** | rejected — reaches no rule there |
| **a deleted object, and one with only `enabled: true`** | both **render** on the chart's defaults; each guard shown load-bearing by removal |
| **a release-level port override** | renders, and the pin demonstrably does not cover it |
### Scope, versions, proof
All 30 charts. **Versions unchanged from where they were** — the switch is still additive with its default off, the render at defaults is still byte-identical, and nothing here is published, so boolean → object costs no extra step.
**Re-proven, not carried over:** all 30 renders byte-identical at defaults against `origin/main` (byte counts unchanged from the previous round; the three charts with a `ci/networkpolicy` overlay proven with and without it), and all 30 non-empty with the switch on. Locally: `30 charts, 333 assertions held, 0 failed`, and all six repo-wide render tests pass.
### Rebased again
`main` moved once more: Renovate's `Update Helm release valkey to v2`, which took a **major** on both parents. Resolved by keeping main's side wholesale — the dependency bump and the major — and putting this change's minor on top: **`paperless-ngx` 15.0.0 → `15.1.0+up3.3.1`**, **`stalwart` 3.0.0 → `3.1.0+upv0.16.26`**. The `valkey` dependency pin stays at main's published `2.0.0+up9.1.2.alpine`; raising it to the `2.1.0` this PR produces is Renovate's job after that version publishes, and pinning it here would reference a version the registry does not have yet and break `helm dependency update`. Both charts re-proven against the new `main` afterwards; `run-bump-level-test.sh` passes.
CI green on the reshaped head 95e0722 — 94 contexts, all success
Run 1245: 50 of 50 jobs success, combined commit status success, 94 of 94 contexts success, including the required validate-charts context and all 28 install-tests.
The NetworkPolicy job's output from the runner, unchanged in total from before the reshape — which is the point, since the switch is still additive and the render at defaults is still byte-identical:
ambient-mesh <chart>: ok for all 30, and the new pinned-defaults assertion reporting per chart — both variants, from the job log:
apache-tika: declares the pinned ambient-mesh defaults verbatim - enabled false, port 15008, redirectedProbeSources [169.254.7.127/32] - so the named exception below is granted to a number this chart really ships, and not to whatever a value happened to say
minecraft-server: declares the pinned ambient-mesh defaults verbatim - enabled false, port 15008, and no redirectedProbeSources, correctly, since this chart renders no ipBlock at all - …
Two process notes, so they are not re-derived from the run list
Three runs raced on this branch. 1243 and 1244 were superseded by the rebase and the reshape; Gitea cancelled 1244 itself, 1243 ran to completion ahead of the queue. Only 1245 is the current head. I could not cancel the stale ones myself — POST …/actions/runs/<id>/cancel returns HTTP 403 for the bot account, which is worth knowing the next time a long matrix is blocked by a superseded run.
main moved twice during this work (two Renovate merges), and both rebases are documented in the comments above with how each version conflict was resolved.
Wiki updated in the same round, one commit, fetch+rebase and no force: all 30 chart pages (the five that render no ipBlock omit redirectedProbeSources entirely), Chart-Style-Guide §15 — including the fourth entry in the overlapping-names table — CI-CD, and a follow-on entry in Lessons-Learned on the general lesson: when a constant becomes configurable, pin the expectation in the check rather than in the thing being checked, and do not let making it configurable re-separate halves that were deliberately joined.
Not merged, and no auto-merge armed.
## CI green on the reshaped head `95e0722` — 94 contexts, all success
Run [1245](https://git.jk-dev.de/jlab-cluster/helm-charts/actions/runs/1245): **50 of 50 jobs success**, combined commit status `success`, **94 of 94 contexts success**, including the required `validate-charts` context and all 28 install-tests.
The NetworkPolicy job's output from the runner, unchanged in total from before the reshape — which is the point, since the switch is still additive and the render at defaults is still byte-identical:
```
checked: 30 - apache-tika bentopdf bulwark calibre-web-automated cyberchef
freesailarr garage gotenberg homeassistant keycloak
matrix-synapse minecraft-router minecraft-server outline
paperless-ngx patchmon rallly rss-bridge samba satisfactory
searxng stalwart sure teamspeak-server template-chart
urlaubsverwaltung valkey voucher-vault ytdlp-web-player zipline
failed: 0
assertions held: 333
```
`ambient-mesh <chart>: ok` for all 30, and the new pinned-defaults assertion reporting per chart — both variants, from the job log:
> `apache-tika: declares the pinned ambient-mesh defaults verbatim - enabled false, port 15008, redirectedProbeSources [169.254.7.127/32] - so the named exception below is granted to a number this chart really ships, and not to whatever a value happened to say`
> `minecraft-server: declares the pinned ambient-mesh defaults verbatim - enabled false, port 15008, and no redirectedProbeSources, correctly, since this chart renders no ipBlock at all - …`
### Two process notes, so they are not re-derived from the run list
- **Three runs raced on this branch.** 1243 and 1244 were superseded by the rebase and the reshape; Gitea cancelled 1244 itself, 1243 ran to completion ahead of the queue. Only **1245** is the current head. I could not cancel the stale ones myself — `POST …/actions/runs/<id>/cancel` returns **HTTP 403** for the bot account, which is worth knowing the next time a long matrix is blocked by a superseded run.
- `main` moved twice during this work (two Renovate merges), and both rebases are documented in the comments above with how each version conflict was resolved.
Wiki updated in the same round, one commit, fetch+rebase and no force: all 30 chart pages (the five that render no `ipBlock` omit `redirectedProbeSources` entirely), `Chart-Style-Guide` §15 — including the fourth entry in the overlapping-names table — `CI-CD`, and a follow-on entry in `Lessons-Learned` on the general lesson: **when a constant becomes configurable, pin the expectation in the check rather than in the thing being checked, and do not let making it configurable re-separate halves that were deliberately joined.**
Not merged, and no auto-merge armed.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #143.
Istio runs on this cluster in ambient mode, and ambient "does not and will never bypass Kubernetes
NetworkPolicyenforcement" — so until now no chart in this repository could put a pod into the mesh at all. This adds the named switchnetworkPolicy.ingress.ambientMesh, switched off by default, to all 30 chart directories (29 real charts plustemplate-chart, so the next new chart does not inherit the gap), and gives assertion 2 ofci/run-networkpolicy-test.shthe one exception it needs — an exception that is itself checked.Implements design C of #143 and the approved plan in its comment. One commit per chart, 32 in total.
The shape
One object under one
enabled, not two sibling values: two values can drift apart, which is the failure this design exists to prevent.Both numbers are Istio constants, not standards, and that is why they are values with documented defaults rather than template literals — a vendor constant can change, and an operator should be able to correct it without waiting for a chart release. Their provenance is written on each one, in every chart:
15008is Istio's HBONE port: not registered with IANA for this, prescribed by no protocol, unknown to Kubernetes.169.254.7.127is vendor magic, recognisable three ways: link-local169.254.0.0/16(RFC 3927, never routed — the range one picks a magic address from); Istio's IPv6 counterpartfd16:9254:7127:1337:ffff:ffff:ffff:ffffcarries the same digits plus1337; and Kubernetes knows it in neither the NetworkPolicy API nor the kubelet — only Istio's data plane rewrites the probe source onto it.redirectedProbeSourcesis a list because a dual-stack cluster needs both of Istio's addresses at once; it is named apart fromnetworkPolicy.probeSources(yours, empty, means open) because the confusion risk between the two is the larger one. Deleting the object is safe (#99) — every read falls back to the chart's declared defaults, and both guards were proven load-bearing by removing them.What it renders, and why it is one value and not two
fromlist, wherever the rule restricts sources at all (i.e.probeSourcesis non-empty). Inside the mesh the kubelet's probes are redirected by Istio and no longer arrive from the worker node's address.The second half is the one nobody thinks of, and that is the whole argument for a named switch. An operator who adds
15008to a port list by hand writes a policy that passes every review — and the first timeprobeSourcesis narrowed, every probe is dropped, the pod never becomesReady, and the symptom reads as a broken application rather than as a policy. That is assertion 4 of the same script, re-created one value further along. A switch whose halves can only be had together cannot be set halfway.Five charts render the port half only:
samba,satisfactory,teamspeak-server,minecraft-server,valkeyoffer nonetworkPolicy.probeSourcesat all, so their probe rule is never source-restricted — and an unrestricted rule needs no probe address. AnipBlockfor one would match nothing while making the rule read as if it did something, which is exactly the strict-looking empty rule this script exists to catch. The CI ties that exemption to the absence ofprobeSources, not to a chart name.The CI exception, and why it is narrow
Assertion 2 holds every ingress port against the selected pod spec's
containerPorts, and15008is deliberately none of them — ztunnel terminates it, not the application. The obvious implementation (a freeingress.extraPorts, design A) would have had to exempt operator-supplied ports, opening the assertion for all 30 charts, NodePort mistake included. So:AMBIENT_PORTandAMBIENT_CIDRstate what we believe Istio's numbers to be, and assertion 7 asserts both that the render at chart defaults produces exactly them and that every chart declares them (read back throughci/yaml2json, typed, not by regex). A chart that drifts is red, and changing a constant takes 30 values files and those two lines — which are what force someone to look. The renders set onlyenabled=true, never a port override: the pin is about the defaults we ship, not about what a release may choose;ipBlock; on ⇒ the pinned port present, still the only non-containerPortingress port, and a source-restricted carrier rule also carries theipBlock. The policy is found by the<release>-<chart>-name convention, because an exception must not be granted to an object the test could not identify. The probe-source half is conditional on the chart offeringprobeSources— the five charts that render noipBlockmust omit the key, and that absence is asserted.Built into the existing script rather than a new one, as for #136 — and here the reason is stronger than convenience: the exception weakens assertion 2, so it belongs beside it. A separate script can be green while the exception it is paired with is wrong, and nothing would connect the two. Everything else was already there: the job runs over every chart on every PR (no path filter can skip it), Helm is already the parser via
ci/yaml2json, and the verdict/summary plumbing is shared.Fail paths executed, not described
ipBlockrendered ungatedfrompeersipBlockhalf deleted while the port stayed, withprobeSourcesfilled<release>-<chart>-<kind>conventionvalues.yaml--setrender alone would have accepted itredirectedProbeSourcesenabled: truenil pointer evaluating interface {}.enabled, andport: 0)The name check earned its keep on the first run rather than in a rehearsal: it read the directory name, and
template-chart's chart is calledxxx.Scope and proof
Minor per chart — additive value, unchanged default, unchanged render. The byte-identity was diffed per chart against
origin/main, not asserted: every chart renders identically at its defaults (and, for the three with aci/networkpolicyoverlay, identically with the overlay too), and the switched-on render differs by exactly the HBONE port — plus theipBlockfortemplate-chartandgotenberg, the two whose overlay fillsprobeSources.Local:
30 charts, 333 assertions held, 0 failed, ~25s.run-quantity-render-test.sh,run-selector-match-test.sh,run-httproute-match-test.sh,run-yaml-scalar-render-test.sh,run-bump-level-test.shall pass as well.Also carried: ten different key shapes under
networkPolicymeant there was no single shape to insert; three charts had noegresskey (homeassistant,valkey,satisfactory—satisfactoryhad onlyenabled), wherenetworkPolicy.ingressis the first sub-object at all; andadditionalProperties: falsein 30 of 30 means schema and template had to land together per chart — a forgotten schema is a red chart, not an ignored key. All reasoning is in{{/* */}}comments; the rendered manifests carry no#comment, which assertion 5 checks.ingressvsingressControlleris now written down in README, in every chart'svalues.yamland in every template, because the two sit side by side after this round andingressControlleris no part ofingress: it is the source selector for the controller's pods. A search foringressmatches all three names including the top-level Ingress object, and one search run during this work reportedingressControlleras an inbound escape hatch on the strength of the substring alone.Two limits that are part of this change, not footnotes
169.254.7.127/32half is unreachable today.probeSourcesis empty in every chart (stalwartsets it to[]explicitly), so no release reaches that branch. Its effect goes into operation unproven; what is proven is its render, through theci/networkpolicyoverlays.istio.io/dataplane-mode(measured 2026-10-19: 0 of 97 namespaces), so there is no path on which either could be measured end to end.Measured while verifying the plan, and it shrinks the largest open question of the issue body rather than leaving it: ztunnel does not run in the host network. No
hostNetworkon the DaemonSet, pods with their own pod IPs inistio-system(10.42.5.51among others), Istio 1.30.6. So if a source selector turns out to be needed, it is expressible as anamespaceSelectorpluspodSelector— not as an unknowable node-IPipBlocklikeprobeSources. Assertion 3 is deliberately not taught a third justification for the open rule15008sits in whileprobeSourcesis empty: that would be a rule written against a guess, and it is named as a limit in the script's own header instead.Consumer side — a note, not work in this PR
jk-cluster-configis untouched by design. Switching this on for a release there is a value key and a chart version in one PR, because Fleet does not retry a failed apply — and withadditionalProperties: falsein all 30 charts an unknown key does not get ignored, it fails the render.Wiki updated in the same round:
Chart-Style-Guide§15,CI-CD, the touched chart pages, andLessons-Learnedfor the transferable lesson — a check that blocks a real necessity is not weakened; it gets an exception that is itself checked.3c2dc5d15btofb275935c9Rebased onto
mainafter two Renovate merges, and how the two version conflicts were resolvedRenovate merged
gotenberg→8.38.1andrallly→4.15.5intomainwhile this branch was being built, both touching the sameChart.yamlversion:lines this change bumps. Rebased onto the newmain(32 commits, all re-signed,0 32againstorigin/main); the two resolutions are a judgement call each and are worth stating rather than leaving in a rebase:maingotenberg9.1.0+up8.38.19.1.0+up8.37.09.2.0+up8.38.19.1.0for the app bump, so the same number could not carry this feature as well — the minor goes on top ofmain, withmain's app versionrallly9.0.1+up4.15.59.1.0+up4.15.49.1.0+up4.15.59.0.0already outranksmain's patch9.0.1, so only the+upsuffix andappVersionhad to followmainBoth charts were then re-proven against the new
main: renders byte-identical at their defaults (gotenbergalso with itsci/networkpolicyoverlay), and the switched-on render differing by exactly15008— plus theipBlockforgotenberg, whose overlay fillsprobeSources.ci/run-bump-level-test.shpasses, which is the check that would have caught a version that no longer matches the change class.Local after the rebase, all six repo-wide render tests:
run-quantity-render-test.sh,run-selector-match-test.sh,run-httproute-match-test.sh,run-yaml-scalar-render-test.sh,run-networkpolicy-test.sh(30 charts, 333 assertions held, 0 failed),run-bump-level-test.sh— all pass.Wiki landed in the same round, one commit: all 30 chart pages (five with the port-half-only row),
Chart-Style-Guide§15,CI-CD,Lessons-Learned.CI green on
fb27593— 62 contexts, all successRun 1226: 50 of 50 jobs success, combined commit status
success, including the requiredvalidate-chartscontext and all 28 install-tests (Validate Helm Charts / Install-test, successful in 38m26s).The NetworkPolicy job's own output, from the runner rather than from my machine:
— the same figures as locally, and
ambient-mesh <chart>: okfor all 30. The four lines assertion 7 contributes per chart are in the job log, e.g. forapache-tika:One red run that is not this change, recorded so nobody has to re-derive it
Run 1225 on the pre-rebase head
3c2dc5dended in failure, and it is worth naming rather than leaving as an unexplained red: the single failing job wasInstall-test / Install-test matrix-synapse, failing after 35s — far too fast for the rollout timeout a policy mistake produces. On the current head the same chart is successful in 1m17s, and that run is superseded in any case (it predates the rebase onto the two Renovate merges). Treated as a runner-side flake, not as a finding; the evidence for that reading is the 35s and the clean re-run of the identical chart.33da8800a0to95e0722d0cReshaped on the maintainer's instruction:
ambientMeshis an object, and the CI exception now carries a pinned expectationTwo changes, and the second has a consequence that had to be handled rather than inherited.
1. The provenance of both constants is written down
The previous round explained the coupling of the two halves well and never said where the numbers come from. It read generically — "the kubelet's probes are redirected… they arrive from 169.254.7.127" — rather than "inside Istio's ambient mesh, by Istio's choice". Now, in every chart's
values.yaml, every template, the schema, the test, README and the wiki:15008is Istio's HBONE port. Not registered with IANA for this, prescribed by no protocol, and unknown to Kubernetes. A constant Istio picked and Istio can change.169.254.7.127is recognisable as vendor magic rather than protocol three ways: it is link-local,169.254.0.0/16(RFC 3927) — reserved for node-local use and never routed, exactly the range one picks a magic address out of; Istio's IPv6 counterpartfd16:9254:7127:1337:ffff:ffff:ffff:ffffcarries the same digits (9254:7127is169.254.7.127) plus1337, which is what vendor constants look like; and Kubernetes knows the address in neither the NetworkPolicy API nor the kubelet — only Istio's own data plane rewrites the probe source onto it.probeSourcesis non-empty, which is nowhere today. Nothing here and nothing in Kubernetes would report it. What to re-check is named too: Istio's release notes, the defaults in all 30 charts, and the pinned expectation in the test.2. Both numbers became values
One object under one
enabled, not two sibling values — two values can drift apart, which is the failure this whole design exists to prevent, so the shape supports the coupling argument rather than undermining it.redirectedProbeSourcesis a list, because a dual-stack cluster needs both of Istio's addresses at once, not one of two — a nameable case, so it does not contradict reason 4 of the issue. The IPv6 counterpart is documented as the dual-stack addition, with the reason it is absent unchanged: SingleStack IPv4, and anipBlockof the wrong family is accepted and matches nothing. It goes alongside, never instead.Named
redirectedProbeSources, notprobeSources, and the distinction is written where both appear (README, the style guide, every chart'svalues.yaml, the schema):networkPolicy.probeSources[]…ambientMesh.redirectedProbeSources[169.254.7.127/32], shipped filled, because unlike node IPs it is a constant the chart can knowNull-safe per #99, and both guards proven load-bearing by removing them — not asserted:
$npIngress.ambientMesh.enabledon a deleted object fails withnil pointer evaluating interface {}.enabled, which is the shape of the defect #136 shipped one value away (itsNOTES.txtbranch dereferenced.networkPolicy.egressdirectly);portrendersport: 0— accepted by the API server and silently wrong.With the guards in place:
ambientMesh: nullrenders with the switch off and no port; an object carrying onlyenabled: truewith the other two nilled renders 15008 and the ipBlock from the fallbacks.The five charts that render no
ipBlock(samba,satisfactory,teamspeak-server,minecraft-server,valkey) omitredirectedProbeSourcesfrom bothvalues.yamland the schema: there it would reach no rule, and a value that silently does nothing reads as a control. That absence is asserted, not tolerated.The consequence, handled: the exception is pinned in the test
Once the port is configurable, the "exactly one port number" tightening can no longer check against the rendered value. An exception permitting whatever the value says is design A's hole wearing design C's name — a mistyped port would pass simply by sitting in the configurable field, which is the single reason design A was rejected.
So the expectation is pinned in
ci/run-networkpolicy-test.sh(AMBIENT_PORT,AMBIENT_CIDR), and assertion 7 now checks two things against that statement:ipBlock, andvalues.yamldeclares the same defaults — read back throughci/yaml2json, typed, not by regex (a substring test over a commented file is how theprobeSourcescheck was once fooled by a deleted key whose comment survived).A chart that drifts is red. If Istio changes a constant it takes 30 values files and the two pinned lines — and the pinned lines are what force someone to look. That block is consequently the one place in the repository stating what we hold Istio's numbers to be, which makes it the answer to the provenance question as well, so it carries that text.
The delicate part — a release-level override — resolved explicitly. The renders set only
enabled=true, never a port override, on purpose: the pin is a statement about the defaults we ship, not about what a release may choose. An operator override is outside the test's reach, as is true of every value here. Both halves were executed: the override renders (operator freedom intact), and forcing the test to render it shows the pinned exception does not stretch to cover it — so there is no path on which a non-pinned port is silently blessed.Ten fail paths executed
ipBlockrendered ungatedfrompeersipBlockhalf deleted while the port stayed<release>-<chart>-<kind>conventionvalues.yamlredirectedProbeSourcesenabled: trueScope, versions, proof
All 30 charts. Versions unchanged from where they were — the switch is still additive with its default off, the render at defaults is still byte-identical, and nothing here is published, so boolean → object costs no extra step.
Re-proven, not carried over: all 30 renders byte-identical at defaults against
origin/main(byte counts unchanged from the previous round; the three charts with aci/networkpolicyoverlay proven with and without it), and all 30 non-empty with the switch on. Locally:30 charts, 333 assertions held, 0 failed, and all six repo-wide render tests pass.Rebased again
mainmoved once more: Renovate'sUpdate Helm release valkey to v2, which took a major on both parents. Resolved by keeping main's side wholesale — the dependency bump and the major — and putting this change's minor on top:paperless-ngx15.0.0 →15.1.0+up3.3.1,stalwart3.0.0 →3.1.0+upv0.16.26. Thevalkeydependency pin stays at main's published2.0.0+up9.1.2.alpine; raising it to the2.1.0this PR produces is Renovate's job after that version publishes, and pinning it here would reference a version the registry does not have yet and breakhelm dependency update. Both charts re-proven against the newmainafterwards;run-bump-level-test.shpasses.CI green on the reshaped head
95e0722— 94 contexts, all successRun 1245: 50 of 50 jobs success, combined commit status
success, 94 of 94 contexts success, including the requiredvalidate-chartscontext and all 28 install-tests.The NetworkPolicy job's output from the runner, unchanged in total from before the reshape — which is the point, since the switch is still additive and the render at defaults is still byte-identical:
ambient-mesh <chart>: okfor all 30, and the new pinned-defaults assertion reporting per chart — both variants, from the job log:Two process notes, so they are not re-derived from the run list
POST …/actions/runs/<id>/cancelreturns HTTP 403 for the bot account, which is worth knowing the next time a long matrix is blocked by a superseded run.mainmoved twice during this work (two Renovate merges), and both rebases are documented in the comments above with how each version conflict was resolved.Wiki updated in the same round, one commit, fetch+rebase and no force: all 30 chart pages (the five that render no
ipBlockomitredirectedProbeSourcesentirely),Chart-Style-Guide§15 — including the fourth entry in the overlapping-names table —CI-CD, and a follow-on entry inLessons-Learnedon the general lesson: when a constant becomes configurable, pin the expectation in the check rather than in the thing being checked, and do not let making it configurable re-separate halves that were deliberately joined.Not merged, and no auto-merge armed.