LAB429/ Cheetah product page ↗

Cheetah / Cheetah documentation

Sessions and sharing

A site session binds one viewer, one host, one site descriptor, and the connector selected when the session opens. It gives the broker a relay base path and a place to record sharing decisions and lifecycle state. It is not automatically an authorization credential merely because its ID is difficult to guess.

Opening a session is a product policy decision

The lifecycle service resolves the current site, requires it to be available, and asks ISiteSharingPolicy whether the viewer may open it. Every allowed or denied decision records the site, host, viewer, policy name, reason, details, evaluation time, and the session ID when one was created.

The supplied metadata policy allows:

  • the same effective user as the host;
  • a user in allowed_viewer_user_ids when sharing_mode is explicit_allowlist;
  • any valid effective user when sharing_mode is allow_all.

Without one of those conditions, access is host-only. The HTTP open route uses the identity from the optional authentication dependency when present and rejects a conflicting body identity. When no authenticated identity is available, the body must provide a valid effective user ID.

This policy is a reference implementation. Organization membership, tenant boundaries, invitations, approval, purpose, and expiry belong in an application implementation of ISiteSharingPolicy, not scattered among route handlers.

Protect the complete route family

The reusable router does not consistently apply identity to every session operation. Supplying its required and optional authentication dependencies protects authenticated list operations and registration, but does not by itself close the whole boundary.

OperationSupplied router behaviorApplication requirement
list sites or read one descriptoranonymousprotect or redact if discovery is not public
list sessions or access decisionsrequired identity; results limited to host or viewerkeep the dependency authoritative
open a sessionoptional identity; otherwise body identityrequire authenticated identity for untrusted use
read one sessionno identity checkrequire host/viewer or an explicit capability policy
close or revokeno identity checkdefine which participant or operator may mutate lifecycle
relay HTTPno identity checkbind every request to the authorized viewer/session
subscribe to events or invoke actionsoptional identity; absence is acceptedrequire identity or a deliberate signed-capability design

Apply one outer middleware or guarded-router policy that covers all of these routes. If the product intentionally uses a signed session URL as a capability, define its scope, expiry, revocation, leakage protections, and tests. Do not let an absent optional dependency make that decision by accident.

Connector registration requires an authenticated host. Remote unregistration additionally checks that host against the stored owner and checks the connector client ID. That protection is current; it does not compensate for the separate session-route gaps above.

Session states are explicit but not automatic

Normal creation goes directly to active. close_session() changes the session to closed, and revoke_session() changes it to revoked; both release the in-process loopback client's resources. Later relay, event, and action operations reject an inactive session.

The model also names pending and expired, but the supplied runtime has no time-based expiry, idle timeout, or cleanup scheduler. Closing a session is not the same as proving that a prior local effect stopped or was undone. A product needing expiry must own the clock, transition, resource release, and user experience.

Default state is process-local

The initialized runtime uses in-memory stores for descriptors, sessions, and access decisions, plus an in-memory event bus. A restart forgets them, and several application replicas do not share them. The access-decision store keeps its newest 200 records by default.

That shape is appropriate for focused development, an embedded application, or a one-process deployment whose limits are understood. A durable or horizontally scaled product needs shared implementations and a cleanup policy. The runtime constructor currently creates its concrete in-memory stores directly; replacing them requires deliberate lower-level composition or an extension of the runtime helper rather than a configuration flag.

Align browser credentials with the policy

CooperativeSiteBrowserClient uses native EventSource for events and ordinary fetch for actions. It has no built-in bearer-header callback. Ambient same-site cookies, an authenticated same-origin shell, or a deliberately signed URL can fit; a header-only bearer design needs a different SSE transport or wrapper.

Choose the browser credential path together with the server authorization matrix. A strong server dependency does not help if the browser client cannot present its proof on every relevant request.

Next: Events and actions.