Init
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# Agent protocol (fleet)
|
||||
|
||||
Агент (`apps/agent`) работает только при `PANEL_MODE=fleet`.
|
||||
|
||||
## Enrollment
|
||||
|
||||
`POST /api/agent/enroll`
|
||||
|
||||
```json
|
||||
{ "token": "<enrollment>", "hostname": "...", "name": "...", "agentVersion": "0.1.0" }
|
||||
```
|
||||
|
||||
Ответ: `{ agentId, agentToken, panelUrl }`. Токен enrollment одноразовый. Состояние агента: `/var/lib/telemt-panel-agent/state.json`.
|
||||
|
||||
## Jobs poll
|
||||
|
||||
`GET /api/agent/jobs` — `Authorization: Bearer <agentToken>`
|
||||
|
||||
Возвращает pending jobs:
|
||||
|
||||
```json
|
||||
[{ "id": "...", "type": "telemt.proxy", "payload": { "method": "GET", "path": "/v1/users", "body": null } }]
|
||||
```
|
||||
|
||||
## Result
|
||||
|
||||
`POST /api/agent/jobs/:id/result`
|
||||
|
||||
```json
|
||||
{ "ok": true, "result": { "ok": true, "data": {} }, "error": "" }
|
||||
```
|
||||
|
||||
## telemt.proxy
|
||||
|
||||
Агент выполняет HTTP к локальному `TELEMT_API_URL` (по умолчанию `http://127.0.0.1:9091`) и возвращает JSON envelope.
|
||||
|
||||
Установка: `GET /install-agent.sh` → `deploy/install-agent.sh`.
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
# Telemt Panel — установка (RU)
|
||||
|
||||
Один Docker-образ: `git.shts.su/denozord/telemtPanel`. Режим задаётся `PANEL_MODE`.
|
||||
|
||||
| Режим | Когда | Агент |
|
||||
|-------|--------|--------|
|
||||
| `standalone` | Telemt на том же хосте | **не нужен** — панель ходит в Control API `/v1` напрямую |
|
||||
| `fleet` | Несколько нод | Go-агент на каждой ноде |
|
||||
|
||||
UI: ReUI PRO Frame. Previews: [app-shell-12](https://reui.io/preview/base/app-shell-12), [auth-4](https://reui.io/preview/base/auth-4), [stats-12](https://reui.io/preview/base/stats-12). Docs: [frame](https://reui.io/docs/components/base/frame), [blocks](https://reui.io/blocks).
|
||||
|
||||
## Требования
|
||||
|
||||
- Docker 24+
|
||||
- Telemt с включённым Control API (`[server.api]`) для standalone
|
||||
- Открытый порт панели (8080) или Traefik
|
||||
|
||||
## Быстрый старт: standalone (рекомендуется на Linux)
|
||||
|
||||
```bash
|
||||
docker pull git.shts.su/denozord/telemtPanel:latest
|
||||
|
||||
docker run -d --name telemt-panel --network host \
|
||||
-e PANEL_MODE=standalone \
|
||||
-e TELEMT_API_URL=http://127.0.0.1:9091 \
|
||||
-e JWT_SECRET="$(openssl rand -hex 32)" \
|
||||
-e BOOTSTRAP_USERNAME=admin \
|
||||
-e BOOTSTRAP_PASSWORD='change-me' \
|
||||
-v /var/lib/telemt-panel:/data \
|
||||
git.shts.su/denozord/telemtPanel:latest
|
||||
```
|
||||
|
||||
Откройте `http://127.0.0.1:8080`, войдите `admin` / пароль из `BOOTSTRAP_PASSWORD`.
|
||||
|
||||
Compose:
|
||||
|
||||
```bash
|
||||
cp .env.example .env # заполните JWT_SECRET и BOOTSTRAP_PASSWORD
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Три сетевых рецепта (standalone)
|
||||
|
||||
1. **`network_mode: host`** (Linux, prod) — контейнер видит `127.0.0.1` хоста, где слушает Telemt.
|
||||
2. **Sidecar** — Telemt и панель в одном compose-network; `TELEMT_API_URL=http://telemt:9091`.
|
||||
3. **Docker Desktop** — `extra_hosts: host.docker.internal:host-gateway`, `TELEMT_API_URL=http://host.docker.internal:9091`. В whitelist Telemt разрешите IP контейнера или lab-only `0.0.0.0/0`.
|
||||
|
||||
## Fleet
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.fleet.yml up -d
|
||||
```
|
||||
|
||||
Обязательно:
|
||||
|
||||
- `PANEL_MODE=fleet`
|
||||
- `PANEL_PUBLIC_URL` — публичный URL панели (для enroll / install script)
|
||||
- `PANEL_ENCRYPTION_KEY`, `JWT_SECRET`
|
||||
|
||||
В UI: **Серверы** → создать enrollment-токен → на ноде:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://panel.example.com/install-agent.sh | sudo bash -s -- \
|
||||
--panel-url https://panel.example.com \
|
||||
--token <TOKEN> \
|
||||
--telemt-url http://127.0.0.1:9091
|
||||
```
|
||||
|
||||
Бинарник агента: соберите `apps/agent` (`go build -o telemt-panel-agent .`) и положите в `/usr/local/bin/telemt-panel-agent`, либо опубликуйте в releases.
|
||||
|
||||
## Traefik (prod)
|
||||
|
||||
См. `deploy/docker-compose.traefik.yml` и `deploy/env.traefik.example`. Каталог на сервере: `/opt/telemt-panel`.
|
||||
|
||||
## Переменные окружения
|
||||
|
||||
| Переменная | Описание |
|
||||
|------------|----------|
|
||||
| `PANEL_MODE` | `standalone` \| `fleet` |
|
||||
| `TELEMT_API_URL` | Base URL Control API (standalone) |
|
||||
| `TELEMT_AUTH_HEADER` | Опциональный `Authorization` к Telemt |
|
||||
| `JWT_SECRET` | Секрет JWT операторов |
|
||||
| `BOOTSTRAP_USERNAME` / `BOOTSTRAP_PASSWORD` | Первый admin при пустой БД |
|
||||
| `PANEL_PUBLIC_URL` | Публичный URL (fleet) |
|
||||
| `PANEL_ENCRYPTION_KEY` | Ключ для чувствительных данных (fleet) |
|
||||
| `DATABASE_URL` | По умолчанию `sqlite:/data/app.db` |
|
||||
| `SERVER_PORT` | По умолчанию `8080` |
|
||||
|
||||
Bootstrap без env (после старта):
|
||||
|
||||
```bash
|
||||
docker exec -it telemt-panel node -e "console.log('use BOOTSTRAP_PASSWORD on first boot')"
|
||||
# или локально: pnpm bootstrap-admin -- --username admin --password '...'
|
||||
```
|
||||
|
||||
## Telemt `[server.api]`
|
||||
|
||||
Включите Control API и whitelist IP панели. Документация API: [Telemt Control API](https://github.com/telemt/telemt/blob/main/docs/Architecture/API/API.md). Локальные заметки: `docs/telemt-control-api.md`.
|
||||
|
||||
## Health
|
||||
|
||||
- `GET /health` — панель + SQLite
|
||||
- `GET /ready` — в standalone также ping Telemt `/v1/health`
|
||||
|
||||
## Скрипт установщика
|
||||
|
||||
```bash
|
||||
chmod +x deploy/install.sh
|
||||
./deploy/install.sh --mode standalone
|
||||
```
|
||||
@@ -0,0 +1,22 @@
|
||||
# Telemt Control API (BFF)
|
||||
|
||||
Панель проксирует [Telemt Control API `/v1`](https://github.com/telemt/telemt/blob/main/docs/Architecture/API/API.md).
|
||||
|
||||
## Контракт UI
|
||||
|
||||
| Режим | Путь |
|
||||
|-------|------|
|
||||
| standalone | `GET/POST/PATCH/DELETE /api/telemt/*` → `TELEMT_API_URL/v1/*` |
|
||||
| оба | `… /api/servers/:id/telemt/*` (`local` в standalone) |
|
||||
| fleet | job `telemt.proxy` на агенте |
|
||||
|
||||
Envelope: `{ ok, data?, revision?, error? }`. Для мутаций с revision передавайте `If-Match`.
|
||||
|
||||
## Типичные эндпоинты
|
||||
|
||||
- `/v1/health`, `/v1/stats/summary`
|
||||
- `/v1/users`
|
||||
- `/v1/runtime/me_pool_state`, `/v1/runtime/events/recent`
|
||||
- `/v1/security/posture`
|
||||
|
||||
Клиент: `apps/api/src/services/telemt-client.ts`.
|
||||
@@ -0,0 +1,121 @@
|
||||
# UI Design Contract (ops apps)
|
||||
|
||||
Единый контракт для **CFDM · telemt-panel · EvoBGP · EvoFirewall · auth-portal**.
|
||||
Surface: **ReUI Frame**. Kit: `apps/web/src/components/reui-kit/`.
|
||||
Иерархия (жёстко): **ReUI PRO > kit > shadcn primitives**. Голый shadcn/ui blocks — не primary для ops.
|
||||
Project rule: `.cursor/rules/reui-pro-priority.mdc`.
|
||||
|
||||
Карта: [llms.txt](https://reui.io/llms.txt) · [Styling](https://reui.io/docs/styling) · [License](https://reui.io/docs/license-setup) · [Blocks](https://reui.io/blocks) · [MCP](https://reui.io/docs/mcp)
|
||||
|
||||
## Surface
|
||||
|
||||
Project lock: **`surface: frame`**. Ops / list / dashboard / detail / settings — только **Frame**, не shadcn Card как shell. Не смешивать Card и Frame на одном ops-экране.
|
||||
|
||||
```ts
|
||||
// apps/web/src/lib/ui-surface.ts (где есть)
|
||||
export const UI_SURFACE = 'frame' as const
|
||||
```
|
||||
|
||||
Settings: секции через Frame + `gap` (без hairline `Separator` под PageHeader); `SettingRow` без `FieldSeparator` по умолчанию (`separated` opt-in). Preview: [settings-3](https://reui.io/preview/base/settings-3) · [settings-16](https://reui.io/preview/base/settings-16).
|
||||
|
||||
## Canonical PRO references
|
||||
|
||||
| Зона | Block | Preview |
|
||||
|------|-------|---------|
|
||||
| Shell | `app-shell-12` (+ cmdk/monitor где нужно) | https://reui.io/preview/base/app-shell-12 · https://reui.io/preview/base/app-shell-7 |
|
||||
| KPI | horizontal compact hybrid (EvoBGP SoT: icon left + label/Badge + value ± variant) | https://reui.io/preview/base/stats-12 |
|
||||
| Quick Actions | Frame tiles (sibling KPI) + Badge «Перейти» | https://reui.io/preview/base/stats-12 · https://reui.io/preview/base/card-12 |
|
||||
| Dashboard | `dashboard-1` | https://reui.io/preview/base/dashboard-1 |
|
||||
| Lists | `data-grid-filtering-2` | https://reui.io/preview/base/data-grid-filtering-2 |
|
||||
| Settings | `settings-16` + SettingRow | https://reui.io/preview/base/settings-16 |
|
||||
| Auth | `auth-13` | https://reui.io/preview/base/auth-13 |
|
||||
| Empty | `empty-state-12` | https://reui.io/preview/base/empty-state-12 |
|
||||
| Forms | `form-7` → Sheet/Drawer | https://reui.io/preview/base/form-7 |
|
||||
|
||||
## Kit API (`reui-kit/`)
|
||||
|
||||
| Component | Role |
|
||||
|-----------|------|
|
||||
| `ResourcePage` | Frame + line tabs + Filters + DataGrid (primary lists; without Filters → simple CRUD grid) |
|
||||
| `FrameDataGrid` | Internal / embedded Frame grid used by ResourcePage simple mode |
|
||||
| `KpiStatGrid` | EvoBGP hybrid KPI tiles (`items`/`cards`, `variant`, Badge) |
|
||||
| `QuickActionGrid` | KPI-like quick action tiles (gated by `showQuickActions`) |
|
||||
| `OpsDashboard` | KPI + optional `afterKpi` + charts + attention queue |
|
||||
| `SettingsShell` | settings nav + Outlet |
|
||||
| `DetailPanel` | detail Frame sections |
|
||||
| `filter-utils` | apply/clear ReUI Filters |
|
||||
|
||||
`KpiStatGrid` / `QuickActionGrid` markup — SoT **EvoBGP**; в остальных apps diff только `@scope/ui` imports.
|
||||
|
||||
## Dashboard layout
|
||||
|
||||
| App | Section order |
|
||||
|-----|---------------|
|
||||
| EvoBGP / CFDM / EvoFirewall | KPI → **QuickActionGrid** → charts / rest |
|
||||
| telemt-panel | banner → KPI → charts → attention → **QuickActionGrid** → CSV |
|
||||
| auth-portal | portal-specific; Quick Actions при наличии dashboard |
|
||||
|
||||
Gating: DB `show_quick_actions` / `showQuickActions` / `ui_show_quick_actions` (default `true`).
|
||||
|
||||
## Shared App Shell chrome
|
||||
|
||||
Эталон разметки: production apps + ReUI [app-shell-12](https://reui.io/preview/base/app-shell-12).
|
||||
При переключении между apps меняются **только** sidebar nav labels/hrefs и `main` content.
|
||||
|
||||
| Токен / зона | Значение |
|
||||
|--------------|----------|
|
||||
| `SIDEBAR_WIDTH` / `--sidebar-width` | `240px` |
|
||||
| Sidebar / hover colors | theme `--sidebar` / `--sidebar-accent` — **без** AppShell `color-mix` override |
|
||||
| Header | `h-12`, `sticky`, `border-b`, `px-4 md:px-6` |
|
||||
| Header left | `SidebarTrigger` + `Separator` + Breadcrumb |
|
||||
| Header right | **AppsMenu** → **SystemMonitorPopover** (тема — в NavUser) |
|
||||
| Sidebar | AppSwitcher → groups → icons `size-4` → **NavUser** в `SidebarFooter` |
|
||||
| `main` | `gap-4 md:gap-6`, `px-4 py-4 md:px-6 md:py-5` |
|
||||
| Search | hotkey ⌘K / Ctrl+K only (не кнопка в header) |
|
||||
|
||||
Запрещено в chrome: `SidebarRail`, sync-row footer, Search pill в header, issues Badge в header, `ModeToggle` в header (тема только в NavUser), Provider `color-mix` для `--sidebar*`.
|
||||
|
||||
NavUser (footer): avatar + name/email; dropdown — Настройки / Тема (segmented) / Выйти. Preview: [app-shell-1](https://reui.io/preview/base/app-shell-1).
|
||||
|
||||
App Switcher: auth-portal `GET /api/v1/app-switcher`. Ids: `cfdm` · `telemt` · `bgp` · `fw`. Admin: portal `/admin/apps`.
|
||||
|
||||
QuickActionGrid / KPI icons: только semantic **text** (`text-info` / `text-primary` / …) на kit `bg-muted` — без solid fills.
|
||||
|
||||
## System monitor
|
||||
|
||||
`SystemMonitorPopover` in header after AppsMenu. Preview: https://reui.io/preview/base/app-shell-12 · https://reui.io/preview/base/app-shell-7
|
||||
|
||||
## MCP workflow
|
||||
|
||||
1. MCP `user-reui` — `search` / `get_block` / `compose_page` / `get_component` with `surface: "frame"`
|
||||
2. Cite `previewUrl` + `docsUrl`
|
||||
3. CLI from `apps/web`: `pnpm dlx shadcn@latest add @reui/...`
|
||||
4. Adapt into kit — do not hand-roll KPI / Quick Actions / grid / settings rows
|
||||
5. `validate_usage` / `get_audit_checklist`
|
||||
|
||||
Primitives: MCP `plugin-shadcn-shadcn` + project `@scope/ui` (`@telemt/ui` / `@evobgp/ui` / `@evofw/ui` / `@authportal/ui`).
|
||||
|
||||
## License
|
||||
|
||||
```env
|
||||
# apps/web/.env.local (gitignored)
|
||||
REUI_LICENSE_KEY=
|
||||
```
|
||||
|
||||
`apps/web/components.json` → `@reui` с `Authorization: Bearer ${REUI_LICENSE_KEY}`.
|
||||
|
||||
## Spacing
|
||||
|
||||
- AppShell main / PageShell: `gap-4 md:gap-6`, `px-4 py-4 md:px-6 md:py-5`
|
||||
- No `space-y-*` / `space-x-*` — use `flex` + `gap-*`
|
||||
- Max 1 primary CTA per screen
|
||||
- Semantic tokens only — no raw `bg-emerald-*`
|
||||
|
||||
## Forbidden
|
||||
|
||||
- Card as ops list/dashboard shell
|
||||
- Hand-rolled data tables when ReUI DataGrid / `ResourcePage` exists
|
||||
- Hand-rolled KPI when `KpiStatGrid` exists
|
||||
- Hand-rolled Quick Actions when `QuickActionGrid` exists
|
||||
- SectionCards / DataGridCard as design эталон
|
||||
- Mixing Card and Frame surfaces on one ops screen
|
||||
Reference in New Issue
Block a user