docs: Document intended updater arch (#63)
This commit is contained in:
@@ -4,35 +4,64 @@ This is the C/Rust side of the Shorebird code push system. This is built
|
||||
in Rust with a C API for easy calling from other languages, most notably
|
||||
for linking into libflutter.so.
|
||||
|
||||
# Parts
|
||||
## Parts
|
||||
* cli: Test the updater library via the Rust API (for development).
|
||||
* dart_cli: Test ffi wrapping of updater library.
|
||||
* library: The rust library that does the actual update work.
|
||||
|
||||
# TODO:
|
||||
* Remove all non-MVP code.
|
||||
* Add an async API.
|
||||
* Add support for "channels" (e.g. beta, stable, etc).
|
||||
* Write tests for state management.
|
||||
* Make state management/filesystem management atomic (and tested).
|
||||
* Move updater values out of the params into post body?
|
||||
* Support hashing values and check them?
|
||||
* Add "validate" command to validate state.
|
||||
* Write a mode that runs the updater first and then launches whatever is downloaded?
|
||||
* Use cbindgen to generate the C api header file.
|
||||
https://github.com/eqrion/cbindgen/blob/master/docs.md
|
||||
## Imagined Architecture (not all implemented)
|
||||
|
||||
### Update State Machine
|
||||
* Server is authoritative, regarding current update/patch state. Client can
|
||||
cache state in memory. Not written to disk.
|
||||
* Client keeps on disk:
|
||||
* cache of patches in "slots"
|
||||
* cache of in-progress download state.
|
||||
* Last booted patch (may not have been successful).
|
||||
* Last successful patch (never rolled back from unless becomes invalid).
|
||||
|
||||
# Rust
|
||||
### Slot State Machine
|
||||
* Patches are cached on disk in "slots".
|
||||
* There is a currently active slot (the one that is booted).
|
||||
* Patches are identified by base revision + patch number.
|
||||
* A given slot is:
|
||||
* `empty`: No update is installed.
|
||||
* `pending`: An update is installed but has not been validated.
|
||||
* `valid`: An update is installed and has been validated.
|
||||
* Validation is a temporary state. Patches/slots are revalidated on boot.
|
||||
|
||||
### Download State Machine
|
||||
* Patches are downloaded to a temporary location on disk.
|
||||
* A given download is:
|
||||
* `queued`: No download has been attempted.
|
||||
* `downloading`: Download is in progress.
|
||||
* `success`: Download is complete.
|
||||
* `failure`: Download failed.
|
||||
|
||||
### Trust model
|
||||
* Network and Disk are untrusted.
|
||||
* Running software (including apk service) is trusted.
|
||||
* Patch contents are signed, public key is included in the APK.
|
||||
|
||||
## Rust
|
||||
We use normal rust idioms (e.g. Result) inside the library and then bridge those
|
||||
to C via an explicit stable C API (explicit enums, null pointers for optional
|
||||
arguments, etc). The reason for this is that it lets the Rust code feel natural
|
||||
and also gives us maximum flexibility in the future for exposing more in the C
|
||||
API without having to refactor the internals of the library.
|
||||
|
||||
## Notes
|
||||
* https://github.com/RubberDuckEng/safe_wren has an example of building a rust library and exposing it with a C api.
|
||||
https://docs.rust-embedded.org/book/interoperability/rust-with-c.html
|
||||
are docs on how to use Rust from C (what we're doing).
|
||||
|
||||
## Other update systems
|
||||
https://github.com/RubberDuckEng/safe_wren has an example of building in Rust
|
||||
and exposing it with a C api.
|
||||
|
||||
## TODO:
|
||||
* Add an async API.
|
||||
* Write tests for state management.
|
||||
* Make state management/filesystem management atomic (and tested).
|
||||
* Support validating patches/slots (hashes, signatures, etc).
|
||||
|
||||
## Later-stage update system design docs
|
||||
* https://theupdateframework.io/
|
||||
* https://fuchsia.dev/fuchsia-src/concepts/packages/software_update_system
|
||||
|
||||
Reference in New Issue
Block a user