Add OAuth session lifecycle telemetry to growthbook
Subscribes to the OAuth client's deleted/updated events and wraps the
client's fetch so every /oauth/token round-trip is observed. Emits four
event types to growthbook for diagnosing silent OAuth sign-outs:
- oauth:sessionRefreshed: successful refresh
- oauth:refreshFailed: any /oauth/token failure (network, 5xx, server
rejection); use_dpop_nonce retries are intentionally suppressed since
they're expected control flow, not failures
- oauth:sessionDeleted: client gave up and removed the session locally;
this is the silent-logout signal that was missing before
- oauth:sessionResumeFailed: resumeSession() threw during AppBoot or
SwitchAccount
Each event carries a coarse errorCategory (sessionDeleted | sessionExpired
| invalidGrant | databaseClosed | dpopSkew | dpopOther | refreshExhausted
| subMismatch | timeout | network | serverError | unknown) so we can
filter by failure mode without parsing message strings.
Pre-Provider events are queued and drained when the analytics sink
registers, so failures during BrowserOAuthClient.init() at boot aren't
dropped. Listeners are guarded with a Symbol so HMR re-running the
module can't double-attach.
Adds a dev-only "Force OAuth token refresh" button in Settings >
DevOptions so failure modes can be reproduced deterministically without
waiting for an access token to expire.
Also removes a few pre-existing unused imports/vars in Settings.tsx and
adds an eslint-disable for the dev-only window.agent assignment in
state/session/index.tsx so the pre-commit hook passes.