aegis_guardian 3.2.0
aegis_guardian: ^3.2.0 copied to clipboard
Native Android and iOS runtime security checks, device signing, screen privacy, and Apple App Attest for Flutter.
example/lib/main.dart
import 'dart:io';
import 'package:aegis_guardian/aegis_guardian.dart';
import 'package:flutter/material.dart';
void main() => runApp(const GuardianExample());
class GuardianExample extends StatefulWidget {
const GuardianExample({super.key});
@override
State<GuardianExample> createState() => _GuardianExampleState();
}
class _GuardianExampleState extends State<GuardianExample> {
final guardian = AegisGuardian(
sentinelConfig: SentinelConfig(
baseUrl: Uri.parse('https://sentinel.example.com'),
clientId: 'client-id',
),
);
SecurityReport? report;
SentinelAssessment? assessment;
String? deviceId;
String? error;
String? sentinelError;
bool busy = false;
bool protected = false;
@override
void initState() { super.initState(); refresh(); }
Future<void> refresh() async {
setState(() { busy = true; error = null; sentinelError = null; });
try {
final id = await guardian.getDeviceId();
final localReport = await guardian.scan();
if (mounted) setState(() { deviceId = id; report = localReport; });
final remoteAssessment = await guardian.scanAndMonitor();
if (mounted) {
remoteAssessment.fold(
onSuccess: (value) => setState(() { assessment = value; }),
onFailure: (e) => setState(() { assessment = null; sentinelError = e.toString(); }),
);
}
} catch (e) {
if (mounted) setState(() { error = e.toString(); });
} finally {
if (mounted) setState(() { busy = false; });
}
}
@override
Widget build(BuildContext context) {
final threats = report?.detectedThreats.length ?? 0;
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xff1565c0)),
scaffoldBackgroundColor: const Color(0xfff8f9fa), useMaterial3: true),
home: Scaffold(body: SafeArea(child: ListView(padding: const EdgeInsets.all(16), children: [
const Text('Aegis Guardian Security Suite', style: TextStyle(fontSize: 24, fontWeight: FontWeight.w800)),
const SizedBox(height: 4),
const Text('Interactive RASP & Device Intelligence Diagnostics', style: TextStyle(color: Colors.black54)),
const SizedBox(height: 14),
_StatusBanner(busy: busy, threats: threats, hasReport: report != null),
const SizedBox(height: 12),
_InfoCard(icon: '📱', title: 'Device Identity',
detail: 'SDK identifier used for dashboard correlation and blacklist rules.',
value: deviceId ?? 'Loading device identity…', monospace: true),
const SizedBox(height: 10),
_SentinelCard(assessment: assessment, error: sentinelError, busy: busy),
const SizedBox(height: 10),
_card(child: SwitchListTile(contentPadding: EdgeInsets.zero,
title: const Text('🛡️ Screen Privacy', style: TextStyle(fontWeight: FontWeight.w700)),
subtitle: Text(Platform.isAndroid
? 'Blocks screenshots, recording, and recent-app previews.'
: 'Hides content while inactive or screen capture is detected.'),
value: protected,
onChanged: (value) async {
try {
await guardian.setScreenProtection(value);
if (mounted) setState(() { protected = value; error = null; });
} catch (e) {
if (mounted) setState(() { error = e.toString(); });
}
})),
const SizedBox(height: 12),
FilledButton.icon(onPressed: busy ? null : refresh, icon: const Icon(Icons.bolt),
label: Text(busy ? 'Running diagnostics…' : 'Scan All Checks')),
const SizedBox(height: 8),
if (report != null) for (final check in report!.checks) ...[
_CheckCard(result: check), const SizedBox(height: 8),
],
]))),
);
}
}
Widget _card({required Widget child}) => Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(14),
border: Border.all(color: const Color(0xffdddddd))),
child: child,
);
class _InfoCard extends StatelessWidget {
const _InfoCard({required this.icon, required this.title, required this.detail,
required this.value, this.monospace = false});
final String icon, title, detail, value;
final bool monospace;
@override
Widget build(BuildContext context) => _card(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text('$icon $title', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w700)),
const SizedBox(height: 5),
Text(detail, style: const TextStyle(fontSize: 12, color: Colors.black54)),
const SizedBox(height: 10),
SelectableText(value, style: TextStyle(fontSize: 12,
fontFamily: monospace ? 'monospace' : null, fontWeight: FontWeight.w600)),
]));
}
class _SentinelCard extends StatelessWidget {
const _SentinelCard({required this.assessment, required this.error, required this.busy});
final SentinelAssessment? assessment;
final String? error;
final bool busy;
@override
Widget build(BuildContext context) {
final blocked = assessment?.isBlacklisted == true;
final color = error != null || blocked ? Colors.red
: assessment != null ? Colors.green : Colors.blue;
final value = error != null ? 'CONNECTION ERROR\n$error'
: assessment != null
? '${blocked ? 'BLACKLISTED' : 'CONNECTED'} · ${assessment!.action}\n'
'Risk ${assessment!.riskScore} · ${assessment!.riskTier}'
: busy ? 'CONNECTING…' : 'OFFLINE';
return _card(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
const Text('🛰️ Aegis Sentinel', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700)),
const SizedBox(height: 5),
const Text('Live monitoring, risk decision, and device blacklist status.',
style: TextStyle(fontSize: 12, color: Colors.black54)),
const SizedBox(height: 10),
Text(value, style: TextStyle(fontSize: 12, fontWeight: FontWeight.w800, color: color)),
]));
}
}
class _StatusBanner extends StatelessWidget {
const _StatusBanner({required this.busy, required this.threats, required this.hasReport});
final bool busy, hasReport;
final int threats;
@override
Widget build(BuildContext context) {
final color = busy || !hasReport ? Colors.blue : threats > 0 ? Colors.orange : Colors.green;
final label = busy ? 'RUNNING DIAGNOSTICS…' : !hasReport ? 'READY'
: threats > 0 ? '⚠️ $threats POTENTIAL THREAT${threats == 1 ? '' : 'S'} DETECTED'
: '✓ NO THREATS DETECTED';
return Container(padding: const EdgeInsets.all(16),
decoration: BoxDecoration(color: color.withValues(alpha: .12),
border: Border.all(color: color.withValues(alpha: .5)), borderRadius: BorderRadius.circular(14)),
child: Text(label, textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.w800, color: color)));
}
}
class _CheckCard extends StatelessWidget {
const _CheckCard({required this.result});
final CheckResult result;
@override
Widget build(BuildContext context) {
final safe = result.status == CheckStatus.clear;
final color = safe ? Colors.green : result.status == CheckStatus.detected ? Colors.red : Colors.orange;
return _card(child: Row(children: [
Icon(safe ? Icons.verified_outlined : Icons.warning_amber_rounded, color: color),
const SizedBox(width: 12),
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(result.check.name, style: const TextStyle(fontWeight: FontWeight.w700)),
const SizedBox(height: 3),
Text(result.evidence.isEmpty ? result.status.name : result.evidence.join('\n'),
style: const TextStyle(fontSize: 12, color: Colors.black54)),
])),
Container(padding: const EdgeInsets.symmetric(horizontal: 9, vertical: 5),
decoration: BoxDecoration(color: color.withValues(alpha: .12), borderRadius: BorderRadius.circular(20)),
child: Text(result.status.name.toUpperCase(),
style: TextStyle(fontSize: 10, fontWeight: FontWeight.w800, color: color))),
]));
}
}