Skip to content

fix: recovery, address-open and 2D view items from #34 - #57

Open
Jozkah wants to merge 6 commits into
CNCKitchen:mainfrom
Jozkah:review/app-recovery-viewer
Open

Jozkah wants to merge 6 commits into
CNCKitchen:mainfrom
Jozkah:review/app-recovery-viewer

Conversation

@Jozkah

@Jozkah Jozkah commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

The app, recovery and 2D view items from #34, rebased on 0.9.3, one commit per item, each with a regression test that fails without it:

  • fix: keep a kept project file from replacing the session's own
  • fix: cap the size of a file opened from the address
  • fix: refuse images whose header declares too many pixels
  • fix: let go of the store when an edge detection wait is given up
  • fix: drop the 2D rubber band when its gesture is cancelled
  • fix: prune local recovery checkpoints

Notes:

  • Recovery: closed pages' checkpoints older than 14 days, or past the 10 newest, are pruned on open. A saved page drops its own checkpoint, and a restore drops the one it came from. Writing this fix turned up a second bug, also fixed here: after Save, a change back to a state checkpointed earlier wrote no new checkpoint. e2e-recovery now leaves unsaved work before its final reload.
  • ?open= checks Content-Length and streams the body with a 1 GiB cap.
  • Images whose PNG or JPEG header declares more than 200 megapixels are refused before decoding. That still allows an A4 page scanned at 1200 dpi.

Build: npm run build passes. npm test (3107), npm --prefix mcp test (127), the plugin boundary and units checks, and npm run e2e:ci all pass.

A project could carry a file of a part no section owns under the name the scan, reference or image is saved as. Writing it after the session's own files let it win in the archive. Kept files now go in only under names nothing else in the session writes.
A ?open= link read the whole response into memory whatever its size, so a link could fill the tab or hand a huge file to a parser. The stated length is checked first and the body is read in pieces, stopping with an error once it passes 1 GiB.
Images were decoded on the page's thread whatever size their header declared, so a small file could claim billions of pixels and freeze or crash the tab. The PNG or JPEG header is now read first, and an image of more than 200 million pixels is refused with a message saying why.
The detect_edges command waited on a store subscription that only ended when the edge version changed, so a detection that never finished, or whose image was replaced, left the listener on the store. The wait now also ends when the image changes and when the command's signal aborts, removing the listener either way.
The rubber band listened only for pointerup, so a touch or pen gesture the browser cancelled left its listeners and box on the page, and the next release anywhere made a selection. A pointercancel now removes the listeners and the box without selecting.
Every page wrote a checkpoint slot with a copy of its source files, and only an explicit Discard ever removed one, so storage grew with each session and saved work was offered back as recovery. A page now removes its own slot when the project is saved, removes the slot it restored from, and on opening lets go of checkpoints older than 14 days or beyond the newest 10.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant