Problem
#6086's third suggested direction — "make the untimed path observable at all, so a future regression here is visible rather than presenting as unexplained queue-overflow" — is the one item PR #6088 did not address. The PR is right not to have solved it the obvious way, but it substituted nothing, so the compatibility path is still invisible in both directions.
withTimeout / withManualTimeout return TimeoutBoundInit { init, cleanup }. No field anywhere records which branch produced a given request's signal.
On failure: the diagnostics object in recordCollectorOutcome already carries failureKind, prismaCode, constraint, botFiltered, and the cohort rates, and rides into Sentry extra. It has no field for the timeout mechanism. An operator (or an agent running sentry-triage against the analytics-collector / write-failed fingerprint) pulling up a timeout issue cannot tell whether it came from native AbortSignal.timeout / AbortSignal.any or from withManualTimeout.
On success it is worse: CollectorOutcome.failure is null and nothing records that the compat branch fired at all. There is no way to know what fraction of live traffic runs in an AbortSignal.timeout-absent environment, whether that population is shrinking, or whether a browser regression widened it.
Why it matters more here than as a general nicety
The defect #6086 fixed was unobservable by construction — no log, no counter, no signal — and surfaced only as unexplained queue-overflow in Sentry, long after the fact. That is the specific failure mode this module has already been bitten by once.
It compounds with the open latch-side gap: if a fetch wrapper ever ignores the forwarded abort, the fix silently reproduces the original park with no differentiating signal at all. Sizing the compat population is also the only way to answer "is this compatibility path still worth carrying?" empirically rather than by guess.
The shape it must NOT take
Widening CollectorFailure.kind is the wrong fix and was correctly avoided by PR #6088. kind is consumed by ENVIRONMENT_NOISE_KINDS, isAlertWorthyCollectorFailure, both retry predicates, and the Sentry fingerprint. A new kind not audited against every one of those arms falls through to return true — "everything left is actionable" — and pages someone on a browser-capability gap.
Suggested direction
Follow the precedent this module already set for botFiltered, which is deliberately a marker, not a kind, with a doc comment explaining exactly why.
Thread a usedFallback: boolean (or timeoutMechanism: 'native' | 'manual') through TimeoutBoundInit and record it as:
- a field on the
diagnostics object -> Sentry extra, and optionally
- a Sentry tag, so it is filterable
and explicitly not:
- part of
CollectorFailure.kind
- an element of the
fingerprint array (grouping and cardinality must not move)
- an input to either retry predicate or
isDurableMarkerResolved
That satisfies the original ask at zero classification risk.
tests/analytics-beacon-rejection.test.mts already asserts on the per-branch signals the transport hands to fetch, so there is a ready-made harness to assert the new field from.
Note
This is consistent with existing convention elsewhere in the repo — src/services/wm-session.ts, src/services/country-geometry.ts, and src/services/ollama-models.ts all fall back to a manual AbortController with zero telemetry. The argument for doing better here is that this is the one module where the silent-degradation failure mode has already caused an incident.
Found during adversarial review of PR #6088; carried over from #6086's open questions.
Problem
#6086's third suggested direction — "make the untimed path observable at all, so a future regression here is visible rather than presenting as unexplained
queue-overflow" — is the one item PR #6088 did not address. The PR is right not to have solved it the obvious way, but it substituted nothing, so the compatibility path is still invisible in both directions.withTimeout/withManualTimeoutreturnTimeoutBoundInit { init, cleanup }. No field anywhere records which branch produced a given request's signal.On failure: the
diagnosticsobject inrecordCollectorOutcomealready carriesfailureKind,prismaCode,constraint,botFiltered, and the cohort rates, and rides into Sentryextra. It has no field for the timeout mechanism. An operator (or an agent runningsentry-triageagainst theanalytics-collector/write-failedfingerprint) pulling up atimeoutissue cannot tell whether it came from nativeAbortSignal.timeout/AbortSignal.anyor fromwithManualTimeout.On success it is worse:
CollectorOutcome.failureisnulland nothing records that the compat branch fired at all. There is no way to know what fraction of live traffic runs in anAbortSignal.timeout-absent environment, whether that population is shrinking, or whether a browser regression widened it.Why it matters more here than as a general nicety
The defect #6086 fixed was unobservable by construction — no log, no counter, no signal — and surfaced only as unexplained
queue-overflowin Sentry, long after the fact. That is the specific failure mode this module has already been bitten by once.It compounds with the open latch-side gap: if a fetch wrapper ever ignores the forwarded abort, the fix silently reproduces the original park with no differentiating signal at all. Sizing the compat population is also the only way to answer "is this compatibility path still worth carrying?" empirically rather than by guess.
The shape it must NOT take
Widening
CollectorFailure.kindis the wrong fix and was correctly avoided by PR #6088.kindis consumed byENVIRONMENT_NOISE_KINDS,isAlertWorthyCollectorFailure, both retry predicates, and the Sentryfingerprint. A newkindnot audited against every one of those arms falls through toreturn true— "everything left is actionable" — and pages someone on a browser-capability gap.Suggested direction
Follow the precedent this module already set for
botFiltered, which is deliberately a marker, not akind, with a doc comment explaining exactly why.Thread a
usedFallback: boolean(ortimeoutMechanism: 'native' | 'manual') throughTimeoutBoundInitand record it as:diagnosticsobject -> Sentryextra, and optionallyand explicitly not:
CollectorFailure.kindfingerprintarray (grouping and cardinality must not move)isDurableMarkerResolvedThat satisfies the original ask at zero classification risk.
tests/analytics-beacon-rejection.test.mtsalready asserts on the per-branch signals the transport hands tofetch, so there is a ready-made harness to assert the new field from.Note
This is consistent with existing convention elsewhere in the repo —
src/services/wm-session.ts,src/services/country-geometry.ts, andsrc/services/ollama-models.tsall fall back to a manualAbortControllerwith zero telemetry. The argument for doing better here is that this is the one module where the silent-degradation failure mode has already caused an incident.Found during adversarial review of PR #6088; carried over from #6086's open questions.