Commit Graph
28 Commits
Author SHA1 Message Date
codingetandCodex 5c7d787b90 test(transport): restore stream regression coverage
CI / lint (pull_request) Successful in 1m39s
CI / format (pull_request) Successful in 1m51s
CI / install (pull_request) Successful in 6m6s
CI / typetest (pull_request) Successful in 1m52s
CI / typecheck (pull_request) Successful in 2m10s
CI / node-tests (pull_request) Successful in 2m34s
CI / browser-tests (pull_request) Successful in 3m34s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-26 23:24:18 +00:00
codingetandCodex c218117597 refactor(transport): group operation helpers
CI / format (pull_request) Successful in 1m26s
CI / lint (pull_request) Successful in 1m36s
CI / install (pull_request) Successful in 6m7s
CI / typetest (pull_request) Successful in 1m29s
CI / typecheck (pull_request) Successful in 1m59s
CI / node-tests (pull_request) Successful in 2m16s
CI / browser-tests (pull_request) Successful in 3m19s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-26 18:06:52 +00:00
codingetandCodex 3aad6182b2 refactor: remove transport helper aliases
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-26 18:06:52 +00:00
codingetandCodex 33d9d115cf docs(transport): clarify pump cleanup timing
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-26 18:06:52 +00:00
codingetandCodex ccc7496ca1 test(transport): cover wrapper cancellation contract
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-26 18:06:52 +00:00
codingetandCodex 304961a839 fix(transport): tighten cancellation helpers
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-26 18:06:52 +00:00
codingetandCodex 048cea10f3 feat(transport): add cancellable stream I/O
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-26 18:06:52 +00:00
codingetandCodex e15718a012 fix(http): reject truncated response bodies
CI / format (pull_request) Successful in 2m53s
CI / lint (pull_request) Successful in 2m57s
CI / install (pull_request) Successful in 8m7s
CI / typetest (pull_request) Successful in 2m59s
CI / node-tests (pull_request) Successful in 3m17s
CI / typecheck (pull_request) Successful in 3m26s
CI / browser-tests (pull_request) Successful in 5m17s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-18 23:13:06 +00:00
codingetandCodex 2798322a0a test(transport): separate WebRTC close from cleanup
CI / lint (pull_request) Successful in 2m45s
CI / format (pull_request) Successful in 2m45s
CI / install (pull_request) Successful in 7m45s
CI / typetest (pull_request) Successful in 2m50s
CI / typecheck (pull_request) Successful in 3m3s
CI / node-tests (pull_request) Successful in 3m13s
CI / browser-tests (pull_request) Successful in 5m6s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-17 02:12:35 +00:00
codingetandCodex 6a84570c63 test(transport): update browser EOF assertion
CI / lint (pull_request) Successful in 2m31s
CI / format (pull_request) Successful in 2m35s
CI / install (pull_request) Successful in 8m55s
CI / typetest (pull_request) Successful in 2m13s
CI / node-tests (pull_request) Successful in 3m6s
CI / typecheck (pull_request) Successful in 3m8s
CI / browser-tests (pull_request) Failing after 4m25s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-17 01:56:10 +00:00
codingetandCodex ba9983de32 feat(transport): signal end of stream explicitly
CI / lint (pull_request) Successful in 2m10s
CI / format (pull_request) Successful in 2m25s
CI / install (pull_request) Successful in 7m4s
CI / typetest (pull_request) Successful in 2m23s
CI / typecheck (pull_request) Successful in 2m41s
CI / node-tests (pull_request) Successful in 2m51s
CI / browser-tests (pull_request) Failing after 4m19s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-17 01:42:34 +00:00
codingetandClaude f659f230cd docs: add per-package READMEs and position Tailshare as the flagship app
CI / lint (pull_request) Successful in 3m39s
CI / format (pull_request) Successful in 3m24s
CI / install (pull_request) Successful in 9m4s
CI / typetest (pull_request) Successful in 3m5s
CI / typecheck (pull_request) Successful in 3m20s
CI / node-tests (pull_request) Successful in 3m31s
CI / browser-tests (pull_request) Successful in 5m16s
Give every workspace a README describing what it does, its entry points,
and a short usage example, and link them from the root package table.

Frame Tailshare in the root README as the application the libraries exist
to be composed into, with the other apps as development and testing
surfaces. Its own README records what works today and what the open
issues intend for it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 23:51:59 +00:00
codingetandCodex 8451205d62 refactor: address package-boundary review
CI / format (pull_request) Successful in 1m38s
CI / lint (pull_request) Successful in 1m39s
CI / typecheck (pull_request) Canceled after 0s
CI / typetest (pull_request) Canceled after 0s
CI / node-tests (pull_request) Canceled after 0s
CI / browser-tests (pull_request) Canceled after 0s
CI / install (pull_request) Canceled after 4m25s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-07-26 14:13:21 +00:00
codingetandCodex e9bde4cf3c feat: extract generic state transfer package
CI / lint (pull_request) Successful in 1m26s
CI / format (pull_request) Successful in 1m26s
CI / install (pull_request) Successful in 4m31s
CI / typetest (pull_request) Successful in 1m2s
CI / node-tests (pull_request) Successful in 1m21s
CI / typecheck (pull_request) Successful in 1m26s
CI / browser-tests (pull_request) Successful in 2m40s
Co-Authored-By: gpt-5.6-luna <noreply@openai.com>
2026-07-25 17:31:13 +00:00
codingetandClaude 2797234f23 feat(transport): add StateTransferable interface
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 17:05:47 +00:00
codingetandClaude 2555cdd47f fix(transport): make pre-handshake upgrade failures consistent and leak-free
Addresses a blocking external-review finding: pre-handshake TLS
configuration failures could leave the connection state inconsistent
or leak the underlying socket.

- The Go upgradeTLS now closes the conn on configuration errors too
  (submodule bump), so Conn.upgradeTls marking itself closed on any
  raw rejection no longer strands a live, unclosable Go conn.
- NodeTransport.upgradeTls constructs the TLS socket inside the
  try/catch: createSecureContext/connectTls throw synchronously on
  invalid PEM, which previously escaped after listeners were detached
  and #upgrading was set, leaving the transport permanently stuck.
- Contract documented on RawTransport: synchronous option-validation
  rejections leave the transport usable; any failure after the upgrade
  starts closes it.

Regression tests: malformed server certPem/keyPem (sync throw path)
and malformed client caCerts (verification failure path) on node, both
asserting the closed-and-not-stuck end state; fatal-rejection contract
on the tsconnect Conn.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfRgMke8p7QDxD5QM5thxH
2026-07-12 14:08:40 +00:00
codingetandClaude da345d4d58 fix(transport): address neutral-review findings on TLS upgrade
- NodeTransport server-side upgrade no longer rejects on buffered data:
  a pipelining peer's ClientHello can land in the internal buffer in the
  gap between writing the go-ahead and calling upgradeTls. Buffered
  chunks are unshifted back into the stream for the TLS wrap to consume.
  Client-side, buffered data still rejects (there it is a protocol bug).
- The worker upgradeError reply now carries a closed flag so WorkerConn
  only tears down the connection when the handshake actually failed;
  rejected upgrades (bad options, stale wasm) leave it usable, matching
  the direct Conn semantics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfRgMke8p7QDxD5QM5thxH
2026-07-12 14:08:40 +00:00
codingetandClaude e29e097863 fix(transport): guard read/write during an in-flight TLS upgrade
Review finding: the quiescence check ran only before starting the
upgrade; reads or writes issued while the handshake was in flight
would race it on the underlying socket (node) or hit the stale
pre-upgrade Go handle (tsconnect). All three implementations now
track an upgrading flag that read(), write() and a second
upgradeTls() reject on. Also front-load the serverName-required
check in Conn.upgradeTls to match NodeTransport.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfRgMke8p7QDxD5QM5thxH
2026-07-12 14:08:40 +00:00
codingetandClaude 1689c2eacc feat(transport): add explicit TLS upgrade (STARTTLS / AUTH TLS) to RawTransport
Adds an optional in-place upgradeTls(options) method and an isTls
getter to RawTransport, implemented on the node and tsconnect
transports. Client mode takes serverName/insecureSkipVerify/caCerts
(serverName required unless skipping verification); server mode takes
isServer with a PEM cert/key pair. Upgrading requires a quiescent
transport and closes the connection on handshake failure.

NodeTransport wraps its existing socket with node:tls; tsconnect's
Conn swaps its raw handle via the new upgradeTLS wasm bridge method
(tailscale submodule bump); tsconnect-worker forwards the upgrade over
new per-conn protocol messages and carries isTls on conn/accepted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfRgMke8p7QDxD5QM5thxH
2026-07-12 14:08:40 +00:00
codinget 57702a3943 chore: run prettier
Node Tests / node-tests (pull_request) Successful in 4m44s
Browser Tests / browser-tests (push) Failing after 7m18s
Browser Tests / browser-tests (pull_request) Successful in 10m9s
Node Tests / node-tests (push) Failing after 11m24s
2026-06-23 23:44:49 +00:00
codingetandClaude 673fa3aba3 fix(test): address code review feedback on browser testing PR
- serveDirectory: replace regex path traversal guard with resolve+relative
  check, which is simpler to reason about and handles encoded edge cases
- drop test:browser:coverage scripts; c8 only covers Node orchestration
  code, not browser-executed code inside page.evaluate() — the resulting
  lcov is nearly empty and would confuse CI coverage dashboards
- guard server?.close() in after() hooks so teardown doesn't throw a
  TypeError if the before() hook failed to start the server
- extract setupLoopback() helper inside each page.evaluate() in
  transport.browser.ts to avoid verbatim repetition between tests
- add comment in helpers.browser.ts explaining the IDB readonly-transaction
  trick that ensures setState()'s async write has settled before opening
  a second IndexedDBState instance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 12:47:31 +00:00
codingetandClaude c89c478286 feat(test): add browser integration testing with Playwright
Uses Playwright as a library within node:test (not @playwright/test) to
keep the same runner and script conventions. Browser test files use the
*.browser.ts extension so the existing src/**/*.test.ts glob picks up zero
browser tests, leaving the regular test suite unaffected.

Key pieces:
- .npmrc: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 prevents binary downloads on
  npm ci; browsers are installed explicitly in CI via playwright install
- @webnet/browser-test-utils: new private package exporting forBrowsers()
  (iterates chromium + firefox, handles browser lifecycle within node:test
  suite/before/after) and a serveDirectory() helper (minimal http.createServer
  that serves a built dist/ or out/ directory so the browser can fetch ES
  modules via dynamic import())
- test:browser / test:browser:coverage scripts added to transport, vfs,
  tsconnect following the same c8 + lcov pattern as test:coverage
- turbo.json: test:browser and test:browser:coverage tasks depend on build +
  ^build (dist/ must exist before the browser can import from it)
- .gitea/workflows/test-browser.yml: CI pipeline that installs browsers with
  --with-deps then runs npm run test:browser

Integration tests:
- DataChannelTransport: real RTCPeerConnection loopback (both peers in one
  page context), exercises send/receive and close propagation
- FsaVFS: OPFS round-trip (writeFile/readFile), stat, readdir, delete
- IndexedDBState: multi-instance persistence (write via instance 1, open
  fresh instance 2 and verify IDB round-trip), empty-DB initialisation
- FsaFileOps: write/read/stat/remove cycle and rename/listFiles over OPFS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 12:47:30 +00:00
codingetandClaude f0be079706 test(transport/webrtc): achieve 100% branch coverage
Add five tests covering the previously-missed branches:
- read() after clean channel close (no stored error)
- read() after error event re-throws the stored error
- error event with null error field falls back to generic message
- close event while write drain is pending rejects the write
- open-phase error with null error field uses generic message

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 19:45:20 +00:00
codingetandClaude eab3d69723 feat(transport): add WebRTC DataChannel transport
Implements RawTransport over an RTCDataChannel with write-side and
receive-side backpressure. Write-side: send() is always synchronous, but
write() defers its promise until bufferedamountlow fires when
bufferedAmount exceeds sendHighWatermark, using
bufferedAmountLowThreshold for the resume threshold. Receive-side:
removes the message event listener when buffered bytes exceed
receiveHighWatermark, letting SCTP's internal buffer fill and signal
flow control back to the sender; re-adds the listener once read() drains
below receiveLowWatermark.

Factory functions openDataChannel (creates + waits for open) and
acceptDataChannel (wraps an incoming channel) return a transport only
once the channel is fully open. Both accept separate send/receive
watermark options. All WebRTC types are defined as structural interfaces
so the package requires no DOM lib and tests use an in-process mock.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 19:21:05 +00:00
codingetandClaude 9bfd119b21 fix(transport): fix NodeListener double-callback and connection leak
When close() was called, it fired #errcallback synchronously and also
left the server's "close" event free to fire it a second time.
Null out #errcallback before invoking it so both event-driven paths
are guarded and only one caller receives the rejection.

In accept(), the once("connection") listener was never removed when the
promise was rejected (e.g. via close()), so any late-arriving connection
would create a NodeTransport that was immediately dropped.
Replace the bare once() with a named handler that the error callback
removes before rejecting.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 20:36:41 +00:00
codingetandClaude c05f20c0bf chore: add test/test:coverage to turbo; remove unit/external test split
- turbo.json: add test and test:coverage pipeline tasks (dependsOn: ^build)
- root package.json: add test and test:coverage scripts via turbo
- Remove test:unit, test:coverage:unit, test:watch:unit from all packages
- Remove test-helpers/flags.ts from transport, http, websocket (and dirs)
- Remove fetch.node.test.ts (external test hitting google.com; always skipped)
- Drop { skip: skipIfNotIntegration } from all suites — tests run unconditionally

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 21:52:42 +00:00
codingetandClaude 2b6c463ef5 refactor(transport): move ReadBuffer/WriteBuffer/prependTransport to @webnet/transport/buffer
Removes @webnet/websocket's _internals dependency on @webnet/http.
http/common/buffer.ts becomes a thin re-export; all http-internal imports are unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 20:15:05 +00:00
codingetandClaude 1fbe2c844c feat(transport): extract @webnet/transport package
Pulls RawTransport, RawDialer, RawListener, Reader, Writer, and PairSync
out of @webnet/http into a new protocol-agnostic @webnet/transport package.
Node and loopback transport implementations move there as sub-exports
(./node, ./loopback); @webnet/http re-exports the types to keep existing
internal imports resolving.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-06 12:45:31 +00:00