feat: networkPolicy.ingress.ambientMesh in all 30 charts, with a checked exception in the render test #144

Merged
jklein merged 63 commits from feat/networkpolicy-ingress-ambientmesh into main 2026-10-19 21:07:36 +02:00
Member

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

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 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.*
jklein force-pushed feat/networkpolicy-ingress-ambientmesh from 3c2dc5d15b to fb275935c9 2026-10-19 15:18:03 +02:00 Compare
Author
Member

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.

## 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`.
Author
Member

CI green on fb27593 — 62 contexts, all success

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:

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.

## 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.
jklein added 63 commits 2026-10-19 19:58:42 +02:00
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.
docs(README): the provenance of Istio's two constants, and the pinned expectation that keeps the exception narrow
Validate Helm Charts / Detect changed charts (pull_request) Successful in 3s
Validate Helm Charts / HTTPRoute match (pull_request) Successful in 9s
Validate Helm Charts / Bump level (pull_request) Successful in 4s
Validate Helm Charts / YAML scalars (pull_request) Successful in 12s
Validate Helm Charts / Resource quantities (pull_request) Successful in 11s
Validate Helm Charts / Selector match (pull_request) Successful in 9s
Validate Helm Charts / NetworkPolicy (pull_request) Successful in 24s
Validate Helm Charts / Build apache-tika (pull_request) Successful in 4s
Validate Helm Charts / Trivy config apache-tika (pull_request) Successful in 11s
Validate Helm Charts / Build bentopdf (pull_request) Successful in 4s
Validate Helm Charts / Build bulwark (pull_request) Successful in 5s
Validate Helm Charts / Build calibre-web-automated (pull_request) Successful in 4s
Validate Helm Charts / Build cyberchef (pull_request) Successful in 4s
Validate Helm Charts / Build freesailarr (pull_request) Successful in 4s
Validate Helm Charts / Build garage (pull_request) Successful in 4s
Validate Helm Charts / Build gotenberg (pull_request) Successful in 4s
Validate Helm Charts / Build homeassistant (pull_request) Successful in 4s
Validate Helm Charts / Build keycloak (pull_request) Successful in 4s
Validate Helm Charts / Build matrix-synapse (pull_request) Successful in 4s
Validate Helm Charts / Build minecraft-router (pull_request) Successful in 5s
Validate Helm Charts / Build minecraft-server (pull_request) Successful in 5s
Validate Helm Charts / Build outline (pull_request) Successful in 5s
Validate Helm Charts / Build paperless-ngx (pull_request) Successful in 6s
Validate Helm Charts / Build patchmon (pull_request) Successful in 5s
Validate Helm Charts / Build rallly (pull_request) Successful in 5s
Validate Helm Charts / Build rss-bridge (pull_request) Successful in 4s
Validate Helm Charts / Build samba (pull_request) Successful in 4s
Validate Helm Charts / Build satisfactory (pull_request) Successful in 5s
Validate Helm Charts / Build searxng (pull_request) Successful in 5s
Validate Helm Charts / Build stalwart (pull_request) Successful in 5s
Validate Helm Charts / Build sure (pull_request) Successful in 5s
Validate Helm Charts / Build teamspeak-server (pull_request) Successful in 9s
Validate Helm Charts / Build template-chart (pull_request) Successful in 7s
Validate Helm Charts / Build urlaubsverwaltung (pull_request) Successful in 5s
Validate Helm Charts / Build valkey (pull_request) Successful in 5s
Validate Helm Charts / Build voucher-vault (pull_request) Successful in 5s
Validate Helm Charts / Build zipline (pull_request) Successful in 5s
Validate Helm Charts / Build ytdlp-web-player (pull_request) Successful in 5s
Validate Helm Charts / Trivy config bentopdf (pull_request) Successful in 13s
Validate Helm Charts / Trivy config cyberchef (pull_request) Successful in 11s
Validate Helm Charts / Trivy config homeassistant (pull_request) Successful in 15s
Validate Helm Charts / Trivy config outline (pull_request) Successful in 12s
Validate Helm Charts / Trivy config bulwark (pull_request) Successful in 13s
Validate Helm Charts / Trivy config calibre-web-automated (pull_request) Successful in 11s
Validate Helm Charts / Trivy config freesailarr (pull_request) Successful in 21s
Validate Helm Charts / Trivy config garage (pull_request) Successful in 12s
Validate Helm Charts / Trivy config gotenberg (pull_request) Successful in 14s
Validate Helm Charts / Trivy config keycloak (pull_request) Successful in 12s
Validate Helm Charts / Trivy config matrix-synapse (pull_request) Successful in 11s
Validate Helm Charts / Trivy config minecraft-router (pull_request) Successful in 11s
Validate Helm Charts / Trivy config minecraft-server (pull_request) Successful in 10s
Validate Helm Charts / Trivy config paperless-ngx (pull_request) Successful in 11s
Validate Helm Charts / Trivy config patchmon (pull_request) Successful in 14s
Validate Helm Charts / Trivy config rallly (pull_request) Successful in 14s
Validate Helm Charts / Trivy config rss-bridge (pull_request) Successful in 18s
Validate Helm Charts / Trivy config samba (pull_request) Successful in 16s
Validate Helm Charts / Trivy config satisfactory (pull_request) Successful in 12s
Validate Helm Charts / Trivy config searxng (pull_request) Successful in 11s
Validate Helm Charts / Trivy config stalwart (pull_request) Successful in 13s
Validate Helm Charts / Trivy config sure (pull_request) Successful in 11s
Validate Helm Charts / Trivy config teamspeak-server (pull_request) Successful in 12s
Validate Helm Charts / Trivy config template-chart (pull_request) Successful in 11s
Validate Helm Charts / Trivy config ytdlp-web-player (pull_request) Successful in 12s
Validate Helm Charts / Trivy config urlaubsverwaltung (pull_request) Successful in 11s
Validate Helm Charts / Trivy config valkey (pull_request) Successful in 11s
Validate Helm Charts / Trivy config voucher-vault (pull_request) Successful in 11s
Validate Helm Charts / Trivy config zipline (pull_request) Successful in 16s
Install-test / Install-test bentopdf (pull_request) Successful in 56s
Install-test / Install-test apache-tika (pull_request) Successful in 1m22s
Install-test / Install-test bulwark (pull_request) Successful in 1m7s
Install-test / Install-test cyberchef (pull_request) Successful in 1m5s
Install-test / Install-test garage (pull_request) Successful in 1m5s
Install-test / Install-test calibre-web-automated (pull_request) Successful in 1m40s
Install-test / Install-test gotenberg (pull_request) Successful in 1m14s
Install-test / Install-test homeassistant (pull_request) Successful in 1m48s
Install-test / Install-test matrix-synapse (pull_request) Successful in 1m23s
Install-test / Install-test freesailarr (pull_request) Successful in 3m34s
Install-test / Install-test minecraft-router (pull_request) Successful in 41s
Install-test / Install-test keycloak (pull_request) Successful in 2m24s
Install-test / Install-test patchmon (pull_request) Successful in 1m19s
Install-test / Install-test minecraft-server (pull_request) Successful in 1m47s
Install-test / Install-test outline (pull_request) Successful in 2m4s
Install-test / Install-test rss-bridge (pull_request) Successful in 43s
Install-test / Install-test paperless-ngx (pull_request) Successful in 2m37s
Install-test / Install-test rallly (pull_request) Successful in 1m35s
Install-test / Install-test searxng (pull_request) Successful in 1m4s
Install-test / Install-test samba (pull_request) Successful in 1m21s
Install-test / Install-test stalwart (pull_request) Successful in 1m10s
Install-test / Install-test teamspeak-server (pull_request) Successful in 1m18s
Install-test / Install-test valkey (pull_request) Successful in 1m7s
Install-test / Install-test urlaubsverwaltung (pull_request) Successful in 1m39s
Install-test / Install-test sure (pull_request) Successful in 2m16s
Install-test / Install-test ytdlp-web-player (pull_request) Successful in 49s
Install-test / Install-test voucher-vault (pull_request) Successful in 2m9s
Install-test / Install-test zipline (pull_request) Successful in 1m40s
Validate Helm Charts / Install-test (pull_request) Successful in 12m7s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 7s
Publish BentoPDF Helm Chart / Publish BentoPDF Helm Chart (push) Successful in 7s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Calibre Web Automated Helm Chart / Publish Calibre Web Automated Helm Chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Freesailarr Helm Chart / Publish Freesailarr Helm Chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 11s
Publish Bulwark Helm Chart / Publish Bulwark Helm Chart (push) Successful in 11s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 6s
Publish Garage Helm Chart / Publish Garage Helm Chart (push) Successful in 6s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 14s
Publish Cyberchef Helm Chart / Publish Cyberchef Helm Chart (push) Successful in 14s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 9s
Publish Gotenberg Helm Chart / Publish Gotenberg Helm Chart (push) Successful in 10s
Publish Homeassistant Helm Chart / Publish Homeassistant Helm Chart (push) Successful in 9s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 9s
Publish Keycloak Helm Chart / Publish Keycloak Helm Chart (push) Successful in 9s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 7s
Publish Matrix Synapse Helm Chart / Publish Matrix Synapse Helm Chart (push) Successful in 7s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 9s
Publish Minecraft-Router Helm Chart / Publish Minecraft-Router Helm Chart (push) Successful in 9s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Paperless-NGX Helm Chart / Publish Paperless-NGX Helm Chart (push) Successful in 10s
Publish Outline Helm Chart / Publish Outline Helm Chart (push) Successful in 10s
Publish Minecraft-Server Helm Chart / Publish Minecraft-Server Helm Chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Patchmon Helm Chart / Publish Patchmon Helm Chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 32s
Publish Apache Tika Helm Chart / Publish Apache Tika Helm Chart (push) Successful in 32s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Satisfactory Helm Chart / Publish Satisfactory Helm Chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 11s
Publish RSS-Bridge Helm Chart / Publish RSS-Bridge Helm Chart (push) Successful in 11s
Publish Samba Helm Chart / Publish Samba Helm Chart (push) Successful in 11s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish SearXNG Helm Chart / Publish SearXNG Helm Chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 19s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Rallly Helm Chart / Publish Rallly Helm Chart (push) Successful in 19s
Publish Stalwart Helm Chart / Publish Stalwart Helm Chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish VoucherVault Helm Chart / Publish VoucherVault Helm Chart (push) Successful in 10s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 11s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 11s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 11s
Publish Sure Helm Chart / Publish Sure Helm Chart (push) Successful in 11s
Publish TeamSpeak Server Helm Chart / Publish TeamSpeak Server Helm Chart (push) Successful in 11s
Publish Urlaubsverwaltung Helm Chart / Publish Urlaubsverwaltung Helm Chart (push) Successful in 11s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 11s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 11s
Publish YTDLP Web Player Helm Chart / Publish YTDLP Web Player Helm Chart (push) Successful in 11s
Publish Valkey Helm Chart / Publish Valkey Helm Chart (push) Successful in 11s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 7s
Publish Zipline Helm Chart / Publish Zipline Helm Chart (push) Successful in 7s
SonarQube Analysis / SonarQube Analysis (push) Successful in 34s
95e0722d0c
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.
jklein force-pushed feat/networkpolicy-ingress-ambientmesh from 33da8800a0 to 95e0722d0c 2026-10-19 19:58:42 +02:00 Compare
Author
Member

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

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.

## 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.
Author
Member

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:

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.

## 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.
jklein approved these changes 2026-10-19 21:07:32 +02:00
jklein merged commit 95e0722d0c into main 2026-10-19 21:07:36 +02:00
jklein deleted branch feat/networkpolicy-ingress-ambientmesh 2026-10-19 21:07:36 +02:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jlab-cluster/helm-charts#144