heldar_kernel/state.rs
1use std::sync::Arc;
2
3use chrono::{DateTime, Utc};
4use sqlx::SqlitePool;
5
6use crate::config::Config;
7use crate::modules::ModuleManifest;
8use crate::services::consumer::DetectionConsumer;
9use crate::services::mirror::MirrorRecorderManager;
10use crate::services::recorder::RecorderManager;
11use crate::services::sampler::SamplerManager;
12
13/// Shared application state, cloned cheaply into every handler and background task.
14///
15/// Note the kernel holds NO concrete domain engine: perception interpreters (zones, ANPR/entry, and
16/// future apps) are registered as [`DetectionConsumer`]s in `consumers`, so the ingest path and this
17/// struct stay domain-agnostic. After the crate split the composing binary decides which app crates
18/// populate the registry.
19#[derive(Clone)]
20pub struct AppState {
21 pub pool: SqlitePool,
22 pub cfg: Arc<Config>,
23 pub recorder: Arc<RecorderManager>,
24 /// Dual/mirror recorder, present only when `HELDAR_MIRROR_RECORDINGS_DIR` is configured.
25 pub mirror: Option<Arc<MirrorRecorderManager>>,
26 pub sampler: Arc<SamplerManager>,
27 /// Registered perception consumers, fanned out to from detection ingest.
28 pub consumers: Arc<Vec<Arc<dyn DetectionConsumer>>>,
29 /// Loaded module manifests (composed by the binary), served at `GET /api/v1/modules` so the
30 /// dashboard renders nav + routes from live truth. The kernel names no module — it only carries
31 /// whatever the composing server populated.
32 pub modules: Arc<Vec<ModuleManifest>>,
33 /// The plugin store's catalog engine (bundled + signed remote registries).
34 pub catalog: Arc<crate::services::registry::CatalogService>,
35 pub http: reqwest::Client,
36 pub started_at: DateTime<Utc>,
37}