
# Архітектура

## Загальний потік

За замовчуванням (локальний tmux + тунель):

```
Browser (phone)
  |
  | HTTPS
  v
Cloudflare Quick Tunnel
  |
  | HTTP/WS
  v
Local Termbridge server
  |
  | PTY
  v
Tmux session
```

Прямий режим пісочниці (Daytona, без тунелю):

```
Browser (phone)
  |
  | HTTPS
  v
Daytona preview link
  |
  | HTTP/WS
  v
Termbridge server (sandbox)
  |
  | PTY
  v
Tmux session (sandbox)
```

Коли задано `--no-tunnel`, Termbridge пропускає Cloudflare і використовує наданий вами публічний URL.

## Компоненти

### Процес CLI

- Запускає сервер HTTP, який обслуговує ресурси UI.
- Запускає сервер WebSocket для вводу-виводу термінала.
- Створює один або кілька сеансів tmux (або псевдотерміналів Daytona).
- Видає одноразові токени для отримання доступу.
- Запускає тунель і стежить за ним, якщо його ввімкнено (нині Cloudflare).
- У прямому режимі пісочниці запускає Termbridge усередині пісочниці та очікує на посилання для доступу URL.

### Бекенд термінала

- **Бекенд tmux**: використовує `node-pty` для підключення до tmux і передавання натискань клавіш та виводу.
- **Бекенд Daytona**: використовує псевдотермінали Daytona у пісочниці.
- Встановлює `TERM=xterm-256color` і `COLORTERM=truecolor` для повної підтримки кольорів.
- Для tmux вимикає рядок стану tmux, щоб не захаращувати UI.

### Реєстр терміналів

- Відстежує доступні сеанси термінала.
- Надає список для UI і перевіряє вибрані ідентифікатори терміналів.

### Автентифікація та сеанс

- Одноразовий токен виводиться як URL і кодується у QR коді.
- `GET /__tb/s/:token` отримує токен і встановлює сеансовий cookie.
- Для з’єднань WebSocket потрібні дійсний сеансовий cookie та CSRF-токен.
- CSRF-токен отримується через `GET /__tb/api/csrf` і передається як параметр запиту WebSocket.

### Режим проксі

Коли передано `--proxy <port>`:
- Усі маршрути termbridge розміщуються за префіксом `/__tb/`
- Запити, не пов’язані з `/__tb/`, перенаправляються до цільового застосунку
- UI надає подання «Термінал» і «Попередній перегляд» через перемикач «Подання»
- Подання «Попередній перегляд» завантажує iframe, що вказує на `/`
- З’єднання WebSocket для HMR пересилаються до цільового застосунку

### Безпека

- **Захист від CSRF**: для оновлення WebSocket потрібен CSRF-токен, що запобігає перехопленню між сайтами.
- **Обмеження розміру вводу**: тіло HTTP до 64KB, повідомлення WebSocket до 1MB, введення в термінал до 64KB на повідомлення.
- **Обмеження частоти запитів**: ліміти для отримання токена та з’єднань WebSocket на IP.

## Кінцеві точки API

Усі маршрути розміщуються за префіксом `/__tb/`, щоб уникнути конфліктів із проксійованими застосунками:

- `GET /__tb/healthz` — перевірка працездатності
- `GET /__tb/s/:token` — отримання токена → cookie → перенаправлення
- `GET /__tb/api/terminals` — список терміналів
- `GET /__tb/api/csrf` — отримання CSRF-токена для WebSocket
- `GET /__tb/api/config` — отримання конфігурації (proxyPort, devProxyUrl)
- `POST /__tb/api/terminals` — створення нового сеансу tmux
- `GET /__tb/app/*` — резервний маршрут SPA
- `WS /__tb/ws/terminal/:terminalId?csrf=<token>` — потокове передавання вводу-виводу термінала

Коли режим проксі ввімкнено:
- `GET /` — перенаправляє до проксійованого застосунку (або `/__tb/app`, якщо вимкнено)
- `* /*` — проксіюється до цільового застосунку

## Протокол WebSocket

Клієнт → сервер:

```json
{ "type": "input", "data": "ls -la" }
{ "type": "resize", "cols": 120, "rows": 32 }
{ "type": "control", "key": "ctrl_c" }
```

Сервер → клієнт:

```json
{ "type": "output", "data": "..." }
{ "type": "status", "state": "connected" }
```

## Стек UI

- Vite + TanStack Router
- xterm.js + додаток Fit + рушій WebGL
- Макет насамперед для мобільних пристроїв із закріпленим рядком вводу
- Автоматичне повторне підключення з експоненційною затримкою (до 10 спроб)
- Індикатор стану з’єднання
