perspt-dashboard¶
Real-time web dashboard for Perspt agent monitoring, built with Axum + Askama + HTMX.
Core Types¶
pub struct AppState {
pub store: Arc<SessionStore>, // read-only DuckDB
pub password: Option<String>, // optional auth password
pub session_token: Arc<Mutex<Option<String>>>,
pub working_dir: PathBuf,
pub is_localhost: bool, // controls Secure cookie flag
}
pub enum DashboardError {
Store(anyhow::Error), // 503 - DB unavailable
Template(askama::Error), // 500 - render failure
Internal(String), // 500 - generic
}
DashboardError implements IntoResponse and renders a styled HTML
error page. Store errors return 503 Service Unavailable.
Router¶
build_router(state: AppState) -> Router constructs the full Axum router:
Method |
Route |
Handler |
|---|---|---|
GET |
|
|
POST |
|
|
GET |
|
|
GET |
|
|
GET |
|
|
GET |
|
|
GET |
|
|
GET |
|
|
GET |
|
|
GET |
|
|
Static assets are served from crates/perspt-dashboard/static/ under
/static via tower_http::services::ServeDir.
All routes except /login and /static are behind
auth::auth_middleware. If no password is configured, all requests pass
through.
Auth Middleware¶
Cookie-based authentication with random session tokens:
On successful login, generates a 32-character alphanumeric token
Stores token in
AppState::session_tokenSets
perspt_sessioncookie:HttpOnly,SameSite=Lax,Path=/,Secure(when not localhost)Middleware checks cookie value against stored token
No password configured -> open access mode
SSE Stream¶
The SSE endpoint pushes named events every 2 seconds:
psp9-stats- live session summary (ledger event count, measurement count, last measured energy)
Each event contains an HTML fragment suitable for HTMX sse-swap.
Templates¶
Askama templates live in crates/perspt-dashboard/templates/:
base.html- layout with navigation, HTMX, and DaisyUI themelogin.html- login formsession_base.html- shared per-session layout with tab navigationpages/overview.html- session list tablepages/session_detail.html- single-session summarypages/dag.html- work-graph topology viewpages/backlog.html- backlog diagnosticspages/energy.html- energy component tablepages/governance.html- governance viewpages/decisions.html- flat Merkle-chained PSP-9 event trace
View Models¶
Each page has a corresponding view model in src/views/:
OverviewViewModel- sessions, node counts, budgetsSessionDetailViewModel- single-session summaryTopologyViewModel- work-graph nodes and edgesBacklogViewModel- backlog diagnosticsEnergyViewModel- per-node energy componentsGovernanceViewModel- governance evidenceDecisionsViewModel- the flat Merkle-chained PSP-9 event trace
views/psp9.rs provides the shared LedgerProjection these view models
and the SSE stream are built from.