web/nginx.conf ended its try_files chain in an unconditional /200.html, so every path the site does not have -- /wp-login.php, /.env, a typo'd inbound link -- came back as the SPA shell with a success status. It now answers 404, which needs nginx to know which routes exist: most it infers from the build output, but dynamic routes and ones that never opted into prerendering have no file on disk and are listed by hand. Those hand-maintained lists drift, and the drift is invisible until it ships: vite dev and npm run preview route from the client manifest and never read nginx.conf, so a new dynamic route works everywhere a developer would look and 404s in production. hack/check-web-routes.sh compares the lists against web/src/routes, and a workflow runs it. Its own workflow rather than another job on license-compliance.yml, which already carries one unrelated check. Also turns absolute_redirect off. With nginx's default the trailing-slash canonicaliser reconstructs the origin from its own listen port, so a request for https://demo.cairnobs.org/settings/ was answered with Location: http://127.0.0.1:3000/settings -- the container's internal address, unreachable from the client, and downgraded to http on the way. Verified by curl against the built image; it was latent here before the canonicaliser existed too, through the directory redirect on /dev.
hack
Local developer tooling that isn't part of any shipped component — scripts
you run against your own machine/dev stack, not code that ends up in a
container image (except dev-certs' output, which mounts into the
ingest container).
Not one of the top-level directories in the original monorepo scaffold —
added because dev-only mTLS cert generation didn't have a natural home in
/deploy (real deployment manifests), /transport, or any other existing
component. /hack is the conventional name for this in a lot of larger Go
monorepos (Kubernetes among them).
dev-certs/— generates a throwaway CA + server/client cert pair for local mTLS between the agent and ingest. See/docs/phase-0-runbook.mdfor when to run it.windows-fixture/— sends synthetic Windows Event Log-shaped records directly toingest, bypassing the real Windows agent. Tests whether the pipeline handles Windows-shaped data; doesn't test the realEvtSubscribe/ETW integration, which needs actual Windows. See/docs/phase-1-runbook.md.demo-simulator/— the public demo's synthetic world: a fictional fleet whose agents check in, report CPU/memory/disk, and ship realistically shaped logs for eight services. Backfills a window of history, then keeps generating in real time. Distinct frombenchmark-fixture/(volume, for the Phase 2 latency benchmark) andwindows-fixture/(correctness, for the Windows ingest path).check-web-routes.sh— assertsweb/nginx.conf's hand-maintained route allowlists still matchweb/src/routes.nginx.conf404s unknown paths, so it has to name the routes that have no prerendered file to match (dynamic ones, and any route withoutprerender = true). Drift here breaks production only — dev andnpm run previewnever readnginx.conf— so this runs in CI, likecheck-tenant-boundary.sh.demo-seed/— the rest of the demo deployment: its reset script, dashboards, alert rules, and the systemd unit that runsdemo-simulator.