Files
nexarch/mail/internal/mailapi/openapi.yaml
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

166 lines
4.5 KiB
YAML

openapi: "3.0.3"
info:
title: NEXARCH Mail API
version: "1.0.0"
description: >
Mail-spezifische v1-Endpunkte für lesenden Zugriff auf archivierte
Mails/Postfächer (INT-01). IAM-nahe Funktionen (Login,
Tenant-Verwaltung) sind bewusst NICHT Teil dieser API — der
Tenant-Kontext wird als bereits validierter Query-Parameter vom
Aufrufer/Gateway mitgegeben.
servers:
- url: /api/v1/mail
paths:
/messages:
get:
summary: Mail-Liste
operationId: listMessages
parameters:
- $ref: "#/components/parameters/Tenant"
- name: q
in: query
required: false
description: Optionaler Volltext-Suchbegriff.
schema:
type: string
responses:
"200":
description: Liste der Treffer.
content:
application/json:
schema:
$ref: "#/components/schemas/MessageListResponse"
"400":
$ref: "#/components/responses/BadRequest"
"502":
$ref: "#/components/responses/UpstreamError"
/messages/{messageID}:
get:
summary: Mail-Detail
operationId: getMessage
parameters:
- $ref: "#/components/parameters/Tenant"
- $ref: "#/components/parameters/MessageID"
responses:
"200":
description: Vollständige Nachricht.
content:
application/json:
schema:
$ref: "#/components/schemas/MessageDetail"
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"502":
$ref: "#/components/responses/UpstreamError"
/messages/{messageID}/attachments/{index}:
get:
summary: Anhang-Download
operationId: getAttachment
parameters:
- $ref: "#/components/parameters/Tenant"
- $ref: "#/components/parameters/MessageID"
- name: index
in: path
required: true
description: Anhang-Index innerhalb der Nachricht (0-basiert).
schema:
type: integer
minimum: 0
responses:
"200":
description: Anhangsinhalt.
content:
application/octet-stream:
schema:
type: string
format: binary
"400":
$ref: "#/components/responses/BadRequest"
"404":
$ref: "#/components/responses/NotFound"
"502":
$ref: "#/components/responses/UpstreamError"
components:
parameters:
Tenant:
name: tenant
in: query
required: true
description: >
Mandanten-Kennung (bereits validiert vom Aufrufer/Gateway —
keine Anmeldung/Sitzungsprüfung Bestandteil dieser API).
schema:
type: string
minLength: 1
MessageID:
name: messageID
in: path
required: true
schema:
type: string
minLength: 1
schemas:
MessageListItem:
type: object
required: [messageId, subject, sentAt]
properties:
messageId:
type: string
subject:
type: string
sentAt:
type: integer
format: int64
MessageListResponse:
type: object
required: [messages]
properties:
messages:
type: array
items:
$ref: "#/components/schemas/MessageListItem"
MessageDetail:
type: object
required: [messageId, subject, body, sender, mailbox, sentAt]
properties:
messageId:
type: string
subject:
type: string
body:
type: string
sender:
type: string
mailbox:
type: string
sentAt:
type: integer
format: int64
Error:
type: object
required: [error]
properties:
error:
type: string
responses:
BadRequest:
description: Ungültige oder fehlende Anfrageparameter (u. a. fehlender Tenant-Kontext).
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
NotFound:
description: Nachricht oder Anhang für diesen Mandanten nicht gefunden.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
UpstreamError:
description: Ein nachgelagerter Dienst (Suchindex/Objektspeicher) hat einen Fehler geliefert.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"