DEV Community

LiraelVex6403
LiraelVex6403

Posted on

Screen Share Publish Permission: 3 Grant Checks for One Participant

A page fires: the property-review editor shows two active screen presenters for one maintenance walkthrough, while the on-call dashboard still reports a healthy connection count. Short answer: keep one server-owned presenter grant per room, authorize the share track at the signaling boundary, and revoke the old grant before admitting a replacement. An Express endpoint can issue the grant, but an HTTP success response cannot itself prevent an already connected peer from publishing; the component that accepts signaling must enforce the same decision. For collaborative cursors, keep a separate, replaceable fan-out path rather than treating every pointer position as a durable delivery obligation.

Why did the page arrive before the warning?

Connection count answers whether peers remain attached. It does not answer whether an unauthorized video track entered a room, whether the intended presenter lost the right to replace a track after reconnecting, or whether a stale cursor continues to appear beside a tenant document. A page based only on disconnected peers would miss all three. The earlier signal is a mismatch between accepted share publications and the room's current presenter grant, annotated with the room, participant, grant generation, and publication decision; keep document or tenant identifiers out of metric labels.

The grant is an application authorization record, not a browser capture permission. Browser consent and server authorization solve different problems: even if a user can capture a display locally, the room still needs to decide whose resulting media it will accept and forward. WebRTC defines peer connections and tracks, but it does not define the application's rule for choosing a presenter. The distinction matters when the operator grants one facilities coordinator permission to show a floor plan while several managers continue moving cursors in the same editor.

How can an Express grant let one participant publish a screen share?

Put the decision at the admission point for a new share publication. A proposed room model has a presenter participant ID and a monotonically increasing grant generation. The control plane updates that record atomically; signaling checks both fields before admitting the track, and the media forwarding path must stop forwarding an old publication when its grant is revoked. A signed credential can carry a short-lived claim, but expiry alone leaves a window in which a revoked publisher may continue; an active-session revocation check closes that gap. A second grant replaces the first; it does not coexist with it. If two managers submit different presenter assignments while a coordinator reconnects, the store decides which generation wins, signaling rejects the stale attempt, and forwarding must independently withdraw any old track that had already passed admission. Those are three different checkpoints, even when the UI exposes one button.

That gap matters.

For a Node.js and Express deployment, POSTing a presenter assignment to an authenticated room endpoint is the control-plane operation. The handler verifies that the caller can manage that room, performs a conditional grant update, and returns the new generation. The signaling service, rather than Express middleware on unrelated requests, compares the generation when a participant attempts to publish. Do not interpret a successful POST as proof that all downstream viewers have stopped receiving the previous track. Acknowledgment should describe the control-plane commit; track removal and viewer confirmation are separate observations.

This Go sketch isolates the state transition that an Express route and its signaling counterpart would need to share; it is illustrative application logic, not a WebRTC library API. The storage operation must be atomic across replicas.

package grant

import (
    "context"
    "errors"
)

type Grant struct {
    Participant string
    Generation uint64
}

type Store interface {
    Read(context.Context, string) (Grant, error)
    CompareAndSwap(context.Context, string, Grant, Grant) (bool, error)
}

var ErrConflict = errors.New("presenter grant changed")

func Assign(ctx context.Context, store Store, room, participant string) (Grant, error) {
    previous, err := store.Read(ctx, room)
    if err != nil { return Grant{}, err }
    next := Grant{Participant: participant, Generation: previous.Generation + 1}
    ok, err := store.CompareAndSwap(ctx, room, previous, next)
    if err != nil { return Grant{}, err }
    if !ok { return Grant{}, ErrConflict }
    return next, nil
}

func MayPublish(current Grant, participant string, generation uint64) bool {
    return current.Participant == participant && current.Generation == generation
}
Enter fullscreen mode Exit fullscreen mode

A collision is ordinary under two simultaneous moderator clicks. Return a conflict and let the caller reread the grant; do not silently accept both. Reconnect is the harder case: the same person may obtain a new session while an old session still has a live track. Bind admission to a specific grant generation and session, then explicitly remove the superseded publication. The limitation of this sketch is deliberate: a store update cannot implement session binding or forwarding enforcement, and the handler cannot promise viewers have switched until the media path reports its own state.

What does fan-out actually guarantee?

Separate the durable event that changes presenter ownership from transient editor presence. The former needs an ordered, auditable state transition and a clear conflict response. Cursor positions can normally be replaced by newer positions: after a brief network interruption, delivering every intermediate pointer coordinate is less useful than delivering the latest position and eventually expiring an abandoned cursor. Document edits belong to a third path whose persistence and conflict rules cannot be inferred from cursor presence.

Never replay obsolete motion.

Path Useful delivery contract Failure response
Presenter grant One committed generation per room Reject stale publication; reconcile forwarded tracks
Collaborative cursor Latest known position plus expiry Discard stale updates; clear abandoned presence
Document edit Application-defined durable revision Reconcile against stored document state

This is a buy-versus-build decision as well as a protocol decision. A managed relay may reduce the team's signaling and media on-call load, while the application still owns presenter authorization and must verify that the relay exposes the admission and revocation controls its policy needs. A self-operated relay offers direct control over those boundaries but adds capacity planning for concurrent tracks, outbound viewer traffic, and reconnect bursts. Neither label establishes the delivery contract; test the actual boundary. I would budget for peak viewers per room and simultaneous shares attempted during a reconnect, then verify the intended SLO against those conditions rather than extrapolating from a single successful call.

How do we move the alert earlier?

Instrument grant commits, rejected publication attempts, admitted share tracks, forwarding stops, and viewer-observed presenter changes as separate events. Correlate them by room and generation in traces, while aggregating metrics without high-cardinality room labels. An actionable alert compares a committed grant with the tracks currently forwarded for that room: zero when an active presenter should be visible, or more than one when policy permits exactly one, merits investigation after a short reconciliation interval. The interval is an operational choice to measure, not an invented universal timeout.

Test a revoked publisher that keeps its connection open, two moderators racing to assign different presenters, and a reconnect that overlaps the prior session. Also test a cursor subscriber that misses several positions and rejoins: it should converge on current presence without replaying obsolete motion. Roll out the extra instrumentation before paging on it; observe how often valid track replacement briefly looks like a mismatch, and tune the alert against that distribution. Otherwise a normal handoff will wake the on-call team, the alert will lose credibility, and the original silent authorization failure will become harder to spot.

Further reading

  • W3C, WebRTC 1.0: Real-Time Communication Between Browsers.

References

Top comments (0)