АРХ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: roadmap двусторонней доски внешних контуров
This commit is contained in:
@@ -0,0 +1,465 @@
|
||||
# Этапы разработки
|
||||
|
||||
## Общий принцип
|
||||
|
||||
Не делаем сразу тяжелую доменную платформу.
|
||||
|
||||
Идем вертикальными поставками:
|
||||
1. сначала транспорт и создание задачи
|
||||
2. потом source-side представление
|
||||
3. потом синхронизация
|
||||
4. потом уведомления и полировка
|
||||
|
||||
## Freeze point на 2026-04-19
|
||||
|
||||
Текущий вертикальный срез временно заморожен.
|
||||
|
||||
На момент freeze point уже есть:
|
||||
- отправка запроса из source project в target project того же `workspace`
|
||||
- отсутствие требования прямого membership в target project для отправки
|
||||
- source-side список `Открытые / Завершенные`
|
||||
- source-side карточка на shell `Предложений`
|
||||
- source-side редактирование открытого запроса по `заголовку` и `описанию`
|
||||
- зеркалирование статуса, комментариев, вложений и activity из целевого контура
|
||||
- source-side действия `Принять`, `Отклонить`, `Ответ во внешний контур`
|
||||
- индикатор непрочитанных изменений
|
||||
- карточка `Маршрутизация` в целевом формате `3 x 3`
|
||||
|
||||
Дальше по roadmap пока не идем, пока не приняты продуктовые решения по внутреннему жизненному циклу принятого запроса.
|
||||
|
||||
## Новая рамка после freeze point на 2026-04-20
|
||||
|
||||
После дополнительной продуктовой фиксации следующий цикл делится на три слоя:
|
||||
1. единый shell карточки внешнего контура
|
||||
2. двусторонняя доска `Исходящие / Входящие`
|
||||
3. пользовательские представления поверх той же доски
|
||||
|
||||
При этом обязательное архитектурное ограничение фиксируется заранее:
|
||||
- во `Внешних контурах` нет drag-and-drop между блоками
|
||||
- блоки здесь означают представления, а не стадии workflow
|
||||
|
||||
Подробные архитектурные шаги вынесены в:
|
||||
- [11_STEP_external-contours-detail-shell.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/11_STEP_external-contours-detail-shell.md)
|
||||
- [12_STEP_external-contours-bidirectional-board.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/12_STEP_external-contours-bidirectional-board.md)
|
||||
|
||||
## Этап 0. Термины и навигация
|
||||
|
||||
### Цель
|
||||
|
||||
Подготовить интерфейс и словарь сущностей без ломки backend-логики.
|
||||
|
||||
### Что входит
|
||||
|
||||
- `Рабочие элементы` -> `Внутренний контур`
|
||||
- новая вкладка `Внешние контуры`
|
||||
- подготовка i18n-ключей и текстов
|
||||
- фиксация терминов в продуктовой документации
|
||||
|
||||
### Результат
|
||||
|
||||
В проекте уже есть новая структура навигации, но бизнес-логика еще не внедрена.
|
||||
|
||||
## Этап 1. Маршрутизация запроса в целевой проект
|
||||
|
||||
### Цель
|
||||
|
||||
Сделать рабочий сценарий отправки задачи из source project в target project.
|
||||
|
||||
### Что входит
|
||||
|
||||
- новая create-form во `Внешних контурах`
|
||||
- выбор целевого проекта
|
||||
- выбор исполнителя из целевого проекта
|
||||
- orchestration endpoint
|
||||
- использование intake bridge как backend-моста
|
||||
- немедленный перевод в default-state целевого проекта
|
||||
- создание target issue
|
||||
- запись source/target metadata
|
||||
|
||||
### Что не входит
|
||||
|
||||
- полноценная синхронизация файлов
|
||||
- полноценная зеркальная история
|
||||
- сложные уведомления
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- пользователь отправляет внешний запрос
|
||||
- в целевом проекте появляется обычная задача
|
||||
- задача не зависает в triage
|
||||
- source-side список уже видит факт отправки
|
||||
|
||||
### Статус
|
||||
|
||||
Реализовано.
|
||||
|
||||
Что работает фактически:
|
||||
- `POST /external-contours/` создает target issue в целевом проекте
|
||||
- target issue сразу попадает в обычный workflow целевого проекта
|
||||
- source-side `GET /external-contours/` возвращает отправленные запросы с metadata источника и цели
|
||||
- target contour теперь выбирается по policy `same workspace + intake enabled`, а не только из joined projects
|
||||
- прямое membership в target project для отправки не требуется
|
||||
|
||||
## Этап 2. Source-side список и статусная пришлепка
|
||||
|
||||
### Цель
|
||||
|
||||
Дать инициатору читаемый контроль за отправленными запросами.
|
||||
|
||||
### Что входит
|
||||
|
||||
- список `Открытые`
|
||||
- список `Завершенные`
|
||||
- текущий статус задачи как пришлепка
|
||||
- отображение целевого проекта
|
||||
- отображение исполнителя
|
||||
- отображение даты обновления
|
||||
- индикатор новых изменений
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- в проекте-источнике виден список отправленных запросов
|
||||
- у каждой записи отображается актуальный статус целевой задачи
|
||||
|
||||
### Статус
|
||||
|
||||
Реализовано частично в рамках текущего вертикального среза.
|
||||
|
||||
Что уже работает:
|
||||
- source-side список `Открытые / Завершенные`
|
||||
- status pill по фактическому state целевой задачи
|
||||
- отображение целевого проекта
|
||||
- отображение исполнителей целевого контура
|
||||
- отображение фактической даты последнего изменения
|
||||
- индикатор новых изменений в source-side списке на базе unread уведомлений
|
||||
- открытие source-side detail экрана
|
||||
|
||||
Что еще остается на следующие этапы:
|
||||
- полноценная зеркальная activity/history
|
||||
- уведомления
|
||||
|
||||
Дополнительно реализовано:
|
||||
- source-side detail показывает блок маршрутизации
|
||||
- в карточке видны источник, цель, отправитель, дата отправки и связанная целевая задача
|
||||
|
||||
## Этап 3. Source-side детальный экран и зеркалирование изменений
|
||||
|
||||
### Цель
|
||||
|
||||
Сделать так, чтобы отправитель видел ход исполнения не только по одной плашке статуса.
|
||||
|
||||
### Что входит
|
||||
|
||||
- детальный экран внешнего контура
|
||||
- блок `Исходный запрос`
|
||||
- блок `Текущий статус`
|
||||
- mirrored activity stream
|
||||
- mirrored comments
|
||||
- mirrored files
|
||||
- mirrored description updates
|
||||
|
||||
### Важное правило
|
||||
|
||||
Исходный запрос не должен теряться.
|
||||
|
||||
Поэтому target-изменения лучше показывать отдельным блоком истории, а не просто затирать исходное описание.
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- если в target issue добавили файл, инициатор видит его в source-side карточке
|
||||
- если в target issue поменяли статус, это видно в source-side карточке
|
||||
- если в target issue написали комментарий, это видно в source-side карточке
|
||||
|
||||
### Статус
|
||||
|
||||
Реализовано частично.
|
||||
|
||||
Что уже работает:
|
||||
- source-side detail использует отдельный экран `Внешних контуров`
|
||||
- в карточке отображается блок маршрутизации с ключевой source-target связью
|
||||
- у отправителя открытый внешний запрос редактируется прямо из source-side карточки по полям `заголовок` и `описание`, даже без membership в target project
|
||||
- текущий статус берется из фактического state целевой задачи
|
||||
- если у инициатора нет membership в target project, карточка переключается в source-side readonly режим без прямого открытия чужого проекта
|
||||
- блок `Маршрутизация` перестроен в фиксированный формат `3 x 3`
|
||||
- в `Маршрутизацию` перенесены `Назначенный` и `Срок выполнения`
|
||||
- в блоке `Свойства` убраны дубли `Внешний контур`, `Назначенный` и `Срок выполнения`
|
||||
- название исходного внутреннего контура в карточке маршрутизации берется из живого проекта, а не из застывшего metadata snapshot
|
||||
- для закрытого внешнего запроса доступны source-side действия `Принять` и `Отклонить`
|
||||
- `Принять` фиксирует решение источника в bridge metadata и помечает запрос как принятый во внутренний контур
|
||||
- `Отклонить` требует комментарий причины, возвращает target issue в default-state целевого проекта и переносит source-side карточку обратно в список `Открытые`
|
||||
- source-side readonly карточка зеркалит актуальные комментарии, вложения и activity целевой задачи
|
||||
- вложения доступны через proxy download endpoint без прямого membership в target project
|
||||
- detail карточка source-only пользователя обновляется polling-ом и подтягивает новые комментарии без ручной перезагрузки
|
||||
- инициатор может отправить комментарий обратно во внешний контур прямо из source-side карточки
|
||||
|
||||
Что остается:
|
||||
- зеркалирование inline-файлов из комментариев и описания, а не только issue attachments
|
||||
- realtime вместо polling
|
||||
- отдельная сущность или шаг для переноса принятого результата во `Внутренний контур`
|
||||
|
||||
## Этап 4. Уведомления
|
||||
|
||||
### Цель
|
||||
|
||||
Не заставлять инициатора вручную проверять изменения.
|
||||
|
||||
### Что входит
|
||||
|
||||
- in-app notification на:
|
||||
- принятие
|
||||
- перевод статуса
|
||||
- добавление файла
|
||||
- новый комментарий
|
||||
- завершение
|
||||
- отмену
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- инициатор получает уведомления по ключевым событиям жизненного цикла внешнего запроса
|
||||
|
||||
### Статус
|
||||
|
||||
Реализовано частично.
|
||||
|
||||
Что уже работает:
|
||||
- создаются in-app уведомления по изменениям целевой задачи внешнего контура
|
||||
- покрыты события:
|
||||
- смена статуса
|
||||
- новый комментарий
|
||||
- изменение описания
|
||||
- новое вложение
|
||||
- уведомление привязано к source project, а не требует membership в target project
|
||||
- notification payload несет `external contour request id` и `target issue id`
|
||||
- список уведомлений помечает такие записи как `is_external_contour = true`
|
||||
- notification preview может открыть source-side карточку внешнего контура, а не обычный issue preview
|
||||
- открытие source-side карточки помечает связанные unread уведомления как прочитанные и снимает индикатор новых изменений в списке
|
||||
|
||||
Что остается:
|
||||
- in-app уведомления на явные source-side решения `Принять / Отклонить`
|
||||
- отдельный индикатор новых изменений в списке `Открытые / Завершенные`
|
||||
- push/realtime канал вместо обычного цикла обновления UI
|
||||
|
||||
## Этап 5. Полировка и правила эксплуатации
|
||||
|
||||
### Что входит
|
||||
|
||||
- edge cases
|
||||
- повторная отправка
|
||||
- отмена
|
||||
- защита от удаления target issue
|
||||
- аудит прав
|
||||
- тест-кейсы
|
||||
- регламент эксплуатации
|
||||
|
||||
## Этап 6. Единый shell карточки внешнего контура
|
||||
|
||||
### Цель
|
||||
|
||||
Привести карточку деталей `Внешних контуров` к тому же UX-паттерну, что и во `Внутреннем контуре`, не ломая при этом внешний data-flow.
|
||||
|
||||
### Что входит
|
||||
|
||||
- общий shell открытия карточки
|
||||
- тот же класс верхнего action-bar:
|
||||
- закрытие просмотра
|
||||
- полноэкранный режим
|
||||
- переключение макета
|
||||
- подписка или отписка
|
||||
- копирование ссылки
|
||||
- меню дополнительных действий
|
||||
- переиспользование общего представления shell без подмены доменной модели внешнего контура
|
||||
- сохранение внешнеконтурного body:
|
||||
- `Маршрутизация`
|
||||
- зеркальные комментарии
|
||||
- зеркальные вложения
|
||||
- external lifecycle
|
||||
|
||||
### Что не входит
|
||||
|
||||
- две системные зоны `Исходящие / Входящие`
|
||||
- пользовательские колонки
|
||||
- drag-and-drop
|
||||
- насильственный перевод внешнего запроса в обычный issue detail
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- карточка `Внешних контуров` открывается по тому же UX-паттерну, что и внутренний peek
|
||||
- source-only сценарий не ломается
|
||||
- body карточки остается внешнеконтурным
|
||||
|
||||
### Статус
|
||||
|
||||
Запланировано.
|
||||
|
||||
Подробно описано в:
|
||||
- [11_STEP_external-contours-detail-shell.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/11_STEP_external-contours-detail-shell.md)
|
||||
|
||||
## Этап 7. Двусторонняя доска `Исходящие / Входящие`
|
||||
|
||||
### Цель
|
||||
|
||||
Дать проекту единый рабочий экран межконтурной работы, где видны и отправленные, и полученные запросы.
|
||||
|
||||
### Что входит
|
||||
|
||||
- две фиксированные системные зоны:
|
||||
- `Исходящие`
|
||||
- `Входящие`
|
||||
- единый board-level data contract
|
||||
- фильтрация обеих зон по аналогии с `Внутренним контуром`
|
||||
- счетчики
|
||||
- открытие карточки в shell этапа 6
|
||||
|
||||
### Важное правило
|
||||
|
||||
Это не kanban статусов.
|
||||
|
||||
Во `Внешних контурах`:
|
||||
- нет drag-and-drop между блоками
|
||||
- блоки означают представления по направлению и фильтрам
|
||||
- смена состояния не должна кодироваться визуальным переносом карточки
|
||||
|
||||
### Что не входит
|
||||
|
||||
- пользовательские кастомные зоны
|
||||
- свободный конструктор колонок
|
||||
- превращение доски во второй workflow движок
|
||||
|
||||
### Критерий приемки
|
||||
|
||||
- пользователь видит и `Исходящие`, и `Входящие`
|
||||
- отправленные запросы не теряются после отправки
|
||||
- обе системные зоны фильтруются через единый механизм
|
||||
- карточка из любой зоны открывается единообразно
|
||||
|
||||
### Статус
|
||||
|
||||
Запланировано.
|
||||
|
||||
Подробно описано в:
|
||||
- [12_STEP_external-contours-bidirectional-board.md](/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER/docs_prod/1_STEP_cross-project-task-routing/12_STEP_external-contours-bidirectional-board.md)
|
||||
|
||||
## Этап 8. Пользовательские представления поверх двусторонней доски
|
||||
|
||||
### Цель
|
||||
|
||||
Разрешить пользователю собирать собственные рабочие выборки поверх уже стабилизированной двусторонней доски.
|
||||
|
||||
### Что входит
|
||||
|
||||
- пользовательские блоки или представления
|
||||
- пользовательское имя блока
|
||||
- сохранение набора фильтров
|
||||
- персональные рабочие выборки по контурам, статусам, пользователям и другим признакам
|
||||
|
||||
### Важное правило
|
||||
|
||||
Пользовательские блоки не меняют базовый принцип:
|
||||
- это не стадии workflow
|
||||
- это не drag-and-drop
|
||||
- это не замена `Внутреннего контура`
|
||||
|
||||
### Зависимость
|
||||
|
||||
Этап начинается только после стабилизации этапов 6 и 7.
|
||||
|
||||
### Статус
|
||||
|
||||
Запланировано как следующий слой развития, но не входит в ближайший обязательный срез.
|
||||
|
||||
## Технические решения, которые желательно держать с самого начала
|
||||
|
||||
### 1. Не ломать штатный intake
|
||||
|
||||
Он остается отдельным продуктовым модулем.
|
||||
|
||||
### 2. Явно хранить source/target связь
|
||||
|
||||
Даже если первая версия идет через `IntakeIssue.extra`, связь не должна быть неявной.
|
||||
|
||||
### 3. Использовать фактический статус target issue
|
||||
|
||||
В source-side плашке лучше показывать не abstract intake status, а реальный текущий статус исполнения.
|
||||
|
||||
### 4. Не пытаться делать полную двустороннюю редакцию сразу
|
||||
|
||||
На старте безопаснее сделать:
|
||||
- создание из источника
|
||||
- исполнение в цели
|
||||
- синхронизацию результата обратно в источник
|
||||
|
||||
## Открытые вопросы
|
||||
|
||||
### 1. Что именно делает `Принять`
|
||||
|
||||
Нужно зафиксировать конечную бизнес-логику:
|
||||
- `Принять` только ставит source-side решение `accepted`
|
||||
- `Принять` создает отдельную сущность во `Внутреннем контуре`
|
||||
- `Принять` переводит карточку в отдельный внутренний статус без создания дубликата
|
||||
|
||||
Это главный блокирующий вопрос перед следующим этапом.
|
||||
|
||||
### 2. Где дальше живет принятый запрос
|
||||
|
||||
Нужно решить:
|
||||
- карточка остается во `Внешних контурах` как историческая запись
|
||||
- карточка уходит во `Внутренний контур`
|
||||
- карточка одновременно видна в обоих местах, но с разной ролью
|
||||
|
||||
### 3. Нужна ли отдельная сущность source-side
|
||||
|
||||
Нужно принять решение:
|
||||
- достаточно ли текущей source-side проекции поверх bridge metadata
|
||||
- или уже пора вводить отдельную таблицу/модель для внешних контуров
|
||||
|
||||
### 4. Файлы
|
||||
|
||||
Нужно решить:
|
||||
- достаточно ли proxy-доступа к файлам целевой задачи
|
||||
- или файлы надо физически копировать в source-side representation
|
||||
- нужно ли зеркалировать inline-файлы из описания и комментариев
|
||||
|
||||
### 5. Комментарии
|
||||
|
||||
Нужно решить:
|
||||
- source-side reply остается облегченной обратной связью
|
||||
- или нужен полноценный двусторонний поток комментариев как единый discussion-thread
|
||||
|
||||
### 6. Уровень realtime
|
||||
|
||||
Нужно решить:
|
||||
- хватает ли polling для PoC
|
||||
- или следующий этап уже должен включать push/realtime события
|
||||
|
||||
### 7. Счетчики и вкладки
|
||||
|
||||
Нужно решить:
|
||||
- нужен ли отдельный unread-counter по вкладкам `Открытые / Завершенные`
|
||||
- нужен ли отдельный сегмент для запросов, принятых во `Внутренний контур`
|
||||
|
||||
### 8. Право редактирования после отправки
|
||||
|
||||
Нужно решить:
|
||||
- отправитель редактирует только `заголовок` и `описание`
|
||||
- или после отправки он может менять еще `срок`, `назначенного`, `приоритет`, `метки`
|
||||
|
||||
### 9. Доступ к target issue
|
||||
|
||||
Нужно решить:
|
||||
- должен ли инициатор иметь прямую ссылку на target issue
|
||||
- или source-side карточка должна оставаться единственной точкой просмотра для пользователей без membership
|
||||
|
||||
Текущее решение:
|
||||
- при отсутствии membership в target project прямой переход в target issue скрывается
|
||||
- карточка остается доступной из source project
|
||||
|
||||
## Рекомендуемый порядок фактической разработки
|
||||
|
||||
1. Этап 0
|
||||
2. Этап 1
|
||||
3. Этап 2
|
||||
4. Этап 3
|
||||
5. Этап 4
|
||||
6. Этап 5
|
||||
|
||||
Это даст быстрый полезный результат и не загонит проект в ранний тяжелый refactor.
|
||||
Reference in New Issue
Block a user