Over-The-Air (OTA) Updates
Deliver application updates directly to users without App Store review cycles.
Overview
Over-The-Air (OTA) updates allow you to download a new web bundle archive (.zip) and extract it securely inside the native application sandbox. On the next application restart, the WebView serves the updated local files instead of the original assets bundled into the binary.
Use OTA updates to:
- Deploy urgent bug fixes instantly.
- A/B test UI variations.
- Distribute content updates without native compilation.
Example
Invoke the update process from JavaScript.
try {
const result = await window.easycord.ota.downloadAndApply({
url: 'https://cdn.example.com/releases/v1.2.0/bundle.zip',
version: '1.2.0',
signature: 'a3f1c2e...'
});
if (result.success) {
window.location.reload();
}
} catch (error) {
console.error('OTA Update Failed:', error.message);
}How It Works
- You build your web application (
npm run build) and compress the output directory into a.ziparchive. - You cryptographically sign the archive using HMAC-SHA256 and your secret key.
- You host the archive on a CDN.
- The JavaScript API triggers the native download.
- The native Dart code streams the download to a temporary file, verifies the HMAC-SHA256 signature, and extracts the contents.
- The WebView route updates its local file server path to the new directory.
Configuration
Generate a Secret Key
Generate a 32-byte secure random string to use as your HMAC key. Do not expose this key in your frontend code.
openssl rand -hex 32Configure the Native Environment
Add your secret key and the required methods to easycord_permissions.yaml.
ota_secret_key: "YOUR_GENERATED_SECRET_KEY"
permissions:
- ota_downloadAndApply
- ota_getCurrentVersion
- ota_clearUpdateWarning Never commit
ota_secret_keyto public source control. Inject it during your CI/CD build process.
Signing the Bundle
Every OTA update must be cryptographically signed. EasyCord rejects unsigned or improperly signed archives to prevent arbitrary code execution attacks.
Sign the bundle using OpenSSL.
openssl dgst -sha256 -hmac "YOUR_SECRET_KEY" -hex bundle.zipOr sign the bundle using a Node.js build script.
const crypto = require('crypto');
const fs = require('fs');
const key = process.env.OTA_SECRET_KEY;
const bundle = fs.readFileSync('bundle.zip');
const signature = crypto.createHmac('sha256', key).update(bundle).digest('hex');
console.log('Signature:', signature);API Reference
downloadAndApply()
Downloads, verifies, and extracts a signed web bundle.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The absolute HTTPS URL of the .zip bundle. |
| version | string | Yes | The version string identifier. |
| signature | string | Yes | The HMAC-SHA256 hex signature of the .zip archive. |
Returns
Promise<{ success: boolean, version?: string }>
Throws
InvalidSignatureError: The provided signature does not match the computed hash of the downloaded archive.NetworkError: The download request failed or timed out.StorageError: The device lacks sufficient disk space to extract the archive.
getCurrentVersion()
Retrieves the active OTA version identifier.
Parameters
None.
Returns
Promise<{ success: boolean, version: string | null }>
Throws
None.
clearUpdate()
Deletes the cached OTA update and reverts the application to the original web assets bundled in the binary.
Parameters
None.
Returns
Promise<{ success: boolean }>
Throws
FileSystemError: Failed to delete the cached directory.
Security Notes
EasyCord enforces strict security rules during the OTA extraction process.
- HMAC-SHA256 Validation: Ensures the archive was created by a trusted party holding the secret key and prevents man-in-the-middle tampering.
- Constant-Time Comparison: The signature verification uses constant-time string comparison to prevent timing attacks.
- Zip Slip Protection: The native extractor sanitizes every file path inside the archive to prevent directory traversal attacks.
- Memory Limits: The archive streams directly to disk rather than buffering in memory, preventing out-of-memory crashes on low-end devices.