A workspace is not a filter in the interface; it is a boundary in the data. This is how one customer's screens, media, and members stay invisible to another — and how the boundary holds for platform staff who need to look at a customer's workspace without belonging to it.
Where the workspace comes from
A signed-in session carries a workspace id inside its access token, and the server reads it from the verified token on every request — not from a header, a query parameter, or anything else the browser can choose. Repository methods take that id and scope on it, so a screen, a playlist, or a play log can only be looked up inside the workspace that asked.
Membership is part of the same boundary. Owners can invite members, manage the workspace, and see billing; members work with the content and the screens they were invited to manage. A role is not a UI convenience — it decides which routes are reachable at all.
Scoping at the query, not the page
Isolation that lives only in the dashboard is one forgotten filter away from a leak, so the rule in this codebase is that user-facing lookups go through workspace-scoped repository methods: find the screen in this workspace, rather than find the screen by id and hope.
Anything that has to cross workspaces is a separate, explicitly chosen path — platform administration, where staff pick the workspace a request acts on, and nothing else. Deleting the workspace id from a query should break a test, not go unnoticed.