Files
amethyst/commons/src/commonMain
Claude 6becc6efbe fix(browser): close five holes found auditing the file-input path
Self-audit of the picker and camera work. Four correctness bugs and one
robustness gap, none of them reachable by the happy path, all of them reachable.

A malformed accept entry became the picker's filter. `accept="image/"` passed
the "contains a slash, so it is a MIME type" test and went straight into
Intent.setType, where it matches no provider — an empty picker with nothing to
choose and no way out. A slashed token is now only a MIME type when both halves
are actually present; otherwise it is unnameable and widens to everything, the
same as an unknown extension. Test first, watched it fail.

The main-process chooser host never reported when the system destroyed it
without finish() — a low-memory kill while the picker is on top. The page's
file input would then wait forever on a result nobody was left to send (dead for
the life of the page), and the coordinator would hold the reply callback, and
the controller behind it, for good. Reporting from onDestroy covers it. A
recreated host now releases the input immediately too, instead of silently
swallowing a pick it can no longer route.

A second file input asking before the first pick returned overwrote the
in-flight request. The page's own callback was already released, but the
superseded request still owned camera scratch files and the URI grants handed
to every camera app — nothing would ever come back for them, so they sat until
the daily sweep. Superseding now runs the cancel path on the old request, and
the same cleanup runs when a host is torn down mid-pick.

Capture filenames were built from a clock and a per-object sequence. The main
and `:napplet` processes each hold their own copy of that object, so the
sequences run independently and two picks started in the same millisecond could
name the same file, one capture silently overwriting the other. createTempFile
removes the question.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FxfdHeR9Ry4qALXHT5Sf1Q
2026-08-25 23:25:22 +00:00
..