Skip to content

feat(digest): дайджест метрик workspace (RBAC + ACL + WCAG AA)#231

Merged
NovakPAai merged 1 commit into
mainfrom
claude/novak-digest
May 20, 2026
Merged

feat(digest): дайджест метрик workspace (RBAC + ACL + WCAG AA)#231
NovakPAai merged 1 commit into
mainfrom
claude/novak-digest

Conversation

@NovakPAai
Copy link
Copy Markdown
Owner

Summary

Новая страница /w/:slug/digest с менеджерскими метриками: продуктивность / своевременность / гигиена / распределение нагрузки. Разрезы личный/командный, периоды 7d/30d/90d. RBAC: VIEWER → 403 на team scope. Team scope для MEMBER фильтрует private boards без BoardMember (R6 SDD).

Без изменений в Prisma schema — всё считается на лету через TaskStatusHistory.

Артефакты

Что изменилось

Backend (новый модуль):

  • modules/digest/ — dto / dates / access / compute / service / router
  • GET /api/workspaces/:wid/digest?scope=personal|team&period=7d|30d|90d
  • OpenAPI/Swagger зарегистрирован
  • app.ts — один mount

Frontend:

  • Новая страница + tab «Дайджест» в AppLayout
  • 3 компонента (DigestCard, DigestSparkline, WorkloadChart)
  • useDigest hook с AbortController + 403 graceful auto-switch
  • Маршрут /w/:slug/digest в App.tsx

Безопасность

  • workspaceMfaGuard('wid')
  • rateLimit({ scope: 'digest', limit: 60/min, key: userId })
  • UUID param validation через Zod ✅
  • effectiveRole fail-safe → VIEWER для неизвестных presets (defense-in-depth) ✅
  • Team scope per-board ACL фильтр (R6) ✅ с strict test assertion
  • Personal scope намеренно bypass per-board ACL для своих assignee-задач (документировано в SDD §10.5)

Доступность (WCAG 2.2 AA)

  • Dedicated role="status" aria-live="polite" announcer (вместо broad page-level)
  • h2 heading hierarchy через aria-labelledby
  • sr-only текст для цветовой semantics delta (▲/▼)
  • Touch targets ≥44×44 (Refresh + Radio)
  • prefers-reduced-motion в bar-chart transitions
  • AntD theme tokens вместо захардкоженных цветов
  • visually-hidden table fallback для sparkline (SR)

Tests

  • Backend: 47 новых (14 dates + 17 compute + 16 integration)
  • Frontend: 15 component (вкл. mobile path для WorkloadChart)
  • Итого: 555 проходят (was 491, +60+) — 0 tsc/lint errors

Test plan

  • npm run typecheck — green (backend + frontend)
  • npm run lint — 0 errors
  • npm test — 555/555 passing (3 skipped pre-existing)
  • Manual smoke: открыть /w/.../digest — переключить scope/period, проверить 4 карточки
  • Viewer scope: убедиться что radio «Командный» disabled + tooltip
  • Refresh shortcut R работает (фокус не в input)

Deferred (с явной причиной)

Что Куда Причина
E2E Playwright (3 сценария) #229 требует запущенные dev-серверы
Polish MEDIUM/LOW из 3 ревью #230 не блокирует MVP
N+1 ACL в accessibleBoardIdsInWorkspace Phase 2 cache plan.md I1, accepted для MVP
Topbar tabs accessibility #230 (pre-existing pattern) вне scope этого PR
Cycle time через status history precision #218 данные уже есть
CSV/email digest, custom range, etc. #220-#222, #224-#228 Phase 3+

Review summary

3 ревью-агента (code + security + UX) выдали 84 находки (5 CRITICAL + 17 HIGH + 25 MEDIUM + 37 LOW). Зафиксил все CRITICAL и HIGH inline, важные MEDIUM/LOW, остальное — в issue #230 с явным reason.

Новая страница /w/:slug/digest с 4 секциями менеджерских метрик:
продуктивность, своевременность, гигиена (score 0-100), нагрузка.

## Backend

- модуль modules/digest/ (DTO + dates + access + compute + service + router)
- GET /api/workspaces/:wid/digest?scope=personal|team&period=7d|30d|90d
- VIEWER → 403 INSUFFICIENT_PERMISSION на scope=team
- team scope для MEMBER фильтрует private boards без BoardMember (R6 SDD)
- effectiveRole fail-safe → VIEWER для неизвестных role presets (security M2)
- workspaceMfaGuard + rateLimit(60/min/user) + UUID param validation
- никаких изменений в Prisma schema — агрегаты на лету через TaskStatusHistory

## Frontend

- страница DigestPage (/w/:slug/digest) + tab «Дайджест» в AppLayout
- useDigest hook с AbortController и graceful 403 auto-switch
- 3 компонента (DigestCard, DigestSparkline, WorkloadChart)
- WCAG 2.2 AA: dedicated aria-live announcer, h2 hierarchy, sr-only delta,
  touch targets ≥44, prefers-reduced-motion, responsive sparkline,
  AntD theme tokens вместо хардкода цветов

## Tests

- 47 backend (14 dates + 17 compute + 16 integration)
- 15 frontend component (вкл. mobile path для WorkloadChart)
- Total: 555 passing, 0 errors

## Deferred (документировано)

- E2E Playwright → #229 (требует dev-серверы)
- Polish MEDIUM/LOW (29 находок из ревью) → #230
- N+1 ACL в accessibleBoardIdsInWorkspace → Phase 2 cache (plan.md I1)
- Topbar tabs accessibility — pre-existing pattern → #230
- Issues #218-228 — Phase 2 roadmap (cycle time history precision,
  CSV export, email digest, etc.)

Связано: docs/design/digest.md, specs/digest.feature, tasks/digest/plan.md
@NovakPAai NovakPAai merged commit d8a553a into main May 20, 2026
8 checks passed
@NovakPAai NovakPAai deleted the claude/novak-digest branch May 20, 2026 07:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants