#server/server

    Native-only policy and state for the reference remote workspace server. Native effects are supplied through ServerHost.

    #The URI namespace

    remote_document_uri, resolve_remote_document_uri, and resolve_remote_directory_uri enforce the readonly-remote://workspace[/...] namespace and safe root-relative paths.

    This is the server's containment boundary. A request names a document by URI, and the only URIs that resolve are the ones inside the workspace namespace — traversal, absolute paths, and foreign schemes are rejected before any filesystem effect runs.

    flowchart LR R["client request URI"] --> N{"scheme is<br>readonly-remote?<br>authority is workspace?"} N -->|no| E["RemotePathError"] N -->|yes| S{"root-relative path<br>is safe?"} S -->|no| E S -->|yes| OK["ParsedRemotePath<br>→ host read"]

    ///|
    fn resolved(raw : String) -> String raise {
    match @server.resolve_remote_document_uri(@base_common.Uri::parse(raw)) {
    ParsedRemotePath(path) => "ok:" + path.to_string()
    RemotePathError(error) => "rejected:" + error.code.to_string()
    }
    }

    ///|
    test "only in-namespace, non-traversing paths resolve" {
    debug_inspect(
    [
    "readonly-remote://workspace/src/main.mbt", "readonly-remote://workspace/../outside.mbt",
    "readonly-remote://other/src/main.mbt", "file:///src/main.mbt",
    ].map(resolved),
    content=(
    #|[
    #| "ok:src/main.mbt",
    #| "rejected:InvalidUri",
    #| "rejected:InvalidUri",
    #| "rejected:InvalidUri",
    #|]
    ),
    )
    }

    remote_document_uri builds the same namespace from a root-relative path, and returns None for a path it would not accept — so constructing and resolving agree.

    ///|
    test "constructing a remote URI agrees with resolving one" {
    debug_inspect(
    ["src/main.mbt", "../escape.mbt", "/absolute.mbt"].map(path => {
    @server.remote_document_uri(path).map(uri => uri.to_string())
    }),
    content=(
    #|[Some("readonly-remote://workspace/src/main.mbt"), None, None]
    ),
    )
    }

    #Flow and API

    • remote_document_uri, resolve_remote_document_uri, and resolve_remote_directory_uri enforce the readonly-remote://workspace[/...] namespace and safe root-relative paths.
    • RemoteServer::with_language_providers receives explicit hover, definition, references, and document-symbol providers.
    • RemoteServer::new_session shares those host/provider services and document sync delivery while giving each protocol connection its own document cache and watch map.
    • handle_client_packet resolves one tree level, opens/caches documents, starts or replaces watches, closes documents, and routes feature requests.
    • Feature requests use the cached URI/revision (a non-empty requested revision must match), adapt the snapshot to a TextModel, and never reread the active file implicitly. Hover additionally revalidates the captured cache entry after its provider returns, including normalized text, so a watch replacement cannot be packaged under the old request. Reference locations are enriched with line previews.
    • Open and watch updates notify the optional document-sync listener used by the native diagnostics runner. Watch callbacks emit later packets; immediate request results are returned from handle_client_packet.
    • dispose_watches is the connection-teardown boundary for that session only.

    Public supporting types are ServerHost, ServerWatch, host read/resolve results, URI parse results, and RemoteServer methods. This package belongs to the reference shell; embedders do not need it.

    #Boundary and validation

    Server owns URI policy, cache/watch lifecycle, protocol dispatch, and provider routing. It must not import browser/workbench/web packages; filesystem, process, timer, socket, and concrete tool behavior stay in a host adapter.

    Run moon test server/server and just check.

    ServerHost

    pub(open) trait ServerHost {
    async fn read_directory(Self, String, String) -> ServerHostResolveResult
    async fn read_text_file(Self, String,
    SourcePath
    ) -> ServerHostReadResult
    fn watch_text_file(Self, String,
    SourcePath
    , async (
    FileChangeType
    ) -> Unit, (async () -> Unit) -> Unit) -> ServerWatch
    }

    Native-effect boundary for the remote server. Paths are root-relative SourcePaths under workspace_root; the host owns filesystem and watcher details.

    RemoteDirectoryResult

    pub(all) enum RemoteDirectoryResult {
    ParsedRemoteDirectory(String, String)
    RemoteDirectoryError(
    ProtocolError
    )
    } derive(
    Debug
    )

    Parsed remote directory URI. The root uses an empty path and display name workspace.

    RemotePathResult

    Parsed remote workspace path or protocol-shaped URI validation error.

    RemoteServer

    type RemoteServer

    Reference remote workspace server: protocol policy, document cache, watches, and language-provider routing without direct native effects.

    RemoteServer::current_workspace_root

    fn RemoteServer::current_workspace_root(self : RemoteServer) -> String

    The workspace root currently served to clients.

    RemoteServer::definition

    Routes a definition request only when the cached document URI/revision still matches the request.

    RemoteServer::dispose_watches

    fn RemoteServer::dispose_watches(self : RemoteServer) -> Unit

    Disposes every active document watch.

    RemoteServer::document_symbols

    Routes a document-symbol request for the cached document revision.

    RemoteServer::handle_client_packet

    Dispatches one decoded client packet and returns immediate response packets. Watch callbacks emit later packets through emit.

    RemoteServer::hover

    Routes a hover request only when the cached document URI/revision still matches the request.

    RemoteServer::new_session

    fn RemoteServer::new_session(self : RemoteServer) -> RemoteServer

    Creates one connection-scoped server session. Host/provider services, document-sync delivery, and the mutable workspace root remain server-scoped, while cached documents and watches are owned exclusively by the new connection.

    RemoteServer::open_document

    Opens, caches, and returns a remote document.

    RemoteServer::references

    Routes a references request and enriches locations with preview line data.

    RemoteServer::resolve_directory

    Resolves one directory level: the stat for the requested URI with its immediate children attached. The workspace root resolves through the bare readonly-remote://workspace URI.

    RemoteServer::set_document_sync_listener

    fn RemoteServer::set_document_sync_listener(self : RemoteServer, listener : (
    DocumentSnapshot
    ) -> Unit?) -> Unit

    Installs a listener notified whenever the server caches a fresh document snapshot (open or watch update). The native host uses it to schedule a moon check run without waiting for a feature request, so diagnostics are published as soon as content is known.

    RemoteServer::set_workspace_root

    fn RemoteServer::set_workspace_root(self : RemoteServer, root : String) -> Unit

    Redirects this server — and every session sharing it — to a new workspace root. The caller owns validation (existence, realpath) and client notification; cached documents keep their per-session lifecycle and are closed by clients reacting to the switch.

    RemoteServer::watch_document

    Starts or replaces a remote document watch, then returns the current document payload as the initial watch value.

    RemoteServer::with_language_providers

    Creates a remote server with explicit semantic feature providers.

    ServerHostReadResult

    Native host file-read result returned to the remote server policy layer.

    ServerHostResolveResult

    One resolved directory level: child stats with provider-minted URIs and children: None (unresolved), the IFileService.resolve contract.

    ServerWatch

    type ServerWatch

    Disposable watch handle owned by the remote server.

    ServerWatch::ServerWatch

    fn ServerWatch::ServerWatch(dispose : () -> Unit) -> ServerWatch

    Builds a server watch from a host disposer.

    ServerWatch::dispose

    fn ServerWatch::dispose(self : ServerWatch) -> Unit

    Stops the host watch.

    remote_document_uri

    fn remote_document_uri(raw_path : String) ->
    Uri
    ?

    Converts a root-relative source path into the remote workspace URI scheme.

    resolve_remote_directory_uri

    fn resolve_remote_directory_uri(uri :
    Uri
    , request_id? : String) -> RemoteDirectoryResult

    Resolves a directory URI to its root-relative path. Accepts the bare readonly-remote://workspace root, which resolve_remote_document_uri rejects because documents always carry a path.

    resolve_remote_document_uri

    fn resolve_remote_document_uri(uri :
    Uri
    , request_id? : String) -> RemotePathResult

    Resolves a readonly-remote://workspace/... document URI into a safe root-relative source path.