None blocked the merge; all four were mechanisms that did not mechanise. _RUNNING_STATES existed twice, in api/routes.py and services/reconciler.py, with a comment asking a human to keep them in lockstep. The panel and the reconciler read the same agent snapshot, so a drift between the copies would paint a service green and flag it as drift on the same page. One definition now, owned by the reconciler and imported by routes - api -> services is the direction the plugin layout already runs in, and the reconciler's import of routes is deferred, so there is no cycle. The operator-report upload checked its 10 MB cap AFTER upload.read() had already pulled the whole body into memory, so the check could not prevent the thing it was there to prevent. content_length is now an early out and the read itself is bounded to cap+1, which is enough to know the cap was exceeded without taking a body that lied about its length. The multipart envelope carries the other form fields too, so the early out allows 64 KB of slack rather than rejecting an image that is just under. The same handler forced the extension to .png and the mimetype to image/png whatever the bytes were, then served the file back under that type. The upload headers (CSP sandbox + nosniff) make the document case inert, so this was never the hole it looks like, but nothing is gained by storing a file we already know is not what it claims. The PNG signature is now checked. The lightbox bound Escape and the arrow keys to a div and never focused it, so every one of those bindings was dead until the user happened to click the backdrop. It takes focus on open and hands it back to the thumbnail on close. On the two upload tests, honestly: the PNG one was confirmed to fail with the check removed. The oversize one passes either way, because the old code did reject an oversized image - it just did so after reading all of it. That test pins the response, not the fix. Whether the read is bounded is not observable through the response, so nothing here proves it; the change stands on reading the handler. Suite 2311 passing, frontend 316 passing, build clean. Scope: product
6.4 KiB
6.4 KiB