Миграция на 26.1.0 — catalog-owned-model + LLM-prediction option¶
Этот документ ранее назывался
migration_1_8.mdи описывал переход с helm chart1.7.x(релиз25.4.x) на1.8.x(25.5.x). С релиза26.1.0мы используем сквозную нумерацию — функционально это тот же набор изменений, под унифицированным тегом.
В версии 26.1.0 (исторически — helm chart 1.8.0/1.8.1,
релизы 25.5.0/25.5.1) изменена архитектура каталога
LLM-провайдеров: каждая запись каталога теперь представляет один
валидированный набор (endpoint, ключ, модель). Также администратор
может назначить LLM-провайдер для роли Prediction (раньше — только
встроенный RL Classifier; после chart 1.7.0 / релиза 25.4.0 —
только LLM).
Что изменилось¶
Архитектура¶
- Каталог LLM-провайдеров теперь владеет моделью. Колонка
modelперенесена сrole_provider_assignmentsнаllm_providers(Liquibase 1.8.0/001_provider_owns_model). Каждая строка каталога — один валидированный набор endpoint + API-ключ + модель. - Multi-role конфиги авто-разделяются при миграции: если один провайдер использовался и для prediction, и для explanation с разными моделями — Liquibase автоматически клонирует строку каталога и переназначает роли.
- Test history теперь поддерживает
role='catalog'для catalog-level test (Liquibase 1.8.0/002_test_history_catalog_role). - Cache invalidation между backend и llm-service: при edit провайдера в UI backend
публикует webhook на
/admin/cache-invalidateв llm-service, и тот сбрасывает кэш конфига (избегает stale config в течение TTL).
REST API¶
- Новые admin-only endpoints для CRUD каталога:
GET /api/settings/llm-providers— списокPOST /api/settings/llm-providers— create с type-aware validationPUT /api/settings/llm-providers/{id}— editDELETE /api/settings/llm-providers/{id}— delete с защитами
- Защиты delete:
- 409 Conflict — если провайдер ассоциирован с ролью (нужно сначала переназначить)
- 403 Forbidden — для vendor-managed (резервировано)
- Защиты create/update:
- 400 Bad Request на
protocol=autoдля LLM — требуется явныйollamaилиopenai_compatible.
- 400 Bad Request на
- Новый probe endpoint:
POST /api/settings/providers/test-connection?role=&providerId= - Discovery + test credentials:
POST /api/settings/providers/llm-providers/{discover-models,test-credentials}
Для администратора¶
- В Settings → LLM-провайдеры теперь у каждой строки своя модель (не общая для всех ролей).
- При редактировании провайдера UI требует пройти "Test connection" перед Save (ensures ключ + endpoint валидны).
- Per-role health monitor: prediction и explanation имеют независимые state-слоты (warmup одной роли не сбрасывает другую).
Для пользователя¶
- Возможность выбрать LLM-провайдер для роли Prediction (через UI Settings → role-card prediction).
- Качество триажа TP/FP теперь зависит от выбранной LLM-модели (mistral / DeepSeek / GPT-4o и т.п.). Замеры на AILAB-20 holdout (DeepSeek, deepseek-v4-pro): accuracy 86.5%, precision 83.3%, recall 55.6%, F1 66.7%, FP filter 96.4%.
Для feedback loop¶
- Approve/reject в Feedback queue → AMQP
FeedbackEvent(внутренняя backend очередьappsecsolutions.copilot.feedback) + HTTP forward черезFeedbackProxyControllerв llm-service. - На approve строка копируется в
few_shot_examplesсsource='user-feedback'и используется в next predict prompt того же CWE/lang. - CWE prefix normalization: входящие CWE в форматах
CWE-89,89,cwe-89нормализуются в canonicalCWE-89.
Шаги миграции с v1.7.0 на v1.8.0 — Docker Compose¶
Для Helm — см. параллельный раздел ниже.
1. Backup¶
# Дамп БД
sudo docker exec copilot-postgres pg_dumpall -U postgres > /opt/copilot-backups/pre-1.8.0-$(date +%Y%m%d-%H%M%S).sql
# Также сохраним текущий compose-файл и .env (потребуется для отката на v1.7.0)
sudo cp /opt/copilot/docker-compose.yml /opt/copilot-backups/docker-compose-pre-1.8.0-$(date +%Y%m%d-%H%M%S).yml
sudo cp /opt/copilot/.env /opt/copilot-backups/.env-pre-1.8.0-$(date +%Y%m%d-%H%M%S)
2. Подготовка .env¶
В /opt/copilot/.env добавить:
# v1.8.0 — обязательный секрет для cache-invalidate webhook между backend и llm-service.
# Сгенерировать random 32+ символов.
APPSECSOLUTIONS_COPILOT_INTERNAL_SECRET=<random-32-chars>
# v1.8.0 — TTL кэша провайдер-конфига в llm-service (по умолчанию 300с).
PROVIDER_CONFIG_TTL_SECONDS=300
# v1.8.0 — toggle feedback loop (по умолчанию true).
FEEDBACK_ENABLED=true
Сгенерировать секрет:
3. Pull новых образов¶
4. Восстановить compose-файл (если нужно)¶
docker-compose.yml остался без изменений relative to v1.7.0 — те же сервисы. Но backend
теперь требует новые env vars (см. §2).
5. Запуск + автомиграция¶
Liquibase автоматически применит:
1.8.0/001_provider_owns_model.sql— переноситmodelна каталог, авто-сплит multi-role1.8.0/002_test_history_catalog_role.sql— добавляетrole='catalog'вprovider_test_history
6. Проверка¶
После старта:
# Все 6 контейнеров healthy
sudo docker compose ps
# Liquibase changelog содержит миграции 1.8.0/001 и 002
sudo docker exec copilot-postgres psql -U postgres -d copilot -c \
"SELECT id FROM databasechangelog WHERE filename LIKE '%1.8%';"
# Каталог провайдеров содержит model column
sudo docker exec copilot-postgres psql -U postgres -d copilot -c \
"SELECT id, name, type, protocol, model FROM checks.llm_providers;"
В UI Settings → LLM-провайдеры — у каждой строки видно поле «Модель». В Settings → role-card prediction теперь можно назначать LLM-провайдера (раньше — только RL).
7. Откат (на крайний случай)¶
# Restore из backup
sudo docker compose down
sudo docker exec -i copilot-postgres psql -U postgres < /opt/copilot-backups/pre-1.8.0-*.sql
# Откатить .env (убрать новые переменные) и запустить v1.7.0 образы
Шаги миграции с v1.7.0 на v1.8.0 — Kubernetes (Helm)¶
Для K8s-инсталляций используется официальный chart
appsec-copilot (version 26.1.0,
appVersion 26.1.0). Логически шаги те же, что для Docker Compose, но конфиг едет через
values.yaml, а не через .env.
1. Backup¶
Перед апгрейдом — снимок namespace + дамп Postgres:
# Сохранить текущий helm release manifest (для отката если что)
helm get manifest copilot -n copilot > /tmp/copilot-manifest-pre-1.8.0.yaml
helm get values copilot -n copilot > /tmp/copilot-values-pre-1.8.0.yaml
# Дамп БД (через kubectl exec в pod postgres)
kubectl -n copilot exec -it deploy/copilot-postgresql -- \
pg_dumpall -U postgres > /tmp/pre-1.8.0-pgdump.sql
2. Обновить values.yaml¶
В values.yaml (или в вашем кастомном overrides) добавить новые обязательные
ключи и удалить legacy блоки. Минимальный diff:
backend:
# NEW v1.8.0 — REQUIRED, иначе chart упадёт с fail-fast при `helm upgrade`
# ("backend.internalSecret is required (32+ char shared secret for cache-invalidation
# webhook between backend and llm-service)").
# Generate: openssl rand -base64 32 | tr -d '\n='
internalSecret: "<random-32+chars>"
# NEW v1.8.0 — REQUIRED, master key для AES-256-GCM шифрования provider credentials
# at rest. Без него SecretsCipherConfig упадёт на старте Pod'а.
# Generate: openssl rand -base64 32 | tr -d '\n='
secretsKey: "<random-32-bytes-base64>"
# NEW v1.8.0 — TTL кэша провайдер-конфига на стороне llm-service.
providerConfigTtlSeconds: "300"
# NEW v1.8.0 — унифицированный сервис predict + explain (merge старых
# vul-detect-rl и vul-explainer-cloud).
llmService:
enabled: true
# Образ берётся из chart-defaults `cr.yandex/.../copilot-vul-explainer-cloud-dev:1.8.0`,
# переопределите при необходимости через image.repository / image.tag.
# REMOVE legacy блоки если присутствуют в текущем values:
# vulDetectRl: # fail-fast: "RL Classifier removed in v1.7.0"
# vulExplainer: # fail-fast: "vul-explainer merged into llm-service in v1.6.0"
Параметры по умолчанию для LLM credentials (llmProvider.cloud.llmApiKey / llmModel /
baseUrl) можно оставить пустыми — заполняются после старта через UI Settings →
LLM-провайдеры (catalog-owned-model).
Полный список доступных values с комментариями — в
values.yaml
самого chart'а.
3. helm upgrade¶
# Если ставите впервые из чартового репозитория — добавить helm repo:
helm repo add appsec https://code.appsec.ru/api/v4/projects/<project-id>/packages/helm/stable
helm repo update
# Сам апгрейд:
helm upgrade copilot appsec/appsec-copilot \
--version 26.1.0 \
--namespace copilot \
-f values.yaml
4. Восстановить compose-файл¶
(не применимо — конфигурация полностью описана в values.yaml через chart templates)
5. Запуск + автомиграция¶
Liquibase выполняется автоматически в init-контейнере backend Pod'а при первом старте
v1.8.0 image — те же changesets 1.8.0/001 и 1.8.0/002 (см. §5 Compose).
6. Проверка¶
Имя llm-service в Kubernetes ≠ имя контейнера в Docker Compose
В Helm-чарте 26.1.x сервис llm-service намеренно разворачивается под
legacy-именем appsec-copilot-vul-explainer-cloud (Deployment, Service,
ServiceAccount, Secret — все под этим именем). Это не баг и не отсутствующий
компонент: внутри Pod'а работает новый унифицированный llm-service (predict +
explain), просто k8s-объект пока сохраняет старое имя ради стабильности Service DNS
при helm upgrade. Переименование k8s-ресурсов запланировано отдельной chart-версией.
В мире Docker Compose контейнер уже переименован в copilot-llm-service — поэтому
в installation.md и compose-примерах фигурирует это имя. На Helm
его в kubectl get deploy не будет — ищите appsec-copilot-vul-explainer-cloud.
# Все Pod'ы Running + Ready
kubectl -n copilot get pods
# llm-service в k8s называется appsec-copilot-vul-explainer-cloud (legacy-имя):
kubectl -n copilot get deploy,svc -l copilot.component=llm-service
# ожидается: deployment/appsec-copilot-vul-explainer-cloud + service/...
kubectl -n copilot logs deploy/appsec-copilot-vul-explainer-cloud --tail=20
# ожидается: Uvicorn running on http://0.0.0.0:8000 / Application startup complete
# Liquibase changelog содержит миграции 1.8.0/001 и 002
kubectl -n copilot exec -it deploy/copilot-postgresql -- \
psql -U postgres -d copilot -c \
"SELECT id FROM databasechangelog WHERE filename LIKE '%1.8%';"
# Каталог провайдеров содержит model column
kubectl -n copilot exec -it deploy/copilot-postgresql -- \
psql -U postgres -d copilot -c \
"SELECT id, name, type, protocol, model FROM checks.llm_providers;"
Не переопределяйте URL llm-service вручную на Helm
Не задавайте backend.llmServiceUrl (или LLM_SERVICE_URL) в http://copilot-llm-service:8000
по аналогии с docker-compose .env-примером — в Kubernetes такого Service нет, и backend
потеряет связь с llm-service. Оставьте значение по умолчанию: чарт сам резолвит его в
http://appsec-copilot-vul-explainer-cloud:8000.
UI: тот же, что для Compose — Settings → LLM-провайдеры → у каждой строки видно «Модель»; Settings → role-card prediction теперь принимает LLM-провайдера.
7. Откат (на крайний случай)¶
# Helm rollback на предыдущий revision
helm history copilot -n copilot
helm rollback copilot <previous-revision> -n copilot
# Restore БД из дампа если новые changesets уже применились
kubectl -n copilot exec -it deploy/copilot-postgresql -- \
psql -U postgres < /tmp/pre-1.8.0-pgdump.sql
Известные ограничения¶
- На стенде разработки наблюдалась нестабильность Ollama (ошибка
unable to create sampling context) — это GPU/model-load issue, не код. Если у клиента похожая ошибка на Ollama — проверить GPU-доступ и memory limit. - Cache invalidation webhook требует, чтобы backend мог достучаться до llm-service
по HTTP. В docker-compose это автоматически (overlay network), в k8s/helm — через
Service DNS
llm-service:8000(см. helm chart valuesbackend.llmServiceUrl).
Поддержка¶
По вопросам и проблемам обращайтесь в техническую поддержку SwordFish Security через ваш контактный канал support (email или helpdesk-портал, выданные при поставке).