Skip to content

Sentinel App β€” Android Client

Version: 2026.06.022
Platform: Android 8.0+ (API 26+)
Framework: Flutter 3.22+ / Dart

Native Android application for infrastructure management. Provides full real-time monitoring, AI Autofix, and P2P admin communication from a mobile phone.


Architecture

Text Only
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚              Android Device                      β”‚
  β”‚                                                  β”‚
  β”‚  Flutter UI Layer (Material 3)                   β”‚
  β”‚  Β· Reactive dashboard Β· Biometric Vault          β”‚
  β”‚  Β· Incident Matrix  Β· AI Chat Console            β”‚
  β”‚            β”‚                                     β”‚
  β”‚            β”‚ Provider State                      β”‚
  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
  β”‚  β”‚   Android Foreground Service (Dart Isolate) β”‚  β”‚
  β”‚  β”‚   WakeLock Β· WiFi Lock Β· Socket.IO heartbeatβ”‚  β”‚
  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”‚
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
       β–Ό               β–Ό
   REST API        WebSocket
  (HTTP JSON)    (Socket.IO)
  GET/DELETE     live stream
  incidents      P2P chat

Dual-Channel Communication

Every HTTP request and WebSocket handshake passes:

  • X-API-Key β€” unique cryptographic admin token
  • X-Device-ID β€” hardware-derived UUID (prevents echo-loop on multi-device)
  • X-Client-User β€” verified user identity (e.g. FoxiK)

Foreground Service β€” 24/7

Android's power management would kill background processes. Sentinel App bypasses this with a persistent Android Foreground Service.

Text Only
App start / biometric unlock
  └──► Spawn Dart Isolate
         β”œβ”€β”€ WakeLock ──── CPU & modem stay awake
         β”œβ”€β”€ WiFi Lock ─── Wi-Fi modem stays active
         └── Socket.IO heartbeat (60 s)
                β”œβ”€β”€ Network switch (Wi-Fi β†’ LTE) β†’ auto-reconnect
                └── Critical packet β†’ flutter_local_notifications
                    (native push, no Google FCM)

Incident Matrix

4 domains displayed as colour-coded badges:

Domain Description Colour
πŸ—„οΈ LOG ISSUES Faults from journalctl and edge system logs Red/Orange
πŸ“‘ AGENTS STATUS Agent outages or telemetry dropouts Orange/Yellow
πŸ”‘ ROOT SESSIONS Active unmapped root terminal sessions Red
πŸ›‘οΈ SECURITY LOGS Fail2ban, port scans, CVE updates Red

Incident actions

Action Description
πŸͺ„ AI Autofix Sends incident to LLM, displays remediation script with Execute/Decline
πŸ‘ Ignore Suppresses incident on server and in the app
πŸ—‘ Delete Hard delete from the database
πŸ”— Share Copies hostname, timestamp, log origin and error text to clipboard

Biometric Authentication

Text Only
App start
  β”‚
  β–Ό
Biometric challenge (fingerprint / face)
  β”‚
  β”œβ”€β”€ SUCCESS β†’ Unlock UI + start foreground service
  β”‚
  └── FAIL / swipe from task switcher
        β†’ Immediate session key wipe from RAM
          β†’ Next open requires fresh biometric

Visual Offline Mode

When provider.isOnline drops to false:

  • Entire dashboard widget tree gets a greyscale colour matrix filter
  • Red overlay banner appears: SPOJENÍ ZTRACENO - OFFLINE
  • Data polling freezes until reconnected

Since v2026.06.022 the offline state is only entered after two consecutive failures (30 s request timeouts), with a single guarded _refreshAll() β€” no auto-logout and no false OFFLINE flicker on transient blips.


Connection Stability (v2026.06.022)

The client version is synced with the Sentinel server (2026.06.022). Connection and auth were hardened:

  • API-key auto-provisioning β€” after LLDAP login the app provisions an API key and switches to the fast X-API-Key path, avoiding a per-request LDAP bind
  • Stale-key self-healing β€” a 302 β†’ /login redirect is detected as an auth failure (no false success), and the key is re-provisioned
  • Reused provider/socket β€” settings changes reuse the existing provider and Socket.IO connection instead of recreating them
  • Lazy tab loading β€” tabs load on demand, removing the startup request storm
  • Full API audit β€” all 138 endpoints verified against the running server; corrected dashboard top_plugins/recent_issues, metric history via /api/predictions, plugin stats, and fixed POST payloads (comment templates, patterns)

P2P Admin Chat

Volatile admin-to-admin messaging with zero database retention.

  • Messages route through Socket.IO room sentinel_admins β€” server is a zero-state relay
  • Device badge distinguishes mobile vs. web UI clients
  • X-Device-ID prevents self-messaging when same admin uses both phone and browser

Technology Stack

Layer Technology
Framework / Language Flutter 3.22+ / Dart
State Management Provider + ChangeNotifierProvider
Persistence shared_preferences β†’ Android Jetpack Security Crypto
Biometrics local_auth (Fingerprint / Face Unlock)
Notifications flutter_local_notifications (no FCM)
Background flutter_background_service (Dart Isolate)
REST http package (10 s timeout)
WebSocket socket_io_client (polling β†’ WebSocket upgrade)
Build Native ARM binary (no WebView)

Build & Deploy

Bash
flutter pub get
flutter pub run flutter_launcher_icons
flutter build apk --release --no-tree-shake-icons

Output: build/app/outputs/flutter-apk/app-release.apk

Required AndroidManifest.xml permissions

XML
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />