docs(nim): STATUS after review fixes, live at 6aa1f35

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev 65264c57b3618b505f742aeea7e61d87c3bf8433 parent 6aa1f35
1 file changed, +44 −6
  • apps/nim/STATUS.md +44 −6
diff --git a/apps/nim/STATUS.md b/apps/nim/STATUS.md
index 8dbabb4..f705d36 100644
--- a/apps/nim/STATUS.md
+++ b/apps/nim/STATUS.md
@@ -1,17 +1,17 @@
-LIVE https://todo-nim.bfj.oncarlos.com df803f7
+LIVE https://todo-nim.bfj.oncarlos.com 6aa1f35
## Where it stands
-- Deployed `df803f7` to `todo-nim` on account `bfj`, channel `edge`.
- `carlos deploy` confirmed it through the `/api/version` build probe, and
- the edge reports `X-Carlos-Version: df803f7`.
+- Deployed `6aa1f35` (the review fixes) to `todo-nim` on account `bfj`,
+ channel `edge`. `carlos deploy` confirmed it through the `/api/version`
+ build probe. The first deploy was `df803f7`.
- Shared behaviour suite: **67 passed, 3 skipped** both locally
(`dist/app --listen`) and against
`https://todo-nim.bfj.oncarlos.com`. The skips are the suite's own: blur
and Escape editing with JavaScript off, and the screenshot test with
JavaScript off.
-- `make test`: 15 unit tests pass (store scoping, filters, toggle-all,
- Unicode and 10,000-character titles, migrations, cookies, 303s, 403 on
+- `make test`: 16 unit tests pass (store scoping, filters, toggle-all,
+ Unicode and 10,000-character titles, Unicode-whitespace trimming, migrations, cookies, 303s, 403 on
a foreign Origin, 404 on a foreign id, the edit view, fragments, static
files).
- `scripts/boot-check.sh dist/app-linux-arm64`: `/healthz` and
@@ -22,6 +22,9 @@ LIVE https://todo-nim.bfj.oncarlos.com df803f7
## Worth knowing
+- `src/httpserver.nim` is a copy of Nim 2.2.12's `std/asynchttpserver`
+ with a single change, marked "todo-nim": chunked bodies are limited.
+ When upgrading Nim, re-copy it and re-apply that change.
- `asynchttpserver` has no unix-socket mode. `unixServer` in `src/app.nim`
binds the socket and gives it to the server through
`std/importutils.privateAccess`, and it has to set `maxFDs` too:
@@ -31,3 +34,38 @@ LIVE https://todo-nim.bfj.oncarlos.com df803f7
upstream would remove it.
- The README and AGENTS.md prose didn't go through a copy review. This
session ran unattended, and that review needs a person.
+
+## Review round
+
+All four findings are fixed in `6aa1f35`:
+
+1. **Chunked bodies (security).** The parser lives inside the standard
+ library, so the server is now vendored as `src/httpserver.nim`. Each
+ chunk's declared size is checked against what's left of the body limit
+ before `recv` allocates anything. Oversized, overflowing and
+ many-small-chunk bodies all get a 413 and the connection closes. The
+ limit is 1 MiB for both chunked and `Content-Length` bodies (it was
+ 8 MiB); a 10,000-character title needs at most about 120 KB. Checked
+ with raw-socket requests against the binary: it stayed at 7 MB RSS.
+2. **Unicode trim.** Add and edit now strip the whitespace JavaScript's
+ `String.prototype.trim` removes (U+00A0, U+2000–U+200A, U+3000, U+FEFF
+ and the rest). A title of only non-breaking spaces adds nothing, and
+ editing to that deletes the item. There's a unit test for both.
+3. **Edits across re-renders.** `render()` keeps the item being edited
+ (text, cursor, focus) and restores it on the same item in the new
+ list, and the blur that removing the old field may fire doesn't
+ count as a save. I checked it with Playwright: toggle one item with
+ the response held for 800 ms, double-click another, type, and wait.
+ The edit is still open, focused and holding the text, and Enter saves
+ it.
+4. **Zig's caches.** The Makefile exports `ZIG_GLOBAL_CACHE_DIR` and
+ `ZIG_LOCAL_CACHE_DIR` under `.cache/`, and `clean-deps` removes them.
+ After `clean-deps`, `make build-arm64` rebuilt musl and compiler-rt
+ (61 MB of cache) from scratch.
+
+After the fixes the shared suite gave 67 passed and 3 skipped both
+locally and against the live host, and the boot check passed.
+
+## Review findings not fixed
+
+None.