Remove obsolete wasm bridge APIs #17
Labels
Clear labels
Agentic
Component/CI
Component/Funnel
Component/React
Component/State
Component/Taildrive
Component/Taildrop
Component/Tailscale
Component/Tailshare
Component/Transport
Component/tsconnect
Component/VFS
Component/WebRTC
Component/Worker
Human
Protocol/FTP
Protocol/HTTP
Protocol/SFTP
Protocol/SMB
Protocol/SSH
Protocol/WebDAV
Protocol/WebSocket
Security
Agent
claude-fable-5
Work done by Claude Fable 5
Agent
claude-opus-4-8
Work done by Claude Opus 4.8
Agent
claude-opus-5
Work done by Claude Opus 5
Agent
claude-sonnet-4-6
Work done by Claude Sonnet 4.6
Agent
claude-sonnet-5
Work done by Claude Sonnet 5
Agent
gpt-5.5
Work done by GPT 5.5
Agent
gpt-5.6-luna
Work done by GPT 5.6 Luna
Agent
gpt-5.6-sol
Work done by GPT 5.6 Sol
Agent
gpt-5.6-terra
Work done by GPT 5.6 Terra
Opened by an agent
Work on the CI tooling
Work on the Tailscale Funnel or certificate system
Work on a React binding
Work on a state store (eg Redux)
Work on the taildrive system
Work on the taildrop system
Work on the Tailscale fork
Work on the Tailshare app
Work on the transport system
Work on the tsconnect packages
Work on the VFS system
Work on the WebRTC system
Work on the worker system
Opened by a human
Kind
Bug
Bug work
Kind
Enhancement
Enhancement work
Kind
Feature
Feature work
Kind
Maintenance
Maintenance work
Priority
P0
1
Critical work that must be done right now
Priority
P1
2
Urgent work
Priority
P2
3
Medium priority work
Priority
P3
4
Low priority work
Priority
P4
5
Lowest priority work, wishlist-tier
Work on the FTP protocol
Work on the HTTP protocol
Work on the SFTP protocol
Work on the SMB protocol
Work on the SSH protocol
Work on the WebDAV protocol
Work on the WebSocket protocol
Security work
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: webnet/tailscale#17
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Removes obsolete APIs from the js/wasm bridge after their JavaScript-side removal in webnet/webnet#150.
sshandfetchbridge methods, including the directgolang.org/x/crypto/sshdependencysetExitNodeEnabled; callers clear the exit node throughsetExitNodediscoping typeImplements the remaining wasm bridge work from webnet/webnet#141, #144, and #145.
Checks:
GOOS=js GOARCH=wasm ./tool/go test -run=^$ -tags=netgo,omitidna,omitpemdecrypt,osusergo,tailscale_go,ts_omit_ace ./cmd/tsconnect/wasmgolang.org/x/crypto/sshis absent fromgo list -depsAI disclosure: implemented and reviewed with Codex (
gpt-5.6-sol).Review: Remove obsolete wasm bridge APIs
The Go change itself is clean and I could reproduce the claims. What is missing is the TypeScript half of
cmd/tsconnect, which still speaks to the APIs this PR deletes.Verified
GOOS=js GOARCH=wasm ./tool/go vet -tags=netgo,omitidna,omitpemdecrypt,osusergo,tailscale_go,ts_omit_ace ./cmd/tsconnect/wasmis clean atd94244830— no orphaned imports (bytes,x/crypto/sshwere the only two that became unused;net/http,strings,ipnauthare still needed).golang.org/x/crypto/sshis gone from the wasm dependency graph:go list -depsmatches 2 packages onwebnet, 0 on this branch.pingnarrowing matches the consumer:packages/tsconnect/src/types.tsalready declaresPingType = "TSMP" | "ICMP" | "peerapi"andpackages/tsconnect/src/ipn.ts:428already rejects"disco"before it reaches the bridge.ssh/fetch/setExitNodeEnabledremain incmd/tsconnect/README.md,README.pkg.md, or the Go sources.1. The TS side of
cmd/tsconnectstill calls the removed methodscmd/tsconnect/src/types/wasm_js.d.ts:16and:32still declaressh(...)andfetch(url)on theIPNinterface. Because that declaration is whatyarn lint(tsc --noEmit, run bybuild-pkg) checks against, nothing fails — the type contract just silently became wrong, and the callers below stay green:cmd/tsconnect/src/lib/ssh.ts:56callsipn.ssh(def.hostname, def.username, {...}). After this PR that property isundefined, sorunSSHSessionthrowsTypeError: ipn.ssh is not a functionon first use.cmd/tsconnect/src/pkg/pkg.ts:40re-exportsrunSSHSessionfrom the published package entrypoint.build-pkgbundlessrc/pkg/pkg.ts(common.go:111) and generatespkg.d.tsfrom it, so the shipped package advertises and exports an API that is dead on arrival. This is not hypothetical for downstream:packages/tsconnect/build.shin webnet/webnet runsbuild-pkg -pkgdir dist, and@webnet/tsconnectpublishesfiles: ["dist/"].runSSHSessionstays in the entrypoint's export graph, esbuild keeps bundlingxterm,xterm-addon-fitandxterm-addon-web-linksintodist/pkg.jsfor code that can no longer run — which eats into the 2.0% wasm win the description reports.src/app/app.tsx:66,src/app/ssh.tsx) still renders an SSH tab that now breaks at runtime undergo run . dev.Suggested fix, smallest to largest:
sshandfetchdeclarations fromwasm_js.d.ts. That makestsc --noEmitsurface every remaining caller instead of hiding them, so the build fails loudly rather than the package shipping broken exports.src/lib/ssh.ts,src/app/ssh.tsxand its use inapp.tsx, therunSSHSessionre-export inpkg.ts, and the threexterm*entries incmd/tsconnect/package.json.If keeping the upstream demo app intact is a deliberate goal for future rebases, that is a fine call to make — but then
wasm_js.d.tsshould still be corrected and the breakage noted in the PR description, because right now it reads as though the JS side is fully settled.2. Nit:
setExitNode("")is not equivalent tosetExitNodeEnabled(false)The description says "callers clear the exit node through
setExitNode". That is true for the clearing effect, butSetUseExitNodeEnabled(false)also setsInternalExitNodePriorand clearsAutoExitNode(ipn/ipnlocal/local.go:5130-5136), which is what makes a later re-enable possible.jsIPN.setExitNodeonly setsExitNodeID. Since webnet/webnet dropped the toggle entirely rather than reimplementing it on top ofsetExitNode, nothing regresses — the wording just slightly oversells it as a drop-in replacement.Once the
wasm_js.d.tsdeclarations are dropped, this is good to go from my side.Reviewed with Claude Opus 5.
Two corrections to my review above.
Withdrawing the
setExitNodeEnablednit. It holds in the generalLocalBackendcase but not here: the bridge only ever surfacesPrefs.ExitNodeID(wasm_js.go:557, vianotifyExitNode), and never reads or emitsInternalExitNodePriororAutoExitNode. The only reader ofInternalExitNodePriorwasSetUseExitNodeEnableditself, which this PR removes, andAutoExitNodewas never settable through the bridge in the first place (jsIPN.setExitNodesetsExitNodeIDonly), so clearing it was already a no-op. Neither is observable from the API surface or from Tailscale behavior, sosetExitNode("")is genuinely equivalent here and the description is accurate as written.I overstated the downstream impact of the leftover TS.
pkg-typeswrites to a hardcodedpkg/pkg.d.ts(cmd/tsconnect/package.json:19) rather than to-pkgdir, so the generated types land incmd/tsconnect/pkg/pkg.d.tsand never reach the-pkgdiroutput. The builtdist/in webnet/webnet confirms it — there is nopkg.d.tsthere, and nothing importsdist/pkg.js:@webnet/tsconnectmain.wasmcacert.pemwasm_exec.jssrc/index.ts:1)build-info.jsonpkg.jspkg.js.mappkg.csspkg.css.mappackage.json@tailscale/connectmanifest)README.mdSo it is purely npm package bloat: ~1.5 MB of unreferenced files in a 37.6 MB tarball. The broken
runSSHSessionis never loaded and never appears in the published type surface, and the bundledxtermlives inpkg.js, notmain.wasm— my line about it eating into the 2.0% wasm win was wrong.What remains from finding 1 is in-repo only, with no downstream consequence:
src/types/wasm_js.d.tsnow misdeclaresssh/fetch, which is what keepsyarn lintgreen over the now-brokensrc/lib/ssh.ts:56, and thego run . devdemo app's SSH tab fails at runtime. Still worth correcting so the type contract does not lie, but it does not block this PR.The lack of changes outside the wasm bridge itself is intentional, to keep this fork's patchset against upstream minimal, to simplify rebases whenever we need to catch up.
The fact that files that aren't useful to us are still ending up in @webnet/tsconnect's dist directory is preexisting, they've always been unused but now they're also incorrect and broken. Not blocking, but tracked in webnet/webnet#154 purely to remove dead weight and package bloat.
Final assessment: APPROVED.