Files
ss-tools/INSTALL.md
busya 4c57789218 fix(mcp): closure-gate remediation rounds 2-5 — unified CoT logging, server.py decomposition, 050 P2 queue closed
Round 2 — P1 MCL + GRACE:
- logger intent-drop repaired across 182 call sites; logging unified repo-wide on the
  intent-first facade (211 direct SSOT log() sites migrated); facade level= support;
  molecular-cot-logging skill synced with the module (.agents -> .kilo).
- EXPLORE/REASON-REFLECT gaps closed: poll-dispatch failure path, exploration fail-closed
  choke point in _finish(), 9 silent mcp_ops_dispatch adapters.
- INV_6: dead agent/app.py edge removed (_llm_health); specs 033/035/036/039 sweep ->
  0 dead edges (5 retargeted to live IDs, 15 tombstoned with successors).
- INV_9 dedupes (TaskDrawer BINDS_TO, vestigial assistantOffset, duplicated @SIDE_EFFECT);
  INV_1: migrations 0014-0016 anchored, exploration_sandbox module-region span fixed.
- Full-suite defect root-caused: leaked DI singleton mocks from test_dependencies_unit ->
  autouse restore fixture + get_session_idle_timeout_minutes hardening (int validation,
  EXPLORE fallback SESSION_POLICY_CONFIG_INVALID).
- Executable pins: tests/test_core/test_logger_wire_format.py (wire fields, misuse proof,
  repo-wide AST sweeps over both forbidden shapes).

Round 3 — server.py decomposition EXECUTED per the binding gate plan
(specs/050-mcp-interface/plans/server-decomposition-gate.md, execution log included):
- 1571 -> 177 LOC: scenario_inputs.py (268), auth.py (238, single _access_token_context
  site), rbac_server.py (393), tools_authoring.py (367), tools_scenario.py (373).
- Addendum E: pre-existing ops_tools.py INV_7 offender split 420 -> 215 + tools_review.py (253).
- Contract IDs frozen, import surface frozen, registration order frozen; monkeypatch seams
  relocated to owning modules (recorded); zero behavior diff.

Round 4 — P2 queue closed:
- Story 5 AC2: HandoffSurface copyable prompt parameterized with dashboard context
  (/agent route forwards objectType/objectId/objectName/envId/route/intent; i18n
  handoff_context_label ru/en; contract + render tests).
- E6 / MCPX-FR-007a: McpTransportGuard enforces server-owned JSON-depth bound (typed
  400 json_depth_exceeded pre-dispatch, iterative fail-closed walker) and per-session
  sliding-window rate limit (typed 429 rate_limited + standard Retry-After); rejections
  create no mutable state. Limits live in McpServerConfiguration.
- SC-005 remnants CLOSED: /api/assistant router unmounted (package retained as MCP parity
  provenance, header records rationale); /api/agent/llm-config REMOVED with in-place
  Tombstone + dead strict service DI deleted; assistant.ts deleted (inbound edge removed
  first); SystemSettings assistant-retention UI + 16 i18n keys removed; .env.example
  7860/GRADIO vars removed (zero consumers verified repo-wide).
- SC-004 + SC-009: exact RBAC catalog pins (admin 47 / analyst 21 / viewer 15 derived from
  the live catalog); mid-flow role revocation hides tools in the next tools/list AND denies
  cached-catalog calls by name on the same identity-only token; mid-flow grant exposes the
  approvals surface without new consent.
- Browser cookie-consent decision recorded (tasks.md T008): not built in 050.

Round 5 — last 050 task + FR-010:
- T008b: Core.EndpointLocality deny-by-default perimeter guard for LLM/VLM provider base_url
  at the create/update choke points (private ranges, enterprise DNS suffixes, all-private
  resolution; fail closed; anti-substring-spoofing; empty URL denied); typed 400
  endpoint_not_local:<reason> pre-persistence; EXPLORE audit line on every denial; env
  escape hatches documented (INSTALL.md "Локальный периметр").
- MCPX-FR-010: MCP_CATALOG_VERSION published as serverInfo.version at initialize;
  deprecated/deprecation_note on McpToolDefinition; [DEPRECATED] marker at the single
  list_tools choke point (entry stays listed/callable one minor cycle); deliberate
  major-bump ritual pinned by test.

Evidence: full backend suite 11243 passed / 240 skipped / 1 xpassed / 0 failed;
frontend vitest 3435 passed / lint 0 errors; MCP slice 103; locality slice 107;
anchor+AST sweeps ALL BALANCED over 138 touched files; 050 tasks.md fully [x] with proof.
2026-09-04 13:07:08 +03:00

21 KiB
Raw Permalink Blame History

Установка и настройка superset-tools

Содержание

Требования

  • Docker (рекомендуется): Docker Engine 24+, Docker Compose v2, 4 GB RAM
  • Локальная разработка: Python 3.9+, Node.js 18+, npm, 2 GB RAM, 5 GB диска

Архитектура

Проект состоит из двух сервисов (внешние ассистенты подключаются через MCP — spec 050):

Сервис Технологии Назначение
backend/ Python FastAPI, SQLAlchemy 2.0, APScheduler, PostgreSQL REST API, бизнес-логика, плагины, MCP-сервер
frontend/ Svelte 5 (Runes), SvelteKit, Vite, Tailwind CSS SPA-клиент
shared/ Python package Общие утилиты (логирование, SSL, LLM HTTP)
superset-tools/
├── backend/                    # REST API (FastAPI)
│   ├── src/
│   │   ├── api/routes/         # 30+ роутов (admin, auth, translate, git, agent...)
│   │   ├── core/
│   │   │   ├── auth/           # JWT, OAuth, API Keys, RBAC
│   │   │   ├── migration/      # Dry-run, risk assessment
│   │   │   ├── task_manager/   # Async jobs, event bus, persistence
│   │   │   ├── superset_client/
│   │   │   ├── logger/         # Structured logging, belief state
│   │   │   └── ...
│   │   ├── models/             # SQLAlchemy модели
│   │   ├── plugins/            # Реализации плагинов
│   │   ├── schemas/            # Pydantic схемы
│   │   ├── services/           # Бизнес-логика
│   │   └── scripts/            # CLI/TUI админ-скрипты
│   └── tests/
├── frontend/                   # SvelteKit SPA
│   ├── src/
│   │   ├── routes/             # 20+ групп страниц
│   │   ├── lib/
│   │   │   ├── api/            # API клиент
│   │   │   ├── auth/           # Auth store, permissions
│   │   │   ├── components/     # UI компоненты
│   │   │   ├── stores/         # Svelte stores
│   │   │   ├── i18n/           # Мультиязычность
│   │   │   └── ...
│   │   └── ...
│   └── tests/
├── shared/                     # Общий Python пакет (ss-tools-shared)
├── docker/                     # Dockerfile, entrypoint, nginx
├── docs/                       # Документация, ADR
├── specs/                      # 40+ feature specifications
├── scripts/                    # Утилиты (coverage, security, build)
├── research/                   # Исследования (mcp-superset)
├── semantics/                  # Семантическая карта кода
├── dist/                       # Релизные бандлы
├── storage/                    # Runtime данные (backups, repos)
├── certs/                      # SSL-сертификаты
└── examples/                   # Примеры интеграции

Технологический стек

Backend: Python 3.9+ (FastAPI 0.126, SQLAlchemy 2.0, APScheduler 3.11), PostgreSQL 16, Authlib, JWT, OpenAI API, GitPython, Playwright, lingua-language-detector

Frontend: Svelte 5 (Runes), SvelteKit 2.49, Vite 7, Tailwind CSS 3, Vitest 4.1, Playwright 1.60

DevOps: Docker & Docker Compose (3 профиля + E2E), GitHub Actions (CI), Nginx (опциональный SSL)

Docker (рекомендуется)

Профили окружения

Система поддерживает несколько профилей через .env файлы:

Профиль Файл Команда
current .env.current docker compose --profile current up --build
master .env.master docker compose --profile master up --build
enterprise-clean .env docker compose -f docker-compose.enterprise-clean.yml up --build
e2e .env.e2e docker compose -f docker-compose.e2e.yml up --build
git clone <repository-url>
cd superset-tools
cp .env.example .env
docker compose --profile current up --build

После запуска:

Offline-бандл

xz -dc dist/docker/superset-tools.20260517.tar.xz | docker load
export POSTGRES_PASSWORD="my-strong-password"
docker compose -f dist/docker/docker-compose.light.yml up -d

Локальная разработка

Backend

cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements-backend.txt
pip install -e ../shared
python3 -m uvicorn src.app:app --reload --port 8000

Frontend

cd frontend
npm install
npm run dev -- --port 5173

Начальная настройка

# Переменные окружения
cp .env.example backend/.env

# Инициализация БД
cd backend && source .venv/bin/activate
python src/scripts/init_auth_db.py

# Создание администратора
python src/scripts/create_admin.py --username admin --password '<temporary-secret>'

Конфигурация

Полный список переменных — в каждом .env.*.example файле.

Основные категории

Категория Переменные Описание
Security AUTH_SECRET_KEY, ENCRYPTION_KEY, SERVICE_JWT JWT-подпись, шифрование данных, сервисный токен для сервисных принципалов
Database DATABASE_URL Единственное PostgreSQL подключение
Admin bootstrap INITIAL_ADMIN_CREATE, INITIAL_ADMIN_USERNAME, INITIAL_ADMIN_PASSWORD, INITIAL_ADMIN_EMAIL Автосоздание admin при первом запуске
LLM OPENAI_API_KEY, ANTHROPIC_API_KEY, LLM_BASE_URL, LLM_MODEL Провайдеры и модели
Features FEATURES__DATASET_REVIEW, FEATURES__HEALTH_MONITOR Включение фич
SSO ADFS_CLIENT_ID, ADFS_CLIENT_SECRET, ADFS_METADATA_URL Active Directory Federation Services
Certificates CERTS_PATH, SSL_KEY_PASSPHRASE, LLM_CA_CERT_URLS PKI для корпоративных сетей
CORS ALLOWED_ORIGINS, FORCE_HTTPS, APP_TIMEZONE Безопасность и регион
Logging ENABLE_BELIEF_STATE_LOGGING, TASK_LOG_LEVEL Структурированное логирование
Ports BACKEND_HOST_PORT, FRONTEND_HOST_PORT, POSTGRES_HOST_PORT Проброс портов Docker

MCP клиент (внешние ассистенты)

Единая точка подключения внешних MCP-клиентов — Streamable HTTP /mcp внутри backend (spec 050). Каталог из 47 инструментов фильтруется по live-RBAC; мутирующие операции проходят через durable approval-гейты.

# 1. Discovery (RFC 9728) — метаданные защищённого ресурса и authorization server
curl http://<host>:8001/.well-known/oauth-protected-resource/mcp
curl http://<host>:8001/.well-known/oauth-authorization-server

# 2. Dynamic Client Registration (нужен Bearer веб-сессии пользователя-владельца)
#    public-клиент (browser PKCE) или confidential (machine, выдаётся client_secret одноразово)
curl -X POST http://<host>:8001/oauth/register \
  -H "Authorization: Bearer <web-jwt>" -H "Content-Type: application/json" \
  -d '{"client_name":"my-mcp","redirect_uris":["http://localhost:9999/cb"],"scope":"mcp:read","client_type":"confidential"}'

# 3a. Machine-клиент: client_credentials → сервисный токен (только read-поверхность каталога)
curl -X POST http://<host>:8001/oauth/token \
  -d "grant_type=client_credentials&client_id=<id>&client_secret=<secret>"

# 3b. Пользовательский клиент: authorization code + PKCE (S256)
#     GET /oauth/authorize?... с Bearer веб-сессии (SPA-mediated consent) → 302 code
#     POST /oauth/token grant_type=authorization_code + code_verifier
# 4. MCP сессия: POST /mcp с Authorization: Bearer <mcp-token>
#    initialize → notifications/initialized → tools/list → tools/call

Альтернатива для доверенных машинных интеграций внутри периметра — SERVICE_JWT (задаётся в .env; композ намеренно падает без него). Gated-инструменты (deploy_dashboard, execute_migration, run_backup, superset-writes, consume_baseline_approval) возвращают approval_required и исполняются только после decide_approval тем же принципалом через серверный поллер. PRODUCTION SQL (superset_execute_sql на PROD-окружении) отклоняется терминально.

Локальный периметр (LLM/VLM/MCP endpoints)

Spec 050 (MCPX-FR-020, T008b): MCP-клиенты и все LLM/VLM-провайдеры по умолчанию расположены внутри enterprise-периметра. PII (дашборды, сэмплы датасетов, маскированные скриншоты) допускается только к локальным провайдерам; credentials/cookies/токены/секреты и raw-пути хранения отвергаются везде (typed secret-exposure rejection, E13).

Deny-by-default на конфигурации провайдера (Admin → LLM Settings): base_url, не являющийся локальным, отклоняется типизированной ошибкой 400 endpoint_not_local:<reason> ДО сохранения. Локальными считаются:

  • host-литералы localhost, 127.*, [::1], 0.0.0.0, host.docker.internal;
  • IP из private/loopback/link-local диапазонов (RFC1918 10/8, 172.16/12, 192.168/16, ULA/loopback IPv6);
  • DNS-имена с enterprise-суффиксами .local, .internal, .lan, .corp, .intranet (split-horizon DNS не требует резолва);
  • DNS-имена, у которых ВСЕ резолвимые адреса приватные;
  • пустой base_url отклоняется (SDK-дефолт указывает на публичное облако).

Нерезолвимое имя = отказ (fail closed). Substring-эвристики не используются: https://api.openai.com/localhost отклоняется по hostname.

Escape hatches (явные, задокументированные, по умолчанию закрыты):

# Полный opt-out периметровой проверки (только для непод perimeter-развёртываний!):
LLM_ALLOW_NONLOCAL_ENDPOINTS=true
# Точечный allowlist публичных хостов (через запятую):
LLM_NONLOCAL_ENDPOINT_ALLOWED_HOSTS=llm.partner.example
# Дополнительные enterprise-суффиксы:
LLM_LOCAL_HOST_SUFFIXES=.enterprise

MCP-транспорт держит свой локальный контур independently: DNS-rebinding protection с локальными дефолтами MCP_ALLOWED_HOSTS/MCP_ALLOWED_ORIGINS, server-owned лимиты тела запроса (4 MiB), JSON-глубины (json_depth_limit=32, typed 400 json_depth_exceeded до dispatch) и per-session rate limit (120 req/60s, typed 429 rate_limited + стандартный Retry-After). Исполнимые пины: tests/test_endpoint_locality.py, tests/test_mcp_transport_limits.py.

Система сборки

build.sh — унифицированная CLI-утилита:

# Сборка и запуск
./build.sh compose                    # docker compose up --build (current profile)
./build.sh compose:master             # docker compose up (master profile)

# Индивидуальные сборки
./build.sh backend                    # backend image only
./build.sh frontend                   # frontend image only

# Offline-бандлы
./build.sh bundle v1.0.0              # полный бандл (все сервисы)
./build.sh bundle:light v1.0.0        # light (backend + frontend)

Артефакты: dist/docker/superset-tools.<version>.tar.xz + sha256sum + manifest.

Тестирование

Makefile (tiered test system)

make test                 # Tier 1: быстрые unit-тесты backend + frontend (<30с)
make test-unit            # Backend unit-тесты с SQLite (без Docker)
make test-frontend        # Frontend vitest-тесты
make test-related F=path  # Tier 2: умный выбор тестов для изменённого файла
make test-integration     # Tier 3: backend integration с testcontainers
make test-e2e             # Tier 3: Playwright E2E (требуется запущенное приложение)
make test-all             # Все тесты (без установки зависимостей)

make lint                 # Все линтеры
make lint-backend         # ruff check
make lint-frontend        # eslint

make coverage             # coverage обоих стеков

Самостоятельный запуск

# Backend тесты
cd backend && source .venv/bin/activate && pytest

# Frontend тесты
cd frontend && npm run test

# Конкретный тест
pytest backend/tests/test_auth.py::test_create_user

E2E тестирование

docker compose -f docker-compose.e2e.yml up --build
cd frontend && npm run test:e2e

Покрытие кода

Сводный отчёт — scripts/coverage-summary.sh:

./scripts/coverage-summary.sh                          # Полный запуск (integration + frontend)
./scripts/coverage-summary.sh --unit                    # Backend unit (SQLite) + frontend
./scripts/coverage-summary.sh --frontend-only           # Только frontend
./scripts/coverage-summary.sh --backend-only --unit     # Только backend
./scripts/coverage-summary.sh --output-dir ./reports/coverage

Результат: coverage-summary/index.html.

Текущие показатели

Стек Тип тестов Процент Покрытие (Stmts)
Backend (unit) 1723 1721/2 48%
Backend (integration) 167 167/0 12%
Frontend 2443 2442/1 99.25%

SSL/TLS конфигурация

Сертификаты для HTTPS (nginx)

Поместите файлы в ./certs/:

Вариант A — отдельные файлы:

./certs/server.crt   # SSL сертификат
./certs/server.key   # Приватный ключ

Вариант B — зашифрованный ключ + пароль:

./certs/server.crt   # SSL сертификат
./certs/server.key   # Приватный ключ (зашифрован, с DEK-Info)
SSL_KEY_PASSPHRASE=my-passphrase

Вариант C — PKCS#12 контейнер:

./certs/server.p12   # Контейнер с сертификатом + ключом
SSL_KEY_PASSPHRASE=my-passphrase

Entrypoint автоматически извлекает .crt и .key из .p12, расшифровывает ключ и передаёт nginx (ключ остаётся в tmpfs контейнера).

Корпоративные CA-сертификаты

Положите .crt/.pem в ./certs/ — entrypoint установит их в системное хранилище Alpine и NSS (Chromium/Playwright). Поддерживаются цепочки (Root → Intermediate).

LLM CA-сертификаты

LLM_CA_CERT_URLS="http://pki.company.com/root-ca.crt http://pki.company.com/intermediate-ca.crt"

Сертификаты скачиваются на старте контейнеров, конвертируются из DER в PEM при необходимости, устанавливаются в системное хранилище.

Диагностика SSL

scripts/check_llm_certs.py                                  # Полная проверка цепочки доверия
scripts/diag_container.py --target your-llm-provider.com:443 # Контейнерная диагностика

Подробнее — ADR-0009. LLM_SSL_VERIFY удалён в 0.2.x — TLS verify всегда включён.

Enterprise Clean Deployment

Разворот в корпоративной сети с очищенным дистрибутивом (без тестовых данных, запрет внешних источников, compliance-проверка):

cp .env.example .env
docker compose --profile enterprise-clean up --build

Поддерживаются CLI, API и TUI flows. Подробнее — docs/enterprise-clean.md.

Авторизация

Два метода аутентификации:

  1. Локальная (username/password) — JWT-токены, RBAC (admin/analyst/viewer)
  2. ADFS SSO — Active Directory Federation Services

Управление: POST /api/admin/users, POST /api/admin/roles.

Мониторинг

  • Dashboard Hub — управление дашбордами с Git-статусом
  • Dataset Hub — управление датасетами с прогрессом маппинга
  • Task Drawer — мониторинг фоновых задач (WebSocket real-time)
  • Unified ReportsGET /api/reports?page=1&page_size=20 (фильтры по статусу, типу, дате)
  • Health Monitor — мониторинг здоровья системы (через FEATURES__HEALTH_MONITOR)
  • Semantic Map — автоматически генерируемая семантическая карта кода (semantics/semantic_map.json)

Спецификации

В specs/ ведётся 40+ feature specifications. Каждая включает: spec.md, research.md, plan.md, contracts/modules.md, data-model.md, checklists/requirements.md, tasks.md.

# Название Описание
011 git-integration-dashboard Git-интеграция дашбордов
017 llm-analysis-plugin LLM-аналитика и валидация
022 sync-id-cross-filters Sync ID cross-filters
023 clean-repo-enterprise Чистый репозиторий для enterprise
033 gradio-agent-chat Gradio/LangGraph AI-агент
034 task-status-center Центр статуса задач
038 dashboard-scenario-model Сценарная модель дашбордов
041 dataset-lineage-blast-radius Lineage и blast radius датасетов

Примеры скриптов

Примеры интеграции с внешними системами (Airflow, CI/CD, cron) — в examples/:

Аутентификация через API Key (X-API-Key), запуск и завершение maintenance-событий.

Утилиты

Скрипт Назначение
coverage-summary.sh Сводный отчёт покрытия
scan_secrets.sh Сканирование секретов
check_llm_certs.py Проверка SSL-сертификатов LLM
diag_container.py SSL-диагностика
find-related-tests.py Поиск тестов по изменённому файлу
pretty_cot.py Форматирование CoT-логов
gen_semantics.py Семантическая карта кода
build_offline_docker_bundle.sh Сборка offline-бандлов

Исследования

  • mcp-superset — MCP-сервер для Apache Superset (137 инструментов, PyPI). Streamable HTTP, SSE, stdio транспорты. Подробнее — research/mcp-superset/.