Add a once-per-boot instance_started event (arch, os, deploy_mode,
gpu_present) so the fleet architecture mix is measurable. It reuses the
existing per-instance instance_id and is exempt from the volume sample
rate, since a census that fires once per boot must not be thinned.
Restore useful capture depth now that the sponsored plan removes the
quota pressure behind the earlier hardening:
- PostHog sample rate 0.1 to 1.0 (full analytics when enabled); the
property allowlist still blocks file data.
- Sentry per-instance ceiling 20 to 500/hr, breadcrumb trail restored
(sanitized: urls/paths redacted, data payloads dropped), full stack
paths kept; local vars, request bodies, and PII still dropped. Both
api and web.
Honor ANALYTICS_ENABLED=false as an opt-out alias: it was documented on
the Docker Hub README but never wired in 2.x, so anyone who set it was
still tracked.
All capture stays behind the analytics opt-out gate.
Removes Sentry tracing entirely (BullMQ idle polling burned 4.8M transactions in 2 days at the baked 0.1 rate), decouples PostHog sampling, and replaces the type-only error scrub with a vetted-field sanitizer plus SafeError/ToolInputError contracts. One classified capture path with per-signature throttles and a per-process ceiling makes storms impossible (NODE-1E was 4,541 events from one 30s loop). Browser errors move to a dedicated web Sentry project with their own source maps. Adds the SNAPOTTER_TELEMETRY runtime kill switch and silences test fleets.
Crash fixes: remote 204/304 SSRF process kill (NODE-20), conversion-preset boot crash loop (NODE-21), Redis version preflight + unhandled subscribe rejection (NODE-1T), Sign PDF on plain-http origins (NODE-1K/1M), wavesurfer/pdf.js teardown rejections (NODE-1P/1N), bundle-import ZlibError to 400 (NODE-1Z), chart-maker input errors declassified (NODE-1H/1J), asset requests skip the session DB lookup (NODE-1D).
* fix(analytics): bake real Sentry DSN and lower trace sampling
The bake script emitted a placeholder Sentry DSN even in on mode, so every
published image initialized Sentry against a dead endpoint and no events ever
reached the project. Point it at the real snapotter project DSN.
Also drop tracesSampleRate from 1 to 0.1. It governs only performance
transactions (errors are always captured), so 100% fleet-wide tracing would
drain Sentry quota for no benefit.
* fix(analytics): point baked Sentry DSN at the snapotter org
* refactor(analytics): inject Sentry DSN + PostHog key from build env
#336 replaced the analytics creds with placeholders but never added a way to
put real values back at build time, so any image built from the repo since then
ships dead analytics (the live fleet only still reports because publishing is
paused and it runs a pre-placeholder image).
Restore the pipeline the clean way: bake-analytics.mjs reads SNAPOTTER_SENTRY_DSN
and SNAPOTTER_POSTHOG_KEY from the environment; the official image's CI supplies
them from repo secrets via build args. A build with neither stays disabled, so
building from source never phones home. Both values are public (they ship in the
browser bundle), so this is about not making source builds report, not secrecy.
Supersedes the hardcoded DSN: real creds are no longer committed to the repo.