# ConvoyPlan — Zugangsdaten für Agenten

> Wie ein Agent oder eine Integration Zugriff auf eine ConvoyPlan-Instanz erhält.
> Gliederung nach der auth.md-Spezifikation (<https://github.com/workos/auth.md>).

ConvoyPlan wird selbst gehostet. Es gibt keinen zentralen Dienst, an dem man sich
anmeldet, und keinen öffentlichen Endpunkt auf convoyplan.de. Authentifiziert wird
immer gegen **die Instanz der jeweiligen Organisation**. Diese Domain hier ist die
Produktseite und stellt selbst keine geschützten Ressourcen bereit.

## Discover

Ausgangspunkt ist die Adresse der Instanz. Sie kommt vom Betreiber, nicht aus einem
Verzeichnis — ConvoyPlan verarbeitet Einsatzdaten von BOS-Organisationen und listet
Installationen deshalb nirgends öffentlich auf.

Steht die Adresse fest, sind die beiden Einstiege:

- MCP-Server: `https://{instanz}/mcp` — die genaue Adresse zeigt das Admin-Portal der Instanz.
- REST-API: `https://{instanz}/api`, auf der öffentlichen Demo-Instanz `https://web.convoyplan.de/api`.

Ein unauthentifizierter Aufruf beantwortet die Frage nach dem Verfahren direkt:

```http
GET /api/auth/me HTTP/1.1
Host: {instanz}

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
```

Der `WWW-Authenticate`-Header nennt das Schema. Ein `resource_metadata`-Parameter
nach RFC 9728 ist darin nicht enthalten; `/.well-known/oauth-protected-resource` und
`/.well-known/oauth-authorization-server` liefern die Instanzen derzeit nicht aus.
Wer sie braucht, hält sich an die Beschreibung hier und an die
[API-Dokumentation](https://github.com/RettTechSolutions/ConvoyPlan/wiki/API-Dokumentation).

## Pick a method

Drei Verfahren, in dieser Reihenfolge:

1. **OAuth 2.0 mit PKCE (S256) über MCP** — der vorgesehene Weg für KI-Agenten.
   Der Agent handelt im Namen eines Menschen, der sich im Browser anmeldet und die
   Organisation auswählt. Berechtigungen werden bei jedem Aufruf frisch gegen die
   Datenbank geprüft, nicht einmalig beim Token-Ausstellen.
2. **JWT per Login** — `POST /api/auth/login` liefert ein Token für einen
   Benutzeraccount. Für Skripte, die als bekannter Benutzer arbeiten.
3. **Statischer API-Key** — `X-API-Key: cvp_<prefix>_<secret>` für Dienst-zu-Dienst-
   Integrationen ohne Benutzerkontext. Der Key trägt eine feste Rolle.

Ausdrücklich **nicht** unterstützt: der `agent_auth`-Block der auth.md-Spezifikation
mit `identity_endpoint`, `identity_types_supported`, `identity_assertion` oder
`service_auth`, und damit auch keine ID-JAG-Token
(`urn:ietf:params:oauth:token-type:id-jag`). Es gibt dafür keine Endpunkte — ein
Agent sollte gar nicht erst danach suchen. Wer so etwas für eine Integration braucht:
anfrage@convoyplan.de.

## Register

Eine dynamische Client-Registrierung gibt es nicht. Registriert wird durch einen
Menschen mit Admin-Rolle in der Instanz:

- **MCP:** Der Admin kopiert die MCP-Adresse aus dem Admin-Portal in den Client
  (Claude, ChatGPT, eigener Agent). Der Client registriert sich dort als Remote-MCP-Server.
- **API-Key:** Superadmin-Portal → Admin → API-Keys. Ein Key wird genau einmal im
  Klartext angezeigt. Er gilt für eine Organisation (Org-Key) oder systemweit
  (System-Key) und trägt die Rolle, die bei der Ausstellung gewählt wurde.
- **Benutzeraccount:** vom Organisations-Admin angelegt, mit einer der Rollen Admin,
  Planer, Fahrer oder Beobachter.

## Claim

Beim MCP-Weg meldet sich der Mensch im Browser mit seinen ConvoyPlan-Zugangsdaten an,
wählt die Organisation und bestätigt die Freigabe. Erst danach erhält der Client den
Autorisierungscode. Der Agent kann diesen Schritt nicht überspringen und nicht
automatisieren — das ist Absicht.

Beim API-Key entfällt der Schritt: der Key ist das Geheimnis und wird bei der
Ausstellung übergeben.

## Exchange

```http
POST /api/auth/login HTTP/1.1
Host: {instanz}
Content-Type: application/json

{"username": "...", "password": "..."}
```

Antwort: ein JWT. Bei aktivierter MFA (TOTP) ist zusätzlich der zweite Faktor nötig.

Beim MCP-Weg tauscht der Client den Autorisierungscode zusammen mit dem
PKCE-`code_verifier` gegen ein Access-Token. Ein statischer API-Key wird nicht
getauscht, sondern direkt gesendet.

## Use the access_token

```http
GET /api/... HTTP/1.1
Host: {instanz}
Authorization: Bearer <access_token>
```

oder

```http
GET /api/... HTTP/1.1
Host: {instanz}
X-API-Key: cvp_<prefix>_<secret>
```

Beide Header nie kombinieren. Der Zugriff ist in jedem Fall auf die Organisation und
die Rolle begrenzt, die am Token oder am Key hängen.

## Errors

| Status | Bedeutung | Reaktion |
|---|---|---|
| `401` mit `WWW-Authenticate: Bearer` | kein, abgelaufenes oder ungültiges Token | neu anmelden bzw. Token erneuern |
| `403` | authentifiziert, aber die Rolle reicht nicht | nicht wiederholen, Rolle beim Admin klären |
| `402` | Instanz läuft im Demo-Modus, der Zugriff wäre schreibend | lesend weiterarbeiten oder Lizenzschlüssel anfragen |
| `404` auf `/docs`, `/redoc`, `/openapi.json` | API-Dokumentation ist deaktiviert | Betreiber setzt `DOCS_API_KEY` oder `ENABLE_DOCS=true` |

## Revocation

- **API-Keys** werden im Superadmin-Portal gelöscht und gelten ab sofort nicht mehr;
  es gibt keine Karenzzeit.
- **MCP-Freigaben** zieht der Benutzer über sein Konto in der Instanz zurück; der
  Client verliert damit den Zugriff.
- **JWTs** laufen ab. Wird ein Benutzer deaktiviert oder seine Rolle geändert, greift
  das sofort, weil die Berechtigung bei jedem Aufruf gegen die Datenbank geprüft wird.
- **Verdacht auf ein geleaktes Geheimnis:** Key löschen und den Sicherheitskontakt
  nach RFC 9116 unter <https://convoyplan.de/.well-known/security.txt> verwenden.

## Weiterführend

- [MCP-Server](https://github.com/RettTechSolutions/ConvoyPlan/wiki/MCP-Server)
- [API-Dokumentation](https://github.com/RettTechSolutions/ConvoyPlan/wiki/API-Dokumentation)
- [Wiki: Rollen, Berechtigungen und Mandantentrennung](https://github.com/RettTechSolutions/ConvoyPlan/wiki)
- [Demo-Modus](https://github.com/RettTechSolutions/ConvoyPlan/wiki/Lizenz-und-Demo-Modus)
- [Entwicklerportal](https://convoyplan.de/developers/)
