Combined with the fix in the engine:
https://github.com/shorebirdtech/engine/commit/4288ae1125e38a772c6cc8a918ed020c276534a4
This makes it so the updater no longer crashes repeatedly with bad patches. Previously
1. the engine was not successfully reporting a patch bad before crashing (now it does just before crashing).
2. With that fixed, the patch was getting marked bad, but because we were sending the "current" patch to the server, the server would tell us to download a new one every time (which we would not check against our bad patches) and we'd repeatedly boot of a "new" known-bad patch. This is now fixed to both send the latest_installed_patch to the server (as patch_version) as well as refusing to install known bad patches.
3. Fixed the cache to destroy itself on version change (which I expect could hit us when an app upgrades its cache might not get cleared).
4. Also fixed tests being flakey because TempDir cleans up after itself when it goes out of scope (thus needs to be held at the test-lifetime scope rather than inside init_for_testing).
This separates patch download from install, which makes it possible for us to later asynchronously download patches into the downloads spot and then install them on completion.
This also makes marking patches good/bad actually do something and tests that it does something.
We're still quite aways away from actually validating patches and having good/bad be meaningful (for example good/bad are never called by the engine code yet) but this is a step in that direction.
activate_latest_bootable_patch is also only used the "set bad" codepath, and isn't even used when installing patches (those still manually set the current slot).
This also makes it so the slot index is now optional, which makes slightly more sense? And would be needed in the case where you have a single bad patch installed in slot 1, with slot 0 empty/invalid and you resolve to a "None" selected.
Lots more to do here, but this is a start.