Repository navigation
fix(telemetry): honor CLI opt-out in Studio and render CI - #4500
Conversation
miguel-heygen
left a comment
There was a problem hiding this comment.
Reviewed this exact SHA, current diff/tests and actual Studio bootstrap and telemetry consumers.
telemetryIdentity.ts:133 transmits the existing CLI policy independently of trusted-host identity. The served Studio shell injects it before the bundle; both browser transports use the shared policy at policy.ts:105. Missing/false preserves existing OSS defaults and other opt-out controls; this does not persist a browser preference. Docker CI forwarding crosses the process boundary explicitly.
Independent exact-head validation: 114 focused tests passed across CLI identity/policy, Studio policy/client and legacy transport, including disabled transport plus enabled control. No new built-browser network E2E or production render was run by this review. Broader CI still has pending jobs, with no failed checks at posting.
Verdict: APPROVE
Reasoning: The injected flag reaches both browser telemetry transports before initialization without changing ordinary OSS defaults. No code blocker found. Older internal pins still need a release/update; review only, no merge/release/deploy performed.
— Magi
The branch was on v0.8.50 and 513 commits behind upstream/main; this takes it to v0.8.89. The fork's main mirror was already identical to upstream/main (1bede47) with the v0.8.89 tag on origin. Merged, not rebased, per the fork rules. 30 conflicts. Resolved one by one, not by taking a side wholesale: Upstream deleted what the patch touched (accepted the deletion): * packages/studio/src/components/storyboard/** and useStoryboard / useProjectSignaturePoll. Upstream heygen-com#4140 removed the Storyboard view and its Storyboard/Preview switch. TAB-703 had added Send-to-Agent buttons and format-aware tile aspect ratios there. The compositor emits its own STORYBOARD.md and imports nothing from this view, and the agent bridge itself (AgentDrawer / Tabario AI) does not depend on it, so the patch goes with the view. Our orphaned storyboardAspectRatio.ts and StoryboardFrameTile.test.tsx went too. The "storyboard-*" AgentRequestKinds are now unused but harmless. Upstream took the fix (dropped ours, patch surface shrinks): * engine wavChunks.ts / audioFxRender.ts / audioVolumeEnvelope.ts: upstream landed its own shared RIFF walk and WAVE_FORMAT_EXTENSIBLE resolution. Both sides added wavChunks.ts, and git's add/add merge left two wavFormatTag declarations that only the build caught. Took upstream's implementation. Our extra extensible-WAV tests stay and pass against it, bar one case: "invalid precision" (validBitsPerSample 33 in a 32-bit container) is now accepted and decoded as ordinary 32-bit float. Dropped that case; the files come from FFmpeg, so it guards malformed input, not render correctness. * useTimelinePlayer.ts: upstream now reloads into a shadow iframe and never hides the live one, so TAB-1062's armRevealFallback has nothing left to unhide. Removed it and its tests; the file is now identical to upstream. * useDomEditTextCommits.ts: upstream inlined the same three helpers we had extracted into domEditCommitHelpers.ts (byte-identical) and moved style commits into domStyleCommit. Deleted our helper module. What remains of our patch is the caption word-span re-plan in capture (+34/-2 vs upstream). * studio-server subComposition.ts: upstream moved isFullHtmlDocument into @hyperframes/core/compiler/html-document, a superset of ours (it also skips leading comments). Used theirs; kept our vendoredGsap import. Both sides kept: * studio-server createStudioApi / index / types / routes/preview and cli studioServer.ts: our agent runtime + write lock, vendored GSAP and Google Font proxy routes, alongside upstream's project history routes and project-dir-missing middleware. Import unions only. * .fallowrc.jsonc: our TAB-1148 exemptions plus upstream's reworded comment. * useSdkSession.ts: our agent refresh subscription plus upstream's whenPreviewBooted. * useAppHotkeys.ts: the caption-editing gate (isTypingKeyEvent, 20eb534) auto-merged into handleAppKeyDown; only the import conflicted. * LintModal.tsx: kept our LintFindingRow, applied upstream's Tailwind v4 rename (flex-shrink-0 -> shrink-0), the only change upstream made to those rows. * StudioFeedbackCard.tsx: kept the removal of the external "Talk to us" interview link. * StudioHeader.tsx: rebuilt from upstream's new design-system header (undo/redo moved to the timeline toolbar in heygen-com#4196, storyboard toggle gone) and re-added "Go to Tabario" and "Tabario AI" on the new Button. The return-to-Tabario fetch moved into a local useReturnToTabario hook so the header's complexity does not grow. * bun.lock: upstream's, then bun install. It differs from upstream only by our vendored gsap dep and workspace version strings upstream left at 0.8.62. Fixed at the seams (upstream changes our code had not caught up with): * studioServer.ts measureLayout: getThumbnailBrowser gained an isShuttingDown argument; our Tabario AI layout probe now passes () => shuttingDown. * studioServer.test.ts: CheckReport gained a required hdr section; the engine mock now spreads importOriginal, because compositions.ts imports resolveReferencedStart from the engine. * propertyPanelFlatCaptionSection.tsx: upstream's new hex ratchet flagged our two "#ffffff" caption defaults. They are composition data, not Studio chrome, so they are hoisted into one DEFAULT_CAPTION_COLOR (the same shape as upstream's InlineTextToolbar DEFAULT_COLOR) and the baseline gains exactly that file at 1. * useAskAgentModal.test.tsx (new upstream): the fork sends the prompt to the agent bridge, not the clipboard. Mocked the bridge; every assertion kept. * telemetry/client.test.ts (new upstream, heygen-com#4500): the opt-out half is upstream's as-is; the "enabled control sends" half asserts not-sent, because Studio telemetry is off in the fork (TAB-697). Verified: * bun install --frozen-lockfile clean; bun run build exit 0. * tsc --noEmit clean for core, engine, producer, player, lint, studio, studio-server, cli, sdk. bun run lint clean. oxfmt clean on changed files. * Tests per package, 4 workers each: core 3645, engine 2021, lint 746, studio-server 1099, cli 3951, player 512, sdk 554, producer 851, studio 6076. All pass, including the fork egress guards (forkEgressGuard.test.ts, policy.forkEgress.test.ts). * No new third-party host in studio / studio-server / runtime / player source. * Tabario symbols confirmed in the built artifacts, not just the source: isTypingKeyEvent, TABARIO_STUDIO_HOSTED, "Tabario AI", "Go to Tabario", buildCaptionWordSpans, /api/tabario/session/exit, AgentRuntime, registerVendorRoutes, registerGoogleFontProxyRoutes. Upstream is not frame-stable. Renders may differ from v0.8.50: this range carries engine colour, HDR, frame-selection and audio-timing fixes. The compositor pin bump and deploy are out of scope for TAB-1216. Pre-commit: every gate ran; none was skipped and --no-verify was not used. largefiles ran with HF_MAX_NONLFS_KB=2300, the gate's documented per-commit override, because upstream committed two catalog assets as plain blobs (not LFS): docs/public/catalog/items/blue-sweater-intro-video/assets/joe-sai-avatar.png (1954 KB) and .../sfx/integrated-melodic-tech-mix.wav (2251 KB). They are upstream's objects byte-for-byte. Moving them into LFS here would diverge from upstream and conflict on every later sync. fallow passed, auditing 3258 changed files (the merge itself); its 32 complexity findings are informational and none of them is in code this merge authored.
A CLI launched with telemetry disabled currently withholds its anonymous identity, but Studio has a separate browser telemetry policy and can still send events. Pass a page-scoped disabled flag before Studio initializes and honor it in the shared browser policy, covering both telemetry transports and canary eligibility. Enabled CLI sessions and standalone Studio keep their existing behavior; no browser preference is persisted.
Also pass the explicit
HYPERFRAMES_NO_TELEMETRY=1opt-out into the first-party regression and fast-video Docker jobs. A workflow-level environment does not crossdocker run. The public render image keeps its existing defaults.Validation: 109 focused CLI opt-out/identity, Studio policy, and Studio client tests pass against built core outputs. The transport test attempts the same render event in both modes: disabled sends nothing, enabled sends once. Full pre-commit checks pass, including oxlint, oxfmt, core/Studio/scripts typechecks, fallow, file-size/artifact checks and commitlint. Core was built to generate the runtime artifacts required by these checks; no generated artifact is committed.
This requires a normal package release and downstream CLI pin updates to protect deployments still serving older Studio bundles. No publication or deployment is included. Ready for review; keep unmerged pending explicit merge authorization.
Before
Browser regression harness using the base Studio policy and the real client transport. A CLI opt-out does not set a browser flag; attempting one
render_completeevent produces one intercepted PostHog batch. The harness intercepts fetch locally; no test analytics are transmitted. This is behavioral evidence, not a screenshot of a visible Studio layout change.After
Same browser harness and event attempt, with this PR's policy and injected CLI disabled flag. Zero PostHog batches. Captures use Chrome, the actual bundled Studio client/policy, and a fresh browser profile for each state.