QA-01: teststrategie-mail (mail-modul-grundstein)
- 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
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user