feat(memory-bank): update active context and progress documentation
CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 25s
CI / web (push) Successful in 30s
CI / go (push) Successful in 54s
CI / bird2 (push) Successful in 14s
CI / release (push) Successful in 3m43s
CI / changes (push) Successful in 8s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 25s
CI / web (push) Successful in 30s
CI / go (push) Successful in 54s
CI / bird2 (push) Successful in 14s
CI / release (push) Successful in 3m43s
Обновлены разделы активного контекста и прогресса для задачи `settings-ui-and-runtime-logs`. Упрощено отображение статуса завершённых фаз и добавлены ссылки на архив. Уточнены следующие шаги и активные задачи, улучшая ясность и доступность информации. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
+10
-378
@@ -2,391 +2,23 @@
|
||||
|
||||
## Current Task
|
||||
|
||||
**settings-ui-and-runtime-logs**
|
||||
|
||||
| Поле | Значение |
|
||||
|------|----------|
|
||||
| **Task ID** | `settings-ui-and-runtime-logs` |
|
||||
| **Complexity** | **Level 4** |
|
||||
| **Status** | **BUILD complete** → REFLECT |
|
||||
| **Дата VAN** | 2026-06-12 |
|
||||
| **Дата PLAN** | 2026-06-12 |
|
||||
_Нет активной задачи. Запустите `/van` для новой._
|
||||
|
||||
---
|
||||
|
||||
## Resolved Decisions (от заказчика)
|
||||
## Last Completed
|
||||
|
||||
| # | Вопрос | Решение |
|
||||
|---|--------|---------|
|
||||
| 1 | `/settings` vs tenant | **`/settings` — только frontend** (токен, тема, localStorage). **Tenant-настройки — отдельный модуль** (новый route + nav). |
|
||||
| 2 | Очистка больших логов | **Синхронно** (HTTP 200/4xx/5xx), без `jobs.Registry` / 202. |
|
||||
| 3 | Где FS API | **Только `evobgp-all`** с bind-mount volume на runtime-logs. На `evobgp-api` — `503` или отсутствие маршрута. |
|
||||
| 4 | Audit очистки | **Да** — персистентный audit в PostgreSQL (и sqlite для паритета). |
|
||||
| Task ID | Archive | Дата |
|
||||
|---------|---------|------|
|
||||
| `settings-ui-and-runtime-logs` | [archive-settings-ui-and-runtime-logs.md](archive/archive-settings-ui-and-runtime-logs.md) | 2026-06-12 |
|
||||
|
||||
---
|
||||
|
||||
## Requirements Summary
|
||||
## Status Template (для следующей задачи)
|
||||
|
||||
### A. Web UI — два независимых модуля
|
||||
|
||||
| Модуль | Route (план) | Данные | Роль |
|
||||
|--------|--------------|--------|------|
|
||||
| **Frontend settings** | `/settings` (существует) | localStorage, theme | любой пользователь UI |
|
||||
| **Tenant settings** | `/tenant-settings` (новый) | `GET/PATCH /v1/settings` → `global_settings` | viewer read / operator write |
|
||||
|
||||
**Tenant module** объединяет сейчас разрозненное:
|
||||
- `OperationsSystemSettingsTab` → revision + custom KV (убрать из Operations)
|
||||
- `BirdSettingsForm` → BIRD keys (убрать с `/network` или оставить read-only summary + ссылка)
|
||||
|
||||
**`/settings` не трогать семантически** — только polish (заголовки, пояснения что это настройки браузера).
|
||||
|
||||
### B. Runtime logs — FS
|
||||
|
||||
- Корень: `EVOBGP_RUNTIME_LOGS_DIR` (prod default: `/opt/evobgp/runtime-logs`)
|
||||
- Источник файлов: sidecar `stack-runtime-logs` (без изменений)
|
||||
- API: list / stat / tail / cleanup (sync)
|
||||
- Audit: каждая операция cleanup → запись в БД
|
||||
|
||||
---
|
||||
|
||||
## Technology Validation
|
||||
|
||||
| Технология | Версия / статус | Примечание |
|
||||
|------------|-----------------|------------|
|
||||
| Go stdlib `os`, `path/filepath` | 1.24 | FS read/truncate; без новых deps |
|
||||
| PostgreSQL + sqlite миграции | 000026 | audit table |
|
||||
| OpenAPI 3.1 | `docs/openapi.yaml` | новые paths под tag `RuntimeLogs` |
|
||||
| SvelteKit 5 + shadcn | web/ | новые routes/components |
|
||||
| Compose bind mount | `deploy/compose/*` | volume на `evobgp-all` |
|
||||
|
||||
**PoC не требуется** — паттерны audit и settings уже в репозитории.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph web [Web UI]
|
||||
FS["/settings<br>frontend only"]
|
||||
TS["/tenant-settings<br>BIRD + revision + KV"]
|
||||
MON["/monitoring?tab=runtime-logs"]
|
||||
end
|
||||
|
||||
subgraph api [evobgp-all only]
|
||||
H[httpapi handlers]
|
||||
RL[internal/runtimelogs]
|
||||
ST[store.Backend]
|
||||
end
|
||||
|
||||
subgraph data [Data]
|
||||
PG[(global_settings)]
|
||||
AUD[(runtime_log_cleanup_audit)]
|
||||
VOL["/opt/evobgp/runtime-logs/*.log"]
|
||||
end
|
||||
|
||||
FS --> localStorage
|
||||
TS --> H
|
||||
MON --> H
|
||||
H --> ST
|
||||
H --> RL
|
||||
ST --> PG
|
||||
ST --> AUD
|
||||
RL --> VOL
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phased Implementation Plan
|
||||
|
||||
### Phase 0 — Creative (обязательно перед BUILD)
|
||||
|
||||
Документы в `memory-bank/creative/`:
|
||||
|
||||
| ID | Тип | Тема | Вопросы |
|
||||
|----|-----|------|---------|
|
||||
| CP-1 | uiux | Tenant settings module | Структура вкладок: BIRD / Ревизии / Дополнительно; nav label |
|
||||
| CP-2 | uiux | Runtime logs UI | Вкладка в Monitoring vs отдельный route |
|
||||
| CP-3 | algorithm | Cleanup semantics | `truncate` (обнулить файл) vs `delete`; max tail bytes/lines |
|
||||
| CP-4 | architecture | Path safety | Allowlist имён файлов `*.log`, запрет `..`, symlink policy |
|
||||
|
||||
**Уже решено (не обсуждать в creative):** sync cleanup, evobgp-all only, audit yes, settings split.
|
||||
|
||||
---
|
||||
|
||||
### Phase 1 — Contract & persistence (OpenAPI + migrations + store)
|
||||
|
||||
**Цель:** контракт и audit до FS-логики.
|
||||
|
||||
| # | Действие | Файлы |
|
||||
|---|----------|-------|
|
||||
| 1.1 | OpenAPI: `RuntimeLogs` tag | `docs/openapi.yaml` |
|
||||
| 1.2 | Схемы: `RuntimeLogFile`, `RuntimeLogTail`, `RuntimeLogCleanupAudit` | `docs/openapi.yaml` |
|
||||
| 1.3 | Paths (см. ниже) | `docs/openapi.yaml` |
|
||||
| 1.4 | Миграция `000026_runtime_log_cleanup_audit` | `migrations/postgres/`, `migrations/sqlite/` |
|
||||
| 1.5 | Типы + `store.Backend` методы | `internal/store/runtime_logs.go`, `backend.go` |
|
||||
| 1.6 | Postgres + Memory реализации | `internal/repository/postgres_runtime_logs.go`, `internal/store/memory_runtime_logs.go` |
|
||||
|
||||
**OpenAPI paths (черновик):**
|
||||
|
||||
```
|
||||
GET /v1/runtime-logs/files # list + size/mtime
|
||||
GET /v1/runtime-logs/files/{filename} # tail (?lines= | ?bytes=, ?grep=)
|
||||
DELETE /v1/runtime-logs/files/{filename} # cleanup (?mode=truncate|delete), operator+, sync 200
|
||||
GET /v1/runtime-logs/cleanup-audit # cursor/limit, viewer+
|
||||
```
|
||||
|
||||
**Audit table `runtime_log_cleanup_audit`:**
|
||||
|
||||
| Column | Type | Note |
|
||||
|--------|------|------|
|
||||
| id | TEXT PK | UUID |
|
||||
| tenant_id | TEXT | из auth |
|
||||
| actor_prefix | TEXT | API key prefix |
|
||||
| filename | TEXT | basename only |
|
||||
| action | TEXT | `truncate` \| `delete` |
|
||||
| size_before | BIGINT | bytes |
|
||||
| size_after | BIGINT | nullable |
|
||||
| detail_json | JSONB | optional (grep stats, error) |
|
||||
| created_at | TIMESTAMPTZ | |
|
||||
|
||||
**Checklist Phase 1:**
|
||||
- [x] `npx @redocly/cli lint docs/openapi.yaml`
|
||||
- [x] миграции `000026` postgres + sqlite (пары up/down)
|
||||
- [x] store interface + memory tests (`TestMemoryRuntimeLogCleanupAudit`)
|
||||
|
||||
---
|
||||
|
||||
### Phase 2 — FS layer & config (evobgp-all only)
|
||||
|
||||
**Цель:** безопасное чтение/очистка файлов.
|
||||
|
||||
| # | Действие | Файлы |
|
||||
|---|----------|-------|
|
||||
| 2.1 | `EVOBGP_RUNTIME_LOGS_DIR` в config | `internal/config/config.go`, `docs/access.md` |
|
||||
| 2.2 | Guard: FS enabled iff dir non-empty **and** `EVOBGP_SERVICE=evobgp-all` | `internal/runtimelogs/guard.go` |
|
||||
| 2.3 | ListDir, Stat, Tail, Cleanup | `internal/runtimelogs/fs.go` |
|
||||
| 2.4 | Path hardening: basename allowlist `[a-z0-9_.-]+\.log` | `internal/runtimelogs/safe.go` |
|
||||
| 2.5 | Unit tests (temp dir) | `internal/runtimelogs/*_test.go` |
|
||||
|
||||
**Поведение при отключённом FS:**
|
||||
- `GET` → `503` problem+json `runtime_logs_unavailable`
|
||||
- `DELETE` → `503`
|
||||
|
||||
**Cleanup flow (sync):**
|
||||
1. Stat file → `size_before`
|
||||
2. Truncate or Remove
|
||||
3. `AppendRuntimeLogCleanupAudit(...)`
|
||||
4. Return `200` + audit id + sizes
|
||||
|
||||
**Checklist Phase 2:**
|
||||
- [x] `go test ./internal/runtimelogs/... -count=1`
|
||||
- [x] path traversal + symlink tests (`safe_test.go`)
|
||||
|
||||
---
|
||||
|
||||
### Phase 3 — HTTP handlers
|
||||
|
||||
| # | Действие | Файлы |
|
||||
|---|----------|-------|
|
||||
| 3.1 | Регистрация маршрутов | `internal/httpapi/routes.go` или `routes_runtime_logs.go` |
|
||||
| 3.2 | Handlers | `internal/httpapi/handlers_runtime_logs.go` |
|
||||
| 3.3 | `actorPrefix(a)` как в maintenance | reuse from `routes_maintenance.go` |
|
||||
| 3.4 | Handler tests | `internal/httpapi/handlers_runtime_logs_test.go` |
|
||||
|
||||
**Роли:** list/tail/audit — `viewer+`; cleanup — `operator+`.
|
||||
|
||||
**Checklist Phase 3:**
|
||||
- [x] `go test ./internal/httpapi/... -run RuntimeLogs` (Windows: без `-race`, CGO disabled)
|
||||
- [x] `scripts/lint-go.ps1` exit 0
|
||||
- [x] lint-httpapi gates (ERR-01, ARCH-01) — проверено grep
|
||||
|
||||
---
|
||||
|
||||
### Phase 4 — Deploy (compose)
|
||||
|
||||
| # | Действие | Файлы |
|
||||
|---|----------|-------|
|
||||
| 4.1 | Bind mount runtime-logs → evobgp-all | `deploy/compose/stack.microvps-full.yaml`, `docker-compose.microvps-full.yaml` |
|
||||
| 4.2 | Env `EVOBGP_RUNTIME_LOGS_DIR=/opt/evobgp/runtime-logs` | compose env |
|
||||
| 4.3 | `EVOBGP_SERVICE=evobgp-all` (если ещё не задан) | compose |
|
||||
| 4.4 | Комментарий в quickstart / manual | `docs/quickstart.md` или `docs/manual.md` |
|
||||
|
||||
**Пример mount:**
|
||||
```yaml
|
||||
volumes:
|
||||
- ${EVOBGP_RUNTIME_LOGS_HOST_DIR:-./runtime-logs}:/opt/evobgp/runtime-logs:rw
|
||||
environment:
|
||||
EVOBGP_RUNTIME_LOGS_DIR: /opt/evobgp/runtime-logs
|
||||
```
|
||||
|
||||
**Checklist Phase 4:**
|
||||
- [x] dev: `./runtime-logs` рядом с compose (`EVOBGP_RUNTIME_LOGS_HOST_DIR` default)
|
||||
- [x] prod: `/opt/evobgp/runtime-logs` на хосте (через `EVOBGP_RUNTIME_LOGS_HOST_DIR` в `.env`)
|
||||
- [x] `stack.microvps-full.yaml` + `docker-compose.microvps-full.yaml` — mount + env на `evobgp-all`
|
||||
- [x] `.env.stack.microvps-full.example`, `docs/quickstart.md`, `docs/manual.md`
|
||||
|
||||
---
|
||||
|
||||
### Phase 5 — Web UI: Tenant settings module
|
||||
|
||||
**Цель:** отдельный модуль tenant-настроек; `/settings` остаётся frontend-only.
|
||||
|
||||
| # | Действие | Файлы |
|
||||
|---|----------|-------|
|
||||
| 5.1 | Новый route | `web/src/routes/tenant-settings/+page.svelte` |
|
||||
| 5.2 | Компонент-обёртка с Tabs | `web/src/lib/components/tenant-settings/TenantSettingsPage.svelte` |
|
||||
| 5.3 | Перенос логики из Operations | refactor `OperationsSystemSettingsTab` → `TenantRevisionSettingsCard.svelte` |
|
||||
| 5.4 | Перенос BIRD | refactor `BirdSettingsForm` → `TenantBirdSettingsCard.svelte` |
|
||||
| 5.5 | Custom KV card | `TenantAdditionalSettingsCard.svelte` |
|
||||
| 5.6 | Nav: добавить пункт (main или bottom) | `web/src/lib/ui/app/layout/nav.ts` |
|
||||
| 5.7 | Убрать tab `system` из Operations | `web/src/routes/operations/+page.svelte` |
|
||||
| 5.8 | Network: заменить форму на Card-summary + link | `web/src/routes/network/+page.svelte` |
|
||||
| 5.9 | Обновить ссылки в docs strings / empty states | grep `tab=system`, `BirdSettingsForm` |
|
||||
|
||||
**Структура tenant module (предложение для creative CP-1):**
|
||||
```
|
||||
/tenant-settings
|
||||
├─ BIRD (bird_*)
|
||||
├─ Ревизии (revision_retention_minutes)
|
||||
└─ Дополнительно (custom KV, operator)
|
||||
```
|
||||
|
||||
**Checklist Phase 5:**
|
||||
- [x] `npm run check && npm run lint`
|
||||
- [x] `/settings` без tenant-форм
|
||||
- [x] `/tenant-settings` с Tabs BIRD / Ревизии / Дополнительно
|
||||
- [x] nav «Параметры»; Operations без tab system; Network summary + link
|
||||
|
||||
---
|
||||
|
||||
### Phase 6 — Web UI: Runtime logs
|
||||
|
||||
| # | Действие | Файлы |
|
||||
|---|----------|-------|
|
||||
| 6.1 | API client | `web/src/lib/runtime-logs/runtime-logs-api.ts` |
|
||||
| 6.2 | Tab в Monitoring | `web/src/lib/components/monitoring/RuntimeLogsTab.svelte` |
|
||||
| 6.3 | Подключить tab | `web/src/routes/monitoring/+page.svelte` |
|
||||
| 6.4 | Таблица файлов (size, mtime) | `AppDataTable` |
|
||||
| 6.5 | Preview dialog | `ScrollPreBlock` + tail API |
|
||||
| 6.6 | Cleanup | `ConfirmDialog` + DELETE sync |
|
||||
| 6.7 | Sub-tab или section: Cleanup audit | таблица `GET /v1/runtime-logs/cleanup-audit` |
|
||||
| 6.8 | 503 empty state | «Доступно только на evobgp-all с volume» |
|
||||
|
||||
**Checklist Phase 6:**
|
||||
- [x] `npm run check && npm run lint`
|
||||
- [x] `/monitoring?tab=runtime-logs` + nested files/audit
|
||||
|
||||
---
|
||||
|
||||
### Phase 7 — Integration, docs, QA
|
||||
|
||||
| # | Действие |
|
||||
|---|----------|
|
||||
| 7.1 | `docs/api.md` — новые endpoints |
|
||||
| 7.2 | `docs/manual.md` — tenant-settings + runtime logs |
|
||||
| 7.3 | `go test ./... -race -count=1` |
|
||||
| 7.4 | E2E manual: list → tail → truncate → audit row |
|
||||
|
||||
**Checklist Phase 7:**
|
||||
- [x] `docs/api.md` — секция RuntimeLogs
|
||||
- [x] `docs/manual.md` — Web UI tenant-settings + runtime logs
|
||||
- [x] `go test ./... -count=1` exit 0 (Windows: без `-race`, CGO disabled)
|
||||
- [x] `npx @redocly/cli lint docs/openapi.yaml`
|
||||
- [x] `npm run check && npm run lint`
|
||||
- [x] `scripts/lint-go.ps1`
|
||||
- [ ] E2E manual на prod/staging (см. ниже)
|
||||
|
||||
**E2E manual (оператор на evobgp-all с volume):**
|
||||
1. `GET /v1/runtime-logs/files` → 200, список `*.log`
|
||||
2. `GET /v1/runtime-logs/files/evobgp-all.log?lines=50` → content
|
||||
3. UI: Monitoring → Файловые логи → preview
|
||||
4. `DELETE ...?mode=truncate` (operator) → 200 + audit_id
|
||||
5. `GET /v1/runtime-logs/cleanup-audit` → новая строка
|
||||
6. `/tenant-settings` — BIRD + revision сохраняются через PATCH
|
||||
|
||||
---
|
||||
|
||||
## Dependency Graph
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
P0[Phase 0 Creative] --> P1[Phase 1 OpenAPI+store]
|
||||
P1 --> P2[Phase 2 FS layer]
|
||||
P2 --> P3[Phase 3 HTTP]
|
||||
P3 --> P4[Phase 4 Deploy]
|
||||
P0 --> P5[Phase 5 Tenant UI]
|
||||
P3 --> P6[Phase 6 Runtime logs UI]
|
||||
P4 --> P6
|
||||
P5 --> P7[Phase 7 QA]
|
||||
P6 --> P7
|
||||
```
|
||||
|
||||
**Параллелизация:** Phase 5 (tenant UI) можно начинать после Phase 0, не дожидаясь runtime logs backend.
|
||||
|
||||
---
|
||||
|
||||
## Risks & Mitigations
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
|------|--------|------------|
|
||||
| Path traversal | Critical | basename only, allowlist, `filepath.Clean` + root check |
|
||||
| Sync cleanup блокирует HTTP worker | Medium | лимит размера файла для DELETE; timeout context; документировать |
|
||||
| evobgp-api без volume | Low | 503 + UI empty state |
|
||||
| Дублирование settings forms | Medium | Phase 5 удаляет старые вхождения |
|
||||
| reference compose (не all) | Low | FS API disabled; документировать |
|
||||
|
||||
---
|
||||
|
||||
## Creative Phases Required
|
||||
|
||||
- [x] **CP-1 uiux** — `creative-tenant-settings-ui.md` ✅ Tabs `/tenant-settings`, nav «Параметры»
|
||||
- [x] **CP-2 uiux** — `creative-runtime-logs-ui.md` ✅ Monitoring tab `runtime-logs` + sub-tabs files/audit
|
||||
- [x] **CP-3 algorithm** — `creative-runtime-logs-cleanup.md` ✅ truncate default, max 512MiB, tail 200/2000 lines, 256KiB
|
||||
- [x] **CP-4 architecture** — `creative-runtime-logs-path-safety.md` ✅ regex + EvalSymlinks + root prefix check
|
||||
|
||||
---
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [x] `/settings` — только frontend (токен, тема)
|
||||
- [x] `/tenant-settings` — все tenant KV (BIRD + revision + custom)
|
||||
- [x] Operations без tab `system`; Network без полной BIRD-формы (summary + link)
|
||||
- [x] Runtime logs: list, tail, sync cleanup на evobgp-all (UI)
|
||||
- [x] Audit cleanup в БД + просмотр в UI
|
||||
- [x] `EVOBGP_RUNTIME_LOGS_DIR`, volume в compose
|
||||
- [x] redocly lint, go test, web check+lint
|
||||
|
||||
---
|
||||
|
||||
## Status Checklist
|
||||
|
||||
- [x] VAN
|
||||
- [x] PLAN
|
||||
- [x] CREATIVE (4 docs)
|
||||
- [x] BUILD Phase 1 (OpenAPI + migration + store)
|
||||
- [x] BUILD Phase 2 (FS layer + config)
|
||||
- [x] BUILD Phase 3 HTTP handlers
|
||||
- [x] BUILD Phase 4 Deploy (compose)
|
||||
- [x] BUILD Phase 5 Tenant settings UI
|
||||
- [x] BUILD Phase 6 Runtime logs UI
|
||||
- [x] BUILD Phase 7 (docs + QA)
|
||||
- [ ] VAN
|
||||
- [ ] PLAN
|
||||
- [ ] CREATIVE (если Level 3–4)
|
||||
- [ ] BUILD
|
||||
- [ ] REFLECT
|
||||
- [ ] ARCHIVE
|
||||
|
||||
---
|
||||
|
||||
## Key Files (reference)
|
||||
|
||||
**Settings today:**
|
||||
- `web/src/routes/settings/+page.svelte` — frontend-only
|
||||
- `web/src/routes/tenant-settings/+page.svelte` — tenant KV
|
||||
- `web/src/lib/components/tenant-settings/*` — BIRD / revision / additional cards
|
||||
- `internal/httpapi/routes_crud.go` — settings handlers (unchanged contract)
|
||||
|
||||
**Runtime logs today:**
|
||||
- `deploy/compose/stack.microvps-full.yaml` — `stack-runtime-logs`, `./runtime-logs`
|
||||
|
||||
**Patterns:**
|
||||
- `internal/httpapi/routes_maintenance.go` — audit list, actor_prefix
|
||||
- `migrations/postgres/000025_*` — config audit table shape
|
||||
|
||||
Reference in New Issue
Block a user