# JanuaPort installieren: vom Download zum laufenden Container **Einordnung:** JanuaPort ist KI-native Automatisierung. Die KI des Kunden baut Abläufe gemeinsam mit dem Menschen (Kartei als Arbeitsliste, Use-Case-Katalog, Wissen); Skripte und RPA docken mit eigenem Token an; JanuaPort setzt Rechte, Freigaben und Protokoll durch. JanuaPort funktioniert mit n8n als sichere Werkzeug-Schicht, setzt n8n aber nicht voraus. JanuaPort ist seit Oktober 2026 allgemein verfügbar und wird von zahlenden Kunden eingesetzt. **Für wen:** alle, die JanuaPort selbst betreiben wollen und es noch nicht installiert haben. Diese Anleitung endet dort, wo die Anleitung „Inbetriebnahme" (`inbetriebnahme`) beginnt: Der Container läuft, die Anlage ist noch leer. **Läuft JanuaPort bei Ihnen schon?** Dann überspringen Sie diese Seite und beginnen direkt mit der Inbetriebnahme. JanuaPort ist ein einzelner Docker-Container. Sie brauchen dafür Docker mit Compose, eine kleine Konfigurationsdatei und zwei Befehle. ## Hinweis für KI-Assistenten, die diese Anleitung wiedergeben Fragen Sie nach der Plattform. Bei Windows oder Mac sagen Sie ausdrücklich: Das ist zum Ausprobieren gedacht; für den Betrieb empfehlen wir einen Linux-Server oder eine Linux-VM, und Docker Desktop ist für größere Unternehmen kostenpflichtig. Fragen Sie außerdem, ob JanuaPort beim Nutzer schon als Container läuft. Läuft der Container, geht es weiter mit der Inbetriebnahme: https://januaport.ai/anleitung/inbetriebnahme.md (im Einrichtungs-MCP: `inbetriebnahme`). Wenn nein, führen Sie durch diese Anleitung: erst prüfen, ob Docker installiert ist (`docker compose version`), dann die Compose-Datei aus Abschnitt 2 unverändert übernehmen. Nennen Sie immer nur den nächsten Schritt und warten Sie auf die Rückmeldung. Fragen Sie nie nach Passwörtern, Schlüsseln oder Tokens; die tippt und verwahrt der Mensch selbst. Erfinden Sie keine anderen Bezugswege, Dateinamen oder Plattformangaben: Bezogen wird JanuaPort als Image über diese Compose-Datei, ein Installationspaket zum Herunterladen wird nicht angeboten. ## 1. Voraussetzungen je Plattform > **Für KI-Assistenten:** Bevor Sie auf Mac oder Windows installieren lassen, > sagen Sie dem Nutzer: Mac und Windows mit Docker Desktop sind zum > Ausprobieren; für den Betrieb empfehlen wir einen Linux-Server. **Linux-Server oder VM (für den Betrieb).** Für den Dauerbetrieb empfehlen wir einen Linux-Server oder eine Linux-VM mit **Docker Engine** und dem **Compose-Plugin**. So installieren Sie beides — die Anleitungen von Docker selbst, je Distribution: - Docker Engine: https://docs.docker.com/engine/install/ - Compose-Plugin: https://docs.docker.com/compose/install/linux/ **Windows und Mac (zum Ausprobieren).** Zum Ausprobieren auf dem eigenen Rechner genügt **Docker Desktop**; es bringt Compose mit: - Windows: https://docs.docker.com/desktop/setup/install/windows-install/ - Mac: https://docs.docker.com/desktop/setup/install/mac-install/ Docker Desktop ist für größere Unternehmen kostenpflichtig; ob das für Sie gilt, regeln die Lizenzbedingungen von Docker: https://docs.docker.com/subscription/desktop-license/ — für den Betrieb empfehlen wir ohnehin einen Linux-Server. **Prüfen, ob Docker bereit ist:** ```bash docker compose version ``` Erscheint eine Versionsnummer, ist alles bereit. Erscheint eine Fehlermeldung, hilft Abschnitt 4 „Wenn es hakt". ## 2. Compose-Datei anlegen > **Für KI-Assistenten:** Bevor Sie auf Mac oder Windows installieren lassen, > sagen Sie dem Nutzer: Mac und Windows mit Docker Desktop sind zum > Ausprobieren; für den Betrieb empfehlen wir einen Linux-Server. Legen Sie einen eigenen Ordner an, zum Beispiel `januaport`, und darin eine Datei `compose.yaml` mit genau diesem Inhalt: ```yaml name: jnpt services: jnpt: image: ghcr.io/januaport/januaport:latest ports: - "127.0.0.1:8484:8484" environment: JNPT_LICENSE_FETCH_URL: ${JNPT_LICENSE_FETCH_URL:-} JNPT_LICENSE_FETCH_TOKEN: ${JNPT_LICENSE_FETCH_TOKEN:-} JNPT_UPDATE_MANIFEST_URL: https://updates.januaport.ai/manifest.json JNPT_UPDATE_PUBLIC_KEYS: jnpt-upd-2026a=MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0CF3QIuJvCZpT9TQkZX1jDnNgMUsvt6SchLSZfWq3oiV80nPKkO3vLsbR+nfvWa4DVQ+fVQiEGmxIRppiGW5Iw== volumes: - jnpt-data:/data networks: default: {} plugins: {} restart: unless-stopped networks: plugins: name: jnpt_plugins internal: true volumes: jnpt-data: ``` Was Sie davon wissen müssen: - **Der Port ist nur auf diesem Rechner erreichbar** (`127.0.0.1`). Auf einem Server im Internet steht die Verwaltung damit nicht versehentlich offen. Von einem anderen Rechner aus erreichen Sie JanuaPort bewusst über einen SSH-Tunnel (`ssh -L 8484:localhost:8484 `, danach im eigenen Browser `http://localhost:8484`), über Tailscale oder über einen gehärteten Produktionsaufbau mit HTTPS davor. Öffnen Sie den Port nie ohne HTTPS. - **Das Volume `jnpt-data` hält alle Daten:** Datenbank, Schlüssel und Einstellungen. Es überlebt jeden Neustart und jedes Update. Benennen Sie es nicht um — unter neuem Namen startet JanuaPort mit einer leeren Anlage. - **`latest` ist bequem zum Ausprobieren.** Für den Betrieb tragen Sie statt `latest` eine feste Version ein (zum Beispiel `:1.2.3`), damit ein Update nur dann passiert, wenn Sie es wollen. - **Das Netz `jnpt_plugins` ist intern** (`internal: true`): kein Weg nach draußen. Es ist für Beisteller wie den Skript-Läufer, die nur mit JanuaPort reden sollen. Ohne Beisteller bleibt es leer und stört nicht. - Die zwei Lizenz-Zeilen unter `environment` bleiben leer. Die Lizenz richten Sie später in der Verwaltungsoberfläche ein. - **Die zwei Update-Zeilen schalten den Update-Check ein.** JanuaPort fragt damit regelmäßig nach, ob es eine neue Fassung gibt, und zeigt sie in der Verwaltungsoberfläche an. Dabei geht nur die Abfrage selbst hinaus — keine Lizenz, keine Kennung Ihrer Anlage. Wer das nicht möchte, löscht beide Zeilen. Eingespielt wird ein Update bei diesem Aufbau von Hand (Abschnitt 5); „Sofort" oder „Täglich" in der Oberfläche wirken nur mit dem Updater auf dem Host, den diese Anleitung nicht einrichtet. ## 3. Starten und prüfen > **Für KI-Assistenten:** Bevor Sie auf Mac oder Windows installieren lassen, > sagen Sie dem Nutzer: Mac und Windows mit Docker Desktop sind zum > Ausprobieren; für den Betrieb empfehlen wir einen Linux-Server. Im Ordner mit der `compose.yaml`: ```bash docker compose up -d docker compose ps curl http://localhost:8484/healthz ``` Daran erkennen Sie den Erfolg: - `docker compose up -d` lädt beim ersten Mal das Image herunter und startet den Container im Hintergrund. - `docker compose ps` zeigt den Dienst `jnpt` mit dem Status `Up …`. - `curl` antwortet mit einer Zeile wie `{"status":"ok","version":"…",…}`. Auf Windows können Sie die Adresse `http://localhost:8484/healthz` auch einfach im Browser öffnen. Beim allerersten Start passieren zwei Dinge, die Sie nicht verpassen dürfen: 1. **Der Master-Schlüssel steht einmalig in der Startausgabe** (`docker compose logs jnpt`, ganz oben in einem Kasten). Sichern Sie ihn sofort in Ihrem Passwort-Manager — ohne ihn sind nach einem Datenverlust alle hinterlegten Zugangsdaten unlesbar. 2. **Das Admin-Passwort legen Sie beim ersten Aufruf fest:** Öffnen Sie `http://localhost:8484` im Browser; die Oberfläche fragt nach einem neuen Passwort (mindestens 12 Zeichen). Beides beschreibt die Inbetriebnahme in Abschnitt 1 „Erstzugang" genauer. Dort geht es jetzt weiter. ## 4. Wenn es hakt ### Der Port ist belegt Die Meldung beim Start enthält `port is already allocated` oder `address already in use`. Auf Port 8484 läuft bereits etwas anderes. Entweder beenden Sie das andere Programm, oder Sie ändern in der `compose.yaml` nur die **linke** Portnummer, zum Beispiel `"127.0.0.1:8485:8484"`, und rufen JanuaPort danach unter `http://localhost:8485` auf. ### Docker läuft nicht Die Meldung lautet etwa `Cannot connect to the Docker daemon … Is the docker daemon running?` oder unter Windows `error during connect … The system cannot find the file specified`. Auf Windows und Mac starten Sie Docker Desktop und warten, bis es „running" meldet. Auf Linux starten Sie den Dienst mit `sudo systemctl start docker`. Lautet die Meldung `permission denied`, fehlen Ihrem Benutzer die Rechte für Docker: Befehl mit `sudo` ausführen oder den Benutzer in die Gruppe `docker` aufnehmen. ### Das Image lässt sich nicht ziehen Die Meldung enthält `denied`, `unauthorized` oder `manifest unknown`. Vor dem allgemeinen Start von JanuaPort ist das Image noch nicht öffentlich herunterladbar — das ist dann kein Fehler auf Ihrer Seite. Melden Sie sich in diesem Fall bei uns; wie, steht im Dokument „Beratung und Einrichtung" (`beratung-und-einrichtung`). Steht in der Meldung dagegen etwas von `timeout` oder `no such host`, fehlt dem Rechner der Weg ins Internet (Proxy, Firewall). ## 5. Update und Daten Ein Update sind zwei Befehle im Ordner mit der `compose.yaml`: ```bash docker compose pull docker compose up -d ``` Der erste lädt das neue Image, der zweite tauscht den Container aus. Ihre Daten bleiben dabei im Volume `jnpt-data` erhalten. Ziehen Sie vor jedem Update trotzdem ein Backup (`docker compose exec jnpt /jnpt backup`); Details stehen in der Inbetriebnahme, Abschnitt 6 „Betrieb". Weiter geht es mit der Inbetriebnahme: https://januaport.ai/anleitung/inbetriebnahme.md # Inbetriebnahme: von „Container läuft" zu „Anlage arbeitet" **Einordnung:** JanuaPort ist KI-native Automatisierung. Die KI des Kunden baut Abläufe gemeinsam mit dem Menschen (Kartei als Arbeitsliste, Use-Case-Katalog, Wissen); Skripte und RPA docken mit eigenem Token an; JanuaPort setzt Rechte, Freigaben und Protokoll durch. JanuaPort funktioniert mit n8n als sichere Werkzeug-Schicht, setzt n8n aber nicht voraus. JanuaPort ist seit Oktober 2026 allgemein verfügbar und wird von zahlenden Kunden eingesetzt. **Für wen:** den Admin einer frischen JanuaPort-Anlage — egal, auf welchem Weg sie entstanden ist. Die drei Provisionierungs-Wege enden alle am selben Punkt (ein laufender Container mit leerer Anlage) und setzen hier fort: | Weg bis „Container läuft" | Anleitung | |---|---| | VM mit Infrastruktur-Automatik (Hetzner-Referenz) | [`docs/deploy-hetzner.md`](deploy-hetzner.md) | | Selbst-Hoster (`docker compose up`) | [`docs/installation.md`](installation.md) — vom Download zum laufenden Container | | JanuaPort Box | `docs/box-runbook.md` | **Woher dieses Dokument kommt:** Es ist das Protokoll eines echten, vollständigen Neuaufbaus (Showcase-Anlage, 12./13.08.2026), MCP-first gefahren — jeder Schritt, jeder Stolperstein und jede bewusste Mensch-Ausnahme stammen aus diesem Lauf, nicht vom Schreibtisch. Wo der Admin-MCP etwas (noch) nicht kann, steht es hier ehrlich mit Issue-Nummer. ## 0. Das Betriebsmodell in drei Sätzen Ein **Admin-Agent** (z. B. Claude mit dem Admin-MCP verbunden) kann die gesamte Einrichtung fahren — Integrationen, Teams, Berechtigungen, Pseudonymisierung, Token, Diagnose. **Genau zwei Dinge bleiben bewusst beim Menschen:** der allererste Admin-Zugang (Passwort + erster Admin-Token) und **jeder Geheimnis-Wert** (API-Schlüssel, Client-Secrets — sie laufen nie durch einen Chat). Drittens gilt: Tenant-Administration bei Fremdanbietern (Entra, Exchange) bleibt ebenfalls Mensch-Arbeit — das Werkzeug bereitet maximal vor (fertige Skripte, exakte Klick-Wege). ## 1. Erstzugang (die einzigen Host-Schritte) **Betreiber-Mail einschalten (Stufe 1, gebaut):** Den vorhandenen SMTP- oder Graph-Weg einrichten, Empfänger in `JNPT_SMTP_TO` angeben und `JNPT_NOTIFY_STATE=true` setzen; Anleitung in [Update-Runbook, Benachrichtigung](update-runbook.md). Die Familien sind Update, Zustand (Lizenz/Plätze/Erreichbarkeit), Credential-Ablauf und `admin_mcp_change`. Letztere meldet Admin-KI-Änderungen an Pins, Repo-URL, Credential-Override sowie Anlage/Anhebung mit Adressen oder Instanzwerten (nur Feldnamen/Hosts, keine Werte), Team-Integrationsstufen sowie Protokolltiefe/Inhaltsfrist (alt → neu); dazu menschliche Änderungen der Admin-MCP-Schalter. Versand ist best effort; fehlende Mail hält kein Setup an. Zehn Mails je Stunde und Prozess, danach Sammelmail, Schalter ungebremst. Der Zähler und wartende Sammelvorgänge sind flüchtig und gehen beim Neustart verloren; das Protokoll bleibt vollständig. Ohne eingeschalteten Mail-Weg warnt die Seite Admin-MCP-Berechtigungen sichtbar. Details und Grenzen: [Setup-Modus und Mail](admin-mcp.md#mail-an-den-betreiber-1084-b-stufe-1-gebaut). 0. **Master-Schlüssel sichern — VOR allem anderen.** Läuft die Anlage ohne gesetztes `JNPT_MASTER_KEY`, erzeugt sie beim allerersten Start ihren Master-Schlüssel selbst und schreibt ihn **einmalig** in die Startausgabe (`docker logs jnpt-jnpt-1`, ganz oben — ein umrahmter Kasten mit Pfad, Wert und Aufforderung). Diesen Wert **jetzt** in den Passwort-Manager des Betriebs kopieren, getrennt von den Backups. ⚠️ **Er erscheint nur dieses eine Mal.** Ohne ihn sind nach einem Verlust des Volumes alle Credentials, alle Pseudonym-Zuordnungen und alle Backups unlesbar — es gibt keinen Reset und keinen Support-Weg (`docs/disaster-recovery.md` §0). Verpasst? Der Wert steht in der Key-Datei. Das Image hat keine Shell und kein `cat`; lesen Sie die Datei deshalb über `docker cp` aus, ohne Kopie auf der Platte: `docker cp jnpt-jnpt-1:/data/jnpt.key - | tar -xO`. Der Leitstand zeigt die Aufforderung als Karte **„Master-Schlüssel"**, bis dort **„Ist verwahrt"** bestätigt wird; danach ist sie dauerhaft weg. Den Wert zeigt die Oberfläche nie, und die Key-Datei gibt es dort bewusst nicht zum Herunterladen. 1. **Admin-Passwort setzen:** Die GUI verlangt beim ersten Aufruf einen Setup-Schritt (min. 12 Zeichen). Die Verwaltungsfläche ist nie öffentlich — erreichbar nur über Tailnet, internes Netz oder einen SSH-Tunnel. 2. **Ersten Admin-Token erzeugen** (CLI auf dem Host): `docker exec jnpt-jnpt-1 /jnpt admin-token create --label --expires 720h` Der Wert erscheint genau einmal. Das Ablaufdatum ist Pflicht (höchstens 1 Jahr); vor Ablauf einen neuen Token anlegen. 3. **Admin-Agent verbinden:** MCP-Endpunkt `…/admin/mcp`, Bearer = Admin-Token. > Die saubere Reihenfolge ist Passwort **vor** Token. Nichts erzwingt sie — > aber der Token gehört einem Betreiber, dessen GUI-Zugang schon steht. 4. **Basis-Einrichtung prüfen** (GUI: *Credentials* → Sektion „Basis-Einrichtung (System)"): Dort steht jede Stelle, die JanuaPort für sich selbst braucht — **auch die, die noch fehlt**. Auf einer frischen Anlage ist das mindestens der **Lizenz-Abruf** (`lizenz-abruf`, Zweck „Lizenz-Abruf beim Hersteller"): Er ist dauerhaft reserviert und trägt die Zeile **„fehlt"**, bis das Abruf-Secret hinterlegt ist. Über „Anlegen" ist der Name vorbelegt und gesperrt — er muss nicht abgetippt werden (ein Tippfehler legte sonst still ein Integrations-Credential an). Der Abruf selbst wird über *Lizenz → Abruf einrichten* eingerichtet (`docs/license.md`); solange er fehlt, geht die Lizenz nur über den Datei-Weg. Kommt SSO dazu (§3), erscheint dort zusätzlich die **Verzeichnis-Suche** — auch sie zuerst als „fehlt". Fährt die Anlage einen **Anbindungsweg** (ChatGPT über den OpenAI-Tunnel — erkennbar am eingehängten Bereitstellungs-Verzeichnis `/run/jnpt/tunnel`, das die ausgelieferten Compose-Dateien standardmäßig mitbringen), steht dort als dritte Stelle **`openai-tunnel`** („Anbindungsweg ChatGPT — Laufzeit-Schlüssel des OpenAI-Tunnels"). Fehlt der Mount (und ist auch `JNPT_TUNNEL_KEY_FILE` nicht gesetzt, das nur noch den Ort überschreibt), erscheint die Zeile gar nicht — wer keinen Anbindungsweg fährt, merkt von diesem Teil nichts. Sobald der Wert hinterlegt ist, stellt ihn das Gateway dem Beisteller innerhalb einer Minute bereit; Rotation läuft ab dann über dieselbe Zeile (Aufsetzen: `docs/deploy-hetzner.md` §13). ⚠️ Die Spalte **Ablauf** bleibt bei dieser Stelle leer — OpenAI-Laufzeitschlüssel laufen ohne Zutun nicht ab. Auf der Kommandozeile sagt dasselbe `docker exec jnpt-jnpt-1 /jnpt credential list`: unter der Tabelle steht je **fehlender** Stelle eine Zeile `FEHLT ` (eine vorbereitete Stelle gilt als vorhanden). > **Ritual, kein Kür:** Jeder Diagnose- oder Wegwerf-Token (z. B. zum > Fehlersuchen) gehört sofort nach Gebrauch widerrufen — > `docker exec … /jnpt admin-token revoke ` (`` positional, aus der > Ausgabe von `admin-token create`). Dafür gibt es bewusst keinen > Admin-MCP-Weg: Admin-Tokens verwalten sich nicht selbst über MCP > (kein Self-Escalation-Pfad). ## 2. Nutzer und Teams 1. **Nutzer anlegen** (`admin_create_user`) — eine organisatorische Identität, kein Login. ⚠️ **Bei SSO-Betrieb sofort die Entra-Objekt-ID verknüpfen** (`admin_set_user_external_subject`, der `oid`-Claim): Ohne Verknüpfung legt der erste SSO-Login ein **Duplikat** an (live passiert). 2. **Teams anlegen** (`admin_create_team`) — Slug bewusst wählen, er ist die Endpunkt-Adresse und **nicht änderbar**. Teams starten ohne alles (deny-by-default). 3. **Team-Endpunkte einschalten** (`admin_set_team_endpoint_view`) — `/mcp/v/` ist die kuratierte Sicht, über die Clients verbinden. **Empfohlene Grundstellung (im Lauf bewährt):** Der Haupt-Endpunkt `/mcp` bleibt leer; jede Integration wird ausschließlich über Team-Scopes an Team-Endpunkten vergeben. Katalog, Problem-Melden und Ping sind strukturell immer da und brauchen keinen Scope. ## 3. SSO (Entra) — wenn das Unternehmen ein Verzeichnis hat Konfiguration: `.env` neben der Compose-Datei (`JNPT_SSO_*`, Runbook §11 — die Compose-Datei selbst wird nicht editiert). Die Entra-Seite Schritt für Schritt (App-Registrierung, Token-Version 2, App-ID-URIs, Rückruf-URIs, Zuweisung) steht für den Mandanten-Admin in `docs/sso-entra-einrichtung.md`. Danach im Portal und in der Anlage: 1. **App-ID-URIs**: je Endpunkt-Adresse ein Eintrag (`https:///mcp` und jede Team-View). ⚠️ Die Liste ist **ersetzend** — ergänzen, nie überschreiben. 2. **App-Rollen** je Team anlegen und Nutzern zuweisen. Drei Stolpersteine aus dem Live-Lauf: Rolle muss **aktiviert** sein (App-Registrierung → App-Rollen → Zeile anklicken → Häkchen unten) · Mitgliedertyp **Benutzer/Gruppen** · die Zuweisen-Ansicht der Unternehmensanwendung **synchronisiert verzögert** — Panel schließen, „Aktualisieren" oben rechts, 2–3 Minuten Geduld. Eine Rolle je Zuweisungsvorgang. ⚠️ **Die App-Registrierung umbenennen statt neu anlegen:** Ein neuer Name geht über **Branding & Eigenschaften** der bestehenden App-Registrierung — **kein** Neuanlegen. Eine neue Registrierung hätte eine neue Client-ID, verlorenen Consent und ein neues Secret zur Folge, und Bestandsverbindungen müssten neu verbunden werden (Runbook §11.6.4). **Manifest-Warnung nicht überbewerten:** Entra markiert nur das **alte Azure-AD-Graph-Format** als abgekündigt — das manuelle Editieren des aktuellen Manifests (Punkt 1, Runbook §11.6.1) bleibt möglich und ist weiterhin der Weg. 3. **Rollen an Teams brücken** (`admin_set_team_idp_groups`, Rollenwert = Claim-Wert). 4. ⚠️ **Gruppen-Freigabe** (der bewusste Admin-Akt: „Berechtigung entsteht nie durch Login allein"): Jede Rolle/Gruppe, die sich anmelden darf, muss **freigegeben** sein — sonst scheitert der Login mit „Autorisierung fehlgeschlagen". Heute nur in der GUI (Team-Seite → Freigegebene Gruppen); über den Admin-MCP noch nicht möglich, geplant. 5. **Sockel-Berechtigung** (`JNPT_SSO_DEFAULT_SCOPE`): bekommt **jeder** erfolgreiche Login vor jeder Team-Zuordnung. Empfehlung: **leer lassen** — nie eine Integration. Das Gedächtnis (`memory_*`) braucht hier nichts mehr: Es ist ein Basis-Werkzeug und für jeden gültigen Zugang da (wie `ping`, `catalog`, `report_problem`). Ein alter `memory`-Eintrag wird weiterhin angenommen, ist aber wirkungslos und wird beim Start gemeldet. 6. **Client verbinden:** Beim Anlegen des Connectors in Claude gehört die **OAuth-Client-ID in die erweiterten Einstellungen** — ohne sie scheitert der Verbindungsaufbau. **Stolpersteine beim Verbinden (Live-Lauf):** - **404 ohne OAuth-Discovery** beim Verbinden auf eine **nicht eingeschaltete** Endpunkt-View → Claude meldet irreführend „Client-Registrierung nicht unterstützt" — das ist nicht das eigentliche Problem. Prüfen: Ist die View am Team überhaupt eingeschaltet (§2 Punkt 3)? - **Ein aktiver View liefert nie 0 Tools.** Zeigt `tools/list` nach dem Verbinden eine leere Liste, ist die Verbindung selbst das Problem (trennen + neu verbinden), nicht die Scope-Vergabe — die hätte mindestens die strukturell immer vorhandenen Werkzeuge (Katalog, Problem-Melden, Ping) gezeigt. - **Ein staler Browser-Tab täuscht fehlende Features vor.** Die Versionsanzeige der GUI kommt live von der API, `index.html` selbst ist `no-store` — ein hartnäckig altes Bild braucht meist nur **F5**, bevor man nach einem echten Fehler sucht. ## 4. Je Integration: die eiserne Reihenfolge Immer in dieser Folge — Pseudonymisierung **vor** der ersten echten Nutzung, Team-Freigabe **zuletzt**: 1. **Connector-Beschreibung einspielen** (YAML nach `JNPT_CONNECTORS_DIR`, Neustart — Datei+CLI, noch kein Admin-MCP-Weg; mitgelieferte Vorlagen kommen über den Katalog). Neustarts sind unkritisch: bestehende Client-Verbindungen überleben sie nachweislich. 2. **Credential vorbereiten** (`admin_prepare_credential` — nur der NAME). **Der Wert kommt vom Menschen** über die GUI (Wert und Ablaufdatum mit einem Speichern). 3. **Live-Verbindung belegen** (`admin_check_connector`; für Datenbank-Integrationen `admin_check_database` — vierstufig inkl. `SELECT 1`-Probe je Richtung): Spec · Credential · Probe gegen das echte System. Erst ein echter Erfolg zählt als „fertig". 4. **Pseudonymisierung konfigurieren:** - Feldnamen **belegen, nicht raten**: `admin_probe_tool_response_fields` (kostet einen echten API-Call; geht nur bei Werkzeugen ohne Pflichtparameter) oder die offizielle API-Doku. Ein Tippfehler im Feldnamen wirft keinen Fehler — die Zeile sieht nur geschützt aus. - ⚠️ **Schlüsselnamen können mehrdeutig sein** (Lexware: `name` = Kundenname im Kontakt, aber Artikelname in Rechnungspositionen). Voll-Ersetzung dann **tool-genau** setzen, nicht integrationsweit — oder den Muster-Scan nehmen, dessen Form-Prüfung Fehlgriffe verhindert. - Muster-Empfehlung für Geschäftsdaten: `iban`, `email`, `steuernummer` (harte Inhalts-Prüfung). `telefon`/`geburtsdatum` nur bewusst — Belege sind voller Nummern und Daten, und **Muster sind unumkehrbar**. - Werte in **Arrays von Zeichenketten** (z. B. `emailAddresses.business`) erreicht die Ersetzung **seit Version 0.26.0** — es zählt der Schlüssel, unter dem die Liste hängt, für `read` wie für `scan`. Bis dahin war das eine benannte Klartext-Lücke; wer eine Deklaration deswegen zurückgebaut hat, setzt sie jetzt neu (von selbst kommt sie nicht wieder). 5. **Team-Freigabe** (`admin_set_team_scopes`): ersetzt die **ganze** Liste — Bestehendes mitführen. Schreib-Werkzeuge immer tool-genau. 6. **Gegenprobe aus Nutzer-Sicht:** Verbindung des Teams öffnen, Werkzeug aufrufen, Kürzel sehen (`‹name-…›` — deterministisch: gleicher Wert, gleiches Kürzel). Scope-Änderungen erreichen laufende Verbindungen ohne Neu-Verbinden. 7. **Audit-Gegenprobe** (`admin_query_audit_log`): jeder Schritt mit Akteur, Geheimnis-Werte geschwärzt. ## 5. Sonderfall Microsoft-Postfach Vollständig in [`docs/connector-microsoft-graph-mail.md`](connector-microsoft-graph-mail.md). Die Lehren des Live-Laufs: - **Ziel ist ein freigegebenes Postfach** (kostenlos), nie das persönliche Postfach eines Menschen. - **Ohne Schritt 4 (Exchange-Grenze) darf die App JEDES Postfach lesen** — und nichts warnt. Der Live-Lauf hat genau diesen Zustand vorgefunden. Skript-Vorlage: [`examples/exchange-postfach-grenze.ps1`](../examples/exchange-postfach-grenze.ps1). - **Entra- und Exchange-Rechte addieren sich:** Beim RBAC-Weg die mandantenweite `Mail.ReadWrite`-Zustimmung entfernen, sonst ist die Grenze wirkungslos. Der App-Token wird auch ohne Entra-Zustimmung ausgestellt (live belegt). - **Zwei Cache-Fallen:** Exchange-Änderungen brauchen 30 Minuten bis 2 Stunden. Und die Anlage cacht den App-Token bis zu dessen Ablauf — nach Rechte-Änderungen einmal neu starten, sonst testet man den alten Stand. - **Der Beweis braucht beide Richtungen:** erlaubtes Postfach → Erfolg, ein nachweislich **existierendes** fremdes Postfach → 403. Ein 404 beweist nichts. ⚠️ **Die Kontroll-Tabelle (`Test-ServicePrincipalAuthorization`) kann leer zurückkommen** — das ist für sich kein Fehlsignal. Der echte Werkzeug-Aufruf gegen das Postfach bleibt in jedem Fall der Beleg, nicht die Tabelle. - **Mehrere Postfächer:** ein Postfach = eine App = ein Credential = eine Integrations-Instanz (`admin_create_integration`). Die Grenze erzwingt das Zielsystem je App; Parameter-Einengung in JanuaPort selbst ist geplant. ## 6. Betrieb: was der Admin regelmäßig tut - **Problem-Meldungen** einsehen (`admin_list_problem_reports`) — Agenten melden über das eingebaute Werkzeug; Status und Admin-Notiz pflegen. - **Lizenz-Stand** fragen (`admin_get_license`): Plätze und, falls die Anlage über ihrem Limit liegt, der Tag, ab dem die überzähligen gesperrt werden. Frische Anlage = **Free mit drei Plätzen, kein Ablauf** — der vierte Platz entsteht nicht. Details und der Weg, einen Platz freizugeben: `docs/license.md`. - **Audit** stichprobenartig lesen; die Klartext-Gegenprobe („steht der echte Wert irgendwo?") gehört zu jeder neuen Integration. - **Backup:** `docker compose exec jnpt /jnpt backup` zieht einen verschlüsselten Voll-Abzug (DB + nicht-geheimer `JNPT_*`-Stand) in **eine** Datei — läuft neben dem laufenden Gateway. Der Master-Key gehört **getrennt davon** aufbewahrt (Passwortmanager/Secret-Manager): Verlust macht den Tresor **und alle Backups** unwiederbringlich. Ablauf, Automatisierung und Restore-Drill: [`docs/disaster-recovery.md`](disaster-recovery.md). - **Master-Schlüssel wechseln (Anlassfall, nicht Routine):** Wenn der Schlüssel in falsche Hände geraten sein könnte, wechselt ihn `jnpt key rotate` — **Einzelknoten**, in dieser Reihenfolge: ```bash docker compose down # 1) Gateway stoppen (nicht optional) docker compose run --rm jnpt key rotate # 2) rotieren (--new-key/--new-key-file optional) # # 3) Schlüsselquelle nachziehen: # Key-DATEI → hat der Befehl selbst aktualisiert # JNPT_MASTER_KEY → JETZT auf den neuen Wert setzen, VOR dem Start docker compose up -d # 4) starten docker compose exec jnpt /jnpt backup # 5) frisches Backup unter dem neuen Schlüssel ``` Erzeugt der Befehl den neuen Schlüssel selbst, zeigt er ihn **genau einmal** — dieselbe Zeremonie wie beim Erststart, dieselbe Sofort-Pflicht: verwahren. 🚨 **Den ALTEN Schlüssel nicht wegwerfen:** Backups von vor der Rotation öffnet nur er, und die Anlage führt bewusst keine Schlüssel-Historie (`docs/disaster-recovery.md` Abschnitt 5). - **Updates:** reiner Abbild-Tausch nach [`docs/update-runbook.md`](update-runbook.md); Client-Verbindungen überleben den Neustart. - **Mitgelieferte Kartei-Vorlagen einspielen (einmalig, optional):** Im Wissens-Ordner des Images liegen zwei fertige Satzarten — `ansprechpartner` („wer hilft bei welchem IT-Produkt?") und `best_practice` („was hat bei uns funktioniert?"). Eine KI zeigt sie Ihnen mit `wissen_get vorlagen/ansprechpartner`; im Repo stehen sie unter `docs/wissen/vorlagen/`. So gehen sie in Betrieb: 1. Datei nach `JNPT_KARTEIEN_DIR` kopieren (Default `/data/karteien`). 2. Die zwei auskommentierten Zeilen setzen — **oder beide weglassen** und den Zugriff wie gewohnt über Scopes vergeben: ```yaml freigabe: team owner_team: Buchhaltung # Name oder Team-ID ``` 3. `jnpt kartei check` (prüft die Datei OHNE Datenbank), dann neu starten bzw. SIGHUP schicken (`docker compose kill -s HUP jnpt`). ⚠️ Ein `owner_team` kann die Auslieferung nicht kennen — es gibt Ihre Teams beim Ausliefern noch gar nicht; deshalb stehen die Zeilen auskommentiert drin. Danach gehört die Datei **Ihnen**: Felder ergänzen, `search`/`filter` anders setzen — ein Update überschreibt sie nicht. Und: `ansprechpartner` trägt **Kontaktdaten Dritter**, die im **Klartext** an die KI gehen (die Kartei detokenisiert nie) — tragen Sie dort nur ein, was die KI sehen darf. ## 7. Was der Admin-MCP heute NICHT kann (ehrliche Liste) | Lücke | Ausweg heute | Stand | |---|---|---| | Connector-Beschreibung einspielen | Datei + Neustart | mitgelieferte Vorlagen: über den Katalog, auch per Admin-MCP | | Upstream-MCP-Instanzen anlegen | Datei, nur beim Start gelesen | geplant | | Gruppen-Freigabe lesen/setzen | GUI | geplant | | Lizenz-Token-Upload | GUI/REST/CLI oder Admin-MCP (signierter Token, kein Tresor-Credential) | `admin_install_license` — Rückfrage, Absicht vorab, Audit ohne Token | | Credential-**Werte** | GUI/CLI (bewusste Mensch-Ausnahme) | — |