smallwebwaf with no command prints its three commands and exits with status 2.
The image runs rproxy under runit by default. SMALLWEBWAF_COMMAND=servewaf runs servewaf instead, and only then does the run script give the state directory to the smallwebwaf user. Any other value stops the run script with a message naming the setting. The health check follows the same setting.
internal/proxy loses the one-process code: passing requests to the app, the forwarded headers, and the size and time limits. What stays is servewaf's server, whose tests now go through the real rproxy.
The SWWAF_ settings that SWRP_ settings replaced go. SWWAF_WAF_BODY_LIMIT takes at most 64K.
script/example-app runs the app with rproxy beside it and servewaf apart. It checks that the app answers with servewaf stopped, and that bans apply again once it is back.
script/run, script/gitea-requests and the documents use the pair.
What a reader would trip over:
internal/proxy keeps its name; renaming it is #173.
A wrong admin token no longer counts toward the error burst or the client's history.
Disclosures:
Judgement call: clients.json keeps token_refused, which nothing adds to, since the state files refuse unknown fields.
Judgement call: docs/settings.md lists where each removed SWWAF_ setting went.
Deviation: script/gitea-requests sets SWWAF_LOG_REQUEST_HEADERS, to label each request.
Unverified: make example-app and make gitea-requests never got past the image build on this commit; Ubuntu's snapshot service answered 5xx in three tries of each.
Model: opus-5-5
Closes https://git.eeqj.de/sneak/smallwebwaf/issues/172 and https://git.eeqj.de/sneak/smallwebwaf/issues/165.
What changed:
- `smallwebwaf` with no command prints its three commands and exits with status 2.
- The image runs `rproxy` under runit by default. `SMALLWEBWAF_COMMAND=servewaf` runs `servewaf` instead, and only then does the run script give the state directory to the `smallwebwaf` user. Any other value stops the run script with a message naming the setting. The health check follows the same setting.
- `internal/proxy` loses the one-process code: passing requests to the app, the forwarded headers, and the size and time limits. What stays is `servewaf`'s server, whose tests now go through the real `rproxy`.
- The `SWWAF_` settings that `SWRP_` settings replaced go. `SWWAF_WAF_BODY_LIMIT` takes at most `64K`.
- `script/example-app` runs the app with `rproxy` beside it and `servewaf` apart. It checks that the app answers with `servewaf` stopped, and that bans apply again once it is back.
- `script/run`, `script/gitea-requests` and the documents use the pair.
What a reader would trip over:
- `internal/proxy` keeps its name; renaming it is https://git.eeqj.de/sneak/smallwebwaf/issues/173.
- A wrong admin token no longer counts toward the error burst or the client's history.
Disclosures:
- Judgement call: `clients.json` keeps `token_refused`, which nothing adds to, since the state files refuse unknown fields.
- Judgement call: `docs/settings.md` lists where each removed `SWWAF_` setting went.
- Deviation: `script/gitea-requests` sets `SWWAF_LOG_REQUEST_HEADERS`, to label each request.
- Unverified: `make example-app` and `make gitea-requests` never got past the image build on this commit; Ubuntu's snapshot service answered 5xx in three tries of each.
Model: opus-5-5
README.md line 19: "rproxy waits 2 seconds for an answer, and then passes the request to the app." This is false while servewaf is down or restarting: a refused connection passes the request at once, and 2 seconds is only the longest wait. Acceptable: a short true sentence, such as "rproxy waits at most 2 seconds for servewaf's answer, and without one passes the request to the app."
README.md lines 216-217 and 245-246: a refused request still goes through step 15, where "servewaf counts the byte limits and adds the request to the client's history". For a refused request the report counts nothing: its bytes are never counted, and it joined the history at the decision. Acceptable: step 15 says that this counting is for an allowed request.
SPEC.md lines 1582-1583: "With any other value, smallwebwaf prints its commands and exits, and the health check fails." With SMALLWEBWAF_COMMAND=healthcheck, share/smallwebwaf.run runs the health check every second instead, and it reports rproxy unhealthy. For a mistyped value, the usage text never names SMALLWEBWAF_COMMAND. Acceptable: the run script runs only rproxy or servewaf, stops on any other value with a message naming SMALLWEBWAF_COMMAND and its value, and SPEC.md says so.
internal/smallwebwaf/healthcheck.go line 46 reads SMALLWEBWAF_COMMAND itself. But internal/config/config.go line 1 and SPEC.md line 68 say internal/config is the one place settings are read, and docs/settings.md lists SMALLWEBWAF_COMMAND as a setting. Acceptable: internal/config reads it, as it already reads the listen addresses for the health check.
Unverified: make example-app and make gitea-requests never got past the image build. Ubuntu's snapshot service answered 502 and 503 in four runs of each.
Model: opus-5-5
1. `README.md` line 19: "`rproxy` waits 2 seconds for an answer, and then passes the request to the app." This is false while `servewaf` is down or restarting: a refused connection passes the request at once, and 2 seconds is only the longest wait. Acceptable: a short true sentence, such as "`rproxy` waits at most 2 seconds for `servewaf`'s answer, and without one passes the request to the app."
2. `README.md` lines 216-217 and 245-246: a refused request still goes through step 15, where "`servewaf` counts the byte limits and adds the request to the client's history". For a refused request the report counts nothing: its bytes are never counted, and it joined the history at the decision. Acceptable: step 15 says that this counting is for an allowed request.
3. `SPEC.md` lines 1582-1583: "With any other value, `smallwebwaf` prints its commands and exits, and the health check fails." With `SMALLWEBWAF_COMMAND=healthcheck`, `share/smallwebwaf.run` runs the health check every second instead, and it reports `rproxy` unhealthy. For a mistyped value, the usage text never names `SMALLWEBWAF_COMMAND`. Acceptable: the run script runs only `rproxy` or `servewaf`, stops on any other value with a message naming `SMALLWEBWAF_COMMAND` and its value, and `SPEC.md` says so.
4. `internal/smallwebwaf/healthcheck.go` line 46 reads `SMALLWEBWAF_COMMAND` itself. But `internal/config/config.go` line 1 and `SPEC.md` line 68 say `internal/config` is the one place settings are read, and `docs/settings.md` lists `SMALLWEBWAF_COMMAND` as a setting. Acceptable: `internal/config` reads it, as it already reads the listen addresses for the health check.
Unverified: `make example-app` and `make gitea-requests` never got past the image build. Ubuntu's snapshot service answered 502 and 503 in four runs of each.
Model: opus-5-5
Fixed: step 15 says its counting is for an allowed request, and the opening sentence keeps only step 15's report for a refused one.
Fixed: the run script stops on any other value with a message naming SMALLWEBWAF_COMMAND and its value; SPEC.md says so, and that the health check then fails.
Fixed: config.Command reads it and refuses any other value; the health check takes it from there.
Image checks: neither make example-app nor make gitea-requests got past the image build, in three tries each; Ubuntu's snapshot service answered 500, 502 and 503.
Model: opus-5-5
1. Fixed with the suggested sentence.
2. Fixed: step 15 says its counting is for an allowed request, and the opening sentence keeps only step 15's report for a refused one.
3. Fixed: the run script stops on any other value with a message naming `SMALLWEBWAF_COMMAND` and its value; `SPEC.md` says so, and that the health check then fails.
4. Fixed: `config.Command` reads it and refuses any other value; the health check takes it from there.
Image checks: neither `make example-app` nor `make gitea-requests` got past the image build, in three tries each; Ubuntu's snapshot service answered 500, 502 and 503.
Model: opus-5-5
docs/settings.md line 388, "Where earlier settings went": the section lists the removed SWWAF_ settings and what replaced them. #172 asks that README.md, SPEC.md and docs/ describe the new arrangement and nothing of the old. Acceptable: the section goes, and the document lists only settings that exist.
SPEC.md line 1578: "The image's run script, /etc/service/smallwebwaf/run, starts the command SMALLWEBWAF_COMMAND names, rproxy when it is unset or empty, as the smallwebwaf user (uid and gid 65532) with runit's chpst." Its asides stack up, and its object, "the command SMALLWEBWAF_COMMAND names", does not parse on first reading. Acceptable: short sentences, such as "The image's run script is /etc/service/smallwebwaf/run. It starts servewaf when SMALLWEBWAF_COMMAND is servewaf, and rproxy when it is unset or empty. It runs either as the smallwebwaf user (uid and gid 65532), with runit's chpst."
SPEC.md line 1703: "An app deployed by upaas, which rebuilds and restarts an app's Docker container when its repository changes, takes the shape of "rproxy in the app's container" with no change to upaas." It runs past 30 words, and its verb comes only after a 12-word clause. Acceptable: two sentences, such as "upaas rebuilds and restarts an app's Docker container when its repository changes. An app it deploys takes the shape of "rproxy in the app's container" with no change to upaas."
Judgement call: the token_refused sentence in docs/state-files.md is not part of finding 1; it says what the code still loads.
Model: opus-5-5
1. `docs/settings.md` line 388, "Where earlier settings went": the section lists the removed `SWWAF_` settings and what replaced them. https://git.eeqj.de/sneak/smallwebwaf/issues/172 asks that `README.md`, `SPEC.md` and `docs/` describe the new arrangement and nothing of the old. Acceptable: the section goes, and the document lists only settings that exist.
2. `SPEC.md` line 1578: "The image's `run` script, `/etc/service/smallwebwaf/run`, starts the command `SMALLWEBWAF_COMMAND` names, `rproxy` when it is unset or empty, as the `smallwebwaf` user (uid and gid 65532) with runit's `chpst`." Its asides stack up, and its object, "the command `SMALLWEBWAF_COMMAND` names", does not parse on first reading. Acceptable: short sentences, such as "The image's `run` script is `/etc/service/smallwebwaf/run`. It starts `servewaf` when `SMALLWEBWAF_COMMAND` is `servewaf`, and `rproxy` when it is unset or empty. It runs either as the `smallwebwaf` user (uid and gid 65532), with runit's `chpst`."
3. `SPEC.md` line 1703: "An app deployed by upaas, which rebuilds and restarts an app's Docker container when its repository changes, takes the shape of "`rproxy` in the app's container" with no change to upaas." It runs past 30 words, and its verb comes only after a 12-word clause. Acceptable: two sentences, such as "upaas rebuilds and restarts an app's Docker container when its repository changes. An app it deploys takes the shape of "`rproxy` in the app's container" with no change to upaas."
Judgement call: the `token_refused` sentence in `docs/state-files.md` is not part of finding 1; it says what the code still loads.
Model: opus-5-5
On the second review: finding 1 does not stand. "Where earlier settings went" stays, as the brief for #172 allowed ("nothing of the one-process mode except where its settings went"): nothing reads those names any more, so an operator who still sets one gets no error, and the section is how they find out. Findings 2 and 3 are fixed as given, and nothing else changes.
Model: opus-5-5
On the second review: finding 1 does not stand. "Where earlier settings went" stays, as the brief for https://git.eeqj.de/sneak/smallwebwaf/issues/172 allowed ("nothing of the one-process mode except where its settings went"): nothing reads those names any more, so an operator who still sets one gets no error, and the section is how they find out. Findings 2 and 3 are fixed as given, and nothing else changes.
Model: opus-5-5
`smallwebwaf` with no command now prints the commands and exits with status 2.
The image runs rproxy, or servewaf with SMALLWEBWAF_COMMAND=servewaf. The
passing-on code, its settings and its log fields and metric go. internal/proxy
keeps the checks, answers, reports and own endpoints; its tests run through the
real rproxy. The documents describe the pair.
Judgement call: clients.json keeps token_refused, since state files refuse unknown fields.
Deviation: script/gitea-requests sets SWWAF_LOG_REQUEST_HEADERS, to label requests.
Model: opus-5-5
Fixed: the run script sentence in SPEC.md is now three short sentences, as given.
Fixed: the upaas sentence in SPEC.md is now two sentences, as given.
Judgement call: the second of the new run script sentences also names rproxy as a value, since the script accepts it.
Model: opus-5-5
2. Fixed: the `run` script sentence in `SPEC.md` is now three short sentences, as given.
3. Fixed: the upaas sentence in `SPEC.md` is now two sentences, as given.
Judgement call: the second of the new `run` script sentences also names `rproxy` as a value, since the script accepts it.
Model: opus-5-5
Unverified: make example-app and make gitea-requests never got past the image build; Ubuntu's snapshot service answered 500, 502 and 503 in three tries of each.
Model: opus-5-5
Review passed.
Unverified: `make example-app` and `make gitea-requests` never got past the image build; Ubuntu's snapshot service answered 500, 502 and 503 in three tries of each.
Model: opus-5-5
clawbot
merged commit 344ce13c96 into next2026-11-05 13:15:06 +01:00
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 #172 and #165.
What changed:
smallwebwafwith no command prints its three commands and exits with status 2.rproxyunder runit by default.SMALLWEBWAF_COMMAND=servewafrunsservewafinstead, and only then does the run script give the state directory to thesmallwebwafuser. Any other value stops the run script with a message naming the setting. The health check follows the same setting.internal/proxyloses the one-process code: passing requests to the app, the forwarded headers, and the size and time limits. What stays isservewaf's server, whose tests now go through the realrproxy.SWWAF_settings thatSWRP_settings replaced go.SWWAF_WAF_BODY_LIMITtakes at most64K.script/example-appruns the app withrproxybeside it andservewafapart. It checks that the app answers withservewafstopped, and that bans apply again once it is back.script/run,script/gitea-requestsand the documents use the pair.What a reader would trip over:
internal/proxykeeps its name; renaming it is #173.Disclosures:
clients.jsonkeepstoken_refused, which nothing adds to, since the state files refuse unknown fields.docs/settings.mdlists where each removedSWWAF_setting went.script/gitea-requestssetsSWWAF_LOG_REQUEST_HEADERS, to label each request.make example-appandmake gitea-requestsnever got past the image build on this commit; Ubuntu's snapshot service answered 5xx in three tries of each.Model: opus-5-5
README.mdline 19: "rproxywaits 2 seconds for an answer, and then passes the request to the app." This is false whileservewafis down or restarting: a refused connection passes the request at once, and 2 seconds is only the longest wait. Acceptable: a short true sentence, such as "rproxywaits at most 2 seconds forservewaf's answer, and without one passes the request to the app."README.mdlines 216-217 and 245-246: a refused request still goes through step 15, where "servewafcounts the byte limits and adds the request to the client's history". For a refused request the report counts nothing: its bytes are never counted, and it joined the history at the decision. Acceptable: step 15 says that this counting is for an allowed request.SPEC.mdlines 1582-1583: "With any other value,smallwebwafprints its commands and exits, and the health check fails." WithSMALLWEBWAF_COMMAND=healthcheck,share/smallwebwaf.runruns the health check every second instead, and it reportsrproxyunhealthy. For a mistyped value, the usage text never namesSMALLWEBWAF_COMMAND. Acceptable: the run script runs onlyrproxyorservewaf, stops on any other value with a message namingSMALLWEBWAF_COMMANDand its value, andSPEC.mdsays so.internal/smallwebwaf/healthcheck.goline 46 readsSMALLWEBWAF_COMMANDitself. Butinternal/config/config.goline 1 andSPEC.mdline 68 sayinternal/configis the one place settings are read, anddocs/settings.mdlistsSMALLWEBWAF_COMMANDas a setting. Acceptable:internal/configreads it, as it already reads the listen addresses for the health check.Unverified:
make example-appandmake gitea-requestsnever got past the image build. Ubuntu's snapshot service answered 502 and 503 in four runs of each.Model: opus-5-5
4b0af7f85btoe3b159db07SMALLWEBWAF_COMMANDand its value;SPEC.mdsays so, and that the health check then fails.config.Commandreads it and refuses any other value; the health check takes it from there.Image checks: neither
make example-appnormake gitea-requestsgot past the image build, in three tries each; Ubuntu's snapshot service answered 500, 502 and 503.Model: opus-5-5
docs/settings.mdline 388, "Where earlier settings went": the section lists the removedSWWAF_settings and what replaced them. #172 asks thatREADME.md,SPEC.mdanddocs/describe the new arrangement and nothing of the old. Acceptable: the section goes, and the document lists only settings that exist.SPEC.mdline 1578: "The image'srunscript,/etc/service/smallwebwaf/run, starts the commandSMALLWEBWAF_COMMANDnames,rproxywhen it is unset or empty, as thesmallwebwafuser (uid and gid 65532) with runit'schpst." Its asides stack up, and its object, "the commandSMALLWEBWAF_COMMANDnames", does not parse on first reading. Acceptable: short sentences, such as "The image'srunscript is/etc/service/smallwebwaf/run. It startsservewafwhenSMALLWEBWAF_COMMANDisservewaf, andrproxywhen it is unset or empty. It runs either as thesmallwebwafuser (uid and gid 65532), with runit'schpst."SPEC.mdline 1703: "An app deployed by upaas, which rebuilds and restarts an app's Docker container when its repository changes, takes the shape of "rproxyin the app's container" with no change to upaas." It runs past 30 words, and its verb comes only after a 12-word clause. Acceptable: two sentences, such as "upaas rebuilds and restarts an app's Docker container when its repository changes. An app it deploys takes the shape of "rproxyin the app's container" with no change to upaas."Judgement call: the
token_refusedsentence indocs/state-files.mdis not part of finding 1; it says what the code still loads.Model: opus-5-5
On the second review: finding 1 does not stand. "Where earlier settings went" stays, as the brief for #172 allowed ("nothing of the one-process mode except where its settings went"): nothing reads those names any more, so an operator who still sets one gets no error, and the section is how they find out. Findings 2 and 3 are fixed as given, and nothing else changes.
Model: opus-5-5
e3b159db07toac1a69e863runscript sentence inSPEC.mdis now three short sentences, as given.SPEC.mdis now two sentences, as given.Judgement call: the second of the new
runscript sentences also namesrproxyas a value, since the script accepts it.Model: opus-5-5
Review passed.
Unverified:
make example-appandmake gitea-requestsnever got past the image build; Ubuntu's snapshot service answered 500, 502 and 503 in three tries of each.Model: opus-5-5