# Connector-Vertrag v1 Code: `packages/connector-sdk/src/index.ts`. Jeder Provider implementiert `Connector` und liefert **nur normalisierte Daten** (`NormalizedResource`). Provider-Rohmodelle bleiben im Connector-Paket. | Element | Beschreibung | |---|---| | `capabilities(ctx)` | Fähigkeiten (`resources.list`, `lifecycle.suspend`, …). Backend/UI bieten nur Gemeldetes an. Das Lizenz-Connector meldet Schreibfähigkeiten nur mit konfiguriertem API-Benutzer. | | `healthCheck(ctx)` | Erreichbarkeit + Latenz. Ergebnis wird an der Instanz gespeichert (`health`, `last_ok_at`). | | `listResources(ctx)` | Abgleich. Ergebnis wird in `resources` gespiegelt; nicht mehr gelieferte Objekte werden mit `missing_since` markiert, nie gelöscht. | | `execute(ctx, {action, externalRef, params, idempotencyKey})` | Schreibende Aktion. Läuft ausschließlich als persistenter Auftrag (`connector.execute`), Idempotenzschlüssel = Job-ID. Aktionen setzen **absolute Zielzustände** (z. B. `until`), damit Wiederholung wirkungsgleich ist. | | Fehler | `ConnectorError` mit Codes `UNREACHABLE, TIMEOUT, AUTH_FAILED, RATE_LIMITED, NOT_FOUND, INVALID_RESPONSE, UNSUPPORTED, CONFLICT, UPSTREAM_ERROR, BAD_CONFIG`; `retryable` und `userMessage` (ohne technische Details). | | HTTP | `httpJson`: Timeout, exponentielles Backoff mit Jitter, `Retry-After`; Wiederholung nur für GET, Schreibzugriffe nie automatisch im Connector. | ## Aufträge Status: geplant → wird ausgeführt → erfolgreich | wird wiederholt → manuelle Prüfung erforderlich / fehlgeschlagen. Retries begrenzt (`max_attempts`, Backoff 30 s · 2ⁿ, max. 1 h). **Destruktive Aktionen (`terminate`) werden nie automatisch wiederholt**, auch nicht nach Worker-Absturz (`needs_review`), und lassen sich nicht über „Erneut ausführen“ starten. ## Neuer Connector 1. Paket `packages/connector-` mit `Connector`-Implementierung, `configFields` (Secrets als `secret: true`). 2. Vertragstest: `runContract(...)` aus `@kc/connector-sdk/dist/contract.js` plus Fixtures mit anonymisierten Antworten. 3. In `packages/connectors/src/index.ts` registrieren. Keine weitere Änderung in API/Worker/UI nötig. ## Vorhandene Connectoren - `mock` – Testdaten (`[Mock]`), simuliert Ausfälle (`simulateOutage`). - `licensing` – eigenes Lizenzsystem. Erkennt Erweiterungen über `GET /` → `features`: - Zugang bevorzugt per **Service-Token** (`token`), alternativ API-Benutzer/Passwort. Ohne Zugang nur lesend. - `catalog.list`: Produktkatalog des Lizenzsystems (Programm → Gruppe → Produkt mit Preis, Dauer, Features) als Übernahmevorlagen; Produkt- und Programmschlüssel werden nie ausgegeben. Ältere Systeme: Programme mit Vorschlägen aus bestehenden Lizenzen. - `lifecycle`: Sperren/Entsperren/Verlängern über die Endpunkte `/licenses/{id}/suspend|unsuspend|extend` (Zielzustand, protokolliert); sonst Rückfall auf `PUT`. - Zustand berücksichtigt `is_active`, `blocked`, `status`, `suspended_at`, `revoked_at` und Ablauf. Bei `utc_timestamps` werden Zeiten als UTC gelesen, sonst als Ortszeit. - Anlage (`lifecycle.create`) mit `product_id` (Plan/Edition des Lizenzsystems); Produkt und Präfix dürfen nie stillschweigend verloren gehen (Antwort wird geprüft). - KeyHelp, Plesk: **offen** (keine Testzugänge; siehe Plane). ## Zugangsdaten Secrets werden pro Verbindung mit AES-256-GCM verschlüsselt (`connector_instances.secrets_enc`), nur Superadmins dürfen Verbindungen anlegen/ändern, die UI zeigt sie nie wieder an, das Audit-Protokoll maskiert sie.