Голосовые системы

Ревью Chat Agent и связанных стеков Monitorsoft

Дата: 29.10.2026. Режим: чтение исходников, истории, корпоративных требований и существующего CI. Изменений проектов, CW, registry, CI или runtime не выполнялось.

Вывод: проверенные репозитории нельзя признать соответствующими корпоративному профилю целиком. Основные проблемы — секреты и журналирование, несколько конкурирующих способов поставки, остатки старого ASR, избыточные команды выпусков и расходящаяся документация. Сами отдельные GPU-сервисы, бинарный аудиотранспорт и проверки целостности не являются лишними.

Материалы:

Что именно проверено

Репозиторий SHA main Tracked-файлов Профиль
rag-stack dee68c4872a2 30 Поставка нескольких стеков
webrtc-komaroff b19930bdfcb9 677 Monorepo приложений + stack
py_faster_whisper d6e12511bd3e 174 ASR/file services + GPU recipes + stack
document-ingestor 131b14c9cc61 31 Ruby service
embedder 2eac40d6b2ab 20 Ruby service
context-retriever 34657145f3f2 28 Ruby service

Для каждого репозитория проверен весь tracked-состав, build/deploy manifests и точки входа. Все найденные .drs прочитаны; основные прикладные пути, обращения между сервисами, хранение, авторизация и кандидаты на удаление разобраны по коду. Для Python, shell и JSON выполнены 322 проверки синтаксиса/разбора без ошибок. Это не означает ручное доказательство корректности каждой строки или выполнение всей функциональной регрессии.

Remote main повторно проверен: все шесть SHA совпадали со снимками. Пользовательские изменения в основных checkout и исходнике CW сохранены. Repowise использован как навигатор: ASR-индекс соответствует SHA, индекс Chat Agent отстаёт на один commit; выводы сверены с текущими файлами. Автоматически безопасных удалений Repowise не подтвердил.

Граница требований. Свежий versioned bundle получен из youtrack-agent на 3234ebf660472a97291b2d51b1cd527c38fff1f4. Он отличается от установленного CW. Живое содержимое статьи CS-A-263 браузерный инструмент прочитать не смог; тождество bundle сегодняшней статье CS не доказано. Нормы и это ограничение подробно указаны в requirements.md. Конфликтующие формулировки о версиях не использованы как повод менять проекты.

Граница runtime. Ни Swarm specs, ни контейнеры, ни внешняя доступность ingress в этом ревью не проверялись. Ниже «объявлен сервис» означает декларацию Git; «успех CI» — существующий результат GitLab. Образ стороннего сервиса не доказывает его фактическую версию или содержимое. Исходники третьих сторон — NATS proxy, vendor LinTO, vLLM, Ollama, ComfyUI и платформы — целиком не ревьюились.

Замечания, требующие первоочередного исправления

R01 — Секреты находятся в stack-репозитории

P1 · подтверждено исходниками. В stack/rag-stack.drs и stack/llm-models.drs есть буквальные значения учётных данных БД/NATS, leaf NKey и Hugging Face token. Часть значений остаётся даже в закомментированных конфигурациях. Значения в этот отчёт не перенесены.

HF token является внешним credential, а shared NATS/leaf credentials не относятся автоматически к разрешённому локальному исключению. Явное решение владельца о хранении этой категории в Git не найдено. Для отдельного непереиспользуемого пароля внутренней тестовой БД корпоративная норма допускает узкое исключение — поэтому не каждый литерал объявлен нарушением. Удаление строки из последнего commit не удаляет её из истории. Будущая правка: классифицировать значения, использовать существующий разрешённый канал для внешних/shared секретов, затем отдельно согласовать их ротацию. Проверка валидности или использование обнаруженных секретов не выполнялись.

R02 — Document Ingestor пишет credential-bearing URL в лог

P1 · подтверждено исходниками. src/config.ru журналирует полный nats_url, а stack/rag-stack.drs формирует его с логином и паролем. При подключении по этой декларации credentials попадут в журнал приложения. Наличие их в текущем хранилище логов не проверялось.

Достаточно оставить событие подключения и адрес без userinfo. Полный URL не нужен для диагностики. В RAG NATS также включены debug и trace (stack/rag-stack.drs, stack/llm-models.drs); необходимость постоянного подробного журналирования не подтверждена, риск записи payload требует отдельной проверки.

R03 — HTTP ingress защищён непоследовательно

P1 для доступных извне маршрутов · объявленная конфигурация подтверждена. В rag-stack.drs у document_ingestor, nats_nui и open_webui есть Slim Auth, а у embedder, context_retriever, nats_ui, pgweb_rag — нет корпоративного ForwardAuth. Basic Auth не является его заменой. stack/rag-stack.drs, stack/rag-stack.drs, stack/rag-stack.drs.

У nats_proxy_ollama и nats_proxy_vllm middleware установлен только на дополнительный /observability, основной HTTP ingress объявлен отдельно без него: stack/rag-stack.drs, stack/rag-stack.drs. В H100-стеках похожая ситуация с HTTP LinTO, vLLM/codex2vllm, Open WebUI, ComfyUI и diarization endpoints.

Сначала классифицировать требуемую доступность каждого маршрута. У внешнего HTTP применить установленный корпоративный контракт; у ненужного внешнего маршрута убрать ingress. Не распространять правило HTTP ForwardAuth автоматически на NATS TCP, WebSocket-аутентификацию или межсервисный доступ. Фактическая внешняя достижимость и возможная прикладная авторизация здесь не подтверждены.

R04 — Общий deploy может вернуть старые версии и затронуть соседние стеки

P1 · подтверждён конфликт декларации и адресной поставки. stack/Dockerfile.deploy всегда применяет четыре стека с --prune. При этом stack/llm-models.drs задаёт старый VOICE_CHAT_IMAGE_TAG=main:0.0.12, используемый HTTP LinTO и прежним STT bridge. Общая CI-команда не передаёт этот override (.gitlab-ci.yml). У vLLM декларация и специальный metrics-release также имеют разные источники выбора image.

Адресные release-скрипты обновляют service spec, но не приводят эти декларации к тому же желаемому состоянию. Следующий полный deploy снова применит значения .drs. Это риск отката и возврата выведенных из эксплуатации компонентов, а не доказательство того, что откат уже произошёл.

Нужен один актуальный декларативный источник на каждый стек и один согласованный способ обычного выпуска. Разные стеки оставить разными целями. Внешние volumes/сети и их физические имена сохранять. Не лечить проблему новым оркестратором.

R05 — Обычный deploy и адресные release могут конкурировать

P2 · подтверждено CI. В .gitlab-ci.yml ASR и vLLM имеют отдельные resource_group, а исторический четырёхстековый deploy не использует ту же блокировку. Ручной режим сам по себе не исключает одновременное применение к одному H100/стеку. Предусмотреть единственного writer для пересекающихся целей; не сериализовать все независимые сервисы без необходимости.

R06 — Старый embedder может давать ложный зелёный тест

P2 · подтверждено wrapper. docker/Dockerfile.build завершает тестовую ветку выражением (... || true) и не обеспечивает передачу кода отказа тестового контейнера. Ошибка docker-compose или контейнера может быть скрыта. В том же wrapper есть env и shell tracing (строки 10–11), что создаёт ненужную поверхность вывода окружения CI.

Зелёный pipeline 5420 поэтому не равен доказательству прохождения функциональных тестов. Учитывая отсутствие функционального embedder API (R12), сначала решить судьбу самого сервиса; не модернизировать пустой сервис только ради зелёной таблицы.

Поставка и оформление репозиториев

R07 — Несколько release-путей всё ещё имеют неограниченное ожидание

P2 · подтверждено исходниками. stack/vllm_release.rb вызывает Open3.capture3('docker', ...) без timeout. Внешние deadlines в циклах не прервут зависший pull, inspect или exec. check_neighbors сравнивает не только config, но и task IDs (строки 72–75, 103–108): независимый restart соседа способен провалить успешный target release.

В stack/deploy.sh весь dry-stack ... --prune повторяется до пяти раз после любой ошибки, без выяснения частично применённого состояния. Это противоречит принятому для этой задачи правилу не повторять deploy вслепую.

У адресных ASR/Chat Agent release уже есть DeliveryCommand с ограничением времени и объёма вывода. Он одинаков в трёх repos. Для будущей правки сначала удалить исторические режимы; оставшиеся вызовы ограничить существующим механизмом. Не создавать четвёртую реализацию тайм-аутов.

R08 — Корпоративный build-контракт заменён проектными ответвлениями

P2 · отклонение от профиля. docker/Dockerfile.build и docker/Dockerfile.build запускают собственные build.sh/build-images.sh. В их build-labels цепочке отсутствует штатный changed; выбор воспроизводится проектными таблицами фаз и дополнительными manifests. Последний опубликованный service-шаблон сохраняет changed → gitlab → set_version → to_dockerfiles → to_compose → Bake → Trivy → push.

Наличие специальных code-only образов и адресной поставки ранее явно согласовано пользователем. Само это требование не ошибка. Проблема — дополнительный параллельный механизм отбора и разросшиеся legacy-ветки. Вернуть один build-manifest и корпоративный контракт там, где он покрывает реальный сценарий; code-only runtime base и его проверку совместимости сохранить. Нельзя просто скопировать свежий template поверх рабочих Dockerfile.

R09 — Build-manifests смешаны с локальным runtime и повторяются

P2 · профиль/сопровождение. docker/docker-compose.yml включает готовые runtime NATS-сервисы в основной build-manifest. В docker/docker-compose.yml сборка смешана с локальными ports/env/volumes, а альтернативные streaming-* и linto-* manifests повторяют часть описаний.

У Chat Agent уже хорошо выделены src_<service> и additional_contexts общего кода — это сохранить. LinTO собирается из корня ASR repo; его реальные inputs стоит выделить, не разрывая code-only base-контракт. Локальный runtime вынести из публикуемого build-manifest. Три ASR image-имени используют один bridge Dockerfile/context: это кандидат на один опубликованный образ с разными командами, но независимые runtime services объединять не требуется.

R10 — Формат версий и версии корпоративных инструментов расходятся с профилем

P2. src_postgres/.version Chat Agent содержит 1.0.0, корневая .version ASR — 1.2.2. Корпоративный формат исходного файла — major.minor, третью часть добавляет CI. Остальные десять найденных .version имеют две части.

На 29.10 опубликованы StackServiceBase 0.0.111, Dry Stack 0.1.62, build-labels 0.0.85. В Ruby приложениях SSB: document-ingestor/context-retriever 0.0.110, embedder 0.0.49. В ASR build используются build-labels 0.0.65, Dry Stack 0.1.16; разные deploy images закрепляют 0.1.53/0.1.60. Для 0.1.53 есть локальный monkey patch самого gem: stack/Dockerfile.deploy и Dockerfile.live-bridge-deploy.

Различие номера версии не доказывает несовместимость или уязвимость. Нужна проверенная актуализация корпоративных gems и удаление уже ненужного патча. Для неподдержанных Python/framework-частей не применять Ruby runtime-контракт буквально. Публичные версии проверены по API RubyGems; совместимость обновлений не тестировалась.

R11 — Десятки исторических feature-команд остаются обычным CI-интерфейсом

P2 · подтверждено. В .gitlab-ci.yml и более ранних блоках есть отдельные build/refresh для Monitor, Chrome, Widget, WebMCP, UI, ASR timings и notes. Одновременно строки 683–697 уже предоставляют build component / refresh component.

Необходимо оставить один понятный обычный выпуск по компоненту. Реально нужные repair/retirement — отдельный maintenance. Обычные проверки Python/frontend/Ruby/dialog/browser NATS не удалять: это разные контрактные поверхности. Удаление псевдонимов выполнить вместе с таблицами action/phase в chat_nats_release.rb, filter-build-phase.rb, документацией и их тестами.

Лишнее и незавершённое в сервисах

R12 — embedder не реализует embedding

P2 · подтверждено кодом всех 20 tracked-файлов. src/config.ru содержит root, /api/foo и демонстрационный /api/create; production embedding handler и подписка отсутствуют. Неиспользуемый download_file остался ниже. Настоящий vectorize.request обрабатывает src/config.ru, а src/context_search.rb обращается туда.

embedder — сильный кандидат на исключение из RAG stack и архивирование repo после проверки внешних потребителей и runtime image. В текущем проверенном пути он не нужен. Не переносить туда рабочий embedding только ради оправдания уже созданного сервиса.

R13 — В декларациях ASR сохранились неиспользуемые streaming-настройки

P2 · подтверждено. WHISPER_STREAM_ENV и LINTO_WS_URL в stack/stack.drs продолжают передаваться batch bridge. stack/live_bridge_release.rb специально добавляет/проверяет WebSocket LinTO URL; нынешний batch-код его не читает.

В stack/llm-models.drs всё ещё объявлен старый bridge inference.whisper.stream.*, связанный с vendor WebSocket LinTO. Его diarization URLs указывают на llm-models_pyannote_diarization, которого в текущих объявлениях уже нет; актуальная модель находится в отдельном diarization-models.

Убрать старые env/guards в новом пути. Вывод старого service допустим только после проверки независимых подписчиков. Каталог src/streaming_asr и service key webrtc-asr_streaming не удалять по имени: в них сейчас расположен рабочий batch worker.

R14 — Есть четыре конкретных неиспользуемых ASR-модуля

P3 · кандидаты подтверждены поиском вызовов в текущих собственных repos. src/utils/audio_utils.py (22 строки), src/utils/silero_onnx_vad.py (302), src/utils/wire_packet.py (35), src/streaming_asr/compare_timing.py (34) — всего 393 строки. В production-коде, entrypoints и тестах импортеров/вызовов не найдено; ссылки остались в исторических документах.

Удалять адресно после одного тестового прогона затронутого пути. onnxruntime не удалять автоматически вместе с серверным Silero: он есть и в runtime/model dependency graph, включая faster-whisper/LinTO. Browser Silero/WASM, сам resampler и архивная проверка хешей остаются нужными.

R15 — Grafana dashboard описывает удалённые стадии

P2/P3. observability/webrtc-streaming-asr.json запрашивает first_partial, speech_final, endpoint_final, queue_audio. В нынешнем worker есть запись stage=decode и RTF (src/streaming_asr/batch_worker.py), но записи этих старых стадий не найдены.

Файл не является runtime-зависимостью ASR; это ручной dashboard artifact. Сохранить полезные decode/error панели, убрать устаревшие streaming-панели или архивировать весь старый dashboard. Его наличие в Git не доказывает, что он сейчас импортирован в Grafana.

R16 — Document Ingestor запускает неограниченное число потоков

P2 · подтверждён ресурсный риск. Каждый upload вызывает новый Thread.new (src/config.ru). Ограничение 50 MiB относится к одному файлу, общей очереди и числа одновременно выполняемых embedding/extraction нет. При параллельных upload память/CPU и количество потоков не ограничены прикладным кодом.

Минимальная правка — один ограниченный существующим процессом executor/очередь с явным отказом при переполнении. Не вводить новый сервис/брокер. Фактический peak memory и частота upload в runtime не измерялись.

R17 — Файлы загрузок и фоновое выполнение не имеют завершённого lifecycle

P2. src/config.ru сохраняет upload в каталог приложения, путь записывается в PostgreSQL, обработка живёт только в локальном Thread. В DRS ingestor нет volume для этого каталога (stack/rag-stack.drs), в processor нет удаления входного файла после обработки или восстановления незавершённой работы после рестарта.

Следствия: успешные uploads накапливаются в writable layer; при замене контейнера pending/processing записи могут остаться без входного файла и исполнителя. Выбрать явный простой контракт: временный файл с очисткой и корректным failed-status либо сохранение исходника и восстановление по существующей таблице. Не создавать новую таблицу без необходимости.

R18 — Изменение параметров HNSW перестраивает индекс при старте приложения

P2 · риск параллельного старта. src/database_init.rb делает DROP INDEX, затем CREATE INDEX при изменении параметров. Нет координации нескольких процессов, операция не concurrent. Между удалением и завершением создания индекс отсутствует; ошибка прерывает подготовку в промежуточном состоянии.

Прикладная схема действительно принадлежит backend, но её изменение должно быть повторяемым и согласованным. Минимально отделить изменение индекса от обычного старта либо использовать существующий schema-механизм с блокировкой. Runtime rebuild во время ревью не выполнялся.

R19 — Многострочные оболочки и значения без владельца в DRS

P2/P3 · оформление и ownership. В llm-models.drs находятся inline lifecycle Ollama, старые закомментированные полные services, устаревшие env и константы. Новая норма явно оставляет запуск приложения в image/code. nats_bootstrap при этом является отдельным осмысленным инфраструктурным initializer; сам факт его существования не ошибка.

В stack/webrtc.drs и других services вручную задаётся STACK_SERVICE_NAME, который уже формируется платформой. В ряде services повторён replicas: 1. Ссылки собственных образов Chat Agent заканчиваются /main с неявным latest, а не единым явным branch/channel. Нужна нормализация деклараций с сохранением реальных resource constraints, update order, shared volumes и ownership.

R20 — Идентификатор pipeline Front задаётся неверным источником

P2 · подтверждено. stack/webrtc.drs присваивает COM_GITLAB_CI_PIPELINE_IID из CI_PIPELINE_ID. Это разные GitLab identifiers. Кроме того, deployment pipeline может отличаться от pipeline сборки уже опубликованного Front image.

Использовать build metadata для версии образа, отдельный существующий deploy provenance — для поставки. Не подменять build IID значением запуска deploy.

R21 — Изменение otlp.drs не выбирает общий deploy RAG

P2 · подтверждено CI rules. .gitlab-ci.yml перечисляет DRS и даже уже не вызываемый prepare-h100-nvidia-cdi.sh, но не stack/otlp.drs. Изменение только общего overlay не создаст эту deploy job. Нужен один проверенный список реальных входов; не компенсировать расхождение ручным широким повтором pipeline.

R22 — Ремонт NVIDIA/CDI находится рядом с обычной поставкой, но больше не вызывается

P2/P3 · отсутствие штатного caller подтверждено. stack/prepare-h100-nvidia-cdi.sh создавался 07.05.2026 для MIG/CDI/systemd. Скрипт меняет host-конфигурацию; текущий Dockerfile.deploy его не запускает. README продолжает утверждать обратное, CI считает его входом deploy.

Для нормального release файл не нужен. Убрать его из обычного workflow; при необходимости сохранить в явно отделённом maintenance runbook/истории с владельцем. Не запускать его для «проверки» и не менять инфраструктуру.

R23 — Дублирование Ruby NATS-обвязки и тесты-заглушки

P3. Ingestor и retriever содержат копии nats_client.rb и nats_patch_174.rb, включая неиспользуемые Listener/CountLatch/JetStream helpers. Приложениям нужны простые subscribe/request/publish. Сначала удалить неиспользуемую часть; только затем решать, нужен ли общий пакет. Новый общий слой ради двух похожих файлов не требуется.

document-ingestor/src/spec/unit/audio_utils_spec.rb и аналогичный файл embedder проверяют длину массива вместо прикладного поведения. Их можно удалить/заменить. Настоящие integration tests PostgreSQL/NATS в ingestor/retriever сохранить; они не являются лишними тестами.

R24 — Документация и стартовые знания не отражают текущий batch-контур

P2/P3. .knowledge/CW project overlays и часть текущих README всё ещё направляют к старому WebRTC/streaming/server Silero workflow. DOCS/ASR_COMPARE.md описывает уже неиспользуемый CompareTiming; RAG README — неисполняемую подготовку MIG.

Датированные исследования и старые презентации являются историческими материалами, а не автоматически мусором. Нужен один актуальный вход в документацию и явная архивная пометка/место для старых схем. Generated OpenWiki не редактировать вручную. Это уменьшит повторное восстановление уже удалённых механизмов.

R25 — Старый экспорт исходников не исключает настоящие .env

P2/P3 · подтверждено кодом, экспорт не запускался. collect_file_contents.sh собирает содержание файлов в JSON. В default exclude есть .env.example, но нет .env/.env.debug, нет redaction значений. Следовательно, передача обычного каталога с локальными credentials в этот ручной инструмент может включить их в результат.

В штатной сборке и запуске script не используется. Удалить неиспользуемый exporter либо ограничить явным списком tracked безопасных файлов при доказанной потребности. Не сохранять универсальную обвязку ради старого разового сбора контекста.

Что не следует удалять при упрощении

  • webrtc-asr.drs, browser Silero Worker, src/streaming_asr/batch_worker.py: это нынешний рабочий batch-контур, несмотря на старые имена.
  • Core, Agent, LLM, Gateway, Audio Ingress, Front и PostgreSQL имеют различные границы ответственности. Ревью не выявило основания сливать их все в один процесс.
  • Проверки owner/session, целостности PCM, идемпотентности команды, ограничение очереди и ожидание фактического окончания native decode — необходимые гарантии, не фильтрация текста Whisper.
  • Файловая транскрипция, staged/bench/summary/status, diarization shared/isolated и соответствующие transport pairs имеют независимых потребителей. Отказ Chat Agent от streaming не удаляет их.
  • RAG PostgreSQL, ingestor и retriever образуют самостоятельный путь документов. В Chat Agent прямой context.search/vectorize.request caller не найден; это не доказывает, что RAG не используется другими клиентами.
  • Два vLLM receivers имеют общую queue group: это не означает двойное выполнение одного запроса. Польза второго процесса требует runtime-измерения; удалить его по сходству конфигурации нельзя.
  • known_hosts, tests release-helper, license/notice и pinned model assets не являются временными файлами.
  • otlp.drs RAG и ASR побайтово совпадает с опубликованным stack-шаблоном SSB 0.0.111. Его переносить в произвольный новый overlay не нужно.
  • Один stack repo вправе содержать несколько независимых стеков. Отклонение — конфликтующие workflows и устаревшее желаемое состояние, а не само количество .drs.
  • StrictHostKeyChecking no есть также в опубликованном generic stack template. Это платформенное свойство/риск; нельзя выдавать его за уникальное самовольное изменение проекта. Адресные helpers уже используют known_hosts.

Существующий CI — отдельный слой доказательств

Репозиторий Pipeline Статус Выполненные jobs
rag-stack 5481 manual 6 manual, 4 success
webrtc-komaroff 5508 manual 25 created, 1 failed, 20 manual, 5 success
py_faster_whisper 5487 manual 5 created, 8 manual, 5 success
document-ingestor 5419 success 2 success
embedder 5420 success 2 success
context-retriever 5412 success 2 success

В Chat Agent пять jobs проверок имеют success. Статус job не доказывает, что внутри запускался полный suite: impact-selector мог завершить его с сообщением о пропуске. Полные логи всех пяти jobs здесь не аудировались. Отдельный Chrome build job 26712 завершился ошибкой на загрузке artifacts: файлы zip/dist найдены, но runner получил DNS lookup gitlab ... server misbehaving. Это не ошибка TypeScript и не повод переписывать приложение. Runner/DNS не изменялись.

Статус pipeline manual не назван полным зелёным PASS. Успешный deploy job не использован как доказательство текущего runtime. При ревью новые jobs не запускались.

Минимальный порядок будущих правок

  1. Уточнить нормативный снимок CS и перенести подтверждённые изменения в source/runtime CW адресно, сохраняя локальные дополнения и dirty work.
  2. Устранить секреты/credential logging и определить защиту каждого HTTP ingress. Ротация секретов — отдельная согласованная операция.
  3. Сделать .drs единственным актуальным желаемым состоянием, исключить конкурирующих writers и отложенный возврат старого LinTO/STT.
  4. Убрать пустой embedder после проверки потребителей; удалить четыре мёртвых ASR-модуля, старые env/guards и неактуальные dashboard panels.
  5. Оставить один обычный выпуск компонента, отделить maintenance. Сократить manifests/helpers; сохранить code-only образы, bounded calls, already_current и необходимые проверки совместимости.
  6. Привести корпоративный build-контракт/версии в порядок, удалить уже ненужный patch Dry Stack. Проверить фактический selection и один production build Front.
  7. Ограничить ingestion и завершить lifecycle uploads; исправить провенанс и документацию.

Каждый пункт должен уменьшать число действующих путей. Не добавлять orchestration service, универсальный registry обработчиков или новый «слой совместимости». Проверки выполнять по изменённому контракту; полную регрессию — при изменении самого механизма отбора/общего контракта, а не на каждую правку комментария.

Оставшиеся неподтверждённые вопросы

  • Свежесть bundle относительно живой CS-A-263; полноценная синхронизация CS → CW не выполнена.
  • Фактические Swarm specs, digest, активные subscribers, наружная доступность HTTP и реальные потребители legacy services.
  • Полный исходный код vendor/platform images и его соответствие текущим images.
  • Динамическое render всех .drs актуальным Dry Stack: Ruby executable в среде отсутствует; изучен официальный gem/template source, но генератор и deployment не запускались.
  • WER/latency/memory soak и реальная утечка памяти: это не предмет статического PASS, измерения в этом ревью не проводились.
  • Безопасность удаления whole-service/volume требует перечисленных runtime checks. Отсутствие такой проверки не превращено в утверждение «можно удалить прямо сейчас».

Исходник

Скачать Markdown · К материалам исследования