device_integrity_guard 1.0.0
device_integrity_guard: ^1.0.0 copied to clipboard
Reusable guard that blocks Flutter apps when the runtime environment looks unsafe.
import 'package:device_integrity_guard/device_integrity_guard.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
final policy = DeviceIntegrityPolicy(
allowDebugMode: !kReleaseMode,
allowEmulator: !kReleaseMode,
allowRoot: !kReleaseMode,
allowJailbreak: !kReleaseMode,
blockOnCompromise: kReleaseMode,
);
final guard = DeviceIntegrityGuard(
policy: policy,
onViolation: (result) {
debugPrint(
'Integrity violation: ${result.blockedSignals.map((s) => s.type.name).join(', ')}',
);
},
);
await runGuardedApp(
app: const GuardedApp(),
guard: guard,
blockedBuilder: (summary) => BlockedScreen(summary: summary),
);
}
class GuardedApp extends StatelessWidget {
const GuardedApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Device Integrity Guard Demo',
theme: ThemeData(colorSchemeSeed: Colors.blue, useMaterial3: true),
home: const GuardedHomePage(),
);
}
}
class GuardedHomePage extends StatelessWidget {
const GuardedHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Integrity Guard')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
'DeviceIntegrityGuard only blocks real users in production.',
textAlign: TextAlign.center,
),
SizedBox(height: 16),
Text(
'In debug and profile builds we allow emulators/rooted devices '
'so you can keep iterating, but every signal is still logged.',
textAlign: TextAlign.center,
),
],
),
),
),
);
}
}
class BlockedScreen extends StatelessWidget {
const BlockedScreen({super.key, required this.summary});
final IntegritySummary summary;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
body: Center(
child: Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.warning, color: Colors.orange, size: 64),
const SizedBox(height: 16),
const Text(
'This build is locked down for security reasons.',
style: TextStyle(color: Colors.white, fontSize: 20),
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
'Signals: ${summary.triggers.map((s) => s.type.name).join(', ')}',
style: const TextStyle(color: Colors.white70),
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
FilledButton(
onPressed: () => debugPrint('User dismissed app'),
child: const Text('Close'),
),
],
),
),
),
),
);
}
}