2025-10-22 - 2026-10-22
Overview
2 Releases published by 1 user
Published
v1.0.0-rc2
Published
v1.0.0-rc1
87 Pull requests merged by 2 users
Merged
#186 server.go starts listenAndServe in an anonymous function (closes #162)
Merged
#188 Match .gitignore, .editorconfig and .golangci.yml to sneak/prompts (closes #174)
Merged
#184 package.json drops its version field and is private (closes #158)
Merged
#185 TODO.md Status says where release candidates are tagged
Merged
#187 netwatch-server refuses arguments it does not understand (closes #179)
Merged
#178 main() is one call into internal/cli (closes #160)
Merged
#182 script/build stamps lightweight tags too (closes #156)
Merged
#183 .dockerignore keeps root test binaries and coverage out (closes #155)
Merged
#181 CI checkout fetches all history and tags (closes #153)
Merged
#176 Bootstrap keeps yarn at its pinned version and node at its pinned major
Merged
#180 Entrypoint steps are functions called from main (closes #163)
Merged
#177 Health check answers 503 while report files cannot be written (closes #142)
Merged
#172 Report file writes run one at a time (closes #150)
Merged
#175 DEBUG turns debug logging on for any non-empty value (closes #159)
Merged
#171 Check builds keep Go's modules and caches between runs (refs #118)
Merged
#173 Discarded-check unit tests check nothing was recorded
Merged
#169 Unusable DATA_DIR error names DATA_DIR; report file number is atomic.Int64
Merged
#170 Page is sent with Cache-Control: no-cache (closes #141)
Merged
#168 README states what refused reports, one sender and nginx's 413 do (closes #145, closes #146, closes #147)
Merged
#167 Clock errors no longer stop probing; legend reads >=500ms (closes #149, closes #152)
Merged
#165 prepare-data-dir leaves files with a second name to their owner (closes #143)
Merged
#166 Client address is the right-most untrusted X-Forwarded-For entry (closes #144)
Merged
#164 Summary reads --/-- after an interval change, not 0/26 in red (closes #140)
Merged
#138 Stopping the server waits for report file writes under way (closes #122)
Merged
#137 make test no longer runs the frontend's production build (refs #118)
Merged
#135 Debug log adds each line instead of drawing the whole panel (closes #131)
Merged
#136 Unset TRUSTED_PROXIES trusts RFC 1918, empty trusts none (closes #129)
Merged
#130 Reports refused while report files cannot be written (closes #123)
Merged
#133 A handler's panic is logged and counted as 500 (closes #125)
Merged
#121 Unset TRUSTED_PROXIES trusts the RFC 1918 ranges (closes #119)
Merged
#132 Reports are taken only as application/json (closes #126)
Merged
#128 Interval change keeps unreported samples for the reporter (closes #124)
Merged
#127 Move to the layout REPO_POLICIES.md gives (closes #30)
Merged
#115 Re-vendor the shared files from sneak/prompts at dd4027b
Merged
#116 Hetzner checks answer again; failed checks go to the console
Merged
#112 Footer no longer says IPv4 only (closes #111)
Merged
#110 README, TODO and the viewport README say what the tree does (closes #24)
Merged
#108 Latency statistics written once, thresholds read from CONFIG (closes #102)
Merged
#109 Rate limit password attempts on /metrics (closes #104)
Merged
#107 Report handler panics to Sentry when SENTRY_DSN is set (closes #95)
Merged
#105 Target names, URLs and log lines reach the page as text (closes #29)
Merged
#106 Add make add-dependency and make tidy (closes #45)
Merged
#103 Serve Prometheus metrics at /metrics behind basic auth (closes #94)
Merged
#101 Shim make dev and make build, format backend/ markdown (closes #28)
Merged
#100 Move tailwind off the deprecated module.register() (closes #32)
Merged
#99 Frontend unit tests cover durations, colours, statistics and health (closes #21)
Merged
#98 Log fx through slog, snake_case health check keys (closes #27)
Merged
#97 Lint the frontend with eslint in its own Docker stage (closes #47)
Merged
#96 Tap-target check expects a pin button per WAN host row (closes #46)
Merged
#92 Each target's row shows its result as soon as its check ends (closes #91)
Merged
#81 Entrypoint acts as root on nothing outside /data (closes #80)
Merged
#90 Delete the oldest report files to stay under the size cap (closes #54)
Merged
#93 Lint's .golangci.yml check says which fix applies (closes #34)
Merged
#89 Go tests run with -race and -cover under Go's own timeout (closes #88)
Merged
#79 Target check timeout is 80% of the refresh interval (closes #78)
Merged
#87 Stamp the git tag or short commit in a plain docker build (closes #86)
Merged
#84 Remove Buildarch: read the architecture at run time (closes #83)
Merged
#73 next into main
Merged
#76 Container sets up its own data directory (closes #75)
Merged
#72 cibuild: the org model, which runs every check uncached (closes #37)
Merged
#71 chore(backend): re-vendor .golangci.yml with gomodguard_v2 (closes #41)
Merged
#49 next into main: netwatch as one container, ready for upaas
Merged
#70 nginx: security headers on every response (closes #18)
Merged
#69 fix(backend): cut request log fields to the log bound (closes #60)
Merged
#68 nginx: trust X-Forwarded-For only from TRUSTED_PROXIES (closes #64)
Merged
#66 fix(backend): give each report file a name of its own (closes #61)
Merged
#67 upaas: health check, settings checked at start, README section (closes #59)
Merged
#65 nginx: listen on PORT, default 8080; server_tokens off (closes #26)
Merged
#63 fix(backend): rate-limit and cap report ingest, drop wildcard CORS (closes #20)
Merged
#62 build: one image, nginx in front of the backend on loopback (closes #52)
Merged
#38 build: unify the gate so root make check covers the backend (closes #16)
Merged
#55 feat(frontend): post collected samples to /api/v1/reports
Merged
#58 Report ingest correctness: propagate storage failure, 413 on oversize, global body-size cap
Merged
#31 lint: adopt org-standard .golangci.yml and golangci-lint v2.12.2 (closes #14)
Merged
#57 fix(server): shut down through fx so buffered reports flush
Merged
#44 test: automated responsive-layout harness (closes #13)
Merged
#56 feat(backend): server hardening — timeouts, security headers, trusted-proxy client IP
Merged
#51 fix(frontend): meet the 44x44 minimum tap target on every control (closes #43)
Merged
#50 fix: wrap per-host status line so 320px viewport does not scroll (closes #42)
Merged
#40 build: Dockerfile.backend multistage lint stage (closes #17)
Merged
#35 chore: root .editorconfig and hardened .gitignore (closes #15)
Merged
#12 frontend: gate the Docker build on make check (closes #11)
Merged
#10 scripts-to-rule-them-all
Merged
#9 TODO
Merged
#5 feat: responsive mobile layout for host rows (closes #2)
Merged
#3 fix: show 'not available on mobile' message instead of broken layout
Merged
#1 add backend in advance of sending report data
2 Pull requests proposed by 1 user
Proposed
#74 main into prod: netwatch as one container, ready for upaas
Proposed
#85 next → main: data directory safe as root, version from git, 80% target timeout, report retention
95 Issues closed from 2 users
Closed
#162 A bare go statement in server.go; the Go style guide asks for an anonymous function
Closed
#174 .gitignore, .editorconfig and .golangci.yml differ from the sneak/prompts copies the policy is vendored from
Closed
#158 package.json says version 1.0.0 at the v1.0.0-rc1 tag
Closed
#157 TODO.md Status says there are no git tags, but v1.0.0-rc1 is tagged
Closed
#179 netwatch-server starts the server when given arguments it does not understand
Closed
#160 cmd/netwatch-server/main.go carries subcommand dispatch that the Go style guide puts in internal/
Closed
#156 script/build stamps versions from annotated tags only; the image build uses --tags
Closed
#155 .dockerignore lacks the Go test-binary and coverage patterns the checklist asks for
Closed
#153 CI checkout fetches no tags, so the CI-built image stamps the short commit instead of the tag
Closed
#154 script/bootstrap keeps any yarn it finds on PATH; the policy says compare versions, never test presence
Closed
#163 bin/entrypoint.sh is not in the functions-and-main form the shell style guide asks for
Closed
#142 The health check answers ok, and the container stays healthy, while every report is refused with 500
Closed
#150 Two report file writes that fail at the same time put their reports back out of order
Closed
#159 DEBUG accepts only true or false; the code style guide says any non-empty value enables debug mode
Closed
#118 make test takes about 35 seconds, over the 20-second target
Closed
#151 The three discarded-check unit tests check only the row, not that nothing was recorded
Closed
#161 reportbuf numbers report files with atomic.Uint64; the Go style guide asks for int types
Closed
#148 An unusable DATA_DIR stops the standalone server with an error that does not name DATA_DIR
Closed
#141 The page's index.html is served without Cache-Control, so a cached copy can point at assets a new deploy no longer has
Closed
#147 README describes the backend's 413 answer, but in the image nginx answers 413 first with an HTML page
Closed
#146 README does not say that one address at the default limits can replace the whole report store in about 17 minutes
Closed
#145 README says the page keeps its samples while reports are refused; at the 1 s interval one refused report already loses 20 s per host
Closed
#149 A failure in the clock formatter runs before the rounds start and stops the page from probing
Closed
#152 The footer legend puts 500 ms in neither colour band
Closed
#143 prepare-data-dir changes the owner of a file outside /data through a hard link in the volume
Closed
#144 The backend takes the leftmost X-Forwarded-For address from a trusted proxy, so a client behind an appending proxy picks its own address
Closed
#140 After an interval change the summary shows Reachable: 0/26 in red until the second round ends
Closed
#134 yarn install prints "Workspaces can only be enabled in private projects" on every build
Closed
#122 Stopping the server does not wait for a report file already being written, so its reports are lost
Closed
#131 Opening the debug log raises the measured latencies, on the page and in the stored reports
Closed
#129 The backend's own TRUSTED_PROXIES default adds loopback, and empty does not trust nothing
Closed
#123 Reports are answered ok while report files cannot be written, and are lost
Closed
#125 A request whose handler panics is logged, and counted in the metrics, as 200 though it is answered 500
Closed
#119 Unset TRUSTED_PROXIES trusts no proxy; the ruled default is the RFC 1918 ranges
Closed
#126 Another origin's page can store reports through its visitors' browsers
Closed
#124 Changing the interval drops the samples not yet reported to the backend
Closed
#30 Repo layout differs from REPO_POLICIES.md, and backend/ repeats repo-level files
Closed
#120 Defect hunt before the first release candidate: run it as a user, read the code
Closed
#117 yarn install warns three times that workspaces need a private project
Closed
#113 Re-vendor the canonical files from sneak/prompts at dd4027b
Closed
#114 Find why the Hetzner targets fail in the browser, and log every failed check to the console
Closed
#111 Footer says IPv4 only, but checks use whatever the browser picks
Closed
#24 README.md and TODO.md are substantially inaccurate — 14 documented claims contradict the code
Closed
#102 src/main.js: two median functions, four passes over a target's history, thresholds written inline
Closed
#104 Rate limit password attempts on /metrics
Closed
#95 Sentry error reporting when SENTRY_DSN is set
Closed
#29 src/main.js: 1262-line monolith with innerHTML injection sinks, unfrozen CONFIG, and duplicated logic
Closed
#45 No sanctioned way to add a dependency: script/bootstrap is --frozen-lockfile and nothing updates the lockfile
Closed
#94 Prometheus metrics at /metrics behind basic auth when METRICS_USERNAME and METRICS_PASSWORD are set
Closed
#28 script/ and Makefile drift from the org models; make dev is not a shim, make build is missing
Closed
#32 Node deprecation warning DEP0205 emitted on every frontend build
Closed
#21 make test is effectively a no-op: Go tests are compile stubs, frontend has no test framework
Closed
#27 Backend observability: fx logs bypass slog, Identify() is dead, Sentry/Prometheus config is parsed but unwired
Closed
#47 Run all linting in Docker via Dockerfile.lint + script/lint
Closed
#46 Viewport harness: derive .pin-btn presence floor from rowCount, and correct two overclaiming statements
Closed
#91 Each target's result shows as soon as its check ends, not when the round's slowest check ends
Closed
#80 Entrypoint acts as root on DATA_DIR before checking it: creates outside /data, accepts paths outside /data
Closed
#54 Retention: prune old report files in DATA_DIR
Closed
#34 golangci config drift guard: failure message loops the operator when the org standard legitimately updates
Closed
#88 Go tests run with -race and -cover under Go's own timeout; remaining handler and report-file tests
Closed
#78 Target timeout is 80% of the refresh interval
Closed
#33 make hooks and make docker both fail when run from a git worktree
Closed
#86 docker build . stamps dev, not the git tag or short commit
Closed
#36 Exclude .git from .dockerignore once the builds no longer read git metadata
Closed
#83 Remove Buildarch: read the architecture at run time with runtime.GOARCH
Closed
#82 Run every build, test and lint step in the Dockerfiles at nice -n 19
Closed
#77 Entrypoint changes a mode through a symbolic link in the data directory
Closed
#75 The container sets its data directory permissions itself before startup
Closed
#37 CI can report a green it did not earn: script/cibuild serves make check from the Docker layer cache
Closed
#41 golangci-lint v2.12.2 deprecates the gomodguard linter; migrate to gomodguard_v2
Closed
#53 Frontend reporting client: POST collected samples to /api/v1/reports
Closed
#22 Shutdown is broken: os.Exit races fx OnStop hooks, losing buffered reports on every restart
Closed
#23 Report ingest correctness: returns 200 on storage failure, 400 on oversize, logs untrusted body
Closed
#18 Frontend image serves zero security headers; add the full REPO_POLICIES set to nginx.conf
Closed
#60 Request log writes URL, User-Agent and Referer with no length limit
Closed
#64 nginx trusts X-Forwarded-For from every private address, so the rate limit can be dodged
Closed
#61 Two report flushes in the same millisecond collide on the file name
Closed
#59 Ready to run under upaas on fsn1app1: prod branch, settings from env, health check, README section
Closed
#26 nginx: PORT env override is documented but does not exist; add it and server_tokens off
Closed
#20 POST /api/v1/reports is unauthenticated, wildcard-CORS, and unrated-limited
Closed
#52 Ship one container image: nginx serves the frontend and proxies /api to the backend in the same container
Closed
#39 Follow-ups from PR #38: bootstrap re-extract guard, message attribution, and the #31 rebase reconciliation
Closed
#16 Unify the gate: root make check must cover the backend, and CI must route through script/
Closed
#14 Adopt the org-standard .golangci.yml and golangci-lint v2.12.2
Closed
#13 QA: test responsive mobile layout on real devices
Closed
#19 Backend hardening: missing IdleTimeout/ReadHeaderTimeout, no security headers, no trusted-proxy client IP
Closed
#25 Decision needed: the backend is not connected to anything — does it ship in 1.0?
Closed
#48 TOP PRIORITY: consolidate all open PRs onto one next branch, one PR
Closed
#43 Mobile: every interactive control is below the 44x44 minimum tap target
Closed
#42 Mobile: per-host status line forces horizontal page scroll at 320px
Closed
#17 Rework Dockerfile.backend to the mandated Go multistage lint-stage pattern
Closed
#15 Dotfile compliance: add root .editorconfig, harden .gitignore, exclude .git from .dockerignore
Closed
#4 Add mobile detection: show "Not yet available on mobile" message
Closed
#11 Frontend Dockerfile CI build does not run make check (only yarn build)
Closed
#2 broken on mobile
97 Issues created by 1 user
Opened
#2 broken on mobile
Opened
#4 Add mobile detection: show "Not yet available on mobile" message
Opened
#11 Frontend Dockerfile CI build does not run make check (only yarn build)
Opened
#13 QA: test responsive mobile layout on real devices
Opened
#14 Adopt the org-standard .golangci.yml and golangci-lint v2.12.2
Opened
#15 Dotfile compliance: add root .editorconfig, harden .gitignore, exclude .git from .dockerignore
Opened
#16 Unify the gate: root make check must cover the backend, and CI must route through script/
Opened
#17 Rework Dockerfile.backend to the mandated Go multistage lint-stage pattern
Opened
#18 Frontend image serves zero security headers; add the full REPO_POLICIES set to nginx.conf
Opened
#19 Backend hardening: missing IdleTimeout/ReadHeaderTimeout, no security headers, no trusted-proxy client IP
Opened
#20 POST /api/v1/reports is unauthenticated, wildcard-CORS, and unrated-limited
Opened
#21 make test is effectively a no-op: Go tests are compile stubs, frontend has no test framework
Opened
#22 Shutdown is broken: os.Exit races fx OnStop hooks, losing buffered reports on every restart
Opened
#23 Report ingest correctness: returns 200 on storage failure, 400 on oversize, logs untrusted body
Opened
#24 README.md and TODO.md are substantially inaccurate — 14 documented claims contradict the code
Opened
#25 Decision needed: the backend is not connected to anything — does it ship in 1.0?
Opened
#26 nginx: PORT env override is documented but does not exist; add it and server_tokens off
Opened
#27 Backend observability: fx logs bypass slog, Identify() is dead, Sentry/Prometheus config is parsed but unwired
Opened
#28 script/ and Makefile drift from the org models; make dev is not a shim, make build is missing
Opened
#29 src/main.js: 1262-line monolith with innerHTML injection sinks, unfrozen CONFIG, and duplicated logic
Opened
#30 Repo layout differs from REPO_POLICIES.md, and backend/ repeats repo-level files
Opened
#32 Node deprecation warning DEP0205 emitted on every frontend build
Opened
#33 make hooks and make docker both fail when run from a git worktree
Opened
#34 golangci config drift guard: failure message loops the operator when the org standard legitimately updates
Opened
#36 Exclude .git from .dockerignore once the builds no longer read git metadata
Opened
#37 CI can report a green it did not earn: script/cibuild serves make check from the Docker layer cache
Opened
#39 Follow-ups from PR #38: bootstrap re-extract guard, message attribution, and the #31 rebase reconciliation
Opened
#41 golangci-lint v2.12.2 deprecates the gomodguard linter; migrate to gomodguard_v2
Opened
#42 Mobile: per-host status line forces horizontal page scroll at 320px
Opened
#43 Mobile: every interactive control is below the 44x44 minimum tap target
Opened
#45 No sanctioned way to add a dependency: script/bootstrap is --frozen-lockfile and nothing updates the lockfile
Opened
#46 Viewport harness: derive .pin-btn presence floor from rowCount, and correct two overclaiming statements
Opened
#47 Run all linting in Docker via Dockerfile.lint + script/lint
Opened
#48 TOP PRIORITY: consolidate all open PRs onto one next branch, one PR
Opened
#52 Ship one container image: nginx serves the frontend and proxies /api to the backend in the same container
Opened
#53 Frontend reporting client: POST collected samples to /api/v1/reports
Opened
#54 Retention: prune old report files in DATA_DIR
Opened
#59 Ready to run under upaas on fsn1app1: prod branch, settings from env, health check, README section
Opened
#60 Request log writes URL, User-Agent and Referer with no length limit
Opened
#61 Two report flushes in the same millisecond collide on the file name
Opened
#64 nginx trusts X-Forwarded-For from every private address, so the rate limit can be dodged
Opened
#75 The container sets its data directory permissions itself before startup
Opened
#77 Entrypoint changes a mode through a symbolic link in the data directory
Opened
#78 Target timeout is 80% of the refresh interval
Opened
#80 Entrypoint acts as root on DATA_DIR before checking it: creates outside /data, accepts paths outside /data
Opened
#82 Run every build, test and lint step in the Dockerfiles at nice -n 19
Opened
#83 Remove Buildarch: read the architecture at run time with runtime.GOARCH
Opened
#86 docker build . stamps dev, not the git tag or short commit
Opened
#88 Go tests run with -race and -cover under Go's own timeout; remaining handler and report-file tests
Opened
#91 Each target's result shows as soon as its check ends, not when the round's slowest check ends
Opened
#94 Prometheus metrics at /metrics behind basic auth when METRICS_USERNAME and METRICS_PASSWORD are set
Opened
#95 Sentry error reporting when SENTRY_DSN is set
Opened
#102 src/main.js: two median functions, four passes over a target's history, thresholds written inline
Opened
#104 Rate limit password attempts on /metrics
Opened
#111 Footer says IPv4 only, but checks use whatever the browser picks
Opened
#113 Re-vendor the canonical files from sneak/prompts at dd4027b
Opened
#114 Find why the Hetzner targets fail in the browser, and log every failed check to the console
Opened
#117 yarn install warns three times that workspaces need a private project
Opened
#118 make test takes about 35 seconds, over the 20-second target
Opened
#119 Unset TRUSTED_PROXIES trusts no proxy; the ruled default is the RFC 1918 ranges
Opened
#120 Defect hunt before the first release candidate: run it as a user, read the code
Opened
#122 Stopping the server does not wait for a report file already being written, so its reports are lost
Opened
#123 Reports are answered ok while report files cannot be written, and are lost
Opened
#124 Changing the interval drops the samples not yet reported to the backend
Opened
#125 A request whose handler panics is logged, and counted in the metrics, as 200 though it is answered 500
Opened
#126 Another origin's page can store reports through its visitors' browsers
Opened
#129 The backend's own TRUSTED_PROXIES default adds loopback, and empty does not trust nothing
Opened
#131 Opening the debug log raises the measured latencies, on the page and in the stored reports
Opened
#134 yarn install prints "Workspaces can only be enabled in private projects" on every build
Opened
#139 netwatch 1.0
Opened
#140 After an interval change the summary shows Reachable: 0/26 in red until the second round ends
Opened
#146 README does not say that one address at the default limits can replace the whole report store in about 17 minutes
Opened
#145 README says the page keeps its samples while reports are refused; at the 1 s interval one refused report already loses 20 s per host
Opened
#143 prepare-data-dir changes the owner of a file outside /data through a hard link in the volume
Opened
#142 The health check answers ok, and the container stays healthy, while every report is refused with 500
Opened
#141 The page's index.html is served without Cache-Control, so a cached copy can point at assets a new deploy no longer has
Opened
#144 The backend takes the leftmost X-Forwarded-For address from a trusted proxy, so a client behind an appending proxy picks its own address
Opened
#147 README describes the backend's 413 answer, but in the image nginx answers 413 first with an HTML page
Opened
#148 An unusable DATA_DIR stops the standalone server with an error that does not name DATA_DIR
Opened
#149 A failure in the clock formatter runs before the rounds start and stops the page from probing
Opened
#150 Two report file writes that fail at the same time put their reports back out of order
Opened
#151 The three discarded-check unit tests check only the row, not that nothing was recorded
Opened
#152 The footer legend puts 500 ms in neither colour band
Opened
#155 .dockerignore lacks the Go test-binary and coverage patterns the checklist asks for
Opened
#157 TODO.md Status says there are no git tags, but v1.0.0-rc1 is tagged
Opened
#156 script/build stamps versions from annotated tags only; the image build uses --tags
Opened
#154 script/bootstrap keeps any yarn it finds on PATH; the policy says compare versions, never test presence
Opened
#153 CI checkout fetches no tags, so the CI-built image stamps the short commit instead of the tag
Opened
#158 package.json says version 1.0.0 at the v1.0.0-rc1 tag
Opened
#159 DEBUG accepts only true or false; the code style guide says any non-empty value enables debug mode
Opened
#160 cmd/netwatch-server/main.go carries subcommand dispatch that the Go style guide puts in internal/
Opened
#161 reportbuf numbers report files with atomic.Uint64; the Go style guide asks for int types
Opened
#162 A bare go statement in server.go; the Go style guide asks for an anonymous function
Opened
#163 bin/entrypoint.sh is not in the functions-and-main form the shell style guide asks for
Opened
#174 .gitignore, .editorconfig and .golangci.yml differ from the sneak/prompts copies the policy is vendored from
Opened
#179 netwatch-server starts the server when given arguments it does not understand
Opened
#189 Rewrite README.md and the other prose documents sentence by sentence, on Fable