Add drive.go: implements drive.FileSystemForRemote with a JS-backed streaming handler. The Go goroutine stays alive for the response duration; JS calls write(chunk)/end() to stream the body back. Request body is streamed chunk-by-chunk via readBodyChunk() (no full-body buffering).
Add drive_stub.go: no-op stubs for ts_omit_drive builds.
Add peer.go: buildPeerAPIURL helper extracted from the inline logic in run().
Modify wasm_js.go: call initDriveForRemote before NewLocalBackend (SubSystem is set-once), expose setDriveHandler and listDrivePeers via wireDriveJS, refactor peerAPI URL logic to use buildPeerAPIURL.
listDrivePeers mirrors native driveRemotesFromPeers: returns empty if DriveAccessEnabled() is false, filters peers by PeerCapabilityTaildriveSharer via the live ACL cap map (lb.PeerCaps(addr).HasCapability()).
Auth is fully handled by handleServeDrive in peerapi_drive.go before our code runs — the JS handler only receives pre-authenticated, permission-scoped requests.
Test plan
GOARCH=wasm GOOS=js ./tool/go vet ./cmd/tsconnect/wasm/ passes
setDriveHandler wired up in the JS object returned by newIPN
listDrivePeers returns empty array when DriveAccessEnabled() is false
End-to-end: peer with drive:share ACL can be browsed via WebDAV from another node
The end-to-end item requires ACL nodeAttrs/grants/Taildrive support on the control plane, which only landed in Headscale v0.29.0 (not yet released stably — only v0.29.0-beta.4 exists as of writing). Deferred until a stable v0.29.0 release. webnet/webnet#27 has unit tests covering the JS-side bridge and IPN methods without requiring a live network.
## Summary
- Add drive.go: implements drive.FileSystemForRemote with a JS-backed streaming handler. The Go goroutine stays alive for the response duration; JS calls write(chunk)/end() to stream the body back. Request body is streamed chunk-by-chunk via readBodyChunk() (no full-body buffering).
- Add drive_stub.go: no-op stubs for ts_omit_drive builds.
- Add peer.go: buildPeerAPIURL helper extracted from the inline logic in run().
- Modify wasm_js.go: call initDriveForRemote before NewLocalBackend (SubSystem is set-once), expose setDriveHandler and listDrivePeers via wireDriveJS, refactor peerAPI URL logic to use buildPeerAPIURL.
listDrivePeers mirrors native driveRemotesFromPeers: returns empty if DriveAccessEnabled() is false, filters peers by PeerCapabilityTaildriveSharer via the live ACL cap map (lb.PeerCaps(addr).HasCapability()).
Auth is fully handled by handleServeDrive in peerapi_drive.go before our code runs — the JS handler only receives pre-authenticated, permission-scoped requests.
## Test plan
- [x] GOARCH=wasm GOOS=js ./tool/go vet ./cmd/tsconnect/wasm/ passes
- [x] GOARCH=wasm GOOS=js ./tool/go build ./cmd/tsconnect/wasm/ compiles cleanly
- [x] setDriveHandler wired up in the JS object returned by newIPN
- [x] listDrivePeers returns empty array when DriveAccessEnabled() is false
- [ ] End-to-end: peer with drive:share ACL can be browsed via WebDAV from another node
The end-to-end item requires ACL `nodeAttrs`/`grants`/Taildrive support on the control plane, which only landed in Headscale v0.29.0 (not yet released stably — only `v0.29.0-beta.4` exists as of writing). Deferred until a stable v0.29.0 release. webnet/webnet#27 has unit tests covering the JS-side bridge and IPN methods without requiring a live network.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add drive.go (build tag !ts_omit_drive): implements drive.FileSystemForRemote
with a JS-backed handler. Streams request bodies chunk-by-chunk via
readBodyChunk() and response bodies via write()/end() callbacks so no
full-body buffering occurs regardless of file size. The handler is nil-safe:
returns 404 until setDriveHandler() is called from JS.
Add drive_stub.go (build tag ts_omit_drive): no-op stubs for stripped builds.
Add peer.go: extract buildPeerAPIURL helper (previously inline in run()).
Modify wasm_js.go: call initDriveForRemote before NewLocalBackend (SubSystem
is set-once), expose setDriveHandler and listDrivePeers via wireDriveJS,
and refactor the inline peerAPI URL logic to use buildPeerAPIURL.
listDrivePeers mirrors native driveRemotesFromPeers: returns empty if
DriveAccessEnabled() is false, then filters peers by PeerCapabilityTaildriveSharer
using lb.PeerCaps(addr).HasCapability() (the live ACL-derived cap map).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Summary
listDrivePeers mirrors native driveRemotesFromPeers: returns empty if DriveAccessEnabled() is false, filters peers by PeerCapabilityTaildriveSharer via the live ACL cap map (lb.PeerCaps(addr).HasCapability()).
Auth is fully handled by handleServeDrive in peerapi_drive.go before our code runs — the JS handler only receives pre-authenticated, permission-scoped requests.
Test plan
The end-to-end item requires ACL
nodeAttrs/grants/Taildrive support on the control plane, which only landed in Headscale v0.29.0 (not yet released stably — onlyv0.29.0-beta.4exists as of writing). Deferred until a stable v0.29.0 release. webnet/webnet#27 has unit tests covering the JS-side bridge and IPN methods without requiring a live network.🤖 Generated with Claude Code
7c5ecfe50fto40e1346ab540e1346ab5tocada6936b9