Files
nexarch/mail/docs/INT-01-PRUEFPROTOKOLL.md
T
sysops c9b062062b feat(mail): INT-01 REST-API v1 für Mail-Zugriff & OpenAPI-Beschreibung
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.
2026-09-01 17:49:40 +02:00

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 (optionaler q-Parameter, läuft über search.Client.Search).
  • GET /api/v1/mail/messages/{messageID} — Mail-Detail (neue Methode search.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 wie web/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

  1. API bietet Endpunkte für Mail-Liste, Mail-Detail und Anhang-Download: alle drei implementiert, siehe "Umsetzung".
  2. Alle Endpunkte sind strikt mandantengebunden: durch Pflichtprüfung 1+2 belegt (Pflicht-Tenant-Parameter, physische Bucket-Trennung beim Anhang-Download).
  3. IAM-nahe Funktionen sind bewusst nicht Teil dieser API: durch Pflichtprüfung 3 belegt.
  4. 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).