From 0900de4b958e1edf3b5c134d10356f0eb8d5de56 Mon Sep 17 00:00:00 2001 From: clawbot <35+clawbot@noreply.example.org> Date: Sun, 4 Oct 2026 01:15:30 +0000 Subject: [PATCH] Shim make dev and make build, format backend/ markdown (closes #28) make dev ran yarn dev inline and there was no make build. Both are now shims, over script/dev and the new script/build. .prettierignore stops leaving out backend/, so backend/README.md is formatted and checked; backend/.golangci.yml is left out by name instead: it is the org standard file whose sha256 backend/script/lint checks, and prettier would reindent it. .claude/ stays in .prettierignore, as git does not ignore it. script/install-precommit and the date on bootstrap's pins go back to the org model; bootstrap, fmt and fmt-check keep what the Go backend and eslint need, each with a comment saying so. Model: opus-5-5 --- .prettierignore | 3 ++- Makefile | 10 +++++++--- README.md | 7 ++++++- TODO.md | 10 ++++++++++ backend/README.md | 36 ++++++++++++++++++------------------ script/bootstrap | 4 +++- script/build | 13 +++++++++++++ script/dev | 13 +++++++++++++ script/fmt | 1 + script/fmt-check | 1 + script/frontend-fmt | 4 ++-- script/install-precommit | 4 ++-- 12 files changed, 78 insertions(+), 28 deletions(-) create mode 100755 script/build create mode 100755 script/dev diff --git a/.prettierignore b/.prettierignore index d0374bc..ddbaa34 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,7 @@ -backend/ dist/ node_modules/ tmp/ yarn.lock .claude/ +# The org standard file, copied verbatim; backend/script/lint checks its sha256. +backend/.golangci.yml diff --git a/Makefile b/Makefile index 211f8b8..3369fb9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -.PHONY: bootstrap setup dev test lint fmt fmt-check check frontend-check \ - frontend-viewport-test docker hooks +.PHONY: bootstrap setup dev build test lint fmt fmt-check check \ + frontend-check frontend-viewport-test docker hooks # Standard targets are thin shims; the implementations live in script/ # per the scripts-to-rule-them-all pattern (see the Entrypoints section @@ -13,7 +13,11 @@ setup: @script/setup dev: - yarn dev + @script/dev + +# The frontend only; backend/Makefile's build target builds the Go server. +build: + @script/build test: @script/test diff --git a/README.md b/README.md index 0a9c256..b9ab277 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,10 @@ halves, so the root `make check` fails if either one is broken. We provide: both linters in Docker - `script/setup` — make a fresh clone ready for development: bootstrap plus the git pre-commit hook +- `script/dev` — run the Vite dev server, which proxies `/api` to a locally + running `netwatch-server` +- `script/build` — build the frontend for production into `dist/`; + `backend/script/build` builds the Go server - `script/projectname` — print the project name (used for the Docker image tag) - `script/test` — run `script/frontend-test`, then `backend/script/test`, the backend's Go tests with the race detector and coverage @@ -61,7 +65,8 @@ halves, so the root `make check` fails if either one is broken. We provide: - `script/frontend-lint` — run eslint with the rules in `eslint.config.js`; it runs inside the `frontend-lint` stage of `Dockerfile`, which `make lint` builds -- `script/frontend-fmt` — format everything prettier understands (writes) +- `script/frontend-fmt` — format everything prettier understands (writes), the + markdown in `backend/` included - `script/frontend-fmt-check` — check prettier formatting (read-only) - `script/frontend-check` — run `script/frontend-test` and `script/frontend-fmt-check`, for the frontend stage of `Dockerfile`, which has diff --git a/TODO.md b/TODO.md index c5a618c..e234b46 100644 --- a/TODO.md +++ b/TODO.md @@ -23,6 +23,16 @@ latest run passes. # Completed Steps +- 2026-10-04: `script/` and `Makefile` follow the org models (issue #28): + `make dev` shims to the new `script/dev`, the Vite dev server, and the new + `make build` to `script/build`, the frontend production build. + `.prettierignore` no longer leaves out `backend/`, so `make fmt` and + `make fmt-check` cover `backend/README.md`; it leaves out + `backend/.golangci.yml` by name, the org standard file whose sha256 + `backend/script/lint` checks. `script/install-precommit` and the date on + `script/bootstrap`'s pins are the org model again; `script/bootstrap`, + `script/fmt` and `script/fmt-check` each say in a comment why they differ from + it - 2026-10-04: a frontend build on Node 26 or newer, such as `make test` on a host with Node 26, no longer prints Node's warning that `module.register()` is deprecated (issue #32); the build in `Dockerfile` runs on Node 22, which never diff --git a/backend/README.md b/backend/README.md index 42faf05..a9498d2 100644 --- a/backend/README.md +++ b/backend/README.md @@ -32,17 +32,16 @@ pattern as the repo root: the targets in `backend/Makefile` are thin shims over `test`, `fmt` and `fmt-check`: - `script/build` — compile the static `netwatch-server` binary with its version - stamped in. The version is `VERSION` from the environment; - when that is unset or empty, it falls back to `git describe` inside a git - checkout, then to `dev` + stamped in. The version is `VERSION` from the environment; when that is unset + or empty, it falls back to `git describe` inside a git checkout, then to `dev` - `script/test` — run the Go tests with the race detector and coverage. Go's `-timeout 30s` bounds the tests, not their compile. If they fail, they run again with `-v` for the details, and the script fails. The race detector needs a C compiler - `script/lint` — check `.golangci.yml` against its pinned sha256, then run - golangci-lint. It runs inside the golangci-lint image of the lint stage of - the root `Dockerfile`; from a checkout, run `make lint` at the repo root, - which builds that stage + golangci-lint. It runs inside the golangci-lint image of the lint stage of the + root `Dockerfile`; from a checkout, run `make lint` at the repo root, which + builds that stage - `script/fmt` — format the Go sources (writes) - `script/fmt-check` — check Go formatting (read-only) - `script/run` — build and run the server locally @@ -61,8 +60,9 @@ flushes them to compressed files on disk for later analysis. ## Design -The server is structured as an `fx`-wired Go application under `cmd/netwatch-server/`. -Internal packages in `internal/` follow standard Go project layout: +The server is structured as an `fx`-wired Go application under +`cmd/netwatch-server/`. Internal packages in `internal/` follow standard Go +project layout: - **`config`**: Loads configuration from environment variables and config files via Viper. @@ -89,11 +89,12 @@ Internal packages in `internal/` follow standard Go project layout: | `REPORTS_PER_MINUTE` | `60` | Reports each client address may send a minute; see [Report limits](#report-limits) | | `CORS_ALLOWED_ORIGINS` | empty | Comma-separated origins whose pages may call the API; see [CORS](#cors) | -`TRUSTED_PROXIES` defaults to `127.0.0.1/32,::1/128,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16`. -The loopback entries cover a reverse proxy on the same host. A request whose -direct peer is outside this set has its forwarded headers ignored, and the -direct peer is logged and rate-limited instead. The container image does not use -this default; see [Container image](#container-image). +`TRUSTED_PROXIES` defaults to +`127.0.0.1/32,::1/128,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16`. The loopback +entries cover a reverse proxy on the same host. A request whose direct peer is +outside this set has its forwarded headers ignored, and the direct peer is +logged and rate-limited instead. The container image does not use this default; +see [Container image](#container-image). A variable set to a value the server cannot use, such as `PORT=abc`, `DEBUG=maybe` or a `BIND_ADDRESS` that is not an IP address, stops it from @@ -109,9 +110,9 @@ only nginx reaches it, and with `TRUSTED_PROXIES=127.0.0.1/32`, so it takes the client address nginx passes on and no other. `DATA_DIR` is `/data/reports`, on the `/data` volume; before starting the server, the entrypoint creates it and gives it and `/data` to `netwatch` with `netwatch-server prepare-data-dir`, -which acts on nothing outside `/data`. nginx replaces the security headers -this server sets with those in the root `security-headers.conf`, so those are -what clients of the image see. +which acts on nothing outside `/data`. nginx replaces the security headers this +server sets with those in the root `security-headers.conf`, so those are what +clients of the image see. The container's own `TRUSTED_PROXIES` goes to nginx instead: IP addresses or CIDRs, separated by commas, of the reverse proxies in front of the container. @@ -162,8 +163,7 @@ credentials, so it is bounded instead. Both refusals below answer with the same to be written fill the cap on their own, and then no file is deleted. At start, report files past the cap, as after lowering it, are deleted the same way. So the cap is how much of the newest reports is kept: the default of 1 - GiB is small enough for any host; set it to the space you can give - `DATA_DIR`. + GiB is small enough for any host; set it to the space you can give `DATA_DIR`. ### CORS diff --git a/script/bootstrap b/script/bootstrap index 7d06df7..d708c81 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -17,11 +17,13 @@ # # golangci-lint is not installed: make lint runs it in Docker, which # this script does not install either. +# +# Unlike the org model: Go and gcc for backend/, a newer node for eslint. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" -# Pinned versions, 2026-07-07 +# Pinned versions, 2026-07-06 NODE_VERSION="22.17.0" # The oldest node the frontend's dependencies accept: the "engines" # field of eslint 10.12.0, the most demanding of them, asks for 22.13.0 diff --git a/script/build b/script/build new file mode 100755 index 0000000..68c4bcb --- /dev/null +++ b/script/build @@ -0,0 +1,13 @@ +#!/bin/sh +# script/build: build the frontend for production into dist/. The Go +# backend is built by backend/script/build. +set -eu + +ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" + +main() { + cd "$ROOT" + yarn build +} + +main "$@" diff --git a/script/dev b/script/dev new file mode 100755 index 0000000..7f879bd --- /dev/null +++ b/script/dev @@ -0,0 +1,13 @@ +#!/bin/sh +# script/dev: run the frontend's Vite dev server. It proxies /api to a +# netwatch-server running locally (see vite.config.js). +set -eu + +ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" + +main() { + cd "$ROOT" + yarn dev +} + +main "$@" diff --git a/script/fmt b/script/fmt index 7270800..0b3eb52 100755 --- a/script/fmt +++ b/script/fmt @@ -1,6 +1,7 @@ #!/bin/sh # script/fmt: format the whole repo (writes): prettier over everything # it understands, then gofmt over the Go backend. +# The org model formats only markdown; this repo also has JS and Go. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" diff --git a/script/fmt-check b/script/fmt-check index 28518f7..bee557b 100755 --- a/script/fmt-check +++ b/script/fmt-check @@ -1,6 +1,7 @@ #!/bin/sh # script/fmt-check: check formatting across the whole repo (read-only). # Same scope as script/fmt, but fails instead of writing. +# The org model checks only markdown; this repo also has JS and Go. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" diff --git a/script/frontend-fmt b/script/frontend-fmt index 1af33b9..523497a 100755 --- a/script/frontend-fmt +++ b/script/frontend-fmt @@ -1,7 +1,7 @@ #!/bin/sh # script/frontend-fmt: format the frontend and every other file prettier -# understands, repo-wide (writes). backend/ is in .prettierignore; Go -# sources are formatted by backend/script/fmt. +# understands, repo-wide (writes), the markdown in backend/ included. +# Prettier does not read Go; backend/script/fmt formats the Go sources. set -eu ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" diff --git a/script/install-precommit b/script/install-precommit index 723bae1..bef6406 100755 --- a/script/install-precommit +++ b/script/install-precommit @@ -8,8 +8,8 @@ ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" main() { cd "$ROOT" hook=".git/hooks/pre-commit" - printf '#!/bin/sh\nset -e\nscript/precommit\n' > "$hook" - chmod +x "$hook" + printf '#!/bin/sh\nset -e\nscript/precommit\n' > .git/hooks/pre-commit + chmod +x .git/hooks/pre-commit echo "pre-commit hook installed: runs script/precommit" } -- 2.54.0