checkIntegration method

Future<ModuleIntegrationStatus> checkIntegration()

Self-audit the host's Deploy integration. Returns a structured status describing whether the manifest, MainActivity, permissions and updater FFI are all wired up.

Called automatically by Sankofa.init after the platform plugin initializes; the result is logged in debug mode and held for later use by the reverse-handshake (which will eventually report integration status to the server so the dashboard can show "incomplete SDK integration" warnings — Phase 2).

Implementation

Future<ModuleIntegrationStatus> checkIntegration() async {
  if (_platformUnavailable) {
    // Native Deploy plugin absent (plain `flutter run` / iOS Path C).
    // Nothing is broken or actionable: KBC OTA works, and the native
    // Android baseline simply isn't part of this build — it lands when
    // the app is built through the Sankofa CLI. Report a clean status
    // so dev runs never surface a false "integration BROKEN" warning.
    return ModuleIntegrationStatus(
      module: name,
      level: ModuleIntegrationLevel.full,
      missing: const [],
    );
  }
  if (!_ready) {
    return ModuleIntegrationStatus(
      module: name,
      level: ModuleIntegrationLevel.broken,
      missing: const [
        'Platform plugin not initialized — `Sankofa.init(enableDeploy: true)` did not complete',
      ],
    );
  }
  Map<String, Object?> raw;
  try {
    raw = await SankofaDeployPlatform.instance.checkIntegration();
  } catch (err) {
    return ModuleIntegrationStatus(
      module: name,
      level: ModuleIntegrationLevel.broken,
      missing: ['Platform integration check failed: $err'],
    );
  }
  final missing = <String>[];
  final warnings = <String>[];

  if (raw['sankofaDeployApplication'] != true) {
    missing.add(
      'AndroidManifest <application android:name="com.sankofa.deploy.SankofaDeployApplication"> '
      'is not set — the Updater never initializes pre-Dart, so patches stage but never load. '
      'Re-run `sankofa init --deploy` or set the application name manually.',
    );
  }
  if (raw['sankofaFlutterActivity'] != true) {
    missing.add(
      'MainActivity does not extend `com.sankofa.deploy.SankofaFlutterActivity` — '
      'the Flutter engine launches without `--aot-shared-library-name=...`, so patches install but the engine '
      "still loads the baseline libapp.so. Change `class MainActivity : FlutterActivity()` to "
      '`class MainActivity : SankofaFlutterActivity()`.',
    );
  }
  if (raw['internetPermission'] != true) {
    missing.add(
      'AndroidManifest is missing `<uses-permission android:name="android.permission.INTERNET" />` — '
      'the updater cannot reach the Sankofa endpoint. Add the permission and re-run.',
    );
  }
  if (raw['apiKeyMetaData'] != true) {
    warnings.add(
      'AndroidManifest is missing `<meta-data android:name="com.sankofa.apiKey" ...>` — '
      'the Updater will fall back to whatever apiKey Dart passes via `Sankofa.init`, '
      "but pre-Dart updates won't run.",
    );
  }
  if (raw['updaterInitialized'] != true) {
    warnings.add(
      'JNI bridge reports the Updater is not yet initialized. If you just called `Sankofa.init`, '
      "this is normal — the audit ran before init completed. Re-check after the first frame.",
    );
  }

  final level = missing.isEmpty
      ? ModuleIntegrationLevel.full
      : (missing.length >= 2
          ? ModuleIntegrationLevel.broken
          : ModuleIntegrationLevel.partial);

  return ModuleIntegrationStatus(
    module: name,
    level: level,
    missing: missing,
    warnings: warnings,
  );
}