- mail/go.mod: erstes eigenstaendiges Go-Modul fuer NEXARCH Mail - mail/docs/TESTSTRATEGIE-MAIL.md: Testpyramide (Unit/Integration/ Protokoll-Zustandsmaschinen/E2E/Vertragstests), Pflichttest-Merge-Gate, Bug-Tracking-Konvention (Gitea-Issues), analog Core QA-01 - mail/internal/example: ein reales, kleines Beispiel (Adress- Normalisierung) mit je einem Test pro Testart (Unit/Integration/E2E), 6 Tests real bestanden - mail/internal/pflichttestgate + cmd/pflichttestgate: Merge-Gate-CLI, echter End-zu-Ende-Beweis (Binary lehnt Verstoss ab, akzeptiert begleiteten Test), .gitea/workflows/mail-pflichttest-gate.yml - Ehrlich dokumentiert: kein Gitea-API-Token verfuegbar, daher kein echter Issue angelegt - Bug-Tracking-Vorgehen stattdessen anhand eines realen, bereits dokumentierten Befunds (RET-10) durchgespielt, als offener Punkt vermerkt - Gegenlesen durch zweite Person (Nutzer) noch ausstehend Pruefungen siehe mail/docs/TESTSTRATEGIE-MAIL.md
73 lines
2.1 KiB
Go
73 lines
2.1 KiB
Go
// Package pflichttestgate erzwingt die in docs/TESTSTRATEGIE-MAIL.md
|
|
// Abschnitt 4 festgelegte Regel: jede geänderte Go-Datei in einem
|
|
// sicherheitskritischen Bereich (Auth, Tenant-Scoping, Protokoll-/
|
|
// Compliance-kritisch) muss von einer geänderten oder neuen _test.go-
|
|
// Datei im selben Package begleitet sein. Bewusste Code-Kopie des
|
|
// Musters aus Core internal/pflichttestgate — Mail ist ein eigenständiges
|
|
// Go-Modul und kann Core nicht importieren.
|
|
package pflichttestgate
|
|
|
|
import (
|
|
"path"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// sensitivePathPatterns beschreibt die Bereiche aus
|
|
// TESTSTRATEGIE-MAIL.md Abschnitt 4.
|
|
var sensitivePathPatterns = []*regexp.Regexp{
|
|
regexp.MustCompile(`(^|/)mail/internal/auth/`),
|
|
regexp.MustCompile(`(^|/)mail/internal/tenant/`),
|
|
regexp.MustCompile(`(^|/)mail/internal/ingest/`),
|
|
regexp.MustCompile(`(^|/)mail/internal/imap/`),
|
|
regexp.MustCompile(`(^|/)mail/internal/smtp/`),
|
|
regexp.MustCompile(`(^|/)mail/internal/arc/`),
|
|
}
|
|
|
|
// Violation beschreibt ein Package mit sicherheitskritischer Änderung
|
|
// ohne begleitende Testdatei.
|
|
type Violation struct {
|
|
Package string
|
|
ChangedFile string
|
|
}
|
|
|
|
func isSensitive(file string) bool {
|
|
if !strings.HasSuffix(file, ".go") || strings.HasSuffix(file, "_test.go") {
|
|
return false
|
|
}
|
|
for _, re := range sensitivePathPatterns {
|
|
if re.MatchString(file) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// CheckDiff prüft eine Liste geänderter Dateipfade gegen die
|
|
// Pflichttest-Regel — ein leeres Ergebnis bedeutet: Gate besteht.
|
|
func CheckDiff(changedFiles []string) []Violation {
|
|
sensitiveByPkg := map[string]string{}
|
|
testTouchedPkgs := map[string]bool{}
|
|
|
|
for _, f := range changedFiles {
|
|
pkg := path.Dir(f)
|
|
if strings.HasSuffix(f, "_test.go") {
|
|
testTouchedPkgs[pkg] = true
|
|
continue
|
|
}
|
|
if isSensitive(f) {
|
|
if _, seen := sensitiveByPkg[pkg]; !seen {
|
|
sensitiveByPkg[pkg] = f
|
|
}
|
|
}
|
|
}
|
|
|
|
var violations []Violation
|
|
for pkg, file := range sensitiveByPkg {
|
|
if !testTouchedPkgs[pkg] {
|
|
violations = append(violations, Violation{Package: pkg, ChangedFile: file})
|
|
}
|
|
}
|
|
return violations
|
|
}
|