Decision record

AD-0031 An optional check session through a tunnel, with traces

Status: accepted. Date: 2026-09-13.

Context

The demo is one container that answers on one port of the machine it runs on. A monitoring service runs elsewhere, on runners of its own, and cannot reach a port on a laptop. The two had never met.

Until this record the repository carried no browser automation. Behaviour that lives in browser JavaScript was demonstrated against a scripted checklist rather than tested (AD-0017), and the two-second bound on a live update was demonstrated for the same reason (AD-0014). SC-01 forbade a dependency that drives a browser in the product code, which is the right rule for a Go repository meant to be read without setup. It left the twelve stories with no check that ran on anyone’s schedule.

SR-03 kept the router off the network. The image sets the variables that turn the router’s telemetry off (AD-0013), so a request’s trace went nowhere, and when a check failed there was nothing to read beyond the check’s own log. The router is the one place a request is seen end to end, with the three fetches it fans out into. It is also the only service in the container that can emit a span without a new dependency.

Decision

We will add a compose profile beside the demo, under checkly/, that starts a Cloudflare tunnel, an OpenTelemetry collector, a trace viewer and a runner. The runner tests, deploys and destroys a Checkly project against this instance. It runs the browser specs and records the run as a session, deploys the project for as long as the stack runs, and destroys it when the stack stops. The tunnel is a named one on the operator’s own hostname when a token is supplied, and a quick one on a hostname the tunnel provider assigns otherwise.

The router’s tracing becomes an operator opt-in. A configuration file is handed to the router only when SYSML_FEDERATION_ROUTER_CONFIG_PATH names one, and the file’s values then govern the router’s telemetry, because the router’s own rule makes a file win over the environment. The session names a file that exports to the collector beside the demo, and the collector forwards every span to the viewer. When an ingest key is supplied, it also forwards to the monitoring service, but only the spans a check marked as its own.

The session runs on the operator’s own Checkly account, supplied as an API key and an account id in checkly/.env, because the maintainer’s credentials cannot ship inside a public image.

Without credentials nothing changes. docker run runs the demo as before, the variable is unset, the router’s environment is what the supervisor sets, and nothing under checkly/ is built, run or read.

Alternatives considered

A hosted demo, one instance running somewhere public that the monitoring service could reach without a tunnel. It would have made the session a fixture rather than a profile. It loses because it needs an account and a bill nobody asked for, and because the repository’s claim is that one docker run on one machine is the whole demo.

A private location, the monitoring service’s runners placed beside the demo so that no tunnel is needed. That is the cleaner topology, and the compose file carries the container for a private location behind a profile of its own. It loses as the route because it needs a paid plan, and the project is kept deployable on the free one.

Instrumenting the Go services, so that the three subgraphs carried spans of their own and a trace showed each resolver. It loses because it is a dependency SC-01 forbids in the product code, and because the router already sees every request and every fetch it makes. The router’s own exporter is the source of spans, and the trace of one request shows the three fetches as the router made them.

Consequences

SR-03 and SC-01 are amended. SR-03 carries the configuration-file opt-in as a clause of its statement and a fourth acceptance criterion, and SC-01 permits go-yaml for the one test that reads the compose file and places the check project outside the product.

AD-0013, AD-0014 and AD-0017 are amended. The telemetry record says how a file governs what the environment turned off, and the two records that said the repository carried no browser automation now say where it lives and what runs it.

A Node project lives under checkly/, outside the product. Browser automation exists in the repository, and it runs on the monitoring service’s runners rather than in make check, so the Go gate keeps its shape and its timing.

go-yaml becomes a direct dependency of the module, for one test that reads the compose file and holds the demo service outside every profile.

The session on a quick tunnel probes whether a subscription’s events cross the tunnel before the checks run. When none arrives, the seven story checks that depend on an event reaching the page skip, with the reason in their log. Quick tunnels are documented as carrying no streamed response, so on one the seven are expected to skip and the named tunnel on the operator’s own zone is the route for all twelve. The record in checkly/README.md says which route each recorded run used.

While a session runs the demo answers at a public hostname without authentication, for the session’s duration. The demo holds no secret, so what a visitor can do in that window is edit a value and fail a check.

Requirements affected

SR-03, SR-48, SC-01

Sources

The check session for the setup, the checks and the verification record. The model of the demo for the session composite and the check cases, in which every live check is a case of its own. The telemetry record (AD-0013), the version events record (AD-0014) and the vanilla web apps record (AD-0017), each amended by this decision.