| 1 | LIVE https://todo-zig.bfj.oncarlos.com e5042a9 |
| 2 | |
| 3 | ## What's live |
| 4 | |
| 5 | - `todo-zig` on account `bfj`, one instance on channel `edge`, build probe |
| 6 | `/api/version`. The deployed version is `e5042a9`; `/api/version` and |
| 7 | `X-Carlos-Version` both report it. |
| 8 | - The shared behaviour suite passed locally (67 passed, 3 skipped) and |
| 9 | again against [https://todo-zig.bfj.oncarlos.com](https://todo-zig.bfj.oncarlos.com) |
| 10 | (67 passed, 3 skipped). The skips are the suite's own: blur and Escape |
| 11 | with JavaScript off, and the screenshot comparison with JavaScript off. |
| 12 | - `scripts/boot-check.sh dist/app-linux-arm64` passed: `/healthz` and |
| 13 | `/api/version` answer 200 on a unix socket under qemu, and SIGTERM exits 0. |
| 14 | - `make test`: 11 Zig unit tests pass (view, routing, form and cookie |
| 15 | parsing, title trimming, origin check, store scoping). |
| 16 | |
| 17 | ## Notes |
| 18 | |
| 19 | - Binary: static aarch64 musl, 1.9 MB, stripped, CSS and JS embedded. |
| 20 | - Cold `make build-arm64` after `make clean-deps` took 8m06s on docs-t1, |
| 21 | with Zig compiling its build runner, musl and the SQLite amalgamation |
| 22 | from scratch (other builders were compiling at the same time). |
| 23 | - Zig 0.17 unpacks fetched packages into a project-local directory; the |
| 24 | Makefile points it (and both Zig caches) into `.cache/`, so |
| 25 | `clean-deps` keeps the downloaded SQLite sources (`.cache/zig/p`, |
| 26 | `.cache/pkg`) and drops everything compiled. |
| 27 | - Nothing in the contract seemed wrong. |
| 28 | |
| 29 | ## Review fixes (576c3b8) |
| 30 | |
| 31 | Both findings are fixed. After the fixes, the shared suite passed |
| 32 | locally and against the live site (67 passed, 3 skipped each time), and |
| 33 | `boot-check.sh` passed on the new arm64 binary. |
| 34 | |
| 35 | 1. **An open editor was lost when an earlier response arrived.** |
| 36 | `static/app.js` now leaves an item being edited in place when it applies |
| 37 | a response. It never detaches that item, so the editor keeps its focus |
| 38 | and unsaved text. It replaces the items around it and refreshes the |
| 39 | item's checkbox, label and classes. If the response no longer contains |
| 40 | that item (deleted, or filtered out), the list is replaced as before. |
| 41 | I checked this in a browser: I delayed a toggle by 1 s and opened |
| 42 | another item's editor while it was pending. When the answer arrived, |
| 43 | the editor kept its text and focus and the counter updated. Enter then |
| 44 | saved the edited text. |
| 45 | 2. **Titles were trimmed of ASCII whitespace only.** Adding and editing |
| 46 | now trim Unicode White_Space characters (U+00A0, U+2003, U+3000 and |
| 47 | the rest) and U+FEFF from both ends (`trimTitle` in `src/app.zig`, with |
| 48 | a unit test). A whitespace-only add creates nothing, and editing an |
| 49 | item to whitespace only deletes it. Both were checked with curl. |
| 50 | |
| 51 | ## Review findings not fixed |
| 52 | |
| 53 | None. |
| 54 | |
| 55 | ## Second review round |
| 56 | |
| 57 | The second review request listed no findings, so the code is unchanged |
| 58 | and nothing was redeployed: rebuilding and redeploying the same commit |
| 59 | would change nothing. The live site still reports `576c3b8`, and the |
| 60 | shared suite run against it again passed (67 passed, 3 skipped). |
| 61 | |
| 62 | ## Third review round (e5042a9) |
| 63 | |
| 64 | 1. **[security] Malformed UTF-8 in a title aborted the server.** Fixed. |
| 65 | The backward scan in `trimTitle` (`src/app.zig`) passed every byte |
| 66 | after a lead byte to `std.unicode.utf8Decode`. That function asserts |
| 67 | it gets exactly one sequence, so `title=a%80%80%80%80` reached |
| 68 | `unreachable` and the ReleaseSafe build aborted. I reproduced the |
| 69 | abort on the previous binary. The scan now checks that the lead |
| 70 | byte's sequence length matches the bytes found before it decodes; |
| 71 | anything else is treated as non-whitespace and ends the trim, so a |
| 72 | malformed title is stored as sent, untrimmed at that end. |
| 73 | Regression cases are in the `trimTitle` unit test. |
| 74 | Verified: locally the four malformed payloads answer 303 and |
| 75 | `/healthz` stays 200, and the live site answers 303 to the reported |
| 76 | payload. The shared suite passed locally and against the live site |
| 77 | (67 passed, 3 skipped each time), and `boot-check.sh` passed on the |
| 78 | new arm64 binary. |
| 79 | |
| 80 | No findings from this round were left unfixed. |
| 81 | |