Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ sha2 = "=0.10.9"
sha1 = "=0.10.6"
hex = "=0.4.3"
reqwest = { version = "=0.12.28", features = ["rustls-tls", "json"], default-features = false }
# Platform trust store (+ SSL_CERT_FILE / SSL_CERT_DIR) for every HTTPS
# client, alongside the bundled webpki roots (utils::http::client_builder).
# `rustls` and `webpki-roots` are the exact builds reqwest's `rustls-tls`
# already pulls in (ring provider); the shared client config is built
# from them directly.
rustls-native-certs = "=0.8.4"
rustls = { version = "=0.23.45", default-features = false, features = ["std", "ring", "tls12"] }
webpki-roots = "=1.0.6"
tokio-rustls = { version = "=0.26.4", default-features = false, features = ["ring", "tls12"] }
tokio = { version = "=1.50.0", features = ["full"] }
tokio-util = "=0.7.18"
futures-util = { version = "=0.3.32", default-features = false, features = ["std"] }
Expand Down
2 changes: 1 addition & 1 deletion crates/socket-patch-cli/CLI_CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,7 @@ Exactly three keys are honored, each slotting **below** the env var and **above*
Contract properties:

- **Read-only pledge**: socket-patch never creates, modifies, or deletes this file; socket-cli owns it. There is no `socket-patch login`/`config` subcommand — use `socket login`.
- Other socket-cli keys (`apiProxy`, `enforcedOrgs`, `skipAskToPersistDefaultOrg`) and unknown keys are ignored. Non-string or empty values for the three honored keys count as unset. For an HTTP forward proxy use the standard `HTTP_PROXY`/`HTTPS_PROXY`/`NO_PROXY` vars, which the HTTP client honors; socket-cli's `apiProxy` is deliberately not mapped (and is unrelated to `--proxy-url`, which is the public patch *endpoint*).
- Other socket-cli keys (`apiProxy`, `enforcedOrgs`, `skipAskToPersistDefaultOrg`) and unknown keys are ignored. Non-string or empty values for the three honored keys count as unset. For an HTTP forward proxy use the standard `HTTP_PROXY`/`HTTPS_PROXY`/`NO_PROXY` vars, which the HTTP client honors. Every HTTPS client (patch API, public proxy, blob/artifact and registry fetches, telemetry, self-update) trusts the bundled webpki (Mozilla) roots plus the platform trust store; `SSL_CERT_FILE` / `SSL_CERT_DIR`, when set, replace the platform store with that bundle/directory, so a TLS-inspecting proxy's private CA can be trusted. Verification is never disabled. socket-cli's `apiProxy` is deliberately not mapped (and is unrelated to `--proxy-url`, which is the public patch *endpoint*).
- Missing file / unresolvable data dir: silent (the normal case). Present but unreadable or undecodable (not base64(JSON), with a plain-JSON leniency fallback): a one-shot stderr warning naming the path, then treated as absent — never fatal, and `--json` stdout stays clean (all diagnostics are stderr-only).
- The file is read lazily at most once per process, only when a key is still unresolved after flag + env.
- The telemetry endpoint resolver shares the same `apiBaseUrl` chain as API-client construction (`resolve_api_base_url`), so telemetry can never target a different host than the client.
Expand Down
4 changes: 4 additions & 0 deletions crates/socket-patch-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ sha2 = { workspace = true }
sha1 = { workspace = true }
hex = { workspace = true }
reqwest = { workspace = true }
rustls-native-certs = { workspace = true }
rustls = { workspace = true }
webpki-roots = { workspace = true }
tokio = { workspace = true }
# CancellationToken for the in-memory hosted engine (`hosted::memory`).
tokio-util = { workspace = true }
Expand Down Expand Up @@ -84,3 +87,4 @@ tempfile = { workspace = true }
tokio = { workspace = true, features = ["full", "test-util"] }
serial_test = { workspace = true }
wiremock = { workspace = true }
tokio-rustls = { workspace = true }
4 changes: 2 additions & 2 deletions crates/socket-patch-core/src/api/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1992,7 +1992,7 @@ fn api_client(api_token: Option<&str>, timeouts: &ApiTimeouts) -> reqwest::Clien
}

timeouts
.apply(reqwest::Client::builder().default_headers(default_headers))
.apply(crate::utils::http::client_builder().default_headers(default_headers))
.build()
.expect("failed to build reqwest client")
}
Expand All @@ -2009,7 +2009,7 @@ fn plain_client(timeouts: &ApiTimeouts) -> reqwest::Client {
HeaderValue::from_static(USER_AGENT_VALUE),
);
timeouts
.apply(reqwest::Client::builder().default_headers(headers))
.apply(crate::utils::http::client_builder().default_headers(headers))
.build()
.expect("failed to build plain reqwest client")
}
Expand Down
2 changes: 1 addition & 1 deletion crates/socket-patch-core/src/telemetry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ fn prepare_send(event: PatchTelemetryEvent, auth: &TelemetryAuth) -> PreparedSen
async fn send_telemetry_event(prepared: PreparedSend) {
let PreparedSend { event, url, bearer } = prepared;

let client = match reqwest::Client::builder()
let client = match crate::utils::http::client_builder()
.connect_timeout(std::time::Duration::from_secs(2))
.timeout(std::time::Duration::from_secs(5))
.build()
Expand Down
2 changes: 1 addition & 1 deletion crates/socket-patch-core/src/update/download.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ fn download_client(
endpoints: &UpdateEndpoints,
timeouts: &UpdateTimeouts,
) -> Result<reqwest::Client, UpdateError> {
reqwest::Client::builder()
crate::utils::http::client_builder()
.user_agent(crate::constants::USER_AGENT)
.connect_timeout(timeouts.connect)
.timeout(timeouts.download)
Expand Down
2 changes: 1 addition & 1 deletion crates/socket-patch-core/src/update/release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ fn metadata_client(
timeouts: &UpdateTimeouts,
redirects: reqwest::redirect::Policy,
) -> Result<reqwest::Client, UpdateError> {
reqwest::Client::builder()
crate::utils::http::client_builder()
.user_agent(crate::constants::USER_AGENT)
.connect_timeout(timeouts.connect)
.timeout(timeouts.metadata)
Expand Down
Loading
Loading