Doku-Vollausbau: 62 Seiten (Projekt/Admin/Anwender/Referenz), Hook-Referenz mit Signaturen, Corporate-Screenshots, Coverage-Inventar
Deploy tibi-docs / build-and-deploy (push) Failing after 38s

- Einstieg: Schnellstart + Neues Projekt aus Starter-Skill, Was-ist-Tibi mit Backend/Website-Trennung
- Projekt: Sammlungen, Felder, Abfragen, Rechte, Hooks, Dateien, i18n, Suche, SSR, Pagebuilder, Jobs, Audit, Deploy, LLM, MCP
- Hook-Referenz: 66 Symbole mit Signatur + Beispiel + Fehlerfall (5 Kapitel)
- Admin: Ansichten, Editor, Medien, Exporte, Aktionen, Rechte, KI, Setup, Customizing
- Anwender: 11 Anleitungen im professionellen Du-Ton, 30 Corporate-Screenshots
- Referenz: Schemas, Token-Köpfe, Fehlerbilder, Shortcuts, OpenAPI-Platzhalter
- ADR-0001 bis 0003, Coverage-Skript (282 Items) + Map, Plan-Dateien
This commit is contained in:
apairon committed 2026-10-16 22:49:07 +00:00
1 parent acb1d32355
commit 1897bb50d9
101 files changed
+8980 -68

No files matched your search

+89
View File
@@ -0,0 +1,89 @@
---
title: 'Betrieb und Beobachtung'
description: 'Logs, Metriken, Suche neu aufbauen, Jobs und Audit aus Betreiber-Sicht.'
---
import { Aside, Tabs, TabItem, Steps, Card, CardGrid, Badge, FileTree } from '@astrojs/starlight/components';
Du betreibst den **tibi-server** als Container. Diese Seite zeigt Startprofile, Gesundheit, Suche, Jobs und typische Störungen. Details zur Datei stehen unter [Server-Konfiguration](/server/konfiguration/).
## Startprofile
Der Starter (`docker-compose-local.yml`) kennt zwei Profile:
<Badge text="tibi" variant="tip" /> <Badge text="tibi-dev" variant="note" />
| Profil | Service | Wofür |
|---|---|---|
| `tibi` | `tibiserver` (Image `tibi-server:nova`) | Normalbetrieb: fertiges Image, Projekt unter `./` als `/data` gemountet |
| `tibi-dev` | `tibiserver-dev` (Build aus `tibi-server/Dockerfile.air`) | Entwicklung am Server: Live-Reload, Server-Code gemountet |
Dazu laufen `mongo` (MongoDB 7) und `maildev` (Mails auf `maildev:25`, Web-UI zum Lesen).
```bash title="Starten und Logs ansehen"
docker compose --profile tibi up -d
docker compose logs -f tibiserver
```
Beim Start loggt der Server die wirksame Konfiguration (`using following server config:`). Prüfe dort zuerst `DB.Dial`, `DB.Prefix` und `API.Port`.
## Gesundheit und Metriken
| Signal | Adresse | Was du siehst |
|---|---|---|
| Version | `GET /api/v1/version` | `{"version":"…"}` — der Server lebt und die Config lädt |
| Prometheus | `GET /metrics` | u. a. `tibi_request_duration_seconds` je Methode, Status, Namespace, Collection |
| Sentry | nur bei gesetzter `sentry.dsn` | Fehler + Traces mit Client-IP und Transaktionsname |
<Steps>
1. `curl http://localhost:8080/api/v1/version` — kommt JSON, läuft der Router.
2. `curl http://localhost:8080/metrics` — kommen `tibi_*`-Zeilen, läuft die Instrumentierung.
3. Antwortzeiten steigen? In `/metrics` nach `status`- und `col`-Labels filtern.
</Steps>
<Aside type="note" title="Audit">
`audit.enabled: true` schreibt System-Änderungen (User, Projekt, Login, Shutdown) mit TTL weg. Vorgabe sind 30 Tage (`720h` über `audit.defaultTTL`). Lies sie über `GET /api/v1/audit` (`audit.read`-Recht nötig).
</Aside>
## Suche und Reload
Die Volltextsuche läuft pro Projekt in einem Worker. Nach Config-Änderungen musst du neu laden:
| Endpunkt | Wirkung |
|---|---|
| `POST /api/v1/_/:project/_/admin/reload` | Lädt Projekt-Config neu (Recht `project.reload`) |
| `POST /api/v1/_/:project/_/admin/regenerate-search` | Baut Suchindex neu auf (`project.regenerate-search`) |
| `GET /api/v1/_/:project/_/admin/search-worker/status` | Status des Such-Workers |
| `GET /api/v1/_/:project/_/admin/embedding/status` | Status der Embedding-Provider |
```bash title="Nach Config-Änderung: Reload plus Suchindex neu aufbauen"
curl -X POST http://localhost:8080/api/v1/_/meinprojekt/_/admin/reload \
-H "X-Admin-Token: $TOKEN"
curl -X POST http://localhost:8080/api/v1/_/meinprojekt/_/admin/regenerate-search \
-H "X-Admin-Token: $TOKEN"
```
Backups und Snapshots meldet der Server per Fortschritts-Stream (SSE, `text/event-stream`). Bricht ein Download ab, hole zuerst die Analyse (`backup/analyze-download`), dann die Datei neu.
## Jobs
Jobs sind geplante Skripte je Projekt (Cron in der Projekt-`config.yml`, gleiche goja-Laufzeit wie Hooks):
- Sie laufen im `JOB_CONTEXT` — ohne HTTP-Request, mit fast allen Hook-Paketen.
- Sie laufen unter der Projekt-UID (suexec-Isolation, siehe [Sicherheit](/server/sicherheit/)).
- Schlägt ein Job fehl, steht die Ursache im Server-Log; Quotas und Nutzung landen in der LLM-Nutzungsablage.
## Störungen
| Bild | Ursache (häufig) | Maßnahme |
|---|---|---|
| Start-Panic `invalid number in env API_PORT` | Port fehlt oder `<= 0` | `API_PORT` setzen, siehe [Server-Konfiguration](/server/konfiguration/) |
| `version` antwortet nicht | Container down, falscher Port | `docker compose ps`, Logs prüfen |
| Login wird immer langsamer | Ratelimit-Backoff nach Fehlversuchen | Warten (Retry-After), Zugangsdaten prüfen |
| Suche findet nichts Neues | Worker hängt oder Index alt | Worker-Status abfragen, `regenerate-search` |
| 413 bei Upload | Body-Limit erreicht (Server → Projekt → Collection) | `API_UPLOAD_MAX_BODY_SIZE` bzw. Collection-Limit erhöhen |
| Leere Seite trotz Daten | CORS blockt den Browser | Origins in der Collection-Config prüfen |
Begriffe wie Collection, Hook oder Namespace klärt [Begriffe](/einstieg/begriffe/). Zum Einrichten siehe [Schnellstart](/einstieg/schnellstart/).
Verifiziert am `68b42785` 2026-10-15 (tibi-server); Compose-Profile am `e3f92ebf` 2026-10-14 (tibi-svelte-starter).
+140
View File
@@ -0,0 +1,140 @@
---
title: 'Server-Konfiguration'
description: 'config.yml und Env-Overrides des tibi-servers selbst (Betreiber-Sicht).'
---
import { Aside, Tabs, TabItem, Steps, Card, CardGrid, Badge, FileTree } from '@astrojs/starlight/components';
Du konfigurierst den **tibi-server** über eine `config.yml` plus Umgebungsvariablen. Env schlägt Datei. Die Wahrheit steht in `internal/config/server.go` (Struct-Tags).
```text title="Config-Vorrang"
config.yml (Datei) < Umgebungsvariable (gewinnt immer)
\ /
v v
Server.Server (Speicher)
```
## Datei und Env-Regeln
- Fehlt die Datei, startet der Server mit Notwerten: Port `8080`, Prefix `tibi`, Stacktraces an.
- `API_PORT` oder `PORT` sind Pflicht: Port `<= 0` beendet den Start per Panic.
- Namen mit Bindestrich werden in Env zu Unterstrich + Großschrift: `bge-m3` → `EMBEDDING_BGE-M3_*`.
- Listen in Env sind Komma-getrennt: `LLM_PROVIDERS=openai,lokal`.
## Die Bereiche im Überblick
| Bereich (`config.yml`) | Wichtigste Schlüssel | Env-Override |
|---|---|---|
| `db` | `dial`, `prefix`, `logging` | `DB_DIAL` (Fallback `MGO_DIAL`), `DB_PREFIX`, `DB_LOGGING` |
| `api` | `port`, `jwtSecret`, `upload.maxBodySize`, Token-Lifetimes | `API_PORT`/`PORT`, `API_JWTSECRET`, `API_UPLOAD_MAX_BODY_SIZE`, `API_ACCESS_TOKEN_LIFETIME`, `API_REFRESH_TOKEN_LIFETIME`, `API_SECURE_COOKIES` |
| `mail` | `host`, `username`, `password` | `MAIL_HOST` |
| `security` | `allowAbsolutePaths`, `allowUpperPaths` | `SECURITY_ALLOWABSOLUTEPATHS`, `SECURITY_ALLOWUPPERPATHS` |
| `response.error` | `stack`, `message` | `RESPONSE_ERROR_STACK`, `RESPONSE_ERROR_MESSAGE` |
| `audit` | `enabled`, `defaultTTL`, `defaultLimit`, `maxLimit` | `AUDIT_ENABLED`, `AUDIT_DEFAULT_TTL`, `AUDIT_DEFAULT_LIMIT`, `AUDIT_MAX_LIMIT` |
| `ratelimit` | `enabled`, `loginInitialDelay`, `loginMaxDelay`, `loginResetAfter` | `RATELIMIT_*` (gleiche Namen) |
| `hook` | `cache.*`, `ratelimit.*` | `HOOK_CACHE_*`, `HOOK_RATELIMIT_*` |
| `mcp` | `enabled`, `route`, `maxResultItems`, `allowAdminActions` | `MCP_ENABLED`, `MCP_ROUTE`, `MCP_MAX_RESULT_ITEMS`, `MCP_ALLOW_ADMIN_ACTIONS` |
| `sentry` | `dsn`, `environment`, `serverName`, `enableTracing`, `debug` | keine — nur Datei |
| `cors` | `allowOrigins`, `allowCredentials`, … | keine — wirksam ist die Projekt-/Collection-Ebene (siehe [Sicherheit](/server/sicherheit/)) |
| `llm` / `embedding` | Provider-Listen | dynamisch, siehe unten |
<Aside type="caution" title="README lügt an zwei Stellen">
Das README-Beispiel ist unvollständig und nennt <del>Go 1.23</del> <ins>go 1.25.0</ins> (Toolchain `go1.25.7`) laut `go.mod`. Verlasse dich nur auf die Struct-Tags in `server.go`.
</Aside>
## Datenbank, API, Mail
<Tabs>
<TabItem label="Minimal-Beispiel">
```yaml title="config.yml"
db:
dial: mongodb://mongo
prefix: meinprojekt
api:
port: 8080
jwtSecret: mindestens-32-zufallszeichen
mail:
host: maildev:25
```
</TabItem>
<TabItem label="Lokaler Dial (Starter)">
```yaml title="docker-compose-local.yml (Service tibiserver)"
environment:
DB_DIAL: mongodb://mongo
DB_PREFIX: ${TIBI_PREFIX}
MAIL_HOST: maildev:25
SECURITY_ALLOWABSOLUTEPATHS: "true"
SECURITY_ALLOWUPPERPATHS: "true"
RESPONSE_ERROR_STACK: "true"
```
Der Starter nutzt `mongodb://mongo` (Compose-Netz). Lokal ohne Compose heißt der Dial `mongodb://localhost:27017`. Der Prefix trennt Projekte in einer MongoDB.
</TabItem>
</Tabs>
Defaults, die du kennen musst:
- `secureCookies`: Standard `true`. Nur für reines HTTP-Lokalsetup auf `false` setzen.
- `accessTokenLifetime`: Standard `60m`. `refreshTokenLifetime`: Standard `10h`. Format ist Go-Duration (`30m`, `24h`).
- Ungültige Duration fällt still auf den Default zurück (Log-Warnung).
## LLM und Embedding per Env
Provider musst du nicht in die Datei schreiben. Diese Muster gelten:
```bash title="LLM-Provider anmelden"
LLM_PROVIDERS=openai,lokal-llm
LLM_OPENAI_APIKEY=sk-...
LLM_OPENAI_TYPE=openai # Vorgabe, wenn leer
LLM_OPENAI_BASEURL=https://api.openai.com/v1 # Vorgabe für Typ openai
LLM_OPENAI_DEFAULTMODEL=gpt-4o
LLM_OPENAI_MODELS=gpt-4o,gpt-4o-mini
```
```bash title="Embedding-Provider anmelden (Starter-Beispiel)"
EMBEDDING_PROVIDERS=bge-m3
EMBEDDING_BGE-M3_TYPE=native
EMBEDDING_BGE-M3_MODELPATH=/models/bge-m3
EMBEDDING_BGE-M3_DIMENSIONS=1024
EMBEDDING_BGE-M3_DOCUMENTPREFIX="search_document: "
EMBEDDING_BGE-M3_QUERYPREFIX="search_query: "
```
Gruppen gehen über `EMBEDDING_GROUPS=main` plus `EMBEDDING_GROUP_MAIN_MEMBERS=...`, `..._POLICY=...`, `..._TIMEOUT_TOTAL=...`.
## Admin-Tokens
Server-Admin-Tokens stehen unter `api.adminTokens`. Jedes Token hat `token`, `label` und `permissions`:
```yaml title="config.yml"
api:
adminTokens:
- token: ersetze-mich-durch-zufall
label: backup-job
permissions: ["project.backup", "project.reload"]
```
- Syntax: `domain.action` (`project.read`, `user.create`, `server.shutdown`).
- Kurzform: `project` meint `project.*`. `*` matcht genau ein Segment (`namespace.*.articles.read`).
- Gültige Domänen: `user`, `project` (plus `reload`, `backup`, `regenerate-search`, `snapshot`), `team`, `org`, `audit.read`, `llm.chat`, `namespace…`.
- Header: `X-Admin-Token: …` oder `Authorization: Bearer …`.
## Abnahme über den Version-Endpunkt
<Steps>
1. Server starten und warten, bis das Config-Dump im Log steht.
2. Version abfragen — antwortet sie, stimmen Port und Prefix:
```bash title="Version prüfen"
curl http://localhost:8080/api/v1/version
# {"version":"0.0.0"}
```
3. Bei Fehlern zuerst `DB_DIAL`, `DB_PREFIX` und `API_PORT` prüfen (Tabelle oben).
</Steps>
Weiter: [Betrieb und Beobachtung](/server/betrieb/) zeigt Profile und Metriken. [Sicherheit](/server/sicherheit/) erklärt Token-Arten und Ratelimit.
Verifiziert am `68b42785` 2026-10-15 (tibi-server); Starter-Compose am `e3f92ebf` 2026-10-14 (tibi-svelte-starter); Go-Version aus `go.mod`.
+104
View File
@@ -0,0 +1,104 @@
---
title: 'Schnittstellen im Überblick'
description: 'REST, SSE, MCP, OpenAPI: was wofür gilt und wo die Referenz liegt.'
---
import { Aside, Tabs, TabItem, Steps, Card, CardGrid, Badge, FileTree } from '@astrojs/starlight/components';
Der **tibi-server** spricht vier Sprachen: REST, SSE-Streams, MCP und OpenAPI. Alle hängen unter `/api/v1` (außer `/metrics`). Quelle: `internal/controller/setup.go`.
```text title="API-Baum im Überblick"
/api/v1
├── System: /login /token/_scopes /llm/* /audit /admin/* /version /mcp
├── Projekt: /_/:project/:collection … /_/:project/_actions/:action
│ /_/:project/_/assets/… /_/:project/_/admin/…
└── Schema: /_openapi/:project
/metrics (Prometheus, außerhalb)
```
## REST: System gegen Collection
<Tabs>
<TabItem label="System-Endpunkte">
| Methode | Pfad | Wofür |
|---|---|---|
| `GET` | `/api/v1/version` | Lebenszeichen (`{"version":"…"}`) |
| `POST` | `/api/v1/login`, `/api/v1/login/impersonate` | JWT holen / als Admin schlüpfen |
| `GET` | `/api/v1/token/_scopes` | Gültige PAT-Scopes auflisten |
| `POST` / `GET` | `/api/v1/llm/chat`, `/api/v1/llm/providers` | Chat (ohne Secrets) / Provider-Namen |
| `GET` | `/api/v1/audit` | Audit-Logs (`audit.read`) |
| `GET` / `POST` | `/api/v1/admin/embedding/status`, `/api/v1/admin/shutdown` | Embedding-Status / Stop (`server.shutdown`) |
</TabItem>
<TabItem label="Collection-Endpunkte">
| Methode | Pfad | Wofür |
|---|---|---|
| `GET` / `POST` | `/_/:project/:collection` | Suchen / anlegen |
| `GET` | `/_/:project/:collection/_count`, `/_facet`, `/_queue` | Zählen / Facetten / Warteschlange |
| `GET` / `PUT` / `DELETE` | `/_/:project/:collection/:id` | Lesen / ersetzen / löschen |
| `PUT` / `DELETE` | `/_/:project/:collection` (ohne ID) | Bulk-Update / Bulk-Delete |
| `GET` | `/_/:project/:collection/:id/:field`, `…/:field/*path` | Einzelnes Feld / Datei |
| `GET` / `POST` | `/_/:project/_actions/:action` | Hook-Aktion ohne Collection |
| `GET` | `/_/:project/_/assets/:name/*path` | Statische Assets |
Trick für lange Filter: `POST` mit Header `X-HTTP-Method-Override: GET` — der Body wird zur Query.
</TabItem>
<TabItem label="Projekt-Admin">
| Methode | Pfad | Recht |
|---|---|---|
| `POST` | `/_/:project/_/admin/reload` | `project.reload` |
| `POST` / `GET` | `/_/:project/_/admin/regenerate-search`, `…/search-worker/status` | `project.regenerate-search` |
| `GET` | `/_/:project/_/admin/embedding/status` | Projekt-Admin |
| `GET` / `POST` / `DELETE` | `/_/:project/_/admin/backup…` | `project.backup` |
| `GET` / `POST` / `DELETE` | `/_/:project/_/admin/snapshots…` | `project.snapshot` |
</TabItem>
</Tabs>
Alle Antworten sind gzip-komprimiert, Body-Limits kaskadieren (Server → Projekt → Collection). Erstellen meldet `201`, Löschen `204` — außer das Projekt will Legacy-Codes.
## SSE (Echtzeit und Fortschritt)
- Der Realtime-Hub ist ein In-Memory-Pub/Sub **je Projekt**: benannte Kanäle, fester Ringpuffer (Standard 256), Nachhol-Optionen (`LastN`, `MaxAge`, TTL).
- Volle Kanäle werfen wahlweise Alt oder Neu weg — langsame Leser blockieren nie den Server.
- **Kein fertiger Abo-Endpunkt:** Der Server liefert keine HTTP-Route für Collection-Abos. Du erreichst den Hub nur über Hooks (`channel.send` / `channel.subscribe`) — typisch als eigene Action (`/_/:project/_actions/:action`), die du selbst als SSE auslieferst.
- `text/event-stream` liefert der Server fertig nur an zwei Stellen: `POST /api/v1/llm/chat` (Chat-Streaming) und Backup-Analyse-Download (`.../admin/backup/analyze-download`). Snapshot-Streaming ist dagegen Datei-Download mit RAM-Begrenzung, kein SSE.
- Backup- und Snapshot-Läufe melden Fortschritt als Event-Stream. Bricht der Stream ab, war es das Netzwerk — der Lauf selbst geht weiter.
## MCP (KI-Werkzeuge)
| Fakt | Wert |
|---|---|
| Transport | Streamable-HTTP, JSON-RPC 2.0 |
| Route | fest `POST` + `GET /api/v1/mcp` — ein gesetztes `mcp.route`/`MCP_ROUTE` wird ignoriert (Routing hart in `setup.go`) |
| Auth | nur PAT via `X-Auth-Token` — kein JWT, kein Admin-Token |
| Rechte | jede Prüfung nutzt die gleichen Gates wie REST (nichts kopiert) |
| Ergebnis-Deckel | `mcp.maxResultItems` (Standard 100) |
| Admin-Werkzeuge | nur mit `mcp.allowAdminActions: true`, weiter pro Scope begrenzt |
```bash title="MCP-Tools auflisten (describe)"
curl -X POST http://localhost:8080/api/v1/mcp \
-H "X-Auth-Token: tibi_pat_..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```
## OpenAPI-Generator
`GET /api/v1/_openapi/:project` erzeugt die Spezifikation **deines** Projekts frisch aus Config und Collections. Nutze sie für Client-Generierung und als Klick-Referenz. Die Version oben (`/api/v1/version`) sagt dir, ob Server und Spec zusammenpassen.
## Welche Referenz wofür
| Frage | Antwort liegt in |
|---|---|
| Wie heißt Config-Schlüssel X? | [Server-Konfiguration](/server/konfiguration/) |
| Wer darf Endpunkt Y? | [Sicherheit](/server/sicherheit/) (Tokens, Scopes) |
| Läuft der Server gesund? | [Betrieb und Beobachtung](/server/betrieb/) (Version, Metriken) |
| Wie frage ich Daten ab? | Projekt-Seiten ab [Begriffe](/einstieg/begriffe/) |
| Was ist Tibi überhaupt? | [Was ist Tibi?](/einstieg/was-ist-tibi/) |
Verifiziert am `68b42785` 2026-10-15 (tibi-server).
+82
View File
@@ -0,0 +1,82 @@
---
title: 'Sicherheit'
description: 'Tokens, CORS-Kaskade, Ratelimit, Pfad-Regeln, Isolation als Betreiber-Überblick.'
---
import { Aside, Tabs, TabItem, Steps, Card, CardGrid, Badge, FileTree } from '@astrojs/starlight/components';
Du sicherst den **tibi-server** auf vier Ebenen: Tokens, CORS, Ratelimit und Dateipfade plus Prozess-Isolation. Quelle ist der Code (`internal/config`, `internal/ratelimit`, `internal/suexec`, `internal/controller/setup.go`).
## Token-Arten
<Badge text="X-Admin-Token" variant="danger" /> <Badge text="X-Auth-Token" variant="tip" /> <Badge text="Token" variant="note" /> <Badge text="Bearer" variant="caution" />
| Art | Header | Wofür | Scope-Syntax |
|---|---|---|---|
| Server-Admin-Token | `X-Admin-Token` oder `Authorization: Bearer` | Betrieb: Reload, Backup, Snapshots, Shutdown (`server.shutdown` nur für Stop) | `domain.action`, Kurzform (`project` = `project.*`), `*` je Segment |
| Benutzer-JWT | `X-Auth-Token` | Anmeldung per `/api/v1/login`; Lebensdauer via `API_ACCESS_TOKEN_LIFETIME` (Standard `60m`) | Rollen + Collection-Rechte |
| Personal Access Token (PAT) | `X-Auth-Token` (`tibi_pat_…`) | Dauerhafte Maschinen-Tokens, immer aktiv | gleiche Syntax wie Admin-Tokens; es gilt **Token-Recht UND Besitzer-Recht** |
| MCP | `X-Auth-Token` (nur PAT) | KI-Werkzeugzugriff über `/api/v1/mcp` | PAT-Scopes, Admin-Aktionen nur mit `mcp.allowAdminActions: true` |
Gültige Domänen: `user`, `project` (`read/create/update/delete`, `reload`, `backup`, `regenerate-search`, `snapshot`), `team`, `org`, `audit.read`, `llm.chat`, `namespace.<ns>.<collection>.<aktion>`.
```text title="Scope-Abgleich (Beispiel)"
Anfrage-Recht: namespace.shop.artikel.read
Token-Scope: namespace.shop → passt (Kurzform)
Token-Scope: namespace.*.artikel.read → passt (Wildcard)
Besitzer darf es nicht → trotzdem verboten (UND-Regel)
```
<Aside type="caution" title="Entfernt: TOKENS_ENABLED">
Ein Flag `TOKENS_ENABLED` gibt es nicht mehr. PATs sind Kernfunktion und immer an. Wer alte Compose-Dateien mit diesem Flag findet, löscht es ersatzlos.
</Aside>
## CORS-Kaskade
Jeder Request bekommt genau eine CORS-Config — vom Spezifischen zum Allgemeinen:
```text title="CORS-Kaskade"
/_actions/<name> → /<collection> → / → "" → keine (Browser blockt)
```
- Die Kaskade steht pro Projekt (`CORSMap`), nicht global. Der `cors:`-Abschnitt der Server-Config ist die **Basis**, Projekt- und Collection-Werte mergen feldweise dazu (`merge: true` hängt an, `merge: false` ersetzt). Globales CORS ist auskommentiert — ohne Projekt-Kontext greift gar kein CORS.
- Action-Endpunkte (`/_actions/…`) haben eigene Einträge — prüfe sie separat.
- Preflight ohne echte Route antwortet `404` (kein offenes `OPTIONS`-Loch).
## Ratelimit (Login)
Der Login-Limiter bremst Fehlversuche mit exponentiellem Backoff — je IP **und** je Benutzername:
| Schlüssel | Standard | Env |
|---|---|---|
| Erste Verzögerung | `1s` | `RATELIMIT_LOGIN_INITIAL_DELAY` |
| Maximale Verzögerung | `60s` | `RATELIMIT_LOGIN_MAX_DELAY` |
| Zähler-Reset nach Ruhe | `15m` | `RATELIMIT_LOGIN_RESET_AFTER` |
| Ganz abschalten | an (`true`) | `RATELIMIT_ENABLED=false` (nur Notfall) |
Erfolg setzt beide Zähler zurück. Gebremste Versuche antworten mit **429** plus `Retry-After`-Header (Sekunden) — warte sie ab statt zu hämmern. Das Limit gilt **nur für Login**, nicht global.
## Pfade und suexec-Isolation
| Schalter | Wirkung |
|---|---|
| `security.allowAbsolutePaths` (`SECURITY_ALLOWABSOLUTEPATHS`) | Absolute Dateipfade erlauben — sonst verboten |
| `security.allowUpperPaths` (`SECURITY_ALLOWUPPERPATHS`) | `..`-Pfade erlauben — sonst verboten |
| suexec (kein Schalter) | Hooks und Jobs laufen unter der Projekt-UID/GID in eigenen Thread-Pools |
Der Starter setzt beide Pfad-Schalter lokal auf `"true"`. In Produktion lässt du sie aus, außer du weißt genau warum.
## Checkliste für den Go-Live
<Steps>
1. `jwtSecret` gesetzt (lang, zufällig) und `secureCookies: true` (HTTPS).
2. Admin-Tokens minimal vergeben: ein Token, ein Zweck, enge Scopes.
3. `RESPONSE_ERROR_STACK` aus — keine Stacktraces an Clients.
4. Pfad-Schalter aus, außer nötig. Ratelimit an.
5. `sentry.dsn` gesetzt, `/metrics` nur intern erreichbar.
6. CORS je Collection geprüft — keine `*`-Origins mit Credentials.
</Steps>
Config-Schlüssel stehen unter [Server-Konfiguration](/server/konfiguration/). Laufende Kontrolle unter [Betrieb und Beobachtung](/server/betrieb/).
Verifiziert am `68b42785` 2026-10-15 (tibi-server).
+40
View File
@@ -0,0 +1,40 @@
---
title: Server-Übersicht
description: Wie der Tibi-Server aufgebaut ist und wo welche Referenzseite hilft.
---
import { Card, CardGrid } from '@astrojs/starlight/components';
> **Handseite.** Wird vom Sync nie überschrieben (`keep`). Stand wird am Code verifiziert, nicht aus alten Docs übernommen.
**Tibi-server** ist das Go-Backend (MongoDB, Gin, goja-Hooks, SSE, LLM, Jobs, Audit). Details stehen in den synchronisierten Referenzseiten daneben — diese Seite ordnet nur.
:::note title="Projekt-Entwickler nutzen, nicht weiterentwickeln"
Als Projekt-Entwickler entwickelst du den Server nicht weiter. Du **nutzt** ihn: `api/config.yml` plus `api/collections/*.yml` und `api/hooks/*.js` in deinem geklonten Starter. Go-Code fasst du nicht an.
:::
## Wo finde ich was?
<CardGrid stagger>
<Card title="Server-Konfiguration">
`config.yml`, Env-Overrides, Admin-Tokens (am Code verifiziert, inkl. Go-Version und Legacy-Default). [Lesen](/server/konfiguration/).
</Card>
<Card title="Betrieb und Beobachtung">
Profile, Version/Metriken, Reload, Jobs, Störungen. [Lesen](/server/betrieb/).
</Card>
<Card title="Sicherheit">
Token-Arten, CORS-Kaskade, Login-Ratelimit (429), Pfad-Schalter, suexec. [Lesen](/server/sicherheit/).
</Card>
<Card title="Schnittstellen">
REST (System vs. Collection), SSE, MCP (`/api/v1/mcp` fest), OpenAPI-Generator. [Lesen](/server/schnittstellen/).
</Card>
<Card title="Projekt-Sicht">
[Sammlungen](/projekt/sammlungen-anlegen/), [Hooks](/projekt/hooks-schreiben/), [Lesen und suchen](/projekt/abfragen-lesen/), [Rechte und Tokens](/projekt/rechte-tokens/).
</Card>
</CardGrid>
Verifiziert am 68b42785 2026-10-15 (tibi-server).
## Nächster Schritt
- Neues Projekt? Siehe [Neues Projekt aufsetzen](/einstieg/neues-projekt/).