fix: #3621928 Keep the session open while the SSE stream renders islands
ApiSseController::sse() re-renders every island inside a streamed response, but Drupal saves - and closes - the session as soon as the kernel returns, before the response is sent. Anything the stream renders which reads the session then tries to start one, and a session cannot start once the headers are out:
ViewsExposedFilterBlock::build() -> viewExposedFormBlocks() -> FormBuilder::buildForm() -> Session::has() -> SessionManager::start()
RuntimeException: Failed to start the session because headers have already been sent.
Every block holding a form does this, so a single Views exposed filter placed anywhere in the display is enough. The exception lands in the event stream and breaks its framing, so collaboration stops relaying instead of failing loudly.
StackMiddleware\Session::handle() skips that save for a response implementing ResponseKeepSessionOpenInterface, which is how BigPipe renders after its own response is sent. KeepSessionOpenEventStreamResponse carries that marker.
Note the interface is @internal in core: there is no public equivalent, and the alternative is a feature that does not work on real content.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com Claude-Session: https://claude.ai/code/session_01YMfbY1TyK2cdzRWcSpJ2BE
Closes #3621928