diff --git a/deploy/beacon/worker.js b/deploy/beacon/worker.js index 5e8ec015f..15bc22d4f 100644 --- a/deploy/beacon/worker.js +++ b/deploy/beacon/worker.js @@ -28,9 +28,12 @@ * deanonymise install_id, so it is never read. */ -// Mirrors the payload built by _Session.payload(). A key absent here is -// dropped, not stored. Adding a metric means adding it here first — that -// friction is the point. +// Mostly mirrors the payload built by _Session.payload(); an extension may +// also emit its own event carrying one of these top-level keys. A key absent +// here is dropped, not stored. Adding a metric means adding it here first — +// that friction is the point, and it is also the only privacy control that +// works retroactively, so it must land BEFORE any client starts sending the +// key or that traffic is silently discarded and unrecoverable. const ALLOWED_KEYS = [ 'schema_version', 'session', @@ -43,6 +46,13 @@ const ALLOWED_KEYS = [ 'models', 'failures', 'failure_statuses', + // Model-routing summary. Emitted by a routing extension rather than by the + // proxy itself -- see proxy/route_advice.py for the decision seam. Same rule + // as everything above: counters and model ids, no free text. Allowlisted + // here so the corpus can answer what the proxy alone cannot -- a provider's + // real minimum cacheable prefix, how long a cache actually survives, and how + // far predicted cache hits are from the ones that happened. + 'routing', ]; // Resource attributes we keep. Same rule: allowlist, not denylist.