Коммуникационная платформа Ruxeo: Assignments + Chat#
Тип документа: L3 архитектурный артефакт. Описывает замысел, текущее состояние реализации и roadmap. Source: ветка
sansay365, 2026-05-17. Backend вmodules/ruxeo-base-core+modules/ruxeo-base-studio, UI там же (web-resources). Mobile-клиент — в отдельном репо/home/ssay/Project/ruxeo-ai-services/mobile/, вне scope этого документа.
§1 Замысел#
Коммуникации в Ruxeo строятся вокруг двух связанных сущностей, доступных пользователю на каждой точке платформы:
- Assignment — universal-носитель Задачи. Универсальный case-management контейнер: исполнитель + соисполнители, deadline, иерархия подзадач, привязка к workflow или агенту, встроенный чат. Базовый doctype в
ruxeo-base-studio, доопределяется функциональными модулями (DocFlow, КЭДО, …) под свои случаи. - Chat — каналы общения с тремя самостоятельными режимами:
- DIRECT — 1:1 переписка между двумя пользователями;
- GROUP — мульти-участник чат без анкера на документ;
- DOCUMENT / WORKFLOW / ASSIGNMENT — встроенный чат, привязанный к конкретному объекту, ACL независим от объекта.
Эти две сущности образуют четыре сценария коммуникации, доступные пользователю:
| Сценарий | Носитель | Точка входа |
|---|---|---|
| «Поговорить с коллегой» | DIRECT chat | Drawer «Чаты» |
| «Обсудить в команде» | GROUP chat | Drawer «Чаты» |
| «Спросить по документу» | DOCUMENT chat | Метаданные документа (раскрывающаяся панель) |
| «Дать поручение» | Assignment + ASSIGNMENT chat | UI «Поручить» (внутри чата или контекстного меню) |
Пользователю не нужно выбирать модуль — каналы коммуникации одинаково доступны на любой странице платформы. Drawer «Чаты» виден всем authenticated users; chat-панель — на любом документе с facet-ом Chattable.
§2 Архитектура#
§2.1 Assignment — universal case container#
Doctype: Assignment (modules/ruxeo-base-studio/src/main/resources/OSGI-INF/rxbm-document-types.xml:454).
- Extends
File. - Facets:
Folderish,Versionable,Commentable,NXTag,Registration,TitleInfo,Recurring,Chattable. - Schema:
rxbm_assignment(префиксasm).
Поля схемы (rxbm_assignment.xsd):
| Поле | Тип | Назначение |
|---|---|---|
asmKind |
enum | Тип Задачи: free (свободная), from_workflow (порождённая WF), from_agent (порождённая AI-агентом), from_chat (созданная из чата) |
asmAssignee |
user-ref | Основной исполнитель |
asmCoExecutors |
user-list | Соисполнители (см. §2.1.1) |
asmInitiator |
user-ref | Постановщик |
asmTitle, asmDescription |
string, html | Содержание задачи |
asmDueDate, asmPriority, asmStatus |
date, enum, enum | SLA + статус (см. SLA.md) |
asmHierarchyLevel, asmParentRef |
int, doc-ref | Иерархия подзадач |
asmWorkflowInstanceId |
string | Backlink на запустившую WF-инстанцию (если есть) |
asmChatRoomRef |
doc-ref | Backlink на встроенный chat-room (lazy-created) |
Lifecycle: assignment_lifecycle (определён в ruxeo-docflow-studio/.../rxdf-lifecycles.xml, шаги: draft → linked_to_wf_step | agent_generated | onExecution → onReview → completed | cancelled | archived).
Physical location: хранится в AssignmentsFolder под путём БЕ (resolution через RxasmAssignmentService.resolveAssignmentsFolder(buCode)).
§2.1.1 Co-executors как набор#
asmCoExecutors — stringList имён пользователей. Operations (RxasmAddCoExecutor, RxasmRemoveCoExecutor, RxasmUpdateCoExecutor) поддерживают diff-операции. ACL Assignment-а наследует прав на запись для всех co-executors через ComputedGroups (см. EMPLOYEE_DELEGATION.md §2.1).
§2.1.2 Sub-assignments#
Folderish + asmParentRef + asmHierarchyLevel. Operation RxasmCreateSubAssignment (assignment-operations.xml:43) создаёт child-Assignment внутри parent-а. Используется для декомпозиции крупных задач.
§2.1.3 Связка с Workflow#
asmWorkflowInstanceId хранит referrer на запустившую DocumentRoute. При завершении WF-step-а (workflowTaskCompleted) listener (TBD) обновляет asmStatus и пишет событие в встроенный chat. Деталь — см. DYNAMIC_APPROVAL_WORKFLOW.md.
§2.1.4 Связка с AI-агентом#
asmKind="from_agent" помечает Assignment-ы, порождённые ruxeo-ai-services/agent/. Агент создаёт Assignment через operation RxasmAssignment.CreateFromChat с source=AGENT (см. §2.2.5).
§2.2 Chat — RuxeoChatRoom#
Doctype: RuxeoChatRoom (rxbm-document-types.xml:257).
- Extends
Document(lightweight, не Folderish). - Schema:
ruxeo_chat_room(префиксrcr). - Comments как messages (Nuxeo native, doctype
Comment).
Поля схемы:
| Поле | Тип | Назначение |
|---|---|---|
rcrKind |
enum | DIRECT / GROUP / DOCUMENT / WORKFLOW / ASSIGNMENT |
rcrContextType, rcrContextId |
string, string | Слабая ссылка на объект (для DOCUMENT/WORKFLOW/ASSIGNMENT) — НЕ parent в дереве, чтобы ACL не наследовался |
rcrParticipants |
string-list | Список user-id participants |
rcrLastMessageId, rcrLastMessageDate |
string, date | Для сортировки и preview |
rcrCreatedBy, rcrCreated |
string, date | Audit |
rcrTitle |
string | Только для GROUP и для context-aware (autocomputed для DIRECT/DOCUMENT) |
Message doctype — обычный Nuxeo Comment, parent-document = ChatRoom. Поле rcm:reactions (расширение Comment-а) хранит JSON-карту {emoji: [userIds]} для реакций.
§2.2.1 Пять kind-ов с одним кодом#
В отличие от типичного «отдельный doctype под каждый use-case», RuxeoChatRoom универсальный — поле rcrKind разграничивает UX:
- DIRECT —
participants.size() == 2,contextType == null. UI: автогенерируемый title из имени собеседника. Поиск/создание идемпотентно черезRuxeo.Chat.GetOrCreateDirectRoom(userA, userB). - GROUP —
participants.size() > 2,contextType == null. UI: editable title, add/remove participants. - DOCUMENT —
contextType = "Document",contextId = <uuid>. Lazy-created при первом разворачиванииrxat-chat-panelна документе. Participants seed-ятся из ACL документа в момент создания (см. §2.2.4). - WORKFLOW —
contextType = "DocumentRoute",contextId = <wf-instance-uuid>. Создаётся при старте WF-инстанции, participants — все assignees всех узлов. - ASSIGNMENT —
contextType = "Assignment",contextId = <asm-uuid>. Создаётся одновременно с Assignment, participants —asmAssignee + asmCoExecutors + asmInitiator.
UI-компонент ruxeo-chat-room.js рендерит один и тот же интерфейс для всех kind-ов, отличаясь только header-section (avatar/title/subtitle, см. rxbm-chats-page.html:329-340).
§2.2.2 Lazy-create и идемпотентность#
Operation Ruxeo.Chat.CreateDocumentChat(docId) (используется из rxat-chat-panel):
1. Ищет существующий chat-room с contextType="Document" AND contextId=docId.
2. Если найден — возвращает его.
3. Если нет — создаёт, заполняет participants из ACL документа (текущие пользователи с Read).
4. Возвращает ChatRoom.
Аналогично для WORKFLOW (Ruxeo.Chat.GetOrCreateWorkflowRoom) и ASSIGNMENT-чатов.
§2.2.3 ACL decoupling#
Ключевая особенность — ACL чата независим от ACL объекта-контекста.
Реализация (RuxeoChatServiceImpl.java:158-180, setupChatRoomACL):
- При создании ChatRoom-а вызывается acp.removeACL("inherited") + setUseInheritedAcl(false).
- Затем ACE для каждого participant-а явно прописываются (Read + Write).
- Документ-контекст в дереве — НЕ parent ChatRoom-а (ChatRoom живёт в /management/chats/, не как child documenta).
Следствие: - Можно пригласить в DOCUMENT-чат внешнего эксперта, не давая ему доступа к самому документу. - Удаление пользователя из ACL документа не удаляет его из чата (пока не вызвать explicit remove-participant). - Закрытие WF-инстанции не закрывает WORKFLOW-чат — он остаётся как history.
§2.3 Транспорт — PubSub + SSE#
Двухуровневая схема для real-time доставки.
§2.3.1 SSE endpoint#
modules/ruxeo-base-core/src/main/java/ru/ruxeo/base/chat/sse/RuxeoChatSSEResource.java:51:
@WebObject(type = "RuxeoChatSSE")
@Path("/chat/sse")
public class RuxeoChatSSEResource {
@GET
@Path("/room/{roomId}")
@Produces(MediaType.SERVER_SENT_EVENTS)
public EventOutput streamRoom(@PathParam("roomId") String roomId) { ... }
}
WebEngine module: MANIFEST.MF → Nuxeo-WebModule: …;name=ruxeo-chat-sse;extends=base;package=ru/ruxeo/base/chat/sse;headless=true.
RuxeoChatSSEEventManager (in-memory registry на узле) держит per-room список открытых SSE-sinks. При получении события от PubSub bridge — fan-out на локальные sinks.
§2.3.2 PubSub bridge (кластер-fanout)#
ChatPubSubBridge (rxbm-chat-pubsub.xml):
- Topic: chat.events.
- Envelope: {roomId, eventType, data} (JSON).
- На каждом узле — subscriber, который при получении envelope-а распределяет на RuxeoChatSSEEventManager своего узла.
- Backend — Nuxeo PubSubService (Redis/JGroups по platform config).
Producer pattern (RuxeoChatServiceImpl.java):
§2.3.3 Типы событий#
| Event | Publisher | Subscriber action |
|---|---|---|
message_added |
RuxeoChatCommentEventListener на commentAdded |
UI добавляет message в feed |
message_updated |
listener на commentUpdated |
UI обновляет content (включая reactions snapshot) |
message_deleted |
listener на commentDeleted |
UI скрывает message |
chat_read |
markRead() |
UI снимает unread badge у других participants |
typing_started |
ruxeo-chat-input.js debounce |
UI отображает «X пишет…» (см. §2.5.4) |
participant_added / _removed |
RuxeoChatServiceImpl.{addParticipant,removeParticipant} |
UI обновляет список + ACL |
reaction_added / _removed |
RxbmReactToChatMessageOperation |
UI обновляет message reactions |
Cluster-safety: события dispatch-ятся через PubSub, локальный SSE-manager — только для presence-tracking. Reconnect клиента — клиент сам refetch-ает state через REST (нет persistent message-queue в SSE).
§2.4 Read-state + Mute#
§2.4.1 RuxeoChatReadState doctype#
Отдельный lightweight-doctype (ruxeo-chat-read-state-types-contrib.xml:31):
- Schema: ruxeo_chat_read_state (префикс rcs).
- Хранится в директории /management/chat-read-states/.
Поля:
| Поле | Тип | Назначение |
|---|---|---|
| rcsUserId | string | User-ключ |
| rcsChatId | string | Chat-ключ |
| rcsLastReadMessageId | string | UUID последнего прочитанного message-а |
| rcsLastReadDate | date | Timestamp |
| rcsMuteLevel | enum | ALL (все нотификации) / MENTIONS (только при упоминании) / NONE (полная тишина) |
Один entry на пару (user, chat). Lazy-created при первом markRead.
§2.4.2 Unread computation#
Operation Ruxeo.Chat.GetUnreadInfo([roomIds]) возвращает per-chat:
Используется:
- rxat-chat-panel для бейджа на свёрнутой панели (§3.1.1).
- rxbm-chats-page для бейджа per-chat в списке + total-pill в drawer header.
- Mobile/portal-web — через тот же REST-операцией.
§2.4.3 Mute UX#
В ruxeo-chat-room.js:407-886 toggle между тремя уровнями. Иконки:
- ALL — communication:notifications
- MENTIONS — communication:notifications-active
- NONE — communication:notifications-off
Mute не влияет на доставку (SSE приходят всегда), но:
- MENTIONS — push/email только при упоминании user-а в message-е.
- NONE — push/email подавляются полностью, бейдж не растёт.
§2.5 Богатый функционал сообщений#
§2.5.1 Mentions#
ChatNotificationEventListener.java:53 — regex MENTION_PATTERN парсит @username в content message-а. Каждое упоминание:
- Расширяет recipients для notification до конкретного user-а (даже если у него mute=ALL).
- Инкрементит mentions counter в GetUnreadInfo.
§2.5.2 Reactions#
RxbmReactToChatMessageOperation.java:
- Properties: messageId, emoji, action (add/remove).
- Хранит JSON-карту {emoji: [userIds]} в rcm:reactions.
- При update эмитится message_updated event с полным snapshot реакций (idempotent).
UI: ruxeo-chat-room.js:753, 767-778 — _toggleReaction(). Полный emoji-picker не реализован, только +1/✓/?.
§2.5.3 Participants management#
ruxeo-chat-participants.html — отдельный side-panel с list + add/remove buttons (только для GROUP и ASSIGNMENT-чатов). API:
- Ruxeo.Chat.AddParticipant(chatId, userId) — добавляет в rcrParticipants + дополняет ACL.
- Ruxeo.Chat.RemoveParticipant(chatId, userId) — обратное, исключает ACE.
§2.5.4 Typing indicator#
ruxeo-chat-input.js:1025-1047 — debounced typing events (typing-start / typing-stop через PubSub). Backend (RuxeoChatSSEResource.java:49) пробрасывает event.
UI-отображение «X пишет…» — в коде помечено как Future (ruxeo-chat-input.js:1007). Sprint неизвестен.
§2.6 Notification digest#
Backend-механизм (см. отдельную NOTIFICATION_DIGEST.md) интегрирован с Chat:
ChatNotificationEventListener(ruxeo-chat-notification-listeners.xml) — слушаетcommentAdded/commentUpdated, фильтрует поrcsMuteLevel.- Templates:
chatNotificationTemplate.ftl,chatMentionNotificationTemplate.ftl,workflowChatNotificationTemplate.ftl(ruxeo-chat-notification-templates.xml). - Feature flag:
rxbm.notifications.chat.enabled(defaulttrue). - Digest агрегирует chat-сообщения в почасовой/дневной отчёт по адресату.
UI для per-user digest preferences (frequency, opt-out per-chat) — не реализован (см. §6).
§3 UI слой#
§3.1 Встроенный чат на документе#
§3.1.1 rxat-chat-panel behavior#
modules/ruxeo-attributes-studio/src/main/resources/web/nuxeo.war/ui/elements/rxat-chat-panel.html.
- Lazy: ChatRoom создаётся/загружается только при первом разворачивании панели (
:240-250). - Persisted UI state в
localStorageper(user, doc)-паре (:162-184). - Unread badge на свёрнутой панели через
Ruxeo.Chat.GetUnreadInfo(:200-222). - Embedded
<ruxeo-chat-room>+ SSE subscriptions при разворачивании (:131). - Height: 480px (
:81).
§3.1.2 Интеграция в rxat-metadata-layout#
rxat-metadata-layout.html:160 — chat-panel зашит как «Discussion» card в metadata-layout, доступна на всех doctype-ах с facet Chattable.
Все основные business-doctype Ruxeo (Contract, IncomingDocument, OutgoingDocument, Invoice, Assignment, …) имеют facet Chattable через rxbm-document-types.xml.
§3.2 Глобальная страница «Чаты»#
§3.2.1 Routes + Drawer#
- Drawer entry:
rxbm-drawer-slots.html:53-69— iconcommunication:chat, order 40, без user-filter (виден всем authenticated). - Drawer component:
rxbm-chats-drawer.html— header с total-unread-pill, menu-item на/chats. - Route:
/chats(rxbm-pages-routes-slots.html:33-37).
§3.2.2 Two-pane layout#
rxbm-chats-page.html:
- Sidebar 320px: room-list, search, kind-filter, mute-icons (:165-167, 300-317), unread-pill per room (:90-104).
- Main: открытый <ruxeo-chat-room> с full message-feed.
- Subtitle per room показывает kind: DOCUMENT, WORKFLOW, ASSIGNMENT, DIRECT, GROUP (:329-340).
§3.3 Home chat widget#
ruxeo-home-chat-widget.html — two-column виджет на главной странице (nuxeo-home.html):
- Left: список contacts (DIRECT-чаты last-active).
- Right: открытый chat-room.
- Поддерживает гибрид: ruxeo-agent-chat-room (для AI-чатов) + ruxeo-chat-room (обычные).
§3.4 Assignment UI#
modules/ruxeo-base-studio/src/main/resources/web/nuxeo.war/ui/document/assignment/:
- nuxeo-assignment-view-layout.html — табы: Main / Sub-Assignments / Execution / History.
- nuxeo-assignment-metadata-layout.html, nuxeo-assignment-create-layout.html, nuxeo-assignment-edit-layout.html.
- Отчёты:
- rxbm-my-assignments-report.html — мои поручения.
- rxbm-management-assignments-report.html — администрирование (для руководителей).
Dedicated /assignments page + drawer entry — не реализованы (см. §6).
§3.5 Mobile#
Mobile-клиент (React Native) живёт в /home/ssay/Project/ruxeo-ai-services/mobile/. Использует те же REST/SSE endpoints. Вне scope этого документа.
§4 Extension model для модулей#
§4.1 Текущая модель — naked Assignment + facet#
Сейчас функциональные модули не наследуют Assignment в своих doctype-ах, а используют его «голым»:
<!-- ruxeo-docflow-studio/.../rxdf-document-types.xml -->
<doctype name="AssignmentsFolder" extends="Folder">
<subtypes>
<type>Assignment</type>
</subtypes>
</doctype>
DocFlow позволяет создавать Assignment внутри AssignmentsFolder, но Assignment остаётся базовым doctype-ом. Дополнительные поля DocFlow-специфичных задач сейчас не выделены — используется generic-схема.
§4.2 Возможные точки расширения#
Архитектурно поддержано следующее (но не используется массово):
Вариант А — facet over Assignment. Модуль создаёт свой facet с дополнительными схемами, навешивается на Assignment контрибуцией. Пример (гипотетический):
Вариант Б — subtype через extends. Модуль объявляет свой doctype extends="Assignment":
Текущий сканер grep по extends="Assignment" не находит ни одного case — модули используют Assignment напрямую. Это сознательное решение или roadmap-обещание — нужно зафиксировать (см. §6.6).
§4.3 ChatSource enum#
RxasmAssignmentService.createFromChat() принимает ChatSource:
- FREE — пользователь создал task вручную в free-standing GROUP/DIRECT чате.
- WORKFLOW — task порождён workflow-узлом.
- AGENT — task порождён AI-агентом.
Это расширяемая точка для extension model — модули могут добавлять свои enum-значения для discrimination origin-а.
§5 Текущее состояние реализации#
§5.1 Матрица capabilities#
| Capability | Backend | UI Web | UI Mobile | Notes |
|---|---|---|---|---|
| DIRECT chat 1:1 | ✅ | ✅ /chats |
🔵 | Idempotent GetOrCreateDirectRoom |
| GROUP chat | ✅ | ✅ /chats |
🔵 | Editable title, participants management |
| DOCUMENT chat | ✅ | ✅ rxat-chat-panel |
🔵 | Lazy на любом Chattable doctype |
| WORKFLOW chat | ✅ | ✅ rxat-chat-panel |
🔵 | Auto-created при старте WF |
| ASSIGNMENT chat | ✅ | ✅ rxat-chat-panel |
🔵 | Auto-created вместе с Assignment |
| ACL decoupling | ✅ | ✅ | 🔵 | setupChatRoomACL explicit ACE |
| SSE real-time | ✅ | ✅ | 🔵 | /chat/sse/room/{roomId} |
| PubSub cluster fanout | ✅ | n/a | n/a | Topic chat.events |
| Mentions | ✅ | ✅ | 🔵 | Regex pattern + notification escalation |
| Reactions | ✅ | ⚠️ (only +1/✓/?) | 🔵 | Full emoji picker не реализован |
| Participants management | ✅ | ✅ | 🔵 | Add/Remove + ACL sync |
| Read-state + badges | ✅ | ✅ Sprint 6.2 | 🔵 | Per-room + total-pill |
| Mute (ALL/MENTIONS/NONE) | ✅ | ✅ Sprint 6.4 | 🔵 | Toggle в ruxeo-chat-room.js |
| Typing indicator (events) | ✅ | ✅ debounce | 🔵 | Display «X пишет…» — TODO |
| Notification digest | ✅ | 🚧 нет preferences UI | 🔵 | Backend готов, UI частично |
| Assignment co-executors | ✅ | ✅ | 🔵 | Add/Remove/Update operations |
| Sub-assignments | ✅ | ✅ tab | 🔵 | Folderish + asmParentRef |
| Launch WF on Assignment | ✅ | ✅ | 🔵 | Через стандартный workflow start UI |
| Embedded chat in Assignment | ✅ | ✅ rxat-chat-panel | 🔵 | Через facet Chattable |
| Create Assignment from Chat | ✅ operation | ❌ нет UI | 🔵 | RxasmAssignment.CreateFromChat без UI button |
| Assignment cover-page + drawer entry | n/a | ❌ нет | 🔵 | Layout-ы есть, entry-point — нет |
Легенда: ✅ реализовано · ⚠️ частично · 🚧 backend есть, UI неполный · ❌ не реализовано · 🔵 mobile out-of-scope.
§5.2 Что готово к продакшну#
- Все 5 kind-ов чатов с UI на web.
- Real-time через SSE + cluster-safe PubSub.
- Read-state, бейджи, mute.
- Mentions, reactions (минимальный набор), participants.
- Assignment как полноценный case-объект с co-executors, sub-assignments, workflow-link, embedded chat.
§5.3 Что в работе или backlog#
- UI кнопка «Создать поручение из чата» (operation готов).
- Dedicated
/assignmentsстраница и drawer entry для свободных задач. - Display typing indicator («X пишет…»).
- Полноценный emoji picker для reactions.
- Per-user digest preferences UI.
- Расширение модулей через subtype/facet (есть гипотетически, нет в проде).
§6 Gaps и roadmap#
§6.1 🟡 P2 — Нет UI-кнопки «Создать поручение из чата»#
Backend operation RxasmAssignment.CreateFromChat готов (params: roomId, task, executorId, deadline, source), включая публикацию card-сообщения обратно в чат. Но кнопки в context-menu чата или slash-command /поручить (упомянутого в CHAT_TOBE_SPECIFICATION.md §5.5) нет в коде.
Целевая реализация: кнопка в header-action-bar ruxeo-chat-room.js с dialog-ом выбора assignee + deadline + title. Slash-command /поручить в ruxeo-chat-input.js с inline-syntax parsing.
Срок: до GA-внедрения чата как «Communications Platform».
§6.2 🟡 P2 — Нет dedicated /assignments страницы#
Layouts (view/create/edit) для Assignment есть, отчёты «Мои поручения» / «Администрирование поручений» — есть. Но единой точки входа «Все мои Assignment-ы (всех источников: WF/Agent/Free/from-chat)» — нет. Drawer entry для Assignment-ов также отсутствует.
В rxbm-drawer-slots.html:36-37 есть комментарий: «Tasks & Reports drawer entry removed (sansay270). Reports are now surfaced via the Home Page «Отчёты» tab.» — отчёты перенесены, но универсального entry для assignments как сущности нет.
Целевая реализация: новый drawer-entry «Поручения» + /assignments page с:
- табы по kind-ам: Свободные / Из workflow / От агента / Из чатов;
- группировка: активные / на ревью / завершённые;
- быстрое создание свободной задачи.
Срок: связан с § «Assignment как universal task carrier» в roadmap-е (UNIVERSAL_TASK_SPECIFICATION.md, см. §6.6).
§6.3 🟡 P2 — UNIVERSAL_TASK_SPECIFICATION.md упомянут как блокер, но не существует#
CHAT_TOBE_SPECIFICATION.md §5.5 ссылается на SPECS/BASEMODULE/UNIVERSAL_TASK_SPECIFICATION.md как блокер для drawer-entry / consolidation отчётов. Файл не существует в репо.
Целевая реализация: написать спецификацию (содержание см. §6.2 + §6.6 этого документа) и зафиксировать как договорённость. Может быть переименовано в ASSIGNMENT_AS_UNIVERSAL_TASK_CARRIER.md чтобы не путать с Nuxeo Task doctype-ом.
Срок: до §6.2 (предшествует UI implementation).
§6.4 🟢 P3 — Display typing indicator не реализован#
Backend events (typing_started/typing_stopped) идут через PubSub, debounce на input-е работает. Но отображение «Иванов И. пишет…» под чатом в ruxeo-chat-room.js:1007 помечено Future.
Целевая реализация: subscribe на typing_started события + список «typing users» с auto-clear через 5 секунд без update-а.
Срок: low-priority, при следующем UX-rework чата.
§6.5 🟢 P3 — Reactions без полного emoji picker#
UI поддерживает только +1/✓/? reactions. Backend гибче — rcm:reactions хранит любую emoji-строку как key.
Целевая реализация: emoji picker (например, <emoji-picker-element>) с поиском. Можно ограничить набор «корпоративных» reactions.
Срок: при пользовательском запросе, не блокер.
§6.6 🟢 P3 — Extension model для модулей не документирован и не использован#
Архитектурно есть два пути расширения Assignment (facet over / subtype extends), но: - Ни одного case в текущем коде. - Нет SPEC-документа «как расширять Assignment в новом модуле». - В консерватории не очевидно, какой вариант предпочтителен.
Целевая реализация: SPEC ASSIGNMENT_EXTENSION_GUIDE.md + один пилотный case (например, RxsmRequest extends Assignment в Service Management) для демонстрации.
Срок: при добавлении специфики Assignment в любом из модулей.
§6.7 🟢 P3 — Per-user digest preferences UI отсутствует#
Backend digest-service работает по global config (rxbm.notifications.chat.enabled). У пользователя нет способа:
- выбрать частоту (immediate / hourly / daily / weekly);
- отписаться от digest-ов конкретного чата (не муть, а именно digest);
- настроить часы тишины (do-not-disturb hours).
Целевая реализация: страница /preferences/notifications с tab-ом «Чат-сообщения», persistent в rxbm_user_preferences directory.
Срок: после accumulated user feedback по noise level.
§6.8 🟢 P3 — Cluster-safety PubSub backend не верифицирован#
PubSubService платформенный, поддерживает Redis/JGroups. В nuxeo.conf на стенде QA backend не выставлен явно — работает на default (in-memory). На production требуется явная конфигурация.
Целевая реализация: dev/QA stand документация + monitoring «PubSub backend type» в Admin Center.
Срок: при первом production deployment.
§6.9 ✅ Sprint 6 — закрыт полностью#
Memory note про Sprint 6 (sansay284, заморожена) — частично устарела. На текущей ветке sprint 6.1 (tx audit), 6.2 (read-state + бейджи + разделитель), 6.4 (mute UI), 6.5 (digest backend) — реализованы. 6.3 (статусы доставки сообщений типа «прочитано/доставлено») — не подтверждено в коде, нужна отдельная проверка при возврате к chat backlog-у.
§7 Связанные документы#
Внутри DOCS/#
- DOCS/MECHANISMS/RU/DYNAMIC_APPROVAL_WORKFLOW.md — WF, запускаемый поверх Assignment.
- DOCS/MECHANISMS/RU/SLA.md — приоритет и просрочка Assignment-ов (§2.5).
- DOCS/MECHANISMS/RU/EMPLOYEE_DELEGATION.md — computed groups, ACL co-executors.
- DOCS/MECHANISMS/RU/NOTIFICATION_DIGEST.md — digest backend.
- DOCS/MECHANISMS/RU/META_ROLES.md — child-роли для участников чата.
- DOCS/ADMIN/ROLE_MODEL.md — 4 контура доступа, в т.ч. контур D (dynamic ACL чата).
- DOCS/MECHANISMS/RU/SSO_KEYCLOAK.md — auth для всех клиентов чата (web + mobile).
Внутри SPECS/#
SPECS/BASEMODULE/CHAT_TOBE_SPECIFICATION.md(черновик 2026-04-29, sansay280) — forward-looking, частично реализован.SPECS/BASEMODULE/UNIVERSAL_TASK_SPECIFICATION.md— отсутствует (см. §6.3).
Внешние#
/home/ssay/Project/ruxeo-ai-services/mobile/— React Native mobile-клиент (вне scope)./home/ssay/Project/ruxeo-ai-services/orchestrator/— orchestrator, через который агент создаёт Assignment-ы.
Memory#
[[project-chat-tobe]]— initiative, sprint roadmap.[[project-chat-sprint6-status]]— Sprint 6 in-progress notes (нужно обновить — см. §6.9).[[project-assignments-chat-case-management]]— концепция от user-а, this document её формализует.[[feedback-nuxeo-workflow-task-event-api]]—ctx.getProperty("taskInstance")для WF-task events (применимо к WORKFLOW-чату).