fix(desktop): normalize ACP lock tarball URLs to the public npm registry

acp-tools.lock.json pinned Block's internal Artifactory host in all 24
tarball URL fields — internal infrastructure leaked into an OSS repo,
and anyone regenerating the lock against a different registry churned
every URL in the diff even when no pin changed. The URLs are
informational only: ensure-acp-tools.sh installs via the developer's
ambient npm registry and validates the registry-agnostic sha512
integrity from npm's package-lock, so no install path dereferences
them.

Normalize at write time instead: update-acp-tools-lock.mjs rebuilds
every tarball URL on https://registry.npmjs.org from the resolved
package name plus the registry-reported tarball basename (the basename
is not derivable from name@version alone — @openai/codex native
tarballs carry a platform suffix like codex-0.144.1-darwin-arm64.tgz).
A dist.tarball with no /-/ segment fails loudly rather than writing an
unnormalizable URL. The usage text documents the normalization, and the
committed lock is regenerated: the diff is exactly the 24 tarball
fields; every version and integrity hash is byte-identical.

Addresses the internal-Artifactory-URL finding from the bundling-series
code review (review 2ed3d00d on b52a665a).

Verification (ambient registry = Block Artifactory, proving
normalization against an internal mirror):
- Full regeneration: versions/integrity byte-identical to the previous
  lock; only tarball hosts changed.
- Partial --target aarch64-apple-darwin rerun on the normalized lock:
  byte-identical output (preserved + fresh entries agree).
- All normalized URL shapes probe live on registry.npmjs.org (303 CDN
  redirect), including the platform-suffixed codex native tarball.
- ensure-acp-tools.sh with the new lock: validates and no-op stages,
  exit 0 (the freshness stamp does not compare tarball fields, so no
  spurious re-install).
- pnpm exec biome check on the script: clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
This commit is contained in:
Matt Toohey
2026-07-15 13:52:14 +10:00
co-authored by Claude Fable 5
parent fbb9f1b94e
commit b991b35f33
2 changed files with 53 additions and 25 deletions
+24 -24
View File
@@ -7,7 +7,7 @@
"package": "@agentclientprotocol/claude-agent-acp",
"version": "0.58.1",
"integrity": "sha512-F1/W6EJdoYbrEUluRUknx0Nn0MAKDOkn2C/9YcP/joVkmdFUGTAxlGDpwdYu239TOkpc8Qm4+ffGsQjPZdryTg==",
"tarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@agentclientprotocol/claude-agent-acp/-/claude-agent-acp-0.58.1.tgz",
"tarball": "https://registry.npmjs.org/@agentclientprotocol/claude-agent-acp/-/claude-agent-acp-0.58.1.tgz",
"target": "aarch64-apple-darwin",
"npmOs": "darwin",
"npmCpu": "arm64",
@@ -15,13 +15,13 @@
"dependencyPackage": "@anthropic-ai/claude-agent-sdk",
"dependencyVersion": "0.3.205",
"dependencyIntegrity": "sha512-ft6iBw9kXudsusiXNpeybIPBJ07Z3tqp1ROSg5cEJqgA+9i+JJj2sRfQth+QD+lyenbbAU8yPieLxIimvfBhtw==",
"dependencyTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.205.tgz",
"dependencyTarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.205.tgz",
"claudeCodeVersion": "2.1.205",
"nativePackage": "@anthropic-ai/claude-agent-sdk-darwin-arm64",
"nativePackageName": "@anthropic-ai/claude-agent-sdk-darwin-arm64",
"nativeVersion": "0.3.205",
"nativeIntegrity": "sha512-lrfJ4eVtzfPkCpbSkBOGSMQCBbvmW6nbPzgHE4IwMN3scZlpuFMUFqh2aaJa/X2SAcWD9H2S0t2WWvSRgM7BjA==",
"nativeTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.205.tgz",
"nativeTarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-arm64/-/claude-agent-sdk-darwin-arm64-0.3.205.tgz",
"nativeExecutable": "claude"
},
{
@@ -31,7 +31,7 @@
"package": "@agentclientprotocol/claude-agent-acp",
"version": "0.58.1",
"integrity": "sha512-F1/W6EJdoYbrEUluRUknx0Nn0MAKDOkn2C/9YcP/joVkmdFUGTAxlGDpwdYu239TOkpc8Qm4+ffGsQjPZdryTg==",
"tarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@agentclientprotocol/claude-agent-acp/-/claude-agent-acp-0.58.1.tgz",
"tarball": "https://registry.npmjs.org/@agentclientprotocol/claude-agent-acp/-/claude-agent-acp-0.58.1.tgz",
"target": "aarch64-unknown-linux-gnu",
"npmOs": "linux",
"npmCpu": "arm64",
@@ -40,13 +40,13 @@
"dependencyPackage": "@anthropic-ai/claude-agent-sdk",
"dependencyVersion": "0.3.205",
"dependencyIntegrity": "sha512-ft6iBw9kXudsusiXNpeybIPBJ07Z3tqp1ROSg5cEJqgA+9i+JJj2sRfQth+QD+lyenbbAU8yPieLxIimvfBhtw==",
"dependencyTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.205.tgz",
"dependencyTarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.205.tgz",
"claudeCodeVersion": "2.1.205",
"nativePackage": "@anthropic-ai/claude-agent-sdk-linux-arm64",
"nativePackageName": "@anthropic-ai/claude-agent-sdk-linux-arm64",
"nativeVersion": "0.3.205",
"nativeIntegrity": "sha512-CXzySK3PV3EizCRPXnxPqeaAtgrBFDnMFOVpMe36oC3U16yDb1b1tAJGqZi/7uFrVvAiaXvnSFxhUWnDDSaO+A==",
"nativeTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.205.tgz",
"nativeTarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-arm64/-/claude-agent-sdk-linux-arm64-0.3.205.tgz",
"nativeExecutable": "claude"
},
{
@@ -56,7 +56,7 @@
"package": "@agentclientprotocol/claude-agent-acp",
"version": "0.58.1",
"integrity": "sha512-F1/W6EJdoYbrEUluRUknx0Nn0MAKDOkn2C/9YcP/joVkmdFUGTAxlGDpwdYu239TOkpc8Qm4+ffGsQjPZdryTg==",
"tarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@agentclientprotocol/claude-agent-acp/-/claude-agent-acp-0.58.1.tgz",
"tarball": "https://registry.npmjs.org/@agentclientprotocol/claude-agent-acp/-/claude-agent-acp-0.58.1.tgz",
"target": "x86_64-apple-darwin",
"npmOs": "darwin",
"npmCpu": "x64",
@@ -64,13 +64,13 @@
"dependencyPackage": "@anthropic-ai/claude-agent-sdk",
"dependencyVersion": "0.3.205",
"dependencyIntegrity": "sha512-ft6iBw9kXudsusiXNpeybIPBJ07Z3tqp1ROSg5cEJqgA+9i+JJj2sRfQth+QD+lyenbbAU8yPieLxIimvfBhtw==",
"dependencyTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.205.tgz",
"dependencyTarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.205.tgz",
"claudeCodeVersion": "2.1.205",
"nativePackage": "@anthropic-ai/claude-agent-sdk-darwin-x64",
"nativePackageName": "@anthropic-ai/claude-agent-sdk-darwin-x64",
"nativeVersion": "0.3.205",
"nativeIntegrity": "sha512-G6ETPmL5mNzJ2DFsWxG3jmsmrXgZX1N2ZCJvxaGUUpjTsKZJ4Tup1cWYvcd/m7o5fYZmx9REmgzTwsAIc1fdPQ==",
"nativeTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.205.tgz",
"nativeTarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-darwin-x64/-/claude-agent-sdk-darwin-x64-0.3.205.tgz",
"nativeExecutable": "claude"
},
{
@@ -80,7 +80,7 @@
"package": "@agentclientprotocol/claude-agent-acp",
"version": "0.58.1",
"integrity": "sha512-F1/W6EJdoYbrEUluRUknx0Nn0MAKDOkn2C/9YcP/joVkmdFUGTAxlGDpwdYu239TOkpc8Qm4+ffGsQjPZdryTg==",
"tarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@agentclientprotocol/claude-agent-acp/-/claude-agent-acp-0.58.1.tgz",
"tarball": "https://registry.npmjs.org/@agentclientprotocol/claude-agent-acp/-/claude-agent-acp-0.58.1.tgz",
"target": "x86_64-unknown-linux-gnu",
"npmOs": "linux",
"npmCpu": "x64",
@@ -89,13 +89,13 @@
"dependencyPackage": "@anthropic-ai/claude-agent-sdk",
"dependencyVersion": "0.3.205",
"dependencyIntegrity": "sha512-ft6iBw9kXudsusiXNpeybIPBJ07Z3tqp1ROSg5cEJqgA+9i+JJj2sRfQth+QD+lyenbbAU8yPieLxIimvfBhtw==",
"dependencyTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.205.tgz",
"dependencyTarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.205.tgz",
"claudeCodeVersion": "2.1.205",
"nativePackage": "@anthropic-ai/claude-agent-sdk-linux-x64",
"nativePackageName": "@anthropic-ai/claude-agent-sdk-linux-x64",
"nativeVersion": "0.3.205",
"nativeIntegrity": "sha512-siS+1iNqBSlGFZZvJY6+mhzZ/6/ec/TbX9GMuwmTF0E6fxGhIIp797jJxR1q8r6FAq7d39mEoRNhC0Ffo60uNQ==",
"nativeTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.205.tgz",
"nativeTarball": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk-linux-x64/-/claude-agent-sdk-linux-x64-0.3.205.tgz",
"nativeExecutable": "claude"
},
{
@@ -105,7 +105,7 @@
"package": "@agentclientprotocol/codex-acp",
"version": "1.1.2",
"integrity": "sha512-qE/R1WdqJJ9OFHsHGvbmVmS2j9iCMZzpWT3g2XIViXrGHu1fLOALLINBIlW+WzKDllCh131aB6cqcIWSt0otbw==",
"tarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@agentclientprotocol/codex-acp/-/codex-acp-1.1.2.tgz",
"tarball": "https://registry.npmjs.org/@agentclientprotocol/codex-acp/-/codex-acp-1.1.2.tgz",
"target": "aarch64-apple-darwin",
"npmOs": "darwin",
"npmCpu": "arm64",
@@ -113,12 +113,12 @@
"dependencyPackage": "@openai/codex",
"dependencyVersion": "0.144.1",
"dependencyIntegrity": "sha512-Xir1zqPfpenhdoAoshN53uonzbBXj18COyzRkFlVZpSNyEl5XtkuYu9oddELePFN7K/0sXUcSO34Ad5IeCXPbw==",
"dependencyTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@openai/codex/-/codex-0.144.1.tgz",
"dependencyTarball": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.1.tgz",
"nativePackage": "@openai/codex-darwin-arm64",
"nativePackageName": "@openai/codex",
"nativeVersion": "0.144.1-darwin-arm64",
"nativeIntegrity": "sha512-dABeDK+ATqMG54MGBd3VjpKfh5EOoqx9PKVQB2QYDaEXx3F6CdUCXue5QIMfr4OxziUj8pUcLAQyd+KFqiTUFw==",
"nativeTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@openai/codex/-/codex-0.144.1-darwin-arm64.tgz",
"nativeTarball": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.1-darwin-arm64.tgz",
"nativeExecutable": "vendor/aarch64-apple-darwin/bin/codex"
},
{
@@ -128,7 +128,7 @@
"package": "@agentclientprotocol/codex-acp",
"version": "1.1.2",
"integrity": "sha512-qE/R1WdqJJ9OFHsHGvbmVmS2j9iCMZzpWT3g2XIViXrGHu1fLOALLINBIlW+WzKDllCh131aB6cqcIWSt0otbw==",
"tarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@agentclientprotocol/codex-acp/-/codex-acp-1.1.2.tgz",
"tarball": "https://registry.npmjs.org/@agentclientprotocol/codex-acp/-/codex-acp-1.1.2.tgz",
"target": "aarch64-unknown-linux-gnu",
"npmOs": "linux",
"npmCpu": "arm64",
@@ -137,12 +137,12 @@
"dependencyPackage": "@openai/codex",
"dependencyVersion": "0.144.1",
"dependencyIntegrity": "sha512-Xir1zqPfpenhdoAoshN53uonzbBXj18COyzRkFlVZpSNyEl5XtkuYu9oddELePFN7K/0sXUcSO34Ad5IeCXPbw==",
"dependencyTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@openai/codex/-/codex-0.144.1.tgz",
"dependencyTarball": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.1.tgz",
"nativePackage": "@openai/codex-linux-arm64",
"nativePackageName": "@openai/codex",
"nativeVersion": "0.144.1-linux-arm64",
"nativeIntegrity": "sha512-451o15+XtaXCCb35t/KCyyPqXHnTPxPxtdqEYOnE3e4sH5AfnI/uVJwfdjOksMG6vRLy6R+fLvSDOMguRFLmQw==",
"nativeTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@openai/codex/-/codex-0.144.1-linux-arm64.tgz",
"nativeTarball": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.1-linux-arm64.tgz",
"nativeExecutable": "vendor/aarch64-unknown-linux-musl/bin/codex"
},
{
@@ -152,7 +152,7 @@
"package": "@agentclientprotocol/codex-acp",
"version": "1.1.2",
"integrity": "sha512-qE/R1WdqJJ9OFHsHGvbmVmS2j9iCMZzpWT3g2XIViXrGHu1fLOALLINBIlW+WzKDllCh131aB6cqcIWSt0otbw==",
"tarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@agentclientprotocol/codex-acp/-/codex-acp-1.1.2.tgz",
"tarball": "https://registry.npmjs.org/@agentclientprotocol/codex-acp/-/codex-acp-1.1.2.tgz",
"target": "x86_64-apple-darwin",
"npmOs": "darwin",
"npmCpu": "x64",
@@ -160,12 +160,12 @@
"dependencyPackage": "@openai/codex",
"dependencyVersion": "0.144.1",
"dependencyIntegrity": "sha512-Xir1zqPfpenhdoAoshN53uonzbBXj18COyzRkFlVZpSNyEl5XtkuYu9oddELePFN7K/0sXUcSO34Ad5IeCXPbw==",
"dependencyTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@openai/codex/-/codex-0.144.1.tgz",
"dependencyTarball": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.1.tgz",
"nativePackage": "@openai/codex-darwin-x64",
"nativePackageName": "@openai/codex",
"nativeVersion": "0.144.1-darwin-x64",
"nativeIntegrity": "sha512-K2g3Q3tNxzFhV0SuzO6HcsYK7EQrp/o4HyeReyhkwVrwwUPoYwyIbB0IRjHIiDzRhbKriDccid2iyF5aPqdTcg==",
"nativeTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@openai/codex/-/codex-0.144.1-darwin-x64.tgz",
"nativeTarball": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.1-darwin-x64.tgz",
"nativeExecutable": "vendor/x86_64-apple-darwin/bin/codex"
},
{
@@ -175,7 +175,7 @@
"package": "@agentclientprotocol/codex-acp",
"version": "1.1.2",
"integrity": "sha512-qE/R1WdqJJ9OFHsHGvbmVmS2j9iCMZzpWT3g2XIViXrGHu1fLOALLINBIlW+WzKDllCh131aB6cqcIWSt0otbw==",
"tarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@agentclientprotocol/codex-acp/-/codex-acp-1.1.2.tgz",
"tarball": "https://registry.npmjs.org/@agentclientprotocol/codex-acp/-/codex-acp-1.1.2.tgz",
"target": "x86_64-unknown-linux-gnu",
"npmOs": "linux",
"npmCpu": "x64",
@@ -184,12 +184,12 @@
"dependencyPackage": "@openai/codex",
"dependencyVersion": "0.144.1",
"dependencyIntegrity": "sha512-Xir1zqPfpenhdoAoshN53uonzbBXj18COyzRkFlVZpSNyEl5XtkuYu9oddELePFN7K/0sXUcSO34Ad5IeCXPbw==",
"dependencyTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@openai/codex/-/codex-0.144.1.tgz",
"dependencyTarball": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.1.tgz",
"nativePackage": "@openai/codex-linux-x64",
"nativePackageName": "@openai/codex",
"nativeVersion": "0.144.1-linux-x64",
"nativeIntegrity": "sha512-HNGVI+BulrOaC/0IzBvd6EL62j7LrlbFKibrhw6hZjjCjAeUYzRB2jB4qDzXN1NfqDi6Xrvniof3kwbwab24lg==",
"nativeTarball": "https://global.block-artifacts.com/artifactory/api/npm/square-npm/@openai/codex/-/codex-0.144.1-linux-x64.tgz",
"nativeTarball": "https://registry.npmjs.org/@openai/codex/-/codex-0.144.1-linux-x64.tgz",
"nativeExecutable": "vendor/x86_64-unknown-linux-musl/bin/codex"
}
]
+29 -1
View File
@@ -91,6 +91,13 @@ const NPM_TARGET_CONFIG = {
},
};
// Tarball URLs in the lock are informational — ensure-acp-tools.sh installs
// via the ambient npm registry and validates the registry-agnostic sha512
// integrity. Normalize them to the public registry so regenerating against an
// internal mirror (e.g. Artifactory) neither leaks internal hosts into the
// committed lock nor churns every URL in the diff.
const PUBLIC_NPM_REGISTRY = "https://registry.npmjs.org";
const npmViewCache = new Map();
const execFileAsync = promisify(execFile);
@@ -106,6 +113,10 @@ A --target run regenerates only the selected targets; the existing lock's
entries for every other target are preserved verbatim, so a partial bump
never drops another target's pins.
Tarball URLs are normalized to ${PUBLIC_NPM_REGISTRY} regardless of the
registry that resolved the metadata, so regeneration is deterministic across
environments and internal mirror hosts never land in the committed lock.
Supported targets:
${SUPPORTED_TARGETS.join("\n ")}
@@ -178,10 +189,27 @@ function requireString(value, label) {
return value;
}
// Rebuild the tarball URL on PUBLIC_NPM_REGISTRY, keeping the registry's
// `<package>/-/<basename>.tgz` path (the basename is not always derivable
// from name@version — @openai/codex native tarballs carry a platform suffix).
function normalizeTarballUrl(tarball, packageName, label) {
const separator = "/-/";
const separatorIndex = tarball.lastIndexOf(separator);
if (separatorIndex === -1) {
throw new Error(`Cannot normalize ${label} tarball URL: ${tarball}`);
}
const basename = tarball.slice(separatorIndex + separator.length);
return `${PUBLIC_NPM_REGISTRY}/${packageName}/-/${basename}`;
}
function packageDist(metadata, label) {
const dist = metadata?.dist;
return {
tarball: requireString(dist?.tarball, `${label} dist.tarball`),
tarball: normalizeTarballUrl(
requireString(dist?.tarball, `${label} dist.tarball`),
requireString(metadata?.name, `${label} name`),
label,
),
integrity: requireString(dist?.integrity, `${label} dist.integrity`),
};
}