@dreamdata_io/verify-tracking 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +756 -0
  3. package/dist/ai/checker.js +222 -0
  4. package/dist/ai/checker.js.map +1 -0
  5. package/dist/ai/checklist.js +190 -0
  6. package/dist/ai/checklist.js.map +1 -0
  7. package/dist/ai/cli-presets.js +27 -0
  8. package/dist/ai/cli-presets.js.map +1 -0
  9. package/dist/ai/evidence-view.js +143 -0
  10. package/dist/ai/evidence-view.js.map +1 -0
  11. package/dist/ai/local-cli.js +58 -0
  12. package/dist/ai/local-cli.js.map +1 -0
  13. package/dist/ai/openai-compatible.js +78 -0
  14. package/dist/ai/openai-compatible.js.map +1 -0
  15. package/dist/ai/response-parser.js +105 -0
  16. package/dist/ai/response-parser.js.map +1 -0
  17. package/dist/ai/types.js +2 -0
  18. package/dist/ai/types.js.map +1 -0
  19. package/dist/analysis/consent-mode.js +225 -0
  20. package/dist/analysis/consent-mode.js.map +1 -0
  21. package/dist/analysis/deployment.js +2658 -0
  22. package/dist/analysis/deployment.js.map +1 -0
  23. package/dist/analysis/diagnosis/copy.en.js +303 -0
  24. package/dist/analysis/diagnosis/copy.en.js.map +1 -0
  25. package/dist/analysis/diagnosis/diagnose.js +172 -0
  26. package/dist/analysis/diagnosis/diagnose.js.map +1 -0
  27. package/dist/analysis/diagnosis/docs.js +118 -0
  28. package/dist/analysis/diagnosis/docs.js.map +1 -0
  29. package/dist/analysis/diagnosis/index.js +5 -0
  30. package/dist/analysis/diagnosis/index.js.map +1 -0
  31. package/dist/analysis/diagnosis/rules.js +656 -0
  32. package/dist/analysis/diagnosis/rules.js.map +1 -0
  33. package/dist/analysis/diagnosis/types.js +2 -0
  34. package/dist/analysis/diagnosis/types.js.map +1 -0
  35. package/dist/cli.js +344 -0
  36. package/dist/cli.js.map +1 -0
  37. package/dist/config/env.js +100 -0
  38. package/dist/config/env.js.map +1 -0
  39. package/dist/config/preflight.js +167 -0
  40. package/dist/config/preflight.js.map +1 -0
  41. package/dist/config/user-config.js +79 -0
  42. package/dist/config/user-config.js.map +1 -0
  43. package/dist/evidence/collect.js +527 -0
  44. package/dist/evidence/collect.js.map +1 -0
  45. package/dist/evidence/consent-accept.js +377 -0
  46. package/dist/evidence/consent-accept.js.map +1 -0
  47. package/dist/evidence/consent.js +340 -0
  48. package/dist/evidence/consent.js.map +1 -0
  49. package/dist/evidence/constants.js +615 -0
  50. package/dist/evidence/constants.js.map +1 -0
  51. package/dist/evidence/globals.js +132 -0
  52. package/dist/evidence/globals.js.map +1 -0
  53. package/dist/evidence/gtm-container.js +432 -0
  54. package/dist/evidence/gtm-container.js.map +1 -0
  55. package/dist/evidence/heuristic-banner.js +107 -0
  56. package/dist/evidence/heuristic-banner.js.map +1 -0
  57. package/dist/evidence/http-probe.js +139 -0
  58. package/dist/evidence/http-probe.js.map +1 -0
  59. package/dist/evidence/init-script.js +112 -0
  60. package/dist/evidence/init-script.js.map +1 -0
  61. package/dist/evidence/network.js +365 -0
  62. package/dist/evidence/network.js.map +1 -0
  63. package/dist/evidence/preference-center.js +368 -0
  64. package/dist/evidence/preference-center.js.map +1 -0
  65. package/dist/evidence/script.js +425 -0
  66. package/dist/evidence/script.js.map +1 -0
  67. package/dist/evidence/second-page.js +332 -0
  68. package/dist/evidence/second-page.js.map +1 -0
  69. package/dist/evidence/selector-probe.js +53 -0
  70. package/dist/evidence/selector-probe.js.map +1 -0
  71. package/dist/evidence/stealth.js +21 -0
  72. package/dist/evidence/stealth.js.map +1 -0
  73. package/dist/evidence/types.js +14 -0
  74. package/dist/evidence/types.js.map +1 -0
  75. package/dist/interactive/prompt.js +31 -0
  76. package/dist/interactive/prompt.js.map +1 -0
  77. package/dist/mcp/server.js +308 -0
  78. package/dist/mcp/server.js.map +1 -0
  79. package/dist/mcp/summary.js +41 -0
  80. package/dist/mcp/summary.js.map +1 -0
  81. package/dist/report/context.js +184 -0
  82. package/dist/report/context.js.map +1 -0
  83. package/dist/report/projection.js +125 -0
  84. package/dist/report/projection.js.map +1 -0
  85. package/dist/report/quote-check.js +90 -0
  86. package/dist/report/quote-check.js.map +1 -0
  87. package/dist/report/render.js +178 -0
  88. package/dist/report/render.js.map +1 -0
  89. package/dist/report/serializers.js +124 -0
  90. package/dist/report/serializers.js.map +1 -0
  91. package/dist/report/store.js +139 -0
  92. package/dist/report/store.js.map +1 -0
  93. package/dist/run/verify.js +77 -0
  94. package/dist/run/verify.js.map +1 -0
  95. package/dist/utils/duration.js +10 -0
  96. package/dist/utils/duration.js.map +1 -0
  97. package/dist/utils/errors.js +17 -0
  98. package/dist/utils/errors.js.map +1 -0
  99. package/dist/utils/logger.js +59 -0
  100. package/dist/utils/logger.js.map +1 -0
  101. package/dist/utils/runTimingsLog.js +27 -0
  102. package/dist/utils/runTimingsLog.js.map +1 -0
  103. package/dist/utils/slug.js +27 -0
  104. package/dist/utils/slug.js.map +1 -0
  105. package/dist/version.js +10 -0
  106. package/dist/version.js.map +1 -0
  107. package/package.json +57 -0
  108. package/scripts/install.sh +314 -0
@@ -0,0 +1,314 @@
1
+ #!/bin/sh
2
+ #
3
+ # One-command install for verify-tracking, for a machine with nothing on it.
4
+ #
5
+ # curl -fsSL https://unpkg.com/@dreamdata_io/verify-tracking/scripts/install.sh | sh
6
+ #
7
+ # The npm package is the same artifact either way; this script exists because
8
+ # the people who need the tool most — CS, not engineers — have no Node, no npm,
9
+ # no Chromium and no Claude Code CLI, and "install Node first" is where a
10
+ # handover stops. So everything the run needs is fetched here, into one
11
+ # directory that `rm -rf` undoes, without sudo and without touching a
12
+ # system-wide npm prefix.
13
+ #
14
+ # The one step that cannot be automated is the Claude sign-in: it is an OAuth
15
+ # flow through a browser, and no script can hold someone's credentials for
16
+ # them. It is *driven* from here instead — the installer checks the auth state
17
+ # and hands over to `claude auth login` on the terminal, so the operator
18
+ # finishes in the same sitting rather than discovering the requirement on a
19
+ # failed first run.
20
+ set -eu
21
+
22
+ PKG="@dreamdata_io/verify-tracking"
23
+ PKG_VERSION="${VERIFY_TRACKING_VERSION:-latest}"
24
+ # Whatever npm should install to get the package. Overridable so a release
25
+ # candidate can be installed from a local tarball — the one-liner itself can
26
+ # only ever test what is already on the registry, which is the previous
27
+ # release.
28
+ PKG_SPEC="${VERIFY_TRACKING_PKG_SPEC:-$PKG@$PKG_VERSION}"
29
+ CLAUDE_PKG="@anthropic-ai/claude-code"
30
+
31
+ # Pinned rather than "latest LTS": an installer that silently changes runtime
32
+ # between two colleagues' machines makes a bug report unreproducible.
33
+ NODE_VERSION="${VERIFY_TRACKING_NODE_VERSION:-v24.21.0}"
34
+ NODE_DIST="${VERIFY_TRACKING_NODE_DIST:-https://nodejs.org/dist}"
35
+
36
+ # Everything this installer writes lives under these two paths, and nothing
37
+ # else does. PREFIX holds the runtime, the packages and the browser; BIN_DIR
38
+ # gets the two shims that are the whole user-facing surface.
39
+ PREFIX="${VERIFY_TRACKING_PREFIX:-$HOME/.local/share/verify-tracking}"
40
+ BIN_DIR="${VERIFY_TRACKING_BIN_DIR:-$HOME/.local/bin}"
41
+
42
+ # Kept out of the shared ~/.cache/ms-playwright on purpose: the browser this
43
+ # installer downloaded is then provably the browser the run launches, and an
44
+ # uninstall takes its 150MB with it instead of orphaning them.
45
+ BROWSERS_DIR="$PREFIX/browsers"
46
+
47
+ say() { printf ' %s\n' "$1"; }
48
+ step() { printf '\n==> %s\n' "$1"; }
49
+ die() { printf '\nverify-tracking install failed: %s\n\n' "$1" >&2; exit 1; }
50
+
51
+ # ---------------------------------------------------------------------------
52
+ # Platform
53
+ # ---------------------------------------------------------------------------
54
+
55
+ os="$(uname -s)"
56
+ arch="$(uname -m)"
57
+ case "$os" in
58
+ Darwin) node_os="darwin" ;;
59
+ Linux) node_os="linux" ;;
60
+ *) die "unsupported OS: $os. macOS and Linux only — on Windows, install Node 20+ and run: npx -y $PKG@latest" ;;
61
+ esac
62
+ case "$arch" in
63
+ arm64|aarch64) node_arch="arm64" ;;
64
+ x86_64|amd64) node_arch="x64" ;;
65
+ *) die "unsupported CPU: $arch." ;;
66
+ esac
67
+
68
+ command -v curl >/dev/null 2>&1 || die "curl is required."
69
+ command -v tar >/dev/null 2>&1 || die "tar is required."
70
+
71
+ printf 'Installing verify-tracking (%s/%s)\n' "$node_os" "$node_arch"
72
+ say "runtime, packages and browser -> $PREFIX"
73
+ say "commands -> $BIN_DIR"
74
+
75
+ # ---------------------------------------------------------------------------
76
+ # 1. A Node the tool can run on
77
+ # ---------------------------------------------------------------------------
78
+
79
+ # Reused rather than replaced when the host already has a new enough one: a
80
+ # second Node in someone's home directory is 60MB and a support question, and
81
+ # the package is plain compiled JS that does not care whose Node runs it.
82
+ host_node_is_usable() {
83
+ command -v node >/dev/null 2>&1 || return 1
84
+ command -v npm >/dev/null 2>&1 || return 1
85
+ major="$(node -p 'process.versions.node.split(".")[0]' 2>/dev/null || echo 0)"
86
+ [ "$major" -ge 20 ] 2>/dev/null
87
+ }
88
+
89
+ sha256_of() {
90
+ if command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | awk '{print $1}'
91
+ elif command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | awk '{print $1}'
92
+ else die "need shasum or sha256sum to verify the Node download."
93
+ fi
94
+ }
95
+
96
+ install_node() {
97
+ name="node-$NODE_VERSION-$node_os-$node_arch"
98
+ url="$NODE_DIST/$NODE_VERSION/$name.tar.gz"
99
+ tmp="$(mktemp -d)"
100
+ # A failed or interrupted download never leaves a half-unpacked runtime
101
+ # where a working one is expected.
102
+ trap 'rm -rf "$tmp"' EXIT
103
+
104
+ say "downloading $NODE_VERSION (~60MB)"
105
+ curl -fsSL --retry 3 -o "$tmp/$name.tar.gz" "$url" || die "could not download $url"
106
+
107
+ # nodejs.org publishes checksums for exactly this reason; bytes that arrive
108
+ # over a hijacked or truncated transfer are not unpacked and executed.
109
+ say "verifying checksum"
110
+ curl -fsSL --retry 3 -o "$tmp/SHASUMS256.txt" "$NODE_DIST/$NODE_VERSION/SHASUMS256.txt" \
111
+ || die "could not download the Node checksums. Refusing to install unverified bytes."
112
+ expected="$(awk -v f="$name.tar.gz" '$2 == f || $2 == "./"f {print $1}' "$tmp/SHASUMS256.txt")"
113
+ [ -n "$expected" ] || die "no published checksum for $name.tar.gz."
114
+ actual="$(sha256_of "$tmp/$name.tar.gz")"
115
+ [ "$expected" = "$actual" ] || die "checksum mismatch for $name.tar.gz. Not installing."
116
+
117
+ say "unpacking"
118
+ rm -rf "$PREFIX/node"
119
+ mkdir -p "$PREFIX/node"
120
+ tar -xzf "$tmp/$name.tar.gz" -C "$PREFIX/node" --strip-components=1 \
121
+ || die "could not unpack $name.tar.gz"
122
+
123
+ rm -rf "$tmp"
124
+ trap - EXIT
125
+ }
126
+
127
+ step "Node runtime"
128
+ if host_node_is_usable; then
129
+ say "using the Node already installed ($(node -v))"
130
+ NODE="$(command -v node)"
131
+ NPM="$(command -v npm)"
132
+ elif [ -x "$PREFIX/node/bin/node" ]; then
133
+ say "using the Node this installer downloaded earlier ($("$PREFIX/node/bin/node" -v))"
134
+ NODE="$PREFIX/node/bin/node"
135
+ NPM="$PREFIX/node/bin/npm"
136
+ else
137
+ say "no Node 20+ on this machine — fetching a private one"
138
+ install_node
139
+ NODE="$PREFIX/node/bin/node"
140
+ NPM="$PREFIX/node/bin/npm"
141
+ fi
142
+
143
+ # npm from an unpacked tarball is a script that wants `node` on the PATH, and
144
+ # on a machine with no system Node there is none. Every npm call below runs
145
+ # through this.
146
+ run_npm() {
147
+ PATH="$PREFIX/node/bin:$PATH" "$NPM" "$@"
148
+ }
149
+
150
+ # ---------------------------------------------------------------------------
151
+ # 2. The tool, and the Claude Code CLI it asks for its answers
152
+ # ---------------------------------------------------------------------------
153
+
154
+ # --prefix keeps both out of any global npm root: no sudo, no fighting a
155
+ # system-managed node_modules, and an uninstall that is one rm -rf.
156
+ step "verify-tracking $PKG_VERSION"
157
+ mkdir -p "$PREFIX/lib"
158
+ run_npm install --prefix "$PREFIX/lib" --no-audit --no-fund --loglevel=error "$PKG_SPEC" \
159
+ || die "npm could not install $PKG_SPEC"
160
+
161
+ PKG_ROOT="$PREFIX/lib/node_modules/$PKG"
162
+ [ -f "$PKG_ROOT/dist/cli.js" ] || die "the installed package has no dist/cli.js — expected at $PKG_ROOT"
163
+
164
+ step "Claude Code CLI"
165
+ if command -v claude >/dev/null 2>&1; then
166
+ say "using the claude already on your PATH"
167
+ CLAUDE="$(command -v claude)"
168
+ else
169
+ say "installing $CLAUDE_PKG"
170
+ run_npm install --prefix "$PREFIX/lib" --no-audit --no-fund --loglevel=error "$CLAUDE_PKG" \
171
+ || die "npm could not install $CLAUDE_PKG"
172
+ CLAUDE="$PREFIX/lib/node_modules/.bin/claude"
173
+ [ -x "$CLAUDE" ] || die "expected a claude executable at $CLAUDE"
174
+ fi
175
+
176
+ # ---------------------------------------------------------------------------
177
+ # 3. A browser to drive
178
+ # ---------------------------------------------------------------------------
179
+
180
+ # The collector launches an installed Google Chrome first and only falls back
181
+ # to Playwright's own Chromium, so a machine with Chrome needs none of this.
182
+ # Mirrors src/config/preflight.ts — if that list grows, this one should too.
183
+ has_chrome() {
184
+ for p in \
185
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
186
+ "/opt/google/chrome/chrome" \
187
+ "/usr/bin/google-chrome" \
188
+ "/usr/bin/google-chrome-stable"
189
+ do
190
+ if [ -x "$p" ]; then return 0; fi
191
+ done
192
+ return 1
193
+ }
194
+
195
+ step "Browser"
196
+ if has_chrome && [ "${VERIFY_TRACKING_FORCE_CHROMIUM:-0}" != "1" ]; then
197
+ say "Google Chrome is installed — nothing to download"
198
+ say "(set VERIFY_TRACKING_FORCE_CHROMIUM=1 to fetch Playwright's Chromium anyway)"
199
+ else
200
+ say "downloading Chromium (~150MB, once)"
201
+ # The package's own Playwright, so the browser revision matches the client
202
+ # that will drive it. A mismatched pair fails at launch, not at install.
203
+ PLAYWRIGHT_BROWSERS_PATH="$BROWSERS_DIR" PATH="$PREFIX/node/bin:$PATH" \
204
+ "$NODE" "$PREFIX/lib/node_modules/playwright/cli.js" install chromium \
205
+ || die "could not download Chromium. Install Google Chrome instead (https://www.google.com/chrome/) and re-run this installer."
206
+ fi
207
+
208
+ # ---------------------------------------------------------------------------
209
+ # 4. Shims
210
+ # ---------------------------------------------------------------------------
211
+
212
+ # A shim rather than a symlink, because the run needs an environment: its own
213
+ # Node, `claude` findable on the PATH (local-cli.ts spawns it by name), and the
214
+ # browser directory this installer actually filled.
215
+ write_shim() {
216
+ shim="$BIN_DIR/$1"
217
+ entry="$2"
218
+ cat > "$shim" <<SHIM
219
+ #!/bin/sh
220
+ # Generated by the verify-tracking installer. Re-run the installer to update;
221
+ # edits here are overwritten.
222
+ PREFIX="$PREFIX"
223
+ export PATH="\$PREFIX/node/bin:\$PREFIX/lib/node_modules/.bin:\$PATH"
224
+ export PLAYWRIGHT_BROWSERS_PATH="\${PLAYWRIGHT_BROWSERS_PATH:-$BROWSERS_DIR}"
225
+
226
+ # The Node this was installed against, with a fallback: a version manager can
227
+ # retire the exact path under us, and any Node 20+ runs this package fine.
228
+ NODE="$NODE"
229
+ if [ ! -x "\$NODE" ]; then
230
+ NODE="\$(command -v node 2>/dev/null || true)"
231
+ fi
232
+ if [ ! -x "\$NODE" ]; then
233
+ printf 'verify-tracking: no Node runtime found. Re-run the installer:\\n' >&2
234
+ printf ' curl -fsSL https://unpkg.com/%s/scripts/install.sh | sh\\n' "$PKG" >&2
235
+ exit 1
236
+ fi
237
+
238
+ exec "\$NODE" "\$PREFIX/lib/node_modules/$PKG/$entry" "\$@"
239
+ SHIM
240
+ chmod +x "$shim"
241
+ say "$shim"
242
+ }
243
+
244
+ step "Commands"
245
+ mkdir -p "$BIN_DIR"
246
+ write_shim "verify-tracking" "dist/cli.js"
247
+ write_shim "verify-tracking-mcp" "dist/mcp/server.js"
248
+
249
+ # ---------------------------------------------------------------------------
250
+ # 5. Sign in to Claude — the one step a human has to finish
251
+ # ---------------------------------------------------------------------------
252
+
253
+ # `curl … | sh` leaves this script's own text on stdin, so a child that prompts
254
+ # would read the rest of the installer as if it were typed. /dev/tty is the
255
+ # operator's actual terminal, and reading from it is what makes an interactive
256
+ # login possible from inside a piped installer.
257
+ claude_is_logged_in() {
258
+ PATH="$PREFIX/node/bin:$PATH" "$CLAUDE" auth status --json 2>/dev/null \
259
+ | grep -q '"loggedIn"[[:space:]]*:[[:space:]]*true'
260
+ }
261
+
262
+ login_instructions() {
263
+ printf '\n'
264
+ say "Finish by signing in to Claude, then you are done:"
265
+ printf '\n'
266
+ printf ' %s auth login\n' "$CLAUDE"
267
+ printf '\n'
268
+ }
269
+
270
+ step "Claude sign-in"
271
+ if claude_is_logged_in; then
272
+ say "already signed in"
273
+ elif [ ! -r /dev/tty ]; then
274
+ # Non-interactive: CI, a provisioning script, a shell with no terminal. The
275
+ # tool is fully installed and one command short of working, so that command
276
+ # is printed rather than a login attempted against nothing.
277
+ say "no terminal available, so the sign-in cannot run here."
278
+ login_instructions
279
+ else
280
+ say "opening the Claude sign-in — a browser window will ask you to log in."
281
+ say "This happens once on this machine."
282
+ printf '\n'
283
+ # `|| true` so a cancelled or failed login leaves a fully installed tool and
284
+ # a printed next step, not a failed install someone has to start over.
285
+ if PATH="$PREFIX/node/bin:$PATH" "$CLAUDE" auth login < /dev/tty > /dev/tty 2>&1; then
286
+ if claude_is_logged_in; then
287
+ say "signed in."
288
+ else
289
+ say "the sign-in did not complete."
290
+ login_instructions
291
+ fi
292
+ else
293
+ say "the sign-in was cancelled or failed."
294
+ login_instructions
295
+ fi
296
+ fi
297
+
298
+ # ---------------------------------------------------------------------------
299
+ # Done
300
+ # ---------------------------------------------------------------------------
301
+
302
+ printf '\n==> Installed\n'
303
+ "$BIN_DIR/verify-tracking" --version 2>/dev/null | sed 's/^/ /' || true
304
+
305
+ case ":${PATH}:" in
306
+ *":$BIN_DIR:"*) ;;
307
+ *)
308
+ printf '\n %s is not on your PATH. Add it, then reopen your terminal:\n\n' "$BIN_DIR"
309
+ printf " echo 'export PATH=\"%s:\$PATH\"' >> ~/.zshrc\n" "$BIN_DIR"
310
+ ;;
311
+ esac
312
+
313
+ printf '\n Try it:\n\n verify-tracking --url https://example.com --quick --no-save-report\n'
314
+ printf '\n Uninstall:\n\n rm -rf %s %s/verify-tracking %s/verify-tracking-mcp\n\n' "$PREFIX" "$BIN_DIR" "$BIN_DIR"