refactor(limrun): write the network HAR on artifacts and close instead of live

Merged
TH
2d ago
+328-1002

Summary

Follow-up to #4043. It keeps the same flags and replaces the live HAR file with a simpler design. --provider-network-logs keeps completed requests in memory. artifacts and close write them to <state-dir>/network-har/<lease-id>.har (mode 0600) and print the path.

  • Bounds: bodies are cut to 64 KiB (inspection.maxBodyBytes and the SDK assembler). The capture keeps the latest 500 requests and counts each dropped request as har-truncated.
  • Failure signal: metadata.failures = { count, last: { kind, host, port }, lastDialFailure }. kind is typed. lastDialFailure is Limrun's typed reason, such as dns_not_found. No error text is matched.
  • Removed: the per-request rewrite loop, the 8 MiB UTF-8 ring, the async write queue, the temp-file renames, the 32-capture retention with deletion, the relative-path and chmod checks, the per-kind failure lists, providerSessionId, and their tests (network-har.test.ts and four runtime tests). Two runtime tests remain: a capture writes a private HAR with its failures on artifacts and at release, and a capture that can't start is an unavailable artifact.
  • Docs: limrun.md says traffic exits through the machine that runs agent-device, the HAR holds secrets, and pinned, DNS-over-HTTPS and HTTP/1.1-only TLS hosts can't be captured. It also tells users to pass --provider-network-hosts.

Why not Limrun's persisted HAR: inspection.persist uploads a networkLog session artifact (listSessionArtifacts(id, 'networkLog') → downloadUrl) only after the tunnel stops. artifacts must work mid-session, so the in-memory entries are needed anyway, and they cover close too.

Diff vs main: 9 files, +291/āˆ’1009. #4043 by itself was +1377/āˆ’31; the two together are +647/āˆ’30.

Validation

  • pnpm check:affected --run at fae6cb3353 and 4c7714c7df (head): format, lint, typecheck, layering, fallow and build pass. vitest-related fails only on two Apple timing tests under host load average ~240. ios-record-trace also fails on clean main f1a17d92b1. apple-platform-output-guard passes alone on this branch (2 of 2 runs). docs-links and docs-prose pass via pnpm gate. At d252150543, which has the same feature files, all 25 remaining static gates passed via pnpm gate.
  • Review fixes in 4c7714c7df: chmod an existing HAR to 0600, keep at most 32 released capture records, and correct the host-limit help. check:affected there fails only on ios-record-trace, which also fails on main. docs-links and docs-prose pass.
  • Live Limrun iOS at d252150543 (same feature files): connect limrun --platform ios --provider-network-logs --provider-network-hosts httpbin.org,agent-device-missing-q7z.com, open https://httpbin.org/get, then open https://agent-device-missing-q7z.com/.
    $ agent-device artifacts            # mid-session
    network: Network traffic (HAR on the daemon host) ready /tmp/ad-har-live/state/network-har/<lease>.har
    Network capture failures: 2; last request-failed agent-device-missing-q7z.com:443; last dial failure dns_not_found
    $ jq -r '.log.entries[] | "\(.response.status) \(.request.method) \(.request.url)"' <har>
    200 GET https://httpbin.org/get
    404 GET https://httpbin.org/favicon.ico
    0 GET https://agent-device-missing-q7z.com/
    0 GET https://agent-device-missing-q7z.com/favicon.ico
    $ agent-device close                # prints the same path and summary
    $ agent-device artifacts            # after close: same file, same summary
    
    The file is -rw------- and the directory is drwx------. After disconnect and daemon stop, the Limrun API listed no non-terminated iOS or Android instances.

šŸ¤– Generated with Claude Code