Commit Graph
240 Commits
Author SHA1 Message Date
codingetandClaude db193130fb feat(sftp): package scaffold, SSH codecs, keys, and SFTP wire helpers
New @webnet/sftp package skeleton: big-endian SSH cursor (string/nameList/
mpint), SSH message constants, openssh-key-v1 Ed25519 key parse/serialize
with PKCS#8 seed wrapping and generateHostKey(), host-key/signature blob
codecs with Ed25519/RSA verification and SHA256 fingerprints, SFTP v3
packet/ATTRS codecs with Stat mapping and packet reassembly, SSH_FX status
to VFSError mapping, unix ls longname formatter, and lexical path helpers.
95 unit tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F3bV2ANs8WMHxefD5pF9LN
2026-07-06 18:20:52 +00:00
codingetandClaude 1313152b66 docs(agents): clarify CLAUDE.md symlink and tea mergeability output
CI / lint (pull_request) Successful in 1m1s
CI / format (pull_request) Successful in 1m9s
CI / install (pull_request) Successful in 4m3s
CI / typetest (pull_request) Successful in 55s
CI / node-tests (pull_request) Successful in 1m5s
CI / typecheck (pull_request) Successful in 1m6s
CI / browser-tests (pull_request) Successful in 2m15s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 08:35:43 +00:00
codinget 6471558e18 ci: don't run CI on main branch, it's guaranteed to have run earlier via PRs
CI / format (pull_request) Successful in 1m32s
CI / lint (pull_request) Successful in 1m35s
CI / install (pull_request) Successful in 4m30s
CI / typecheck (pull_request) Successful in 1m13s
CI / typetest (pull_request) Successful in 1m19s
CI / node-tests (pull_request) Successful in 1m19s
CI / browser-tests (pull_request) Successful in 2m40s
2026-07-04 01:23:50 +02:00
codingetandClaude f693b21210 test(tsconnect-worker): poll for message conditions instead of fixed sleeps
CI / format (pull_request) Successful in 1m15s
CI / lint (pull_request) Successful in 1m22s
CI / install (pull_request) Successful in 5m26s
CI / typetest (pull_request) Successful in 1m16s
CI / typecheck (pull_request) Successful in 1m24s
CI / node-tests (pull_request) Successful in 1m26s
CI / browser-tests (pull_request) Successful in 2m43s
CI / format (push) Successful in 53s
CI / lint (push) Successful in 1m2s
CI / install (push) Successful in 4m8s
CI / typetest (push) Successful in 1m9s
CI / node-tests (push) Successful in 1m14s
CI / typecheck (push) Successful in 1m20s
CI / browser-tests (push) Successful in 3m28s
Several worker.test.ts tests (WorkerSSHSession.resize()/close() flagged
as flaky in CI, plus other close()-message, callback-firing, and
pumpStreamToPort tests) waited a flat setTimeout(r, 10) after
postMessage before asserting the message arrived — the same race
already fixed for closed-state checks in b917cd8. Under CI load the
10ms sleep can elapse before the message is delivered, causing
sporadic AssertionErrors.

Added a generic waitFor(predicate, timeoutMs?) helper that polls via
setImmediate, replaced every fixed sleep with a poll on the actual
condition, and consolidated the four pre-existing
`while (!x.closed) await setImmediate()` spin-loops from b917cd8 onto
the same helper for consistency.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 22:59:40 +00:00
codingetandClaude 1aa26fd33e ci: consolidate workflows, build once per run
CI / lint (pull_request) Successful in 1m24s
CI / format (pull_request) Successful in 1m26s
CI / install (pull_request) Successful in 4m16s
CI / typetest (pull_request) Successful in 1m0s
CI / typecheck (pull_request) Successful in 1m29s
CI / browser-tests (pull_request) Successful in 2m48s
CI / node-tests (pull_request) Successful in 28s
CI / format (push) Successful in 1m6s
CI / lint (push) Successful in 1m6s
CI / install (push) Successful in 4m33s
CI / typecheck (push) Successful in 1m40s
CI / typetest (push) Successful in 1m42s
CI / node-tests (push) Successful in 1m38s
CI / browser-tests (push) Successful in 3m11s
Every job in the old checks.yml/test-node.yml/test-browser.yml
independently repeated checkout + tailscale submodule clone + npm ci,
and 5 of 7 also independently rebuilt the whole workspace via Turbo.
There was no caching anywhere.

Live smoke tests against this Gitea instance found actions/cache
(and setup-node's built-in cache: npm, same API) times out against
the built-in cache proxy - a server-side issue, not fixable from
workflow YAML - and actions/upload-artifact/download-artifact v4
refuse to run at all (GHES detection). v3 of the artifact actions
work correctly, so they're used as the handoff mechanism instead.

.gitea/workflows/checks.yml, test-node.yml, and test-browser.yml are
merged into one ci.yml. A new `install` job does the real work once
(submodule clone, npm ci, build) and hands node_modules plus Turbo's
local cache off via v3 artifacts to typecheck/typetest/node-tests/
browser-tests (all `needs: install`), instead of every job reinstalling
and rebuilding from scratch. lint/format never touched the submodule
or build output, so they drop that step and stay independent for fast
feedback. The shared checkout+submodule+setup-node preamble is now a
composite action, .gitea/actions/setup/action.yml (composite actions
require the repo to already be checked out, so actions/checkout stays
a separate first step in every job). A concurrency group cancels
superseded runs on the same ref.

The node_modules archive step must include per-package node_modules
overrides, not just the root: packages/xml and packages/vfs pin a
newer local TypeScript than the workspace root, installed by npm as
nested packages/{xml,vfs}/node_modules/typescript. Missing those in
the archive caused those two packages to silently typecheck against
the wrong TypeScript version.

Cross-run caching (reusing a previous run's install/build) isn't
available until the Gitea instance's cache backend is fixed
server-side - that's a separate, out-of-scope follow-up.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 22:40:24 +00:00
codingetandClaude 3ed8095263 chore: update AI_CHANGES.md for PR #56
Checks / lint (pull_request) Successful in 1m24s
Checks / format (pull_request) Successful in 1m30s
Checks / typetest (pull_request) Successful in 7m56s
Checks / build (pull_request) Successful in 8m33s
Checks / typecheck (pull_request) Successful in 8m37s
Node Tests / node-tests (pull_request) Successful in 7m44s
Browser Tests / browser-tests (pull_request) Successful in 8m51s
Checks / lint (push) Successful in 1m40s
Checks / format (push) Successful in 1m48s
Checks / typetest (push) Successful in 8m59s
Checks / build (push) Successful in 9m11s
Checks / typecheck (push) Successful in 9m22s
Node Tests / node-tests (push) Successful in 8m13s
Browser Tests / browser-tests (push) Successful in 9m35s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 02:24:39 +00:00
codingetandClaude b917cd88eb test(tsconnect-worker): fix flaky closed-state tests
Checks / lint (pull_request) Successful in 1m15s
Checks / format (pull_request) Successful in 1m21s
Checks / typecheck (pull_request) Successful in 7m21s
Checks / typetest (pull_request) Successful in 7m42s
Checks / build (pull_request) Successful in 8m0s
Node Tests / node-tests (pull_request) Successful in 7m13s
Browser Tests / browser-tests (pull_request) Successful in 8m16s
Replace racy `setTimeout(r, 10)` waits with a `setImmediate` poll on
the `.closed` property. The 10 ms sleep was insufficient under load,
causing `readFrom()`/`read()`/`write()`/`accept()` to run before the
"closed" message was delivered, resulting in "packet conn closed"
instead of the expected "already closed" error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 23:49:43 +00:00
codingetandClaude c04b0d6eea fix(utils): fix suggestedName typo and defer URL revocation in download()
Checks / format (pull_request) Successful in 3m6s
Checks / lint (pull_request) Successful in 3m14s
Checks / typecheck (pull_request) Successful in 11m10s
Checks / typetest (pull_request) Successful in 11m39s
Checks / build (pull_request) Successful in 11m43s
Node Tests / node-tests (pull_request) Successful in 9m46s
Browser Tests / browser-tests (pull_request) Successful in 11m10s
Checks / lint (push) Successful in 2m46s
Checks / format (push) Successful in 3m32s
Checks / typecheck (push) Successful in 11m31s
Checks / typetest (push) Successful in 12m29s
Checks / build (push) Successful in 12m41s
Node Tests / node-tests (push) Failing after 10m51s
Browser Tests / browser-tests (push) Successful in 12m36s
- Fix `suggegestedName` typo in showSaveFilePicker call (extra "ge");
  the browser silently ignored the unknown key so the Save dialog opened
  with a blank filename on Chrome/Edge
- Defer URL.revokeObjectURL to setTimeout() so Safari's download
  manager has a task boundary to open the object URL before revocation
- Add AI_CHANGES.md entry for the @webnet/react/@webnet/utils integration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 18:29:45 +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 5dc0478970 feat: add @webnet/react and @webnet/utils packages
Checks / lint (pull_request) Successful in 2m5s
Checks / format (pull_request) Successful in 2m4s
Checks / typecheck (pull_request) Successful in 9m10s
Checks / typetest (pull_request) Successful in 10m16s
Checks / build (pull_request) Successful in 11m12s
Node Tests / node-tests (pull_request) Successful in 10m57s
Browser Tests / browser-tests (pull_request) Successful in 12m28s
Checks / format (push) Successful in 3m15s
Checks / lint (push) Successful in 3m46s
Checks / typetest (push) Successful in 9m41s
Checks / typecheck (push) Successful in 11m54s
Checks / build (push) Successful in 11m59s
Node Tests / node-tests (push) Failing after 9m54s
Browser Tests / browser-tests (push) Successful in 14m28s
Extracts the useClient and useLocalStorage hooks into @webnet/react,
and the download, upload, readBlob, and fmtSize utilities into @webnet/utils,
so they can be shared by tailshare and other apps without living inside
a single app package.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 00:42:38 +00:00
codingetandClaude 9914bd07a8 docs(agents): PR labeling and auto-finalise guidance
Node Tests / node-tests (push) Has been cancelled
Browser Tests / browser-tests (push) Has been cancelled
Checks / lint (push) Has been cancelled
Checks / format (push) Has been cancelled
Checks / typecheck (push) Has been cancelled
Checks / typetest (push) Has been cancelled
Checks / build (push) Has been cancelled
Node Tests / node-tests (pull_request) Has been cancelled
Browser Tests / browser-tests (pull_request) Has been cancelled
Checks / lint (pull_request) Successful in 3m34s
Checks / format (pull_request) Successful in 3m1s
Checks / typetest (pull_request) Successful in 9m17s
Checks / typecheck (pull_request) Successful in 9m45s
Checks / build (pull_request) Successful in 9m42s
Add instructions for agents to apply `Agentic` + `Agent/<model-line>`
labels to every PR they open (creating the labels via `tea labels create`
if absent), and to auto-finalise PRs without user prompting when the
work is trivial or was fully specified upfront.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 02:25:32 +02:00
codingetandClaude d1e4352765 docs(ai): finalise AI_CHANGES.md for PR #51
Checks / format (pull_request) Successful in 3m32s
Checks / lint (pull_request) Successful in 3m33s
Checks / typetest (pull_request) Successful in 11m24s
Checks / build (pull_request) Successful in 11m54s
Checks / typecheck (pull_request) Successful in 12m1s
Node Tests / node-tests (pull_request) Successful in 9m19s
Browser Tests / browser-tests (pull_request) Successful in 6m48s
Checks / typecheck (push) Successful in 8m34s
Browser Tests / browser-tests (push) Has been cancelled
Checks / typetest (push) Has been cancelled
Checks / build (push) Has been cancelled
Checks / lint (push) Has been cancelled
Checks / format (push) Has been cancelled
Node Tests / node-tests (push) Successful in 8m10s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 23:36:11 +00:00
codingetandClaude 1ad12e7a77 fix(tsconnect-worker): address code review findings
Checks / lint (pull_request) Successful in 3m11s
Checks / format (pull_request) Successful in 3m23s
Checks / typecheck (pull_request) Successful in 10m21s
Checks / typetest (pull_request) Successful in 10m45s
Checks / build (pull_request) Successful in 10m55s
Node Tests / node-tests (pull_request) Successful in 8m14s
Browser Tests / browser-tests (pull_request) Successful in 4m57s
- IpnClientHandle.disconnect() JSDoc clarifies that the main-thread path
  terminates IPN while the worker path is a soft detach
- connectWithFallback logs a console.warn with the caught error when falling
  back from the SharedWorker path, so unexpected fallbacks are diagnosable
- IpnMainThreadHandle constructor comment explains that pre-run() callbacks
  are intentionally dropped (run() snapshots current state on subscribe)
- lock?.release ?? null -> lock ? () => lock.release() : null to avoid
  passing an unbound method reference
- Browser test: first test adds stateStorage: "memory" to avoid leaving IDB
  state between runs
- Browser test: new test covers the IDB lock-contention path — acquires the
  lock manually then confirms connectMainThread rejects immediately

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 07:50:01 +00:00
codingetandClaude 3165653471 docs(ai): update AI_CHANGES.md for WorkerConfig.wasmUrl type widening and test isolation fix
Checks / lint (pull_request) Successful in 3m51s
Checks / format (pull_request) Successful in 3m17s
Checks / typecheck (pull_request) Successful in 12m4s
Checks / typetest (pull_request) Successful in 11m46s
Browser Tests / browser-tests (pull_request) Failing after 9m54s
Checks / build (pull_request) Successful in 12m7s
Node Tests / node-tests (pull_request) Successful in 6m32s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 23:51:52 +00:00
codingetandClaude 8040418f09 fix(tsconnect-worker): widen WorkerConfig.wasmUrl type and fix test isolation
Checks / lint (pull_request) Successful in 4m15s
Checks / format (pull_request) Successful in 4m30s
Checks / typetest (pull_request) Successful in 11m11s
Checks / typecheck (pull_request) Successful in 11m47s
Node Tests / node-tests (pull_request) Successful in 10m6s
Checks / build (pull_request) Failing after 13m8s
Browser Tests / browser-tests (pull_request) Successful in 15m26s
- WorkerConfig.wasmUrl now accepts string | ArrayBuffer | ArrayBufferView,
  allowing tests (and callers) to pass raw WASM bytes without going through
  a URL fetch (useful in Node.js where file:// fetch is unsupported)
- Restructured connect.test.ts to share a single WASM+IPN instance across
  tests via before()/after() hooks, preventing uncaught Go goroutine errors
  that fired after sequential shutdown of multiple WASM runtimes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 23:50:49 +00:00
codingetandClaude 564dbfad3f feat(tsconnect-worker): main-thread fallback with IpnClientHandle and connectWithFallback
Checks / lint (pull_request) Successful in 3m3s
Checks / format (pull_request) Successful in 3m12s
Checks / typetest (pull_request) Failing after 10m1s
Checks / build (pull_request) Failing after 10m49s
Checks / typecheck (pull_request) Failing after 10m50s
Browser Tests / browser-tests (pull_request) Failing after 12m36s
Node Tests / node-tests (pull_request) Failing after 14m20s
- IpnClientHandle interface: shared contract for both SharedWorker client and
  main-thread handle (connectionMode, store, state, running, fileOps, run,
  disconnect)
- IpnMainThreadHandle: wraps IPN + Redux store; all IpnClient methods proxy
  directly; run() fires user callbacks with current state and delegates future
  state changes via runWithStore; disconnect() releases the lock and shuts down
- connectMainThread: IndexedDB-backed state uses a web lock keyed to the DB
  name ("tsconnect-idb:<name>"), rejecting immediately if held; in-memory
  state skips the lock entirely
- connectWithFallback: tries SharedWorker first, falls back to main thread if
  unavailable, disabled (disableSharedWorker option), or on worker init failure
- useBuildIpnWorker updated to use connectWithFallback, returns IpnClientHandle
- Tests: 6 Node tests verifying main-thread init and fallback behaviour; 4
  browser tests (Chromium + Firefox) verifying worker path and explicit
  disable fallback via esbuild-bundled inline build

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 23:40:45 +00:00
codingetandClaude 061a7ee50c feat(tsconnect-worker): add connectMainThread fallback for environments without SharedWorker
Checks / format (pull_request) Successful in 3m12s
Checks / lint (pull_request) Successful in 3m25s
Checks / typecheck (pull_request) Successful in 10m5s
Checks / typetest (pull_request) Successful in 10m49s
Checks / build (pull_request) Successful in 10m56s
Browser Tests / browser-tests (pull_request) Successful in 10m5s
Node Tests / node-tests (pull_request) Failing after 13m2s
Adds connectMainThread(config) for browsers that do not support
SharedWorker (e.g. Chrome on Android before 2025). It mirrors the
worker's init path but runs in the main thread, returning an IPN
instance directly instead of a worker-proxy client.

Uses navigator.locks.request with { ifAvailable: true } to protect
against concurrent tabs; rejects immediately if the lock is already
held. The lock is released when the returned IPN.shutdown() resolves.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 23:09:29 +00:00
codingetandClaude 03d12d25a9 test(tsconnect-worker): cover WorkerSSHSession.close() idempotency
Checks / lint (pull_request) Successful in 3m1s
Checks / format (pull_request) Successful in 3m16s
Checks / typetest (pull_request) Successful in 9m49s
Checks / build (pull_request) Successful in 10m41s
Checks / typecheck (pull_request) Successful in 11m31s
Node Tests / node-tests (pull_request) Successful in 9m49s
Browser Tests / browser-tests (pull_request) Successful in 10m50s
Checks / lint (push) Successful in 2m53s
Checks / format (push) Successful in 3m14s
Checks / build (push) Successful in 9m54s
Checks / typetest (push) Successful in 10m47s
Checks / typecheck (push) Successful in 11m22s
Node Tests / node-tests (push) Successful in 10m6s
Browser Tests / browser-tests (push) Successful in 11m40s
Verify that the second close() call returns false (the #closed guard path
added in the previous commit).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 19:54:52 +00:00
codingetandClaude b0c25375d4 fix(tsconnect-worker): close MessagePort in close() to prevent event loop hang
Checks / format (pull_request) Successful in 3m11s
Checks / lint (pull_request) Successful in 3m40s
Checks / typecheck (pull_request) Successful in 10m58s
Checks / typetest (pull_request) Successful in 12m16s
Checks / build (pull_request) Successful in 12m26s
Node Tests / node-tests (pull_request) Successful in 10m17s
Browser Tests / browser-tests (pull_request) Successful in 11m59s
WorkerConn/WorkerTCPListener/WorkerPacketConn/WorkerSSHSession.close() sent a
"close" message but never called port.close(). The port stayed active until the
worker sent a "closed" reply, which never happens in tests. Node.js's --test
runner uses process.on('exit') rather than process.exit(), so an undrained event
loop (open MessagePort handles) caused the test process to hang indefinitely.

Fix: close() now calls this.#port.close() and immediately rejects pending
promises. WorkerSSHSession gains a #closed guard to make close() idempotent.
Test cleanup updated to call close() methods rather than leaking ports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 19:35:24 +00:00
codingetandClaude a49588d3b1 docs(ai): log test coverage gap-fill for xml, tsconnect-redux, vfs, tsconnect-worker
Checks / lint (pull_request) Successful in 2m55s
Checks / format (pull_request) Successful in 3m34s
Checks / typecheck (pull_request) Successful in 11m46s
Checks / typetest (pull_request) Successful in 12m38s
Checks / build (pull_request) Successful in 12m41s
Browser Tests / browser-tests (pull_request) Successful in 12m34s
Node Tests / node-tests (pull_request) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 18:50:40 +00:00
codingetandClaude 23a2dca900 test: fill coverage gaps across xml, tsconnect-redux, vfs, tsconnect-worker
- xml: add xml.test.ts (el/text/stringify — 17 tests), add test scripts to package.json
- tsconnect-redux: add selectors.test.ts covering all ~25 exported selectors (60 tests)
- vfs: add memory/memory.test.ts with direct MemoryVFS unit tests (44 tests)
- tsconnect-worker: add worker.test.ts (38 tests — WorkerConn, WorkerTCPListener,
  WorkerPacketConn, WorkerSSHSession, pumpStreamToPort, portToReadableStream); add
  test scripts, @types/node devDep, and "types":["node"] to tsconfig

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 18:50:16 +00:00
codingetandClaude b69bac3c24 docs(agents): add CI watch, auto-review, and push-notification guidance
Checks / lint (pull_request) Successful in 2m36s
Checks / format (pull_request) Successful in 3m3s
Checks / typecheck (pull_request) Successful in 10m20s
Checks / typetest (pull_request) Successful in 10m23s
Checks / build (pull_request) Successful in 11m14s
Node Tests / node-tests (pull_request) Successful in 8m49s
Browser Tests / browser-tests (pull_request) Successful in 12m18s
Checks / lint (push) Successful in 2m50s
Checks / format (push) Successful in 3m33s
Checks / build (push) Successful in 10m34s
Checks / typecheck (push) Successful in 10m45s
Checks / typetest (push) Successful in 10m44s
Node Tests / node-tests (push) Successful in 8m31s
Browser Tests / browser-tests (push) Failing after 14m46s
- Always base PRs on origin/main (fetch before branching)
- Watch CI results after push and address errors
- Spawn autonomous Sonnet-class code review when PR work is complete
- Send push notification to user when work settles or needs unblocking

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 10:24:00 +00:00
codingetandClaude ecb5b7e3c4 docs(ai): update AI_CHANGES.md for FileOpsLimits refactor
Checks / format (pull_request) Successful in 2m53s
Checks / lint (pull_request) Successful in 3m6s
Checks / build (pull_request) Successful in 11m19s
Checks / typetest (pull_request) Successful in 12m0s
Checks / typecheck (pull_request) Successful in 12m19s
Node Tests / node-tests (pull_request) Successful in 10m49s
Browser Tests / browser-tests (pull_request) Successful in 11m53s
Checks / format (push) Successful in 2m55s
Checks / lint (push) Successful in 3m11s
Checks / typetest (push) Successful in 11m7s
Checks / typecheck (push) Successful in 12m27s
Checks / build (push) Successful in 12m36s
Node Tests / node-tests (push) Successful in 10m58s
Browser Tests / browser-tests (push) Successful in 14m58s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:42:38 +00:00
codingetandClaude 76579017ee refactor(tsconnect-worker): extract FileOpsLimits type to prevent drift
The setFileOpsConfig handler in worker.ts and the setFileOpsConfig method
in client.ts previously used duplicate inline type literals.  Extracting
FileOpsLimits from protocol.ts ties both to a single source of truth so
the compiler catches any future skew.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:42:38 +00:00
codingetandClaude 01a1fed6ec feat(tsconnect-worker): wire FileOps limits through WorkerConfig to init
Add fileOpsMaxFiles, fileOpsMaxTotalSize, and fileOpsMaxFileSize to
WorkerConfig so callers can set initial Taildrop limits at startup rather
than having to call setFileOpsConfig() after connecting.  The options are
passed straight through to FsaFileOps.createFromOpfs().  Runtime changes
via setFileOpsConfig() continue to work as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:42:38 +00:00
codingetandClaude 488ec9bb2d docs(ai): log turbo typecheck fix alongside CI workflow addition
Checks / lint (pull_request) Successful in 2m48s
Checks / format (pull_request) Successful in 3m19s
Checks / typetest (pull_request) Successful in 10m59s
Checks / typecheck (pull_request) Successful in 11m52s
Checks / build (pull_request) Successful in 11m7s
Node Tests / node-tests (pull_request) Successful in 10m8s
Browser Tests / browser-tests (pull_request) Successful in 11m43s
Checks / lint (push) Successful in 3m5s
Checks / format (push) Successful in 3m15s
Browser Tests / browser-tests (push) Failing after 4m5s
Checks / typetest (push) Successful in 9m25s
Checks / typecheck (push) Successful in 10m54s
Checks / build (push) Successful in 11m5s
Node Tests / node-tests (push) Successful in 8m31s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 00:16:51 +00:00
codingetandClaude a1942ff38e fix(turbo): make @webnet/tsconnect#typecheck depend on its own build
Checks / lint (pull_request) Successful in 3m5s
Checks / format (pull_request) Successful in 3m6s
Checks / typetest (pull_request) Successful in 9m28s
Checks / typecheck (pull_request) Successful in 9m44s
Checks / build (pull_request) Successful in 9m58s
Browser Tests / browser-tests (pull_request) Successful in 9m11s
Node Tests / node-tests (pull_request) Failing after 14m50s
src/index.ts imports ../dist/wasm_exec.js which only exists after build.sh
runs; the generic typecheck task only declares ^build (dependencies' build)
as a prerequisite, leaving the package's own dist absent in a fresh env.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 00:05:27 +00:00
codingetandClaude 02b80eecbd docs(ai): log CI checks workflow addition
Checks / format (pull_request) Successful in 3m49s
Checks / lint (pull_request) Successful in 3m49s
Checks / typecheck (pull_request) Failing after 3m54s
Checks / typetest (pull_request) Successful in 7m18s
Checks / build (pull_request) Successful in 6m49s
Browser Tests / browser-tests (pull_request) Successful in 8m10s
Node Tests / node-tests (pull_request) Failing after 11m53s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 23:52:09 +00:00
codingetandClaude 13c25e6f4d ci: add lint, format, typecheck, typetest, and build workflows
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 23:51:51 +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 a0cc6fc4da docs(ai): log ControlledFileOps binding
Node Tests / node-tests (pull_request) Successful in 6m28s
Browser Tests / browser-tests (pull_request) Successful in 8m21s
Node Tests / node-tests (push) Successful in 5m29s
Browser Tests / browser-tests (push) Successful in 7m40s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 23:24:50 +00:00
codingetandClaude 630f21c898 feat(fileops): bind ControlledFileOps state to ipn store
Add a ControlledFileOps interface (UserIPNFileOps + observable limits +
onChange) satisfied by InMemoryFileOps and FsaFileOps. Bind its state
into a new fileOps Redux slice so file storage metrics and limits are
observable via store.getState().fileOps and broadcast to all clients.

In tsconnect-worker: hoist the FsaFileOps instance to module scope,
wire bindFileOpsToStore after init, and handle a new setFileOpsConfig
call that lets clients reconfigure maxFiles/maxTotalSize/maxFileSize
at runtime. Limit changes propagate back via the existing action
broadcast path so all connected clients see updated state immediately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 23:24:50 +00:00
codingetandClaude 22232c921b fix(browser-test-utils): polyfill __name for tsx-compiled page.evaluate callbacks
Node Tests / node-tests (pull_request) Successful in 4m45s
Browser Tests / browser-tests (pull_request) Successful in 4m22s
Node Tests / node-tests (push) Successful in 3m52s
Browser Tests / browser-tests (push) Successful in 5m39s
tsx hardcodes keepNames:true in its esbuild transform, injecting a __name
helper at module scope. Playwright's page.evaluate() serializes callbacks
via .toString(), so the helper is absent in the browser context. Inject a
matching polyfill via addInitScript on every new page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 22:13:38 +00:00
codinget a1081a8194 test: setup node tests in CI 2026-06-23 22:13:38 +00:00
codingetandClaude b7df7c35e3 chore(test): update AI_CHANGES.md to reflect coverage script removal
Browser Tests / browser (push) Failing after 1m5s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 12:49:27 +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
codinget bba2c5c6f5 feat(tsconnect): add limits and change handlers to InMemoryFileOps (#43)
Reviewed-on: #43
Co-authored-by: Codinget <codinget@codi.moe>
Co-committed-by: Codinget <codinget@codi.moe>
2026-06-21 13:16:59 +02:00
codingetandClaude 39b6cdb8ec chore(tsconnect): update AI_CHANGES for FsaFileOps review fixes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 23:15:10 +00:00
codingetandClaude a15be0f378 fix(tsconnect): address FsaFileOps review feedback
- Move #fileSizes.set in openWriter to after all async FSA ops, so a
  failed getFileHandle/createWritable/seek doesn't leave a phantom entry
  inflating fileCount and totalSize
- Fix rename to stat the file when it wasn't previously tracked, so
  untracked files don't become permanently invisible after a rename
- Document stat/totalSize inconsistency during active writes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 23:04:04 +00:00
codingetandClaude 1a3bd53348 feat(tsconnect): add limits and change handlers to FsaFileOps
Adds maxFiles/maxTotalSize/maxFileSize limit getters/setters,
fileCount/totalSize/openFiles getters, and onChange/offChange
notification to FsaFileOps, mirroring InMemoryFileOps. File sizes
are tracked in memory via a #fileSizes map; createFromOpfs now scans
the directory at startup so pre-existing files count toward limits.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-20 22:41:42 +00:00
codinget be031f0655 fix(tsconnect-redux): export all selectors 2026-06-20 17:11:29 +00:00
codinget 050de5c2f3 fix(tsconnect-react): add overloads to useBuildIpnWorker to make it clear options are incompatible with factory 2026-06-20 16:23:56 +00:00
codinget 52069887f3 chore(tsconnect-react): remove console.log 2026-06-20 16:21:16 +00:00
codinget 44d6a073bf fix(tsconnect-react): add webpack support for worker via factory 2026-06-20 16:08:37 +00:00
codingetandClaude 5ba7de1998 docs(ai-changes): log @webnet/vfs extraction
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 16:21:00 +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
codingetandClaude 1e683507e7 docs(agents): PR review instructions, AI_CHANGES.md consolidation
- Add "Reviewing pull requests" section to AGENTS.md: use `tea` (not
  `gh`), validate assumptions with the user in interactive mode, and
  post feedback directly on the PR in autonomous mode.
- Consolidate the AI disclosure out of README.md into a standalone
  AI_CHANGES.md; README.md now links to it.
- Add .gitattributes with merge=union on AI_CHANGES.md so parallel
  branches each appending entries never produce conflicts.
- Update the "AI disclosure" section in AGENTS.md to point agents at
  AI_CHANGES.md instead of README.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 12:06:41 +00:00
codingetandClaude f11eaaa670 style: fix prettier formatting in hooks and Debug component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 11:38:44 +00:00
codingetandClaude b12c2fe0b1 fix(tsconnect-worker): address round-3 review feedback
Bugs:
- Liveness detection now fires for all clients, including those that connect
  while init is pending. Previously, the "hello" message was consumed by the
  onFirst handler before registerClient set up its port.onmessage listener,
  so navigator.locks.request was never called for the first tab and any tab
  that connected during init. Fix: unified onHello handler in onconnect
  extracts lockName from every "hello"; registerClient always takes lockName
  and acquires the lock immediately.
- Remove dead bodyCallbacks field from bridgeDriveHandler pending map. The
  map was allocated on every request but never read or populated; body chunk
  reads go directly through entry.req.readBodyChunk().
- Drive cleanup in cleanupClient now only installs the no-op handler when no
  other client still has driveRegistered = true, preventing the surviving
  client's handler from being silently replaced.

Code quality:
- wrapDispatch: replace (s as any).dispatch with a two-step cast through
  unknown — avoids the any escape hatch while satisfying RTK's overloaded
  ThunkDispatch type.
- IndexedDBState.setState: add tx.onerror handler so failed IDB writes are
  logged rather than silently dropped.
- pumpStreamToPort fire-and-forget in openWaitingFile fallback: add
  .catch(() => {}) to make the intentional discard explicit.
- tsconfig.json: add skipLibCheck: true to match tsconfig.worker.json (both
  transitively import @webnet/tsconnect which has an unresolved wasm_exec.js
  declaration issue).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 11:35:52 +00:00