stalwart liefert seine MTA-STS-Policy selbst, aber die Route dorthin gehört einem anderen Repository. Sie soll in den Chart wandern und dort als Liste pflegbar sein — mehrere Domänen, auch Subdomänen.
Gemessener Stand
Im Namensraum stalwart liegen zwei Ingress-Objekte, und nur eines gehört diesem Chart:
Objekt
Release
Host
Pfad
Backend
stalwart-stalwart-ingress
stalwart (dieser Chart)
mail.bekemeyer-klein.de
/Prefix
stalwart-stalwart-full-http-servicehttp
mta-sts-ingress
jk-cluster-config-fleet-cd-stalwart-mta-sts
mta-sts.bekemeyer-klein.de
/.well-known/mta-sts.txt, Exact
derselbe Service
Das MTA-STS-Objekt: className: nginx, cert-manager.io/cluster-issuer: letsencrypt-issuer, eigenes TLS-Secret tls-mta-sts-bekemeyer-klein-de-ingress, keine nginx-Annotationen. Also genau eine Regel mit genau einem Pfad auf den Service, den dieser Chart ohnehin rendert.
Der Chart kennt MTA-STS bislang gar nicht — git grep -i 'mta-sts\|well-known' über stalwart/ auf origin/main: null Treffer.
Stalwart liefert die Policy, und zwar domänenspezifisch:
1. mtaSts.hosts: [] — die Liste ist der Schalter. Kein zusätzliches enabled: „aktiviert, Liste leer" wäre ein Zustand ohne Bedeutung, den der Chart abfangen müsste.
2. Eintragsform{ host, tlsSecretName, clusterIssuer? }. Die beiden TLS-Felder gelten nur im Ingress-Modus — im Gateway-Modus sitzt TLS am Listener und der Chart rendert kein Zertifikat. Dieselbe Trennung wie in #122.
clusterIssuer ist optional und leer bedeutet keine Annotation: so wird pro Secret nur ein Certificate angefordert, falls mehrere Hosts dasselbe Secret teilen. Dieselbe bewusste Auslassung wie beim qBittorrent-Objekt in freesailarr und bei zwei der vier Realm-Ingresses in #122.
3. Gateway-Modus: eine HTTPRoute mit allen Hostnamen. Hier unterscheidet sich nichts je Host — gleicher Pfad, gleiches Backend —, spec.hostnames ist eine Liste, ein Objekt genügt. Das ist der Unterschied zu #122, wo app-root je Realm abweicht und deshalb je Host ein Objekt nötig ist.
4. Ingress-Modus: ein Ingress, eine Regel je Host, tls: nach Secret gruppiert. Dafür gibt es einen Präzedenzfall im Repository: rss-bridge.tlsGroups (rss-bridge/templates/_helpers.tpl:320) gruppiert genau so Hosts nach TLS-Secret. Übernehmen oder begründen, warum nicht — nicht neu erfinden.
5. Der Pfad wird fest verdrahtet./.well-known/mta-sts.txt mit Exact bzw. type: Exact. RFC 8461 legt ihn fest; ein Wert für einen protokollvorgeschriebenen Pfad ist ein Wert, den man nur falsch setzen kann. Das gehört als Kommentar dazu, damit die Festverdrahtung nicht als Versäumnis gelesen wird.
6. Subdomänen müssen gehen, und das ist der Punkt, an dem es schiefgehen kann: mta-sts.sub.domain.tld liegt eine Label-Ebene tiefer als *.domain.tld. Ein Wildcard-Zertifikat der Elterndomäne deckt es nicht. Mit einem Secret je Eintrag ist das gelöst; die Falle gehört trotzdem in values.yaml, weil die naheliegende Annahme „der Wildcard deckt das schon" falsch ist und das Symptom ein TLS-Fehler beim sendenden MTA ist — also nichts, was hier auffällt.
7. TLS-Entscheidung: Secret je Eintrag, nicht in das Mail-Zertifikat gefaltet. Die Alternative lag vor — der Chart hat bereits „Additional DNS names for the mail certificate" (values.yaml:593) — und wurde verworfen: das Mail-Zertifikat würde dann an der MTA-STS-Liste hängen, und ein Fehler dort träfe den Mail-Host mit.
8. Version Minor 1.3.0+upv0.16.25 (main: 1.2.0+upv0.16.25), additiv mit leerer Vorgabe. Zu belegen mit einem leeren helm template-Diff gegen origin/main für die Vorgaben.
9. Overlayci/httproute/stalwart.yaml erweitern (es existiert aus #120), damit die neuen Routen von der Zusicherung erfasst werden. Beide Formen abdecken: ein Eintrag mit clusterIssuer, einer ohne, und ein Host auf einer Subdomäne, weil das der Fall ist, der die Wildcard-Falle trägt.
Die Grenze, die laut dokumentiert werden muss
stalwart/values.yaml:7 sagt es selbst: Data Store, TLS-Objekte, Domänen und Cluster-Rollen liegen im Data Store, nicht im Chart.
Daraus folgt: der Chart registriert Routen, er legt keine Domänen an. Ob Stalwart für mta-sts.beispiel.de antwortet, hängt daran, dass beispiel.de in seinem Data Store existiert — was der Chart nie sieht. Ein Eintrag ohne zugehörige Domäne ergibt einen 404 an einem korrekt gerouteten Endpunkt, und MTA-STS-Fehler sind auf der Senderseite still: der sendende MTA findet keine Policy und schickt unverschlüsselt weiter, ohne dass hier etwas protokolliert wird.
Das ist dieselbe Gattung wie die OnePasswordItem-Grenze, die der Chart schon dokumentiert: eine Zusage, die der Chart nicht halten kann, und deshalb eine, die er benennen muss statt sie zu suggerieren.
Nicht in diesem Umfang
Die DNS-Einträge. MTA-STS braucht zusätzlich einen _mta-sts.<domain> TXT-Record; ohne ihn sucht kein sendender MTA die Policy. Das ist DNS, nicht Kubernetes.
mode: testing. Die laufende Policy steht auf testing, sendende MTAs erzwingen also nichts. Das ist Stalwart-Konfiguration im Data Store und keine Chart-Frage — hier nur als Beobachtung festgehalten.
Das Entfernen des Objekts aus jk-cluster-config. Wie in #122 ist das eine Migration, keine Chart-Änderung: erst dort entfernen, dann die Liste füllen. Umgekehrt weist das Admission-Webhook von ingress-nginx das zweite Objekt auf demselben Host und Pfad ab. Mit der Vorgabe [] ändert diese PR an der laufenden Installation nichts.
`stalwart` liefert seine MTA-STS-Policy selbst, aber die Route dorthin gehört einem anderen Repository. Sie soll in den Chart wandern und dort als **Liste** pflegbar sein — mehrere Domänen, auch Subdomänen.
## Gemessener Stand
Im Namensraum `stalwart` liegen zwei Ingress-Objekte, und nur eines gehört diesem Chart:
| Objekt | Release | Host | Pfad | Backend |
| --- | --- | --- | --- | --- |
| `stalwart-stalwart-ingress` | `stalwart` (dieser Chart) | `mail.bekemeyer-klein.de` | `/` `Prefix` | `stalwart-stalwart-full-http-service` `http` |
| `mta-sts-ingress` | `jk-cluster-config-fleet-cd-stalwart-mta-sts` | `mta-sts.bekemeyer-klein.de` | **`/.well-known/mta-sts.txt`, `Exact`** | **derselbe Service** |
Das MTA-STS-Objekt: `className: nginx`, `cert-manager.io/cluster-issuer: letsencrypt-issuer`, eigenes TLS-Secret `tls-mta-sts-bekemeyer-klein-de-ingress`, **keine** nginx-Annotationen. Also genau eine Regel mit genau einem Pfad auf den Service, den dieser Chart ohnehin rendert.
**Der Chart kennt MTA-STS bislang gar nicht** — `git grep -i 'mta-sts\|well-known'` über `stalwart/` auf `origin/main`: null Treffer.
**Stalwart liefert die Policy, und zwar domänenspezifisch:**
```
$ curl https://mta-sts.bekemeyer-klein.de/.well-known/mta-sts.txt
version: STSv1
mode: testing
max_age: 604800
mx: mail.bekemeyer-klein.de
```
## Umfang
**1. `mtaSts.hosts: []` — die Liste ist der Schalter.** Kein zusätzliches `enabled`: „aktiviert, Liste leer" wäre ein Zustand ohne Bedeutung, den der Chart abfangen müsste.
**2. Eintragsform** `{ host, tlsSecretName, clusterIssuer? }`. Die beiden TLS-Felder gelten **nur im Ingress-Modus** — im Gateway-Modus sitzt TLS am Listener und der Chart rendert kein Zertifikat. Dieselbe Trennung wie in #122.
`clusterIssuer` ist **optional und leer bedeutet keine Annotation**: so wird pro Secret nur **ein** Certificate angefordert, falls mehrere Hosts dasselbe Secret teilen. Dieselbe bewusste Auslassung wie beim qBittorrent-Objekt in `freesailarr` und bei zwei der vier Realm-Ingresses in #122.
**3. Gateway-Modus: eine HTTPRoute mit allen Hostnamen.** Hier unterscheidet sich nichts je Host — gleicher Pfad, gleiches Backend —, `spec.hostnames` ist eine Liste, ein Objekt genügt. Das ist der Unterschied zu #122, wo `app-root` je Realm abweicht und deshalb je Host ein Objekt nötig ist.
**4. Ingress-Modus: ein Ingress, eine Regel je Host, `tls:` nach Secret gruppiert.** Dafür gibt es einen Präzedenzfall im Repository: `rss-bridge.tlsGroups` (`rss-bridge/templates/_helpers.tpl:320`) gruppiert genau so Hosts nach TLS-Secret. Übernehmen oder begründen, warum nicht — nicht neu erfinden.
**5. Der Pfad wird fest verdrahtet.** `/.well-known/mta-sts.txt` mit `Exact` bzw. `type: Exact`. **RFC 8461 legt ihn fest**; ein Wert für einen protokollvorgeschriebenen Pfad ist ein Wert, den man nur falsch setzen kann. Das gehört als Kommentar dazu, damit die Festverdrahtung nicht als Versäumnis gelesen wird.
**6. Subdomänen müssen gehen**, und das ist der Punkt, an dem es schiefgehen kann: `mta-sts.sub.domain.tld` liegt **eine Label-Ebene tiefer** als `*.domain.tld`. Ein Wildcard-Zertifikat der Elterndomäne deckt es **nicht**. Mit einem Secret je Eintrag ist das gelöst; die Falle gehört trotzdem in `values.yaml`, weil die naheliegende Annahme „der Wildcard deckt das schon" falsch ist und das Symptom ein TLS-Fehler beim sendenden MTA ist — also nichts, was hier auffällt.
**7. TLS-Entscheidung: Secret je Eintrag**, nicht in das Mail-Zertifikat gefaltet. Die Alternative lag vor — der Chart hat bereits „Additional DNS names for the mail certificate" (`values.yaml:593`) — und wurde verworfen: das Mail-Zertifikat würde dann an der MTA-STS-Liste hängen, und ein Fehler dort träfe den Mail-Host mit.
**8. Version Minor `1.3.0+upv0.16.25`** (`main`: `1.2.0+upv0.16.25`), additiv mit leerer Vorgabe. Zu belegen mit einem leeren `helm template`-Diff gegen `origin/main` für die Vorgaben.
**9. Overlay** `ci/httproute/stalwart.yaml` erweitern (es existiert aus #120), damit die neuen Routen von der Zusicherung erfasst werden. Beide Formen abdecken: ein Eintrag mit `clusterIssuer`, einer ohne, und **ein Host auf einer Subdomäne**, weil das der Fall ist, der die Wildcard-Falle trägt.
## Die Grenze, die laut dokumentiert werden muss
`stalwart/values.yaml:7` sagt es selbst: Data Store, TLS-Objekte, **Domänen** und Cluster-Rollen liegen **im Data Store**, nicht im Chart.
Daraus folgt: **der Chart registriert Routen, er legt keine Domänen an.** Ob Stalwart für `mta-sts.beispiel.de` antwortet, hängt daran, dass `beispiel.de` in seinem Data Store existiert — was der Chart nie sieht. Ein Eintrag ohne zugehörige Domäne ergibt einen **404 an einem korrekt gerouteten Endpunkt**, und MTA-STS-Fehler sind auf der **Senderseite** still: der sendende MTA findet keine Policy und schickt unverschlüsselt weiter, ohne dass hier etwas protokolliert wird.
Das ist dieselbe Gattung wie die `OnePasswordItem`-Grenze, die der Chart schon dokumentiert: eine Zusage, die der Chart nicht halten kann, und deshalb eine, die er benennen muss statt sie zu suggerieren.
## Nicht in diesem Umfang
- **Die DNS-Einträge.** MTA-STS braucht zusätzlich einen `_mta-sts.<domain>` TXT-Record; ohne ihn sucht kein sendender MTA die Policy. Das ist DNS, nicht Kubernetes.
- **`mode: testing`.** Die laufende Policy steht auf `testing`, sendende MTAs erzwingen also nichts. Das ist Stalwart-Konfiguration im Data Store und keine Chart-Frage — hier nur als Beobachtung festgehalten.
- **Das Entfernen des Objekts aus `jk-cluster-config`.** Wie in #122 ist das eine Migration, keine Chart-Änderung: **erst** dort entfernen, **dann** die Liste füllen. Umgekehrt weist das Admission-Webhook von ingress-nginx das zweite Objekt auf demselben Host und Pfad ab. Mit der Vorgabe `[]` ändert diese PR an der laufenden Installation nichts.
Der Rumpf und mein Auftrag an den Agenten behaupten, in #120 seien „mit genau dieser Begründung" — Modus-Asymmetrie — keine CORS-Werte eingebaut worden. Das stimmt nicht. Der Chart-Style-Guide protokolliert zwei andere Gründe:
both Support: Extended, neither Core … Extended is not promisable — a rejected route is rejected whole, and the observed failure is quieter still (Cilium accepts filters.type: CORS and forwards the preflight upstream anyway).
And half a feature is worse than none: a responseHeaderModifier can add the Access-Control-Allow-* headers but cannot answer the preflight … and with Authorization in the allowed headers every request is preflighted, so the expressible half is exactly the useless one.
Modus-Asymmetrie steht dort nicht. Die Folge für den Umfang ist unverändert — beide Modi bleiben richtig —, aber die tragende Regel ist eine andere: Routing-Werte sind in diesem Repository modus-unabhängig (ingress.domain wird im Gateway-Modus mitgelesen, ingress.hosts in beiden), und ein Filter wird nur gerendert, wenn es Werte dafür gibt und das Support-Level das Verhalten zusagbar macht.
Der Entwicklungs-Agent hat die falsche Behauptung nicht übernommen, sondern durch die belegte ersetzt und den Commit vor dem Push amendiert. Dieselbe Korrektur gilt für den Rumpf von #122.
2. Die Objektbenennung geht auf Index — und der Style-Guide-Satz war falsch
Punkt 1 des Umfangs sagt nichts über Objektnamen; der Agent hat zunächst nach Issuer benannt und das gut begründet: Chart-Style-Guide §4 erlaubt Index-Benennung mit dem Nachsatz
Acceptable only because a route holds no state and no certificate.
— und die MTA-STS-Ingress-Objekte halten Zertifikate. Parallel hat #125 (keycloak) nach Index benannt und seine Realm-Objekte in dieselbe Regel eingetragen, obwohl auch die Zertifikate halten. Zwei Charts hätten damit für dieselbe Gestalt Gegenteiliges gemacht, und die Regel wäre auf einen Fall erweitert worden, den ihre eigene Voraussetzung ausschließt.
Entscheidung des Maintainers: in #126 angleichen — Index-Benennung wie homeassistant und keycloak —, und den Begründungssatz korrigieren. Denn tragfähig ist die Regel aus einem anderen Grund, und der ist jetzt gemessen:
Gemessen: in jk-cluster ist --enable-certificate-owner-refnicht gesetzt — weder in den Args des cert-manager/cert-manager-Deployments noch in der config.yaml seines --config-Flags (dort stehen nur enableGatewayAPI: true und kind: ControllerConfiguration).
Dokumentiertes Verhalten: damit gilt cert-managers Vorgabe, und das Secret überlebt, wenn das Certificate über die Owner-Reference des Ingress mit eingesammelt wird.
Nicht angewandt: dass ein konkretes Umbenennen glattgeht, hat niemand getestet — beide Agenten waren ausschließlich lesend.
Tragfähig ist die Index-Benennung also nicht, weil kein Zertifikat beteiligt wäre, sondern weil das Secret den Umbenennung überlebt und nur das Certificate-Objekt neu entsteht — keine Neuausstellung, keine Rate-Limit-Berührung. Und das hängt an einem Cluster-Schalter, den dieses Repository nicht kontrolliert; genau so gehört es in den Style-Guide.
Eine Asymmetrie fällt dabei auf und gehört in den Template-Kopf: dieser Chart rendert im Gateway-Modus eine einzige Route mit allen Hostnamen, weil TLS dort nicht beteiligt ist. Die Index-Frage stellt sich hier also nur auf der Ingress-Seite — anders als bei keycloak, wo beide Modi je Eintrag ein Objekt haben.
Nebenbefund für die Gateway-Seite allgemein
cert-manager läuft in diesem Cluster mit enableGatewayAPI: true. Im Gateway-Modus sind die tlsSecretName-Werte dieses Charts inert — die Zertifikate der Listener kann cert-manager hier aber selbst ausstellen. Das ist der fehlende Halbsatz zu „TLS sitzt am Listener und gehört der Plattform": für diese Zuständigkeit existiert in diesem Cluster ein funktionierender Mechanismus. Gehört nicht in den Umfang dieses Issues, aber in die Akte.
# Zwei Korrekturen am Rumpf, beide nach dem Messen
## 1. Meine CORS-Begründung war falsch
Der Rumpf und mein Auftrag an den Agenten behaupten, in #120 seien „mit genau dieser Begründung" — Modus-Asymmetrie — keine CORS-Werte eingebaut worden. **Das stimmt nicht.** Der `Chart-Style-Guide` protokolliert zwei andere Gründe:
> both `Support: Extended`, neither Core … **Extended is not promisable** — a rejected route is rejected **whole**, and the observed failure is quieter still (Cilium accepts `filters.type: CORS` and forwards the preflight upstream anyway).
> **And half a feature is worse than none**: a `responseHeaderModifier` can add the `Access-Control-Allow-*` headers but cannot answer the **preflight** … and with `Authorization` in the allowed headers every request is preflighted, so the expressible half is exactly the useless one.
Modus-Asymmetrie steht dort nicht. Die **Folge für den Umfang ist unverändert** — beide Modi bleiben richtig —, aber die tragende Regel ist eine andere: Routing-*Werte* sind in diesem Repository modus-unabhängig (`ingress.domain` wird im Gateway-Modus mitgelesen, `ingress.hosts` in beiden), und ein Filter wird nur gerendert, wenn es Werte dafür gibt **und** das Support-Level das Verhalten zusagbar macht.
Der Entwicklungs-Agent hat die falsche Behauptung nicht übernommen, sondern durch die belegte ersetzt und den Commit vor dem Push amendiert. Dieselbe Korrektur gilt für den Rumpf von #122.
## 2. Die Objektbenennung geht auf Index — und der Style-Guide-Satz war falsch
Punkt 1 des Umfangs sagt nichts über Objektnamen; der Agent hat zunächst nach **Issuer** benannt und das gut begründet: `Chart-Style-Guide` §4 erlaubt Index-Benennung mit dem Nachsatz
> Acceptable only because **a route holds no state and no certificate**.
— und die MTA-STS-Ingress-Objekte halten Zertifikate. Parallel hat #125 (`keycloak`) nach **Index** benannt und seine Realm-Objekte in dieselbe Regel eingetragen, obwohl auch die Zertifikate halten. Zwei Charts hätten damit für dieselbe Gestalt Gegenteiliges gemacht, und die Regel wäre auf einen Fall erweitert worden, den ihre eigene Voraussetzung ausschließt.
**Entscheidung des Maintainers:** in #126 angleichen — Index-Benennung wie `homeassistant` und `keycloak` —, und den **Begründungssatz korrigieren**. Denn tragfähig ist die Regel aus einem anderen Grund, und der ist jetzt gemessen:
- **Gemessen:** in `jk-cluster` ist `--enable-certificate-owner-ref` **nicht gesetzt** — weder in den Args des `cert-manager/cert-manager`-Deployments noch in der `config.yaml` seines `--config`-Flags (dort stehen nur `enableGatewayAPI: true` und `kind: ControllerConfiguration`).
- **Dokumentiertes Verhalten:** damit gilt cert-managers Vorgabe, und das **Secret überlebt**, wenn das Certificate über die Owner-Reference des Ingress mit eingesammelt wird.
- **Nicht angewandt:** dass ein konkretes Umbenennen glattgeht, hat niemand getestet — beide Agenten waren ausschließlich lesend.
Tragfähig ist die Index-Benennung also **nicht**, weil kein Zertifikat beteiligt wäre, sondern weil das Secret den Umbenennung überlebt und nur das Certificate-Objekt neu entsteht — keine Neuausstellung, keine Rate-Limit-Berührung. Und das hängt an einem **Cluster-Schalter, den dieses Repository nicht kontrolliert**; genau so gehört es in den Style-Guide.
Eine Asymmetrie fällt dabei auf und gehört in den Template-Kopf: dieser Chart rendert im **Gateway-Modus eine einzige Route** mit allen Hostnamen, weil TLS dort nicht beteiligt ist. Die Index-Frage stellt sich hier also **nur auf der Ingress-Seite** — anders als bei `keycloak`, wo beide Modi je Eintrag ein Objekt haben.
## Nebenbefund für die Gateway-Seite allgemein
cert-manager läuft in diesem Cluster mit **`enableGatewayAPI: true`**. Im Gateway-Modus sind die `tlsSecretName`-Werte dieses Charts inert — die Zertifikate der Listener kann cert-manager hier aber selbst ausstellen. Das ist der fehlende Halbsatz zu „TLS sitzt am Listener und gehört der Plattform": für diese Zuständigkeit existiert in diesem Cluster ein funktionierender Mechanismus. Gehört nicht in den Umfang dieses Issues, aber in die Akte.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
stalwartliefert seine MTA-STS-Policy selbst, aber die Route dorthin gehört einem anderen Repository. Sie soll in den Chart wandern und dort als Liste pflegbar sein — mehrere Domänen, auch Subdomänen.Gemessener Stand
Im Namensraum
stalwartliegen zwei Ingress-Objekte, und nur eines gehört diesem Chart:stalwart-stalwart-ingressstalwart(dieser Chart)mail.bekemeyer-klein.de/Prefixstalwart-stalwart-full-http-servicehttpmta-sts-ingressjk-cluster-config-fleet-cd-stalwart-mta-stsmta-sts.bekemeyer-klein.de/.well-known/mta-sts.txt,ExactDas MTA-STS-Objekt:
className: nginx,cert-manager.io/cluster-issuer: letsencrypt-issuer, eigenes TLS-Secrettls-mta-sts-bekemeyer-klein-de-ingress, keine nginx-Annotationen. Also genau eine Regel mit genau einem Pfad auf den Service, den dieser Chart ohnehin rendert.Der Chart kennt MTA-STS bislang gar nicht —
git grep -i 'mta-sts\|well-known'überstalwart/auforigin/main: null Treffer.Stalwart liefert die Policy, und zwar domänenspezifisch:
Umfang
1.
mtaSts.hosts: []— die Liste ist der Schalter. Kein zusätzlichesenabled: „aktiviert, Liste leer" wäre ein Zustand ohne Bedeutung, den der Chart abfangen müsste.2. Eintragsform
{ host, tlsSecretName, clusterIssuer? }. Die beiden TLS-Felder gelten nur im Ingress-Modus — im Gateway-Modus sitzt TLS am Listener und der Chart rendert kein Zertifikat. Dieselbe Trennung wie in #122.clusterIssuerist optional und leer bedeutet keine Annotation: so wird pro Secret nur ein Certificate angefordert, falls mehrere Hosts dasselbe Secret teilen. Dieselbe bewusste Auslassung wie beim qBittorrent-Objekt infreesailarrund bei zwei der vier Realm-Ingresses in #122.3. Gateway-Modus: eine HTTPRoute mit allen Hostnamen. Hier unterscheidet sich nichts je Host — gleicher Pfad, gleiches Backend —,
spec.hostnamesist eine Liste, ein Objekt genügt. Das ist der Unterschied zu #122, woapp-rootje Realm abweicht und deshalb je Host ein Objekt nötig ist.4. Ingress-Modus: ein Ingress, eine Regel je Host,
tls:nach Secret gruppiert. Dafür gibt es einen Präzedenzfall im Repository:rss-bridge.tlsGroups(rss-bridge/templates/_helpers.tpl:320) gruppiert genau so Hosts nach TLS-Secret. Übernehmen oder begründen, warum nicht — nicht neu erfinden.5. Der Pfad wird fest verdrahtet.
/.well-known/mta-sts.txtmitExactbzw.type: Exact. RFC 8461 legt ihn fest; ein Wert für einen protokollvorgeschriebenen Pfad ist ein Wert, den man nur falsch setzen kann. Das gehört als Kommentar dazu, damit die Festverdrahtung nicht als Versäumnis gelesen wird.6. Subdomänen müssen gehen, und das ist der Punkt, an dem es schiefgehen kann:
mta-sts.sub.domain.tldliegt eine Label-Ebene tiefer als*.domain.tld. Ein Wildcard-Zertifikat der Elterndomäne deckt es nicht. Mit einem Secret je Eintrag ist das gelöst; die Falle gehört trotzdem invalues.yaml, weil die naheliegende Annahme „der Wildcard deckt das schon" falsch ist und das Symptom ein TLS-Fehler beim sendenden MTA ist — also nichts, was hier auffällt.7. TLS-Entscheidung: Secret je Eintrag, nicht in das Mail-Zertifikat gefaltet. Die Alternative lag vor — der Chart hat bereits „Additional DNS names for the mail certificate" (
values.yaml:593) — und wurde verworfen: das Mail-Zertifikat würde dann an der MTA-STS-Liste hängen, und ein Fehler dort träfe den Mail-Host mit.8. Version Minor
1.3.0+upv0.16.25(main:1.2.0+upv0.16.25), additiv mit leerer Vorgabe. Zu belegen mit einem leerenhelm template-Diff gegenorigin/mainfür die Vorgaben.9. Overlay
ci/httproute/stalwart.yamlerweitern (es existiert aus #120), damit die neuen Routen von der Zusicherung erfasst werden. Beide Formen abdecken: ein Eintrag mitclusterIssuer, einer ohne, und ein Host auf einer Subdomäne, weil das der Fall ist, der die Wildcard-Falle trägt.Die Grenze, die laut dokumentiert werden muss
stalwart/values.yaml:7sagt es selbst: Data Store, TLS-Objekte, Domänen und Cluster-Rollen liegen im Data Store, nicht im Chart.Daraus folgt: der Chart registriert Routen, er legt keine Domänen an. Ob Stalwart für
mta-sts.beispiel.deantwortet, hängt daran, dassbeispiel.dein seinem Data Store existiert — was der Chart nie sieht. Ein Eintrag ohne zugehörige Domäne ergibt einen 404 an einem korrekt gerouteten Endpunkt, und MTA-STS-Fehler sind auf der Senderseite still: der sendende MTA findet keine Policy und schickt unverschlüsselt weiter, ohne dass hier etwas protokolliert wird.Das ist dieselbe Gattung wie die
OnePasswordItem-Grenze, die der Chart schon dokumentiert: eine Zusage, die der Chart nicht halten kann, und deshalb eine, die er benennen muss statt sie zu suggerieren.Nicht in diesem Umfang
_mta-sts.<domain>TXT-Record; ohne ihn sucht kein sendender MTA die Policy. Das ist DNS, nicht Kubernetes.mode: testing. Die laufende Policy steht auftesting, sendende MTAs erzwingen also nichts. Das ist Stalwart-Konfiguration im Data Store und keine Chart-Frage — hier nur als Beobachtung festgehalten.jk-cluster-config. Wie in #122 ist das eine Migration, keine Chart-Änderung: erst dort entfernen, dann die Liste füllen. Umgekehrt weist das Admission-Webhook von ingress-nginx das zweite Objekt auf demselben Host und Pfad ab. Mit der Vorgabe[]ändert diese PR an der laufenden Installation nichts.Zwei Korrekturen am Rumpf, beide nach dem Messen
1. Meine CORS-Begründung war falsch
Der Rumpf und mein Auftrag an den Agenten behaupten, in #120 seien „mit genau dieser Begründung" — Modus-Asymmetrie — keine CORS-Werte eingebaut worden. Das stimmt nicht. Der
Chart-Style-Guideprotokolliert zwei andere Gründe:Modus-Asymmetrie steht dort nicht. Die Folge für den Umfang ist unverändert — beide Modi bleiben richtig —, aber die tragende Regel ist eine andere: Routing-Werte sind in diesem Repository modus-unabhängig (
ingress.domainwird im Gateway-Modus mitgelesen,ingress.hostsin beiden), und ein Filter wird nur gerendert, wenn es Werte dafür gibt und das Support-Level das Verhalten zusagbar macht.Der Entwicklungs-Agent hat die falsche Behauptung nicht übernommen, sondern durch die belegte ersetzt und den Commit vor dem Push amendiert. Dieselbe Korrektur gilt für den Rumpf von #122.
2. Die Objektbenennung geht auf Index — und der Style-Guide-Satz war falsch
Punkt 1 des Umfangs sagt nichts über Objektnamen; der Agent hat zunächst nach Issuer benannt und das gut begründet:
Chart-Style-Guide§4 erlaubt Index-Benennung mit dem Nachsatz— und die MTA-STS-Ingress-Objekte halten Zertifikate. Parallel hat #125 (
keycloak) nach Index benannt und seine Realm-Objekte in dieselbe Regel eingetragen, obwohl auch die Zertifikate halten. Zwei Charts hätten damit für dieselbe Gestalt Gegenteiliges gemacht, und die Regel wäre auf einen Fall erweitert worden, den ihre eigene Voraussetzung ausschließt.Entscheidung des Maintainers: in #126 angleichen — Index-Benennung wie
homeassistantundkeycloak—, und den Begründungssatz korrigieren. Denn tragfähig ist die Regel aus einem anderen Grund, und der ist jetzt gemessen:jk-clusterist--enable-certificate-owner-refnicht gesetzt — weder in den Args descert-manager/cert-manager-Deployments noch in derconfig.yamlseines--config-Flags (dort stehen nurenableGatewayAPI: trueundkind: ControllerConfiguration).Tragfähig ist die Index-Benennung also nicht, weil kein Zertifikat beteiligt wäre, sondern weil das Secret den Umbenennung überlebt und nur das Certificate-Objekt neu entsteht — keine Neuausstellung, keine Rate-Limit-Berührung. Und das hängt an einem Cluster-Schalter, den dieses Repository nicht kontrolliert; genau so gehört es in den Style-Guide.
Eine Asymmetrie fällt dabei auf und gehört in den Template-Kopf: dieser Chart rendert im Gateway-Modus eine einzige Route mit allen Hostnamen, weil TLS dort nicht beteiligt ist. Die Index-Frage stellt sich hier also nur auf der Ingress-Seite — anders als bei
keycloak, wo beide Modi je Eintrag ein Objekt haben.Nebenbefund für die Gateway-Seite allgemein
cert-manager läuft in diesem Cluster mit
enableGatewayAPI: true. Im Gateway-Modus sind dietlsSecretName-Werte dieses Charts inert — die Zertifikate der Listener kann cert-manager hier aber selbst ausstellen. Das ist der fehlende Halbsatz zu „TLS sitzt am Listener und gehört der Plattform": für diese Zuständigkeit existiert in diesem Cluster ein funktionierender Mechanismus. Gehört nicht in den Umfang dieses Issues, aber in die Akte.