docs: scanner-host README after the review fixes (copy approved by Paul); spec synced
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 files changed,
+9
−5
docs/superpowers/specs/2026-10-04-scanner-host-rollout-design.md+6 −2infra/modules/scanner-host/README.md+3 −3
CI passed — run details
diff --git a/docs/superpowers/specs/2026-10-04-scanner-host-rollout-design.md b/docs/superpowers/specs/2026-10-04-scanner-host-rollout-design.md| index 5a2df4cf9..0739dc3fd 100644 |
| --- a/docs/superpowers/specs/2026-10-04-scanner-host-rollout-design.md |
| +++ b/docs/superpowers/specs/2026-10-04-scanner-host-rollout-design.md |
| @@ -126,7 +126,11 @@ So clamd itself never listens on TCP. Three units: |
| `clamd.conf` keys, each rewritten idempotently (clamd has no include |
| directory): |
| - - `StreamMaxLength <stream_max_bytes>`. |
| + - `StreamMaxLength <stream_max_bytes / 1 MiB>M`. Written in whole MiB, not |
| + bytes: Debian's debconf round trip strips an `M` and appends one, so a bare |
| + byte count would become a 25 TiB limit on the first configure (final |
| + review I1). `clamav-daemon/debconf` is also set false after install, so |
| + later upgrades leave `clamd.conf` alone. |
| - `AlertExceedsMax yes`. With the default `no`, an archive that expands past |
| `MaxScanSize`, `MaxFileSize`, `MaxFiles` or `MaxRecursion` is partly |
| scanned and answered `OK`. With `yes` clamd answers |
| @@ -245,7 +249,7 @@ engine wherever it runs. |
| | `ami_id` | — | Debian arm64, from `region-host` | |
| | `client_security_group_id` | — | The console box's group | |
| | `instance_type` | `t4g.medium` | `t4g.small` only with `concurrent_database_reload = false` | |
| -| `stream_max_bytes` | `26214400` | Must equal the console's `CARLOS_CLAMD_MAX_BYTES`. Validation: between 8 MiB and 100 MiB, so the self-test's fixtures (about 5 MB compressed) always fit the stream and a whole stream always fits the scan budget **(codex 11)** | |
| +| `stream_max_bytes` | `26214400` | Must equal the console's `CARLOS_CLAMD_MAX_BYTES`. Validation: a whole number of MiB, between 8 MiB and 100 MiB, so the self-test's fixtures (about 5 MB compressed) always fit the stream and a whole stream always fits the scan budget **(codex 11)** | |
| | `memory_max` | `"3G"` | clamd's cgroup ceiling | |
| | `concurrent_database_reload` | `true` | | |
| | `subnet_id` | `null` | | |
diff --git a/infra/modules/scanner-host/README.md b/infra/modules/scanner-host/README.md| index 708b6b094..803fd079f 100644 |
| --- a/infra/modules/scanner-host/README.md |
| +++ b/infra/modules/scanner-host/README.md |
| @@ -59,7 +59,7 @@ clamd runs with `MaxFileSize 100M`, `MaxScanSize 100M` and `AlertExceedsMax yes` |
| That is not enough on its own. ClamAV 1.4.3 trims a zip member that expands past `MaxFileSize`, scans the trimmed copy, and raises no limit. With the two limits equal, the trimmed copy is as large as the whole scan budget, so scanning it always trips `MaxScanSize`, which does alert. The fixtures and expected answers in the self-test are sized for 100 MiB, so changing the limit means deriving both from it. |
| -Measured on 2026-10-05 against Debian trixie's clamd (ClamAV 1.4.3), with `StreamMaxLength` at 25M and every fixture streamed with `clamdscan --stream`. Each member is a repeating 16 KiB random block, distinct per member, so clamd's clean cache cannot short-circuit it. "Limit" means a `Heuristics.Limits.Exceeded.*` reply. |
| +Measured on 2026-10-05 against Debian trixie's clamd (ClamAV 1.4.3), with `StreamMaxLength` at 25M and every fixture streamed with `clamdscan --stream`. Each member is a repeating 16 KiB random block, distinct per member, so clamd's clean cache cannot short-circuit it. "Limit" means a `Heuristics.Limits.Exceeded.*` reply. The self-test does not count `Heuristics.Limits.Exceeded.MaxScanTime` as one. That reply is a timeout, not a limit, and it fails the test. |
| | Fixture | `MaxFileSize 25M`, `MaxScanSize 100M` | Both 100M (this module) | Self-test requires | |
| |---|---|---|---| |
| @@ -77,7 +77,7 @@ Measured on 2026-10-05 against Debian trixie's clamd (ClamAV 1.4.3), with `Strea |
| The first column is what an unequal pair does: three fixtures were signed clean over content nobody read. |
| -`stream_max_bytes` is the one limit you can change. It is clamd's `StreamMaxLength`, the largest object it accepts on a stream. It defaults to 26214400 (25 MiB) and must be between 8 MiB and 100 MiB. The floor keeps the self-test's fixtures, about 5 MB each, inside the stream. The ceiling keeps a whole stream inside the scan budget. The console's `CARLOS_CLAMD_MAX_BYTES` must equal it. Use the `stream_max_bytes` output rather than typing the number twice. |
| +`stream_max_bytes` is the one limit you can change. It is clamd's `StreamMaxLength`, the largest object it accepts on a stream. It defaults to 26214400 (25 MiB). It must be a whole number of MiB, between 8 MiB and 100 MiB. The floor keeps the self-test's fixtures, about 5 MB each, inside the stream. The ceiling keeps a whole stream inside the scan budget. The console's `CARLOS_CLAMD_MAX_BYTES` must equal it. Use the `stream_max_bytes` output rather than typing the number twice. |
| ## What a clean verdict does not cover |
| @@ -94,7 +94,7 @@ systemctl is-active scanner-selftest.service scanner-tcp.socket |
| journalctl -u scanner-selftest.service --no-pager | tail -14 |
| ``` |
| -You should see `status: done`, a ClamAV version line, `active` twice, and then ten `pass` lines and `scanner-selftest: PASS`. The init script also writes each step to the serial console, ending in `SCANNER-HOST READY <version>` or `SCANNER-HOST FAILED: <reason>`. To read it without a session: |
| +You should see `status: done`, a ClamAV version line, `active` twice, and then ten `pass` lines and `scanner-selftest: PASS`. The init script writes each step to `/var/log/cloud-init-output.log`, and copies it to the serial console when it can, ending in `SCANNER-HOST READY <version>` or `SCANNER-HOST FAILED: <reason>`. To read the console copy without a session: |
| ```sh |
| aws ec2 get-console-output --instance-id <scanner-instance-id> --latest --output text | grep 'SCANNER-HOST' |