From 73c16dd7e48f417fc6ec00f370d7b28db734db71 Mon Sep 17 00:00:00 2001 From: Mikola Lysenko Date: Thu, 13 Aug 2026 10:33:54 -0700 Subject: [PATCH 1/2] fix(test): give four get edge-case fixtures a real file so #158's guard passes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged PR #158 (5d7eb6f, "fix(get,scan): retain patch-added new files; guard empty patch records") added a correct guardrail: a fetched patch view whose `files_for_manifest` map is EMPTY is now an exit-1 failure ("patch has no applicable files") instead of a silent `applied:1`. But #158 only touched get.rs and left four tests in get_edge_cases_e2e.rs carrying stale `"files": {}` patch-view fixtures that still assert the `get` succeeds (exit 0). Those four now fail on main: - get_with_id_flag_selects_specific_patch - get_uuid_returns_paid_patch_with_token_succeeds - get_on_vendored_purl_warns_about_uuid_drift - get_uuid_replacing_existing_manifest_entry_reports_updated Their real concern is selection / paid-token / drift-warning / manifest-replacement logic, not "a patch with zero files" — the empty map was only a lazy stand-in. Give each view fixture one recordable net-new file (all-zero `beforeHash`, real git-blob `afterHash` via the shared `common::git_sha256` oracle, matching base64 `blobContent`), modeled on the passing `get_invariants::patch_response_json` fixture, so `files_for_manifest` is non-empty and the guard is satisfied. Every existing assertion (found==1, selected UUID, drift warning, `updated` reporting + `oldUuid`, manifest move) is unchanged. The guardrail in get.rs is untouched. get_edge_cases_e2e now 22/22; lib (350) and get_invariants / get_update_summary (15) unaffected. Co-Authored-By: Claude Opus 4.8 --- .../tests/get_edge_cases_e2e.rs | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/crates/socket-patch-cli/tests/get_edge_cases_e2e.rs b/crates/socket-patch-cli/tests/get_edge_cases_e2e.rs index eff3139e..5c87276d 100644 --- a/crates/socket-patch-cli/tests/get_edge_cases_e2e.rs +++ b/crates/socket-patch-cli/tests/get_edge_cases_e2e.rs @@ -32,6 +32,31 @@ async fn received_paths(mock: &MockServer) -> Vec { .collect() } +/// A single-file patch-view `files` map that survives PR #158's +/// "patch has no applicable files" guardrail (5d7eb6f): a fetched view +/// whose `files_for_manifest` map is empty is now an exit-1 failure, not a +/// silent `applied:1`. The tests below assert SELECTION / paid-token / +/// drift-warning / manifest-replacement behavior — the empty `"files": {}` +/// they used to carry was only ever a lazy stand-in, never the point. +/// +/// Modeled on the passing `get_invariants::patch_response_json` fixture: a +/// net-new file with an all-zero `beforeHash`, a real git-blob `afterHash` +/// (via the shared `common::git_sha256` oracle over the decoded blob), and +/// the matching base64 `blobContent`. These tests all pass `--save-only`, +/// which records without verifying content on disk, so one recordable file +/// is enough to make `files_for_manifest` non-empty and clear the guard. +fn single_file_view() -> serde_json::Value { + // base64 "cGF0Y2hlZAo=" decodes to exactly these bytes. + let blob_bytes = b"patched\n"; + serde_json::json!({ + "package/index.js": { + "beforeHash": "0000000000000000000000000000000000000000000000000000000000000000", + "afterHash": common::git_sha256(blob_bytes), + "blobContent": "cGF0Y2hlZAo=", + } + }) +} + #[test] fn get_one_off_and_save_only_together_errors() { // The two flags are mutually exclusive — using both must fail. @@ -100,7 +125,7 @@ async fn get_with_id_flag_selects_specific_patch() { "uuid": UUID_B, "purl": purl, "publishedAt": "2024-02-01T00:00:00Z", - "files": {}, + "files": single_file_view(), "vulnerabilities": {}, "description": "Second patch", "license": "MIT", @@ -405,7 +430,7 @@ async fn get_uuid_returns_paid_patch_with_token_succeeds() { "uuid": UUID_A, "purl": purl, "publishedAt": "2024-01-01T00:00:00Z", - "files": {}, + "files": single_file_view(), "vulnerabilities": {}, "description": "Paid patch with token access", "license": "MIT", @@ -496,7 +521,7 @@ async fn get_on_vendored_purl_warns_about_uuid_drift() { "uuid": UUID_B, "purl": purl, "publishedAt": "2024-02-01T00:00:00Z", - "files": {}, + "files": single_file_view(), "vulnerabilities": {}, "description": "Newer patch", "license": "MIT", @@ -583,7 +608,7 @@ async fn get_uuid_replacing_existing_manifest_entry_reports_updated() { "uuid": UUID_B, "purl": purl, "publishedAt": "2024-02-01T00:00:00Z", - "files": {}, + "files": single_file_view(), "vulnerabilities": {}, "description": "Newer patch for the same purl", "license": "MIT", From 28af3a022d2b62c1baf4a48acc95cbb97c948ea1 Mon Sep 17 00:00:00 2001 From: Mikola Lysenko Date: Thu, 13 Aug 2026 11:00:32 -0700 Subject: [PATCH 2/2] fix(test): repair telemetry_e2e fixture broken by #158 empty-files guardrail Same root cause as this PR's get_edge_cases_e2e fixes: #158's guardrail (empty applicable-files map -> "patch has no applicable files", exit 1) broke get_emits_patch_fetched_telemetry_on_uuid_lookup_success, whose mock patch-view used "files": {} while asserting a successful get. Give it a recordable new-file entry (afterHash = git-blob sha256 of the decoded blob) so the success + telemetry assertions hold; guardrail untouched. Verified with a full `cargo test --workspace --no-fail-fast` pass that these two binaries held the only 5 casualties, now all green. Co-Authored-By: Claude Opus 4.8 --- crates/socket-patch-cli/tests/telemetry_e2e.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/socket-patch-cli/tests/telemetry_e2e.rs b/crates/socket-patch-cli/tests/telemetry_e2e.rs index 5a40b7af..05df12ba 100644 --- a/crates/socket-patch-cli/tests/telemetry_e2e.rs +++ b/crates/socket-patch-cli/tests/telemetry_e2e.rs @@ -301,7 +301,16 @@ async fn get_emits_patch_fetched_telemetry_on_uuid_lookup_success() { "publishedAt": "2024-06-01T00:00:00Z", "license": "MIT", "description": "test patch", - "files": {}, + // A recordable new-file patch (afterHash is the git-blob sha256 of + // the decoded blobContent "patched\n"). Post-#158, a patch whose + // applicable-files map is empty is a hard failure ("no applicable + // files"), so the success path this test asserts needs a real file. + "files": { + "package/index.js": { + "afterHash": "d2802877eb1c2f442d30d18abcb281cb2830875571624544f2f1acb36480997e", + "blobContent": "cGF0Y2hlZAo=", + } + }, "vulnerabilities": {}, }); let mock = setup_mock(