Skip to content

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 the MultiUserSession, adds the user to the roster, publishes a viz.data.updated event with event=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 under presence:<user_id>, which late joiners pick up via sync_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 a user_left UX event.
  • UC6 — Moderate roster: Facilitator calls add_user / remove_user on 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 + SessionRecorder stack.
  • 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_bus via subscribe_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-user CollaborationEngine)
  • 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)