diff --git a/docs/web-ui/shape.md b/docs/web-ui/shape.md index 38ad869b..c16d8030 100644 --- a/docs/web-ui/shape.md +++ b/docs/web-ui/shape.md @@ -37,10 +37,10 @@ `marked` (npm dep, replacing the vendored UMD bundle) and then `DOMPurify.sanitize()` before hitting `innerHTML` — untrusted row text (peer-agent / matrix-relayed message bodies, agent-authored - state files) can carry arbitrary HTML/script via markdown, so the - markdown path is sanitized rather than XSS-safe by construction the - way the text-node `linkify` path is. Rendered ``s are rewritten - to `target="_blank"`. + state files) can carry arbitrary HTML/script via markdown, so + `DOMPurify.sanitize()` cleans the markdown path rather than it being + XSS-safe by construction the way the text-node `linkify` path is. + Rendered ``s are rewritten to `target="_blank"`. - `GET /api/state` → JSON snapshot the JS app renders into the DOM. Includes a top-level `seq` (the dashboard event channel's high-water mark at the moment the server assembled the snapshot); @@ -192,9 +192,10 @@ inside a fresh text node, so the autolinker never touches trailing-punctuation strip keeps `.,;:` outside the link surface. Markdown bodies go through `marked` separately, then `DOMPurify.sanitize()` on the resulting HTML before it's assigned to -`innerHTML` (see `mdNode` in `app.js` / `common.js`) — this path is -sanitized, not text-node-safe like `linkify`, since markdown can -carry raw HTML. Rendered ``s get the same target rewrite. +`innerHTML` (see `mdNode` in `app.js` / `common.js`) — +`DOMPurify.sanitize()` cleans this path rather than it being +text-node-safe like `linkify`, since markdown can carry raw HTML. +Rendered ``s get the same target rewrite. The JS app handles all `form[data-async]` submissions via a delegated listener: read `data-confirm`, swap the button to a spinner, POST @@ -226,12 +227,12 @@ before returning. **Keyed DOM caching:** for sections whose rows hold interactive state (textarea drafts, checkboxes, focused inputs) `paintAtomic` isn't -enough — wiping and rebuilding still destroys the state even if the -flash is hidden. The keyed pattern keeps a `Map` -where the fingerprint is `JSON.stringify({...visible fields...})`. -On each render: cache-hit rows are reused verbatim (preserving -textarea draft, checkbox state, and event listeners); only cache-miss -rows are rebuilt and inserted. Used for: containers (`containerRowCache`), +enough — wiping and rebuilding still destroys the state even if +`paintAtomic` hides the flash. The keyed pattern keeps a +`Map` where the fingerprint is +`JSON.stringify({...visible fields...})`. On each render, the pattern +reuses cache-hit rows verbatim (preserving textarea draft, checkbox +state, and event listeners) and rebuilds only cache-miss rows. Used for: containers (`containerRowCache`), rebuild-queue entries (`rebuildQueueRowCache`). The spawn-form input+focus and meta-input checkboxes use a lighter snapshot-then-restore pattern (snapshot before `replaceChildren`, restore after) since they're single @@ -298,7 +299,7 @@ flood the journal. The per-agent UI's `bind_with_retry` than looping forever. The per-agent UI optionally binds a `UnixListener` instead of -TCP when `HIVE_WEB_SOCKET` is set — the unix-socket transition +TCP when the nix module sets `HIVE_WEB_SOCKET` — the unix-socket transition mechanics (per-agent `/run/hive-agent//` bind-mount, `.bound` marker filtering, `agent-sockets.json` consumer on the gateway side) live in [`docs/networking/gateway.md::Per-agent unix-socket