arch/realtime-tree: единый restriction-aware emit + единый снапшот move-аудитории (emitTreeEvent дублирует emitCommentEvent; окно гонки на move) #93

Closed
opened 2026-06-21 02:33:15 +03:00 by Ghost · 0 comments

Найдено в multi-aspect code review (грань: architecture, forward-looking, не блокирует мерж).

Область: apps/server/src/ws/ws.service.ts + ws-tree.service.ts

Наблюдение
Правка делает emitTreeEvent (ws.service.ts:82-103) побайтовой копией emitCommentEvent (50-71): идентичный резолв комнаты, кэш-гейт spaceHasRestrictions, hasRestrictedAncestor, fallback. Дополнительно restricted-move путь размазан по 3 методам (broadcastPageMoved → emitToAuthorizedUsers + emitDeleteToUnauthorized): два независимых fetchSockets/getUserIdsWithPageAccess с окном гонки между ними.

Значимость
Forward-looking, низкая вероятность, но высокая цена ровно для целевой угрозы (утечка ограниченного узла). Restriction-routing — тот код, где будущая правка опасна.

Опции

  • Option 1 (small): свести оба в один emitRestrictedAwareToSpace(spaceId, pageId, data); comment/tree — тонкие алиасы. Pros: один restriction-гейт. Cons: минимально.
  • Option 2 (medium): вычислять разбиение аудитории один раз (один fetchSockets + один getUserIdsWithPageAccess в broadcastPageMoved), слать move авторизованным и delete остальным из единого снапшота. Pros: убирает окно гонки move. Cons: рефактор move-пути.

Рекомендация
Для concurrency-heavy фичи с целью «не утекать ограниченные узлы» — Option 1 (единый emit) + Option 2 (единый снапшот move-аудитории) делают свойство безопасным конструктивно.

Связанные: #53

Найдено в multi-aspect code review (грань: architecture, forward-looking, не блокирует мерж). **Область:** apps/server/src/ws/ws.service.ts + ws-tree.service.ts **Наблюдение** Правка делает emitTreeEvent (ws.service.ts:82-103) побайтовой копией emitCommentEvent (50-71): идентичный резолв комнаты, кэш-гейт spaceHasRestrictions, hasRestrictedAncestor, fallback. Дополнительно restricted-move путь размазан по 3 методам (broadcastPageMoved → emitToAuthorizedUsers + emitDeleteToUnauthorized): два независимых fetchSockets/getUserIdsWithPageAccess с окном гонки между ними. **Значимость** Forward-looking, низкая вероятность, но высокая цена ровно для целевой угрозы (утечка ограниченного узла). Restriction-routing — тот код, где будущая правка опасна. **Опции** - *Option 1 (small)*: свести оба в один `emitRestrictedAwareToSpace(spaceId, pageId, data)`; comment/tree — тонкие алиасы. Pros: один restriction-гейт. Cons: минимально. - *Option 2 (medium)*: вычислять разбиение аудитории один раз (один fetchSockets + один getUserIdsWithPageAccess в broadcastPageMoved), слать move авторизованным и delete остальным из единого снапшота. Pros: убирает окно гонки move. Cons: рефактор move-пути. **Рекомендация** Для concurrency-heavy фичи с целью «не утекать ограниченные узлы» — Option 1 (единый emit) + Option 2 (единый снапшот move-аудитории) делают свойство безопасным конструктивно. **Связанные:** #53
Ghost closed this issue 2026-06-21 14:25:22 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#93