← back to Homesonspec
mobile: make the tracker-drift canary baseline-aware (was firing on steady state)
ba37b54c863feed2dc7bd3229cae79559b938388 · 2026-09-04 11:53:46 -0700 · Steve
As first written the canary exited 1 whenever ANY uncovered third-party host was
present — which is permanently true, because homesonspec.com serves listing photos
from www.drhorton.com and awh.widen.net. A canary that fires on the steady state is
noise and gets ignored, which is the one failure mode that makes it worthless.
Now baseline-aware, per house canary doctrine: known-benign hosts live in
tracker-drift-baseline.json, are reported as 'accepted', and do NOT fail. Exit 1
fires only on a host that is NEW since the baseline — an actual worsening transition.
Adds --accept to fold a newly verified asset host into the baseline.
Baseline seeded with the two hosts verified 2026-09-04 by inspecting the page source:
both appear only as <img src> listing photos (D.R. Horton product catalogue, Widen
DAM CDN), so they are asset hosts, not trackers.
Verified both directions, not just the quiet one:
steady state -> PASS, exit 0
simulated new host -> FAIL, names www.drhorton.com, exit 1
baseline restored -> PASS, exit 0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEhnWQSSkAhSYxWXHJ3MCw
Files touched
A apps/mobile/scripts/tracker-drift-baseline.jsonM apps/mobile/scripts/tracker-drift-check.mjs
Diff
commit ba37b54c863feed2dc7bd3229cae79559b938388
Author: Steve <steve@designerwallcoverings.com>
Date: Fri Sep 4 11:53:46 2026 -0700
mobile: make the tracker-drift canary baseline-aware (was firing on steady state)
As first written the canary exited 1 whenever ANY uncovered third-party host was
present — which is permanently true, because homesonspec.com serves listing photos
from www.drhorton.com and awh.widen.net. A canary that fires on the steady state is
noise and gets ignored, which is the one failure mode that makes it worthless.
Now baseline-aware, per house canary doctrine: known-benign hosts live in
tracker-drift-baseline.json, are reported as 'accepted', and do NOT fail. Exit 1
fires only on a host that is NEW since the baseline — an actual worsening transition.
Adds --accept to fold a newly verified asset host into the baseline.
Baseline seeded with the two hosts verified 2026-09-04 by inspecting the page source:
both appear only as <img src> listing photos (D.R. Horton product catalogue, Widen
DAM CDN), so they are asset hosts, not trackers.
Verified both directions, not just the quiet one:
steady state -> PASS, exit 0
simulated new host -> FAIL, names www.drhorton.com, exit 1
baseline restored -> PASS, exit 0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEhnWQSSkAhSYxWXHJ3MCw
---
apps/mobile/scripts/tracker-drift-baseline.json | 7 ++++
apps/mobile/scripts/tracker-drift-check.mjs | 43 +++++++++++++++++++------
2 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/apps/mobile/scripts/tracker-drift-baseline.json b/apps/mobile/scripts/tracker-drift-baseline.json
new file mode 100644
index 00000000..42cf2cac
--- /dev/null
+++ b/apps/mobile/scripts/tracker-drift-baseline.json
@@ -0,0 +1,7 @@
+{
+ "acceptedHosts": [
+ "awh.widen.net",
+ "www.drhorton.com"
+ ],
+ "note": "Verified 2026-09-04 (TK-11155) by inspecting homesonspec.com source: both appear only as <img src> listing photos \u2014 D.R. Horton's product catalogue and the Widen DAM CDN. Asset hosts, not trackers. Re-verify if their usage ever changes."
+}
\ No newline at end of file
diff --git a/apps/mobile/scripts/tracker-drift-check.mjs b/apps/mobile/scripts/tracker-drift-check.mjs
index 5529aa70..8b917b2d 100644
--- a/apps/mobile/scripts/tracker-drift-check.mjs
+++ b/apps/mobile/scripts/tracker-drift-check.mjs
@@ -10,15 +10,26 @@
* On an account already cited under Guideline 5.6 for a declaration that did not match a
* binary, that is the drift we cannot afford. This flags it.
*
- * READ-ONLY. Exit 0 = clean, 1 = drift found. Usage: node scripts/tracker-drift-check.mjs
+ * BASELINE-AWARE (house canary doctrine): a canary that fires on the steady state is
+ * noise and gets ignored. Known-benign third-party hosts (listing-photo CDNs) live in
+ * tracker-drift-baseline.json and are reported but do NOT fail. Exit 1 fires only on a
+ * host that is NEW since the baseline — i.e. an actual worsening transition.
+ *
+ * READ-ONLY. Exit 0 = no new hosts, 1 = NEW uncovered host. node scripts/tracker-drift-check.mjs
+ * --accept after verifying a flagged host is a harmless asset/CDN, add it to the baseline
*/
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
+import { existsSync, writeFileSync } from 'node:fs';
const here = dirname(fileURLToPath(import.meta.url));
const policy = readFileSync(join(here, '..', 'lib', 'tracker-policy.ts'), 'utf8');
const DENYLIST = [...policy.matchAll(/'([a-z0-9.-]+\.[a-z]{2,})'/g)].map(m => m[1]);
+const BASELINE_PATH = join(here, 'tracker-drift-baseline.json');
+const baseline = existsSync(BASELINE_PATH)
+ ? JSON.parse(readFileSync(BASELINE_PATH, 'utf8'))
+ : { acceptedHosts: [], note: '' };
const SITE = process.env.HOS_SITE || 'https://homesonspec.com';
const FIRST_PARTY = new URL(SITE).hostname.replace(/^www\./, '');
@@ -33,16 +44,28 @@ const hosts = [...new Set([...html.matchAll(/https?:\/\/([a-z0-9.-]+)/gi)].map(m
const uncovered = hosts.filter(h => !isFirstParty(h) && !onDenylist(h));
const covered = hosts.filter(onDenylist);
+const accepted = uncovered.filter(h => baseline.acceptedHosts.includes(h));
+const novel = uncovered.filter(h => !baseline.acceptedHosts.includes(h));
+
+if (process.argv.includes('--accept')) {
+ const merged = [...new Set([...baseline.acceptedHosts, ...uncovered])].sort();
+ writeFileSync(BASELINE_PATH, JSON.stringify({ ...baseline, acceptedHosts: merged }, null, 2) + '\n');
+ console.log(`baseline updated — ${merged.length} accepted host(s): ${merged.join(', ')}`);
+ process.exit(0);
+}
+
console.log(`site: ${SITE}`);
console.log(`denylist (${DENYLIST.length}): ${DENYLIST.join(', ')}`);
-console.log(`\nBLOCKED third-party hosts present on the page (${covered.length}): ${covered.join(', ') || '(none)'}`);
-console.log(`\nUNCOVERED third-party hosts — these would NOT be blocked (${uncovered.length}):`);
-uncovered.forEach(h => console.log(` ⚠️ ${h}`));
-
-if (uncovered.length) {
- console.log(`\nVERDICT: WARN — review each host above. If any transmits user/usage data, the`);
- console.log(`"Data Not Collected" label is no longer accurate: add it to TRACKER_HOSTS and rebuild,`);
- console.log(`or amend the App Privacy label. Purely static asset/CDN/font hosts are fine.`);
+console.log(`\nBLOCKED trackers present on the page (${covered.length}): ${covered.join(', ') || '(none)'}`);
+console.log(`accepted asset hosts, baselined (${accepted.length}): ${accepted.join(', ') || '(none)'}`);
+
+if (novel.length) {
+ console.log(`\nNEW uncovered third-party host(s) — NOT blocked, NOT baselined (${novel.length}):`);
+ novel.forEach(h => console.log(` \u26a0\ufe0f ${h}`));
+ console.log(`\nVERDICT: FAIL — a third-party host appeared that the blocker does not cover.`);
+ console.log(`If it transmits user/usage data, "Data Not Collected" is no longer accurate:`);
+ console.log(`add it to TRACKER_HOSTS and REBUILD, or amend the App Privacy label.`);
+ console.log(`If it is a harmless asset/CDN/font host, verify it then run with --accept.`);
process.exit(1);
}
-console.log('\nVERDICT: PASS — every third-party host on the page is covered by the denylist.');
+console.log(`\nVERDICT: PASS — every tracker on the page is blocked, and no new third-party host has appeared.`);
← 693125b2 mobile: add tracker-drift canary guarding the 'Data Not Coll
·
back to Homesonspec
·
snapshot before restart: preserve in-flight work aaf2c487 →