diff --git a/.env.enterprise-clean.example b/.env.enterprise-clean.example deleted file mode 100644 index bb096ed41..000000000 --- a/.env.enterprise-clean.example +++ /dev/null @@ -1,107 +0,0 @@ -# #region env.enterprise-clean [C:2] [TYPE Module] [SEMANTICS env,docker,enterprise] -# @BRIEF Переменные окружения для docker-compose.enterprise-clean.yml. -# Сервисы собираются из исходников или загружаются из pre-built .tar.xz. -# PostgreSQL запускается в контейнере (сервис db). -# @LAYER Infrastructure -# @RELATION DEPENDS_ON -> [docker-compose.enterprise-clean.yml] -# #endregion env.enterprise-clean - -# ====================================================================== -# PostgreSQL (контейнер) — настройки встроенной БД -# ====================================================================== -# Для использования внешнего PostgreSQL — переопределите POSTGRES_HOST -# и удалите/закомментируйте сервис db в docker-compose.enterprise-clean.yml. -POSTGRES_HOST=db -POSTGRES_PORT=5432 -POSTGRES_DB=ss_tools -POSTGRES_USER=postgres -POSTGRES_PASSWORD=change-me -POSTGRES_HOST_PORT=5432 - -# Однократный универсальный reset старой Alembic-схемы перед baseline. -# Можно оставить true: после применения 0001_baseline последующие старты безопасно пропускают reset. -# Непустая БД без таблицы alembic_version никогда не удаляется автоматически. -RESET_DATABASE_SCHEMA=true - -# ====================================================================== -# Порты хоста -# ====================================================================== -BACKEND_HOST_PORT=8001 -FRONTEND_HOST_PORT=8000 -FRONTEND_SSL_PORT=443 -AGENT_HOST_PORT=7860 - -# ====================================================================== -# Безопасность (ОБЯЗАТЕЛЬНО) -# ====================================================================== -# JWT-ключ подписи токенов — единый для backend и agent. -# Сгенерировать: python3 -c "import secrets; print(secrets.token_urlsafe(32))" -AUTH_SECRET_KEY=change-me-to-a-random-secret-32-chars-min - -# Fernet-ключ шифрования паролей подключений и API-ключей. -# Сгенерировать: python3 -c "import base64,os; print(base64.urlsafe_b64encode(os.urandom(32)).decode())" -ENCRYPTION_KEY=change-me-generate-a-fernet-key - -# Сервисный токен для agent→backend вызовов. -# Сгенерировать: python3 -c "import secrets; print('svc-' + secrets.token_urlsafe(24))" -SERVICE_JWT=replace-with-random-service-secret - -# ====================================================================== -# Сертификаты (корпоративные) -# ====================================================================== -CERTS_PATH=./certs -SSL_KEY_PASSPHRASE= - -# ====================================================================== -# LLM / AI провайдеры -# ====================================================================== -OPENAI_API_KEY= -ANTHROPIC_API_KEY= -# Агент: LLM настройки (если не подтягиваются из FastAPI /api/agent/llm-config) -LLM_API_KEY= -LLM_BASE_URL=https://api.openai.com/v1 -LLM_MODEL=gpt-4o - -# ====================================================================== -# Логирование -# ====================================================================== -ENABLE_BELIEF_STATE_LOGGING=true -TASK_LOG_LEVEL=INFO - -# ====================================================================== -# Admin bootstrap (первый запуск) -# ====================================================================== -INITIAL_ADMIN_CREATE=false -INITIAL_ADMIN_USERNAME=admin -INITIAL_ADMIN_PASSWORD=change-me -INITIAL_ADMIN_EMAIL= - -# ====================================================================== -# CORS / Безопасность деплоя -# ====================================================================== -ALLOWED_ORIGINS=http://localhost:8000 -FORCE_HTTPS=false -APP_TIMEZONE=Europe/Moscow - -# ====================================================================== -# Features -# ====================================================================== -FEATURES__DATASET_REVIEW=true -FEATURES__HEALTH_MONITOR=true - -# ====================================================================== -# Агент (опциональные тонкие настройки) -# ====================================================================== -# GRADIO_ALLOW_PORT_FALLBACK=true -# AGENT_ENABLE_LLM_TITLES=true -# AGENT_TITLE_GENERATION_TIMEOUT_S=0.25 -# AGENT_PREFETCH_DASHBOARD_LIMIT=25 -# AGENT_CONFIRM_TOOLS=false -# AGENT_INTERRUPT_BEFORE= - -# ====================================================================== -# ADFS SSO (опционально) -# ====================================================================== -# ADFS_CLIENT_ID= -# ADFS_CLIENT_SECRET= -# ADFS_METADATA_URL= diff --git a/.env.example b/.env.example index 02cefb25c..d90bc1420 100644 --- a/.env.example +++ b/.env.example @@ -9,11 +9,17 @@ COMPOSE_PROJECT_NAME=ss-tools-current # ── PostgreSQL (встроенный, docker compose db service) ────────────────── POSTGRES_IMAGE=postgres:16-alpine +POSTGRES_HOST=db +POSTGRES_PORT=5432 POSTGRES_HOST_PORT=5433 POSTGRES_DB=ss_tools POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres +# Universal one-shot migration reset. Legacy Alembic revisions are replaced +# by 0001_baseline; repeated starts preserve the baseline schema. +RESET_DATABASE_SCHEMA=false + # ── Application storage ───────────────────────────────────────────────── STORAGE_ROOT_PATH=/app/storage @@ -63,6 +69,7 @@ GRADIO_SERVER_PORT=7860 # ── Сертификаты / фронтенд ───────────────────────────────────────────── CERTS_PATH=./certs SSL_KEY_PASSPHRASE= +LLM_CA_CERT_URLS= # ── Логирование ──────────────────────────────────────────────────────── ENABLE_BELIEF_STATE_LOGGING=true diff --git a/INSTALL.md b/INSTALL.md index 46d729816..a7cd793f6 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -105,7 +105,7 @@ superset-tools/ |---|---|---| | **current** | `.env.current` | `docker compose --profile current up --build` | | **master** | `.env.master` | `docker compose --profile master up --build` | -| **enterprise-clean** | `.env.enterprise-clean` | `docker compose --profile enterprise-clean 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` | ```bash @@ -353,7 +353,7 @@ scripts/diag_container.py --target your-llm-provider.com:443 # Контейне Разворот в корпоративной сети с очищенным дистрибутивом (без тестовых данных, запрет внешних источников, compliance-проверка): ```bash -cp .env.enterprise-clean.example .env +cp .env.example .env docker compose --profile enterprise-clean up --build ``` diff --git a/backend/tests/test_release_templates.py b/backend/tests/test_release_templates.py index 674acff9c..1a6f94444 100644 --- a/backend/tests/test_release_templates.py +++ b/backend/tests/test_release_templates.py @@ -15,6 +15,8 @@ def test_generated_enterprise_backend_requires_service_jwt() -> None: assert "SERVICE_JWT: \\${SERVICE_JWT:?Set SERVICE_JWT in .env}" in backend_block assert "RESET_DATABASE_SCHEMA: \\${RESET_DATABASE_SCHEMA:-true}" in backend_block + assert '"env_template": ".env.example"' in text + assert '${DIST_ROOT}/.env.example' in text def test_generated_light_compose_requires_all_runtime_secrets() -> None: diff --git a/build.sh b/build.sh index b8aef52eb..540ad01f7 100755 --- a/build.sh +++ b/build.sh @@ -75,7 +75,7 @@ setup_compose_profile() { COMPOSE_FILE="docker-compose.yml" ;; enterprise-clean) - PROFILE_ENV_FILE="$SCRIPT_DIR/.env.enterprise-clean" + PROFILE_ENV_FILE="$SCRIPT_DIR/.env" PROJECT_NAME="superset-tools-enterprise" COMPOSE_FILE="docker-compose.enterprise-clean.yml" ;; @@ -567,7 +567,7 @@ postgres_image_id=${postgres_id} postgres_repo_digest=$(get_repo_digest "${postgres_tag}") postgres_archive=superset-tools-postgres.${tag}${suffix}.tar.xz compose_file=docker-compose.enterprise-clean.yml -env_template=.env.enterprise-clean.example +env_template=.env.example env_bootstrap_fields=INITIAL_ADMIN_CREATE,INITIAL_ADMIN_USERNAME,INITIAL_ADMIN_PASSWORD,INITIAL_ADMIN_EMAIL checksums_file=sha256sums.${tag}${suffix}.txt generated_at_utc=$(date -u +"%Y-%m-%dT%H:%M:%SZ") @@ -608,7 +608,7 @@ EOF } ], "compose_file": "docker-compose.enterprise-clean.yml", - "env_template": ".env.enterprise-clean.example", + "env_template": ".env.example", "env_bootstrap_fields": [ "INITIAL_ADMIN_CREATE", "INITIAL_ADMIN_USERNAME", @@ -626,7 +626,7 @@ EOF generate_bundle_env() { local tag="$1" - cat > "${DIST_ROOT}/.env.enterprise-clean.example" << 'ENV' + cat > "${DIST_ROOT}/.env.example" << 'ENV' # #region env.enterprise-clean.bundle [C:2] [TYPE Module] [SEMANTICS env,docker,bundle] # @BRIEF Переменные окружения для docker-compose.enterprise-clean.yml (bundled postgres). # Все образы предварительно загружены через xz -dc ... | docker load. @@ -711,7 +711,7 @@ APP_TIMEZONE=Europe/Moscow FEATURES__DATASET_REVIEW=true FEATURES__HEALTH_MONITOR=true ENV - echo "[bundle] ✅ Generated bundle env template: ${DIST_ROOT}/.env.enterprise-clean.example" + echo "[bundle] ✅ Generated bundle env template: ${DIST_ROOT}/.env.example" } bundle_release() { @@ -770,8 +770,9 @@ bundle_release() { echo " xz -dc ${DIST_ROOT}/superset-tools-frontend.${tag}.tar.xz | docker load" echo " xz -dc ${DIST_ROOT}/superset-tools-agent.${tag}.tar.xz | docker load" echo " xz -dc ${DIST_ROOT}/superset-tools-postgres.${tag}.tar.xz | docker load" - echo " # Edit .env.enterprise-clean.example -> .env.enterprise-clean, then:" - echo " docker compose --env-file ${DIST_ROOT}/.env.enterprise-clean -f ${DIST_ROOT}/docker-compose.enterprise-clean.yml up -d" + echo " # In the bundle directory, create and edit the standard Compose .env:" + echo " cd ${DIST_ROOT} && cp .env.example .env" + echo " docker compose -f docker-compose.enterprise-clean.yml up -d" echo "" echo " NOTE: Bundle includes postgres container (db) — no external PostgreSQL needed." echo " Corporate certs: mount .crt files via CERTS_PATH=./certs (optional)." @@ -887,7 +888,7 @@ volumes: postgres_data: COMPOSE - cp "${SCRIPT_DIR}/.env.enterprise-clean.example" "${DIST_ROOT}/.env.light.example" + cp "${SCRIPT_DIR}/.env.example" "${DIST_ROOT}/.env.light.example" echo "[bundle:light] ✅ Lightweight bundle created in ${DIST_ROOT}" echo " # Load image:" @@ -964,7 +965,8 @@ EOF echo " xz -dc ${DIST_ROOT}/superset-tools-frontend.${tag}${suffix}.tar.xz | docker load" echo " xz -dc ${DIST_ROOT}/superset-tools-agent.${tag}${suffix}.tar.xz | docker load" echo " xz -dc ${DIST_ROOT}/superset-tools-postgres.${tag}${suffix}.tar.xz | docker load" - echo " # Edit .env.enterprise-clean.example -> .env.enterprise-clean, then:" + echo " # In the bundle directory: cp .env.example .env, edit .env, then:" + echo " docker compose -f docker-compose.enterprise-clean.yml up -d" echo " docker compose -f ${DIST_ROOT}/docker-compose.enterprise-clean.yml up -d" echo "" echo " NOTE: Agent image includes sentence-transformers+torch (~500 MB+)." diff --git a/docker-compose.enterprise-clean.yml b/docker-compose.enterprise-clean.yml index a6ac8c08d..cdd6061b2 100644 --- a/docker-compose.enterprise-clean.yml +++ b/docker-compose.enterprise-clean.yml @@ -1,7 +1,7 @@ # #region docker.compose.enterprise-clean [C:4] [TYPE Module] [SEMANTICS docker,compose,enterprise] # @BRIEF Enterprise docker compose — сборка backend + frontend + agent из исходников, # встроенный Postgres (контейнер), корп. сертификаты. -# @PRE Docker и docker compose установлены. Файлы .env.enterprise-clean настроены. +# @PRE Docker и docker compose установлены. Стандартный файл .env настроен. # Postgres: запускается в контейнере (сервис db). Для внешнего PG — переопределить POSTGRES_HOST. # Сертификаты: опциональные .crt файлы в CERTS_PATH монтируются в /opt/certs. # @POST Сервисы db, backend, frontend и agent запущены. SSL терминация в nginx опциональна. @@ -16,7 +16,7 @@ # @RELATION DEPENDS_ON -> [docker/nginx.ssl.conf] # @RELATION DEPENDS_ON -> [docker/frontend.entrypoint.sh] # @RELATION DEPENDS_ON -> [docker/backend.entrypoint.sh] -# @DATA_CONTRACT Input: .env.enterprise-clean + ./certs/*.crt -> Output: запущенные контейнеры +# @DATA_CONTRACT Input: .env + ./certs/*.crt -> Output: запущенные контейнеры # @INVARIANT При использовании встроенного postgres (сервис db) healthcheck гарантирует # готовность БД через depends_on condition: service_healthy. # Для внешнего PG — переопределить POSTGRES_HOST и удалить сервис db. @@ -41,7 +41,7 @@ services: environment: POSTGRES_DB: ${POSTGRES_DB:-ss_tools} POSTGRES_USER: ${POSTGRES_USER:-postgres} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env.enterprise-clean} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env} ports: - "${POSTGRES_HOST_PORT:-5432}:5432" volumes: @@ -61,14 +61,14 @@ services: db: condition: service_healthy environment: - DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env.enterprise-clean}@${POSTGRES_HOST:-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools} + DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}@${POSTGRES_HOST:-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools} STORAGE_ROOT_PATH: /app/storage # Safe one-shot default: legacy revisions are reset; 0001_baseline is preserved. RESET_DATABASE_SCHEMA: ${RESET_DATABASE_SCHEMA:-true} BACKEND_PORT: 8000 ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-} - AUTH_SECRET_KEY: ${AUTH_SECRET_KEY:?Set AUTH_SECRET_KEY in .env.enterprise-clean} - ENCRYPTION_KEY: ${ENCRYPTION_KEY:?ENCRYPTION_KEY обязателен — сгенерируйте и укажите в .env.enterprise-clean} + AUTH_SECRET_KEY: ${AUTH_SECRET_KEY:?Set AUTH_SECRET_KEY in .env} + ENCRYPTION_KEY: ${ENCRYPTION_KEY:?ENCRYPTION_KEY обязателен — сгенерируйте и укажите в .env} ENABLE_BELIEF_STATE_LOGGING: ${ENABLE_BELIEF_STATE_LOGGING:-true} TASK_LOG_LEVEL: ${TASK_LOG_LEVEL:-INFO} INITIAL_ADMIN_CREATE: ${INITIAL_ADMIN_CREATE:-false} @@ -129,9 +129,9 @@ services: LLM_MODEL: ${LLM_MODEL:-gpt-4o} FASTAPI_URL: http://backend:8000 CERTS_PATH: /opt/certs - AUTH_SECRET_KEY: ${AUTH_SECRET_KEY:?Set AUTH_SECRET_KEY in .env.enterprise-clean} + AUTH_SECRET_KEY: ${AUTH_SECRET_KEY:?Set AUTH_SECRET_KEY in .env} SERVICE_JWT: ${SERVICE_JWT:?Set SERVICE_JWT in .env — do not use a public default for the service secret} - DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env.enterprise-clean}@${POSTGRES_HOST:-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools} + DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}@${POSTGRES_HOST:-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools} STORAGE_ROOT_PATH: /app/storage GRADIO_SERVER_PORT: 7860 GRADIO_ROOT_PATH: /api/agent/gradio diff --git a/docs/adr/ADR-0009-ssl-certificate-management.md b/docs/adr/ADR-0009-ssl-certificate-management.md index 90f592b1f..2f18601eb 100644 --- a/docs/adr/ADR-0009-ssl-certificate-management.md +++ b/docs/adr/ADR-0009-ssl-certificate-management.md @@ -155,7 +155,7 @@ correctly building chains with intermediate CAs. docker cp scripts/check_llm_certs.py superset-tools-backend-1:/tmp/ docker compose -f docker-compose.enterprise-clean.yml \ - --env-file .env.enterprise-clean exec backend \ + exec backend \ python3 /tmp/check_llm_certs.py --target https://lite.ai.rusal.com ``` @@ -255,15 +255,15 @@ ls ./certs/ # RUSAL_ROOT.crt RGM_Issuing.crt UC_RUSAL_Policy_CA.crt etc. docker compose -f docker-compose.enterprise-clean.yml \ - --env-file .env.enterprise-clean down + down docker compose -f docker-compose.enterprise-clean.yml \ - --env-file .env.enterprise-clean up -d + up -d # Verify docker cp scripts/check_llm_certs.py superset-tools-backend-1:/tmp/ docker compose -f docker-compose.enterprise-clean.yml \ - --env-file .env.enterprise-clean exec backend \ + exec backend \ python3 /tmp/check_llm_certs.py --target https://lite.ai.rusal.com ``` diff --git a/docs/enterprise-clean.md b/docs/enterprise-clean.md index ae38edf74..09818715b 100644 --- a/docs/enterprise-clean.md +++ b/docs/enterprise-clean.md @@ -85,7 +85,7 @@ cd /home/busya/dev/superset-tools - `frontend` image с уже собранным SvelteKit bundle; - `postgres` image или внутренний pinned base image; - `docker-compose.enterprise-clean.yml` для запуска в air-gapped окружении; -- `.env.enterprise-clean.example` с обязательными переменными; +- `.env.example` с обязательными переменными; - manifest с версиями, sha256 и перечнем образов; - инструкции по `docker load` / `docker compose up` без обращения к внешним registry. @@ -99,7 +99,7 @@ cd /home/busya/dev/superset-tools # 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 +# manifest + sha256sums + docker-compose.enterprise-clean.yml + .env.example # 2. Передать dist/docker/* в изолированный контур # 3. Импортировать образы локально (распаковка на лету) @@ -108,7 +108,8 @@ 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 +cd dist/docker +cp .env.example .env # 4a. Для первого запуска задать bootstrap администратора # INITIAL_ADMIN_CREATE=true @@ -116,7 +117,7 @@ cp dist/docker/.env.enterprise-clean.example .env.enterprise-clean # INITIAL_ADMIN_PASSWORD= # 5. Запустить только локальные образы -docker compose --env-file .env.enterprise-clean -f dist/docker/docker-compose.enterprise-clean.yml up -d +docker compose -f docker-compose.enterprise-clean.yml up -d ``` Для легковесного all-in-one образа (без Playwright, **~104 MB** вместо 575 MB): @@ -139,7 +140,7 @@ 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) должны совпадать с фактически загруженными образами `superset-tools-backend:v1.0.0-rc2-docker` и `superset-tools-frontend:v1.0.0-rc2-docker`; +- runtime-параметры задаются стандартным Compose-файлом `.env` рядом с bundle compose; - после первого входа пароль должен быть ротирован, а `INITIAL_ADMIN_CREATE` возвращён в `false`. Ограничения для production-grade offline release: diff --git a/docs/installation.md b/docs/installation.md index 3e3953d38..81b9577db 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -176,7 +176,7 @@ cd /home/busya/dev/superset-tools - `sha256sums.v1.0.0-rc2-docker.txt` - `manifest.v1.0.0-rc2-docker.{txt,json}` - `docker-compose.enterprise-clean.yml` -- `.env.enterprise-clean.example` +- `.env.example` Результат легковесного бандла: - `superset-tools.v1.0.0.tar` @@ -200,7 +200,7 @@ docker load -i postgres.v1.0.0-rc2-docker.tar ### 4. Подготовка конфигурации ```bash -cp .env.enterprise-clean.example .env.enterprise-clean +cp .env.example .env ``` Минимально проверьте: @@ -216,14 +216,14 @@ cp .env.enterprise-clean.example .env.enterprise-clean - `INITIAL_ADMIN_PASSWORD=` - `INITIAL_ADMIN_EMAIL=` -Также проверьте, что теги образов в [`.env.enterprise-clean`](.env.enterprise-clean.example) совпадают с реально загруженными: +Также проверьте, что теги образов в `.env` совпадают с реально загруженными: - `BACKEND_IMAGE=superset-tools-backend:v1.0.0-rc2-docker` - `FRONTEND_IMAGE=superset-tools-frontend:v1.0.0-rc2-docker` ### 5. Запуск в offline-контуре ```bash -docker compose --env-file .env.enterprise-clean -f docker-compose.enterprise-clean.yml up -d +docker compose -f docker-compose.enterprise-clean.yml up -d ``` Compose-файл использует `pull_policy: never`, поэтому runtime не должен обращаться к внешним registry. @@ -239,7 +239,7 @@ Compose-файл использует `pull_policy: never`, поэтому runti После первого успешного входа обязательно: - смените bootstrap-пароль на постоянный организационный секрет; - установите `INITIAL_ADMIN_CREATE=false`; -- перезапустите stack с обновлённым `.env.enterprise-clean`. +- перезапустите stack с обновлённым `.env`. Если bootstrap завершается ошибкой, backend не стартует — это ожидаемый fail-fast режим для безопасного ввода в эксплуатацию. diff --git a/frontend/e2e/run-enterprise-clean-e2e.sh b/frontend/e2e/run-enterprise-clean-e2e.sh index 9b9d7440c..803cf6e46 100755 --- a/frontend/e2e/run-enterprise-clean-e2e.sh +++ b/frontend/e2e/run-enterprise-clean-e2e.sh @@ -24,7 +24,7 @@ # (fresh PostgreSQL, StartupEnvironmentWizard), так и "живой" проект с настроенными окружениями. # @REJECTED Использование одного docker-compose файла для обоих стейджей — enterprise-clean требует # build из исходников + внешний PostgreSQL, а run.sh использует локальный dev compose. -# @DATA_CONTRACT Input: тег релиза (аргумент), .env.enterprise-clean.example, backend/.env +# @DATA_CONTRACT Input: тег релиза (аргумент), .env.example, backend/.env # Output: dist/docker/*.tar.xz, dist/docker/manifest*.txt, playwright-report/ # #endregion E2E.RunEnterpriseCleanE2E diff --git a/specs/023-clean-repo-enterprise/plan.md b/specs/023-clean-repo-enterprise/plan.md index 78136274f..be7b9975a 100644 --- a/specs/023-clean-repo-enterprise/plan.md +++ b/specs/023-clean-repo-enterprise/plan.md @@ -35,7 +35,7 @@ - 1 TUI сценарий подготовки/проверки; - 6–9 новых/обновлённых модулей (+config_loader, filesystem_scanner, db_cleanup_executor); - документация и контракты в пределах feature-папки; -- runtime bootstrap администратора через переменные `.env.enterprise-clean` без hardcode секретов в образах. +- runtime bootstrap администратора через стандартный Compose `.env` без hardcode секретов в образах. ## Constitution Check @@ -169,7 +169,7 @@ frontend/ ## Implementation Traceability & Final Notes - Статус реализации: Phase 1–7 завершены (T001–T044). -- Новое расширение (post-release hardening, 2026-03-13): добавлен scope на управляемый bootstrap администратора через `.env.enterprise-clean` и docker startup flow. +- Новое расширение (post-release hardening, 2026-03-13): добавлен scope на управляемый bootstrap администратора через `.env` и docker startup flow. - Ключевые подтверждения polish-фазы: - T039: smoke TUI сценария зафиксирован в [`quickstart.md`](./quickstart.md). - T040: контрактная проверка API подтверждена тестом [`backend/src/api/routes/__tests__/test_clean_release_api.py`](../../backend/src/api/routes/__tests__/test_clean_release_api.py). @@ -179,12 +179,12 @@ frontend/ Итог: базовая feature готова к финальному релизному циклу с обязательным CI gate (`COMPLIANT` only) и операционной доказательной базой для аудита. -## Post-Release Hardening Addendum — Admin Bootstrap via `.env.enterprise-clean` +## Post-Release Hardening Addendum — Admin Bootstrap via `.env` Цель addendum: убрать ручной шаг создания initial admin после доставки offline bundle и сделать это управляемой частью container startup. Архитектурные решения: -1. В `.env.enterprise-clean.example` добавить параметры: +1. В `.env.example` добавить параметры: - `INITIAL_ADMIN_CREATE=false` (default-safe), - `INITIAL_ADMIN_USERNAME=admin`, - `INITIAL_ADMIN_PASSWORD=change-me`, @@ -195,7 +195,7 @@ frontend/ - обрабатывает idempotency (существующий пользователь => без ошибки, лог `already exists`). 3. В `docker-compose.enterprise-clean.yml` прокинуть переменные bootstrap администратора только в `backend` service. 4. В операционном runbook зафиксировать обязательную ротацию bootstrap-пароля после первого входа. -5. В offline bundle manifest оставить ссылку на `.env.enterprise-clean.example` как source-of-truth для параметров запуска. +5. В offline bundle manifest оставить ссылку на `.env.example` как source-of-truth для параметров запуска. Нефункциональные ограничения: - Никаких default production секретов в Git. diff --git a/specs/023-clean-repo-enterprise/quickstart.md b/specs/023-clean-repo-enterprise/quickstart.md index a398806e3..acaab52c8 100644 --- a/specs/023-clean-repo-enterprise/quickstart.md +++ b/specs/023-clean-repo-enterprise/quickstart.md @@ -73,9 +73,9 @@ cd /home/busya/dev/superset-tools 2. Повторно запустить проверку из того же TUI экрана (`F5`). 3. Повторять до статуса `COMPLIANT`. -## Admin Bootstrap via `.env.enterprise-clean` (Docker Runtime) +## Admin Bootstrap via `.env` (Docker Runtime) -Для offline bundle deployment в контейнерах используйте runtime файл `.env.enterprise-clean` на базе шаблона `.env.enterprise-clean.example`. +Для offline bundle deployment в контейнерах используйте стандартный runtime файл `.env` на базе шаблона `.env.example`. Обязательные параметры bootstrap: - `INITIAL_ADMIN_CREATE=true` для первого запуска; diff --git a/specs/023-clean-repo-enterprise/spec.md b/specs/023-clean-repo-enterprise/spec.md index 41d6c27af..cfb3ab631 100644 --- a/specs/023-clean-repo-enterprise/spec.md +++ b/specs/023-clean-repo-enterprise/spec.md @@ -102,9 +102,9 @@ - **FR-018**: Стадия `NO_EXTERNAL_ENDPOINTS` MUST сканировать все текстовые файлы (включая код, конфиги, скрипты) на наличие URL/хостов и сверять каждый найденный endpoint с `allowed_sources`. - **FR-019**: Процесс clean-подготовки MUST включать стадию очистки БД от тестовых пользователей и демо-данных. Правила очистки (таблицы, условия, исключения) задаются в секции `database_cleanup` файла `.clean-release.yaml`. - **FR-020**: Структура `.clean-release.yaml` MUST включать секции: `profile`, `scan_mode`, `prohibited_categories`, `prohibited_paths`, `allowed_sources`, `ignore_paths`, `database_cleanup` (с подсекциями `tables` и `preserve`). -- **FR-021**: Enterprise clean release bundle MUST включать `.env.enterprise-clean.example` с параметрами bootstrap администратора (`INITIAL_ADMIN_USERNAME`, `INITIAL_ADMIN_PASSWORD`, `INITIAL_ADMIN_EMAIL` optional, `INITIAL_ADMIN_CREATE`) и безопасными комментариями по ротации пароля. +- **FR-021**: Enterprise clean release bundle MUST включать `.env.example` с параметрами bootstrap администратора (`INITIAL_ADMIN_USERNAME`, `INITIAL_ADMIN_PASSWORD`, `INITIAL_ADMIN_EMAIL` optional, `INITIAL_ADMIN_CREATE`) и безопасными комментариями по ротации пароля. - **FR-022**: Docker startup flow backend MUST поддерживать idempotent bootstrap администратора при запуске контейнера: при `INITIAL_ADMIN_CREATE=true` система создаёт администратора только если пользователь отсутствует и не перезаписывает существующие credentials/roles. -- **FR-023**: Процесс публикации clean bundle MUST включать операторский сценарий заполнения runtime `.env.enterprise-clean` из шаблона и подтверждение, что bootstrap-пароль заменён на организационный секрет до первого production запуска. +- **FR-023**: Процесс публикации clean bundle MUST включать операторский сценарий заполнения runtime `.env` из шаблона и подтверждение, что bootstrap-пароль заменён на организационный секрет до первого production запуска. ### Key Entities *(include if feature involves data)* diff --git a/specs/023-clean-repo-enterprise/tasks.md b/specs/023-clean-repo-enterprise/tasks.md index e9619d698..989ae06d9 100644 --- a/specs/023-clean-repo-enterprise/tasks.md +++ b/specs/023-clean-repo-enterprise/tasks.md @@ -143,9 +143,9 @@ ## Phase 8: Post-Release Hardening — Admin Bootstrap in Docker -**Purpose**: Автоматизировать первичное создание администратора через runtime `.env.enterprise-clean` в offline/enterprise deployment. +**Purpose**: Автоматизировать первичное создание администратора через runtime `.env` в offline/enterprise deployment. -- [X] T045 Add admin bootstrap env contract to `.env.enterprise-clean.example` (`INITIAL_ADMIN_CREATE`, `INITIAL_ADMIN_USERNAME`, `INITIAL_ADMIN_PASSWORD`, optional `INITIAL_ADMIN_EMAIL`) +- [X] T045 Add admin bootstrap env contract to `.env.example` (`INITIAL_ADMIN_CREATE`, `INITIAL_ADMIN_USERNAME`, `INITIAL_ADMIN_PASSWORD`, optional `INITIAL_ADMIN_EMAIL`) - [X] T046 Wire admin bootstrap envs to backend runtime in `docker-compose.enterprise-clean.yml` - [X] T047 Add backend entrypoint flow that performs idempotent admin bootstrap before app start in `docker/backend.Dockerfile` and new entrypoint script - [X] T048 Extend admin creation script for optional email and deterministic exit behavior for existing user in `backend/src/scripts/create_admin.py`