If the compiler is separating server-side code from client-side code, then it's also separating out symbol bindings as well. So it knows where symbols are bound, and where they are referenced, and it can use this to limit information flow.
For example:
(client
(let [token (get-client-token)]
(server
(let [username (get-username db token)]
(client
(dom/p "Hello " username))))))
The compiler can infer that
token is defined on the client, then sent to the server, which in turn defines
username and sends that back to the client.
It's the same system you'd use in normal server/client architecture, just inlined.