9. Unterstützte Funktionen

Die Funktionen auf Protokoll- und Richtlinienebene, die Pepsi unterstützt, jeweils mit dem maßgeblichen RFC: die SMTP- und Authentifizierungsmaschinerie, die Ende-zu-Ende-Kryptographie und die Betriebsoberfläche um beides. Der RFC-Index verweist jeden RFC auf Code und Konfiguration; die programmweisen Kapitel führen auf, welches Programm jede Funktion umsetzt.

9.1. Eingehender SMTP-Empfang

pepsi-ingress ist ein standardkonformer SMTP-Server (RFC 5321) mit diesen Erweiterungen:

  • Transportsicherheit. Klartext, STARTTLS-Upgrade (RFC 3207) und implizites TLS (RFC 8314, z. B. der Submission-Port 465) — je Listener über MODE ausgewählt. Submission-Listener (RFC 6409, SUBMISSION = yes) können gebunden werden — siehe Nachrichteneinlieferung.

  • Übertragung des Nachrichtentexts. Klassisches DATA und CHUNKING/BDAT (RFC 3030) für große Nachrichten. BINARYMIME wird nicht angekündigt, und ein MAIL FROM mit BODY=BINARYMIME wird mit 501 5.5.4 abgelehnt.

  • SIZE-Ankündigung und -Durchsetzung (MAX_MESSAGE_SIZE; Überschreitung → 552).

  • PIPELINING und ENHANCEDSTATUSCODES.

  • 8BITMIME (RFC 6152) und SMTPUTF8 (RFC 6531) — siehe Internationalisierte und 8-Bit-Inhalte.

  • DSN (RFC 3461) — siehe Zustellungsstatusbenachrichtigungen.

  • SMTP AUTH (RFC 4954) für die Submission — siehe Client-Authentifizierung.

  • Annahmerichtlinie: Mail wird nur für ACCEPTED_DOMAINS angenommen (andere werden als Relaying mit 550 abgelehnt); das domainlose Postfach <Postmaster> wird immer angenommen (RFC 5321 §4.5.1); Empfänger, die gültige SRS-Tokens sind, werden rückwärtsdekodiert und weitergeleitet (siehe Sender Rewriting Scheme (SRS)).

  • Dauerhaftigkeit: Dem Client wird 250 erst mitgeteilt, nachdem der Datensatz festgeschrieben ist; ist die Datenbank nicht verfügbar, erhält der Client ein vorübergehendes 451 und wiederholt.

9.2. Trace-Header

Ingress stellt jeder Nachricht vor der Authentifizierung einen Received:-Header gemäß RFC 5321 §4.4 voran (sodass die ARC-Versiegelung ihn abdeckt). Die with-Klausel hält den Übertragungstyp fest — SMTP, ESMTP, ESMTPS, ESMTPA oder ESMTPSA — gemäß RFC 3848 (das bloße ESMTPA, authentifiziert, aber nicht über TLS, ist der lokale UNIX-Submission-Socket), und eine for-Klausel benennt bei Einzelempfänger-Transaktionen den Empfänger.

9.3. Client-Authentifizierung

Jeder Listener kann den sich verbindenden Client authentifizieren und dessen Mail als lokal erzeugt markieren (was ihr erlaubt, an jede Domain weiterzuleiten, und ESMTPSA in die Received:-Spur stempelt). Eine Sitzung ist authentifiziert, wenn einer von vier listenerspezifischen Mechanismen gelingt:

  • die Peer-IP ist im MYNETWORKS des Listeners (von vornherein vertrauenswürdig);

  • ein SMTP-AUTH-Austausch gelingt (RFC 4954, PLAIN/LOGIN), verifiziert gegen ein konfiguriertes SASL-Backend (SASL_TYPE/SASL_PATH; heute der Auth-Client-Socket von Dovecot). AUTH wird nur über TLS angeboten und akzeptiert — ein Klartextversuch wird mit 504 5.5.4 abgelehnt, dem Code, den RFC 4954 §4 für ein Verfahren vorschreibt, das „eine Verschlüsselungsschicht erfordert“ (§1 erklärt das ältere 538 für veraltet);

  • ein vorgelegtes TLS-Client-Zertifikat passt zu einem konfigurierten Schlüssel/CA-Pin (TLS_AUTH_CLIENT);

  • die Gegenstelle eines UNIX-Sockets wird über SO_PEERCRED identifiziert (AUTH_PEERCRED, der lokale Submission-Socket) und ihr Login ist auf mindestens eine Adresse abgebildet. Dieser Mechanismus trägt einen Benutzernamen, speist also dieselbe USERNAME_MAP-Durchsetzung, die auch eine SASL-Sitzung erfährt.

Dies ist verschieden von der Grenz-Authentifizierung unten, die die Nachricht verifiziert (SPF/DKIM/DMARC), unabhängig davon, wie — oder ob — sich der Client selbst authentifiziert hat. Siehe pepsi-ingress.

9.4. Nachrichteneinlieferung

Ein mit SUBMISSION = yes markierter Listener verhält sich als Message Submission Agent (RFC 6409) statt als MX:

  • Authentifizierung ist verpflichtend — ein nicht authentifiziertes MAIL FROM wird mit 530 5.7.0 abgelehnt (das Flag erfordert also einen der obigen Client-Auth-Mechanismen sowie TLS auf jedem Listener, der kein lokaler UNIX-Domain-Socket ist); und

  • Submission-Korrekturen werden auf jede angenommene Nachricht angewendet: ein fehlendes Date: (§8.2) und Message-ID: (§8.3) werden ergänzt, bevor die Nachricht gespeichert wird; und

  • Durchsetzung der Submission-Identität (§6) über USERNAME_MAP: das Umschlag-MAIL FROM und der From:-Header müssen Adressen sein, die der authentifizierte Benutzer verwenden darf (andernfalls 550), und ein erlaubtes From:, das von der kanonischen Identität des Benutzers abweicht, erhält einen Sender:-Header, der sie benennt (§8.1).

Das Flag hat auf einem MX-Listener keine Wirkung.

9.5. Grenz-Authentifizierung

Bevor Ingress eine Nachricht speichert, authentifiziert es sie, damit der schließliche Empfänger weiterhin das Urteil sehen kann, das Pepsi an der Grenze gefällt hat (die Weiterleitung wird die ursprünglichen SPF/DKIM-Signale zerstören):

  • SPF (RFC 7208) auf der MAIL FROM-Identität unter Verwendung der Client-IP.

  • DKIM-Signaturverifikation (RFC 6376 / RFC 8463).

  • DMARC-Auswertung (RFC 7489), mit optionaler Durchsetzung zur SMTP-Zeit (DMARC_ENFORCE → 550 bei einem eindeutigen Fehlschlag unter einer quarantine/reject-Richtlinie). Andernfalls ist die Authentifizierung fail-open: Ein DNS- oder Parse-Fehler wird festgehalten und die Mail angenommen.

  • iprev / FCrDNS (RFC 8601) — bestätigt der PTR des Clients vorwärts auf seine IP.

  • Ein Authentication-Results-Header (RFC 8601), der all das Obige festhält, gestempelt mit dem Ingress-Hostnamen als authserv-id.

9.6. Authenticated Received Chain (ARC)

Die Stage pepsi-stage-arc implementiert ARC (RFC 8617). Sie verifiziert jede eingehende ARC-Kette und versiegelt die Nachricht als unsere ADMD, indem sie ein Set aus ARC-Authentication-Results / ARC-Message-Signature / ARC-Seal voranstellt, signiert mit dem einzigen ARC_ALGORITHM (ARC erlaubt eine Signatur pro Hop). Dies erlaubt einem nachgelagerten Empfänger, dem Grenzurteil zu vertrauen, nachdem die Weiterleitung das SPF/DKIM-Alignment zerstört hat. Die Versiegelung ist fail-open. Weil ARC die Authentifizierung eines vorgelagerten Absenders über den Weiterleitungs-Hop hinweg bewahrt, gilt es nur für Mail, die Pepsi empfängt: lokal erzeugte Einlieferungen (state.local_origin) werden übersprungen — sie werden von der DKIM-Signierungs-Stage als Autor-Domain authentifiziert —, sodass die generierte Pipeline ARC im eingehenden Zweig platziert, nach der state.local_origin-Aufteilung.

9.7. Sender Rewriting Scheme (SRS)

Die Stage pepsi-stage-srs schreibt den Umschlagabsender in eine lokale Adresse einer von Pepsi kontrollierten SRS_DOMAIN um, die den ursprünglichen Absender per HMAC kodiert (der gekürzte MAC ist base32-kodiert, RFC 4648), sodass SPF beim nächsten Hop besteht. Der Null-Absender und eine bereits in der SRS-Domain liegende Adresse bleiben unverändert; eine bereits-SRS-Adresse wird in der kompakten SRS1-Form neu signiert. Ingress führt die Gegenrichtung aus: Ein an eine gültige SRS-Adresse zurückgesendeter Bounce wird verifiziert und an den ursprünglichen Absender weitergeleitet, während ein gefälschtes oder abgelaufenes Token abgelehnt wird (550).

9.8. Ende-zu-Ende-Verschlüsselung und -Signierung

pepsi-stage-encrypt verschlüsselt eine lokal eingelieferte Nachricht an jeden Empfänger, in OpenPGP (PGP/MIME, RFC 3156) oder S/MIME (CMS, RFC 8551 / 5083), signiert mit dem eigenen Schlüssel des From:-Autors. Die Signatur liegt innerhalb des Chiffrats.

ENABLE_PEP (standardmäßig an) ist eine Voreinstellung von Standardwerten nach dem Vorbild des Projekts pretty Easy privacy: Jeder lokale Absender an einer bedienten Domain erhält automatisch einen OpenPGP-Schlüssel, eine Nachricht wird nur signiert, wenn sie verschlüsselt wird (SIGN = encrypted-only), und Klartext-Mail trägt den Schlüssel des Absenders in einem Autocrypt:-Header, aber keine Signatur. Jede ausdrücklich ausgeschriebene Option hat weiterhin Vorrang; ENABLE_PEP = no macht das Signieren opportunistisch und schaltet die automatische Schlüsselerzeugung ab.

Jeder verschlüsselte Empfänger bekommt sein eigenes Chiffrat auf seinem eigenen Warteschlangendatensatz: Es gibt keine Offenlegung der Empfängerliste, keinen zwischen Empfängern geteilten Inhaltsschlüssel, und ein Bcc-Leck ist strukturell unmöglich. Empfänger, die ein Ergebnis teilen, teilen sich einen Datensatz.

Empfängerschlüssel stammen aus dem Speicher von Schlüsselverwaltung, gefüllt von der Entdeckungsschicht (WKD, VKS, DANE, LDAP, Ernte aus eingehender Mail). Die Stage selbst betreibt keine Netzwerk-E/A: Ein Empfänger, dessen Schlüssel nicht zwischengespeichert ist, pausiert die Nachricht, bis ein Entdeckungsdienst die Anfrage erledigt, und einer mit einem frischen negativen Cache-Eintrag nimmt sofort den Schlüssellos-Pfad.

Was mit einem Empfänger ohne Schlüssel geschieht, ist Richtlinie — ON_NO_KEY ist cleartext, secure-link oder bounce und bezieht seinen Standardwert aus ENCRYPT, statt einen eigenen zu tragen. ENCRYPT = required fällt nie auf Klartext zurück, und kein Klartextergebnis ist je stillschweigend — jedes wird protokolliert und je Empfänger in state.crypto.out festgehalten, samt dem tatsächlich verwendeten Inhaltscontainer und der Angabe, ob es eine Herabstufung war.

Die Stage läuft vor der DKIM-Signierung, sodass DKIM die tatsächlich übertragenen Bytes abdeckt; Konfiguration erklärt, warum diese Reihenfolge nicht optional ist.

9.9. Serverseitige Entschlüsselung und Verifikation

pepsi-stage-decrypt ist die eingehende Hälfte. Für eine Nachricht an einen Empfänger, den dieser Host bedient, öffnet es jedes Chiffrat, das die Nachricht trägt, verifiziert jede Signatur, die sie trägt, hält das Urteil fest und entfernt jeden Sicherheitsindikator, den der Absender gefälscht hat. Der Benutzer liest gewöhnliche Mail in seinem üblichen Client, ohne dass ein Plugin beteiligt ist. Die Ausnahme ist Mail, die an einen Schlüssel verschlüsselt ist, den der Benutzer aus seinem eigenen Mail-Client registriert hat (ein Schlüssel in Client-Verwahrung, dessen private Hälfte Pepsi nie besitzt): Sie wird ungeöffnet durchgereicht, damit der Client sie entschlüsselt.

Es läuft nur für Empfänger, die dieser Host bedient, und versucht es bei allem anderen gar nicht erst. Das Entschlüsseln schreibt den Nachrichtentext um, was die DKIM-Signatur des Absenders ungültig macht; das ist bei einer Nachricht, die gleich hier in ein Postfach abgelegt wird, harmlos und bei einer weitergeleiteten nicht. Eine Nachricht mit Empfängern beider Art wird aufgeteilt, sodass die weitergeleitete Kopie diejenige ist, die ankam.

Das Urteilsvokabular ist genau. valid bedeutet, die Signatur ist einwandfrei und der Schlüssel war verankert — eine X.509-Kette zu einer konfigurierten CA oder ein OpenPGP-Schlüssel aus einer eingestuften Entdeckungsquelle. valid-untrusted bedeutet einwandfrei mit einem Schlüssel, der sich an nichts binden ließ, was der Zustand des meisten signierten Mailverkehrs der Welt ist und nie als valid gemeldet wird. invalid, unverifiable und none vervollständigen die Menge, und trägt eine Nachricht mehrere Signaturen über denselben Inhalt, so gewinnt die schlechteste von ihnen. (Eine außerhalb des Chiffrats angebrachte Signatur ist eine eigene Klasse: Sie steht nur dann für die Nachricht ein, wenn nichts den Klartext signiert, und dann nie besser als valid-untrusted — siehe pepsi-stage-decrypt.) Nur valid setzt state.signature_verified, woran pepsi-stage-check-whitelist einen Datensatz der weißen Liste knüpft.

Beide Fehlerpfade stellen standardmäßig zu, im Einklang mit Pepsis fail-open-Haltung bei eingehendem SPF, DKIM und DMARC: Eine Nachricht, die wir nicht öffnen konnten, wird weiterhin verschlüsselt zugestellt (der Benutzer hält den Schlüssel womöglich in seinem eigenen Client), und eine schlechte Signatur ist ein festgehaltenes Urteil und kein Zustellfehler (Mailinglisten, die Nachrichtentexte umschreiben, erzeugen sie an völlig legitimer Mail). Quarantäne- und Bounce-Wege gibt es für Installationen, die sie wünschen.

Das Ergebnis erreicht den Benutzer auf zwei Wegen: über einen X-Pepsi-Crypto-Header mit dokumentierter Grammatik und — standardmäßig — über ein [decrypted][verified], das dem Subject in Schachtelungsreihenfolge vorangestellt wird, was für die meisten Benutzer das einzige Signal ist, das sie je sehen werden. Beides beruht auf derselben Disziplin: Jedes X-Pepsi-*-Feld und jede unserer eigenen Betreffmarkierungen wird aus eingehender Mail entfernt, bevor unsere hinzugefügt wird. Ein privater Header ist definitionsgemäß fälschbar, und diese Entfernung ist die gesamte Grundlage dafür, dass man ihm glauben darf.

Das Schlüsselmaterial, das eine Nachricht mitführt — S/MIME-Signiererzertifikate, application/pgp-keys-Teile, Autocrypt-Header —, wird im Speicher gelesen, um die Signatur eben dieser Nachricht zu prüfen, denn die meiste signierte Mail führt das Zertifikat mit, das sie signiert hat. Tut sie es nicht, pausiert die Nachricht an einer Entdeckungsanfrage, statt an einem Keyserver zu blockieren, sodass selbst die erste Nachricht eines neuen Korrespondenten ein echtes Urteil erhält.

Die Entschlüsselungs-Stage speichert nichts davon. Alles Lernen von Peer-Schlüsseln ist eine eigene Stage, pepsi-stage-autocrypt-learn, platziert nach dem Spam-Urteil — was „Nachrichten ignorieren, die die MUA für Spam hält“ aus Autocrypt Level 1 §5.3 überhaupt erst umsetzbar macht (LEARN_FROM_SPAM, standardmäßig aus). Eine eingehende Pipeline ohne diese Stage verifiziert Signaturen einwandfrei und lernt nie den Schlüssel eines Korrespondenten.

Was die Decrypt-Stage öffnet, wird als Klartext abgelegt — es sei denn, der Empfänger hat seinen eigenen Mail-Client-Schlüssel registriert; dann versiegelt pepsi-stage-reencrypt, unmittelbar vor der lokalen Zustellung platziert, die Nachricht mit diesem Schlüssel, sobald jede lesende Stage fertig ist. Eine Richtlinie pro Empfänger (ON_NO_CLIENT_KEY) kann Mail für einen Benutzer ohne einen solchen Schlüssel abweisen, statt sie lesbar abzulegen.

9.10. Schlüsselverwaltung, -entdeckung und -veröffentlichung

Keine der beiden Krypto-Stages betreibt eigene Netzwerk-E/A. Beide schöpfen aus einem Schlüsselspeicher im gemeinsamen Schema, der aus zwei Richtungen gefüllt wird: von pepsi-keydisc — je eine Dienstinstanz pro Entdeckungsmethode, sodass ein langsamer Keyserver niemanden aufhält — und von pepsi-stage-autocrypt-learn aus der eintreffenden Mail. Eine Stage, die einen Schlüssel braucht, den sie nicht hat, committet, was sie behalten darf, pausiert die Nachricht und reiht eine Anfrage ein; der antwortende Dienst gibt im selben Round-Trip jede an dieser Adresse geparkte Nachricht frei.

  • Entdeckungsquellen, jede eine eigene, nebenläufig ausgeführte Abfrage mit eigenem Rang auf einer Vertrauensleiter: das Web Key Directory (erweiterte und direkte Form), DANE OPENPGPKEY (RFC 7929) und SMIMEA (RFC 8162) — nur angenommen, wenn das AD-Bit des Resolvers sagt, die Antwort sei DNSSEC-validiert —, das VKS-Protokoll eines verifizierenden Keyservers und LDAP. Unter ihnen allen sitzen auf der Leiter die beiden Sprossen, die keine Entdeckungsdienste sind und keine Instanz haben: aus eingehender Mail geerntetes Material (S/MIME-Signiererzertifikate, application/pgp-keys-Teile und Autocrypt-Header) und — noch eine Sprosse tiefer, ganz unten — der durch Autocrypt-Gossip: eingeführte Schlüssel eines Dritten in einer Nachricht, die verschlüsselt ankam. Beide werden von pepsi-stage-autocrypt-learn unmittelbar geschrieben; eine der beiden in SOURCES zu benennen wird abgelehnt.

  • Veröffentlichung der Schlüssel unserer eigenen Benutzer: die WKD-Endpunkte, die pepsi-httpd bedient, die OPENPGPKEY/SMIMEA-Einträge, die pepsi-keys und pepsi-setup ausgeben, und — nur auf Anforderung, je Identität — das Hochladen auf einen verifizierenden Schlüsselserver, dessen Bestätigungsmail pepsi-stage-vks-confirm beantwortet.

  • Verwahrung. Privates Material wird verpackt unter einem Schlüsselverschlüsselungsschlüssel gespeichert, der außerhalb der Datenbank liegt, und ist nur von der einen Datenbankrolle erreichbar, unter der die Krypto-Stages laufen.

  • Ein negativer Cache bedeutet, dass nur die erste Nachricht an oder von einem unbekannten Korrespondenten je wartet.

Schlüsselverwaltung ist das Kapitel über all dies; die Optionsreferenz ist pepsi.conf(5).

9.12. Ausgehende DKIM-Signierung

Die Stage pepsi-stage-dkim-sign stellt DKIM-Signaturen (RFC 6376) voran — standardmäßig sowohl eine RSA-2048- als auch eine Ed25519-Signatur (RFC 8463), oder unter [pepsi] DKIM_ALGORITHMS nur eine von beiden — unter der SIGNING_DOMAIN oder der From:-Domain der Nachricht. Gmail, Microsoft 365 und Yahoo verifizieren Ed25519 nicht, und Google führt eine solche Signatur in seinen DMARC-Aggregatberichten als fail; DMARC besteht trotzdem über die RSA-Signatur. Die Signatur deckt immer den ganzen Body ab: Das l=-Body-Längen-Tag aus RFC 6376 wird nie ausgegeben, da strenge Verifizierer eine solche Signatur rundweg ablehnen, statt die kürzere Abdeckung hinzunehmen. Das Signieren ist fail-closed: Eine Nachricht, deren Signaturdomain keine Schlüssel hat oder die nicht signiert werden kann, wird als failed markiert, statt unsigniert weitergeschickt zu werden. Da die Header-Auswahl von unten nach oben erfolgt, stört die Signatur bestehende Signaturen nicht.

9.13. Zustellungsstatusbenachrichtigungen

Pepsi implementiert DSN durchgängig (RFC 3461 / RFC 3463 / RFC 3464):

  • Ingress kündigt DSN an und validiert/speichert RET/ENVID (bei MAIL FROM) und NOTIFY/ORCPT (bei RCPT TO) unter state.dsn.

  • Die Relay-Stages propagieren diese Parameter an einen nächsten Hop, der ebenfalls DSN ankündigt, und lassen sie andernfalls weg (RFC 3461 §6 — Pepsi wird nicht zum DSN-verantwortlichen Relay).

  • pepsi-stage-bounce gibt den Bericht als RFC-3464-multipart/report mit erweiterten RFC-3463-Statuscodes aus:

    • einen Failure-Bericht, wenn NOTIFY FAILURE anfordert (der Standard bei Abwesenheit) — NOTIFY=NEVER verwirft stillschweigend;

    • einen Success-Bericht (Action: delivered) nur, wenn das globale ORIGINATE_SUCCESS_DSN gesetzt ist und NOTIFY=SUCCESS angefordert wurde;

    • einen Delay-Bericht (Action: delayed), wenn das DELAY_DSN_AFTER einer Relay-Stage bei einer noch eingereihten Nachricht abläuft, die NOTIFY=DELAY angefordert hat (höchstens einmal gesendet).

Eine Null-Absender-Nachricht (ein Bounce) wird niemals selbst gebounct (RFC 5321 §6.1).

9.14. Internationalisierte und 8-Bit-Inhalte

Ingress kündigt 8BITMIME (RFC 6152) und SMTPUTF8 (RFC 6531) an und hält die BODY=-Deklaration fest. Weil die Fähigkeiten eines nächsten Hops bis nach dem Verbindungsaufbau unbekannt sind, entscheidet der ausgehende SMTP-Client pro Hop:

  • Unterstützt der Hop die Erweiterung, kündigt Pepsi BODY=8BITMIME / SMTPUTF8 erneut an.

  • Andernfalls stuft es herab: 8-Bit-MIME-Blattteile werden in eine 7-Bit-Transferkodierung umkodiert (RFC 2045 — Quoted-Printable für text/*, sonst Base64), nach dem Befund der Oktette statt nach der deklarierten Kodierung; UTF-8-Header-Felder werden als RFC-2047-Encoded-Words umgeschrieben, an den drei Stellen, an denen RFC 2047 §5 eines erlaubt (ein unstrukturiertes Feld, eine Display-Name-Phrase, das Innere eines Kommentars); ein Nicht-ASCII-Parameter von Content-Type / Content-Disposition — der Dateiname eines Anhangs, in einem beliebigen MIME-Teil — erhält die RFC-2231-Form (filename*=UTF-8''caf%C3%A9.txt), und ein Nicht-ASCII-boundary=, für das es keine kodierte Form gibt, wird zusammen mit den Begrenzungszeilen durch ein neues ASCII-Boundary ersetzt.

  • Die herabgestuften Bytes werden dann erneut geprüft: Die Umwandlung geschieht nach bestem Bemühen an einer Nachricht, die niemand validiert hat, und RFC 6152 §3 untersagt es „unter allen Umständen“, einem Hop 8-Bit-Inhalte anzubieten, der 8BITMIME nicht angekündigt hat; ein Nachrichtentext, der danach immer noch 8-bittig ist, ist daher stattdessen ein dauerhafter Fehler (Bounce).

  • Eine Nicht-ASCII-Adresse (im Umschlag oder innerhalb einer Header-Adresse), die einem Nicht-SMTPUTF8-Hop gegenüber nicht darstellbar ist, ist ein dauerhafter Fehler (Bounce).

Das Umkodieren des Nachrichtentexts zerstört zwangsläufig eine den Nachrichtentext abdeckende DKIM/ARC-Signatur; dies ist unvermeidbar (Fähigkeiten werden spät gebunden) und selten.

9.15. Ausgehendes Relay

Zwei austauschbare Relay-Stages versenden Mail nach außerhalb:

  • pepsi-stage-relay-to-internet — Direkt-zu-MX-Zustellung (RFC 5321 §5): eigene MX-Abfrage mit Präferenz-Reihenfolge und Happy-Eyeballs-Adressauswahl (pro Adresse in pepsi.dns_address zwischengespeichert), impliziter MX über Adress-Einträge (§5.1) und Null-MX-Behandlung (RFC 7505). TLS wird per MTA-STS (RFC 8461) mit Zertifikatsidentitätsprüfungen (RFC 6125) authentifiziert; enforce-Richtlinien verlangen STARTTLS zu einem gelisteten MX.

  • pepsi-stage-relay-to-smarthost — Relay über einen konfigurierten Smarthost, nach Empfängerdomain (oder einem Catch-All) gewählt, mit Transport je MTA (plain/tls/starttls), Zertifikatsverifikation und der vollständigen SMTP-AUTH-Suite (RFC 4954) — PLAIN/LOGIN, CRAM-MD5, SCRAM-SHA-1/-SHA-256 (mit optionalem -PLUS-Channel-Binding), OAUTHBEARER/XOAUTH2, SASL EXTERNAL (TLS-Client-Zertifikat), NTLM, GSSAPI/Kerberos und dem veralteten DIGEST-MD5 — oder auto-Aushandlung. Siehe Client-Authentifizierung und den RFC-Index.

Beide Stages wenden den Schleifenschutz an und zählen die Received:-Header der Nachricht gegen ihre eigene Option MAX_HOP_COUNT — sie ist eine Einstellung der Relay-Stage im Abschnitt [stage-<name>] jeder Stage, keine von Ingress, sodass eine Nachricht gestoppt wird, wenn sie gerade weitergesendet werden soll, und nicht erst, wenn sie ankommt.

Beide Stages authentifizieren das TLS des nächsten Hops mit DANE (RFC 7672, DANE = off|warn|strict) — sie schlagen die TLSA-Einträge des Hops nach und gleichen sie mit der vorgelegten Kette ab, mit Vorrang vor MTA-STS — und halten, wenn [pepsi-tlsrpt] SEND_REPORTS eingeschaltet ist (standardmäßig ist es aus), jede ausgehende TLS-Sitzung für TLS-Reporting (RFC 8460) fest; pepsi-tlsrpt verschickt die täglichen Sammelberichte. Sie teilen sich die Wiederholungssemantik: Ein vorübergehender Fehler pausiert die Nachricht mit exponentiellem Backoff (RETRY_INITIAL/ RETRY_MAX_INTERVAL/RETRY_FACTOR) bis MAX_LIFETIME, nach dem sie gebounct oder als fehlgeschlagen markiert wird; ein dauerhafter Fehler wird zu BOUNCE_STAGE geroutet (oder markiert den Datensatz als failed).

9.16. Lokale Zustellung

Für Empfänger in einer lokalen Domain legen drei Stages die Mail auf dem Host ab, statt sie weiterzuleiten (jede reicht die Empfänger, die sie nicht bearbeiten kann, an ihr NEXT_STAGE weiter, sodass sie sich kombinieren lassen):

  • pepsi-stage-relay-to-maildir — schreibt die Nachricht direkt in das Maildir/new/ jedes lokalen Benutzers. Die Lokalität wird durch LOCAL_DOMAINS und TARGETS (passwd-uid-Bereiche) entschieden; der privilegierte Schreibvorgang wird vom setuid-root pepsi-helper-maildir-writer erledigt, der über das eigene pepsi-maildir-Set-Group-ID-Bit der Stage erreicht wird.

  • pepsi-stage-relay-to-lmtp — übergibt die Nachricht an einen lokalen Mail Delivery Agent (typischerweise Dovecot) über LMTP (RFC 2033), der beim Ablegen der Mail das Sieve-Filter (RFC 5228) jedes Empfängers ausführt. Sie stellt alle Empfänger in einer Transaktion zu und routet jeden, den der MDA ablehnt, anhand seines RFC-3463-Status weiter. Benötigt keinen privilegierten Helper (der MDA gibt Privilegien ab).

  • pepsi-stage-dot-forward — verarbeitet die ~/.forward-Datei jedes lokalen Benutzers (der klassische sendmail/Postfix-Mechanismus) über den setuid-root pepsi-helper-dot-forward, der seine Privilegien vor dem Lesen auf den Benutzer absenkt: Weitergeleitete Adressen starten die Pipeline neu, |pipe//file-Direktiven laufen als der Benutzer, und ein Empfänger ohne ~/.forward läuft unverändert durch.

pepsi-stage-aliases ergänzt diese, indem es vor der lokalen Zustellung die Umschlagempfänger über eine Postfix-virtual(5)-artige Map (Volladresse oder @domain-Catch-All, transitiv expandiert) expandiert.

pepsi-stage-vacation beantwortet Mail, die eintrifft, während ein Empfänger abwesend ist, und markiert den Betreff der weitergeleiteten Kopie, sodass er bei seiner Rückkehr sehen kann, welche Mail für ihn beantwortet wurde. Es ist die eine Benutzerfilteraktion, die Pepsi selbst umsetzt, statt sie dem Sieve eines MDA zu überlassen, weil die Antwort eine neue Nachricht ist, die signiert und weitergeleitet werden muss — und weil die Entscheidung, keine zu senden, Pipeline-Wissen ist: RFC 3834 sagt, beantworte nie einen Bounce, Mailinglisten-Mail, irgendetwas bereits als automatisch Markiertes oder eine Dienstadresse, und Pepsi ergänzt sein eigenes „beantworte nie Spam“ und eine Ratenbegrenzung je Korrespondent. Urlaubszeiträume sind gewöhnliche Konfiguration je Adresse, sodass dieselbe Option im globalen Geltungsbereich ein nationaler Feiertag ist und im eigenen pepsi.settings-Datensatz der Urlaub einer einzelnen Person.

pepsi-stage-route ergänzt sie anders: Statt zuzustellen, wählt es je Empfänger einen nächsten Hop anhand der Domain dieses Empfängers und teilt die Nachricht, wenn ihre Empfänger uneins sind. Es ist das, was Pepsi einem bestehenden Mailsystem vorschalten lässt — die Domains hinter dem Gateway gehen zu diesem System, der Rest ins Internet — und es ist die Stelle, an der pepsi-setup nachweist, dass keine von diesem Host bediente Domain in seinen eigenen Ingress zurückgeroutet werden kann. Siehe Microsoft Exchange als Gateway.

9.17. Mailinglisten und Archive

Pepsis Mailinglisten-Subsystem ist eine Neuimplementierung von GNU Mailman 3: sein Datenmodell, seine Rule/Chain- und Handler/Pipeline-Architektur, seine REST-API, sein E-Mail-Befehlsvokabular und die Namen seiner Benachrichtigungsvorlagen sind der Entwurf des GNU-Mailman-Projekts, urheberrechtlich geschützt durch die Free Software Foundation, und Dateien, die aus GNU Mailman, Postorius oder HyperKitty übernommen wurden, stehen weiterhin unter der GNU General Public License (vendor/PEPSI-VENDORING.md führt sie auf). Der Abnahmetest lautet: ein unveränderter mailmanclient, Postorius oder HyperKitty steuert es. Siehe Mailinglisten, Archive und Die REST-API von GNU Mailman 3.

  • Fünf Pipeline-Stages statt eines eigenen Daemons: Routing, Einlieferung, Zustellung pro Mitglied, E-Mail-Befehle und Bounce-Verarbeitung – eine Listennachricht ist damit ein gewöhnlicher Datensatz in der Warteschlange, den ARC, DKIM, SRS, TLS und die Relay-Stages bereits behandeln. Wie das Subsystem aufgebaut ist ist die Übersicht.

  • Neun Adressen pro Liste und keine Alias-Datei. Mailman schreibt für die neun Adressen jeder Liste Postfix- oder Exim-Maps und lädt den MTA neu; Pepsi routet anhand des Empfängers innerhalb der eigenen Pipeline, es gibt also nichts neu zu erzeugen und nichts, was aus dem Tritt geraten kann.

  • Moderation mit dem Vokabular von upstream: achtzehn Rules, vier abschließende Chains (accept, hold, reject, discard) und eine Pipeline aus siebzehn Handlern, mit den Namen, die die REST-API meldet.

  • ``List-*``-Header nach RFC 2369 und ``Archived-At`` nach RFC 5064 in jeder Listennachricht.

  • Ein-Klick-Abmeldung nach RFC 8058 – List-Unsubscribe-Post plus eine mit einem Schlüssel gesicherte https:-URI, die ein einzelnes POST ausführt. Upstream hat das nicht; es ist die eine Stelle, an der Pepsi darüber hinausgeht.

  • Sammelnachrichten in beiden Formaten: die einfache Sammelnachricht nach RFC 1153 und das MIME-multipart/digest, je Abonnent, mit Band- und Ausgabennummer, einer Größenschwelle und einem periodischen Timer.

  • Bounce-Verarbeitung mit der Bewertungslogik von upstream, VERP-Zuordnung bei jeder Kopie (die siebzehn heuristischen Erkenner sind daher der Rückfall und nicht der Mechanismus), optionalen Probenachrichten, Warnungen und schließlich der Abmeldung.

  • Ein Archiv – eine Neuimplementierung von HyperKitty, die dessen Message-ID-Hash und URL-Schema beibehält, damit bestehende Archivlinks eine Migration überleben – mit Volltextsuche, optionaler Trigramm-Teilzeichenfolgensuche, mbox-Import und -Export sowie einer purge-Löschung, die einen Grabstein hinterlässt.

  • Migration von Mailman 2.1 und 3: die config.pck von 2.1 wird mit einer eingeschränkten Pickle-Maschine gelesen, die keine Klasse instanziieren kann (ein nicht vertrauenswürdiges Pickle ist damit Daten und kein Code), und ein Mailman-3-Server wird über dessen eigene REST-API gelesen.

  • Kein JavaScript auf irgendeiner Listen- oder Archivseite, und kein 403 auf einer öffentlichen Oberfläche: eine Ablehnung ist dasselbe 404, das eine nicht vorhandene Liste erhält, denn ein 403 verrät, dass es sie gibt.

9.18. Unerwünschte Mail

Pepsi filtert, nachdem es eine Nachricht angenommen hat; alles Folgende entscheidet also, was mit Mail geschieht, die bereits in der Warteschlange liegt. Drei Mechanismen wirken über ein Urteil, state.spam, und eine Tabelle, pepsi.whitelist, zusammen:

  • Die Korrespondenz-Whitelist. pepsi-stage-auto-whitelist hält die Empfänger der Mail fest, die Ihre Benutzer senden; pepsi-stage-check-whitelist erkennt deren Antworten (wahlweise nur, wenn DKIM, eine verifizierte Signatur oder ein benannter ARC-Versiegler für sie bürgt) und setzt state.spam = false. Operator und Benutzer können sie mit pepsi-whitelist von Hand verwalten.

  • Pay-to-Send (pepsi-stage-anti-spam): Mail von allen anderen wird zurückgehalten, bis ihr Absender einen kleinen GNU-Taler-Betrag zahlt.

  • Confirm-to-Send (pepsi-stage-secretary): Mail von allen anderen wird zurückgehalten, bis ihr Absender einmal auf eine Challenge antwortet. Die Antwort setzt ihn auf die Whitelist, sodass ein Korrespondenzpartner nur ein einziges Mal gefragt wird.

Post-Queue-Milter (SpamAssassin, rspamd, ClamAV, …) und der Sprachfilter können das Urteil ebenfalls setzen oder beeinflussen; siehe pepsi-stage-milter.

9.18.1. Gemeinsame und benutzereigene Whitelists

Jede dieser Stages benennt ihre Liste mit WHITELIST_NAME. Ein Name ist entweder global (correspondents) oder gehört einem Konto (alice/sent, der Namensraum <login>/...; die Vorlagen {login}/{localpart} werden pro Empfänger zu einem solchen Namen expandiert, wo eine Stage sie unterstützt).

Ein Unternehmen möchte meist eine Liste, die alle Mitarbeiter teilen: Ein Kunde, dem gesagt wurde, er solle an einen Kollegen schreiben statt an den Mitarbeiter, der ihn zuerst angeschrieben hat, sollte nicht an der Spam-Sperre hängen bleiben. Der Operator setzt sie einmal:

[stage-auto-whitelist]
PROGRAM = pepsi-stage-auto-whitelist
NEXT_STAGE = dkim-sign
WHITELIST_NAME = correspondents

[stage-check-whitelist]
PROGRAM = pepsi-stage-check-whitelist
NEXT_STAGE = anti-spam
WHITELIST_NAME = correspondents

Der Operator darf jede Liste, gemeinsam oder benutzereigen, in jeder Ebene benennen, die er kontrolliert: der INI-Datei, pepsi.config_override in jedem Geltungsbereich (etwa eine andere gemeinsame Liste für die domain: einer Abteilung) und pepsi.settings-Datensätzen, die mit pepsi-settings geschrieben werden. Ein Kontoinhaber, der pepsi-stage-auto-whitelist oder pepsi-stage-secretary per Mail bearbeiten darf (pepsi-stage-edit-settings), darf das WHITELIST_NAME dieser Stages nur in seinen eigenen Namensraum verlegen oder zurück auf die Liste des Operators setzen: Beide Stages schreiben die Liste, sodass ein gemeinsamer oder fremder Name einem Benutzer erlauben würde, sie mit Adressen seiner Wahl zu füllen. pepsi-stage-check-whitelist liest nur und unterliegt keiner solchen Einschränkung.

Vorsicht

Die Bezahlschranke nimmt nur den Null-Umschlagabsender aus und hält daher auch Mail zurück, für die niemand zahlen wird. Die Link-Benachrichtigung und die PIN-Mail des Secure-Link-Portals tragen den ursprünglichen Absender als Umschlagabsender; kommen sie an ein geschütztes Postfach auf derselben Installation zurück, werden sie bis zur Frist zurückgehalten und dann abgewiesen, und das Portal funktioniert ohne jede Fehlermeldung nicht mehr. Beiträge von Mailinglisten tragen die From:-Adressen ihrer Autoren, die keine Korrespondenzliste abdeckt, und ihre List-*-Felder unterdrücken die Zahlungsaufforderung, sodass jeder Beitrag zurückgehalten und abgewiesen wird, ohne dass jemand zur Zahlung aufgefordert wurde. (Abwesenheitsnotizen und die Zahlungsaufforderungen selbst verwenden den Null-Absender und werden nicht zurückgehalten.)

Setzen Sie diese Absender in einer Gruppe, die [stage-check-whitelist] WHITELIST_NAME nennt, auf die Whitelist: Ihre eigenen Domains mit verlangtem DKIM (die Voreinstellung, die ein gefälschtes From: nicht erfüllen kann) und jede Liste anhand ihrer Kennung und ihres ARC-Versieglers:

pepsi-whitelist add correspondents '^[^@]+@example\.com$'
pepsi-whitelist add-list --sealer lists.example.org \
    correspondents users.lists.example.org

pepsi-stage-anti-spam nennt die Einzelheiten.

9.18.2. Pay-to-Send und Confirm-to-Send im Vergleich

Beide halten die Mail unbekannter Absender zurück, und beide senden dem Absender eine automatische Antwort mit Null-Absender, in seiner Sprache. Sie unterscheiden sich darin, was der Absender beweisen muss:

Pay-to-Send

Confirm-to-Send

Der Absender beweist

dass er für diese Nachricht Geld ausgeben wird

dass er Mail an der Adresse lesen kann, von der er geschrieben hat

Stoppt

Massenmail in jedem Umfang, auch von funktionierenden Postfächern

Massenmail von Adressen, die nicht empfangen können (den Großteil davon)

Stoppt nicht

einen zahlungswilligen Absender

einen Spammer mit funktionierendem Postfach, der die Antwort automatisieren kann

Abschreckung

wirtschaftlich: Jede Nachricht kostet

nur rechtlich: PENALTY nennt, was der Absender zu zahlen zusagt, falls die Mail unerwünscht war, was nichts durchsetzt

Benötigt

ein GNU-Taler-Händler-Backend und eine Wallet auf Seiten des Absenders

nichts außer einer Antwort

Offen gesagt: Confirm-to-Send ist der schwächere Filter. Er lohnt sich trotzdem, weil er einen legitimen Korrespondenzpartner eine einzige Antwort kostet und einen Mailserver im Betrieb nichts — und beide lassen sich kombinieren. Sind beide aktiviert, läuft der Sekretär zuerst und sein UNCHALLENGEABLE_STAGE zeigt auf die Bezahlschranke, sodass Mail, die man nicht um eine Antwort bitten kann (ein Listenbeitrag, ein nicht authentifizierter oder gefälschter Absender, ein Absender über der täglichen Challenge-Obergrenze), stattdessen zur Zahlung aufgefordert wird, während ein bestätigter Absender die Bezahlschranke mit state.spam = false erreicht und sie unberührt passiert.

Confirm-to-Send geht sorgsam mit Backscatter um, da seine Challenge an den Umschlagsabsender geht und der Umschlagsabsender von Spam meist gefälscht ist: Er fordert nur einen Absender heraus, der SPF oder DMARC bestanden hat (REQUIRE_AUTHENTICATED) und dessen From: dieselbe Adresse ist, höchstens MAX_CHALLENGES_PER_SENDER-mal pro Tag über alle Benutzer hinweg; er antwortet nie auf das, worauf RFC 3834 nicht zu antworten gebietet; und seine Challenge zitiert nichts von der zurückgehaltenen Nachricht außer einem kurzen Hinweis auf ihren Betreff (SUBJECT_HINT_LENGTH, standardmäßig acht Zeichen).

9.18.3. Spamfilter und der Sekretär

Standardmäßig bleiben spambewertende Milter (SpamAssassin über spamass-milter, rspamd, MIMEDefang, …) vor der Whitelist-Prüfung, und der Assistent von pepsi-setup erzeugt diese Reihenfolge:

… → milter-spamassassin → check-whitelist → secretary → local
                                         UNCHALLENGEABLE_STAGE = local

Eine Nachricht, die der Filter ablehnt, erreicht den Sekretär nie, sodass offensichtlicher Spam keine Challenge an seinen gefälschten Absender auslöst — so wird Backscatter vermieden. Was den Sekretär doch erreicht, hat den Filter passiert; deshalb setzt der Assistent UNCHALLENGEABLE_STAGE auf das eigene NEXT_STAGE des Sekretärs: Den Filter erneut laufen zu lassen, hieße zweimal zu scannen.

Die Alternative ist, den Filter hinter den Sekretär zu verlegen, sodass er nur Mail scannt, die nicht herausgefordert werden konnte:

… → check-whitelist → secretary → local
                        └─ UNCHALLENGEABLE_STAGE → milter-spamassassin → local

Die Konfigurationsänderung für einen Filter unter [stage-milter-spamassassin]:

  1. Nehmen Sie den Filter aus der Hauptkette: Setzen Sie das NEXT_STAGE der Stage, die auf ihn zeigte, auf das eigene NEXT_STAGE des Filters (normalerweise check-whitelist).

  2. Setzen Sie in [stage-secretary] UNCHALLENGEABLE_STAGE = milter-spamassassin.

  3. Setzen Sie in [stage-milter-spamassassin] NEXT_STAGE auf das NEXT_STAGE des Sekretärs (hier local).

Führen Sie dann pepsi-setup check (oder run) aus, um den Graphen zu validieren.

Der Kompromiss wirkt in beide Richtungen:

  • Dafür: Die CPU-Zeit des Filters wird nur für die Mail aufgewendet, die ihn braucht. Mail von der Whitelist und Mail von bestätigten Absendern — der Großteil eines persönlichen Postfachs — wird nie gescannt.

  • Dagegen: Challenges gehen nun ungescannt hinaus. Spam, den der Filter abgelehnt hätte, löst zuerst eine Challenge aus, was mehr Backscatter an gefälschte Absender bedeutet (begrenzt durch REQUIRE_AUTHENTICATED und die tägliche Obergrenze, aber nicht null); und Spam, dessen Absender tatsächlich bestätigt — die eine Art, die Confirm-to-Send nicht stoppen kann —, wird zugestellt, ohne dass der Filter ihn je sieht.

Welches Layout Sie auch wählen, Viren- und Richtlinien-Milter bleiben auf dem Hauptpfad (vor der Whitelist-Prüfung): Ein bestätigter oder auf der Whitelist stehender Korrespondenzpartner kann trotzdem Malware senden, von einem kompromittierten Konto aus oder unwissentlich, und das Urteil eines Richtlinienfilters gilt für alle.

9.19. Betriebsfunktionen

  • Einzeltabellen-Pipeline mit Absturzwiederherstellung: verwaiste running-Datensätze werden beim Dispatcher-Start zurückgesetzt; in Bearbeitung befindliche Kindprozesse werden beim Herunterfahren zurückgesetzt.

  • Elastische, pipelinende Worker-Pools und Watchdog: Jede Stage betreibt persistente Worker-Prozesse, die bei Bedarf bis zu ihrem PARALLELISM gestartet und nach WORKER_IDLE_TIMEOUT abgeräumt, nach MAX_MESSAGES erneuert werden; jeder Worker bekommt bis zu QUEUE_LIMIT Nachrichten auf einmal zugeführt (in Bearbeitung befindliche Kapazität QUEUE_LIMIT × PARALLELISM, ohne zusätzliche Verbindungskosten), und ein Worker, der MAX_RUNTIME bei seiner vordersten Nachricht überschreitet, wird beendet (timeout) und ersetzt.

  • Warteschlangen-Werkzeuge: pepsi-queue listet, löscht, verschiebt zwischen Stages und löst Nachrichten in großer Zahl los.

  • Zustandsüberwachung: pepsi-status gibt eine nur lesende Zusammenfassung der Warteschlange, festhängender Nachrichten, kumulativer Zustell-/Fehlerzähler und jüngster ausgehender TLS-Ergebnisse aus (auch als --json), geeignet zur Ausführung über SSH.

  • Einrichtung und DNS-Überprüfung: pepsi-setup installiert das Schema, erzeugt Schlüssel und gibt DNS aus/validiert es (DKIM, SPF, MTA-STS).

  • HTTP-Server: pepsi-httpd bedient über einen oder mehrere TLS- (SNI-gewählte) oder Klartext-Listener die MTA-STS-Richtliniendatei (/.well-known/mta-sts.txt), eine Prometheus-/metrics-Seite (nur auf einem Listener mit ADMIN = yes — sie beschreibt die Pipeline), die Web-Key-Directory-Endpunkte, die die eigenen Identitäten dieser Installation veröffentlichen (/.well-known/openpgpkey/…, direkte und erweiterte Form), das Das Secure-Link-Ausweichportal-Portal und das untenstehende Mail-Autokonfigurations-Dokument.

  • Autokonfiguration von Mail-Clients (draft-ietf-mailmaint-autoconfig): Ein Client, dem nichts als fred@example.org gegeben wurde, holt https://autoconfig.example.org/mail/config-v1.1.xml und konfiguriert sich selbst — Submission-Host, Port, Transportsicherheit und Authentifizierung, und dasselbe für den Postfachserver. Die Submission-Hälfte wird vom laufenden Submission-Listener abgeleitet, sodass sie nicht von dem Server abdriften kann, den sie beschreibt; die Postfachhälfte benennt den MDA, mit dem die Installation gepaart ist. Öffentlich und ohne Authentifizierung bedient, wie der Entwurf es verlangt, weil ein Client es lesen muss, bevor er wissen kann, wie er sich authentifiziert.

  • Administrative API und Konsole: Auf einem Listener, der ausdrücklich mit ADMIN = yes gekennzeichnet ist — und nie auf einem, der sie im Klartext vom Host führen würde —, stellt derselbe Server die Die administrative API unter /api/v1 (Warteschlange, Gesundheit, Konfiguration, Schlüsselspeicher, Prüf- und Mailjournale) und die Browser-Die Verwaltungskonsole unter /ui bereit, die ein Client genau dieser API ist. Überall sonst antworten diese Pfade mit demselben 404 wie ein unbekannter Pfad. Die Authentifizierung erfolgt über die Peer-Zugangsdaten des UNIX-Sockets, ein Sitzungs-Cookie oder ein Bearer-Token, und jeder Prinzipal trägt Geltungsbereiche; all das wird im Prüfprotokoll erfasst.

  • Metriken: pepsi-dispatch zeichnet den Durchsatz pro Stage, Kills/Timeouts, Abstürze und Verarbeitungszeit sowie die globalen Stage-/Nachrichten-Gesamtwerte auf (etwa einmal pro Minute in einer Transaktion in die Datenbank geschrieben), exportiert von pepsi-httpd neben Live-Anzeigen für aktiv/pausiert, die aus der Warteschlange gelesen werden.

  • Strukturiertes Logging über tracing auf konfigurierbaren Stufen.

Für Standards, die Pepsi nicht implementiert (darunter BINARYMIME), siehe Anwendbare, noch nicht implementierte RFCs.

9.20. Funktionsstabilität

Jede in diesem Kapitel beschriebene Funktion wird in einer einzigen Funktionsstabilität-Tabelle erfasst, die — pro Funktion — ihren maßgeblichen RFC festhält, ob sie einen automatisierten Test hat (und welcher Art: U Unit, I Integration, I/U beides), ob sie von Hand verifiziert wurde und wie weit sie laut anonymer, freiwilliger Nutzungstelemetrie (pepsi-telemetry) verbreitet und genutzt ist.

Diese Tabelle wird generiert: contrib/update-feature-stability.sh führt das von Hand gepflegte Register contrib/feature-registry.tsv (Spalten Name, RFC, Test und manueller Test) mit einem pepsi-telemetry-GET /telemetry/report (den Verbreitungs- und Nutzungszahlen) zusammen. Siehe Die Pipeline erweitern dazu, wie Sie sie aktuell halten, wenn Sie eine Funktion hinzufügen, einen Test schreiben oder die Telemetriezahlen auffrischen.