Skip to content
Open
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
15 changes: 9 additions & 6 deletions crates/socket-patch-cli/src/commands/scan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -981,8 +981,10 @@ fn overlap_from_states(
/// them to right now — the truth source for takeover direction.
///
/// Both directions are proved by lockfile discovery with the same liveness
/// rules `vex` gates attestations on (core `Discovery::redirect_record_live`
/// / `Discovery::vendor_entry_live`). `redirect` holds the overlap PURLs the
/// rules `vex` gates attestations on (core `Discovery::redirect_record_verdict`
/// / `Discovery::vendor_entry_live`); a hosted record on a patch server this
/// run was not given (`RecordLiveness::Undecided`) counts as wired, since the
/// wiring is still there. `redirect` holds the overlap PURLs the
/// lock routes to the hosted patch server (the vendored ledger entry is
/// stale); `vendored` holds those it routes to a committed
/// `.socket/vendor/<eco>/<uuid>` artifact.
Expand Down Expand Up @@ -1067,7 +1069,7 @@ pub(super) async fn classify_overlap_takeover_with(
let mut liveness = LedgerLiveness::new(cwd, discovery, None);
for purl in overlap {
let hosted_live = match redirect_uuid_by_purl.get(&PurlKey::new(&purl)) {
Some(uuid) => liveness.redirect_record(&purl, uuid).await,
Some(uuid) => liveness.redirect_record_retained(&purl, uuid).await,
None => discovery.wires_package(&purl, WiringMode::Hosted),
};
let vendored_live = match vendor_by_purl.get(&PurlKey::new(&purl)) {
Expand Down Expand Up @@ -1391,8 +1393,9 @@ async fn gradle_scan(
/// pin names the purl (`redirect_state`, the lockfiles' hosted state — see
/// [`crate::commands::hosted_state_from_pins`]) AND lockfile discovery
/// proves the current lockfile still routes it to that hosted patch — core
/// `Discovery::redirect_record_live`, the same liveness rule `vex` gates
/// hosted attestations on.
/// `Discovery::redirect_record_verdict`, the same liveness rule `vex` gates
/// hosted attestations on, keeping a record on a patch server this run was
/// not given (`RecordLiveness::Undecided`): its wiring is still retained.
///
/// Deliberately NOT routed through [`classify_overlap_takeover`]: that
/// classifier keys on purls present in BOTH ledgers, so hosted-only wiring
Expand Down Expand Up @@ -1435,7 +1438,7 @@ pub(super) async fn hosted_wiring_retained_purls(
let mut liveness = LedgerLiveness::new(cwd, &discovery, None);
let mut out = Vec::new();
for (purl, uuid) in candidates {
if liveness.redirect_record(&purl, uuid).await {
if liveness.redirect_record_retained(&purl, uuid).await {
out.push(purl);
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/socket-patch-core/src/hosted/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ pub async fn read_candidate_files(
// unsatisfiable. Keyed `<dir>/Cargo.toml` for the cargo rewriter.
if out.files.contains_key("Cargo.toml") && candidates.iter().any(|c| c.dep.ecosystem == "cargo")
{
for rel in crate::utils::cargo_workspace::member_manifests_in(view) {
for rel in crate::utils::cargo_workspace::member_manifests_in(view).await {
out.read(view, unreadable, &rel).await;
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/socket-patch-core/src/hosted/memory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use std::time::Instant;
use crate::api::client::PatchApi;
use crate::api::types::{PatchResponse, PatchSearchResult};
use crate::crawlers::Ecosystem;
use crate::utils::cargo_workspace::member_manifests_in;
use crate::utils::cargo_workspace::member_manifests_in_memory;
use crate::vendor::lock_inventory::{
inventory_project_diagnosed_in, MemoryEntry, MemoryProject, ProjectView,
};
Expand Down Expand Up @@ -279,7 +279,7 @@ fn demote_cargo_members(states: &mut [RootState], warnings: &mut Vec<EngineWarni
if !project.contains("Cargo.lock") {
continue;
}
for rel in member_manifests_in(&ProjectView::Memory(project)) {
for rel in member_manifests_in_memory(project) {
if let Some(dir) = rel.strip_suffix("/Cargo.toml") {
member_of
.entry(roots::join_root(&state.root, dir))
Expand Down
26 changes: 18 additions & 8 deletions crates/socket-patch-core/src/patch/redirect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2415,7 +2415,7 @@ fn crlf_to_lf(text: &str) -> Option<String> {
/// A workspace-member manifest key the caller supplied: `<dir>/Cargo.toml`,
/// a plain repo-relative path (never absolute, never `..`, never under the
/// ledger's `.socket/` or a build `target/`).
fn is_cargo_member_manifest_key(key: &str) -> bool {
pub(crate) fn is_cargo_member_manifest_key(key: &str) -> bool {
let Some(dir) = key.strip_suffix("/Cargo.toml") else {
return false;
};
Expand Down Expand Up @@ -7648,8 +7648,11 @@ pub fn hosted_patch_uuid(url: &str, extra_origins: &[String]) -> Option<String>
/// exact acceptance rules, without electing one segment. `vex` discovery
/// uses it to RECOGNIZE every Socket identity a lockfile mentions, including
/// the malformed or rejected shapes whose "last uuid" is not a patch.
pub fn hosted_patch_url_uuids(url: &str, extra_origins: &[String]) -> Option<Vec<String>> {
use crate::patch::path_safety::is_canonical_uuid;
/// `url` normalized the way [`hosted_patch_url_uuids`] reads it: `\/`
/// unescaped, a percent-encoded `http(s)://` url decoded, and a Cargo
/// `sparse+` / `registry+` source prefix stripped. `None` without a
/// `://`.
pub(crate) fn normalized_hosted_url(url: &str) -> Option<String> {
use crate::utils::purl::percent_decode_purl_component;

let unescaped = url.trim().replace("\\/", "/");
Expand All @@ -7661,13 +7664,20 @@ pub fn hosted_patch_url_uuids(url: &str, extra_origins: &[String]) -> Option<Vec
};
// `sparse+https://…` / `registry+https://…` (Cargo.lock `source`).
let (scheme, _) = decoded.split_once("://")?;
let text = match scheme.rsplit_once('+') {
Some(match scheme.rsplit_once('+') {
Some((kind, _)) if !kind.is_empty() && kind.bytes().all(|b| b.is_ascii_alphabetic()) => {
&decoded[kind.len() + 1..]
decoded[kind.len() + 1..].to_string()
}
_ => decoded.as_str(),
};
let parsed = reqwest::Url::parse(text).ok()?;
_ => decoded,
})
}

pub fn hosted_patch_url_uuids(url: &str, extra_origins: &[String]) -> Option<Vec<String>> {
use crate::patch::path_safety::is_canonical_uuid;
use crate::utils::purl::percent_decode_purl_component;

let text = normalized_hosted_url(url)?;
let parsed = reqwest::Url::parse(&text).ok()?;
if !matches!(parsed.scheme(), "https" | "http")
|| !parsed.username().is_empty()
|| parsed.password().is_some()
Expand Down
Loading
Loading