Back to list
Skywire Development Update — September 28, 2026

Skywire Development Update — September 28, 2026

The twenty-eighth let a visor host the network’s own deployment services directly under its own key rather than as separate standalone processes, and then spent most of the day working through what that exposed — a missing nonce store, duplicate aggregator ports, and a registration cycle that had been needlessly re-handshaking with every service every thirty seconds regardless of whether anything had actually changed. A transport manager lock held across an entire incoming handshake, which could freeze the whole transport map for most of a minute against one slow peer, was narrowed to just the lookup it actually needs to protect. The browser visor’s bulk downloads were found dying whenever one of its small handful of relays dropped, fixed with five separate changes to how it spreads across hosts and recovers a pruned leg. And the onboarding tour, which had quietly stopped shipping three weeks earlier when the browser’s rendering engine was swapped out from under it, came back as two separate tours for two surfaces that no longer share a page.

Skywire: Deployment Services Move Inside the Visor

5237 let transport-discovery, the address resolver, the route finder and service-discovery all run directly inside a visor process rather than as their own standalone services, each one mounted under its own path prefix on the visor’s existing dmsg HTTP port and addressed by the visor’s own key — a service configured this way keeps no key, listener or dmsg session of its own, since its CXO publishers and aggregators simply run on the visor’s own dmsg client instead. 5241 fixed the e2e lane the very same day, having found the embedded service-discovery left without a nonce store at all, which meant its registration endpoint didn’t exist and no client could register through it; it now keeps the same in-memory nonce store the embedded address-resolver and transport-discovery already had.

5243 found a second, more structural conflict: a visor already publishes its registration and telemetry feeds on fixed dmsg ports, and an embedded service tries to aggregate a feed on those same ports under the same key, so the two could never both actually listen — an embedded aggregator now attaches directly to the visor’s own publisher node instead of trying to open its own, with the visor handing it its Roots in-process rather than over a loopback announce that would otherwise cost a pointless self-directed handshake. 5245 cleared out years of drift across the five discovery-type services, which had accumulated two different flags with different meanings for the same “test mode” concept, five separate copies of the same store and nonce-store rules, and four separate copies of the same health-check type; all five now share one common configuration base, with a single --testing flag replacing the inconsistent pair and meaning exactly one thing everywhere it appears.

Skywire: Registration Learns to Trust the Feed It’s Already Subscribed To

5249 found visors re-posting their service-discovery entries and address-resolver bindings over a fresh Noise handshake every ninety seconds, regardless of whether anything had actually changed, even though the CXO feed both services are already subscribed to refreshes the identical stored record every forty-five seconds on its own; an unchanged entry is now only re-sent over HTTP once every thirty minutes while the subscription stays healthy, with any real change still posting immediately.

5252 extended the same idea further, dropping a thirty-minute timed HTTP refresh entirely in favor of trusting the feed’s own heartbeat, with HTTP now reserved for the first registration, any actual change, and the one re-registration a service needs after reconnecting on a fresh connection. 5253 fixed a bug the previous day’s change exposed: a service can hold two simultaneously subscribed connections to the same visor’s feed, and picking whichever one happened to come first as the canonical subscription was bumping a keepalive counter on most checks, which kept forcing the local visor to re-bind to the address resolver over HTTP every single cycle regardless of the new logic.

5251 fixed an e2e test that had been asserting a specific service published at least one root locally when that service, by design in the embedded test topology, legitimately registers none.

5240 found a quieter but much larger cost in the same area: the CXO layer’s own idle-connection reaper closed any connection with no inbound message for ninety seconds, but a registration feed only actually publishes when its entry changes, so a perfectly healthy, idle connection got reaped and redialed on every single announce cycle regardless — on one production host that meant roughly forty-eight hundred needless resubscribes for fewer than a thousand visors in half an hour. A connection silent for thirty seconds now gets a lightweight list request instead of being torn down outright, which every node already answers and which keeps both ends alive without waiting for a reply.

5239 found a related cost on the dmsg server side: a server with no local session for an offline destination asks every one of its peers in turn on every single forwarding attempt, which for a key that’s redialed constantly, like an offline hypervisor, cost one stream per peer per attempt and logged tens of thousands of failed forwards in half an hour on one production server; a destination every peer has already said “not here” about is now refused outright for thirty seconds rather than asked again immediately.

Skywire: A Lock Held Too Long, and Relays Spread Across Hosts

5235 found the transport manager’s write lock held across an entire incoming settlement handshake, which waits on the dialing peer for up to twenty seconds — so a single peer that connected and then simply never sent its own entry could freeze the entire transport map for that whole window, and one peer doing exactly that three times in a row held the lock for fifty-nine seconds straight on a production host while a dozen other transports backed up behind it. The lock is now held only for the lookup-or-create step, with the handshake itself running outside it, mirroring what the outbound dial path had already been doing correctly.

5234 found the browser visor’s bulk downloads dying whenever one of its small handful of WebTransport relays dropped, often because several of those few relays happened to sit on the same host; five separate fixes spread the visor’s own autoconnect across distinct hosts rather than counting a second relay on an already-reached host as progress, made a pruned leg’s in-flight data resend on a surviving leg instead of being lost, and let a tunnel below its target width dial a fresh leg even when the standby pool is empty rather than waiting on a pool that may never fill.

Skywire: Two Guided Tours Return

5242 brought the onboarding tour back after discovering it had quietly stopped shipping three weeks earlier, when the file it lived in was handed off to the netscrape project and netscrape then retired the JavaScript rendering engine that tour’s code depended on, taking it down with no one noticing since nothing had linked to the page in the meantime. It returns as two separate tours rather than one, because the dashboard and the desk no longer share a single page to walk through together — an Angular admin console about visors, and a window manager about the browser tab itself, each now gets its own tour built for what it actually is.

5244 fixed the hypervisor tour’s eleven steps about “your own visor” actually pointing at whichever visor happened to sort first in a fleet listing, rather than the one the reader is actually running, found by walking the merged tour against a hypervisor managing thirty-five visors. 5247 fixed the tour’s own help button going permanently stale after logging in, since the code meant to notice navigation only listened for browser history events the Angular router’s own navigation never actually fires.

5248 tracked down why an apostrophe in the tour’s own copy was rendering with visible gaps on either side of it, down to the specific system font’s own glyph-width table rather than any CSS the previous day’s fix had blamed.

5250 rewrote both tours’ opening copy, which had oversold an ordinary Angular admin console as something unusual when the actually unusual thing is a visor routing mesh traffic from inside a browser tab with a window manager around it, and shifted both tours from addressing the reader directly to simply narrating what’s on the screen, since the same copy is read by someone who installed a system daemon and someone who merely clicked a link.

Skywire: Documentation Catches Up With the Desk

5236 rewrote the desk’s own UI tour document, which had still been describing cmd/wasm-visor’s chat, content-hosting, console and log windows years after that command was removed and replaced outright by the desk — stale specifically because nothing in the docs tree still linked to the page, so its drift went unnoticed until someone walked it against the running desk directly. The rewrite replaces seven outdated screenshots with current ones and explains which windows change shape when a native hypervisor is the one serving the desk rather than treating the browser and native cases as a single, identical UI.