# Enterprise Clean Deployment (internal-only) Для разворота в корпоративной сети используйте профиль enterprise clean: - очищенный дистрибутив без test/demo/load-test данных; - запрет внешних интернет-источников; - загрузка ресурсов только с внутренних серверов компании; - обязательная блокирующая проверка clean/compliance перед выпуском. ## Операционный workflow (CLI/API/TUI) ### 1) Headless flow через CLI (рекомендуется для CI/CD) ```bash cd backend # 1. Регистрация кандидата .venv/bin/python3 -m src.scripts.clean_release_cli candidate-register \ --candidate-id 2026.03.09-rc1 \ --version 1.0.0 \ --source-snapshot-ref git:release/2026.03.09-rc1 \ --created-by release-operator # 2. Импорт артефактов .venv/bin/python3 -m src.scripts.clean_release_cli artifact-import \ --candidate-id 2026.03.09-rc1 \ --artifact-id artifact-001 \ --path backend/dist/package.tar.gz \ --sha256 deadbeef \ --size 1024 # 3. Сборка манифеста .venv/bin/python3 -m src.scripts.clean_release_cli manifest-build \ --candidate-id 2026.03.09-rc1 \ --created-by release-operator # 4. Запуск compliance .venv/bin/python3 -m src.scripts.clean_release_cli compliance-run \ --candidate-id 2026.03.09-rc1 \ --actor release-operator ``` ### 2) API flow (автоматизация через сервисы) - V2 candidate/artifact/manifest API: - `POST /api/clean-release/candidates` - `POST /api/clean-release/candidates/{candidate_id}/artifacts` - `POST /api/clean-release/candidates/{candidate_id}/manifests` - `GET /api/clean-release/candidates/{candidate_id}/overview` - Legacy compatibility API (оставлены для миграции клиентов): - `POST /api/clean-release/candidates/prepare` - `POST /api/clean-release/checks` - `GET /api/clean-release/checks/{check_run_id}` ### 3) TUI flow (тонкий клиент поверх facade) ```bash cd /home/busya/dev/ss-tools ./run_clean_tui.sh 2026.03.09-rc1 ``` Горячие клавиши: - `F5`: Run Compliance - `F6`: Build Manifest - `F7`: Reset Draft - `F8`: Approve - `F9`: Publish - `F10`: Refresh Overview Важно: TUI требует валидный TTY. Без TTY запуск отклоняется с инструкцией использовать CLI/API. Типовые внутренние источники: - `repo.intra.company.local` - `artifacts.intra.company.local` - `pypi.intra.company.local` Если найден внешний endpoint, выпуск получает статус `BLOCKED` до исправления. ## Docker release для изолированного контура Текущий `enterprise clean` профиль уже задаёт policy-level ограничения для внутреннего контура. Следующий логичный шаг для релизного процесса — выпускать не только application artifacts, но и готовый Docker bundle для разворота без доступа в интернет. Целевой состав offline release-пакета: - `backend` image с уже установленными Python-зависимостями; - `frontend` image с уже собранным SvelteKit bundle; - `postgres` image или внутренний pinned base image; - `docker-compose.enterprise-clean.yml` для запуска в air-gapped окружении; - `.env.enterprise-clean.example` с обязательными переменными; - manifest с версиями, sha256 и перечнем образов; - инструкции по `docker load` / `docker compose up` без обращения к внешним registry. Рекомендуемый workflow для такого релиза: ```bash # 1. Собрать образы в подключённом контуре ./build.sh bundle v1.0.0-rc2-docker # Результат: dist/docker/ # backend.v1.0.0-rc2-docker.tar.xz # frontend.v1.0.0-rc2-docker.tar.xz # postgres.v1.0.0-rc2-docker.tar.xz # manifest + sha256sums + docker-compose.enterprise-clean.yml + .env.enterprise-clean.example # 2. Передать dist/docker/* в изолированный контур # 3. Импортировать образы локально (распаковка на лету) xz -dc dist/docker/backend.v1.0.0-rc2-docker.tar.xz | docker load xz -dc dist/docker/frontend.v1.0.0-rc2-docker.tar.xz | docker load xz -dc dist/docker/postgres.v1.0.0-rc2-docker.tar.xz | docker load # 4. Подготовить env из шаблона cp dist/docker/.env.enterprise-clean.example .env.enterprise-clean # 4a. Для первого запуска задать bootstrap администратора # INITIAL_ADMIN_CREATE=true # INITIAL_ADMIN_USERNAME= # INITIAL_ADMIN_PASSWORD= # 5. Запустить только локальные образы docker compose --env-file .env.enterprise-clean -f dist/docker/docker-compose.enterprise-clean.yml up -d ``` Для легковесного all-in-one образа (без Playwright, **~104 MB** вместо 575 MB): ```bash # Сборка ./build.sh bundle:light v1.0.0 # Результат: # dist/docker/ss-tools.v1.0.0.tar.xz (×5.5 меньше за счёт xz -9) # dist/docker/docker-compose.light.yml # dist/docker/manifest-light.v1.0.0.txt # dist/docker/sha256sums-light.v1.0.0.txt # Загрузка и запуск: xz -dc dist/docker/ss-tools.v1.0.0.tar.xz | docker load docker compose -f dist/docker/docker-compose.light.yml up ``` Bootstrap администратора выполняется entrypoint-скриптом внутри backend container: - если `INITIAL_ADMIN_CREATE=true`, контейнер вызывает [`create_admin.py`](backend/src/scripts/create_admin.py) перед стартом API; - если администратор уже существует, учётная запись не меняется; - теги в [`.env.enterprise-clean.example`](.env.enterprise-clean.example) должны совпадать с фактически загруженными образами `ss-tools-backend:v1.0.0-rc2-docker` и `ss-tools-frontend:v1.0.0-rc2-docker`; - после первого входа пароль должен быть ротирован, а `INITIAL_ADMIN_CREATE` возвращён в `false`. Ограничения для production-grade offline release: - build не должен тянуть зависимости в изолированном контуре; - все base images должны быть заранее зеркалированы во внутренний registry или поставляться как tar; - runtime-конфигурация не должна ссылаться на внешние API/registry/telemetry endpoints; - clean/compliance manifest должен включать docker image digests как часть evidence package. Практический план внедрения: - pinned Docker image tags и отдельный `enterprise-clean` compose profile добавлены; - unified `build.sh bundle ` добавлен для `build -> save -> checksum` (заменил `scripts/build_offline_docker_bundle.sh`); - следующим шагом стоит включить docker image digests в clean-release manifest; - следующим шагом стоит добавить smoke-check, что compose-файлы не содержат внешних registry references вне allowlist.