Commit Graph
19 Commits
Author SHA1 Message Date
codingetandCodex 6499f202ad fix(tooling): typecheck support workspaces
CI / install (pull_request) Successful in 8m10s
CI / lint (pull_request) Successful in 3m7s
CI / format (pull_request) Successful in 3m8s
CI / typecheck (pull_request) Successful in 3m39s
CI / typetest (pull_request) Successful in 3m22s
CI / browser-tests (pull_request) Successful in 5m49s
CI / node-tests (pull_request) Successful in 1m22s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-20 17:12:54 +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 2cfb14eb29 refactor: rename drive package to webdav
CI / lint (pull_request) Successful in 3m59s
CI / format (pull_request) Successful in 4m18s
CI / install (pull_request) Successful in 9m3s
CI / typetest (pull_request) Successful in 3m14s
CI / typecheck (pull_request) Successful in 3m19s
CI / node-tests (pull_request) Successful in 3m35s
CI / browser-tests (pull_request) Successful in 5m35s
Co-Authored-By: gpt-5.6-sol <noreply@openai.com>
2026-08-14 23:08:01 +00:00
codinget b35a533164 feat(test-app): add ssh to test-app
CI / format (pull_request) Successful in 1m41s
CI / lint (pull_request) Successful in 1m53s
CI / install (pull_request) Successful in 6m7s
CI / typetest (pull_request) Successful in 2m13s
CI / node-tests (pull_request) Successful in 2m35s
CI / typecheck (pull_request) Successful in 2m36s
CI / browser-tests (pull_request) Successful in 4m2s
2026-07-12 23:41:20 +00:00
codinget 4ea36eb05b feat(test-app): add sftp to test-app
CI / lint (pull_request) Successful in 1m48s
CI / format (pull_request) Successful in 2m9s
CI / install (pull_request) Successful in 6m18s
CI / typetest (pull_request) Successful in 2m8s
CI / typecheck (pull_request) Successful in 2m24s
CI / node-tests (pull_request) Successful in 2m23s
CI / browser-tests (pull_request) Successful in 4m9s
2026-07-12 22:59:01 +00:00
codingetandClaude ac7a7ab464 feat(smb2): add SMB2/3 client with async VFS interface
Add @webnet/smb2, an SMB2/3 client that runs over the existing transport
abstraction and exposes a remote Windows/Samba share as an AsyncVFS, the
same way @webnet/drive exposes WebDAV. Targets default Windows 10/11
(including 24H2 mandatory signing) and supported Samba, negotiating
dialects {2.0.2, 2.1, 3.1.1}.

Runs unchanged in browser and Node with no Node APIs and no new
dependencies: MD4/MD5/HMAC-MD5 are hand-written (NTLM only), AES-CMAC is
built on Web Crypto AES-CBC, SP800-108 KDF on HMAC-SHA256, and SHA-512
preauth and HMAC-SHA256 signing use Web Crypto. NTLMv2 over NTLMSSP/SPNEGO
with MIC; SMB signing implemented, SMB3 encryption deferred.

Includes crypto/auth vector tests, protocol codec round-trips, an in-repo
mock SMB2 server for end-to-end coverage over the loopback transport, and
an env-gated integration test. Wired into test-app as window.smb2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014AcGBx7EjVaByiHcBcsSfP
2026-07-12 19:28:12 +00:00
codingetandCodex 77041f815f feat(dev): add remote host development mode
CI / typecheck (pull_request) Successful in 2m11s
CI / node-tests (pull_request) Successful in 2m11s
CI / browser-tests (pull_request) Successful in 3m40s
CI / lint (pull_request) Successful in 1m25s
CI / format (pull_request) Successful in 1m18s
CI / install (pull_request) Successful in 5m31s
CI / typetest (pull_request) Successful in 1m58s
Co-Authored-By: GPT-5.6 Terra <noreply@openai.com>
2026-07-12 00:36:02 +00:00
codinget fee32aeb67 feat(test-app): add ftp to test-app
CI / format (pull_request) Successful in 1m39s
CI / browser-tests (pull_request) Successful in 3m45s
CI / install (pull_request) Successful in 5m29s
CI / typetest (pull_request) Successful in 2m1s
CI / node-tests (pull_request) Successful in 2m11s
CI / lint (pull_request) Successful in 1m34s
CI / typecheck (pull_request) Successful in 2m13s
2026-07-12 00:22:09 +00:00
codingetandClaude 37f2fb04a0 feat: integrate @webnet/react and @webnet/utils into example-app and test-app
Checks / lint (pull_request) Successful in 2m50s
Checks / format (pull_request) Successful in 3m22s
Checks / typetest (pull_request) Successful in 10m10s
Checks / typecheck (pull_request) Successful in 10m43s
Node Tests / node-tests (pull_request) Successful in 10m50s
Checks / build (pull_request) Successful in 11m27s
Browser Tests / browser-tests (pull_request) Successful in 12m2s
- example-app: replace local useClient duplicate with @webnet/react, add
  useLocalStorage to persist SharedWorker preference across page reloads
- example-app: replace local fmtSize duplicate with @webnet/utils/fmtSize,
  use download() util in WaitingFileDebug instead of inline logic
- test-app: add @webnet/utils dependency and expose it on window alongside
  other globals for console testing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 16:34:42 +00:00
codingetandClaude 68313fdcda feat(vfs): extract @webnet/vfs package from @webnet/drive
Splits the VFS abstraction (AsyncVFS, Stat, VFSError, VFSErrorCode) and
its implementations (MemoryVFS, NodeVFS, FsaVFS) into a new standalone
@webnet/vfs package, following the same pattern as the @webnet/transport
split from @webnet/http.

packages/drive now depends on @webnet/vfs and imports directly from it.
packages/test-app likewise imports MemoryVFS and FsaVFS from @webnet/vfs.
The drive package.json export map drops the ./vfs/* sub-exports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 16:20:27 +00:00
codinget 5a6c6e97bc feat(test-app): expose http/router, websocket and drive 2026-06-08 19:18:39 +00:00
codinget 0b0c02e2f9 feat(test-app): expose helpers to window 2026-04-14 22:12:19 +00:00
codingetandClaude 61ec60b46c feat(http): initialize @webnet/http package and wire into test-app
- Add packages/http with package.json, tsconfig.json, and empty index.ts
- Add @webnet/http as a dependency of test-app
- Expose http namespace on window for console testing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 22:19:55 +00:00
codingetandClaude 341ece4f55 chore: add prettier, eslint, dpdm, lint-staged, commitlint; bump TS to 6
- Add Prettier with .prettierrc.json and format all source files
- Add ESLint v9 flat config with @eslint/js + typescript-eslint
- Add dpdm for circular dependency checking
- Add lint-staged (runs eslint + prettier on staged files)
- Add commitlint with conventional commits config
- Add husky pre-commit (lint-staged) and commit-msg (commitlint) hooks
- Bump TypeScript to ^6.0.2 in both packages
- Fix tsconnect moduleResolution: node → bundler (node10 deprecated in TS 6)
- Remove unused IPNConfig import and stale eslint-disable in ipn.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 20:35:51 +00:00
codingetandClaude fe4058184d feat(test-app): wire up cacert.pem for manual dialTLS testing
Import @webnet/tsconnect/cacert.pem as a URL and expose cacertURL plus a
fetch-and-cache loadCACerts() helper on window. The example snippet in
index.html now shows how to pass the bundle into IPN.dialTLS for hosts that
the baked-in LE roots don't cover.

Vite's default server.fs.deny blocks *.{crt,pem} to guard TLS private keys;
the shipped bundle is a public trust store, so vite.config.ts overrides the
deny list to drop that pattern while keeping the .env guards. (The 403 error
reports this as an allow-list failure, which is misleading — both paths go
through the same handler in isFileLoadingAllowed.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 16:45:22 +00:00
codinget fc3e46f9c0 feat(tsconnect): add class wrappers that validate before hitting Go
The raw objects returned from the wasm bridge are untyped bags of
js.FuncOf handlers. Calling them with the wrong types, on a closed
handle, or before the IPN is running, panics the Go runtime and
takes down the entire wasm instance for the lifetime of the page —
one bad call and the user has to reload.

Add src/ipn.ts with IPN / Conn / PacketConn / TCPListener classes
that wrap the raw handles and:

- Throw NotRunningError if an IPN method is called before run().
- Throw ClosedError if read/write/accept is called on a closed
  Conn/PacketConn/TCPListener, without dispatching into Go.
- Type-check string/Uint8Array arguments in JS before they reach
  js.CopyBytesToGo, which would otherwise crash.
- Range-check network literals for dial/listen/listenICMP.
- Expose addr / localAddr / remoteAddr / state / running / closed
  as getters rather than methods. Addresses are cached in the
  constructor so reading them never dispatches into Go, eliminating
  the "call .localAddr() on a closed conn" crash.
- Parse the netmap JSON inside notifyNetMap before handing it off,
  and make all run() callbacks optional (state is also a getter).

initIPN now returns a factory that produces IPN class instances
directly; index.ts re-exports the classes and hides the raw types,
so the public surface is the validated one.

The test-app inline example is updated to use getters (conn.remoteAddr,
ln.addr, ipn.state) instead of method calls.
2026-04-10 21:44:30 +00:00
codinget bdc4bcccee feat(tsconnect): add TCPListener and tighten dial/listen network types
Type the new TCP listening surface from the tailscale submodule:

- listen() is now overloaded: tcp/tcp4/tcp6 returns a TCPListener,
  udp/udp4/udp6 returns a PacketConn. The network parameter is a
  literal union instead of a bare string so callers get completion
  and typo protection.
- TCPListener extends AsyncIterable<Conn>, so consumers can write
  `for await (const conn of listener)`.
- dial() drops "udp" from its accepted networks. Connected UDP
  through a stream-shaped Conn was confusing; UDP belongs in
  listen(), and ICMP in listenICMP(). The Go side still accepts
  whatever string for callers who really want to bypass the type.

Bumps the TS lib/target to ES2018 for AsyncIterable, bumps the
tailscale submodule, and updates the test-app inline example to
demonstrate `for await` over a TCP listener.
2026-04-10 21:09:55 +00:00
codinget 08ddc31da1 feat(tsconnect): expose dialTLS and TLSDialOptions
Type the new ipn.dialTLS bridge from the tailscale submodule. The
default verification path uses the baked-in LetsEncrypt roots that
ship with the existing tsconnect wasm — sufficient for any tailnet
HTTPS endpoint provisioned via `tailscale cert`. Callers can supply
PEM roots, override SNI, or skip verification via TLSDialOptions.

Bumps the tailscale submodule and updates the test-app inline
example to demonstrate dialTLS.
2026-04-10 20:49:03 +00:00
codinget f445f03282 feat(test-app): add vite test app for manual browser testing
Adds a minimal @webnet/test-app package that boots a Vite dev server,
imports initIPN from @webnet/tsconnect and the bundled main.wasm as a
URL asset, and hangs both on window so you can drive the full IPN
lifecycle from devtools:

  const newIPN = await initIPN(wasmURL)
  const ipn = newIPN({ authKey, hostname })
  ipn.run({ ... })
  ipn.login()
  const conn = await ipn.dial("tcp", "peer:22")
  const pc = await ipn.listenICMP("icmp4")

The index.html doubles as usage documentation for the wrapper API.
2026-04-10 13:58:44 +00:00