Your assumption is correct. The preview token is only set after Update Preview is clicked. It's always been this way.
Not this cookie no. It's set by the XPM client when it retrieves a result back from the Update Preview call
Not that I am aware of.
Note that Session Preview != XPM. It's a subset feature of XPM, so the IsSessionPreview property is behaving ...
I have seen similar issues, it’s because of XPM markup tag ComponentTemplateID is empty on that page some of the components, that is why it’s throwing the Invalid URI error while Finishing Editing in XPM inline while updating the preview button.
You can check these values in view source of the page to see those markup page, you can also see in the chrome ...
So I went with sending current components used as XPM prototypes through a small WF to get them to Draft.
When New Page is used in XPM this status is copied into the new component, preventing it from begin published (via minimum approval status) when initial created.
In general, you need to have CD (incl. ADF) somewhere in your architecture to make Session Preview work.
In the architecture you describe, you do have CD (underneath DD4T), but the challenge is that it is not directly in the Web App itself, but in a (custom) REST service.
With Session Preview, the XPM front-end will send a cookie containing a Preview ...
You can conditionally execute the XPM filters per environment by defining your own custom filter which implement a FilterChain with the chain.doFilter() command executed conditionally based on your environment configuration.
You're essentially replacing the XPM filters in the web.xml with your own custom ones that conditionally execute a FilterChain.