Multi-User Session Use Cases¶
This diagram maps the three active roles in a real-time multi-user
collaboration session to the FCC subsystems they exercise. v1.5.0
Pillar D introduced the MultiUserSession surface at
src/fcc/collaboration/multi_user.py:178; it wraps a
:class:CollaborativeDocument (CRDT-backed) together with a roster of
connected users, a presence map, a broadcaster callback for WebSocket
fan-out, and an optional UX-lane event bus for live-view updates. The
three roles — User, Facilitator, Auditor — cover editing,
moderation, and compliance observation respectively.
The diagram below shows each role's tasks and the subsystems those
tasks touch. All three roles share the same MultiUserEngine
entry-point but exercise different surfaces under it.
graph LR
UserA((User))
Fac((Facilitator))
Aud((Auditor))
UC1[/"Join session"/]
UC2[/"Edit text concurrently"/]
UC3[/"Publish cursor / selection"/]
UC4[/"Observe peers' presence"/]
UC5[/"Leave session"/]
UC6[/"Moderate roster (add/remove users)"/]
UC7[/"Resolve merge conflicts"/]
UC8[/"Broadcast system message"/]
UC9[/"Review CRDT update history"/]
UC10[/"Export session recording"/]
UC11[/"Subscribe to UX-lane events"/]
S1[MultiUserEngine]
S2[MultiUserSession]
S3[CollaborativeDocument]
S4[CRDTBackend<br/>InMemory / YPy]
S5[PresenceInfo map]
S6[WebSocket bridge :8765]
S7[UXBus<br/>viz.data.updated]
S8[CollaborationEngine<br/>turn recorder]
UserA --> UC1
UserA --> UC2
UserA --> UC3
UserA --> UC4
UserA --> UC5
Fac --> UC6
Fac --> UC7
Fac --> UC8
Fac --> UC1
Aud --> UC9
Aud --> UC10
Aud --> UC11
UC1 --> S1
UC1 --> S2
UC2 --> S3
UC2 --> S4
UC3 --> S5
UC3 --> S7
UC4 --> S5
UC5 --> S2
UC6 --> S2
UC7 --> S4
UC8 --> S6
UC8 --> S7
UC9 --> S8
UC10 --> S8
UC11 --> S7
S2 -.CRDT observer.-> S6
S2 -.UX-lane event.-> S7
S3 -.wraps.-> S4
S2 -.presence map.-> S5
Three patterns are worth noting. First, every role enters via
MultiUserEngine.join_session(session_id, user_id) — there is no
"admin-only" entry point — and the engine dispatches to the right
MultiUserSession. Second, the wire envelope for every outbound
message is a canonical {user_id, session_id, type, payload} dict
(type is one of edit, presence, ack, state, join, leave
per the _VALID_ENVELOPE_TYPES frozenset at
src/fcc/collaboration/multi_user.py:50), which keeps the transport
layer transport-agnostic. Third, audit use cases (UC9, UC10, UC11) are
served by the sibling CollaborationEngine / SessionRecorder stack,
not by the multi-user subsystem itself — multi-user covers live
editing, single-user covers turn recording, and the two compose on the
same session_id.
Operational implications: the WebSocket bridge at port 8765 is the
primary live-edit channel; the UX-lane event bus (see
../data-flow-diagrams/dual-bus-lane-routing.md) is a secondary
notification channel that the React frontend subscribes to via SSE at
port 8901. When the broadcaster is unset, edits still converge at the
CRDT level — only the fan-out is silent — which is what lets tests
exercise the full convergence path without spinning up a wire
transport.
Use-case detail¶
- UC1 — Join session:
MultiUserEngine.join_session(session_id, user_id)creates or fetches theMultiUserSession, adds the user to the roster, publishes aviz.data.updatedevent withevent=user_joined. - UC2 — Edit text concurrently:
MultiUserSession.apply_local_edit(user_id, Edit(kind=SET_TEXT, value=...))flows through the CRDT backend; concurrent edits converge via Lamport + replica-id LWW. - UC3 — Publish cursor / selection:
update_presence(user_id, cursor_pos, selection)writes to the CRDT meta map underpresence:<user_id>, which late joiners pick up viasync_state(). - UC4 — Observe peers' presence:
CollaborativeDocument.get_presence()returns all known presence entries refreshed from CRDT state. - UC5 — Leave session:
remove_user(user_id)drains the roster and emits auser_leftUX event. - UC6 — Moderate roster: Facilitator calls
add_user/remove_useron the session directly. - UC7 — Resolve merge conflicts: Facilitator resolves via the bidirectional sync layer when cross-namespace merges need human judgment (see
../sequence-diagrams/bidirectional-federation-sync.md). - UC8 — Broadcast system message: Facilitator injects an envelope with
user_id="__system__"via the engine's broadcaster callback. - UC9 — Review CRDT update history: Auditor reads the recorded session events from the sibling
CollaborationEngine+SessionRecorderstack. - UC10 — Export session recording: Auditor invokes
SessionRecorder.save(session_id)to persist a JSON + event-stream bundle. - UC11 — Subscribe to UX-lane events: Auditor registers a subscriber on
ux_busviasubscribe_ux(...)and receives live view updates.
See also¶
- Source:
src/fcc/collaboration/multi_user.py:178(MultiUserSession),src/fcc/collaboration/crdt.py:408(CollaborativeDocument),src/fcc/collaboration/engine.py:67(single-userCollaborationEngine) - Related sequence:
../sequence-diagrams/crdt-multi-user-merge.md - Related class diagram:
../class-diagrams/collaboration-engine.md(single-user sibling),../class-diagrams/six-pillars-overview.md - Related DFD:
../data-flow-diagrams/dual-bus-lane-routing.md - ADR:
docs/decisions/ADR-012_*.md(CRDT multi-user) - Audience tier:
docs/for-professionals/*(facilitator),docs/for-auditors/*(auditor)