M6 removes the transitional public WebUi* identity. Runic Desktop now models
the actual ownership graph instead of making one “window” own content, a
listener, sessions, and a platform presentation at once.
| Source-preview API | M6 API | Reason |
|---|---|---|
WebUiApplication process globals |
immutable DesktopHostOptions and await using DesktopHost |
configuration and shutdown belong to one host |
WebUiWindow server/content state |
DesktopSurface |
content, capabilities, requests, and sessions share one isolated namespace |
WebUiWindow browser/WebView state |
DesktopWindow |
closing a presentation no longer implicitly closes its surface |
BindAsync |
RegisterCapability |
capabilities are admitted explicitly and handlers are async-first |
WebUiEvent |
PresentationInvocation and PresentationSession |
invocation and session ownership are distinct |
WebUiResult |
PresentationResult |
removes compatibility identity while retaining the selected wire profile |
WebUiContent / WebUiFileHandler |
ContentResponse / ContentHandler |
handlers receive request-scoped services and cancellation |
SetPort, SetPublic, global client flags |
DesktopHostOptions / DesktopSecurityPolicy |
live security boundaries cannot be mutated silently |
IWebUiEmbeddedHost* |
IDesktopWindowHost* |
platform adapters describe presentation hosting, not WebUI compatibility |
The common server-only migration is:
await using var desktop = await DesktopHost.StartAsync(new DesktopHostOptions
{
...
});
var surfaceOptions = new DesktopSurfaceOptions
{
Content = new DesktopContent.Directory(Path.Combine(AppContext.BaseDirectory, "www"), "index.html"),
};
...
await using var surface = await desktop.CreateSurfaceAsync(surfaceOptions);
Content takes one DesktopContent case: Directory(root, entry?) for local
files, Html(document), ExternalUrl(url) or Handler(contentHandler). Only
directory content serves local files. This form is new in Runic SDK
0.7.0-preview.1; 0.6.0-preview.1 sets RootFolder and a Content
string, or ContentHandler. The
0.7 upgrade notes
map each 0.6 form to its case.
Register capabilities on the surface, then open an optional window:
using var greeting = surface.RegisterCapability(
"greet",
static (invocation, _) =>
ValueTask.FromResult<PresentationResult>($"Hello, {invocation.GetString()}!"));
await using var window = await surface.OpenWindowAsync();
window.WaitForClose();
WaitForClose keeps the platform window loop responsive while synchronously
holding the process open, including AppKit's main-thread loop on macOS.
Security is intentionally stricter. The default bridge handshake requires the surface's 256-bit bootstrap credential and a canonical same origin. Public binding, additional origins, missing origins for non-browser clients, and multi-client admission must be selected explicitly. Credentials never appear in URLs and are invalidated with their surface or host.
Runic Desktop remains on the webui-compat/52f9e75 wire profile during M6, so
existing pages using webui.js and generated capability functions continue to
work. CS-WebUI remains the separate upstream-compatible product for consumers
that need the original WebUI-shaped .NET API.