Display runtime and reactive state ================================== .. note:: Planned architecture. A terminal loads a kiosk shell either inside Mission Control or from ``/display/``. The UUID locates the Display but is not a credential. An authenticated Assignment selects an immutable ViewVersion and one or more authorized Scopes. Views ----- A View contains HTML, CSS, JavaScript and schemas for its Properties and interactions. Generated code always runs in a sandboxed iframe. It communicates with the parent runtime through a versioned ``postMessage`` bridge; it never receives display credentials or direct Channels access. Scopes and Properties --------------------- A Scope is a shared, authorized namespace. Properties are typed JSON values with monotonic revisions. Displays and Agents use high-level operations such as ``set``, ``increment``, ``toggle`` and compare-and-set. The backend applies operations atomically and publishes the committed value. Example:: scope campaign-madrid revision 42 title = "Traffic update" image = "/media/campaign/…" counter = 18 Two tablets assigned to the same Scope receive the same Property deltas. A button may increment ``counter`` when its schema and policy allow display writes. The emitting tablet reconciles with the authoritative server result. Channels layout --------------- Planned functional groups include: * ``display-`` — Assignment and directed commands; * ``display-scope-`` — Property deltas; * ``display-campaign-`` — aggregate rollout state; * ``display-session-`` — acknowledgements to one connection; * ``user-`` / ``workspace-`` — authorized control projections. Group names route messages; they never grant authorization. Django policies validate every subscription and mutation. Consumers remain thin and call transactional services. Services write state/outbox; publishers project only after commit. Recovery -------- REST provides Assignment and Scope snapshots. WebSocket provides deltas. The client applies the next revision, ignores duplicates/old frames and rehydrates when it detects a gap. Offline terminals cache the last allowed View and state under campaign freshness policy, then reconcile on reconnect.