# TI-Gateway — Lokaler Telematikinfrastruktur-Prototyp

> **⚠️ PROTOTYP — NICHT FÜR PRODUKTIVEN EINSATZ!**
> Dieses Projekt emuliert Teile der Telematikinfrastruktur (TI) zu Test- und Lernzwecken. Es ersetzt keinen echten Konnektor und darf nicht im Klinikbetrieb eingesetzt werden. Alle Karten, Zertifikate und Tokens sind Demo-Daten.

## Was ist das?

Das TI-Gateway ist ein lokaler Prototyp, der die Schnittstellen eines gematik-Konnektors emuliert. Damit lassen sich SOAP-Anfragen (wie sie z.B. von Praxisverwaltungssystemen kommen) lokal testen, ohne Zugang zur echten TI zu benötigen.

Features:
- **SOAP-Konnektor-Schnittstelle** — ReadVSD, GetCards, VerifyPin, ExternalAuthenticate, GetCardTerminals, SignDocument
- **Smartcard-Emulation** — Virtuelle eGK- und SMC-B-Karten mit realistischen Testdaten
- **SICCT-Kartenterminal** — TCP-Server auf Port 4742, emuliert ein eHealth-Kartenterminal
- **ePA 2.0** — Elektronische Patientenakte mit Dokumentenverwaltung, feingranularer Zugriffskontrolle, Medikationsplan und Berechtigungsprofilen
- **Web-Dashboard** — Live-Übersicht über Karten, Dienste und SOAP-Requests via SSE
- **Externe Dienste** — Optionale Anbindung an Titus (VSDM), gematik IdP und E-Rezept-Fachdienst

## Architektur

```
┌─────────────────────────────────────────────────────────┐
│                    TI-Gateway (FastAPI)                  │
│                     localhost:8500                       │
├──────────┬──────────┬───────────┬───────────────────────┤
│  SOAP    │  REST    │   SSE     │   Static              │
│ /soap    │ /api/*   │ /api/     │   /static/            │
│ /conn*   │          │  events   │   index.html          │
├──────────┴──────────┴───────────┴───────────────────────┤
│                                                         │
│  ┌─────────────┐  ┌──────────────┐  ┌───────────────┐  │
│  │ SoapHandler │  │ CardManager  │  │ SicctServer   │  │
│  │ (Konnektor) │──│ (eGK, SMC-B) │──│ TCP :4742     │  │
│  └─────────────┘  └──────────────┘  └───────────────┘  │
│                                                         │
│  ┌─────────────┐  ┌──────────────┐  ┌───────────────┐  │
│  │ VsdmClient  │  │  IdpClient   │  │  ErpClient    │  │
│  │ (Titus)     │  │ (Docker)     │  │ (E-Rezept)    │  │
│  └──────┬──────┘  └──────┬───────┘  └──────┬────────┘  │
│                                                         │
│  ┌─────────────────────────────────────────────────┐   │
│  │              EpaClient (ePA 2.0)                 │   │
│  │  Dokumente │ Berechtigungen │ Medikationsplan    │   │
│  └─────────────────────────────────────────────────┘   │
└─────────┼────────────────┼──────────────────┼───────────┘
          ▼                ▼                  ▼
   Titus VSDM        IdP-Server         eRp-Fachdienst
   (gematik)       (localhost:8571)      (gematik Ref)
```

## Projektstruktur

```
TI-Gateway/
├── main.py                     # FastAPI-Server, Endpoints, SSE, Lifespan
├── config.json                 # Konfiguration (wird automatisch erstellt)
├── requirements.txt            # Python-Abhängigkeiten
├── docker-compose.yml          # IdP-Server (Docker)
├── cards/
│   ├── card_manager.py         # Karten-Emulation (VirtualCard, CardManager)
│   ├── egk_demo.json           # Demo-eGK (Max Mustermann, IKK classic)
│   └── smcb_demo.json          # Demo-SMC-B (IKK Kliniken)
├── konnektor/
│   ├── soap_handler.py         # SOAP-Request-Routing und Responses
│   └── sicct_server.py         # SICCT-TCP-Server (Kartenterminal-Emulation)
├── services/
│   ├── vsdm_client.py          # Client für Titus VSDM-Fachdienst
│   ├── idp_client.py           # Client für gematik IdP-Server
│   ├── erp_client.py           # Client für E-Rezept-Fachdienst
│   └── epa_client.py           # Client für ePA 2.0 (Elektronische Patientenakte)
└── static/
    └── index.html              # Dashboard (Single-File, SSE-basiert)
```

## Installation

### Einzeiler

```bash
pip install -r requirements.txt && python main.py
```

### Manuell

```bash
# 1. Abhängigkeiten installieren
pip install -r requirements.txt

# 2. Optional: IdP-Server starten (Docker)
docker compose up -d

# 3. Gateway starten
python main.py
```

Der Browser öffnet automatisch `http://localhost:8500`.

## Konfiguration

Beim ersten Start wird `config.json` erstellt:

```json
{
  "gateway_name": "TI-Gateway Prototyp",
  "version": "0.2.0",
  "soap_port": 8500,
  "sicct_port": 4742,
  "titus_enabled": false,
  "titus_url": "https://kon-instanz1.titus.gematik.solutions",
  "idp_url": "http://localhost:8571"
}
```

| Feld | Beschreibung |
|------|-------------|
| `gateway_name` | Anzeigename im Dashboard |
| `version` | Aktuelle Version |
| `soap_port` | Port für SOAP/REST/Dashboard (Standard: 8500) |
| `sicct_port` | Port für SICCT-TCP-Server (Standard: 4742) |
| `titus_enabled` | Titus-Anbindung aktivieren (Standard: false) |
| `titus_url` | URL der Titus-Instanz (gematik Referenzumgebung) |
| `idp_url` | URL des IdP-Servers (Standard: lokaler Docker-Container) |

Falls Port 8500 belegt ist, wechselt das Gateway automatisch auf 8501.

## API-Referenz

### SOAP-Endpoints

Alle drei Pfade führen zum gleichen Handler:

| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| POST | `/connector.sds` | Standard-Konnektor-Pfad |
| POST | `/soap` | Kurzform |
| POST | `/webservices/soap` | Alternativer Pfad |

**Unterstützte SOAP-Operationen:**

| Operation | Beschreibung | Voraussetzung |
|-----------|-------------|---------------|
| `ReadVSD` / `ReadVSD_Request` | Versichertenstammdaten von eGK lesen | eGK eingelegt |
| `GetCards` / `GetCards_Request` | Alle gesteckten Karten auflisten | — |
| `VerifyPin` / `VerifyPin_Request` | PIN einer Karte verifizieren | Karte eingelegt |
| `ExternalAuthenticate` / `ExternalAuthenticate_Request` | Authentifizierung mit SMC-B | SMC-B eingelegt |
| `GetCardTerminals` / `GetCardTerminals_Request` | Kartenterminals auflisten | — |
| `SignDocument` / `SignDocument_Request` | Dokument signieren (Mock) | SMC-B eingelegt |

**Beispiel: ReadVSD**

```bash
curl -X POST http://localhost:8500/soap \
  -H "Content-Type: application/soap+xml; charset=utf-8" \
  -d '<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <ReadVSD_Request xmlns="http://ws.gematik.de/conn/vsds/VSDService/v5.2">
      <Context>
        <MandantId>Mandant1</MandantId>
        <ClientSystemId>CS1</ClientSystemId>
        <WorkplaceId>WP1</WorkplaceId>
      </Context>
    </ReadVSD_Request>
  </soap:Body>
</soap:Envelope>'
```

**Beispiel: GetCards**

```bash
curl -X POST http://localhost:8500/soap \
  -H "Content-Type: application/soap+xml; charset=utf-8" \
  -d '<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <GetCards_Request xmlns="http://ws.gematik.de/conn/CardService/v8.1">
      <Context><MandantId>Mandant1</MandantId></Context>
    </GetCards_Request>
  </soap:Body>
</soap:Envelope>'
```

### REST-API Endpoints

| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| GET | `/api/status` | Gateway-Status (Config, Karten, Slots, Log) |
| GET | `/api/cards` | Alle eingelegten Karten |
| POST | `/api/cards/{slot}/insert` | Karte in Slot einlegen (JSON-Body) |
| POST | `/api/cards/{slot}/remove` | Karte aus Slot entfernen |
| POST | `/api/cards/{handle}/verify-pin` | PIN verifizieren (`{"pin": "123456"}`) |
| GET | `/api/soap-log` | Letzte 50 SOAP-Log-Einträge |
| GET | `/api/services` | Status aller externen Dienste |
| POST | `/api/test/read-vsd` | Test: ReadVSD simulieren |
| POST | `/api/test/get-cards` | Test: GetCards simulieren |
| POST | `/api/test/external-auth` | Test: ExternalAuthenticate simulieren |
| POST | `/api/test/titus-vsdm` | Test: VSDM gegen Titus |
| POST | `/api/test/idp-challenge` | Test: IdP-Challenge holen |
| POST | `/api/test/erp-create` | Test: Demo-E-Rezept erstellen |
| POST | `/api/test/erp-list` | Test: E-Rezepte auflisten |
| POST | `/api/test/epa-status` | Test: ePA-Aktenstatus abfragen |
| POST | `/api/test/epa-documents` | Test: ePA-Dokumente abrufen |
| POST | `/api/test/epa-upload` | Test: Dokument in ePA hochladen |
| POST | `/api/test/epa-permissions` | Test: ePA-Berechtigungen anzeigen |
| POST | `/api/test/epa-medication` | Test: Medikationsplan abrufen |

**Beispiel: Status abfragen**

```bash
curl http://localhost:8500/api/status
```

**Beispiel: Karte einlegen**

```bash
curl -X POST http://localhost:8500/api/cards/3/insert \
  -H "Content-Type: application/json" \
  -d @cards/egk_demo.json
```

### SSE-Endpoint

| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| GET | `/api/events` | Server-Sent Events (Live-Updates) |

Event-Typen:
- `init` — Initialzustand bei Verbindungsaufbau
- `soap_log` — Neuer SOAP-Log-Eintrag
- `card_inserted` — Karte eingelegt
- `card_removed` — Karte entfernt
- `services_status` — Status-Update externer Dienste (alle 30 Sekunden)

## Karten-Emulation

### Funktionsweise

Beim Start lädt der `CardManager` alle `*_demo.json`-Dateien aus `cards/`. Die eGK wird in Slot 1, die SMC-B in Slot 2 eingelegt. Es stehen 4 Slots zur Verfügung.

Jede Karte bekommt einen zufälligen Handle (z.B. `card-a3f8b2c1`), über den sie in SOAP-Responses referenziert wird.

### Neue Karten hinzufügen

Eine JSON-Datei mit dem Suffix `_demo.json` in `cards/` anlegen.

**eGK-Format:**

```json
{
  "card_type": "eGK",
  "generation": "2+",
  "iccsn": "80276883110000000099",
  "pin": "123456",
  "versicherter": {
    "vorname": "Erika",
    "nachname": "Musterfrau",
    "geburtsdatum": "1990-07-20",
    "geschlecht": "W",
    "strasse": "Beispielweg 7",
    "plz": "10115",
    "ort": "Berlin",
    "land": "D"
  },
  "versicherung": {
    "kvnr": "X110501500",
    "versicherten_id": "X110501500",
    "kostentraeger": "109519005",
    "kostentraeger_name": "IKK classic",
    "kostentraeger_laendercode": "D",
    "versicherungsschutz_beginn": "2021-01-01",
    "versicherungsschutz_ende": "2099-12-31",
    "versichertenart": "1",
    "besondere_personengruppe": "00",
    "dmp_kennzeichen": "00",
    "wop": "38"
  },
  "ef_pd": "<?xml ... Persönliche Versichertendaten als XML ...>",
  "ef_vd": "<?xml ... Allgemeine Versicherungsdaten als XML ...>"
}
```

**SMC-B-Format:**

```json
{
  "card_type": "SMC-B",
  "iccsn": "80276883120000000099",
  "pin": "123456",
  "institution": {
    "name": "Praxis Dr. Beispiel",
    "telematik_id": "3-SMC-B-Testkarte-883110000000099",
    "institution_typ": "Arztpraxis",
    "betriebsstaetten_nr": "987654321",
    "strasse": "Praxisweg 3",
    "plz": "10115",
    "ort": "Berlin",
    "land": "D"
  },
  "zertifikate": {
    "auth": {
      "algorithm": "ECC",
      "not_before": "2024-01-01T00:00:00",
      "not_after": "2029-12-31T23:59:59",
      "issuer": "gematik GmbH NOT-VALID (Demo)"
    },
    "sign": {
      "algorithm": "ECC",
      "not_before": "2024-01-01T00:00:00",
      "not_after": "2029-12-31T23:59:59",
      "issuer": "gematik GmbH NOT-VALID (Demo)"
    }
  }
}
```

Die `iccsn` muss eindeutig sein. Die Felder `ef_pd` und `ef_vd` sind optional und enthalten das rohe gematik-XML für ReadVSD-Responses.

## SICCT-Server

Der SICCT-Server emuliert ein eHealth-Kartenterminal über TCP.

| Eigenschaft | Wert |
|-------------|------|
| Port | 4742 (Standard für SICCT) |
| Protokoll | TCP, Binär: 2 Bytes Länge (Big-Endian) + Payload |
| Start | Automatisch beim Gateway-Start |

**Unterstützte Befehle:**

| Command | INS-Byte | Beschreibung |
|---------|----------|-------------|
| RESET CT | `0x11` | Terminal zurücksetzen, ATR zurückgeben |
| REQUEST ICC | `0x12` | Karte im Slot prüfen |
| GET STATUS | `0x13` | Terminal- oder Slot-Status |
| EJECT ICC | `0x15` | Karte auswerfen |
| OUTPUT | `0x17` | Text auf Display (wird geloggt) |
| INPUT | `0x18` | PIN-Eingabe simulieren |
| PERFORM VERIFICATION | `0x19` | PIN verifizieren |

Unbekannte Befehle werden als APDU an die virtuelle Smartcard weitergeleitet (SELECT, READ BINARY, VERIFY).

## Externe Dienste

### Titus (VSDM-Fachdienst)

URL: `https://kon-instanz1.titus.gematik.solutions`

Titus ist die gematik-Referenzumgebung für VSDM-Tests. Die Verbindung benötigt Netzwerkzugang zur gematik-Infrastruktur. Im Normalbetrieb nicht erreichbar — der lokale SOAP-Handler übernimmt.

### IdP-Server (Identity Provider)

URL: `http://localhost:8571`

Der gematik Referenz-IdP-Server läuft als Docker-Container:

```bash
docker compose up -d
```

Wird für die IdP-Challenge-Tests benötigt. Ohne Docker bleibt der IdP-Status im Dashboard rot.

### E-Rezept-Fachdienst (eRp)

URL: `https://erp-ref.zentral.erp.splitdns.ti-dienste.de`

Der eRp-Fachdienst benötigt echte TI-Zertifikate. Ohne diese werden Demo-Daten zurückgegeben (Mock-Rezepte mit Demo-IDs).

### ePA 2.0 (Elektronische Patientenakte)

Die ePA 2.0 läuft im Demo-Modus und ist immer verfügbar (kein externer Dienst nötig). Sie simuliert:

**Operationen:**

| Operation | Beschreibung |
|-----------|-------------|
| `GetRecordStatus` | Aktenstatus (Version, Dokumentanzahl, Größe, letztes Update) |
| `GetDocuments` | Dokumente abrufen mit Berechtigungsprüfung gegen SMC-B Telematik-ID |
| `UploadDocument` | Neues Dokument in die Akte hochladen |
| `GetPermissions` | Berechtigungsprofile anzeigen (3 Demo-Einrichtungen) |
| `GetMedicationPlan` | Medikationsplan mit PZN, Dosierung und Verordner |

**Demo-Daten:**

- 6 Dokumente (Arztbriefe, Laborbefunde, Medikationsplan, Impfausweis, psychiatrische Stellungnahme)
- 3 Berechtigungsprofile (IKK Kliniken, Hausarzt, Psychotherapie) mit unterschiedlichen Zugriffsrechten
- 3 Medikamente im Medikationsplan
- Vertraulichkeitsstufen: normal und sehr hoch
- Feingranulare Zugriffskontrolle: Praxis Weber sieht nur Psychiatrie-Dokumente

**Beispiel: ePA-Dokumente abrufen**

```bash
curl -X POST http://localhost:8500/api/test/epa-documents
```

## Docker

Die `docker-compose.yml` enthält den gematik IdP-Server:

```bash
# IdP-Server starten
docker compose up -d

# Status prüfen
docker compose ps

# Logs ansehen
docker compose logs idp-server

# Stoppen
docker compose down
```

## Einschränkungen

- **Kein echter Konnektor** — Emuliert nur die SOAP-Schnittstelle, keine echte Krypto
- **Demo-Zertifikate** — Alle Zertifikate und Signaturen sind ungültig
- **Keine echte PIN-Sicherheit** — PINs stehen im Klartext in den JSON-Dateien
- **Mock-Tokens** — IdP- und eRp-Tokens sind nicht echte Bearer-Tokens
- **Kein TLS** — Der Server läuft ohne HTTPS
- **Nur für lokale Tests** — Nicht ins Internet exponieren
