mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-10 22:20:14 +00:00
fix(cli,studio,core): close five R5 telemetry and canary findings
- A long-lived preview cached its telemetry posture in two places (readConfig and shouldTrack). Running `telemetry disable` in another terminal left it resolving canaries and injecting the CLI id for hours. Both caches are now dropped together at a request boundary. - Studio minted and shipped a telemetry id for every render regardless of the browser profile's opt-out, and the server emitted the outcome under CLI policy, which cannot see localStorage or DNT. The browser now sends an explicit telemetryOptOut, distinct from an old client's omission. - Any non-empty HYPERFRAMES_PREVIEW_HOST disabled the DNS-rebinding guard, so even a loopback bind accepted a hostile Host. The guard now holds for loopback binds and, on a LAN bind, admits only names this machine answers on. - sunsetAfter had no reader of the current date. A scheduled workflow runs scripts/check-canary-sunset.ts weekly, so a failure lands on the rollout's owner rather than on an unrelated PR author. - The install-state seed memo outlived `rm -rf ~/.hyperframes`, resurrecting a cleared cohort. Removed; it only saved a read on a readConfig cache miss. Docs updated for the Host rule and the 100% exclusion carve-out. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3f69a2c635
commit
6f0df2640b
@@ -2,6 +2,7 @@ import { useState, useEffect, useCallback, useRef, useMemo } from "react";
|
||||
import type { CanvasResolution } from "@hyperframes/parsers";
|
||||
import { trackStudioRenderStart } from "../../telemetry/events";
|
||||
import { getAnonymousId } from "../../telemetry/config";
|
||||
import { browserTelemetryAllowed } from "../../telemetry/policy";
|
||||
import { generateId } from "../../utils/generateId";
|
||||
|
||||
export interface RenderJob {
|
||||
@@ -157,16 +158,28 @@ export function useRenderQueue(projectId: string | null) {
|
||||
resolution?: string;
|
||||
composition?: string;
|
||||
variables?: Record<string, unknown>;
|
||||
telemetryDistinctId: string;
|
||||
telemetryDistinctId?: string;
|
||||
telemetryOptOut?: boolean;
|
||||
} = {
|
||||
fps,
|
||||
quality,
|
||||
format,
|
||||
};
|
||||
// The id is MINTED by getAnonymousId(), so calling it unconditionally
|
||||
// created a telemetry identity for a profile that had opted out — and
|
||||
// then shipped it to the server. The server's own policy cannot see this
|
||||
// browser's localStorage or DoNotTrack, so it has to be told: an
|
||||
// explicit `telemetryOptOut` suppresses the render outcome, which
|
||||
// omitting the id alone does NOT (an old client omits it too, and that
|
||||
// falls back to the install id).
|
||||
if (browserTelemetryAllowed()) {
|
||||
// So the server-emitted render_complete/render_error is attributed to
|
||||
// this browser user (same id studio_* events use), making the render
|
||||
// funnel joinable. Matches studio_render_start fired just above.
|
||||
telemetryDistinctId: getAnonymousId(),
|
||||
};
|
||||
body.telemetryDistinctId = getAnonymousId();
|
||||
} else {
|
||||
body.telemetryOptOut = true;
|
||||
}
|
||||
if (resolution && resolution !== "auto") body.resolution = resolution;
|
||||
if (composition) body.composition = composition;
|
||||
if (opts.variables && Object.keys(opts.variables).length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user