Signing and encryption
How Hotrail signs bundle manifests, how devices verify them, and what encrypted bundles need.
Signing is on by default
The init command creates an Ed25519 key pair in .hotrail/signing-key.json and adds that folder to .gitignore. Keep the private key out of source control. The public key is printed once. Put it in your Capacitor config as hotrailPublicKey.
On the first signed upload the public key is registered for the app. Every later upload is verified against it.
What is signed
Upload hashes every file with SHA-256, builds a manifest of paths and hashes, and signs the manifest. Only files the server does not already have are sent. The plugin verifies the signature, then verifies the hash of every file it downloads.
npx @buffersol/hotrail upload
# for a test only, skips signing:
npx @buffersol/hotrail upload --unsignedDevice checks
With publicKey set in the plugin, only bundles that offer a signed manifest are installed. A bad signature, a wrong key, a changed manifest or a hash mismatch rejects the whole bundle, sends a failure beacon and marks that version as failed so it is not downloaded again. Unsigned bundles are rejected by devices that check signatures.
Encrypted bundles
The update response can carry a session_key, which is AES-CBC key material. The plugin TypeScript layer reads it. Decryption of the zip or files happens in native code, and that native code has not been compiled or tested on devices yet. Do not rely on encrypted bundles in production until the plugin CI is green and you have tested on a device.