Release notes

What changed, and when.

Every release of Helix Internet Monitor, including the things that did not work and the limitations that are still open. A changelog that only lists additions is an advertisement.

1.1.0 2026-08-20

Added

  • Per-hop MTR reaches the cloud. Each hop carries its loss classification as part of the row rather than as a rendering decision: whether a hop's loss persists downstream is a property of the whole trace, so a reader holding one row cannot recompute it. A hop arriving unclassified is refused at ingest, because the only thing left to render would be a bare percentage - the reading that gets an innocent transit provider blamed. Only the first propagating hop is marked as the culprit; everything downstream inherits the loss.
  • Diurnal profile - a 7x24 weekday-hour grid. Cells recombine from counts, never from averaged rates, so a 12-probe window does not weigh as much as a 600-probe one, and bucketing happens in the subscriber's local zone, because a fixed offset is wrong twice a year in every DST zone and moves the evening peak into the wrong column. The worst hour is a ratio against the line's own median and is left unnamed below a coverage floor.
  • Per-application usage on Windows, collected via ETW.
  • Target packs - mode-specific host sets selected by id. The list is compiled in and the type deliberately does not implement Deserialize, because constructing one from bytes is exactly the ability to name a host from outside the binary. Pack targets never join outage consensus, so a Discord outage is not reported as the subscriber's line going down.
  • On-site CDN and IP-transit checks, with HTTPS health checks alongside ICMP and MTR. One catalogue entry records that www.netflix.com blocks ICMP by policy, so its ping failure is not read as a fault.
  • DoH resolver catalogue with filtering levels and a lowest-latency pick.
  • User-defined watched hosts, labelled, visible on the desktop and in the cloud.
  • Tiered providers and ticketing - bilateral provider_links invited by the customer and accepted by the provider, escalation as a forward rather than a move, attach-time redaction against an allowlist, and an SLA clock that runs in business hours.
  • Crash reporting for the desktop app. Reports stay on the machine.
  • The app now opens maximised.
  • POST /v1/admin/releases/fetch registers a release by downloading it from its published URL and measuring it, rather than hashing a copy placed on the server by hand. Cutting a release no longer needs shell access to production. The digest still describes bytes the server received rather than a claim the caller made, which is the property that matters while the installer is unsigned.

Changed

  • Dark is unconditional; light is an explicit opt-out. There is no prefers-color-scheme: light block anywhere, so a visitor whose OS prefers light still gets the intended theme. The theme control lost its third "auto" state in the same change, because with the media query gone "auto" and "dark" selected identical pixels.
  • The chart palette is six series, not eight. The shipped values were measured against a CVD simulation rather than read: two of them sat adjacent at roughly half the required separation under deuteranopia - indistinguishable to about one man in twelve, and the exact defect the code comment claimed the ordering prevented. No seven-hue set clears all-pairs separation inside the required lightness band, so both palettes are now generated rather than chosen. A seventh series folds into an "Other" bucket or a second encoding channel.
  • Installs to C:\Program Files\Helix Internet Monitor, with a branded installer.
  • Gauges are determinate only when the wire carries a real fraction. The loss gauge refuses to draw an arc below 300 probes and shows counts instead; latency is graded against the line's own baseline, never an absolute scale.
  • Release downloads are served from GitHub. The counted, rate-limited /v1/downloads/him URL is unchanged - only what it redirects to moved.

Fixed

  • A cross-organisation ticket could leak an internal article. The read predicate compared author and reader organisation without a non-null guard, and JavaScript's null === null is true where SQL's NULL = NULL is not, so the two halves of the check disagreed. Unreachable in practice only because subscribers cannot author internal articles.
  • Loopback traffic was counted as internet usage by the ETW collector.
  • Recovery notices were swallowed by the packet-loss cooldown, so a line coming back could go unannounced.
  • Hop tables are never cropped. A 58vh cap on the desktop hid exactly the row nearest the fault.
  • The sign-in pages now say which password they want.
  • Every /v1/admin route in the download area was unreachable. They call requireSuperAdmin(), which reads a principal that only the requireUser preHandler sets, and none of them registered it -- so release registration and the whole download console answered 401 to a valid super-admin token, looking exactly like a bad one. No behavioural test could have caught it: an anonymous request gets 401 either way, so the wiring is now pinned structurally and a missing principal raises a named error instead of impersonating an authentication failure.
  • The published release body began with a byte order mark, and its unsigned-installer warning was absorbed into the table above it by markdown, so the one paragraph that has to be seen rendered as a table row.

Security

  • The subscriber sign-in identifier uses autocomplete="username", which is what makes a password manager offer the saved Helix password rather than leaving the user to type a remembered - and often reused - one.
  • Release redirect targets are validated against a compiled-in host allowlist, on write and again on read. /v1/downloads/him is public and unauthenticated and it hands out executables, so a free-text target would be an open redirect wearing the product's own domain.

Known limitations

  • The installer is not code-signed. SmartScreen will show "Windows protected your PC" and Chrome will warn on download. Signing is blocked on a certificate whose key must live on FIPS 140-2 Level 2 hardware, a CA/Browser Forum requirement since June 2023. The published SHA-256 is the honest mitigation until then.
  • Method::SetTargets is refused by the service pending an elevated confirmation flow.

1.0.0 2026-08-18

First public release: the measurement service, the desktop viewer, the cloud API and the four-tenant ISP model.

  • Latency, packet loss and outage detection, with counts and run lengths on the wire rather than percentages, because a percentage cannot be re-aggregated. Loss below 300 probes is flagged coarse rather than quoted as a rate.
  • A diagnosis engine whose verdicts carry contradicting[] as well as supporting[]; one that cannot populate the second is not shipped.
  • Consent, scope and article-visibility as three separate gates, each in one module, so a widening shows up in a diff.
  • Maintenance windows suppress fault attribution only when declared at least fifteen minutes before the fault, or the feature inverts into a retroactive amnesty.
  • Desktop app talking to the service over a named pipe on a versioned wire.

Version numbering

Releases follow semantic versioning. The wire protocol between the desktop app and the background service carries its own version, and the service accepts both the current one and the one before it, so an app and a service from adjacent releases keep working during the window where one has updated and the other has not.

Dates are when a version was cut, not when it was published.