fix(remote): harden transport (redirects, artifact paths, upload hash, socket cap, proxy RPC errors)

Merged
TH
4h ago
+1117-168

Summary

Transport fixes from the 2026-11-10 audit.

  • Credentials (CONTR-1): no upload request that carries daemon credentials follows a hop to another origin. The streamer follows redirects only on the daemon origin. Preflight and finalize use redirect: 'error', since the daemon never redirects them. A refused leg falls back to legacy /upload.
  • Artifact paths (CONTR-4, partial): the client chooses local paths. A response localPath counts only on record/trace stop and perf stop or report. Otherwise the file lands in cwd under the basename.
  • Request limit (DSRV-3): DAEMON_REQUEST_MAX_BYTES (64 MiB, contracts/daemon-http) bounds the socket framer, HTTP /rpc and the proxy default, all in UTF-8 bytes. The socket answers framed requests before it refuses an oversized one. Clients refuse larger requests before sending (daemon_request_too_large). A max-size replay bundle fits even with worst-case escaping. The proxy README says when to lower the limit.
  • DSRV-6: legacy /upload verifies x-artifact-hash.
  • Proxy: /rpc failures use JSON-RPC envelopes (CONTR-3). upstreamTimeoutMs has no default; /health has its own 5 s bound (CONTR-2).
  • Wire-ledger entries record each compatible change.

Moved to their own branch: DSRV-4 and CONTR2-4. Deferred: DSRV-5. Dropped: CMD-5 (the install-timeout ledger pins its 120 s bound).

Validation

  • Tested SHA efd63d1 (exactCommit=true): format, lint, typecheck, layering, fallow, build, related tests and all unit-lane Vitest tests pass.
  • The unit lane's node smoke step fails 2 smoke-daemon-clean tests locally. They fail the same way on origin/main 5a836c0: the local container does not reap zombie processes. CI owns this lane.
  • Each new test fails on the pre-fix code.
  • Risk: a proxy deployment that relied on the implicit 5-minute cap must set upstreamTimeoutMs.

Generated by Claude Code