docs: the proxy is the open door, not the closed one (Copilot review)

Both Copilot findings on PR #21 applied. The first is the serious one and it
is a defect in documentation this PR itself introduced.

`improvise-ws-server` has NO authentication -- a deliberate MVP limit its own
module doc states -- so anyone who can open a socket to it can rewrite every
document it serves. Loopback binding is the only thing standing between that
and the network, and terminating TLS in front of it REMOVES EXACTLY THAT
PROTECTION. The previous text not only omitted the warning, it actively
reassured the reader: the `--bind` note explained that keeping loopback means
the port "is not reachable from anywhere else", which is true of the port and
false of the deployment, because the proxy is public. TLS buys
confidentiality, not access control, and the two read alike in a recipe.

So the warning leads the section, the Caddyfile carries `basic_auth` with a
comment saying it is not optional, the `--bind` note now says what it does and
does not buy, and the tunnel line says cloudflared/ngrok print public URLs and
authenticate nothing by default -- an unguessable URL is not a control.

Second finding: the watchdog comment was ambiguous in a file whose only
verification is reading, which makes an ambiguous comment a real defect. It
said a drop before the first frame "leaves the watchdog armed", meaning the
state on ARRIVAL; it reads as a claim about the state after the call, which is
the opposite of what `setShellFailure` does. Reworded to say the call disarms,
why the opened path needs that (the watchdog is armed only after
`transport.ready` resolves, i.e. on `open`), and that the never-opened path
makes it a no-op.

No open ticket covers server auth -- improvise-j31x is the multi-document
registry and is closed -- so nothing is cited here and one is proposed in the
hand-back rather than an ID invented.

1184 passing, unchanged. `node --check` clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Edward Langley
2026-09-19 22:43:41 -07:00
parent fa40abe932
commit 16471d7def
2 changed files with 35 additions and 6 deletions
+7 -3
View File
@@ -223,9 +223,13 @@ function socketTransport() {
// disarmed because it is for silence only, whereas suppressing `close`
// outright would hide a genuine mid-session disconnect, which is the one
// thing this listener is really for. Hence the split rather than a guard.
// Both arms go through `setShellFailure`: a drop before the first frame
// leaves the watchdog armed, and "disconnected" is more precise than the
// guess it would fire 8s later.
// Both arms go through `setShellFailure`, which DISARMS the watchdog. That
// matters on the opened path: the watchdog is armed after `transport.ready`
// resolves — i.e. on `open` — so a socket that opened and then dropped
// before its first frame reaches here with the timer still pending, and
// "disconnected" is more precise than the guess it would otherwise fire 8s
// later. On the never-opened path there is no timer yet and the clear is a
// no-op. Neither arm leaves one armed.
socket.addEventListener("close", () =>
setShellFailure(opened ? "disconnected" : unreachable),
);