---
doc_id: DLV-CK8S-AAC-WAVE7
type: delivery-plan
title: kodex — домен доступа, план кодовой волны 7
status: completed
owner_role: EM
created_at: 2026-04-26
updated_at: 2026-05-11
related_issues: [599, 600, 601, 602, 711]
related_prs: []
related_docsets:
  - docs/domains/access-and-accounts/product/requirements.md
  - docs/domains/access-and-accounts/architecture/design.md
  - docs/domains/access-and-accounts/architecture/data_model.md
  - docs/domains/access-and-accounts/architecture/api_contract.md
approvals:
  required: ["Owner"]
  status: approved
  request_id: "owner-2026-04-26-wave6-4-access-domain"
  approved_by: "ai-da-stas"
  approved_at: 2026-04-26
---

# План поставки: кодовая волна 7, доступ и аккаунты

## TL;DR

- Что поставляем: новый сервис-владелец `access-manager` и минимальный доменный вертикальный срез доступа.
- Текущее состояние: кодовый объём по входу, внешним аккаунтам, вычислению доступа, организациям, группам и membership готов.
- Операторское чтение графа членства закрывает остаток #599: `ListMembershipGraph` подключён к домену и gRPC, принимает `CommandMeta.actor` и проверяет право через `CheckAccess`.
- Главные риски на следующем домене: скопировать проверки доступа локально, обойти каталог внешних аккаунтов, оставить временные скрипты как постоянный контур выкладки.

## Входные артефакты

| Артефакт | Путь |
|---|---|
| Сквозные требования | `docs/platform/product/requirements.md` |
| Архитектурная карта доменов | `docs/platform/architecture/domain_map.md` |
| Границы сервисов | `docs/platform/architecture/service_boundaries.md` |
| Модель данных платформы | `docs/platform/architecture/data_model.md` |
| Требования домена | `docs/domains/access-and-accounts/product/requirements.md` |
| Дизайн домена | `docs/domains/access-and-accounts/architecture/design.md` |
| Модель данных домена | `docs/domains/access-and-accounts/architecture/data_model.md` |
| API-контракт домена | `docs/domains/access-and-accounts/architecture/api_contract.md` |

## Структура работ

| Этап | Issue | Содержание |
|---|---|---|
| Основа | #599 | Организации, группы, пользователи, членство, версии агрегатов, outbox. |
| Вход | #600 | SSO/OIDC, allowlist, bootstrap пользователя, статусы пользователя, операторский путь. |
| Внешние аккаунты | #601 | Реестр внешних аккаунтов, метаданные ссылок на секреты, область применения, операторская видимость. |
| Вычисление доступа | #602 | Правила доступа, явный запрет, вычисление доступа, аудит и путь объяснения. |

## Мелкие PR-срезы

Чтобы ревью оставалось управляемым, кодовая волна 7 делится на последовательные PR-срезы. Один PR не должен смешивать repository, транспорт, новые сценарии, эксплуатационную готовность и закрытие поставки без необходимости.

| Срез | Фокус | Что входит | Что не входит |
|---|---|---|---|
| 7.1 | PostgreSQL-репозиторий | SQL и реализация репозитория для уже созданного доменного интерфейса, тесты репозитория и миграций. | gRPC-обработчики, новые пользовательские сценарии, frontend. |
| 7.2 | gRPC-транспорт | Серверный gRPC-слой, преобразование `proto <-> domain`, маппинг ошибок, граница проверки вызывающей стороны с отказом по умолчанию, конфигурируемые лимиты, базовые метрики и тесты gRPC-слоя. | Расширение бизнес-логики за пределы уже согласованных операций и полноценная трассировка. |
| 7.2.1 | Общий gRPC-контур | Вынос общей сборки gRPC-сервера, восстановления после panic, лимитов, таймаута выполнения RPC, keepalive-политики, ограничения размера сообщений, базовых метрик и расширяемой проверки вызывающей стороны в `libs/go/grpcserver`. | Доменные обработчики, преобразования `proto <-> domain` и маппинг доменных ошибок. |
| 7.3 | Проверка доступа | Полные `CheckAccess`, `ExplainAccess`, аудит решений, тесты пограничных случаев. | Внешние аккаунты и вход пользователя, если они не нужны для проверки доступа. |
| 7.4 | Вход и операторский жизненный цикл | `BootstrapUserFromIdentity`, allowlist, `SetUserStatus`, `DisableAllowlistEntry`, `ListPendingAccess`, тесты SSO/OIDC-пути идентичности и операторского списка pending/blocked. | UI и внешние каналы входа. |
| 7.5 | Внешние аккаунты | Поставщики, внешние аккаунты, ссылки на секреты, `ResolveExternalAccountUsage`, аудитный след. | Реальные операции `provider-hub`, кроме контрактной проверки зависимости. |
| 7.6 | События | Outbox-доставщик, идемпотентность публикации, сверка AsyncAPI и контрактные тесты. | Полная платформа событий для всех доменов. |
| 7.6.1 | PostgreSQL-журнал событий | Отдельный контур `platform-event-log`, миграции общего журнала, штатный канал публикации из сервисного outbox, веерная доставка для нескольких потребителей, checkpoint API, базовые PostgreSQL-манифесты, секреты времени выполнения, промышленное задание миграций и интеграционные проверки. | Реальные домены-потребители и бизнес-обработчики событий. |
| 7.7.1 | Эксплуатационный контур сервиса | Корреляционные gRPC-метаданные для логов, Dockerfile-стадия миграций, Kubernetes-манифесты, рендер шаблонов выкладки и проверка готовности `access-manager` в среде. | Выкладка всей платформы в промышленный контур. |
| 7.8 | Закрытие волны | Delivery-карты, статусы Issue, остаточный бэклог и критерии перехода к следующему домену. | Новые функциональные возможности. |

## Закрывающий checkpoint

| Issue | Состояние | Решение checkpoint |
|---|---|---|
| #599 | Фундамент организаций, групп, membership, версии агрегатов, транзитивное раскрытие графа для `CheckAccess` и операторское чтение `ListMembershipGraph` готовы. | Закрыть как выполненную. |
| #600 | SSO/OIDC bootstrap, allowlist, статусы пользователя, отключение allowlist-записи, операторский список pending/blocked и организационная область готовы. | Закрыть как выполненную. |
| #601 | Поставщики, внешние аккаунты, привязки, ссылки на секреты, команды жизненного цикла и `ResolveExternalAccountUsage` готовы. | Закрыть как выполненную. |
| #602 | Каталог действий, правила доступа, приоритет deny, `CheckAccess`, `ExplainAccess`, аудит решений и события готовы. | Закрыть как выполненную. |

## Инфраструктурный бэклог перед следующим сервисом

До создания следующего доменного сервиса общий gRPC-контур вынесен из `access-manager` в `libs/go/grpcserver`.

В общий пакет должны перейти только инфраструктурные части без доменных зависимостей:
- сборка `grpc.Server` из типизированной конфигурации;
- восстановление после panic;
- лимит активных RPC;
- таймаут выполнения RPC;
- keepalive-политика, `MaxConcurrentStreams`, ограничение размера сообщений;
- базовые Prometheus-метрики unary RPC;
- расширяемая проверка вызывающей стороны без привязки к домену `access-manager`.

В общий пакет не переносить преобразования `proto <-> domain`, маппинг доменных ошибок, конкретные доменные типы и обработчики `AccessManagerService`. `access-manager` становится первым потребителем общей библиотеки, а следующий сервис не должен копировать локальные gRPC-помощники.

## Готовность к началу

- Доменный пакет документации принят.
- Целевой каталог нового сервиса не пересекается со старым `deprecated/**`.
- Машинно-проверяемые контракты `proto` и AsyncAPI созданы как стабильный `v1` на весь согласованный объём внутреннего доменного API.
- Все команды изменения проектируются с идемпотентным ключом и ожидаемой версией агрегата.
- Секреты проектируются через ссылку на секрет, а не через хранение значения в БД.

## Контрактная готовность и бэклог реализации

Стабильный контракт `v1` фиксирует целевой внешний и межсервисный API домена. Это не означает, что весь контракт уже реализован в коде текущего среза. Реализация закрывается по запланированным Issue домена до того, как соответствующие операции станут обязательной зависимостью других сервисов или пользовательского интерфейса.

| Область | Статус | Где закрывается |
|---|---|---|
| gRPC `AccessManagerService` и AsyncAPI на весь согласованный объём | Готово как стабильный внутренний контракт `v1`. | API-контракт домена и машинно-проверяемые спецификации. |
| Сервисный каркас `access-manager`, конфигурация, health/readyz/metrics и пустой gRPC-сервер | Готово как базовый процесс без зарегистрированных RPC-обработчиков. | Текущий срез реализации. |
| gRPC-восстановление, лимиты и единая граница обработки ошибок | Готово для unary RPC: общий `libs/go/grpcserver` собирает сервер, восстанавливается после panic, проверяет вызывающую сторону, ограничивает активные RPC, задаёт таймаут выполнения RPC, keepalive-политику, ограничения размера сообщений и базовые метрики. Доменные ошибки маппятся в стабильные gRPC-коды внутри `access-manager`. Полная корреляция логов и трассировка остаются частью эксплуатационного среза. | #599, #600, #601, #602; трассировка и расширенная наблюдаемость закрываются в эксплуатационном срезе. |
| Миграция БД для основных таблиц домена и outbox | Готово как начальная схема. | #599, #600, #601, #602. |
| Доменный слой организаций, групп, членства, allowlist, внешних аккаунтов, правил доступа, `CheckAccess`, `ExplainAccess` и `ResolveExternalAccountUsage` | Готов в согласованном срезе: `CheckAccess` проверяет каталог действий, явные запреты, состояния субъекта и пишет audit-запись, `ExplainAccess` читает сохранённое объяснение решения, а команды жизненного цикла внешних аккаунтов проверяют право оператора и версию агрегата. `ResolveExternalAccountUsage` подтверждает выбранный внешний аккаунт, действие и область использования, возвращает `provider_slug` и ссылку на секрет без значения секрета; само значение разрешается через общий `libs/go/secretresolver` вне публичного gRPC-контракта. Поддерживаемые типы ссылок первой версии: `kubernetes_mounted_secret`, `env`, `vault`. | #599, #600, #601, #602, #711. |
| PostgreSQL-репозиторий для всех методов текущего доменного интерфейса | Готов: сервис открывает ограниченный `pgxpool` через общую библиотеку, репозиторий пишет агрегат, результат команды и outbox в одной транзакции, команды с естественным ключом сохраняют стабильный идентификатор агрегата, ограничения БД проверяют области владения внешних аккаунтов и уникальность правил доступа, реализованы чтения и изменения для операторского входного контура и внешних аккаунтов, интеграционные PostgreSQL-тесты входят в обязательный явный контур `make test-go-postgres`. | #599, #600, #601, #602. |
| gRPC-обработчики и маппинг `proto <-> domain` | Готов базовый транспортный срез: `AccessManagerService` зарегистрирован, обработчики подключены к уже реализованным доменным операциям, включая изменение статуса пользователя, отключение allowlist-записи, список pending/blocked для оператора, операторское чтение графа членства, жизненный цикл внешних аккаунтов и `ResolveExternalAccountUsage`; кастеры вынесены в gRPC-слой. Методы, для которых доменный сценарий ещё не готов, явно возвращают `Unimplemented`. | #599, #600, #601, #602; оставшиеся доменные сценарии закрываются последующими срезами. |
| HTTP-поверхности gateway-сервисов и OpenAPI | В бэклоге соответствующих gateway-срезов: `staff-gateway` появляется рядом с `web-console`, `integration-gateway` — после базового `provider-hub`, `user-gateway` — на границе MVP или после MVP. `access-manager` остаётся внутренним сервисом. | #600, #601, #602, срезы пользовательского интерфейса и интеграций с провайдерами. |
| Жизненный цикл обновления, отключения, приостановки и архивации агрегатов | В бэклоге; контракт уже зафиксирован, код закрывается по мере реализации административных сценариев. | #599, #600, #601, #602. |
| `SetUserStatus`, `DisableAllowlistEntry`, `ListPendingAccess` | Готово: доменный слой, PostgreSQL repository, обработчики gRPC и тесты подключены для операторского жизненного цикла входа. Операторские операции проверяют `CommandMeta.actor` через `CheckAccess`; команды изменения требуют идемпотентный след и ожидаемую версию, а `DisableAllowlistEntry` обновляет запись с проверкой версии вместо upsert. Организационный администратор может работать только с пользователями и allowlist-записями своей области, а операторский список для организации включает пользователей, найденных по allowlist до создания membership, и сортируется по последнему изменению состояния. | #600, #619. |
| `ListMembershipGraph` | Готово: доменный слой, обработчик gRPC, преобразование `proto <-> domain` и тесты подключены для операторского чтения графа членства. Операция проверяет `CommandMeta.actor` через `CheckAccess`, действие `access.membership_graph.list` и ресурс `membership_graph`; область проверки выводится из корневого субъекта графа. Пользовательский корень учитывает членство через группы, родительские группы и организационный allowlist; организация и группа как корень читают входящие membership-связи по target-side; внешний аккаунт сохраняет исходную область владельца в аудите и проверке доступа. Для области операторской видимости учитываются конечные точки связей в состояниях `active`, `pending` и `blocked`, поэтому администратор организации видит проблемные связи через группы. По умолчанию возвращаются активные membership-связи, а `include_inactive` добавляет связи в состояниях `pending`, `blocked` и `disabled` без использования их для дальнейшего раскрытия графа; `disabled`-связи не расширяют область авторизации. | #599. |
| `UpdateExternalProvider`, `UpdateExternalAccountStatus`, `DisableExternalAccountBinding` | Готово: доменный слой, PostgreSQL repository, обработчики gRPC и тесты подключены для внешних аккаунтов. Операции проверяют `CommandMeta.actor` через `CheckAccess`, требуют идемпотентный след и ожидаемую версию, а отключение привязки обновляет запись без удаления истории. | #601. |
| Остальные `Update*` и остальные `Disable*` | В бэклоге: proto-контракт уже стабилен, но часть административных методов не подключена к доменному сценарию. Эти методы закрываются там, где понадобятся пользовательскому интерфейсу, MCP или операторским сценариям. | #602, срезы пользовательского интерфейса и MCP. |
| Доставщик outbox-событий сервиса | Готов сервисный механизм: PostgreSQL-репозиторий забирает события с арендой записи, доставщик повторяет временные ошибки с задержкой, постоянные ошибки выводит из автоматического повтора, отметки успеха и ошибки защищены номером попытки, контракт событий сверяется тестом AsyncAPI. Диагностическая публикация в лог имеет явный режим с потерей последующей доставки, выключена по умолчанию, не является MVP-доставкой и запрещена там, где событие должно уйти реальным потребителям. | #599, #600, #601, #602. |
| MVP-доставка доменных событий | Готов минимальный путь: сервисный outbox публикует событие через штатный канал `postgres-event-log` в отдельную БД `platform-event-log`, запись в журнал идемпотентна по `event_id` и неизменяемому содержимому события, разные потребители получают веерную доставку через собственный checkpoint. Миграции общего журнала не входят в БД `access-manager`; промышленный порядок включает создание БД, отдельное Kubernetes-задание миграций `platform-event-log` и только затем запуск сервисов-публикаторов. | Будущие домены-потребители используют `libs/go/eventlog` для чтения и идемпотентного продвижения checkpoint. |
| Подписчики доменных событий | В бэклоге: реальные бизнес-подписчики добавляются в сервисах-потребителях; текущий срез даёт только общий журнал, checkpoint API и интеграционные проверки. | Домены-потребители. |
| Эксплуатационный контур `access-manager` | Готов первый промышленный путь сервиса: Dockerfile содержит отдельную стадию `migrations`, секреты времени выполнения включают DSN и gRPC-token, Kubernetes-манифесты описывают ServiceAccount, Service, Deployment, initContainer ожидания БД, readiness/liveness/metrics, ресурсы и отдельное задание миграций. Рендер шаблонов выполняется через `cmd/manifest-render`, а первый серверный контур проверяется через `bootstrap/host/smoke_backend_contour.sh`: `PostgreSQL -> миграции platform-event-log -> миграции access-manager -> выкладка access-manager` и `/health/readyz`. | Серверная проверка выполняется после загрузки образов в целевой кластер или реестр; доменные сценарии должны жить в Go tests или будущем Go integration runner. |
| Корреляция запросов в логах | Готова лёгкая корреляционная граница: общий gRPC-контур читает безопасные метаданные `x-kodex-trace-id`, `x-kodex-request-id`, `x-kodex-session-id`, `x-kodex-request-source` и добавляет их в контекст логирования ошибок и восстановления после panic. Полноценный сборщик распределённой трассировки остаётся сквозным контуром наблюдаемости платформы, а не отдельной обязанностью домена доступа. | Платформенная наблюдаемость и следующие сервисы используют тот же `libs/go/grpcserver`. |

Правило для следующих сервисов: если контракт создаётся раньше полной реализации, в документе поставки должен быть такой же раздел. Без него стабильный контракт нельзя считать готовым к слиянию.

## Критерии завершения

- В новом коде есть `access-manager` как сервис-владелец домена.
- Есть собственный контур БД, миграций и typed domain models.
- Есть промышленные манифесты, отдельное задание миграций, секреты времени выполнения, health/readyz/metrics и проверочный путь выкладки сервиса.
- Организации, пользователи, группы, членство, allowlist, поставщики внешних аккаунтов, внешние аккаунты, действия доступа и правила доступа реализованы без произвольного JSON как основной модели.
- Есть outbox для доменных событий `access.*`.
- Есть API для `CheckAccess`, `ExplainAccess`, `BootstrapUserFromIdentity` и управления внешними аккаунтами.
- Есть след аудита для административных изменений и решений доступа.
- Документация и карты Issue синхронизированы с фактической реализацией.

## Зависимости

- Базовая инфраструктура разработки новых сервисов должна создаваться с нуля, без переноса старого `control-plane`.
- Операции провайдера в следующих волнах должны использовать ссылки на внешние аккаунты из `access-manager`.
- Пользовательский интерфейс может стартовать с минимального пути чтения, но не должен читать БД напрямую.

## Риски и буферы

| Риск | Митигирование |
|---|---|
| Одноорганизационная модель зацементирована в коде | Все сущности сразу имеют модель организации и области применения. |
| Секреты попали в БД или аудит | Ссылка на секрет, маскированная диагностика и проверки безопасности. |
| `provider-hub` начал владеть политикой аккаунта | Контракт: `provider-hub` получает разрешённое использование аккаунта у `access-manager`. |
| Проверки доступа размазаны по сервисам | Все сервисы используют `CheckAccess` и не создают локальные правила. |

## Апрув

- request_id: `owner-2026-04-26-wave6-4-access-domain`
- Решение: approved
- Комментарий: план поставки домена доступа готовит кодовую волну 7.
