# 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).