Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/de/cloud/data-residency.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Die Default-Region für neue Cloud-Orgs ist die Schweiz. Die Region nach der Anm

## Ein durchgespieltes Beispiel — ein Chat-Roundtrip

Der User in Zürich öffnet Chat und sendet „fass den letzten Kundenanruf zusammen". Die Anfrage trifft Tales Edge in der gewählten Region, landet auf `tale-platform`, ruft in `tale-convex` (das Backend), liest Wissen aus der Datenbank des Wissens-Korpus, sobald das Wissens-Tool des Agents danach fragt, und emittiert einen ausgehenden Anruf an den Provider hinter dem Modell, das die sendende Person gewählt hat. Der Wissens-Abruf läuft im Convex-Backend — es fragt die Korpus-Datenbank direkt ab, ohne separaten Retrieval-Dienst im Pfad. Der Modell-Provider gibt Tokens zurück; Tale streamt sie auf demselben Pfad zurück. Die Antwort und die Zitate landen in der operativen Datenbank, der Korpus bleibt in der Wissensdatenbank, und beide werden innerhalb der Region repliziert.
Der User in Zürich öffnet Chat und sendet „fass den letzten Kundenanruf zusammen". Die Anfrage trifft Tales Edge in der gewählten Region, die die Seite aus der Web-Schicht ausliefert und die Nachricht selbst an das Anwendungs-Backend routet. Das Backend liest Wissen aus der Korpus-Datenbank, sobald das Wissens-Tool des Agents danach fragt, und schickt einen ausgehenden Aufruf an den Provider hinter dem Modell, das die sendende Person gewählt hat. Der Wissens-Abruf läuft im selben Backend-Prozesser fragt die Korpus-Datenbank direkt ab, ohne separaten Retrieval-Dienst im Pfad. Der Modell-Provider gibt Tokens zurück; das Backend streamt sie an den Browser. Die Antwort und die Zitate landen in der operativen Datenbank, der Korpus bleibt in der Wissensdatenbank, jede Datei, die der Turn erzeugt hat, landet im Objektspeicher der Region, und alle drei werden innerhalb der Region repliziert.

Zwei Pfeile überqueren in diesem Trip die regionale Grenze: der Anruf an den Modell-Provider (immer extern) und jeder Sub-Prozessor, den die Tools des Agents ausgelöst haben (Web-Fetch, OneDrive-Lese, MCP-Server in einer anderen Region). Alles andere bleibt in der Region.

Expand Down
2 changes: 1 addition & 1 deletion docs/de/develop/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ curl -sS "https://your-host.example.com/api/v1/tasks/<taskId>" \
# → 200 { "task": { "id": "<taskId>", "title": "...", "status": "in_progress", "externalId": "case-991", "labels": [], ... } }
```

Und hol die Ergebnisse. Was die Automatisierung zurückgemeldet hat, steht in der Diskussion der Aufgabe; was sie abgelegt hat, liegt als Dateien im Quartalsordner — beides liest du durch denselben Zugang. Der Content-Endpoint streamt einen Convex-Blob direkt; bei einer Organisation mit eigenem Objektspeicher antwortet er mit **302** auf eine kurzlebige präsignierte URL, folge also Redirects:
Und hol die Ergebnisse. Was die Automatisierung zurückgemeldet hat, steht in der Diskussion der Aufgabe; was sie abgelegt hat, liegt als Dateien im Quartalsordner — beides liest du durch denselben Zugang. Der Content-Endpoint streamt selbst keine Bytes: Jede Datei liegt im Objektspeicher, er antwortet also immer mit **302** auf eine kurzlebige präsignierte URL. Folge Redirects und behandle diese URL wie ein Credential — sie gibt die Bytes an jeden heraus, der sie hat, bis sie abläuft:

```bash
curl -sS "https://your-host.example.com/api/v1/tasks/<taskId>/comments" \
Expand Down
8 changes: 5 additions & 3 deletions docs/de/develop/status-page.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ Der RSS-Feed trägt jeden Status-Wechsel — offen, Update, gelöst — für jed

| Service | Was er abdeckt | Wann er rot wird |
| ---------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| `platform` | Die TanStack-Start-+-Convex-Anwendung — Agents, Workflows, Connectors, UI. | UI nicht erreichbar; API gibt 5xx; Auth defekt. |
| `platform` | Der TanStack-Start-UI-Server und das Node-Backend dahinter — Agents, Workflows, Connectors, UI. | UI nicht erreichbar; API gibt 5xx; Auth defekt. |
| `rag` | Der Python-FastAPI-Dokumentdienst — Indexierung, Retrieval. | Dokument-Uploads stocken; Retrieval ist leer. |
| `crawler` | Der Crawl4AI-Web-Extraktionsdienst — verwendet von Document-Ingest und Tavily-Fallback. | Web-gezogene Dokumente scheitern; Deep Research stockt. |
| `proxy` | Der Caddy-Edge — TLS-Terminierung, HTTP-Routing. | Gesamter Tale-Cloud-Verkehr betroffen. |
| `db` | TimescaleDB — dauerhafter Zustand für die Convex-Schicht und Plattform-Metadaten. | Schreiben abgelehnt; die platform-Zeile wird ebenfalls rot. |
| `db` | Postgres — dauerhafter Anwendungszustand und die Job-Warteschlange. | Schreiben abgelehnt; die platform-Zeile wird ebenfalls rot. |

Jede Zeile trägt die letzten 90 Tage Uptime als Sparkline. Ein Incident liest sich als farbiges Band auf der Zeile; ein Klick aufs Band öffnet den Verlauf — erstes Update, Folge-Updates, Auflösung, Post-Mortem, wenn eines ansteht.

Expand All @@ -37,7 +37,9 @@ Die Seite gehört der Bereitschafts-Rotation. Updates werden vom Engineer gescho

## Self-hosted: was sich ändert

Selbst gehostete Instanzen erscheinen nicht auf `status.tale.dev` — die Seite deckt Tale Cloud ab. Jedes Deployment bringt stattdessen seine eigene Status-Page mit, von der Plattform ausgeliefert und ohne Anmeldung erreichbar unter `https://<dein-host>/status`. Sie rendert serverseitig eine Gesundheits-Zusammenfassung — operational, degraded oder outage — aus einem Liveness-Probe gegen das Convex-Backend, sodass ein Betreiber (oder ein Endnutzer, der prüft, ob es nur bei ihm hakt) die Verfügbarkeit ohne Login lesen kann. Die maschinenlesbare Form ist `https://<dein-host>/status.json`, die dasselbe Ergebnis als JSON zurückgibt, das ein Uptime-Monitor pollen kann.
Selbst gehostete Instanzen erscheinen nicht auf `status.tale.dev` — die Seite deckt Tale Cloud ab. Jedes Deployment bringt stattdessen seine eigene Status-Page mit, von der Plattform ausgeliefert und ohne Anmeldung erreichbar unter `https://<dein-host>/status`. Sie rendert serverseitig eine Gesundheits-Zusammenfassung — operational, degraded oder outage — aus einem Liveness-Probe gegen die `/ping`-Route der Backend-Schicht, dieselbe Route, die auch der Healthcheck des `backend-api`-Containers nutzt. Ein Betreiber (oder ein Endnutzer, der prüft, ob es nur bei ihm hakt) liest die Verfügbarkeit damit ohne Login. Die maschinenlesbare Form ist `https://<dein-host>/status.json`, die dasselbe Ergebnis als JSON zurückgibt, das ein Uptime-Monitor pollen kann.

Der Probe meldet genau eine Komponente, `backend`, denn diese Schicht bedient jede Anfrage der App: Antwortet sie, fließen Daten. Die Liveness des Plattform-Containers steckt implizit drin — sonst hätte die Status-Page nicht gerendert. Ergebnisse sind fünf Sekunden gecacht und jeder Probe läuft nach zwei Sekunden ab, ein Uptime-Monitor auf `/status.json` kostet das Backend also selbst im kurzen Intervall fast nichts.

Diese Seite meldet die Verfügbarkeit des Deployments selbst. Für tieferes Betriebssignal — Container-Gesundheit von `tale status`, Anfrage-Metriken aus den Caddy-Logs und Control-Plane-Events im In-Product-Audit-Log — bildet die [Observability-Troubleshooting-Seite](/de/self-hosted/operate/observability/troubleshooting) Symptome auf Logs ab.

Expand Down
12 changes: 6 additions & 6 deletions docs/de/develop/webdav-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ Jede authentifizierte Anfrage prüft zusätzlich, dass der anfragende Benutzer a
| PROPFIND | Eine Ressource auflisten (Depth 0) oder die direkten Kinder einer Sammlung (Depth 1). Die emittierte Eigenschaftsliste ist unten dokumentiert. **Depth: infinity wird mit 403 abgelehnt**, um unbegrenzte Antworten zu verhindern. | Erforderlich |
| PROPPATCH | Gibt 207-Erfolg pro Eigenschaft zurück, ohne Werte zu speichern. Dead Properties werden in v1 nicht persistiert; PROPPATCH gelingt optimistisch zur Client-Kompatibilität. | Erforderlich |
| GET / HEAD | Den Dokument-Blob streamen. Setzt `Content-Type`, `Content-Length`, `ETag` und `Last-Modified`. GET auf eine Sammlung gibt 405 zurück. | Erforderlich |
| PUT | Ein Dokument erstellen oder ersetzen. Neuer Blob im Convex-Speicher mit Content-Hash-Dedup; die Dokument-Zeile erhält `sourceProvider: "webdav"`. Gibt 201 beim Erstellen, 204 beim Überschreiben zurück. | Erforderlich |
| PUT | Ein Dokument erstellen oder ersetzen. Der Body streamt unter einem frischen Key in den Objektspeicher der Organisation; die Dokument-Zeile erhält `sourceProvider: "webdav"`. Gibt 201 beim Erstellen, 204 beim Überschreiben zurück. Eine Anfrage ohne `Content-Length` (Chunked Transfer Encoding) wird abgelehnt — die präsignierte URL braucht die Länge vorab. | Erforderlich |
| DELETE | Ein Dokument soft-löschen (`lifecycleStatus: "trashed"`) oder einen Ordner (kaskadiert Trash auf enthaltene Dokumente, hard-löscht die Ordner-Zeilen). Gibt 204 zurück. | Erforderlich |
| MKCOL | Einen Ordner unter einem bestehenden Eltern erstellen. Nur leerer Body. Gibt 201 zurück, 405 wenn das Ziel existiert oder 409 wenn der Eltern fehlt. | Erforderlich |
| MOVE | Umbenennen oder verschieben. Atomar für Dokumente. Für Ordner wird die `parentId` des verschobenen Ordners aktualisiert. Beachtet `Overwrite: T/F` und `If`. Gibt 201 (neues Ziel) oder 204 (Überschreiben) zurück. | Erforderlich |
| COPY | Serverseitige Kopie. Dokumentkopien wiederverwenden die Convex-Storage-ID (Dedup). Ordnerkopien rekursiv. Beachtet `Overwrite` und `If`. | Erforderlich |
| COPY | Serverseitige Kopie. Eine Dokumentkopie ist eine zweite Zeile auf dasselbe gespeicherte Objekt — keine Bytes wandern, und das Objekt bleibt, bis die letzte Zeile darauf verschwindet. Ordnerkopien rekursiv. Beachtet `Overwrite` und `If`. | Erforderlich |
| LOCK | Class-2-exklusive oder geteilte Schreibsperre. Timeout aus `Timeout: Second-N`-Header, gedeckelt auf 3600. Refresh durch erneutes LOCK mit `If: (<opaquelocktoken:...>)` und leerem Body. | Erforderlich |
| UNLOCK | Eine Sperre per Token freigeben. Nur der Sperr-Besitzer kann freigeben. Gibt 204 zurück. | Erforderlich |

Expand All @@ -67,7 +67,7 @@ Dead Properties werden nicht gespeichert. PROPPATCH gibt für eine allein gesetz

## Sperrsemantik

Sperren leben in ihrer eigenen Convex-Tabelle, gekeyt mit `(organizationId, resourcePath)`. Wire-Form ist `opaquelocktoken:<uuid>`. Der Server:
Sperren leben in ihrer eigenen Postgres-Tabelle, indiziert über `(organizationId, resourcePath)`. Wire-Form ist `opaquelocktoken:<uuid>`. Der Server:

- Deckelt Timeout auf 3600 Sekunden. Anfragen für längere Fenster werden still gekappt.
- Behandelt `LOCK` mit `If: (<opaquelocktoken:UUID>)`-Header und leerem Body als Refresh — der Ablauf der bestehenden Sperre wird verlängert.
Expand Down Expand Up @@ -111,16 +111,16 @@ Der Server bewirbt `DAV: 1, 2` in der OPTIONS-Antwort.

- `Depth: infinity` auf PROPFIND wird mit `403` abgelehnt.
- `Timeout: Second-N` auf LOCK wird auf `[1, 3600]` begrenzt.
- Die PUT-Body-Größe ist standardmäßig auf **5 GB** begrenzt (`413` bei Überschreitung), erzwungen sowohl am Reverse-Proxy als auch im Plattform-Server. Betreiber können das Limit über die Umgebungsvariable `WEBDAV_MAX_PUT_BYTES` anpassen. Der Body wird an eine Convex-Presigned-URL gestreamt, ohne dass ein großer Upload im Plattform-Speicher gepuffert wird.
- Die PUT-Body-Größe ist standardmäßig auf **5 GB** begrenzt (`413` bei Überschreitung), erzwungen sowohl am Reverse-Proxy als auch im Backend. Betreiber passen das Limit über die Umgebungsvariable `WEBDAV_MAX_PUT_BYTES` an — setz sie auch auf dem Proxy-Container, sonst bleibt der Proxy die bindende Grenze. Der Body streamt an eine präsignierte Objektspeicher-URL, ohne dass ein großer Upload im Speicher des Backends gepuffert wird.
- XML-Request-Bodys (PROPFIND / PROPPATCH / MKCOL / LOCK) sind auf **64 KB** begrenzt (`413` bei Überschreitung) — diese Envelopes sind per Design winzig.
- App-Passwörter werden mit HMAC-SHA256 gehasht; das Geheimnis taucht nach dem Create-Call in keiner Antwort mehr auf.
- `lastUsedAt` wird höchstens einmal pro Minute pro App-Passwort gepatcht, um Write-Storms auf belebten Mounts zu vermeiden.

## Netzwerk-Voraussetzungen

Der WebDAV-Endpunkt läuft im Plattform-Hono-Server (`platform:3000` in Compose). Caddy routet `/dav/*` über den Default-Fallback dorthin — keine Extra-Konfiguration erforderlich. Der Pfad erfordert, dass der Plattform-Server `ADMIN_KEY` in seiner Umgebung gesetzt hat, damit er interne Convex-Abfragen mit Admin-Auth aufrufen kann.
Den WebDAV-Endpunkt bedient die Backend-Schicht (`backend-api:3005` in Compose). Caddy hat dafür einen eigenen `handle /dav/*`-Block, der dorthin weiterleitet und das Body-Limit anwendet — keine Extra-Konfiguration erforderlich. Der Endpunkt braucht kein Deployment-Credential: Jede Anfrage authentifiziert sich mit ihrem eigenen App-Passwort, und die Handler lesen und schreiben Postgres im selben Prozess.

Für Dev (`bun dev`) wird derselbe Dispatch als Vite-Middleware gemountet (`vite-plugins/serve-webdav.ts`) — `curl` und Clients können `http://localhost:3000/dav/<orgSlug>/...` gegen einen laufenden Dev-Server ohne Rebuild treffen.
Für Dev (`bun run dev`) proxyt Vite `/dav` an dasselbe Backend, `curl` und gemountete Clients treffen also `http://localhost:3000/dav/<orgSlug>/...` gegen einen laufenden Dev-Server.

## Sicherheit

Expand Down
Loading
Loading