Files
SciMesh/docs/ui-admin-worker-plan.md
T

182 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План реализации: Coordinator Admin UI и Worker Setup UI
> Статус: **реализовано (M1–M3), E2E проверено**. Визуал утверждён — мокапы:
> [`ui-mockups/coordinator-admin.html`](ui-mockups/coordinator-admin.html),
> [`ui-mockups/worker-setup.html`](ui-mockups/worker-setup.html).
> Два UI живут в **разных бинарниках**: админка кластера — в `coordinator`
> (`/ui/admin`), визард установки воркера — в `worker-agent`
> (`worker-agent setup`, локально на 127.0.0.1).
## 1. Цель
1. **Coordinator Admin UI** — консоль админа распределённого кластера:
System, Jobs, Workers, Users & keys, Workloads, Metrics, Settings.
Реальные данные, никакой симуляции; только роль `admin`.
2. **Worker Setup UI** — локальный визард в бинарнике `worker-agent` для
машины, на которой стоит только воркер: подключение (URL + токен/ключ),
параметры машины, preflight-проверка, запуск/остановка, статус и лог.
## 2. Что уже есть в коде (фундамент)
- `requireAdmin` middleware и `/ui/admin` (`internal/transport/http/ui_admin.go`)
— сейчас минимальная панель: прокси `promote/demote/verify/unverify` в
userservice.
- Userservice (`internal/userservice/`): `POST /users/{id}/promote|demote|
verify|unverify` (admin), `GET/POST/DELETE /worker-keys` (per-user),
`POST /worker-tokens/exchange`. **Нет**: list users, list all keys.
- `domain.Worker.TrustLevel` (`trusted`/`untrusted`) + quorum для untrusted —
колонка в БД есть, нужен только метод смены и отображение.
- `domain.Job.OwnerID *uuid.UUID` — владелец джобы из JWT `sub` (может быть nil).
- Каталог ворклоадов `internal/workloads` (embedded `workloads.json`) —
enable/disable кладём поверх через таблицу настроек.
- UIReadRepo (`ui_read_repo.go` в обоих движках) — bounded read model для UI.
- Агент целиком конфигурируется env (таблица в `mkdocs/sdk/worker-integration.md`);
`--config` маппится на ту же поверхность `agent.Config`.
## 3. Coordinator Admin UI
### 3.1 Страницы ↔ API ↔ данные
Все API — JSON, под `withUISession` + `requireAdmin`, префикс
`/ui/admin/api/`. Страница `admin.html` — оболочка из мокапа (сайдбар,
7 разделов), данные подтягивает JS через fetch (паттерн dashboard).
| Раздел | API | Данные |
| --- | --- | --- |
| System | `GET /system` | version, uptime, storage stats, health (db/userservice/reducer), node info |
| Jobs | `GET /jobs?status=&page=` | пагинированный список + счётчики по статусам; owner email резолвится через userservice |
| Workers | `GET /workers`, `POST /workers/{id}/trust` | список + trust, смена trust (trusted/untrusted) |
| Users & keys | `GET /users`, `POST /users/{id}/role`, `GET /worker-keys`, `POST /worker-keys/{id}/revoke` | прокси/агрегация userservice |
| Workloads | `GET /workloads`, `POST /workloads/{name}/enabled` | каталог + persisted enabled-флаг |
| Metrics | `GET /metrics` | jobs/day (7d), jobs by workload, shards, failure rate, avg shard time |
| Settings | `GET /settings`, `POST /token/reveal` | read-only конфиг + reveal токена (audit-лог) |
### 3.2 Userservice — новые эндпоинты
- `GET /users` (admin) — `id, email, role, verified, created_at`.
- `GET /worker-keys/all` (admin) — все ключи + owner email.
- Репозитории: `ListUsers(ctx)`, `ListWorkerKeysAll(ctx)` в `memstore` и
`storage/sqlite` (+ тесты). Координатор вызывает их через
`callUserserviceAuthed` и отдаёт в свой bounded API — браузер юзерсервис
не касается.
### 3.3 Storage координатора — новые методы
- `WorkerRepository.SetTrust(ctx, id, trust)` — оба движка + тесты.
- `UIReadRepo.ListJobsPaginated(ctx, status string, limit, offset int)`
→ `([]UIJob, total int, counts map[string]int)` — фильтр по статусу,
счётчики для табов.
- `UIReadRepo.JobMetrics(ctx, since time.Time)` → jobs/day, by workload,
shards completed/failed, avg shard duration (из `tasks`).
- `UIReadRepo.StorageStats(ctx)` → суммы байт по kind артефактов
(datasets/artifacts) + размер файла БД (sqlite: `page_count*page_size`;
postgres: `pg_database_size(current_database())`).
- Миграция `0002_workload_settings` (оба движка):
`workload_settings(workload TEXT PRIMARY KEY, enabled BOOL NOT NULL,
updated_at TIMESTAMP NOT NULL)`; отсутствие строки = enabled (default).
Repo: `WorkloadSettingsRepo{ List, Set }`.
- **Enforcement**: `SubmitDataset` отклоняет disabled-ворклоад;
`/ui/api/workloads` и форма new-job помечают disabled (скрываем из выбора).
### 3.4 Usecase — `internal/usecase/admin.go`
`AdminSystem`, `ListJobsAdmin(status,page)` (+owner emails), `ListWorkersAdmin`,
`SetWorkerTrust`, `ListUsersAdmin`, `SetUserRole` (через userservice promote/demote),
`ListWorkerKeysAdmin`, `RevokeWorkerKeyAdmin`, `ListWorkloadsAdmin`,
`SetWorkloadEnabled`, `AdminMetrics`, `RevealWorkerToken` (читает
`worker.token`/env, пишет audit-лог).
### 3.5 Шаблон
`templates/admin.html` заменяется на дизайн мокапа: сайдбар (Operate /
Access / Platform), topbar с env-бейджем (serve/postgres, addr), 7 разделов,
рендер через JS. Имя ворклоада — реальное `descriptor-batch`.
## 4. Worker Setup UI (бинарник `worker-agent`)
### 4.1 Новые файлы
```
coordinator/internal/agent/
configfile.go # ConfigFile (json), Load/Save (0600), путь по умолчанию
check.go # CheckCoordinator(url, auth) — health + версии + python/scimesh
setupui/
server.go # локальный HTTP 127.0.0.1:12700, API + запуск/остановка
template.html # визард + статус (по мокапу), go:embed
coordinator/cmd/worker-agent/main.go # + setup / --config / --check
```
### 4.2 CLI
- `worker-agent setup [--port 12700] [--no-open]` — визард; печатает URL,
открывает браузер.
- `worker-agent --config <path>` — демон из JSON-конфига; env имеет приоритет.
- `worker-agent --check [--coordinator-url URL]` — пинг `/health`, auth
(token → claim-endpoint 401/200 probe или exchange для ключа), python3 +
`import scimesh`; exit 0/1. Используется визардом на шаге 3.
### 4.3 config.json
`~/.scimesh-worker/config.json` (переопределяется `WORKER_CONFIG`), права 0600:
```json
{
"coordinator_url": "http://192.168.1.10:8080",
"token": "…", // или
"worker_key": "…", "userservice_url": "http://…:8081",
"work_dir": "…", "worker_name": "emil-laptop",
"cpu_count": 8, "memory_mb": 16384,
"task_runner": ["python", "-m", "scimesh.worker.task"]
}
```
### 4.4 API визарда (только 127.0.0.1, без auth)
| Метод | Путь | Назначение |
| --- | --- | --- |
| GET | `/api/status` | конфиг (секрет маскирован), running (pid alive), статистика из лога, runtime |
| POST | `/api/config` | валидация + сохранение `config.json` (0600) |
| POST | `/api/test` | preflight: coordinator reachable, auth ok, python, scimesh |
| POST | `/api/start` | spawn `worker-agent --config <path>` (лог → `worker.log`, pid-файл) |
| POST | `/api/stop` | SIGTERM по pid-файлу |
| GET | `/api/logs?tail=` | хвост `worker.log` |
Статистика — парсинг лога (registered/claimed/completed/failed/heartbeat).
Spawner — интерфейс, в тестах подменяется.
## 5. Милестоуны
- **M1. Admin-фундамент** — ✅ done: оболочка `admin.html` по мокапу +
`GET /system` (storage stats, health, node) + `GET /jobs`
(фильтр+пагинация+счётчики) + `GET /metrics`; тесты на sqlite, 403 для
не-админа.
- **M2. Access & Platform** — ✅ done: userservice `ListUsers`/
`ListWorkerKeysAll` + admin revoke (mem+sqlite+http), `SetTrust` (оба
движка), users/keys/trust разделы, `workload_settings` (миграции 0002/
0014) + enforcement в `SubmitDataset` и форме, settings + audited token
reveal. Все секции админки на живых данных.
- **M3. Worker Setup** — ✅ done: `configfile.go` (0600), `--config` (env
wins), `--check`, `setupui` (сервер на 127.0.0.1, 6 API, шаблон по мокапу),
тесты (roundtrip, права, check, API с fake supervisor).
- **M4. E2E + docs** — ✅ done: браузерный E2E (admin видит реальные
данные; визард запустил реального воркера → `wizard-machine online` в
админке), обновлены `mkdocs/index.md` и `mkdocs/standalone.md`
(`worker-agent setup`), README, статусы CTX-19/CTX-20 в `PLAN.md`.
## 6. Тестирование
- **Go unit**: usecase admin (fakes + sqlite), repos обоих движков
(SetTrust, pagination, metrics, settings, storage stats), userservice
List/ListAll (mem+sqlite), HTTP permission (user → 403 на все `/ui/admin/api/*`),
enforcement disabled-ворклоада, configfile/check/setupui агента.
- **Go integration (postgres)**: миграция 0002 и parity новых методов —
через существующий docker-хелпер, skip без docker.
- **E2E браузер**: M4.
## 7. Открытые решения (зафиксировано)
- Локальный визард без аутентификации — слушает только 127.0.0.1.
- Settings-раздел v1 — read-only + reveal токена; редактирование конфигурации
и prune/reset (danger zone) — v2, в UI помечены как таковые.
- `owner` джобы: email из userservice по `OwnerID`; при nil — «cluster token».
- Статистика воркера в визарде — из лога, без новых эндпоинтов координатора.