EasyCord LogoDocs
Core Architecture

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

  1. You build your web application (npm run build) and compress the output directory into a .zip archive.
  2. You cryptographically sign the archive using HMAC-SHA256 and your secret key.
  3. You host the archive on a CDN.
  4. The JavaScript API triggers the native download.
  5. The native Dart code streams the download to a temporary file, verifies the HMAC-SHA256 signature, and extracts the contents.
  6. 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 32

Configure 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_clearUpdate

Warning Never commit ota_secret_key to 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.zip

Or 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

NameTypeRequiredDescription
urlstringYesThe absolute HTTPS URL of the .zip bundle.
versionstringYesThe version string identifier.
signaturestringYesThe 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.