# npm proxy configuration loopback experiment

This fixture sends actual npm registry requests to a synthetic HTTP registry through two forwarding proxies. It records the route and validates installed package content. It uses only Node standard libraries and the npm executable already in PATH. It never forwards proxy requests to a destination outside its own loopback registry.

Run from the directory containing the downloads:

```sh
node --version
npm --version
node npm-proxy-lab.mjs ./results-rerun.json
node npm-config-edit-check.mjs ./config-edit-results-rerun.json
```

The recorded run used Node v26.10.0, npm 11.19.1, macOS 15.7.4 (Darwin 24.6.0), arm64, on 2026-10-12. The registry run began at 19:12:47 UTC and finished at 19:12:54 UTC. Dynamic ports and temporary paths will change on rerun. Results from another npm version should be reported as a separate observation.

Each network case runs `npm ping --json`, `npm view ipvolt-proxy-fixture@1.0.0 version dist.tarball --json`, and `npm install ipvolt-proxy-fixture@1.0.0 --ignore-scripts --no-audit --no-fund --no-package-lock --save=false --json`. The JSON preserves the exact argument arrays, working directories, isolated npmrc contents, selected environment variables, npm stdout/stderr, exit codes, timestamps and registry/proxy request logs. Every command receives its own fresh cache. No original user or global npm configuration file is modified; HOME is inherited unchanged while explicit `--userconfig`, `--globalconfig` and `--cache` paths isolate the experiment.

The fixture builds a valid package tarball itself, publishes its metadata, sha512 integrity and sha1 shasum on the synthetic registry, and serves the archive over loopback. A successful installation requires the exact name/version and contents of `proof.txt` and `index.js` to match. HTTP 200 alone cannot pass acceptance. Install scripts are disabled; the fixture package contains none.

| Case | Synthetic input conflict | Observed route | Expected installation outcome |
| --- | --- | --- | --- |
| 01 | No proxy setting or inherited proxy environment | Direct | Verified package payload |
| 02 | User npmrc sets both proxy keys to A | A | Verified package payload |
| 03 | Project B conflicts with user A for both keys | B | Verified package payload |
| 04 | `npm_config_proxy` and `npm_config_https_proxy` A conflict with project/user B | A | Verified package payload |
| 05 | CLI sets both keys B over config environment A | B | Verified package payload |
| 06 | Only raw `HTTP_PROXY=A`; both npm config proxy values are null | A | Verified package payload |
| 07 | Both user proxy keys A plus raw `NO_PROXY=127.0.0.1`; npm config noproxy is empty | Direct | Verified package payload |
| 08 | B permits ping and metadata but refuses tarball requests | B | Expected E502 failure; package absent |
| 09 | User `https-proxy=A`, project `proxy=B`, CLI `--proxy=B` | A | Verified package payload |

All nine cases pass their stated acceptance conditions. Eight installations validate the payload; one is an intentional tarball failure. Case 08 demonstrates why registry ping, even followed by successful metadata, is insufficient to prove package download. Case 09 is a conflict between different keys: the CLI wins the `proxy` key, while the separately configured `https-proxy` remains A and npm-registry-fetch selects it for this observed HTTP request. Cases 06 and 07 demonstrate raw proxy/bypass environment behavior absent from the displayed npm config values.

The separate configuration-edit experiment verifies the exact multi-key `npm config set` command with `--location=user`, then deletion with `--location=user` and `--location=project`. All four acceptance checks pass: setting user keys preserves the project keys; the project still wins; deleting user keys preserves the project; deleting project keys finally produces null for both effective proxy values. This bounds cleanup advice to the selected file.

This is synthetic plain HTTP evidence. It does not test HTTPS CONNECT, TLS, corporate certificate trust, proxy credentials, private registries, Git dependencies, npm lifecycle downloader behavior, npm ci/lockfile host behavior, internet speed or any commercial proxy service. The bypass test covers an exact IPv4 hostname, not wildcard, CIDR or port semantics. Each final case is one sequential observation, not a reliability benchmark.
