Migrate Dioxus admin UI to the spec-driven, multidomain contract #161

Open
opened 2026-06-22 11:08:21 +00:00 by nabil_salah · 0 comments
Member

Area: crates/hero_aibroker_app (Dioxus WASM admin UI)
Type: Refactor / migration
Depends on: server oschema + multidomain migration (separate PR, server side)
Owner (this ticket): Dioxus / frontend


Background

The repo-wide Hero server migration has two coupled parts:

  1. OSchema-first spec generation — replace hand-written OpenRPC specs + hand-rolled
    JSON-RPC dispatchers with the openrpc_server! macro (server side, separate owner).
  2. Multidomain serving — one rpc.sock carrying every domain as path segments:
    • /api/{domain}/rpc — per-domain JSON-RPC
    • /api/{domain}/openrpc.json — per-domain spec
    • /api/domains.json — discovery endpoint

Reference skills:

  • Migration: skills/blueprint/migration/hero_server_migration.md
  • OSchema: skills/blueprint/oschema/oschema_best_practices.md
  • Server: skills/blueprint/server/hero_server_implemenation.md
  • Admin UI: skills/web/hero_admin_ui.md ← target architecture for this ticket
  • Dioxus bootstrap: skills/web/dioxus_bootstrap.md

(Forge: https://forge.ourworld.tf/lhumina_code/hero_skills/src/branch/development/)

Problem

The Dioxus admin UI follows dioxus_bootstrap.md for its building blocks (Dioxus 0.7,
dioxus-bootstrap-css, BootstrapHead/ThemeProvider, use_signal, gloo-net RPC) but
does not follow the architecture in hero_admin_ui.md. It is hard-wired to the
old server contract that the migration removes:

  • Talks to a single hardcoded /rpc endpoint — crates/hero_aibroker_app/src/rpc.rs
    (base /hero_aibroker/ui).
  • Uses dotted method names (info, config.get, metrics.get, mcp.health,
    models.list, models.config, models.get/delete/save, …) — src/app.rs,
    src/components/*.
  • Static, hand-written API docs (MethodDoc consts) — src/components/api_docs_tab.rs.
  • Hand-written serde DTOs mirroring responses by hand — src/types.rs.
  • Navbar links a fixed singular /openrpc.jsonsrc/components/navbar.rs.
  • No runtime discovery of domains or specs.

hero_admin_ui.md instead intends a generic, self-discovering admin shell: discover
services + OpenRPC specs at runtime and render Docs/Playground from the spec — no
hardcoded URLs, method names, or per-method UI.

Goal

Make the Dioxus admin UI conform to hero_admin_ui.md: drive the UI from OpenRPC specs
fetched at runtime, over the multidomain contract, with the server contract isolated in a
single module so the cutover is a constant flip — not a component rewrite.

Key enabler

The server already ships 10 real, standard OpenRPC 1.3.2 specs in
crates/hero_aibroker_server/specs/*.openrpc.json (methods / params / result /
servers). The spec-driven renderer can be built and tested against these today — its
parser does not care whether a method is named models.list or models_list. The oschema
PR only regenerates these (new names, new serving paths); the parsed shape is unchanged.

Scope

In scope (Dioxus side):

  • Contract isolation layer in rpc.rs.
  • Runtime discovery (/api/domains.json + per-domain /api/{domain}/openrpc.json).
  • Per-domain RPC routing.
  • Spec-driven Docs + Playground (replacing static MethodDoc consts).
  • Dotted → underscore method-name migration at call sites.

Out of scope:

  • oschema files and openrpc_server! adoption (server side, separate PR/owner).
  • Spec generation itself.

Approach — can start now, contract-isolated

Develop against the existing specs/*.openrpc.json. Keep everything that depends on
the server contract (base path, endpoint shape, dotted→underscore mapping, per-call domain)
in one place (rpc.rs) so the cutover after the server PR is a constant change.

Tasks — start now (not blocked)

  • Add a contract module in rpc.rs: endpoint constants (/api/{domain}/rpc,
    /api/domains.json, /api/{domain}/openrpc.json), base-path handling, and a
    central dotted→underscore + per-call domain map.
  • Add a rpc(domain, method, params) layer (keep current rpc() as a thin wrapper
    during transition).
  • Discovery functions: fetch domains list + each domain's spec (dev against
    specs/*.openrpc.json; real URLs behind the isolated constants).
  • OpenRPC parser types (minimal serde structs for methods/params/result).
  • Spec-driven Docs component — replace static MethodDoc consts in
    api_docs_tab.rs with rendering from the fetched spec.
  • Spec-driven Playground — method picker + params form + "Send" routed through the
    rpc(domain, method, …) layer.
  • Make the navbar OpenRPC link discovery-aware (per-domain) instead of fixed
    /openrpc.json.

Tasks — after server oschema/multidomain PR lands (blocked)

  • Flip endpoint constants to the final /api/{domain}/… paths.
  • Apply the final dotted→underscore method mapping.
  • Migrate per-domain calls in app.rs (info/config/metrics/mcpmeta/admin
    domains; models.*models domain).
  • End-to-end verification against a live multidomain server.
  • Decide (A) retrofit current island vs (B) full unified shell per
    hero_admin_ui.md (markup-string tabs, build.rs+dx, serve_admin_dioxus).
    (B) couples to the serving model and is not fully parallelizable.

Acceptance criteria

  • Docs + Playground render entirely from fetched OpenRPC specs — no MethodDoc consts.
  • No hardcoded /rpc or dotted method names outside the single contract module.
  • Domains/specs are discovered at runtime (no fixed /openrpc.json).
  • Switching from the legacy endpoints to /api/{domain}/… is a constant change in one
    module, verified end-to-end against the migrated server.

Open questions (confirm with oschema/server owner)

  1. Exact discovery endpoint paths/api/domains.json + /api/{domain}/openrpc.json
    (skill) vs the /users/api.json shorthand discussed. Lock this before wiring.
  2. Dotted → underscore naming rule and the per-method → domain mapping.
  3. (A) retrofit vs (B) unified shell — which architecture is the target for this repo.

References

  • crates/hero_aibroker_app/src/rpc.rs — single /rpc client (contract lives here)
  • crates/hero_aibroker_app/src/app.rs — root component, polling, tab list
  • crates/hero_aibroker_app/src/components/api_docs_tab.rs — static docs to replace
  • crates/hero_aibroker_app/src/types.rs — hand-written DTOs
  • crates/hero_aibroker_app/src/components/navbar.rs — fixed /openrpc.json link
  • crates/hero_aibroker_server/specs/*.openrpc.json — existing OpenRPC specs to build against
**Area:** `crates/hero_aibroker_app` (Dioxus WASM admin UI) **Type:** Refactor / migration **Depends on:** server oschema + multidomain migration (separate PR, server side) **Owner (this ticket):** Dioxus / frontend --- ## Background The repo-wide Hero server migration has two coupled parts: 1. **OSchema-first spec generation** — replace hand-written OpenRPC specs + hand-rolled JSON-RPC dispatchers with the `openrpc_server!` macro (server side, *separate owner*). 2. **Multidomain serving** — one `rpc.sock` carrying every domain as path segments: - `/api/{domain}/rpc` — per-domain JSON-RPC - `/api/{domain}/openrpc.json` — per-domain spec - `/api/domains.json` — discovery endpoint Reference skills: - Migration: `skills/blueprint/migration/hero_server_migration.md` - OSchema: `skills/blueprint/oschema/oschema_best_practices.md` - Server: `skills/blueprint/server/hero_server_implemenation.md` - **Admin UI: `skills/web/hero_admin_ui.md`** ← target architecture for this ticket - **Dioxus bootstrap: `skills/web/dioxus_bootstrap.md`** (Forge: `https://forge.ourworld.tf/lhumina_code/hero_skills/src/branch/development/`) ## Problem The Dioxus admin UI follows `dioxus_bootstrap.md` for its **building blocks** (Dioxus 0.7, `dioxus-bootstrap-css`, `BootstrapHead`/`ThemeProvider`, `use_signal`, `gloo-net` RPC) but does **not** follow the **architecture** in `hero_admin_ui.md`. It is hard-wired to the *old* server contract that the migration removes: - Talks to a **single hardcoded `/rpc`** endpoint — `crates/hero_aibroker_app/src/rpc.rs` (base `/hero_aibroker/ui`). - Uses **dotted method names** (`info`, `config.get`, `metrics.get`, `mcp.health`, `models.list`, `models.config`, `models.get/delete/save`, …) — `src/app.rs`, `src/components/*`. - **Static, hand-written API docs** (`MethodDoc` consts) — `src/components/api_docs_tab.rs`. - **Hand-written serde DTOs** mirroring responses by hand — `src/types.rs`. - Navbar links a **fixed singular** `/openrpc.json` — `src/components/navbar.rs`. - **No runtime discovery** of domains or specs. `hero_admin_ui.md` instead intends a **generic, self-discovering** admin shell: discover services + OpenRPC specs at runtime and render Docs/Playground *from the spec* — no hardcoded URLs, method names, or per-method UI. ## Goal Make the Dioxus admin UI conform to `hero_admin_ui.md`: drive the UI from OpenRPC specs fetched at runtime, over the multidomain contract, with the server contract isolated in a single module so the cutover is a constant flip — not a component rewrite. ## Key enabler The server **already ships 10 real, standard OpenRPC 1.3.2 specs** in `crates/hero_aibroker_server/specs/*.openrpc.json` (`methods` / `params` / `result` / `servers`). The spec-driven renderer can be built and tested **against these today** — its parser does not care whether a method is named `models.list` or `models_list`. The oschema PR only *regenerates* these (new names, new serving paths); the parsed shape is unchanged. ## Scope **In scope (Dioxus side):** - Contract isolation layer in `rpc.rs`. - Runtime discovery (`/api/domains.json` + per-domain `/api/{domain}/openrpc.json`). - Per-domain RPC routing. - Spec-driven Docs + Playground (replacing static `MethodDoc` consts). - Dotted → underscore method-name migration at call sites. **Out of scope:** - oschema files and `openrpc_server!` adoption (server side, separate PR/owner). - Spec *generation* itself. ## Approach — can start now, contract-isolated Develop against the **existing** `specs/*.openrpc.json`. Keep everything that depends on the server contract (base path, endpoint shape, dotted→underscore mapping, per-call domain) in **one place** (`rpc.rs`) so the cutover after the server PR is a constant change. ### Tasks — start now (not blocked) - [ ] Add a **contract module** in `rpc.rs`: endpoint constants (`/api/{domain}/rpc`, `/api/domains.json`, `/api/{domain}/openrpc.json`), base-path handling, and a central dotted→underscore + per-call domain map. - [ ] Add a **`rpc(domain, method, params)`** layer (keep current `rpc()` as a thin wrapper during transition). - [ ] **Discovery functions:** fetch domains list + each domain's spec (dev against `specs/*.openrpc.json`; real URLs behind the isolated constants). - [ ] **OpenRPC parser types** (minimal serde structs for `methods`/`params`/`result`). - [ ] **Spec-driven Docs component** — replace static `MethodDoc` consts in `api_docs_tab.rs` with rendering from the fetched spec. - [ ] **Spec-driven Playground** — method picker + params form + "Send" routed through the `rpc(domain, method, …)` layer. - [ ] Make the navbar **OpenRPC link** discovery-aware (per-domain) instead of fixed `/openrpc.json`. ### Tasks — after server oschema/multidomain PR lands (blocked) - [ ] Flip endpoint constants to the final `/api/{domain}/…` paths. - [ ] Apply the final dotted→underscore method mapping. - [ ] Migrate per-domain calls in `app.rs` (`info`/`config`/`metrics`/`mcp` → `meta`/`admin` domains; `models.*` → `models` domain). - [ ] **End-to-end verification** against a live multidomain server. - [ ] Decide **(A) retrofit current island** vs **(B) full unified shell** per `hero_admin_ui.md` (markup-string tabs, `build.rs`+`dx`, `serve_admin_dioxus`). (B) couples to the serving model and is *not* fully parallelizable. ## Acceptance criteria - Docs + Playground render entirely from fetched OpenRPC specs — no `MethodDoc` consts. - No hardcoded `/rpc` or dotted method names outside the single contract module. - Domains/specs are discovered at runtime (no fixed `/openrpc.json`). - Switching from the legacy endpoints to `/api/{domain}/…` is a **constant change** in one module, verified end-to-end against the migrated server. ## Open questions (confirm with oschema/server owner) 1. **Exact discovery endpoint paths** — `/api/domains.json` + `/api/{domain}/openrpc.json` (skill) vs the `/users/api.json` shorthand discussed. Lock this before wiring. 2. **Dotted → underscore naming rule** and the per-method → domain mapping. 3. **(A) retrofit vs (B) unified shell** — which architecture is the target for this repo. ## References - `crates/hero_aibroker_app/src/rpc.rs` — single `/rpc` client (contract lives here) - `crates/hero_aibroker_app/src/app.rs` — root component, polling, tab list - `crates/hero_aibroker_app/src/components/api_docs_tab.rs` — static docs to replace - `crates/hero_aibroker_app/src/types.rs` — hand-written DTOs - `crates/hero_aibroker_app/src/components/navbar.rs` — fixed `/openrpc.json` link - `crates/hero_aibroker_server/specs/*.openrpc.json` — existing OpenRPC specs to build against
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_aibroker#161
No description provided.