# Profile und Ausweis

Nach dieser Anleitung kennt die CLI Ihre Umgebung, Ihren Ausweis und den Schreibschutz — als Profil in einer Datei oder nur über Umgebungsvariablen — und `szenera whoami` zeigt, mit welchem Konto und welcher Organisation sie spricht.

> **Typ:** anleitung
> **Für wen:** Wer die CLI zum ersten Mal gegen eine Umgebung richtet oder mehrere Umgebungen nebeneinander bedient
> **Voraussetzung:** die gebaute CLI, die Basis-Adresse Ihrer Umgebung und ein API-Schlüssel `ak_…` (Regelweg) oder ein Konto mit Kennwort
> **Ort:** Kommandozeile

Ein Profil bündelt zwei Dinge: den Ausweis und die Zuordnung Dienst → Basis-Adresse. Alles, was ein Befehl über seine Gegenseite wissen muss, steht dort — und nirgends sonst. Jedes Profil gehört einer Organisation.

## Schritte

1. Legen Sie die Profil-Datei an: `~/.config/szenera/profile.json` (ein gesetztes `$XDG_CONFIG_HOME` wird beachtet). Die Form:

   ```json
   {
     "default": "staging",
     "profiles": {
       "staging": {
         "services": { "*": "https://<basis-adresse-ihrer-umgebung>" },
         "credential": { "kind": "api-key", "key": "ak_…" },
         "readOnly": false
       },
       "prod": {
         "services": { "*": "https://<basis-adresse-der-produktion>" },
         "credential": { "kind": "api-key", "key": "ak_…" },
         "readOnly": true
       }
     }
   }
   ```

2. Tragen Sie unter `services` die Basis-Adresse ein. Der Eintrag `*` gilt für alles, was keinen eigenen Eintrag hat, und genügt heute; die Adresse muss mit `http://` oder `https://` beginnen, ein Schrägstrich am Ende wird entfernt.

3. Wählen Sie den Ausweis unter `credential`. Die Art `api-key` mit einem Wert `ak_…` unter `key` ist der Regelweg; die beiden anderen Arten stehen unter „Optionen".

4. Entscheiden Sie über `readOnly`. `true` sperrt jeden verändernden Befehl, bevor ein einziges Netzpaket entsteht; für ein Produktions-Profil bleibt das stehen. **Fehlt die Angabe, gilt `true`.**

5. Setzen Sie `default` auf das Profil, das ohne `--profile=` gelten soll. Führt die Datei genau ein Profil, gilt dieses auch ohne Vorgabe; führt sie mehrere ohne Vorgabe, bricht die CLI ab und nennt die Namen.

6. Prüfen Sie das Profil:

   ```bash
   szenera whoami
   szenera whoami --profile=prod --json
   ```

## Optionen

### Ohne Datei: Umgebungsvariablen

Umgebungsvariablen liegen **über** der Datei — jede gesetzte Variable ersetzt den entsprechenden Wert des gewählten Profils. `SZENERA_BASE_URL` und `SZENERA_API_KEY` allein tragen ein vollständiges Profil, ganz ohne Datei; es heißt dann `environment` und ist nicht schreibgeschützt.

| Variable | Wirkung |
|---|---|
| `SZENERA_PROFILE` | Welches Profil der Datei gilt; `--profile=<name>` schlägt es |
| `SZENERA_BASE_URL` | Setzt den Eintrag `*` unter `services` |
| `SZENERA_API_KEY` | API-Schlüssel; ersetzt den Ausweis des Profils |
| `SZENERA_OUTPUT` | `json` oder `table`; `--json` und `--table` schlagen es |
| `SZENERA_PROFILE_FILE` | Pfad der Profil-Datei; schlägt jede Suche |

```bash
SZENERA_BASE_URL="https://<basis-adresse>" SZENERA_API_KEY="ak_…" szenera device list
```

### Wo die CLI sucht

Der erste Treffer gewinnt:

| Ort | Wann |
|---|---|
| `$SZENERA_PROFILE_FILE` | ausdrücklich benannt |
| `~/.config/szenera/profile.json` | sonst; `$XDG_CONFIG_HOME` wird beachtet |

### Ausweisarten

**`api-key`** — der Regelweg. Der Schlüssel reist als `Authorization: Bearer` an jedem Aufruf mit und läuft nicht nach einer Viertelstunde ab; die CLI braucht dafür weder Zwischenspeicher noch Auffrischung. Ein Wert ohne einen Präfix, den die API als Schlüssel kennt, wird abgewiesen, bevor ein Netzpaket entsteht — sobald ein Befehl den Ausweis braucht (Exit 2); `--help` und `health` laufen auch mit einem falschen Wert durch.

**`password`** — für den Menschen am Rechner. Das Profil trägt `email` und `password`, bei Zwei-Faktor zusätzlich `totpSecret` (Base32); den Einmalcode rechnet die CLI selbst. Das Zugriffsmerkmal liegt danach mit Rechten `0600` neben der Konfiguration (`.szenera-token-<profil>.json`), wird eine Minute vor Ablauf verworfen und vor jedem Aufruf erneuert, wenn es die nächste Rundreise nicht mehr trägt — auch mitten in einem Befehl, der Minuten wartet. Gehört das Konto zu mehreren Organisationen, bricht die Anmeldung ab, statt zu raten.

```json
{ "credential": { "kind": "password", "email": "…", "password": "…", "totpSecret": "…" } }
```

**`none`** — nur öffentliche Routen. `szenera health` läuft damit; jeder andere Befehl bricht mit dem Hinweis ab, dass das Profil keinen Ausweis trägt.

### Dienste je Domäne

Statt `*` darf ein Eintrag unter `services` eine Domäne der Plattform nennen (etwa `fleet` oder `composition`) und ihr eine eigene Adresse geben; `*` bleibt für den Rest. Ein Name, der keine Domäne ist, wird beim Lesen abgewiesen — ein Tippfehler fällt nicht still auf `*` zurück.

## Ergebnis prüfen

- `szenera whoami` zeigt Kennung, E-Mail, Name, **Organisation** und die Zahl der Rollen (Route `GET /v1/me`).
- Steht dort eine andere Organisation als erwartet, zeigt das Profil woandershin, als gedacht — nicht der Schlüssel ist falsch, sondern die Wahl.

## Wenn etwas nicht klappt

| Symptom | Bedeutung | Lösung |
|---|---|---|
| „Keine Konfiguration gefunden — die Kommandozeile weiß nicht, mit welcher Umgebung sie sprechen soll." (Exit 2) | Weder eine Datei an einem der beiden Orte noch `SZENERA_BASE_URL`. | Datei anlegen oder die beiden Variablen setzen. |
| „Unbekanntes Profil „…". … führt: dev, prod." (Exit 2) | `--profile=` oder `SZENERA_PROFILE` nennt einen Namen, den die Datei nicht kennt. | Einen der genannten Namen wählen. |
| „… ist im Profil „prod" gesperrt — das Profil ist schreibgeschützt." (Exit 2) | Ein verändernder Befehl trifft auf ein schreibgeschütztes Profil — oder auf eines ohne die Angabe. | `readOnly: false` setzen, wenn das Profil schreiben darf. |
| „… „audience" muss „tenant" sein." (Exit 2) | Die Datei führt ein Profil für den Plattformbetrieb. Das kennt `szenera` nicht. | Das Profil aus der Datei nehmen oder eine eigene Datei über `SZENERA_PROFILE_FILE` benennen. |
| „Kein API-Schlüssel: erwartet wird ein Wert mit dem Präfix …" (Exit 2) | Der Wert im Profil oder in `SZENERA_API_KEY` ist kein Schlüssel. | Den Klartext aus dem Portal übernehmen; siehe [Einen API-Schlüssel erzeugen](/de/getting-started/create-api-key). |
| „… braucht einen Ausweis, das Profil „…" trägt keinen." (Exit 1) | Das Profil hat `credential` nicht oder `kind: "none"`. | `SZENERA_API_KEY=ak_…` mitgeben oder `credential` im Profil setzen. |
| HTTP 401 mit Exit 3 | Der Schlüssel gilt nicht: widerrufen, abgelaufen, oder das Profil zeigt auf eine andere Umgebung als der Schlüssel. | `szenera whoami --profile=<name>` je Profil prüfen; siehe [Ausgabe als JSON und Exit-Codes](/de/cli/output-and-exit-codes). |
| „… gehört zu mehreren Organisationen …" | Kennwort-Anmeldung mit einem Konto in mehreren Organisationen. | Einen API-Schlüssel der gewünschten Organisation verwenden. |

## Weiterführendes

- [Die CLI beziehen](/de/cli/get-cli)
- [Ausgabe als JSON und Exit-Codes](/de/cli/output-and-exit-codes)
- [Einen API-Schlüssel erzeugen](/de/getting-started/create-api-key)
