feat(ui): Phase 25 — operator admin dashboard (Dioxus + Bootstrap 5.3.3, shared with _ui_wasm) #10
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why
hero_assistance has a customer-facing SPA (
_ui_wasm) but no operator-facing admin dashboard. Every Hero service ships an admin dashboard with Logs / Stats / Domain / Admin / Docs tabs + system-stats sidebar (perhero_ui_dashboardskill).Decision: build the dashboard in Dioxus 0.7 + dioxus-bootstrap-css rather than canonical Askama+Unpoly. File D-22 documenting the deviation. Justified because:
dioxus-bootstrap-cssalready vendors Bootstrap 5.3.3 with typed components_ui_wasmalready has/rpcproxy, theme handling (Phase 16aassist://URI scheme), SSE wiring (D-20)Cost: hero_assistance is the only Hero service with a Dioxus admin dashboard. Future maintainers see D-22 first.
Order: Phase 25 first, then 24. Phase 25 has zero dependency on hero_proc lifecycle work; can be built and validated against any running
hero_assistance_server. Derisks the deviation early.What
A. Dashboard structure (per
hero_ui_dashboardskill)Three zones: navbar (brand + clock + refresh + theme toggle + status dot) / sidebar (live system stats with sparklines) / content area (tab bar + per-tab content).
B. Tabs
Domain tabs (with badge counts):
Utility tabs:
hero_logintegration; filter by level/source/time range; live tail/openrpc.jsonrendered at runtime perhero_ui_dashboard_adminskill (left: method browser grouped by capability; right: full method documentation with curl example, params, errors, side effects). All 91 methods auto-render from Phase 23 OpenRPC spec.C. Sidebar widgets
D. Auth
UDS / localhost-only binding. No login forms. Whitelist via
hero_ui_whitelistspattern withADMIN_SECRETSfrom hero_proc secrets (Phase 24 dependency for full integration; static config OK for Phase 25 standalone validation).E. Routing — decide in step 1
_ui_wasmwith/admin/*routes (single SPA, two view modes)_admin_ui_wasmcrate (sibling, shared_ui_wasm_componentslibrary extracted)Pick based on extracted-component-library complexity vs single-binary footprint.
F. Connection status widget
Per
hero_ui_connection_status— green pulse / red disconnected / amber backend-down with text labels in degraded states.Acceptance
cargo build --releasesucceeds for the dashboard cratedx build --releaseproduces a working WASM bundle/openrpc.jsonwith: name, summary, description, params, curl example, response example, error codes, x-hero-intent metadataFiles to touch
crates/hero_assistance_admin_ui_wasm/OR new routes in_ui_wasm(Option A vs B)decisions/D-22-dioxus-admin-dashboard.mdtests/baselines/admin-{tickets,users,logs,stats,admin,docs}.png(visual regression)crates/hero_assistance_ui/src/main.rs— admin dashboard dist servingCargo.tomlworkspace members + default-membersOut of scope
References
hero_ui_dashboard— canonical dashboard pattern (1187-line spec)hero_ui_dashboard_admin— admin section + OpenRPC docs rendererhero_ui_connection_statushero_ui_themehero_ui_whitelistshero_loghero_proc_ui(canonical),hero_books_ui,hero_db_uiSession 39 progress — Phase 25 infrastructure landed (Stages 1-3)
Three commits this session:
a0381fa— file #13 Phase 27-prep (orthogonal to Phase 25; release-infra audit found 6 tags / 0 Releases) and integrate into roadmap (order: 25 -> 24 -> 26 -> 27-prep -> 27)73d58c4— Stage 1: scaffold_admin_ui_wasm+_ui_wasm_componentscrates (additive; clean compile)6f7ef00— Stages 2 + 3: clean/adminfrom_ui_wasm(-657 LoC; deleted Phase-9a hero_collabIndexPage+Layoutartifacts) + wire_uiserver with--admin-dist <path>flag + admin handlers + byte-passthrough/openrpc.jsonproxy + file D-22What landed
hero_assistance_ui_wasm_components— target-agnostic shared lib. Phase 25 surface:ThemePreferenceenum +BsThememapping helper + 2 unit tests. Joinsdefault-membersso its tests run in the kickstart baseline. Future shared widgets (ConnectionStatus,Shellwrapper, base-path-aware RPC client wrapper for Phase 26 island integration) extend this crate without touching either SPA.hero_assistance_admin_ui_wasm— Dioxus 0.7 WASM SPA crate, sibling to_ui_wasm. App + Router + Dashboard skeleton + NotFound.BootstrapHead(Bundled CSS + icons) +ThemeProviderwired. Tab content lands next session._uiserver wiring —--admin-dist <path>CLI flag;AppState.admin_dist_dir;admin_index_pagehandler (serves<admin-dist>/index.htmlfor/admin,/admin/, and/admin/{*path}so admin Dioxus router can dispatch client-side; 404 with helpful message when unset);admin_dist_assetshandler (parallel to customer/assets/*, ordered before catch-all);openrpc_proxybyte-passthrough handler.B.5 adversarial review caught 2 load-bearing issues (both type-locked from day one)
x-hero-intent— fields MUST be modelled asOption<String>+#[serde(flatten)] extra: serde_json::Map<String, Value>, NEVER closed Rust enums. D-21 declares schema fields are open (consumers must tolerate unknown values perinfo.x-hero-intent-schema). Pattern-matching on a closed Rust enum would panic on future router-defined values./openrpc.jsonproxy — implemented as a mirror of the existingrpc_proxy(raw HTTP over UDS, slice on\r\n\r\n, return body bytes verbatim). Does NOT parse-and-re-serialise — that would defeat the FNV-1a-64 cache key hero_router computes on the agentic-calling side (D-21 byte-stable invariant).Test posture
_ui_wasm_componentslib's 2 unit tests)_ui_wasmlib unchangedphase10_multi_project_merged_stream_tags_by_project_id, passes in isolation per s12)What's left for Phase 25 part 2 (next session)
/openrpc.json; unit test feeding"side_effect_class": "future-unknown-value"to verify open-enum tolerance./health+ system stats; reactive memo-based, no polling jitter.hero_logintegration; SSE live tail._serverRPCs.ConnectionStatuswidget perhero_ui_connection_status; IP whitelist viahero_ui_whitelists+ADMIN_SECRETS; visual baselines (admin-tickets-*.pngetc.) replacing the orphaned Phase-9a admin captures._ui_openrpc_proxy_byte_passthroughmirroringphase23_http_openrpc_returns_spec_over_uds_rpc_sockbut through_uito catch any future drift to a parse-based proxy.templates/index.html+templates/base.html(Phase 9a hero_collab admin chrome with no askama struct referencing them).Estimated ~1 session for Phase 25 part 2 + polish.
See
decisions/D-22-dioxus-admin-dashboard.mdfor the full deviation rationale andsessions/39.ymlfor the per-commit manifest.Phase 25 closed — part 2c landed s42
Part 2c shipped 3 of 5 originally-planned items; B.5 deferred 2.
Landed (s42)
hero_ui_routesskill —Route::DashboardTab { tab: String }matches/admin/#/<tab>for all 8 tabs (logs/stats/admin/docs/tickets/users/projects/comments).Tab::route_segment()/Tab::from_route_segment()round-trip pinned by 4 host-side tests. Signal-basedactive_tabretired — URL is the single source of truth,use_navigator()push on tab click, browser refresh / deep-link share / back-forward all just work.placeholder.rsdeleted.workspace.list(D-04 single-project per server). Mirrors the Tickets/Users/Comments shape with full Workspace metadata (id, name, description, avatar_url, created_at, updated_at).capture-spa-baselines.sh --surface admin+make admin-dist+make baseline-admin+make visual-diff-admin. Operator-side capture deferred (Phase 18c pattern: script lands separately from PNGs). Stale Phase-9a/adminroute removed fromcapture-baselines.sh+Makefile VISUAL_PAGES; orphanedadmin-{1920,768,375}.pngdeleted.Deferred (B.5)
hero_ui_whitelistsskill's no-fallback principle make any env-loaded form axiom-growth that Phase 24 deletes. The canonicaladmin_secrets.rsdrops in verbatim once hero_proc lifecycle is in place.tracing::*refactor; scope balloon. L-08 already documents the 2-step closure path.Pending operator-side
make admin-dist && make baseline-adminagainst a live stack captures the 21 admin SPA visual baselines. Mirrors the Phase 18c (s28) pattern. Manual operator-only —visual-diff-adminis not on any CI gate today.Test posture
_serverchanges)Acceptance
cargo build --releasesucceeds for the dashboard cratedx build --releaseproduces a working WASM bundle (verified s42)/openrpc.jsonrequire_admin_role(D-23, s41)Closing as engineering-complete with the two B.5-deferred items tracked downstream. Phase 24 (#9) is NEXT — picks up the IP whitelist as a free byproduct.