[aidan] fix/affiliate-scan: tolerate future mtimes + cover win32 and all artifact shapes

The Downloads scan rejected any file whose mtime was newer than the scan's
Date.now() snapshot (sub-ms fs timestamps, NTP stepping the clock back), and
the ambiguity test was green only because both fixtures were skipped by that
guard. Allow 60s of future skew, add a win32 end-to-end bind test, and cover
every stamped artifact name (mac arm64/x64 dmg, windows setup exe, linux
AppImages) plus unstamped negatives in the parser test.
This commit is contained in:
abccodes
2026-07-10 18:51:04 -07:00
parent c7004c9878
commit 1e1d0d3c60
2 changed files with 55 additions and 1 deletions
+5 -1
View File
@@ -41,6 +41,10 @@ const FILENAME_ATTRIBUTION_WINDOW_MS =
Number(process.env.OPENSWARM_AFFILIATE_FILENAME_WINDOW_MS) || 30 * 24 * 60 * 60 * 1000;
const INSTALLER_HASH_RE =
/^OpenSwarm(?:-Setup)?-(?:arm64|x64)-([A-Za-z0-9_-]{16,32})(?: \([0-9]+\))?\.(dmg|exe|AppImage)$/i;
// A file whose mtime is slightly in the future is NOT suspicious: APFS/NTFS
// keep sub-ms timestamps, and NTP can step the clock backwards between the
// download and first launch. Only skip files more than a minute ahead.
const FUTURE_MTIME_TOLERANCE_MS = 60 * 1000;
function getStateFilePath(userDataDir) {
return path.join(userDataDir, "install.json");
@@ -214,7 +218,7 @@ function recentInstallerHashesInDir(dir, nowMs) {
try {
const st = fs.statSync(fullPath);
const ageMs = nowMs - st.mtimeMs;
if (ageMs < 0 || ageMs > FILENAME_ATTRIBUTION_WINDOW_MS) continue;
if (ageMs < -FUTURE_MTIME_TOLERANCE_MS || ageMs > FILENAME_ATTRIBUTION_WINDOW_MS) continue;
out.push({ hash, path: fullPath, mtimeMs: st.mtimeMs });
} catch (_) {}
}
+50
View File
@@ -297,6 +297,56 @@ test("filename parser keeps hyphens inside base64url affiliate hash", () => {
);
});
test("filename parser covers every stamped artifact shape (mac/win/linux)", () => {
const h = "abcDEF1234567890_hash";
for (const name of [
`OpenSwarm-arm64-${h}.dmg`, // mac Apple Silicon
`OpenSwarm-x64-${h}.dmg`, // mac Intel
`OpenSwarm-Setup-x64-${h}.exe`, // windows squirrel setup
`OpenSwarm-x64-${h}.AppImage`, // linux x64
`OpenSwarm-arm64-${h}.AppImage`, // linux arm64
]) {
assert.equal(affiliateTracking._hashFromInstallerBasename(name), h, name);
}
// Unstamped artifacts must NOT parse as carrying a hash.
for (const name of ["OpenSwarm-arm64.dmg", "OpenSwarm-Setup-x64.exe", "OpenSwarm-x64.AppImage"]) {
assert.equal(affiliateTracking._hashFromInstallerBasename(name), null, name);
}
});
test("first launch (win32): stamped setup exe in Downloads binds before welcome URL", async () => {
const cloud = await makeMockCloud();
try {
const userDataDir = makeTempUserDataDir();
const shell = makeFakeShell();
const hash = "abcDEF1234567890_hash";
cloud.filenameHashes.set(hash, "windows-affiliate");
const downloads = path.join(userDataDir, "Downloads");
fs.mkdirSync(downloads, { recursive: true });
fs.writeFileSync(path.join(downloads, `OpenSwarm-Setup-x64-${hash}.exe`), "");
process.env.OPENSWARM_AFFILIATE_LANDING_URL = "https://landing.test";
process.env.OPENSWARM_AFFILIATE_CLOUD_URL = cloud.url;
await affiliateTracking.maybeRunFirstLaunchHandshake({
shell,
userDataDir,
isDev: false,
isPackaged: true,
platform: "win32",
homeDir: userDataDir,
});
assert.equal(shell.opened.length, 0, "filename hash bind skips welcome URL");
const state = readJson(path.join(userDataDir, "install.json"));
assert.equal(state.ref, "windows-affiliate");
assert.equal(state.ref_bind_method, "affiliate_filename_hash");
} finally {
await cloud.close();
}
});
test("download scan refuses ambiguous stamped installers", () => {
const userDataDir = makeTempUserDataDir();
const downloads = path.join(userDataDir, "Downloads");