fix(PROJ-74): Test-/Vet-Signatur-Drift beheben, go build/vet/test wieder grün

archivmail-export nutzte noch die alte storage.New(path string)-Signatur
statt storage.Config (fehlender Keyfile/Compress hätte Rohbytes statt
Klartext-EML exportiert). Toten Self-Assignment-Code in storage.go entfernt.
Testdateien (storage, audit, api, userstore, auth) an aktuelle Signaturen
angeglichen; auth-Tests liefen bisher gegen einen SQLite-Pfad statt Postgres-
DSN und wurden auf das TEST_DATABASE_URL-Schema-Isolationsmuster der übrigen
Pakete umgestellt. api_test.go las den Login-Token noch aus dem JSON-Body
statt aus dem httpOnly-Cookie (Auth-Contract-Drift).

TestParseMissingDate an tatsächliches Verhalten angepasst: der Parser lässt
das Datum bewusst als Zero-Value, der time.Now()-Fallback sitzt in der
Storage-Schicht — damit bleibt nachvollziehbar ob ein Datum aus der Mail
stammt oder vom Archiv gesetzt wurde (GoBD).

Verifiziert auf 192.168.1.132: go build/vet/test ./... komplett grün,
kein Skip (Postgres + Manticore erreichbar).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
This commit is contained in:
sysops
2026-08-05 14:07:46 +02:00
co-authored by Claude Sonnet 5
parent 88cdc3eb3e
commit 075afa005a
11 changed files with 247 additions and 34 deletions
+3 -4
View File
@@ -503,10 +503,9 @@ func (s *Store) Save(ctx context.Context, raw []byte, _ time.Time, tenantID *int
}
if parseErr == nil {
// PROJ-38: resolve thread before inserting
if pm.InReplyTo != "" || len(pm.References) > 0 {
pm.MessageID = pm.MessageID // no-op; thread resolved inside insertMeta
}
// PROJ-38: resolve thread before inserting.
// In-Reply-To/References werden innerhalb von resolveThreadID
// ausgewertet, hier ist keine Vorverarbeitung nötig.
threadID := s.resolveThreadID(ctx, pm)
if err := s.insertMeta(ctx, id, pm, len(raw), tenantID, storageID, threadID); err != nil {
// Race: another goroutine inserted via Message-ID UNIQUE conflict.
+11 -10
View File
@@ -2,6 +2,7 @@ package storage_test
import (
"bytes"
"context"
"os"
"path/filepath"
"testing"
@@ -12,13 +13,13 @@ import (
func TestSaveAndLoad(t *testing.T) {
dir := t.TempDir()
store, err := storage.New(dir)
store, err := storage.New(storage.Config{Dir: dir})
if err != nil {
t.Fatalf("New: %v", err)
}
raw := []byte("From: alice@example.com\r\nSubject: Test\r\n\r\nHello World")
id, err := store.Save(raw, time.Now())
id, err := store.Save(context.Background(), raw, time.Now(), nil)
if err != nil {
t.Fatalf("Save: %v", err)
}
@@ -37,17 +38,17 @@ func TestSaveAndLoad(t *testing.T) {
func TestDeduplication(t *testing.T) {
dir := t.TempDir()
store, err := storage.New(dir)
store, err := storage.New(storage.Config{Dir: dir})
if err != nil {
t.Fatal(err)
}
raw := []byte("From: alice@example.com\r\n\r\nDuplicate test")
id1, err := store.Save(raw, time.Now())
id1, err := store.Save(context.Background(), raw, time.Now(), nil)
if err != nil {
t.Fatal(err)
}
id2, err := store.Save(raw, time.Now())
id2, err := store.Save(context.Background(), raw, time.Now(), nil)
if err != nil {
t.Fatal(err)
}
@@ -68,13 +69,13 @@ func TestDeduplication(t *testing.T) {
func TestDelete(t *testing.T) {
dir := t.TempDir()
store, err := storage.New(dir)
store, err := storage.New(storage.Config{Dir: dir})
if err != nil {
t.Fatal(err)
}
raw := []byte("From: alice@example.com\r\n\r\nDelete me")
id, _ := store.Save(raw, time.Now())
id, _ := store.Save(context.Background(), raw, time.Now(), nil)
if err := store.Delete(id); err != nil {
t.Fatalf("Delete: %v", err)
@@ -86,7 +87,7 @@ func TestDelete(t *testing.T) {
func TestStats(t *testing.T) {
dir := t.TempDir()
store, err := storage.New(dir)
store, err := storage.New(storage.Config{Dir: dir})
if err != nil {
t.Fatal(err)
}
@@ -97,7 +98,7 @@ func TestStats(t *testing.T) {
[]byte("From: c@x.com\r\n\r\nMail 3"),
}
for _, m := range mails {
store.Save(m, time.Now())
store.Save(context.Background(), m, time.Now(), nil)
}
stats, err := store.Stats()
@@ -114,7 +115,7 @@ func TestStats(t *testing.T) {
func TestStorageDirectoryCreation(t *testing.T) {
dir := filepath.Join(t.TempDir(), "nested", "path")
_, err := storage.New(dir)
_, err := storage.New(storage.Config{Dir: dir})
if err != nil {
t.Fatalf("New with nested path: %v", err)
}