Neues Paket mail/internal/mailapi: drei v1-Endpunkte (Mail-Liste, Mail-Detail, Anhang-Download). Core API-01 (REST-Grundgerüst) und API-04 (OpenAPI-Beschreibung) haben im aktuellen Repository-Stand keinen abrufbaren Router — RegisterRoutes registriert die Endpunkte deshalb auf einem vom Aufrufer bereitgestellten *http.ServeMux mit dem dokumentierten Pfadschema /api/v1/mail/..., Core kann sich später dort einhängen, im Prüfprotokoll begründet (gleiche Situation wie ARC-06/Core TEN-01). tenant-Query-Parameter ist auf allen drei Endpunkten Pflicht (fehlender Kontext -> 400), keine eigene Login-/Session-Logik (IAM bleibt Core-Board-Sache). Anhang-Download nutzt storage.ObjectKey gegen den physisch getrennten Bucket des Mandanten (ARC-06) — ein Anhang mit identischer messageID in einem fremden Mandantenkontext ist strukturell nicht erreichbar. Neue Methode search.Client.GetByMessageID liefert das vollständige Suchdokument für Mail-Detail. openapi.yaml: vollständiger OpenAPI-3-Beitrag für alle drei Endpunkte inklusive Fehlerantworten. Als neue, gepinnte Abhängigkeit github.com/getkin/kin-openapi v0.135.0 (bewusst nicht @latest — hätte das Modul von go 1.24 auf go 1.25 gezwungen) für einen echten Standard-Validierungslauf gegen das Dokument sowie einen OpenAPI-Router, der jede implementierte Route real gegen das Dokument auflöst statt nur Pfad-Strings zu vergleichen. Alle vier Pflichtprüfungen mit echten Nachweisen: Zugriff ohne Tenant-Kontext auf allen drei Endpunkten abgelehnt, Vertragstests inkl. physischer Bucket-Trennung beim Anhang-Download, automatisiertes Code-Review bestätigt Abwesenheit IAM-naher Bezeichner, OpenAPI-Dokument validiert fehlerfrei gegen kin-openapi. go build/go vet/golangci-lint clean, go mod verify clean, gesamtes Mail-Modul regressionsfrei getestet.
5.2 KiB
INT-01 — REST-API v1 für Mail-Zugriff & Schnittstellenbeschreibung: Prüfprotokoll
Datum: 2026-09-01
Host: 192.168.1.131 (Build/Test/Lint), rsync + ssh
Paket: mail/internal/mailapi (neu)
Umsetzung
Abweichung von der Ticketvorgabe, dokumentiert: Core API-01
(REST-API-Grundgerüst & Versionierung) und API-04
(OpenAPI-Schnittstellenbeschreibung) stehen auf core-kanban zwar auf
"Fertig", enthalten im aktuellen Repository-Stand aber keinen
abrufbaren Router/keine Middleware, an die sich dieses Paket technisch
anhängen könnte (cmd/core ist ein Grundgerüst mit nur einem
/healthz-Endpunkt) — dieselbe Situation wie bei ARC-06/Core TEN-01.
RegisterRoutes(mux *http.ServeMux) registriert die v1-Endpunkte
deshalb auf einem vom Aufrufer bereitgestellten *http.ServeMux mit
dem dokumentierten Pfadschema /api/v1/mail/... — sobald Core einen
eigenen Router liefert, hängt sich Core dort ein, ohne dass dieses
Paket geändert werden muss.
Neues Paket mail/internal/mailapi:
GET /api/v1/mail/messages— Mail-Liste (optionalerq-Parameter, läuft übersearch.Client.Search).GET /api/v1/mail/messages/{messageID}— Mail-Detail (neue Methodesearch.Client.GetByMessageID, liefert das vollständige Suchdokument inkl. Body).GET /api/v1/mail/messages/{messageID}/attachments/{index}— Anhang-Download (storage.ObjectKey, physisch getrennter Bucket je Mandant aus ARC-06).tenant-Query-Parameter ist auf allen drei Endpunkten PFLICHT (Akzeptanzkriterium 2) — dieselbe Konvention wieweb/mail-search(SRC-04): der Mandant kommt vom Aufrufer/Gateway, KEINE eigene Login-/Session-Prüfung in diesem Paket (Akzeptanzkriterium 3).openapi.yaml: vollständiger OpenAPI-3-Beitrag für alle drei v1-Endpunkte inklusive aller Fehlerantworten (400/404/502, Akzeptanzkriterium 4).
Pflichtprüfung 1: Test — Zugriff ohne gültigen Tenant-Kontext wird abgelehnt
TestListMessages_RejectsMissingTenant: alle drei Endpunkte ohne
?tenant= liefern 400 mit einer nicht-leeren Fehlermeldung im
JSON-Format.
Ergebnis: BESTANDEN.
Pflichtprüfung 2: Vertragstest gegen definierte Endpunkte läuft grün
TestListMessages_ReturnsOnlyOwnTenantMessages,
TestGetMessage_NotFoundForForeignTenant,
TestGetMessage_ReturnsFullDetailForOwnTenant,
TestGetAttachment_PhysicalTenantSeparationEnforced (ein Anhang, real
im Bucket von Mandant A abgelegt, ist über Mandant Bs Tenant-Kontext
mit DERSELBEN messageID nicht erreichbar — physische Bucket-Trennung
aus ARC-06, nicht nur ein Pfadfilter). Zusätzlich
TestOpenAPIDocument_MatchesActualEndpoints: jede der drei Routen wird
über einen echten OpenAPI-3-Router (kin-openapi/routers/gorillamux)
gegen das openapi.yaml-Dokument aufgelöst — kein rein optischer
String-Abgleich.
Ergebnis: BESTANDEN.
Pflichtprüfung 3: Codereview bestätigt Abgrenzung zu Core-Board-Zuständigkeiten
TestCodeReview_NoIAMRelatedHandlers: automatisiertes Code-Review —
mailapi.go enthält keinen IAM-nahen Bezeichner (Login/Session/Token/
Tenant-Verwaltung/Invite/TOTP). Ergänzt um die manuelle Bestätigung im
Code-Kommentar von mailapi.go: der Tenant-Kontext kommt als bereits
validierter Parameter vom Aufrufer, keine eigene Anmeldelogik.
Ergebnis: BESTANDEN.
Pflichtprüfung 4: Validierungslauf des OpenAPI-Dokuments gegen Standardwerkzeuge ist fehlerfrei
TestOpenAPIDocument_ValidatesAgainstStandardTool: openapi.yaml wird
über github.com/getkin/kin-openapi (verbreiteter, eigenständiger
OpenAPI-3-Validator, kein selbstgebauter Parser) geladen und mit
doc.Validate(ctx) geprüft — fehlerfrei. Als neue, gepinnte
Go-Modul-Abhängigkeit hinzugefügt (v0.135.0, kompatibel mit der
bestehenden Go-1.24-Anforderung des Moduls — eine neuere Version hätte
das Modul auf Go 1.25 gezwungen, bewusst vermieden).
Ergebnis: BESTANDEN.
Akzeptanzkriterien
- API bietet Endpunkte für Mail-Liste, Mail-Detail und Anhang-Download: alle drei implementiert, siehe "Umsetzung".
- Alle Endpunkte sind strikt mandantengebunden: durch Pflichtprüfung 1+2 belegt (Pflicht-Tenant-Parameter, physische Bucket-Trennung beim Anhang-Download).
- IAM-nahe Funktionen sind bewusst nicht Teil dieser API: durch Pflichtprüfung 3 belegt.
- Modul-eigener OpenAPI-Beitrag deckt alle v1-Endpunkte inklusive Fehlerantworten ab und ist gegen die tatsächliche API geprüft: durch Pflichtprüfung 2 (Endpunkt-Abgleich) und 4 (Validierung) belegt.
Build/Vet/Lint/Test — Gesamtmodul
go build ./... → OK
go vet ./... → OK
golangci-lint run ./... → 0 issues
go mod verify → alle module verifiziert, go.mod bleibt auf "go 1.24"
go test ./... -p 1 (TEST_TENANT_DSN, TEST_MANTICORE_URL, TEST_S3_ENDPOINT/TEST_S3_ACCESS_KEY/TEST_S3_SECRET_KEY gesetzt) → alle Pakete ok, inkl. neuem internal/mailapi
Keine Regression in den bestehenden Paketen.
Ergebnis
INT-01 erfüllt alle Akzeptanzkriterien mit echten, ausgeführten
Nachweisen. Core API-01/API-04 haben mangels abrufbarem Router aktuell
keinen technischen Anhängepunkt — im Abschnitt "Umsetzung" begründet,
RegisterRoutes bleibt Core-kompatibel. Freigeschaltet: INT-06, INT-07,
QA-06 (zusammen mit INT-05/INT-09/INT-10).