installer: transport auto/compat, HTTPS-proxy sandboxes, root without systemd - #49
Merged
Merged
Conversation
… systemd
Ports the installer half of pilot-protocol/pilotprotocol#feat/native-https-proxy
onto the canonical script. The managed-node code (--managed-url, --no-start,
PILOT_ENROLLMENT_TOKEN) is unchanged; in managed mode the new "start the
daemon manually" hints stay silent because the managed flow starts it.
- --transport <auto|udp|compat> (or PILOT_TRANSPORT). udp and compat are
saved in config.json; auto (the default) never is, and --transport auto
removes a saved transport. A saved transport=auto is rewritten to udp for
a pilot-daemon that predates it (reinstalling an older --version).
- Root is allowed in a Linux container/VM without systemd (hosted agent
sandboxes such as Meta Muse run the agent as root); hosts with systemd or
launchd still refuse root unless PILOT_ALLOW_ROOT=1.
- proxy_cmd: in such a sandbox, when HTTPS_PROXY carries credentials and the
daemon supports -proxy-cmd, save bash -c 'printf %s "${https_proxy:-$HTTPS_PROXY}"'
(or $PILOT_PROXY_CMD) so the daemon re-reads rotating proxy credentials.
An existing proxy_cmd is never replaced.
- Compat installs leave the raw-TCP default registry/beacon off the service
units; switching back from compat restores the raw registry an older
compat install saved. Service units carry PILOT_TRANSPORT_DEFAULT=auto for
daemons that support it.
- Download failures name the proxy (redacted) and the hosts it must allow;
proxy credentials never reach the output.
tests/proxy-transport-install.sh covers the above with a fixture release
(no network, never sudo); tests/managed-install.sh still passes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TeoSlayer
pushed a commit
to pilot-protocol/pilotprotocol
that referenced
this pull request
Sep 24, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Sep 24, 2026
…, clean onboarding Proxy / sandbox (Meta Muse: root, no systemd, rotating HTTPS_PROXY credentials): - Fresh config.json leaves out the stock raw-TCP registry and UDP beacon (34.71.57.205) when the node runs compat, or auto behind a proxy; the daemon applies the endpoint that fits its transport. A compat install with a pilotctl that predates --transport gets registry.pilotprotocol.network:443 by name (it forwards config.json's registry verbatim). Service units omit the stock endpoints in the same cases. Custom PILOT_REGISTRY/PILOT_BEACON are always kept. - Downloads survive a credential rotation mid-install: pcurl retries once after re-reading the proxy URL from $PILOT_PROXY_CMD or, in a sandbox, a fresh bash (only this process's environment changes; nothing is printed or written). - The sandbox proxy_cmd is the credential-preferring command pilotctl uses (pilotprotocol#470): whichever of $https_proxy/$HTTPS_PROXY carries credentials. It is saved also for a daemon that predates -proxy-cmd (it ignores the key until upgraded), with a note. - PILOT_PROXY (http/https URL) carries the downloads when no *_PROXY is set. - A proxy the installed daemon cannot use (v1.13.x) now gets a warning in every transport, pointing at the pilot-sandbox recipe instead of a release that does not exist yet; the no-systemd start hint refers to it. - The service-unit proxy note no longer suggests writing a credentialed URL without saying so, and offers proxy_cmd. - The `daemon start --help` probe runs only for compat with a daemon that has -transport (v1.11+; per-command help exists since v1.10), so it can never start a daemon. Onboarding text: - Replies are read from `send-message --wait` output (JSON: .data.reply), not "the newest inbox message", which may answer an older question. - `appstore install` examples drop the routine --force (it reinstalls over the app and can delete its saved state). - A blank "Email:" line now says what the daemon uses; the manual pointer names `pilotctl skills` instead of one harness path. Tests: tests/proxy-transport-install.sh adds the rotation retry (BASH_ENV stands in for the sandbox), no raw-IP endpoint for compat/auto behind a proxy, old-pilotctl compat, PILOT_PROXY downloads, root refused on macOS, --help range, and no credentials in output or ~/.pilot. Mutation-checked. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The first skills pass runs after the downloads; in a sandbox whose proxy credentials rotated in between, pilotctl inherited stale ones (seen as a 407 on raw.githubusercontent.com in the rotating-proxy rig). Refresh from PROXY_REFRESH_CMD first; a no-op everywhere else. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TeoSlayer
pushed a commit
to pilot-protocol/pilotprotocol
that referenced
this pull request
Sep 24, 2026
Byte-identical copy of the canonical installer on pilot-protocol/release feat/installer-proxy-transport, so canonical-drift passes once release#49 merges. Takes this branch's credential-preferring sandbox proxy_cmd, and adds: no raw-IP registry/beacon in config.json for compat or auto behind a proxy, downloads retried once after a proxy credential rotation, proxy_cmd saved for older daemons too, PILOT_PROXY downloads, the v1.13.x proxy warning pointing at the pilot-sandbox recipe, and onboarding text that reads replies from send-message --wait and drops routine appstore --force. Only install.sh changes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…passes the proxy, honest transport, pinned tags install - Root reached through sudo/doas/pkexec for a regular user (SUDO_UID/SUDO_USER, DOAS_USER, PKEXEC_UID) is refused again on every host, with the reason and the command to run instead. `curl | sudo sh` on WSL/OpenRC/dev containers installed into /root/.pilot (0700) and left the user with "command not found"; `sudo -E` left a root-owned ~/.pilot. A root agent (Meta Muse) is unaffected; PILOT_ALLOW_ROOT=1 still overrides. - With a daemon that cannot use the proxy (v1.13.9) on a host whose proxy is the way out (credential-bearing proxy without systemd, or PILOT_PROXY_CMD), no output tells the agent to run `pilotctl daemon start` (warning, no-systemd hint, GET STARTED step 0, re-run summary): each points at the pilot-sandbox recipe instead. Elsewhere the command stays, with the condition next to it. - auto is no longer announced before the download. The summary (install and update) states the transport the installed daemon runs; a release without auto says udp and, where nothing chose udp, how to get compat on a UDP-blocked host. compat saved for a daemon without -transport is reported as udp. - --version / --channel beta: the manifest hash is compared only for the tag the manifest describes (its platform url names it, or latest_stable), so a pinned or beta tag installs against checksums.txt instead of aborting with "integrity anchors disagree". The tag it describes still needs both. - --help prints the usage header up to "WHAT THIS SCRIPT DOES" instead of a fixed line range. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TeoSlayer
pushed a commit
to pilot-protocol/website
that referenced
this pull request
Sep 24, 2026
…eview fixes) Byte-identical to release@67e83fc: root refused under sudo, no `pilotctl daemon start` advice on proxy-only hosts with a daemon that cannot use the proxy, the transport stated after the download, and --version / --channel beta installable again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TeoSlayer
pushed a commit
to pilot-protocol/pilotprotocol
that referenced
this pull request
Sep 24, 2026
Byte-identical to release@67e83fc (review fixes: root refused under sudo, no `pilotctl daemon start` advice on proxy-only hosts with a daemon that cannot use the proxy, the transport stated after the download, --version / --channel beta installable again). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ound 2)
- Save the sandbox proxy_cmd only when the proxy environment itself carries
the credentials (read before PILOT_PROXY is copied into it for the
downloads) and no explicit PILOT_PROXY is set. Credentials that arrive in
PILOT_PROXY never reach a fresh shell, so the command printed nothing and
the summary still claimed "rotation needs no restart"; next to an explicit
PILOT_PROXY the command would have replaced it (pilotctl leaves it alone
the same way).
- Restart advice on a proxy-only host ("No managed service was running")
now says to stop the running daemon first (`pilotctl daemon stop`) before
the pilot-sandbox recipe starts one: the recipe never stops a daemon, and
following the old advice ran two daemons with one identity.
- macOS: the LaunchAgent start line goes through start_hint like every other
start line (condition on PROXY_UNSUPPORTED, "Do not run" on PROXY_ONLY),
and nothing points macOS at the Linux-root-only recipe: PROXY_REMEDY there
is a re-run once a release whose pilot-daemon -h lists -proxy is out.
- `--transport auto` with a daemon that predates auto no longer claims
"keeps its default (udp)" while a saved compat stays in effect: it says
the saved transport is kept and how to switch.
tests/proxy-transport-install.sh covers each case (new darwin fixture with a
fake launchctl); passes on macOS and in a Linux container as root, as a
regular user and with /run/systemd/system present. shellcheck clean.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TeoSlayer
pushed a commit
to pilot-protocol/pilotprotocol
that referenced
this pull request
Sep 24, 2026
…all.sh sync with release#49 (c36ad9b) - pilotctl daemon start: when the daemon re-reads its credentials with a proxy command and the proxy still rejects them, the hint names the command in use and says to check what it prints from a fresh shell, instead of telling the operator to set one (E2E scenario 3: the 407 hint said "give the daemon a command that prints the current proxy URL" with config.json proxy_cmd in place). The daemon's own CredentialHint is worded for both. - TestInstallerSavesTheSandboxProxyCmd: install.sh's SANDBOX_PROXY_CMD must evaluate to pilotctl's sandboxProxyCmd. A saved proxy_cmd turns off the one `daemon start` hands the daemon, so the two must never drift (web4-470 review: the installer kept the pre-change command). - gosec: #nosec G204 with the reason on proxyconf.CommandSource (the operator's proxy command run with sh -c is the function's purpose), and the new G104 warnings (unchecked Close/Remove) in relay.go and pilotctl. - install.sh: byte-identical to pilot-protocol/release#49 c36ad9b (sandbox proxy_cmd only for credentials a fresh shell sees and never over an explicit PILOT_PROXY; restart advice stops the running daemon before the sandbox recipe; macOS LaunchAgent line conditioned and never sent to the Linux-only recipe; truthful --transport auto note for pre-auto daemons). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TeoSlayer
pushed a commit
to pilot-protocol/website
that referenced
this pull request
Sep 24, 2026
…36ad9b) Byte-identical to release@c36ad9b (sha256 4384f0cb...): sandbox proxy_cmd only for credentials a fresh shell sees and never over an explicit PILOT_PROXY; restart advice stops the running daemon before the sandbox recipe; macOS LaunchAgent start line conditioned and never sent to the Linux-only recipe; truthful --transport auto note for pre-auto daemons. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Sep 24, 2026
Merged
TeoSlayer
added a commit
to pilot-protocol/website
that referenced
this pull request
Sep 24, 2026
) * install.sh: sync the Pages fallback with pilot-protocol/release#49 public/install.sh must stay byte-identical to pilot-protocol/release:install.sh (sync-install-sh.yml fails its last step when it drifts). This is the installer from release#49 (ae447bc): root allowed in a Linux container/VM without systemd (Meta Muse), --transport auto|udp|compat, proxy_cmd for rotating proxy credentials (never the credentials), no raw-IP registry for compat or auto behind a proxy, downloads retried once after a credential rotation, and onboarding text that reads replies from send-message --wait. Merge right AFTER release#49: merging it first leaves the fallback ahead of the canonical script until #49 lands. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * install.sh: sync the Pages fallback with pilot-protocol/release#49 (review fixes) Byte-identical to release@67e83fc: root refused under sudo, no `pilotctl daemon start` advice on proxy-only hosts with a daemon that cannot use the proxy, the transport stated after the download, and --version / --channel beta installable again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * install.sh: sync the Pages fallback with pilot-protocol/release#49 (c36ad9b) Byte-identical to release@c36ad9b (sha256 4384f0cb...): sandbox proxy_cmd only for credentials a fresh shell sees and never over an explicit PILOT_PROXY; restart advice stops the running daemon before the sandbox recipe; macOS LaunchAgent start line conditioned and never sent to the Linux-only recipe; truthful --transport auto note for pre-auto daemons. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Teodor Calin <teodor@vulturelabs.io> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TeoSlayer
added a commit
to pilot-protocol/pilotprotocol
that referenced
this pull request
Sep 24, 2026
…xy-only sandboxes) (#470) * feat(pilotctl): daemon start --transport/--proxy and proxy env passthrough `pilotctl daemon start` could not bring a node online from sandboxes whose only way out is an authenticating HTTPS proxy (Meta Muse): - config.json from `pilotctl init` holds the raw-TCP registry default 34.71.57.205:9000 and daemon start forwarded it as an explicit -registry, which stops pilot-daemon from switching to registry.pilotprotocol.network:443 (TLS) in compat mode. In compat mode the compiled-in registry/beacon defaults are now left off argv (a default-equal $PILOT_REGISTRY is dropped from the child env too). - PILOT_TRANSPORT never took effect: the daemon's -transport flag defaults to "udp", masking the env var. pilotctl now resolves --transport, then $PILOT_TRANSPORT, then config "transport" and passes an explicit -transport. New: --transport <udp|compat> and --proxy <auto|off|URL> (plus config keys "transport"/"proxy", validated by `config --set`). Both reach the daemon only when set; a pilot-daemon whose -help lacks them gets them dropped with a warning instead of a flag-parse crash. A proxy URL with credentials travels as $PILOT_PROXY (never argv, PILOT-290) and is redacted in config output. The child env explicitly keeps HTTPS_PROXY/HTTP_PROXY/ALL_PROXY/NO_PROXY (both cases), PILOT_PROXY, PILOT_TRANSPORT, SSL_CERT_FILE, SSL_CERT_DIR on both the fork and --foreground paths. --compat-beacon, --registry-trust, --registry-fingerprint, --tls-trust and the documented-but-dropped --endpoint/--motd-* are forwarded when given. Also: create ~/.pilot before the O_EXCL PID claim (a fresh HOME failed with "PID file locked" forever), and registry dial failures behind a proxy now say pilotctl's direct registry dials do not use the proxy yet (TODO(netproxy)). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(install): --transport compat for UDP-blocked / proxy-only hosts install.sh --transport compat (or PILOT_TRANSPORT=compat) merges "transport": "compat" and "proxy": "auto" into ~/.pilot/config.json via `pilotctl config --set` (atomic, 0600, other keys kept) and generates compat systemd/launchd units (-transport compat, raw-TCP registry/beacon defaults left to the daemon). A re-run without the flag keeps a compat config. Audited for a no-root, no-systemd VM whose only egress is an authenticating CONNECT-:443 proxy with poisoned local DNS for *.pilotprotocol.network: every network call is curl over HTTPS (proxy env honored, CONNECT by hostname, no wget / raw IP / non-443 / registry or beacon probes). Proxy URLs are only ever printed redacted. Download failures now name the proxy and the hosts it must allow instead of falling silently into "Go is required". With an older release (pilotctl without --transport) compat points config's registry at registry.pilotprotocol.network:443, and a pilot-daemon without -proxy gets an explicit warning when HTTPS_PROXY is set. No-systemd hosts get the `pilotctl daemon start` hint; service-manager units get a note that they do not inherit the shell's HTTPS_PROXY. Tested in docker (debian bookworm, non-root, temp HOME) on an --internal network whose only egress is an authenticating CONNECT-443 proxy, with poisoned /etc/hosts for the Pilot names: v1.13.9 download + SHA-256 verify + install succeeds; missing/wrong proxy credentials fail with a clear hint. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(daemon): native HTTPS proxy support (-proxy / PILOT_PROXY) Hosted agent sandboxes such as Meta Muse block outbound UDP, poison local DNS for *.pilotprotocol.network, and allow only an authenticating HTTP proxy that CONNECTs to :443. Until now the daemon ignored HTTPS_PROXY entirely, so compat mode needed root, an SNI router and a mount-namespace /etc/hosts override to get online. New flag -proxy (env PILOT_PROXY, config key "proxy"), resolved once at startup by daemon.ResolveProxy into a common/netproxy policy: auto (default) -transport=compat: HTTPS_PROXY/https_proxy, falling back to ALL_PROXY/all_proxy, honoring NO_PROXY. -transport=udp: no policy, dialing exactly as before. off never proxy (HTTP clients also stop following env). http(s)://URL that proxy for every outbound TCP/HTTP connection. The policy (daemon.Config.Proxy) is applied to every outbound connection: the registry client (primary, pool and reconnects, via registry.WithDialer), the compat WSS beacon (wss.Config.Proxy), the MOTD fetch, and http.DefaultTransport for plugin HTTP clients (catalogue pins, skillinject, trustedagents, webhook, enterprise control). Targets are CONNECTed by host name and never resolved locally; TLS, SNI and pinned-fingerprint checks stay end to end. One startup line logs the transport and the redacted proxy. Compat mode now treats the compiled-in raw-TCP registry default (34.71.57.205:9000, which pilotctl passes on every daemon start) as not explicit, so it still switches to registry.pilotprotocol.network:443. -transport honors PILOT_TRANSPORT. -beacon-rtt-probe is skipped in compat mode (its UDP probes cannot leave the host). Pins github.com/pilot-protocol/common to the netproxy feature commit (v0.5.14-0.20260923210943-65ea5b1a3d2d); move to a tagged release before merge. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * build(deps): pin github.com/pilot-protocol/common v0.5.14 Replace the feature-branch pseudo-version with the tagged release that ships netproxy (HTTP CONNECT dialer, independent proxy env parsing, credential-safe URL handling) and registry/client WithDialer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: -transport=auto, proxy precedence, proxy-aware pilotctl, Muse onboarding Unifies the daemon (-proxy) and pilotctl/install.sh (--transport/--proxy) branches and fixes every confirmed review finding on both. pilot-daemon - -transport=auto (also $PILOT_TRANSPORT, config "transport"): udp when the beacon answers a UDP discover (one round trip; two attempts within 1.5s), else compat when the compat beacon accepts TCP through the proxy compat would use, else udp as before. Logged once. Never picks compat for a private registry/beacon. The binary default stays udp. pkg/daemon exports SelectTransport/NormalizeTransport; the embedder path (TransportMode "" or "auto") uses the same check. - Precedence for -transport, -proxy, -registry-trust, -registry-fingerprint: flag, then $PILOT_TRANSPORT / $PILOT_PROXY / $PILOT_REGISTRY_TRUST / $PILOT_REGISTRY_FINGERPRINT, then config.json, then default. Literal flag defaults: -help never prints $PILOT_PROXY. - registry_trust/registry_fingerprint from config/env survive compat mode; a fingerprint alone selects pinned trust. compat keeps the raw registry with an explicit -registry-tls=false (TCP/9000 fallback) and a custom registry from config.json. registry.pilotprotocol.network:443 always gets TLS, also in udp mode. - internal/proxyconf (on common/netproxy): off also accepts none/no/false/direct; bare words and scheme-less values are errors, not proxy host names. Loopback targets are never proxied (DefaultTransport, daemon HTTP clients, registry and WSS dials), even with an explicit URL. - WSS beacon dials through a netproxy dialer (wss.Config.DialContext replaces Config.Proxy): an https:// proxy is verified with the system roots; the beacon TLS config applies to the beacon only. - Unusable HTTP_PROXY/ALL_PROXY no longer drop a valid HTTPS_PROXY (common v0.5.14); skipped variables are logged. Certificate errors against the system store name SSL_CERT_FILE and the fingerprint. pilotctl - daemon start asks a daemon that supports it for -transport=auto when no transport is configured; the daemon is probed once (-help) and flags/values it predates are dropped (auto -> udp) with a warning. The ready summary reports the transport the daemon chose. - --proxy, then $PILOT_PROXY, then config "proxy"; any '@' means credentials, which travel as $PILOT_PROXY only, and nothing on argv contradicts them. Redaction/validation via internal/proxyconf. - lookup/register/rotate-key, the auto-handshake visibility check and recovery dial the registry through the egress proxy (CONNECT by name), using registry.pilotprotocol.network:443 over TLS when proxied or in compat mode (pinned with registry_fingerprint when configured), with a one-shot TLS fallback when the raw registry is unreachable directly. - config --set transport accepts auto and normalizes; leaving compat restores the raw-TCP registry an older compat install saved. - withTempHomeFull clears PILOT_TRANSPORT/PILOT_PROXY/*_PROXY. install.sh - --transport auto|udp|compat; fresh installs save auto when the daemon supports it; no "proxy" key is written; units take the transport from config.json; --transport udp restores the raw registry. - Root is allowed in a Linux container/VM without systemd (hosted agent sandboxes); regular hosts still refuse without PILOT_ALLOW_ROOT. Docs: README compat/proxy section (precedence, SSL_CERT_FILE, pinned registry), env table, CHANGELOG, regenerated docs/cli-reference.md. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: rotating proxy credentials, auto/compat and registry routing re-review Fixes the six re-review findings on feat/native-https-proxy. muse-proxy-cred-rotation-unhandled (high) - New -proxy-cmd / $PILOT_PROXY_CMD / config.json proxy_cmd: a command whose stdout is the current proxy URL. internal/proxyconf.Policy wraps it: re-run every 60s (Config.ProxyRefreshInterval) and whenever a CONNECT gets 407 (or the malformed status line sandbox proxies send), then the dial is retried once with the new URL. The registry client (primary, pool, every redial), the WSS beacon (every reconnect), daemon HTTP clients (retrying RoundTripper) and http.DefaultTransport (refresh on 407 via OnProxyConnectResponse) all follow it. Output and stderr are never logged; PILOT_ADMIN_TOKEN/PILOT_WEBHOOK_SECRET are kept from the command. A failing first run falls back to the launch environment's proxy. - pkg/daemon: Config.ProxyPolicy (*ProxyPolicy), StaticProxyPolicy, NewCommandProxyPolicy; Start runs the refresher until Stop. - install.sh saves proxy_cmd=bash -c 'printf %s "${https_proxy:-$HTTPS_PROXY}"' in a Linux container/VM without systemd whose HTTPS_PROXY carries credentials (or PILOT_PROXY_CMD when set); README documents it. version-skew-config-transport-auto-bricks-older-daemon (medium) - install.sh never saves transport=auto (--transport auto removes a saved transport); service units get Environment PILOT_TRANSPORT_DEFAULT=auto, which a pre-auto daemon ignores. pilot-daemon honours $PILOT_TRANSPORT_DEFAULT only when flag, $PILOT_TRANSPORT and config.json choose nothing. - install.sh --version <pre-auto tag> and pilotctl update --pin rewrite a saved transport=auto to udp. pilotctl config --set transport= (proxy=, proxy_cmd=) removes the key. compat-explicit-registry-tls-now-pinned-fatal (low) - applyRegistryDefaults defaults trust (pinned with a fingerprint, else system) whenever TLS is on in compat or for the compat registry address, also when -registry-tls was explicit. auto-compat-check-tcp-only-fatal-on-beacon-outage (low) - SelectTransport's compat check now does TLS + GET of the beacon path and requires 426 Upgrade Required (live WebSocket endpoint); a TCP front with the beacon down (502/503/close) keeps auto on udp. daemon-proxied-udp-registry-stays-raw-9000 (low) - When the registry dial goes through the proxy (any transport), the compiled-in raw registry moves to registry.pilotprotocol.network:443 over TLS, the rule pilotctl already applied. pilotctl-auto-proxy-regardless-of-transport (low) - pilotctl's registry routes follow the daemon: an explicit proxy URL always; the environment's proxy only when the transport is compat (the running daemon's, from the new info "transport" field, else $PILOT_TRANSPORT / config.json). udp hosts dial directly; unknown transport tries direct first and the proxied TLS registry as fallback for the production registry only; private raw registries are never sent to the environment's proxy outside compat. Tests: proxyconf policy unit tests (407 retry for dials and HTTP, NO_PROXY, Run loop, command runner); pkg/daemon compat start through a rotating proxy (registry + WSS reconnect); cmd/daemon end-to-end runs for PILOT_PROXY_CMD rotation, command failure fallback, proxied udp registry, explicit -registry-tls trust, PILOT_TRANSPORT_DEFAULT; SelectTransport front-up/beacon-down; pilotctl route matrix, private registry direct, fitTransportToDaemon, config key clearing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: installer changes via pilot-protocol/release, proxy-first pilotctl registry dial Fixes the two re-review findings on feat/native-https-proxy. web4-install-sh-edits-not-in-canonical-installer (high) - install.sh here is a synced copy of pilot-protocol/release:install.sh (the script https://pilotprotocol.network/install.sh serves; the canonical-drift job enforces byte equality). The installer changes are now ported onto the canonical script in pilot-protocol/release branch feat/installer-proxy-transport, keeping its managed-node mode (--managed-url, --no-start, PILOT_ENROLLMENT_TOKEN), and this copy is byte-identical to that branch. canonical-drift passes once the release change merges; merge it first. - Rotation no longer depends on the installer: on Linux without systemd, when $HTTPS_PROXY / $https_proxy carries credentials, the proxy setting is auto, no proxy_cmd is configured ($PILOT_PROXY_CMD, config.json / --config file) and the daemon supports -proxy-cmd, `pilotctl daemon start` hands the daemon PILOT_PROXY_CMD=bash -c 'printf %s "${https_proxy:-$HTTPS_PROXY}"'. A node set up by the currently served installer (PILOT_ALLOW_ROOT=1, no proxy_cmd) therefore re-reads rotated credentials too. The ready summary says so (JSON: "proxy_cmd"). - README/CHANGELOG describe both paths. web4-pilotctl-raw-route-defeated-by-muse-guard (low) - With the transport unknown (no daemon answering, nothing configured) and a proxy in the environment, pilotctl now tries the TLS registry through the proxy first and the raw registry directly second. The direct fallback is probed: a peer that sends data or hangs up within 300ms of connecting (a sandbox network guard) is rejected, so the proxied route's error is reported instead of a broken pipe. NO_PROXY exempting the registry keeps direct-first. Tests: route plan table (proxy first, probe flag, NO_PROXY), probedDirectDial (guard that talks, guard that closes, silent registry usable, dial error), dialRegistry against a local guard + authenticating CONNECT proxy + pinned TLS registry (proxy allowed, proxy refusing, raw fallback to a real registry), sandboxProxyCmdFor matrix, CLI daemon start passes/keeps PILOT_PROXY_CMD. Reviewer repro (muse-sim-vm, --network none, guard on 34.71.57.205:9000): CONNECT registry.pilotprotocol.network:443 is now the first attempt and the error names the proxy. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(changelog): link the installer change to pilot-protocol/release#49 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(proxy): netproxy credential refresh (common v0.5.15); auto stays on the proxy; daemon start names the proxy error Credential refresh now comes from common v0.5.15's netproxy instead of the branch-local proxy policy (internal/proxyconf/policy.go is gone): - -proxy-cmd / $PILOT_PROXY_CMD / config.json proxy_cmd build the resolver with netproxy.WithRefreshCommand. The command runs at startup, again once 60s have passed (lookup-driven), and whenever a proxy answers 407; the rejected connection is then retried once. - Registry (primary, pool, every redial) and the compat WSS beacon (and its reconnects) dial through netproxy.Dialer; daemon-owned HTTP clients use netproxy.RefreshingTransport (proxyconf.RoundTripper, loopback direct); http.DefaultTransport is configured in place so plugin clients take the current credentials and a 407 refreshes them for the next request. - pkg/daemon: Config.Proxy is the only knob (ProxyPolicy, ProxyRefreshInterval, StaticProxyPolicy, NewCommandProxyPolicy removed); ResolveProxy takes netproxy options. - pilotctl daemon start --proxy-cmd (passed as $PILOT_PROXY_CMD, never on argv); pilotctl's own registry commands use $PILOT_PROXY_CMD, config proxy_cmd or the sandbox default too, so a stale HTTPS_PROXY in its environment is refreshed and a 407 is retried. E2E product gap (phase-2 scenario 2c): with a proxy configured and -transport=auto, a proxy error during the compat check (407, 403, garbled answer, proxy unreachable) no longer falls back to udp, which dialed the raw registry directly past the proxy. SelectTransport picks compat and returns the proxy error; the daemon logs it at WARN with a hint, and the registry/compat dial failures end with a hint naming the fix. Fatal startup errors are logged at ERROR (log.Fatalf printed them at INFO). pilotctl daemon start notices a daemon that exits during startup instead of polling until the deadline, and on exit or timeout prints the daemon's last error and last proxy error from its log with a hint, instead of only "did not become ready". gosec: annotate the daemon exec and log read, handle probe Close errors. Tests: in-process rotating-credential CONNECT proxies for proxyconf (dial retry, RoundTripper retry, DefaultTransport refresh), pkg/daemon (registry + WSS reconnect after rotation, timed refresh, MOTD client retry, auto stays compat on 407/403/unreachable), cmd/daemon (subprocess: auto + 407 stays on the proxy, mutation-checked), pilotctl (registry dial follows rotated credentials, proxy-first routes, daemon start failure reporting with fake daemons, and an end-to-end run of the real daemon behind a rejecting proxy). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(pilotctl): --json trusted list; warn when an old daemon will ignore HTTPS_PROXY Two phase-2 E2E onboarding papercuts: - `pilotctl --json trusted list` ignored --json and printed the table. - A new pilotctl paired with a daemon that predates -proxy (v1.13.9) in a shell with HTTPS_PROXY/ALL_PROXY started it silently; the failure then surfaced only as "did not become ready". daemon start now warns that the daemon will not use the proxy (not with --proxy off, and not twice when an explicit --proxy was already dropped). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(daemon): -transport=auto help says a refusing proxy keeps compat Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(daemon): record the beacon's authenticated node before auth_ok TestStartCompatModeThroughConnectProxy failed on ubuntu CI with "beacon authenticated node 0, want 1": the daemon's Start returns as soon as it reads auth_ok, and the fake beacon stored the node only after writing it. Store first. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(proxy): apps follow rotating proxy credentials via a loopback relay; Muse rejection diagnostics; credential-preferring sandbox command Phase-3 review findings on #470: web4-470-apps-inherit-stale-proxy-creds (high). App-store apps are processes the daemon spawns with its environment, so they kept the launch-time HTTPS_PROXY credentials: after one rotation every app that opened a new connection failed ("node online, all apps broken"), also after a respawn. New internal/proxyconf.Relay: a CONNECT proxy on 127.0.0.1:<random> that opens each tunnel upstream with a netproxy.Dialer (current credentials, refresh + one retry on a 407 or a garbled answer), CONNECT only, guarded by its own random credentials, never inside the TLS tunnel. A proxying daemon runs one; with -proxy-cmd it points HTTPS_PROXY/https_proxy (and PILOT_PROXY when it is a URL) at it before any plugin starts, so every app it spawns inherits the relay instead of credentials. The daemon itself never uses the relay: the refresh command now runs in the launch environment (proxyconf.CommandSource, same process-group/timeout/output-cap rules as netproxy's), a refresh that names the relay is refused, and a remote restart re-execs with the launch environment. web4-470-configuretransport-ignores-garbled-rejection. net/http never passes an unparseable CONNECT answer to OnProxyConnectResponse, so http.DefaultTransport clients never refreshed on Muse's rejection form and quoted the proxy's bytes. ConfigureTransport now takes the relay: https requests tunnel through it (refresh + retry, netproxy's wording in errors, the relay's upstream error surfaced to the client); http:// keeps going to the proxy. Doc comments and CHANGELOG corrected. web4-470-muse-rejection-diagnostics-misdirect. proxyconf.CredentialHint / UnreadableConnectReply recognise netproxy's "read CONNECT response: ... (response text withheld)"; daemon.ProxyRefusalHint, the auto-selected WARN and pilotctl's start-failure hint now name the credentials and proxy_cmd for it. No hint suggests -transport=udp unconditionally any more. web4-470-sandbox-cmd-variable-precedence. The sandbox proxy_cmd (pilotctl and install.sh) now prints whichever of $https_proxy / $HTTPS_PROXY carries credentials ($https_proxy when both do, the daemon's order when neither does), so it can never replace a credentialed URL with a bare one. install.sh differs from release#49 by that one line; #49 must take it. Tests: real daemon + app-store supervisor + sideloaded app across garbled rotations (fails with "malformed HTTP status code 4O7" without the relay), relay unit tests, the reviewer's ConfigureTransport repro, CommandSource, hints (daemon subprocess, pkg/daemon, pilotctl CLI), and the sandbox command through bash for 7 variable combinations. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * install.sh: sync with pilot-protocol/release#49 (ae447bc) Byte-identical copy of the canonical installer on pilot-protocol/release feat/installer-proxy-transport, so canonical-drift passes once release#49 merges. Takes this branch's credential-preferring sandbox proxy_cmd, and adds: no raw-IP registry/beacon in config.json for compat or auto behind a proxy, downloads retried once after a proxy credential rotation, proxy_cmd saved for older daemons too, PILOT_PROXY downloads, the v1.13.x proxy warning pointing at the pilot-sandbox recipe, and onboarding text that reads replies from send-message --wait and drops routine appstore --force. Only install.sh changes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * install.sh: sync with pilot-protocol/release#49 (67e83fc) Byte-identical to release@67e83fc (review fixes: root refused under sudo, no `pilotctl daemon start` advice on proxy-only hosts with a daemon that cannot use the proxy, the transport stated after the download, --version / --channel beta installable again). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(proxy): hints that fit a daemon already on proxy_cmd; gosec; install.sh sync with release#49 (c36ad9b) - pilotctl daemon start: when the daemon re-reads its credentials with a proxy command and the proxy still rejects them, the hint names the command in use and says to check what it prints from a fresh shell, instead of telling the operator to set one (E2E scenario 3: the 407 hint said "give the daemon a command that prints the current proxy URL" with config.json proxy_cmd in place). The daemon's own CredentialHint is worded for both. - TestInstallerSavesTheSandboxProxyCmd: install.sh's SANDBOX_PROXY_CMD must evaluate to pilotctl's sandboxProxyCmd. A saved proxy_cmd turns off the one `daemon start` hands the daemon, so the two must never drift (web4-470 review: the installer kept the pre-change command). - gosec: #nosec G204 with the reason on proxyconf.CommandSource (the operator's proxy command run with sh -c is the function's purpose), and the new G104 warnings (unchecked Close/Remove) in relay.go and pilotctl. - install.sh: byte-identical to pilot-protocol/release#49 c36ad9b (sandbox proxy_cmd only for credentials a fresh shell sees and never over an explicit PILOT_PROXY; restart advice stops the running daemon before the sandbox recipe; macOS LaunchAgent line conditioned and never sent to the Linux-only recipe; truthful --transport auto note for pre-auto daemons). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * proxyconf: name the rotation hint so gosec G101 does not read it as a credential Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(proxyconf): fixed order in the relay garbled-rejection test TestConfigureTransportViaRelayHandlesGarbledRejection ranged over a map of the two transports and afterwards restored the proxy to "p-clone", the password the clone iteration rotates to. Go randomizes map order, so half the runs restored a password the relay no longer held and the 403 check saw a garbled 407 instead (architecture-gates race run on 30c034b). Iterate in a fixed order. -race -count=5 passes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * deps: skillinject v0.2.5 (gated Meta Muse injection target) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Teodor Calin <teodor@vulturelabs.io> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
This PR fixes the installer users actually run,
curl -fsSL https://pilotprotocol.network/install.sh | sh, for hosted agent sandboxes. The target is Meta Muse, where:HTTPS_PROXYrotate every few minutes.Normal hosts install exactly as before (same files, same
config.json). Their output now states the transport the installed daemon actually uses.It is the installer half of pilot-protocol/pilotprotocol#470 (
feat/native-https-proxy). At head c36ad9b this branch'sinstall.sh(sha2564384f0cb2890177cb87a2e2bc49e1b814d2850434d24c54d1730c9955fbbb671) is byte-identical to pilotprotocol#470's copy (synced in pilotprotocol@df090a8a, whereTestInstallerSavesTheSandboxProxyCmdalso pinsSANDBOX_PROXY_CMDto pilotctl's command) and to the website fallback in pilot-protocol/website#263 (website@a7f94bc).How it deploys (checked)
worker/(Cloudflare Workerpilot-release, routepilotprotocol.network/install.sh) readsinstall.shfrom the R2 bucketpilot-release-assetson every request (cache-control: public, max-age=300). The script is not bundled into the Worker atwrangler deploy, so the Worker does not need redeploying for this change.pilot-protocol/website.github/workflows/sync-install-sh.yml. That workflow:raw.githubusercontent.com/pilot-protocol/release/main/install.sh;bash -non it;wrangler r2 object put pilot-release-assets/install.sh;public/install.shhas drifted.notify-install-sh-sync.ymlruns on a push tomainthat touchesinstall.sh. It sendsrepository_dispatch: release-install-sh-changedto the website repo. A daily 06:17 UTC cron andworkflow_dispatchare the safety nets.install.sh, so the tests below were run by hand.Changes
Root and transport
/run/systemd/system(containers and VMs such as Muse) when root itself runs the installer, and prints a note. Root is still refused, unlessPILOT_ALLOW_ROOT=1:SUDO_UID/SUDO_USER,DOAS_USER,PKEXEC_UID).curl … | sudo shon WSL, OpenRC/runit hosts or dev containers would otherwise install into/root/.pilot, which that user cannot run, andsudo -Ewould leave a root-owned~/.pilot. The error names the user and gives the command to run instead.--transport auto|udp|compat(orPILOT_TRANSPORT):udpandcompatare saved.autois never saved.transport=autois rewritten toudpfor a daemon that predates it.No raw-IP endpoints behind a proxy
config.jsonleaves out34.71.57.205:9000and34.71.57.205:9001when the node runs compat, or auto behind a proxy. The daemon then applies the endpoint that fits its transport:registry.pilotprotocol.network:443over TLS in compat mode or through a proxy.--transport(v1.13.x forwards config.json's registry verbatim), a compat install getsregistry.pilotprotocol.network:443by name.PILOT_REGISTRYorPILOT_BEACONis always kept.Rotating credentials. Nothing credential-bearing is ever written or printed.
proxy_cmdis saved inconfig.json:$PILOT_PROXY_CMD, or in a sandbox whoseHTTPS_PROXY/https_proxycarries credentials, the credential-preferring command pilotctl uses:bash -c 'case $https_proxy in *@*) printf %s "$https_proxy";; *) printf %s "${HTTPS_PROXY:-$https_proxy}";; esac'proxy_cmdis never replaced.-proxy-cmd: that daemon ignores the key until it is upgraded, and the installer prints a note saying so.pcurlretries once after re-reading the proxy URL from that command, mirroring the daemon's 407 → refresh → retry-once. The re-read URL only changes this process's environment.pilotctl skills checkgets the refreshed credentials too.PILOT_PROXYhttp(s) URL carries the downloads when no*_PROXYvariable is set.http://***@host:port).proxystores the credentials, and offersproxy_cmdinstead.Honest output with today's releases (v1.13.9, v1.13.10: no
-proxy)PILOT_PROXY_CMDset), no output tells the agent to runpilotctl daemon start. That covers the warning, the no-systemd hint, GET STARTED step 0 and the re-run summary: each says not to run it and points at the recipe. On other hosts with such a proxy, the command stays, with the condition and the recipe next to it.autois no longer announced before the download. The install and update summaries state the transport of the installed daemon. For v1.13.9 that isudp (… predates auto and never falls back to TCP 443 by itself), plus, when nothing chose udp, the--transport compatre-run for UDP-blocked hosts.compatsaved for a daemon without-transportis reported as udp.Release pins (pre-existing bug)
--version <tag>and--channel betaaborted with "integrity anchors disagree" for every tag except latest_stable, because the manifest only hashes latest_stable. The manifest hash is now compared only for the tag it describes: its platformurlnames the tag, or the tag islatest_stable, which covers the managed-runtime manifest without urls. Any other tag is verified againstchecksums.txt. The tag the manifest describes still needs both anchors to agree.--helpprints the usage header up to "WHAT THIS SCRIPT DOES" instead of a fixed line range.Onboarding text
send-message --wait(JSON:.data.reply), not from "the newest inbox message".appstore installexamples drop the routine--force.Email:line now explains the synthesized identity.pilotctl skillsinstead of one harness path.Safety
pilotctl daemon start --helpprobe now runs only for compat with a daemon that has-transport(v1.11+). Per-command help exists since v1.10, so the probe can never start a daemon.tests/managed-install.shcaught the unconditional version.Round 2 review fixes (c36ad9b)
proxy_cmdonly for credentials a fresh shell can print.ENV_PROXY_CREDSis read beforePILOT_PROXYis copied intohttps_proxy/HTTPS_PROXYfor the downloads, and the sandbox command is chosen only when the proxy environment carries credentials andPILOT_PROXYis unset orauto(pilot-daemon runs a proxy command in place of the URL it would use, so it would have replaced an explicitPILOT_PROXY, as pilotctl already avoids). Before,PILOT_PROXY=http://u:p@…saved a command that printed nothing and the summary claimed "rotation needs no restart".Stop the running daemon first: pilotctl daemon stop, then the recipe; the recipe starts a daemon but never stops one, and following the old advice ran two daemons with one identity.start_hintlike every other start line (condition onPROXY_UNSUPPORTED, "Do not run" onPROXY_ONLY), and nothing points macOS at the Linux-root-only recipe:PROXY_REMEDYthere is "re-run this installer once a Pilot release whose pilot-daemon -h lists -proxy is out".--transport autowith a pre-auto daemon no longer says "keeps its default (udp)" while a saved compat stays in effect; it says the saved transport is kept and how to switch.proxy_cmd): fixed in pilot-mcp#23 (itsSANDBOX_PROXY_CMDis now this exact command; the older pre-release one is still recognised).Tests for round 2 (
tests/proxy-transport-install.sh, new darwin fixture with a fakelaunchctl): 4d (PILOT_PROXY credentials: noproxy_cmd, no rotation claim, no leak; explicit PILOT_PROXY next to a credentialed HTTPS_PROXY: noproxy_cmd), the re-run advice keepspilotctl daemon stop, 3b (old daemon,--transport compatthen--transport auto: compat stays and is reported), 10a (macOS with a proxy: conditioned LaunchAgent line, no Linux recipe; withPILOT_PROXY_CMD: "Do not runlaunchctl load -w …"). Passes on macOS sh and in a Linux container as root, as a regular user and with/run/systemd/system;tests/managed-install.shpasses;shellcheck -s sh install.sh tests/*.shclean.E2E (round 3 Muse sim, rotating-credential CONNECT-443 proxy, root, no systemd, packet sink for direct dials): installed through pilot-skills#34's one-shot with
PILOT_INSTALL_URL=file://this c36ad9b script — with the next release's binaries: rc=0,config.jsontransport=compat+proxy_cmd(the pilotctl command), node registered through the proxy; with released v1.13.10 and root without CAP_SYS_ADMIN: the WARNING, the no-systemd hint and GET STARTED name the recipe and say not to runpilotctl daemon start(no output line tells the agent to run it).Tests
Fixture tests
sh tests/proxy-transport-install.sh: OK under macOS sh and dash. It uses a fixture release with fakecurl,uname,idandsudo, and needs no network. New cases:BASH_ENVstands in for Muse's fresh-shell credentials;PILOT_PROXY;proxy_cmdsaved, plus the warning with the recipe link;SUDO_UID+SUDO_USER,SUDO_USERalone) and doas. It is allowed under sudo from root (SUDO_UID=0) and withPILOT_ALLOW_ROOT=1;--transport compat: no line tells the agent to runpilotctl daemon start(orstop && start, orsystemctl enable), and the warning, the no-systemd hint and GET STARTED all point at the recipe. With a proxy that has no credentials, the command stays with the condition. A daemon that can use the proxy keeps the command and gets no recipe;Transport: udp (… predates auto, neverTransport: auto, plus the compat hint. There is no hint after--transport udpor with a daemon that has auto;-transportand--transport compat: the summary says udp;--version v9.9.8 --yesand--channel betaagainst a manifest that hashes only latest_stable, with and without platform urls: installed and verified bychecksums.txt. The latest_stable tag with a disagreeing manifest hash, and a pinned tag that the manifest's url names, are still refused;--helprange;~/.pilot.PILOT_TEST_SH=dash dash tests/proxy-transport-install.shruns the installer itself under dash.PILOT_PROXYexport each fails the suite. So does each review fix disabled on its own: the sudo refusal, the manifest-tag rule (either half), proxy-only detection, GET STARTED step 0, the compat hint, or restoring the earlyautobanner.sh tests/managed-install.sh: OK.shellcheck -s sh install.sh tests/*.sh: clean.sh -npasses under busybox, dash and bash.Docker, review fixes (head 67e83fc, real v1.13.9 downloads)
ubuntu:24.04, no systemd, useragentwith NOPASSWD sudo:cat install.sh | sudo shandsudo -E sh install.shrefusing to install as root: this runs under sudo for agent. No/root/.pilot, no~/.pilot, no/usr/local/binlinks. Base 36c38dc refuses too; the previous head installed into/root/.pilot.HOME=/root, noSUDO_*)/root/.pilot/bin.agent, plain installTransport: udp (this pilot-daemon, v1.13.9, predates auto …)plus the--transport compatre-run. That re-run saves compat withregistry.pilotprotocol.network:443and the update summary says compat.--version v1.13.8 --yes,--channel beta(v1.13.10-rc.2),--version v1.10.1 --transport compat --yesVerified SHA-256 (checksums.txt), andpilotctl versionmatches. Base 36c38dc:--version v1.13.8givesintegrity anchors disagree.BASH_ENVfresh credentials, poisoned DNS, rootHOME=/root, no systemd. Fresh install, re-run, and--transport compatpilotctl daemon start, 3 recipe pointers (warning, no-systemd hint, GET STARTED), 0Transport: auto, 0 credential matches in the output,/rootor/usr/local/bin. Three 407s from rotations were each retried and allowed. The proxy log has only :443 CONNECTs.Docker, served path
curl -fsSL https://raw.githubusercontent.com/pilot-protocol/release/<head>/install.sh | shin a Muse-like rig with:--internalnetwork;BASH_ENVexporting the current credentials;HOME=/rootand no systemd.--transport compat, v1.13.9, 5 runsgithub.com,release-assets.githubusercontent.comandpilotprotocol.network, and every one was retried and allowed. The proxy log has only :443 CONNECTs; direct egress fails (Could not resolve host).config.json={transport: compat, registry: registry.pilotprotocol.network:443, proxy_cmd: <command>}, no raw IP. 0 credential matches in the output,/rootor/usr/local/bin. The v1.13.9 warning names the sandbox recipe.curl | sh, v1.13.9, 3 runsproxy_cmdis saved and the warning is shown.feat/native-https-proxy@ 5097bc22 and copied over the download by a test-only copy of this script. Output:Transport: auto.config.jsonhas no registry or beacon and hasproxy_cmd. Thenpilotctl daemon startregistered in 5s (transport auto-selected transport=compat,registry=registry.pilotprotocol.network:443, node 251998, since deregistered). Across 3+ rotations (30s period): 4 registry reconnects got 407 and were each retried and allowed.pilotctl --json send-message list-agents --data '/data {"search":"weather","limit":2}' --waitreturned.data.reply, andpilotctl appstore catalogueworked. 0 credential matches in the daemon log.--transport udp--transport udpsaves udp.agent), no proxyconfig.jsonhas the stock registry and beacon as before. No root note./run/systemd/systempresent is refused (refusing to install as root, no~/.pilot). Root without systemd is allowed with the note.Deploy order (all six PRs)
notify-install-sh-syncdispatches to pilot-protocol/website →sync-install-sh.ymlputsinstall.shinto R2pilot-release-assets/install.sh(thepilot-releaseWorker reads R2 per request; no Worker deploy). Check:curl -fsSL https://pilotprotocol.network/install.sh | shasum -a 256→4384f0cb2890177cb87a2e2bc49e1b814d2850434d24c54d1730c9955fbbb671(up to 5 min cache).public/install.sh, same bytes) → the sync workflow's drift step goes green.install.sh matches pilot-protocol/release, merge.v1.13.11on main (release workflow: binaries,checksums.txt, signedlatest.json). v1.13.10 shipped without #470, so until this tag every install gets a daemon without-proxy. Checkpilot-daemon -hlists-proxyand-proxy-cmd.skills.json/setups.jsonandskills/pilotctl/SKILL.md, dispatches the website deploy; the Muse one-shot (raw.githubusercontent.com/TeoSlayer/pilot-skills/main/muse/install.sh) is live at merge.0.3.0(behaviour change; last published 0.2.13): bumppackage.json,package-lock.json,server.json(both fields),.well-known/mcp/server-card.json,src/version.js,src/openclaw-plugin/openclaw.plugin.json,src/openclaw-plugin/evaluate.jsand the pinnedpilotprotocol-mcp@0.2.13strings intest/{hermes-setup,openclaw-plugin,native-harness-setup,harness-config-contracts}.test.js(test/release-contract.test.jslocks them), move[Unreleased]to[0.3.0], push tagv0.3.0→publish.yml(tag must equalv+version; lint + tests; npm via OIDC, MCP Registryserver.json,ghcr.io/pilot-protocol/pilot-mcp).v0.2.5→ pilotprotocol follow-up PRgo get github.com/pilot-protocol/skillinject@v0.2.5 && go mod tidy(GOWORK=off) → next daemon release (v1.13.12; or fold the bump in before tagging v1.13.11).gatedToolsmuse row). Released daemons drop the key (CIreleased-skillinjectv0.2.2–v0.2.4). No manifest signing step:DefaultManifestPublicKeyHexis empty; only hosts that installed~/.pilot/skillinject.pubverifyinject-manifest.json.sig.🤖 Generated with Claude Code