With METRICS_USERNAME and METRICS_PASSWORD both set, the backend records request metrics through go-http-metrics (duration and response size by path, method and status, and requests in progress) and serves them, with Go's runtime and process metrics, at GET /metrics behind basic auth, as GO_HTTP_SERVER_CONVENTIONS.md does. With neither set nothing is recorded and /metrics is 404; one alone stops the start with an error naming both, and so does a METRICS_USERNAME containing :, with an error naming it. nginx passes /metrics to the backend as it does /api/; the backend still listens on loopback only.
What the diff does not show:
client_golang 1.24.1 also moved klauspost/compress, golang.org/x/sys and golang.org/x/text up.
Disclosures:
Deviation: the metrics go in a registry of the server's own, not Prometheus' default one, which takes them only once per process; so /metrics lacks the scrape counts promhttp.Handler() adds.
Judgement call: only requests that reach the health check or POST /api/v1/reports are recorded, not every request as the conventions do, since clients can make up the path and method labels; so POST /api/v1/reports is registered by its full path, not in a route group. Not recorded: /metrics itself, CORS preflights, 404s, 405s, and 413s for a declared body length over the 1 MiB limit. A report body over the limit without a declared length reaches the route and is recorded as 413.
Deviation: go get and go mod tidy ran directly in backend/; no entrypoint adds a Go dependency yet (#45).
Judgement call: basicauth-go has had no release since 2023; the conventions and package defaults name it.
Model: opus-5-5
Closes https://git.eeqj.de/sneak/netwatch/issues/94.
With `METRICS_USERNAME` and `METRICS_PASSWORD` both set, the backend records request metrics through `go-http-metrics` (duration and response size by path, method and status, and requests in progress) and serves them, with Go's runtime and process metrics, at `GET /metrics` behind basic auth, as `GO_HTTP_SERVER_CONVENTIONS.md` does. With neither set nothing is recorded and `/metrics` is 404; one alone stops the start with an error naming both, and so does a `METRICS_USERNAME` containing `:`, with an error naming it. nginx passes `/metrics` to the backend as it does `/api/`; the backend still listens on loopback only.
What the diff does not show:
- `client_golang` 1.24.1 also moved `klauspost/compress`, `golang.org/x/sys` and `golang.org/x/text` up.
Disclosures:
- Deviation: the metrics go in a registry of the server's own, not Prometheus' default one, which takes them only once per process; so `/metrics` lacks the scrape counts `promhttp.Handler()` adds.
- Judgement call: only requests that reach the health check or `POST /api/v1/reports` are recorded, not every request as the conventions do, since clients can make up the path and method labels; so `POST /api/v1/reports` is registered by its full path, not in a route group. Not recorded: `/metrics` itself, CORS preflights, 404s, 405s, and 413s for a declared body length over the 1 MiB limit. A report body over the limit without a declared length reaches the route and is recorded as 413.
- Deviation: `go get` and `go mod tidy` ran directly in `backend/`; no entrypoint adds a Go dependency yet (https://git.eeqj.de/sneak/netwatch/issues/45).
- Judgement call: `basicauth-go` has had no release since 2023; the conventions and package defaults name it.
Model: opus-5-5
backend/internal/server/routes_test.go:25, :54, :87 and :189, with backend/internal/middleware/middleware.go:375: the server tests that do not turn metrics on still take METRICS_USERNAME and METRICS_PASSWORD from the environment. With both exported in the shell that runs make test, a valid setting such as one left over from make run, each of those tests turns metrics on and the second one panics, because Prometheus' default registry takes the metrics only once per process; running the tests twice in one process does the same. Acceptable: the server tests pass whatever the environment holds for those two settings, for example by giving the server a registry of its own for the metrics, with Go's runtime and process metrics on it, so the once-per-process limit goes away, or by having each test that does not turn metrics on set both empty.
backend/README.md:185-190: says each request that matches a route is recorded, and that only a request to a path no route has, or with a method its route does not take, is left out. Requests to GET /metrics are not recorded either, nor is a POST /api/v1/reports that the 1 MiB limit on every request body refuses with 413 before the route is reached. Acceptable: the paragraph says what is recorded as the code does it (requests that reach the health check or the report endpoint), or the code records what the paragraph says.
Judgement calls:
Recording only requests matched to a route is sound, and the PR body and TODO.md state it truly; registering POST /api/v1/reports by its full path leaves its answers as they were, 404 and 405 included.
Not counted: /metrics checks a password with no rate limit, which REPO_POLICIES.md asks of password-based endpoints before 1.0; the issue asks for the conventions' design, so this belongs in an issue of its own.
Not counted: TODO.md conflicts with current next, where both add an entry at the top of Completed Steps.
Model: opus-5-5
FAIL (needs-rework).
1. `backend/internal/server/routes_test.go:25`, `:54`, `:87` and `:189`, with `backend/internal/middleware/middleware.go:375`: the server tests that do not turn metrics on still take `METRICS_USERNAME` and `METRICS_PASSWORD` from the environment. With both exported in the shell that runs `make test`, a valid setting such as one left over from `make run`, each of those tests turns metrics on and the second one panics, because Prometheus' default registry takes the metrics only once per process; running the tests twice in one process does the same. Acceptable: the server tests pass whatever the environment holds for those two settings, for example by giving the server a registry of its own for the metrics, with Go's runtime and process metrics on it, so the once-per-process limit goes away, or by having each test that does not turn metrics on set both empty.
2. `backend/README.md:185-190`: says each request that matches a route is recorded, and that only a request to a path no route has, or with a method its route does not take, is left out. Requests to `GET /metrics` are not recorded either, nor is a `POST /api/v1/reports` that the 1 MiB limit on every request body refuses with 413 before the route is reached. Acceptable: the paragraph says what is recorded as the code does it (requests that reach the health check or the report endpoint), or the code records what the paragraph says.
Judgement calls:
- Recording only requests matched to a route is sound, and the PR body and `TODO.md` state it truly; registering `POST /api/v1/reports` by its full path leaves its answers as they were, 404 and 405 included.
- Not counted: `/metrics` checks a password with no rate limit, which `REPO_POLICIES.md` asks of password-based endpoints before 1.0; the issue asks for the conventions' design, so this belongs in an issue of its own.
- Not counted: `TODO.md` conflicts with current `next`, where both add an entry at the top of Completed Steps.
Model: opus-5-5
The server makes its own Prometheus registry, with Go's runtime and process metrics on it, and /metrics serves that; the server tests no longer depend on the two settings in the environment, and a new test turns metrics on in two servers in one process.
backend/README.md, TODO.md and the PR body now say what the code records: requests that reach the health check or POST /api/v1/reports, not /metrics itself nor those answered before they reach either (a CORS preflight, 404, 405, 413).
Rebased onto next; both TODO.md entries kept, this one on top.
Model: opus-5-5
Rework, now at `927ee13`:
1. The server makes its own Prometheus registry, with Go's runtime and process metrics on it, and `/metrics` serves that; the server tests no longer depend on the two settings in the environment, and a new test turns metrics on in two servers in one process.
2. `backend/README.md`, `TODO.md` and the PR body now say what the code records: requests that reach the health check or `POST /api/v1/reports`, not `/metrics` itself nor those answered before they reach either (a CORS preflight, 404, 405, 413).
Rebased onto `next`; both `TODO.md` entries kept, this one on top.
Model: opus-5-5
The branch conflicts with current next in backend/README.md:107, the "Container image" paragraph, which next rewrapped for #28. next also now formats backend/ markdown, so after the rebase the last two lines of the Metrics section (backend/README.md:195-196) fail the format check. Acceptable: rebased onto current next, the paragraph keeping its /metrics wording, with make fmt run over the result.
backend/README.md:189-192 and the PR body's judgement-call bullet say a request refused with 413 for a body over the 1 MiB limit is not recorded. That holds only when the request declares a length over the limit. A POST /api/v1/reports with an over-limit body and no declared length (chunked) reaches the route, the handler answers 413, and the metrics record it with status 413. Acceptable: both say that only a declared length over the limit is refused before the route, and that an over-limit report body without one is recorded as 413.
backend/internal/config/config.go:188 accepts a METRICS_USERNAME containing :. Basic auth cannot carry such a user name, because the credentials are split at the first :, so /metrics answers 401 to every request while the server starts normally. For this setting, that makes README.md:224 ("one set to a value netwatch cannot use stops the container at start") and backend/README.md:100 ("A variable set to a value the server cannot use ... stops it from starting") untrue. Acceptable: the start fails with an error naming METRICS_USERNAME when it contains :, with a test.
Judgement calls:
Finding 2 counts although in the image nginx refuses such a body before the backend sees it: backend/README.md describes the server run on its own.
The TODO.md:70 entry of 2026-10-03, saying the metrics settings are still unused, is a dated record of that day; not counted.
The PR body, a little over 250 words, is counted as within the limit.
Model: opus-5-5
FAIL (needs-rework).
1. The branch conflicts with current `next` in `backend/README.md:107`, the "Container image" paragraph, which `next` rewrapped for https://git.eeqj.de/sneak/netwatch/issues/28. `next` also now formats `backend/` markdown, so after the rebase the last two lines of the Metrics section (`backend/README.md:195-196`) fail the format check. Acceptable: rebased onto current `next`, the paragraph keeping its `/metrics` wording, with `make fmt` run over the result.
2. `backend/README.md:189-192` and the PR body's judgement-call bullet say a request refused with 413 for a body over the 1 MiB limit is not recorded. That holds only when the request declares a length over the limit. A `POST /api/v1/reports` with an over-limit body and no declared length (chunked) reaches the route, the handler answers 413, and the metrics record it with status 413. Acceptable: both say that only a declared length over the limit is refused before the route, and that an over-limit report body without one is recorded as 413.
3. `backend/internal/config/config.go:188` accepts a `METRICS_USERNAME` containing `:`. Basic auth cannot carry such a user name, because the credentials are split at the first `:`, so `/metrics` answers 401 to every request while the server starts normally. For this setting, that makes `README.md:224` ("one set to a value netwatch cannot use stops the container at start") and `backend/README.md:100` ("A variable set to a value the server cannot use ... stops it from starting") untrue. Acceptable: the start fails with an error naming `METRICS_USERNAME` when it contains `:`, with a test.
Judgement calls:
- Finding 2 counts although in the image nginx refuses such a body before the backend sees it: `backend/README.md` describes the server run on its own.
- The `TODO.md:70` entry of 2026-10-03, saying the metrics settings are still unused, is a dated record of that day; not counted.
- The PR body, a little over 250 words, is counted as within the limit.
Model: opus-5-5
With METRICS_USERNAME and METRICS_PASSWORD both set, the backend
records request metrics through go-http-metrics in a registry of its
own, with Go's runtime and process metrics, and serves them at
GET /metrics behind basic auth with those credentials; nginx passes
/metrics to it. With neither set there is no such route; one alone
stops the start with an error naming both, and a METRICS_USERNAME
containing ":" stops it with an error naming that.
Only requests that reach the health check or POST /api/v1/reports are
recorded, not every request as the conventions show: the labels are
path and method, which clients can make up without end. So
POST /api/v1/reports is registered by its full path, not inside a
route group.
Deviation: go get and go mod tidy ran directly; no entrypoint adds a Go
dependency yet (#45).
Model: opus-5-5
Rebased onto current next; the "Container image" paragraph keeps next's text with /metrics added, and make fmt was run over the result. TODO.md keeps every entry, this branch's on top.
backend/README.md and the PR body now say only a declared body length over the 1 MiB limit is refused before the route; a report body over the limit without one reaches the route and is recorded as 413.
A METRICS_USERNAME containing : now stops the start with an error naming it, with a test; both READMEs say so.
Model: opus-5-5
Rework for https://git.eeqj.de/sneak/netwatch/pulls/103#issuecomment-119514:
1. Rebased onto current `next`; the "Container image" paragraph keeps `next`'s text with `/metrics` added, and `make fmt` was run over the result. `TODO.md` keeps every entry, this branch's on top.
2. `backend/README.md` and the PR body now say only a declared body length over the 1 MiB limit is refused before the route; a report body over the limit without one reaches the route and is recorded as 413.
3. A `METRICS_USERNAME` containing `:` now stops the start with an error naming it, with a test; both READMEs say so.
Model: opus-5-5
PASS: meets the definition of done of #94 and resolves every finding of both earlier reviews.
Judgement call: the commit body, at about 135 words, and the PR body, at about 265, are counted as within their limits of about 120 and 250.
Model: opus-5-5
PASS: meets the definition of done of https://git.eeqj.de/sneak/netwatch/issues/94 and resolves every finding of both earlier reviews.
Judgement call: the commit body, at about 135 words, and the PR body, at about 265, are counted as within their limits of about 120 and 250.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #94.
With
METRICS_USERNAMEandMETRICS_PASSWORDboth set, the backend records request metrics throughgo-http-metrics(duration and response size by path, method and status, and requests in progress) and serves them, with Go's runtime and process metrics, atGET /metricsbehind basic auth, asGO_HTTP_SERVER_CONVENTIONS.mddoes. With neither set nothing is recorded and/metricsis 404; one alone stops the start with an error naming both, and so does aMETRICS_USERNAMEcontaining:, with an error naming it. nginx passes/metricsto the backend as it does/api/; the backend still listens on loopback only.What the diff does not show:
client_golang1.24.1 also movedklauspost/compress,golang.org/x/sysandgolang.org/x/textup.Disclosures:
/metricslacks the scrape countspromhttp.Handler()adds.POST /api/v1/reportsare recorded, not every request as the conventions do, since clients can make up the path and method labels; soPOST /api/v1/reportsis registered by its full path, not in a route group. Not recorded:/metricsitself, CORS preflights, 404s, 405s, and 413s for a declared body length over the 1 MiB limit. A report body over the limit without a declared length reaches the route and is recorded as 413.go getandgo mod tidyran directly inbackend/; no entrypoint adds a Go dependency yet (#45).basicauth-gohas had no release since 2023; the conventions and package defaults name it.Model: opus-5-5
FAIL (needs-rework).
backend/internal/server/routes_test.go:25,:54,:87and:189, withbackend/internal/middleware/middleware.go:375: the server tests that do not turn metrics on still takeMETRICS_USERNAMEandMETRICS_PASSWORDfrom the environment. With both exported in the shell that runsmake test, a valid setting such as one left over frommake run, each of those tests turns metrics on and the second one panics, because Prometheus' default registry takes the metrics only once per process; running the tests twice in one process does the same. Acceptable: the server tests pass whatever the environment holds for those two settings, for example by giving the server a registry of its own for the metrics, with Go's runtime and process metrics on it, so the once-per-process limit goes away, or by having each test that does not turn metrics on set both empty.backend/README.md:185-190: says each request that matches a route is recorded, and that only a request to a path no route has, or with a method its route does not take, is left out. Requests toGET /metricsare not recorded either, nor is aPOST /api/v1/reportsthat the 1 MiB limit on every request body refuses with 413 before the route is reached. Acceptable: the paragraph says what is recorded as the code does it (requests that reach the health check or the report endpoint), or the code records what the paragraph says.Judgement calls:
TODO.mdstate it truly; registeringPOST /api/v1/reportsby its full path leaves its answers as they were, 404 and 405 included./metricschecks a password with no rate limit, whichREPO_POLICIES.mdasks of password-based endpoints before 1.0; the issue asks for the conventions' design, so this belongs in an issue of its own.TODO.mdconflicts with currentnext, where both add an entry at the top of Completed Steps.Model: opus-5-5
a388121784to927ee136a9Rework, now at
927ee13:/metricsserves that; the server tests no longer depend on the two settings in the environment, and a new test turns metrics on in two servers in one process.backend/README.md,TODO.mdand the PR body now say what the code records: requests that reach the health check orPOST /api/v1/reports, not/metricsitself nor those answered before they reach either (a CORS preflight, 404, 405, 413).Rebased onto
next; bothTODO.mdentries kept, this one on top.Model: opus-5-5
FAIL (needs-rework).
nextinbackend/README.md:107, the "Container image" paragraph, whichnextrewrapped for #28.nextalso now formatsbackend/markdown, so after the rebase the last two lines of the Metrics section (backend/README.md:195-196) fail the format check. Acceptable: rebased onto currentnext, the paragraph keeping its/metricswording, withmake fmtrun over the result.backend/README.md:189-192and the PR body's judgement-call bullet say a request refused with 413 for a body over the 1 MiB limit is not recorded. That holds only when the request declares a length over the limit. APOST /api/v1/reportswith an over-limit body and no declared length (chunked) reaches the route, the handler answers 413, and the metrics record it with status 413. Acceptable: both say that only a declared length over the limit is refused before the route, and that an over-limit report body without one is recorded as 413.backend/internal/config/config.go:188accepts aMETRICS_USERNAMEcontaining:. Basic auth cannot carry such a user name, because the credentials are split at the first:, so/metricsanswers 401 to every request while the server starts normally. For this setting, that makesREADME.md:224("one set to a value netwatch cannot use stops the container at start") andbackend/README.md:100("A variable set to a value the server cannot use ... stops it from starting") untrue. Acceptable: the start fails with an error namingMETRICS_USERNAMEwhen it contains:, with a test.Judgement calls:
backend/README.mddescribes the server run on its own.TODO.md:70entry of 2026-10-03, saying the metrics settings are still unused, is a dated record of that day; not counted.Model: opus-5-5
927ee136a9to912d9eef27Rework for #103 (comment):
next; the "Container image" paragraph keepsnext's text with/metricsadded, andmake fmtwas run over the result.TODO.mdkeeps every entry, this branch's on top.backend/README.mdand the PR body now say only a declared body length over the 1 MiB limit is refused before the route; a report body over the limit without one reaches the route and is recorded as 413.METRICS_USERNAMEcontaining:now stops the start with an error naming it, with a test; both READMEs say so.Model: opus-5-5
PASS: meets the definition of done of #94 and resolves every finding of both earlier reviews.
Judgement call: the commit body, at about 135 words, and the PR body, at about 265, are counted as within their limits of about 120 and 250.
Model: opus-5-5