---
doc_id: EPC-CK8S-S3-D11
type: epic
title: "Epic S3 Day 11: Full-env slot namespace + subdomain templating (TLS) + agent run"
status: completed
owner_role: EM
created_at: 2026-02-13
updated_at: 2026-02-18
related_issues: [19]
related_prs: []
approvals:
  required: ["Owner"]
  status: approved
  request_id: "owner-2026-02-19-full-docset"
  approved_by: "ai-da-stas"
  approved_at: 2026-02-19
---

# Epic S3 Day 11: Full-env slot namespace + subdomain templating (TLS) + agent run

## TL;DR
- Цель: сделать full-env слоты полностью самодостаточными и пригодными для manual QA.
- MVP-результат: по webhook-triggered full-env деплою поднимается изолированный namespace слота (вся инфра/сервисы/БД), запускается агент внутри этого namespace, а слот доступен по отдельному HTTPS поддомену с валидным сертификатом.

## Priority
- `P0`.

## Контекст
- В Day9 введен typed `services.yaml` и persisted reconcile-контур `runtime_deploy_tasks` для full-env.
- Чтобы полноценно использовать full-env режим для dogfooding и внешних проектов, нужен:
  - запуск agent-run внутри slot namespace (как часть full-env исполнения),
  - детерминированный рендер и выдача public URL для слота (поддомен + TLS),
  - отсутствие cluster-scope конфликтов между prod/production и ai-слотами.

## Scope
### In scope
- Full-env runtime: в slot namespace разворачиваются все `infrastructure` и `services` из `services.yaml` в правильном порядке (stateful -> migrations -> internal -> edge -> frontend).
- Agent-run внутри slot namespace:
  - после readiness сервисов создается `Job`/`Pod` с `agent-runner` (или эквивалентный runtime workload);
  - агент использует те же политики и аудит, что и обычный `run:*` контур;
  - результат работы сохраняется в БД и виден через staff UI.
- Шаблонизация поддоменов для full-env slot namespaces:
  - контракт `services.yaml` расширяется полем уровня окружения (MVP): `environments.<env>.domainTemplate`.
  - шаблон использует контекст рендера: `.Project`, `.Env`, `.Slot`, `.Namespace`.
  - runtime deploy резолвит host в `KODEX_PRODUCTION_DOMAIN` и `KODEX_PUBLIC_BASE_URL` перед рендером манифестов.
  - ingress манифесты используют резолвленный host, а oauth2-proxy redirect URL всегда соответствует этому host.
- TLS и cert-manager:
  - `ClusterIssuer` (Let’s Encrypt) считается bootstrap-only и не применяется в runtime deploy.
  - для слотов создается только namespaced `Ingress` + `Certificate` (через аннотацию), используя общий `ClusterIssuer`.
- Manual QA маршрут:
  - после деплоя слот доступен по URL вида, полученного из `domainTemplate` (HTTPS);
  - staff UI и runbook содержат команды проверки (ingress/cert/job/logs).

### Out of scope
- Автоматизация DNS провайдера (создание wildcard-записей) и DNS01-валидация.
- Переход на wildcard-сертификаты для всех слотов.
- `vcluster`/nested clusters.

## Критерии приемки
- Full-env деплой по webhook создает/обновляет slot namespace и выводит его public URL (host) детерминированно.
- В slot namespace:
  - инфраструктура и сервисы развернуты и готовы;
  - агент запущен и пишет артефакты/логи/статусы;
  - повторный reconcile идемпотентен.
- Поддомен слота:
  - соответствует `domainTemplate`;
  - резолвится в ingress (предусловие: wildcard DNS настроен);
  - cert-manager выпускает сертификат и `kubectl get certificate` показывает `Ready=True`;
  - слот открывается в браузере и доступен для manual QA.
- Slot mode не пытается создавать/менять cluster-scoped ресурсы (в т.ч. `ClusterIssuer`), чтобы исключить конфликты с production/prod.

## Реализация (2026-02-18)
- Слот-режим и full-env контур работают через persisted runtime deploy задачи и reconcile-loop:
  - `services/internal/control-plane/internal/domain/runtimedeploy/service_prepare.go`
  - `services/internal/control-plane/internal/domain/runtimedeploy/service_reconcile.go`
  - `services/internal/control-plane/internal/domain/runtimedeploy/model.go`
- Поддержан `domainTemplate` и слот-контекст рендера (`Project/Env/Slot/Namespace`) в typed `services.yaml`:
  - `libs/go/servicescfg/model.go`
  - `libs/go/servicescfg/load.go`
- Для AI-слотов используется отдельный домен и slot-specific env:
  - `KODEX_AI_DOMAIN` в prerequisites/манифестах:
    - `services/internal/control-plane/internal/domain/runtimedeploy/service_prerequisites.go`
    - `deploy/base/kodex/app.yaml.tpl`
- TLS для слотов реализован namespaced-путём (без создания cluster-scoped ресурсов из runtime deploy):
  - runtime TLS reuse/validation: `services/internal/control-plane/internal/domain/runtimedeploy/service_tls.go`
  - `ClusterIssuer` остаётся bootstrap/base-ресурсом: `deploy/base/cert-manager/clusterissuer.yaml.tpl`.

## Acceptance checklist
- [x] Full-env деплой создаёт/обновляет slot namespace и формирует детерминированный public host.
- [x] Слот использует отдельный namespace/runtime mode (`full-env`) без конфликтов с production/prod.
- [x] Поддержан `domainTemplate` + slot context (`Project/Env/Slot/Namespace`) в render pipeline.
- [x] Slot runtime не создаёт cluster-scoped issuer-ресурсы; TLS работает через namespaced контур.
