26 KiB
Межпроектная маршрутизация задач
Цель
Добавить в NODE.DC TM отдельный сценарий межпроектной постановки задач между контурами без перепрошивки штатного Intake.
Базовая идея:
Рабочие элементыпереименовываются вВнутренний контур- рядом появляется новый модуль
Внешние контуры - пользователь из проекта-источника создает внешний запрос
- запрос уходит в целевой проект
- в целевом проекте он становится обычной задачей
- в проекте-источнике сохраняется видимый объект маршрутизации со статусом, историей и материалами
Почему выбран именно этот путь
Не трогаем штатный Intake как пользовательский модуль.
Используем его только как внутренний backend-мост, потому что:
- механизм уже умеет создавать bridge между
IssueиIntakeIssue - уже есть переход из
TRIAGEв default-state проекта - уже есть
extra JSONдля метаданных маршрутизации - это самый безопасный путь для форка и дальнейших обновлений
Термины
Внутренний контур
То, что сейчас в UI является обычными рабочими элементами проекта.
Внешние контуры
Новый отдельный модуль проекта, через который задача отправляется в другой проект внутри того же workspace.
Проект-источник
Проект, из которого инициируется запрос.
Целевой проект
Проект, в котором задача реально исполняется.
Исходная карточка внешнего контура
Карточка или запись в проекте-источнике, где инициатор видит:
- текущий статус
- целевой проект
- назначенного исполнителя
- историю обработки
- файлы
- уведомления о ходе работы
Целевая задача
Обычная задача в целевом проекте, которая попадает в обычный workflow этого проекта.
Ключевой продуктовый результат
Пользователь из Менеджеры должен иметь возможность:
- открыть
Внешние контуры - выбрать целевой проект, например
Бухгалтерия - описать запрос
- назначить исполнителя из
Бухгалтерия - отправить запрос
После этого:
- у
Бухгалтерияпоявляется обычная задача в их проекте - у отправителя в
Менеджерыпоявляется запись воВнешних контурах - у этой записи есть статусная пришлепка
- при любом изменении статуса в целевом проекте статус в источнике обновляется
- если в целевом проекте меняют описание, прикладывают файлы, комментируют или закрывают задачу, это отражается в источнике
- инициатор получает уведомления о существенных изменениях
Текущий статус реализации
На текущем этапе уже реализовано:
- отдельный модуль
Внешние контуры - отдельный backend endpoint маршрутизации
- создание target issue в целевом проекте через intake bridge
- немедленный перевод target issue в обычный workflow целевого проекта
- source-side список отправленных запросов
- source-side детальный экран на базе shell
Предложений - status pill по фактическому состоянию target issue
- workspace-wide выбор целевого внешнего контура по policy:
- тот же
workspace - у целевого проекта включен модуль
- прямой membership в target project не требуется
- тот же
- source-side карточка как основная точка работы отправителя, если у него нет доступа в целевой проект
- source-side редактирование открытого запроса:
заголовокописание
- source-side действия:
ПринятьОтклонитьОтвет во внешний контур
- зеркалирование из целевой задачи в source-side карточку:
- комментарии
- вложения
- activity
- обновления статуса
- proxy download для вложений без прямого membership в target project
- unread-индикатор новых изменений по source-side карточке
- блок
Маршрутизацияв фиксированном формате3 x 3
Freeze point на 2026-04-19
Текущий этап временно заморожен.
Заморозка делается после достижения рабочего вертикального среза:
- запрос можно отправить из проекта-источника в другой проект того же
workspace - в целевом проекте создается обычная задача и сразу попадает в обычный workflow
- отправитель видит свой source-side список и карточку без обязательного доступа в чужой проект
- в source-side карточке видны статус, маршрут, назначенный, срок, комментарии, вложения и activity из целевого контура
- отправитель может поправить ошибку в
заголовкеиописании, пока запрос открыт - отправитель может принять результат во внутренний контур или вернуть запрос обратно во внешний контур с комментарием причины
На этом месте разработка следующего шага останавливается до фиксации продуктовых решений.
Зафиксированные продуктовые решения на 2026-04-20
После freeze point приняты дополнительные продуктовые решения по следующему циклу развития Внешних контуров.
1. Нужны две обязательные системные зоны
Во Внешних контурах должны появиться:
ИсходящиеВходящие
Исходящие обязательны, потому что пользователь должен видеть запросы, которые он сам отправил в другие контуры, до и после обработки.
Входящие обязательны, потому что проект должен видеть запросы, пришедшие к нему из других контуров, в отдельном специализированном режиме работы, а не только как обычные задачи Внутреннего контура.
2. Обе зоны должны фильтроваться так же гибко, как во Внутреннем контуре
Минимальный целевой принцип:
- фильтрация по пользователям
- фильтрация по статусам
- фильтрация по назначенным
- фильтрация по автору
- фильтрация по контурам и связанным проектам
То есть Внешние контуры должны получить не просто статичный список, а управляемое рабочее представление.
3. Карточка деталей внешнего контура должна перейти на тот же UX-паттерн, что и во Внутреннем контуре
При клике по карточке должна открываться панель того же класса:
- закрыть просмотр
- открыть на весь экран
- переключить макет
- подписка или отписка
- копирование ссылки
- меню дополнительных действий
При этом:
- действие удаления в этом shell не является обязательным
- тело карточки остается внешнеконтурным, а не превращается в обычную карточку внутренней задачи
4. Внешний контур — это не workflow-kanban
Важно зафиксировать заранее:
- пользователь не должен перетаскивать задачи между блоками
- блоки во
Внешних контурах— это представления и выборки, а не стадии исполнения - нельзя переносить сюда механику drag-and-drop из
Внутреннего контура
5. Пользовательские колонки нужны, но не входят в ближайший обязательный срез
Собственные пользовательские блоки и сортировки нужны как следующий этап развития, но не должны размыть ближайшие обязательные поставки:
- единый shell карточки внешнего контура
- двусторонняя доска
Исходящие / Входящие
6. Архитектура должна остаться расширяемой
Следующий слой развития не ограничивается только внешними контурами.
Дальше в проекте могут появиться:
- новые типы досок
- агентные доски
- специализированные мониторинговые представления
- пользовательские рабочие поверхности под разные роли
Поэтому нельзя решать следующий этап только переобертками и точечными хаками.
Но и полный демонтаж текущего проекта ради абстрактной платформы тоже недопустим.
Рабочий принцип:
- не ломать текущий runtime
- не дублировать уже существующие механики без причины
- выносить только те контракты, которые реально переиспользуются дальше
Что нужно решить перед продолжением
- Что именно делает действие
Принять:- только фиксирует решение источника
- создает отдельную сущность во
Внутреннем контуре - или переводит внешний запрос в отдельный внутренний режим без дублирования сущностей
- Должен ли принятый запрос оставаться во
Внешних контурахкак историческая карточка, или он должен исчезать из рабочего списка и жить только воВнутреннем контуре - Нужен ли отдельный статус или отдельная вкладка для запросов, которые уже приняты во
Внутренний контур - Должна ли коммуникация по комментариям быть полностью двусторонней, или source-side ответов достаточно только для возврата и уточнений
- Нужно ли физически копировать файлы в source-side представление, или для PoC достаточно proxy-доступа к файлам целевой задачи
- Нужно ли переводить обновление карточки с polling на realtime/push уже в следующем этапе, или polling пока приемлем
- Нужны ли отдельные счетчики непрочитанных изменений по вкладкам
ОткрытыеиЗавершенные - Должен ли отправитель после создания запроса иметь право менять только
заголовокиописание, или еще иназначенного,срок,приоритет,метки - Нужно ли сохранять запрет на прямой переход в целевую задачу для пользователей без membership в target project как постоянное правило
- Какой финальный lifecycle должен быть у запроса после возврата, принятия, завершения и отмены, чтобы source-side карточка не стала второй несогласованной системой учета
Обязательные требования
1. Отдельный модуль
Внешние контуры не должны быть переименованным Intake.
Это отдельная новая вкладка проекта.
2. Обычная задача в целевом проекте
Задача не должна висеть в ручном triage.
После отправки она должна сразу попадать в обычный workflow целевого проекта, в его default-state.
3. Статусная пришлепка в источнике
У каждой записи во Внешних контурах в списке должен быть видимый статус.
Для первой версии правильнее показывать фактическое имя текущего статуса целевой задачи:
В планеК выполнениюВ работеГотовоОтменено- либо любой другой кастомный статус целевого проекта
То есть источник видит не абстрактное accepted, а реальный текущий статус исполнения.
4. Зеркалирование изменений из целевого проекта в источник
Изменения в целевой задаче должны отражаться в исходной карточке внешнего контура.
Минимальный обязательный набор:
- изменение статуса
- изменение названия
- изменение описания
- добавление/удаление файлов
- комментарии и служебные заметки по задаче
- закрытие/отмена задачи
5. Уведомления инициатору
Инициатор должен получать уведомления, когда:
- задача принята в работу
- задача переведена в другой статус
- добавлен файл
- добавлен комментарий
- задача завершена
- задача отменена
6. Трассировка между источником и целью
Связь между источником и целевой задачей должна быть явной и восстановимой.
Нельзя делать фичу как “создали задачу и забыли”.
Архитектурный подход
Общая схема
Используем существующий intake bridge как транспортный слой:
- создаем
Issueв целевом проекте - создаем
IntakeIssue - сразу переводим bridge в
ACCEPTED - целевая задача попадает в default-state проекта
Но только этого уже недостаточно.
Из-за требований на статусную пришлепку, зеркалирование файлов и уведомления нужен еще source-side слой отображения.
Что остается от текущей идеи варианта 2
Сохраняем:
- reuse intake backend-механики
- отдельный orchestration endpoint
- отдельный фронтовый модуль
Внешние контуры
Расширяем:
- добавляем источник правды для source-side карточки
- добавляем синхронизацию изменений из target issue в source representation
- добавляем уведомления
Рекомендуемая модель данных для первой итерации
Обязательная связь
Нужна явная пара:
source_project_idsource_request_idtarget_project_idtarget_issue_id
Метаданные bridge
В IntakeIssue.extra храним:
- тип моста:
external-contours - источник
- цель
- автора
- временные метки
Пример:
{
"bridge": "external-contours",
"source_project_id": "uuid",
"source_project_name": "Менеджеры",
"target_project_id": "uuid",
"target_project_name": "Бухгалтерия",
"requested_by_id": "uuid",
"requested_by_name": "Иван Петров",
"requested_at": "2026-04-18T19:00:00Z"
}
Source-side представление
Для source-side части есть два пути:
- Легкая проекция без отдельной таблицы
- список
Отправленныесобирается поIntakeIssue.extra - детали берутся из целевой задачи
- Отдельная source-side сущность или shadow-record
- отдельная запись для внешнего контура в проекте-источнике
- в ней хранится mirrored state
Для требований текущего этапа безопаснее считать, что source-side проекция понадобится.
Причина:
- нужен список со статусом
- нужны файлы в источнике
- нужна история изменений
- нужны уведомления
Простого “читать target issue на лету” для этого, скорее всего, будет мало.
UX первой рабочей вертикали
Модуль Внешние контуры
В проекте появляется новая вкладка:
Внешние контуры
Внутри:
- кнопка
Новый внешний запрос - список
Открытые - список
Завершенные
Форма создания
Поля:
- целевой проект
- название
- описание
- исполнитель из целевого проекта
- приоритет
- срок
- метки
Вложения можно заложить сразу в спецификацию, но в первую техническую поставку лучше включать аккуратно.
Карточка в списке
В строке списка должны быть:
- название
- целевой проект
- исполнитель
- дата создания
- статусная пришлепка
- индикатор новых изменений
Детальный экран внешнего контура
Детальный экран источника не должен быть просто копией target issue.
Правильнее собрать его из блоков:
- исходный запрос
- текущий статус
- целевой проект и исполнитель
- история изменений
- синхронизированные файлы
- комментарии/обновления
Это безопаснее, чем пытаться перетирать исходное описание данными целевого проекта.
Правила синхронизации
Направления
Источник -> цель
На этапе создания отправляем:
- название
- описание
- исполнителя
- приоритет
- срок
- метки
Цель -> источник
После создания отражаем обратно:
- текущий статус
- изменения описания
- комментарии
- файлы
- итоговый результат
Что должно быть синхронизировано в обязательном порядке
target issue state.nametarget issue updated_at- файлы target issue
- пользовательские комментарии
- итоговый resolution state
Что пока не нужно считать обязательным
- полная двусторонняя редакция из источника после отправки
- редактирование чужих project labels через источник
- полный realtime-collab режим
Уведомления
Минимальный набор событий:
- запрос создан
- задача принята
- статус изменен
- добавлен файл
- добавлен комментарий
- задача завершена
- задача отменена
Каналы первой версии:
- in-app notifications
Каналы последующих итераций:
- внешние integrations
Ограничения текущего этапа
1. Вложения сейчас хрупкие
Текущий runtime уже показывал хрупкость attachment flow.
Поэтому вложения нужно учитывать в дизайне, но внедрять аккуратно и тестировать отдельно.
2. Права сложнее, чем кажется
Отправитель должен иметь право отправлять запрос из source project, но не обязан быть участником target project.
При этом:
- target assignee должен быть участником target project
- target issue создается в target project
- источник должен иметь возможность видеть результат обработки без полного membership в target project
3. Простая “копия intake” уже недостаточна
Как только добавляются:
- статусная пришлепка
- файлы
- история
- уведомления
фича перестает быть просто формой создания.
Нужен отдельный источник правды для source-side представления.
Что считаем текущим этапом
Текущий этап — это не финальная реализация, а проектирование и запуск вертикального среза.
В этот этап входят:
- фиксация терминологии
- фиксация архитектурного подхода
- разбиение на поставки
- определение обязательных требований для первой версии
- определение границ MVP
Подробная поэтапная разработка описана в: