Context. surface studio · domain collaboration · route /studio/notification-center · auth signed-in + studio entitlement · source apps/oshun/web/src/app/studio/notification-center/page.tsx
Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md; content re-verified 2026-06-03 against current source
Purpose#
Operate the notification center as a live, admin-scoped BFF console. The
workspace (StudioNotificationCenterWorkspace) wires a single Notification
Routing Lane to the real notification-routing engine via
/v1/admin/studio/notification-routing: during quiet hours it suppresses
anything below the minimum priority; otherwise it digests normal/low priority
notifications and delivers high-and-above immediately. This is a real domain
computation, not a simulation.
Entry points#
- Studio root (
/studio) — discoverable as a collaboration workspace - Quick-action links from sibling workspaces (activity/change feeds, real-time collaboration, commenting/annotation, review/approval, audit/compliance surfaces, enterprise tenant isolation, RBAC/permission policy)
- Direct URL / bookmark — yes
Layout regions#
page.tsx mounts ShellLayout active="studio", renders
StudioNotificationCenterWorkspace, then a single panel containing 7 sibling
quickAction links. There is no Route Map panel on this page.
- Shell header — from
ShellLayout - Workspace
<h1>— "Studio Notification Center" (WorkspaceHeading), followed by adata-notification-center-summaryparagraph describing the routing - Notification Routing Lane (
<h2>data-nr-lane-heading"Notification Routing Lane") — the catalog/loading/unauthorized/error states, the route form, and the result - Quick-actions panel —
panelwith 7quickActionlinks to sibling workspaces (no self-link, no Route Map)
States#
- Loading —
data-nr-loading"Loading notification router…" while the GET catalog request is in flight (outcome === null) - Unauthorized —
data-nr-unauthorized"Access restricted." on 401/403 (admin scope required); shows the BFF message or "Studio admin scope required to route notifications." - Error —
data-nr-error"Could not load the notification router." on any non-OK catalog response or network failure - Ready (form) — catalog loaded;
data-nr-enumsshows{priorities.length} priorities · {routes.length} routes, and thedata-nr-formform renders - Result — after a successful POST,
data-nr-resultrenders the routing headline + per-notification table - Route validation error —
data-nr-route-errorfor invalid JSON, network unavailable, or a non-200 POST (shows the POSTdetail)
Interactions#
Notification Routing Lane form#
- Notifications (
textareadata-nr-payload,aria-label="notifications json") — JSON{ context{ withinQuietHours }, policy{ quietHoursMinPriority, digestLowPriority }, notifications[{ notificationId, priority, channel }] }; seeded with a default payload - Route notifications (
buttondata-nr-submit,type="submit") —submitRouteparses the JSON (rejecting invalid JSON withdata-nr-route-error) and POSTs to/v1/admin/studio/notification-routing/route
Result#
- Headline (
data-nr-headline) —<data-nr-count="deliver_now"> · <data-nr-count="digest"> · <data-nr-count="suppressed"> - Notifications table (
data-nr-notifications) — onedata-nr-notification-rowper notification withdata-notification-id,data-route,data-priority, plus adata-nr-notification-routecell
Quick actions#
- Open Activity and Change Feeds workspace
- Open Real-Time Collaboration Substrate workspace
- Open Commenting and Annotation System workspace
- Open Review and Approval Workflows workspace
- Back to Audit and Compliance Surfaces workspace
- Back to Enterprise Tenant Isolation workspace
- Back to RBAC and Permission Policy UX workspace
Data & contracts#
- GET catalog:
/v1/admin/studio/notification-routing— fetched on mount withbuildBffAuthHeaders()andcache: 'no-store'; returns{ priorities[], routes[] } - POST verb:
/v1/admin/studio/notification-routing/routewith body{ context{ withinQuietHours }, policy{ quietHoursMinPriority, digestLowPriority }, notifications[{ notificationId, priority, channel }] }→{ result: { notifications[], summary{ deliverNowCount, digestCount, suppressedCount } } }(200) or adetailerror - Realtime: none — request/response only
- Client fetch: direct
fetchwithcache: 'no-store'; no client-side caching - Auth/role check: admin-scoped, fail-closed at the BFF (
admin:*|admin:studio; 401/403); reached through the signed-in + studio route gate
Cross-references#
- Parent:
../studio-overview.md - Sibling:
studio-activity-change-feeds.md,studio-review-approval-workflows.md - Shell:
../../shell/05-notifications.md - Component:
apps/oshun/web/src/components/studio/StudioNotificationCenterWorkspace.tsx - BFF route:
apps/oshun/bff/src/routes/admin-studio-notification-routing.ts - BFF store:
apps/oshun/bff/src/studio/notification-routing-store.ts
Open questions / known gaps#
- Confirm whether routed notifications persist or dispatch to real channels, or whether the lane stays a stateless router
- Document the
quietHoursMinPrioritycomparison (priority rank ordering) and the digest-batch flush cadence