Context. surface studio · domain collaboration · route /studio/presence-cursor-systems · auth signed-in + studio entitlement · source apps/oshun/web/src/app/studio/presence-cursor-systems/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 presence and cursor systems as a live, admin-scoped BFF console. The
workspace (StudioPresenceCursorSystemsWorkspace) wires a single Presence FSM
Lane to the real presence finite-state machine via
/v1/admin/studio/presence: it derives each participant's presence state —
active, idle (cursor stale), away (heartbeat stale), or offline — from heartbeat
age and cursor idle time against the policy thresholds. 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 (real-time collaboration, commenting/annotation, review/approval, activity/change feeds, notification center)
- Direct URL / bookmark — yes
Layout regions#
page.tsx mounts ShellLayout active="studio", renders
StudioPresenceCursorSystemsWorkspace, then a single panel containing 5
sibling quickAction links. There is no Route Map panel on this page.
- Shell header — from
ShellLayout - Workspace
<h1>— "Studio Presence & Cursor Systems" (WorkspaceHeading), followed by adata-presence-cursor-summaryparagraph describing the derivation - Presence FSM Lane (
<h2>data-pr-lane-heading"Presence FSM Lane") — the catalog/loading/unauthorized/error states, the evaluate form, and the result - Quick-actions panel —
panelwith 5quickActionlinks to sibling workspaces (no self-link, no Route Map)
States#
- Loading —
data-pr-loading"Loading presence evaluator…" while the GET catalog request is in flight (outcome === null) - Unauthorized —
data-pr-unauthorized"Access restricted." on 401/403 (admin scope required); shows the BFF message or "Studio admin scope required to evaluate presence." - Error —
data-pr-error"Could not load the presence evaluator." on any non-OK catalog response or network failure - Ready (form) — catalog loaded;
data-pr-enumsshows{presenceStates.length} presence states, and thedata-pr-formform renders - Result — after a successful POST,
data-pr-resultrenders the presence headline + per-participant table - Evaluate validation error —
data-pr-evaluate-errorfor invalid JSON, network unavailable, or a non-200 POST (shows the POSTdetail)
Interactions#
Presence FSM Lane form#
- Presence (
textareadata-pr-payload,aria-label="presence json") — JSON{ policy{ idleAfterMs, awayAfterMs, offlineAfterMs }, participants[{ participantId, heartbeatAgeMs, cursorIdleMs }] }; seeded with a default payload - Evaluate presence (
buttondata-pr-submit,type="submit") —submitEvaluateparses the JSON (rejecting invalid JSON withdata-pr-evaluate-error) and POSTs to/v1/admin/studio/presence/evaluate
Result#
- Headline (
data-pr-headline) —<data-pr-active-count> · {idleCount} idle · {awayCount} away · {offlineCount} offline - Participants table (
data-pr-participants) — onedata-pr-participant-rowper participant withdata-participant-id,data-presence, plus adata-pr-presencecell
Quick actions#
- Back to Real-Time Collaboration Substrate workspace
- Open Commenting and Annotation System workspace
- Open Review and Approval Workflows workspace
- Back to Activity and Change Feeds workspace
- Back to Notification Center workspace
Data & contracts#
- GET catalog:
/v1/admin/studio/presence— fetched on mount withbuildBffAuthHeaders()andcache: 'no-store'; returns{ presenceStates[] } - POST verb:
/v1/admin/studio/presence/evaluatewith body{ policy{ idleAfterMs, awayAfterMs, offlineAfterMs }, participants[{ participantId, heartbeatAgeMs, cursorIdleMs }] }→{ result: { participants[], activeParticipants[], summary{ activeCount, idleCount, awayCount, offlineCount } } }(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-real-time-collaboration-substrate.md,studio-commenting-annotation-system.md,studio-activity-change-feeds.md - Component:
apps/oshun/web/src/components/studio/StudioPresenceCursorSystemsWorkspace.tsx - BFF route:
apps/oshun/bff/src/routes/admin-studio-presence.ts - BFF store:
apps/oshun/bff/src/studio/presence-fsm-store.ts
Open questions / known gaps#
- Confirm the live presence transport (WebSocket / awareness channel) if the lane moves beyond a stateless evaluator
- Document the precedence between cursor-idle (idle) and heartbeat-age (away/offline) thresholds when both are exceeded