Files
hyperframes/scripts/check-canary-sunset.ts
Vance IngallsandClaude Opus 5 6f0df2640b 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>
2026-08-01 17:21:41 -07:00

37 lines
1.4 KiB
TypeScript

#!/usr/bin/env bun
/**
* Sunset governance for the canary registry.
*
* Every canary declares a `sunsetAfter` date. Without something that reads the
* CURRENT date, that field is a comment: a rollout can sit at 10% forever and
* nothing notices. The registry's own unit tests deliberately do NOT check it
* against wall-clock time, because a date-triggered failure there turns the
* whole core suite red on an unrelated PR whose author cannot fix it.
*
* So the check lives here and runs on a schedule instead. A failure names an
* expired rollout and belongs to its owner, not to whoever pushed that day.
*
* Run: `bun scripts/check-canary-sunset.ts`
*/
import { CANARIES, overdueCanaries } from "../packages/core/src/canaryRegistry.js";
const overdue = overdueCanaries(new Date());
if (overdue.length === 0) {
console.log(`✓ ${CANARIES.length} canary/canaries registered, none past sunset.`);
process.exit(0);
}
console.error(`✗ ${overdue.length} canary/canaries are past their sunset date:\n`);
for (const name of overdue) {
const canary = CANARIES.find((c) => c.name === name);
console.error(
` ${name} — sunset ${canary?.sunsetAfter ?? "?"}, ${canary?.percentage ?? "?"}%, owner ${canary?.owner ?? "?"}`,
);
}
console.error(
"\nRamp it to 100 and delete the guard, roll it back, or move the date with a" +
"\nreason. See docs/contributing/canary-rollouts.mdx.",
);
process.exit(1);