applyKbcPatchFromBytes method
- Uint8List envelopeBytes, {
- required KbcLoaderFn loader,
β.3 + ε + β.4 + η: apply a Sankofa Deploy: Flutter Code KBC patch.
Pass a SANKOFA_KBC_ENVELOPE (.skdp) buffer plus a loader
callback that calls the Dart VM's loadDynamicModule. The
canonical wiring (from a host app's pubspec with
dynamic_modules as a path-dep on pkg/dynamic_modules from our
Dart SDK fork) is:
import 'package:dynamic_modules/dynamic_modules.dart';
final result = await Sankofa.deploy!.applyKbcPatchFromBytes(
envelopeBytes,
loader: loadModuleFromBytes,
);
The SDK:
- parses the envelope (
magic SKDP, version 1, length-prefixed header + JSON metadata + KBC payload + signature trailer) - verifies the payload SHA-256 against the carried digest — fail-closed on mismatch, the loader is never called
- sanity-checks the inner KBC magic (
DBC3= 33 43 42 44) - hands the verified KBC bytes to
loader - returns the dyn-module entry-point's return value plus the envelope metadata in a KbcPatchResult
Throws KbcApplyException on any pre-load failure. Throws via
the loader on engine-side issues (e.g. running a stock Flutter
engine that wasn't built with dart_dynamic_modules=true → "Loading
of dynamic modules is not supported"). The exception message
names the most likely cause to keep debugging short.
This is the iOS Path C ship surface (β.3 proved on iPhone 2026-05-24). Android baseline OTA still uses the Phase 5 libapp.so binary-diff route — see checkForUpdate.
Implementation
Future<KbcPatchResult> applyKbcPatchFromBytes(
Uint8List envelopeBytes, {
required KbcLoaderFn loader,
}) {
// Path C is pure Dart — no platform plugin needed. Do NOT call
// _assertReady(): on iOS the platform plugin's libapp.so updater
// doesn't exist, so _ready stays false even though Path C works.
return kbc_loader.applyKbcEnvelope(
envelopeBytes,
loader: loader,
signingPubkeysB64: _effectiveSigningPubkeys,
);
}