[hero_codescalers] Fix prefix routing through hero_router #19

Closed
opened 2026-04-29 07:10:14 +00:00 by mahmoud · 4 comments
Owner

Problem

hero_codescalers is not correctly reachable through hero_router due to a
prefix routing issue. The service was tested directly (netcat) but not
through the router, so the prefix forwarding was never validated.

Steps to fix

  • Verify hero_codescalers_ui correctly handles the forwarded prefix header
    injected by hero_router
  • Test end-to-end: browser → hero_router → hero_codescalers_ui
  • Do not test with netcat or direct socket — must go through hero_router

Acceptance Criteria

  • hero_codescalers UI loads correctly when accessed via hero_router
  • All UI routes work with the injected prefix
  • No direct socket bypass needed
## Problem hero_codescalers is not correctly reachable through hero_router due to a prefix routing issue. The service was tested directly (netcat) but not through the router, so the prefix forwarding was never validated. ## Steps to fix - Verify hero_codescalers_ui correctly handles the forwarded prefix header injected by hero_router - Test end-to-end: browser → hero_router → hero_codescalers_ui - Do not test with netcat or direct socket — must go through hero_router ## Acceptance Criteria - [ ] hero_codescalers UI loads correctly when accessed via hero_router - [ ] All UI routes work with the injected prefix - [ ] No direct socket bypass needed
mahmoud self-assigned this 2026-04-30 11:12:24 +00:00
mahmoud added this to the ACTIVE project 2026-04-30 11:12:26 +00:00
Author
Owner

Implementation Spec for Issue #19

Objective

Make hero_codescalers_ui correctly reachable via hero_router at /hero_codescalers/ui (and any future webname alias such as /hero_codescalers/admin). The UI service already extracts X-Forwarded-Prefix and uses {{ base_path }} in templates, but the design has two latent problems that prevent the end-to-end browser → hero_router → hero_codescalers_ui path from working in every supported case, and this path was never validated. This spec fixes the prefix wiring, makes the in-page JSON-RPC calls always go through hero_router via the sibling-shortcut convention, and adds a real end-to-end test that exercises the path from the TCP entry point.

Requirements

  1. The UI must read the prefix injected by hero_router (X-Forwarded-Prefix) and stamp it into every absolute link, asset URL, and JSON-RPC URL emitted to the browser. This already partially works — finish the job.
  2. The JSON-RPC URL the browser uses (RPC_BASE + "/rpc") must reach rpc.sock of hero_codescalers regardless of which webname the UI is mounted under (ui today, admin is a future alias). Today the rpc_base computation hard-codes the "/ui" suffix and silently produces an empty RPC_BASE for any other webname, which collides with hero_router's own TCP-level /rpc and breaks all RPC.
  3. Direct (no-prefix) access must keep working — no hard dependency on the proxy.
  4. There must be a curl-driven smoke test that goes browser-style through hero_router's TCP listener (not netcat into the UI Unix socket). It must verify HTML loading, static assets, /health, /.well-known/heroservice.json, and a JSON-RPC round-trip.
  5. README/docs note pointing at the hero_web_prefix skill convention so future contributors do not regress this.

Files to Modify/Create

Modify:

  • crates/hero_codescalers_ui/src/main.rs
  • crates/hero_codescalers_ui/templates/base.html
  • crates/hero_codescalers_ui/templates/index.html (only if any new absolute URL is added; current contents already use {{ base_path }} consistently)
  • Makefile (add make test-router target)

Create:

  • crates/hero_codescalers_ui/scripts/test-router-prefix.sh — curl-driven end-to-end smoke test through hero_router's TCP port.

No new Rust modules are required — the existing base_path_middleware and IndexTemplate already cover everything; the change is one struct field, one handler line, two template lines, one bash script.

Implementation Plan

Step 1: Fix the rpc_base computation so it works for any webname

Files:

  • crates/hero_codescalers_ui/src/main.rs

Subtasks:

  1. Locate index_handler (current logic computes rpc_base as format!("{}/rpc", &base_path[..base_path.len() - 3]) only when base_path.ends_with("/ui")).

  2. Replace with the sibling-shortcut path that hero_router already supports for both ui and admin webnames (see hero_router/crates/hero_router/src/server/routes.rs lines 1100-1144 — POST /<svc>/<webname>/rpc is rewritten internally to rpc.sock POST /rpc):

    let rpc_base = if base_path.is_empty() {
        String::new()                      // direct access — same-origin /rpc
    } else {
        format!("{}/rpc", base_path)       // sibling-shortcut → rpc.sock via hero_router
    };
    

    Rationale: this collapses both webname cases (and any future alias) into one branch, removes the silent failure when accessed under /admin, and uses the documented hero_router shortcut. The same-origin direct-access fallback is preserved (empty base_path → empty rpc_base → browser fetches /rpc → local rpc_proxy_handler).

  3. Confirm the existing IndexTemplate field rpc_base: String still matches; no struct change needed.

  4. Add a 2-line doc comment above index_handler referencing the hero_web_prefix skill and the hero_router sibling shortcut so the next reader does not re-introduce the bug.

Dependencies: none.

Step 2: Audit templates for any remaining unprefixed absolute URLs

Files:

  • crates/hero_codescalers_ui/templates/base.html
  • crates/hero_codescalers_ui/templates/index.html

Subtasks:

  1. Grep both templates for href="/, src="/, action="/, and any string literal starting with /. Confirm every one of them is preceded by {{ base_path }}.
  2. Verify the inline JS block in base.html that defines BASE_PATH and RPC_BASE is reading the same Tera variables produced by IndexTemplate.
  3. If any literal /css/, /js/, /favicon.svg, or hash-based but absolute link is found without {{ base_path }}, prefix it.

Dependencies: none — can run in parallel with Step 1.

Step 3: Verify the JS layer respects BASE_PATH/RPC_BASE everywhere

Files:

  • crates/hero_codescalers_ui/static/js/dashboard.js
  • crates/hero_codescalers_ui/static/js/connection-status.js

Subtasks:

  1. Confirm rpcCall() uses RPC_BASE + '/rpc'.
  2. Confirm initDashboard() builds the connection-status healthUrl as BASE_PATH + '/health'.
  3. Confirm connection-status.js only fetches opts.healthUrl and never hard-codes a path.
  4. Confirm the hash router only mutates window.location.hash — never the path.
  5. No source change is expected in this step — verification pass; if any hard-coded absolute fetch URL turns up that bypasses both BASE_PATH and RPC_BASE, change it.

Dependencies: Step 1.

Step 4: Add an end-to-end smoke test through hero_router

Files (create):

  • crates/hero_codescalers_ui/scripts/test-router-prefix.sh

Files (modify):

  • Makefile

Subtasks:

  1. Write a bash script that:
    • Accepts ROUTER_HOST (default 127.0.0.1) and ROUTER_PORT (default 9988) and SERVICE (default hero_codescalers).
    • Asserts hero_router's TCP listener is up.
    • Asserts the UI HTML loads through the prefix and contains BASE_PATH = "/hero_codescalers/ui" and RPC_BASE = "/hero_codescalers/rpc".
    • Asserts a static asset loads through the prefix.
    • Asserts the UI's /health is reachable through the prefix and returns JSON with "service":"hero_codescalers".
    • Asserts the heroservice manifest loads through the prefix.
    • Asserts the sibling-shortcut RPC works through the prefix.
    • Forbids netcat / direct ui.sock probing — comment the file with a banner.
    • Exits non-zero on any assertion failure.
  2. Reuse the colour helpers and structure from crates/hero_codescalers_ui/scripts/test-users-ui.sh.
  3. Add a test-router target to the top-level Makefile.

Dependencies: Step 1, Step 2.

Step 5: Document the convention for future contributors

Files:

  • crates/hero_codescalers_ui/src/main.rs (extend module docstring)
  • CLAUDE.md (one-paragraph note under Architecture)

Subtasks:

  1. Add a short note to the UI crate's module docstring referencing the hero_web_prefix Claude skill.
  2. Add a one-paragraph entry to CLAUDE.md explaining the prefix mount point and make test-router.

Dependencies: Step 1, Step 4.

Acceptance Criteria

  • make test-router passes against a running stack (service_codescalers start plus a running hero_router).
  • Loading http://<router-host>:9988/hero_codescalers/ui/ in a browser renders the dashboard, all CSS/JS/images load (no 404s), connection-status dot is green, and tab switches / RPC calls succeed.
  • Loading http://<router-host>:9988/hero_codescalers/ui (no trailing slash) also renders.
  • Loading the UI directly via its Unix socket still works.
  • No netcat or direct ui.sock manipulation is part of the new test path.
  • grep -nE 'href="/|src="/|action="/' crates/hero_codescalers_ui/templates/*.html returns zero hits without {{ base_path }} immediately after the opening quote.

Notes

  • hero_router's exact prefix semantics: the injected header is always X-Forwarded-Prefix: /<service_name>/<webname> with no trailing slash. The middleware in main.rs already trims trailing slashes defensively.
  • The sibling-shortcut behaviour (POST /<svc>/ui/rpc and POST /<svc>/admin/rpc both reach rpc.sock) is the linchpin of the Step 1 fix — no client-side changes are required, only emitting the correct URL from the template.
  • hero_proc_ui is the canonical reference implementation. It does not need a separate rpc_base because it merges the generated openrpc_proxy! router and the JS uses BASE_PATH + '/rpc' which equals the sibling-shortcut path that hero_router rewrites. The fix in Step 1 brings hero_codescalers_ui to the same shape.
  • No Cargo.toml changes are required. No new dependencies. No new Rust modules.
  • The existing admin_secrets whitelist gate runs only on TCP connections, not on UDS — when traffic arrives via hero_router's UDS proxy to ui.sock, it is correctly bypassed. This is unchanged by this issue.
## Implementation Spec for Issue #19 ### Objective Make `hero_codescalers_ui` correctly reachable via `hero_router` at `/hero_codescalers/ui` (and any future webname alias such as `/hero_codescalers/admin`). The UI service already extracts `X-Forwarded-Prefix` and uses `{{ base_path }}` in templates, but the design has two latent problems that prevent the end-to-end browser → hero_router → hero_codescalers_ui path from working in every supported case, and this path was never validated. This spec fixes the prefix wiring, makes the in-page JSON-RPC calls always go through hero_router via the sibling-shortcut convention, and adds a real end-to-end test that exercises the path from the TCP entry point. ### Requirements 1. The UI must read the prefix injected by hero_router (`X-Forwarded-Prefix`) and stamp it into every absolute link, asset URL, and JSON-RPC URL emitted to the browser. This already partially works — finish the job. 2. The JSON-RPC URL the browser uses (`RPC_BASE + "/rpc"`) must reach `rpc.sock` of `hero_codescalers` regardless of which webname the UI is mounted under (`ui` today, `admin` is a future alias). Today the `rpc_base` computation hard-codes the `"/ui"` suffix and silently produces an empty `RPC_BASE` for any other webname, which collides with hero_router's own TCP-level `/rpc` and breaks all RPC. 3. Direct (no-prefix) access must keep working — no hard dependency on the proxy. 4. There must be a curl-driven smoke test that goes browser-style through `hero_router`'s TCP listener (not netcat into the UI Unix socket). It must verify HTML loading, static assets, `/health`, `/.well-known/heroservice.json`, and a JSON-RPC round-trip. 5. README/docs note pointing at the `hero_web_prefix` skill convention so future contributors do not regress this. ### Files to Modify/Create Modify: - `crates/hero_codescalers_ui/src/main.rs` - `crates/hero_codescalers_ui/templates/base.html` - `crates/hero_codescalers_ui/templates/index.html` (only if any new absolute URL is added; current contents already use `{{ base_path }}` consistently) - `Makefile` (add `make test-router` target) Create: - `crates/hero_codescalers_ui/scripts/test-router-prefix.sh` — curl-driven end-to-end smoke test through hero_router's TCP port. No new Rust modules are required — the existing `base_path_middleware` and `IndexTemplate` already cover everything; the change is one struct field, one handler line, two template lines, one bash script. ### Implementation Plan #### Step 1: Fix the `rpc_base` computation so it works for any webname Files: - `crates/hero_codescalers_ui/src/main.rs` Subtasks: 1. Locate `index_handler` (current logic computes `rpc_base` as `format!("{}/rpc", &base_path[..base_path.len() - 3])` only when `base_path.ends_with("/ui")`). 2. Replace with the sibling-shortcut path that hero_router already supports for both `ui` and `admin` webnames (see `hero_router/crates/hero_router/src/server/routes.rs` lines 1100-1144 — `POST /<svc>/<webname>/rpc` is rewritten internally to `rpc.sock` `POST /rpc`): ``` let rpc_base = if base_path.is_empty() { String::new() // direct access — same-origin /rpc } else { format!("{}/rpc", base_path) // sibling-shortcut → rpc.sock via hero_router }; ``` Rationale: this collapses both webname cases (and any future alias) into one branch, removes the silent failure when accessed under `/admin`, and uses the documented hero_router shortcut. The same-origin direct-access fallback is preserved (empty `base_path` → empty `rpc_base` → browser fetches `/rpc` → local `rpc_proxy_handler`). 3. Confirm the existing `IndexTemplate` field `rpc_base: String` still matches; no struct change needed. 4. Add a 2-line doc comment above `index_handler` referencing the hero_web_prefix skill and the hero_router sibling shortcut so the next reader does not re-introduce the bug. Dependencies: none. #### Step 2: Audit templates for any remaining unprefixed absolute URLs Files: - `crates/hero_codescalers_ui/templates/base.html` - `crates/hero_codescalers_ui/templates/index.html` Subtasks: 1. Grep both templates for `href="/`, `src="/`, `action="/`, and any string literal starting with `/`. Confirm every one of them is preceded by `{{ base_path }}`. 2. Verify the inline JS block in `base.html` that defines `BASE_PATH` and `RPC_BASE` is reading the same Tera variables produced by `IndexTemplate`. 3. If any literal `/css/`, `/js/`, `/favicon.svg`, or hash-based but absolute link is found without `{{ base_path }}`, prefix it. Dependencies: none — can run in parallel with Step 1. #### Step 3: Verify the JS layer respects `BASE_PATH`/`RPC_BASE` everywhere Files: - `crates/hero_codescalers_ui/static/js/dashboard.js` - `crates/hero_codescalers_ui/static/js/connection-status.js` Subtasks: 1. Confirm `rpcCall()` uses `RPC_BASE + '/rpc'`. 2. Confirm `initDashboard()` builds the connection-status `healthUrl` as `BASE_PATH + '/health'`. 3. Confirm `connection-status.js` only fetches `opts.healthUrl` and never hard-codes a path. 4. Confirm the hash router only mutates `window.location.hash` — never the path. 5. No source change is expected in this step — verification pass; if any hard-coded absolute fetch URL turns up that bypasses both `BASE_PATH` and `RPC_BASE`, change it. Dependencies: Step 1. #### Step 4: Add an end-to-end smoke test through hero_router Files (create): - `crates/hero_codescalers_ui/scripts/test-router-prefix.sh` Files (modify): - `Makefile` Subtasks: 1. Write a bash script that: - Accepts `ROUTER_HOST` (default `127.0.0.1`) and `ROUTER_PORT` (default `9988`) and `SERVICE` (default `hero_codescalers`). - Asserts hero_router's TCP listener is up. - Asserts the UI HTML loads through the prefix and contains `BASE_PATH = "/hero_codescalers/ui"` and `RPC_BASE = "/hero_codescalers/rpc"`. - Asserts a static asset loads through the prefix. - Asserts the UI's `/health` is reachable through the prefix and returns JSON with `"service":"hero_codescalers"`. - Asserts the heroservice manifest loads through the prefix. - Asserts the sibling-shortcut RPC works through the prefix. - Forbids netcat / direct ui.sock probing — comment the file with a banner. - Exits non-zero on any assertion failure. 2. Reuse the colour helpers and structure from `crates/hero_codescalers_ui/scripts/test-users-ui.sh`. 3. Add a `test-router` target to the top-level Makefile. Dependencies: Step 1, Step 2. #### Step 5: Document the convention for future contributors Files: - `crates/hero_codescalers_ui/src/main.rs` (extend module docstring) - `CLAUDE.md` (one-paragraph note under Architecture) Subtasks: 1. Add a short note to the UI crate's module docstring referencing the `hero_web_prefix` Claude skill. 2. Add a one-paragraph entry to `CLAUDE.md` explaining the prefix mount point and `make test-router`. Dependencies: Step 1, Step 4. ### Acceptance Criteria - [ ] `make test-router` passes against a running stack (`service_codescalers start` plus a running `hero_router`). - [ ] Loading `http://<router-host>:9988/hero_codescalers/ui/` in a browser renders the dashboard, all CSS/JS/images load (no 404s), connection-status dot is green, and tab switches / RPC calls succeed. - [ ] Loading `http://<router-host>:9988/hero_codescalers/ui` (no trailing slash) also renders. - [ ] Loading the UI directly via its Unix socket still works. - [ ] No netcat or direct ui.sock manipulation is part of the new test path. - [ ] `grep -nE 'href="/|src="/|action="/' crates/hero_codescalers_ui/templates/*.html` returns zero hits without `{{ base_path }}` immediately after the opening quote. ### Notes - hero_router's exact prefix semantics: the injected header is always `X-Forwarded-Prefix: /<service_name>/<webname>` with no trailing slash. The middleware in `main.rs` already trims trailing slashes defensively. - The sibling-shortcut behaviour (`POST /<svc>/ui/rpc` and `POST /<svc>/admin/rpc` both reach `rpc.sock`) is the linchpin of the Step 1 fix — no client-side changes are required, only emitting the correct URL from the template. - `hero_proc_ui` is the canonical reference implementation. It does not need a separate `rpc_base` because it merges the generated `openrpc_proxy!` router and the JS uses `BASE_PATH + '/rpc'` which equals the sibling-shortcut path that hero_router rewrites. The fix in Step 1 brings hero_codescalers_ui to the same shape. - No Cargo.toml changes are required. No new dependencies. No new Rust modules. - The existing `admin_secrets` whitelist gate runs only on TCP connections, not on UDS — when traffic arrives via hero_router's UDS proxy to `ui.sock`, it is correctly bypassed. This is unchanged by this issue.
Author
Owner

Test Results

cargo check --workspace

pass

cargo test --workspace --lib

pass

  • Total: 0
  • Passed: 0
  • Failed: 0

(Workspace libs hero_codescalers_sdk and nu_exec compiled and ran with 0 tests defined; test result: ok for both.)

Smoke script syntax (bash -n scripts/test-router-prefix.sh)

pass

Note

make test-router was not run here — it requires a live hero_router + running hero_codescalers service. Run it manually after deploying:

make test-router
## Test Results ### `cargo check --workspace` pass ### `cargo test --workspace --lib` pass - Total: 0 - Passed: 0 - Failed: 0 (Workspace libs `hero_codescalers_sdk` and `nu_exec` compiled and ran with 0 tests defined; `test result: ok` for both.) ### Smoke script syntax (`bash -n scripts/test-router-prefix.sh`) pass ### Note `make test-router` was not run here — it requires a live `hero_router` + running `hero_codescalers` service. Run it manually after deploying: make test-router
Author
Owner

Implementation Summary

Changes

crates/hero_codescalers_ui/src/main.rs (+13 / -3)

  • index_handler: replaced the /ui-suffix-specific rpc_base computation with a webname-agnostic sibling-shortcut form. When base_path is non-empty, rpc_base = "{base_path}/rpc" (e.g. /hero_codescalers/ui/rpc); when empty (direct UDS access), rpc_base = "" so the browser falls through to same-origin /rpc served by the local rpc_proxy_handler.
  • Added a 3-line // comment above the block explaining the sibling-shortcut convention and pointing at the hero_web_prefix skill.
  • Extended the module-level //! docstring with a "Reverse-proxy prefix" note (template prefix rule, RPC_BASE rule, X-Forwarded-Prefix source).

crates/hero_codescalers_ui/scripts/test-router-prefix.sh (new, executable)

  • Curl-driven end-to-end smoke test through hero_router's TCP listener — validates HTML loading, the inline BASE_PATH/RPC_BASE JS values, a static asset, /health, .well-known/heroservice.json, and a sibling-shortcut JSON-RPC round-trip.
  • Banner forbids netcat / direct ui.sock probing. Env vars: ROUTER_HOST (127.0.0.1), ROUTER_PORT (9988), SERVICE (hero_codescalers), WEBNAME (ui).
  • Color helpers and assertion style mirror the existing scripts/test-users-ui.sh.
  • 6 assertions, fail-fast with red summary, green summary on success.

Makefile (+4 / -1)

  • New test-router target invoking bash crates/hero_codescalers_ui/scripts/test-router-prefix.sh, placed adjacent to test-server and test-ui.
  • test-router added to .PHONY.

CLAUDE.md (+4 / -0)

  • New "Reverse-proxy / hero_router prefix" subsection at the end of Architecture: documents the /hero_codescalers/ui mount, the X-Forwarded-Prefix injection, the sibling-shortcut RPC rewrite, and the make test-router validation step.

crates/hero_codescalers_ui/templates/*.html — no changes
Audit confirmed every absolute URL in base.html and index.html is already prefixed with {{ base_path }} and the inline <script> block stamps both BASE_PATH and RPC_BASE from the Tera variables.

crates/hero_codescalers_ui/static/js/*.js — no changes
Verified dashboard.js uses RPC_BASE + '/rpc' and BASE_PATH + '/health' consistently; connection-status.js only fetches opts.healthUrl; the hash router never touches the path.

Tests

  • cargo check --workspace: pass
  • cargo test --workspace --lib: pass (2 lib crates, all green)
  • bash -n scripts/test-router-prefix.sh: pass

Manual validation (post-deploy)

Run this once hero_router and hero_codescalers are running on this machine:

make test-router

Then load http://<router-host>:9988/hero_codescalers/ui/ in a browser and confirm:

  • The dashboard renders (no 404s in the network tab).
  • The connection-status dot turns green.
  • Switching tabs / triggering RPCs (e.g. opening Sessions to call session.list) succeeds with no rpcCall failed console errors.
  • Direct UDS access to the UI socket still works for both HTML and /rpc.

Acceptance criteria mapping

  • UI loads through hero_router: covered by Step 1 fix + assertion 1 of make test-router.
  • All UI routes work with the injected prefix: covered by template/JS audit (Steps 2–3) plus assertions 3, 4, 5 of make test-router.
  • No direct socket bypass: explicit banner in the smoke script forbids it; the script only exercises hero_router's TCP entry.
## Implementation Summary ### Changes **`crates/hero_codescalers_ui/src/main.rs`** (+13 / -3) - `index_handler`: replaced the `/ui`-suffix-specific `rpc_base` computation with a webname-agnostic sibling-shortcut form. When `base_path` is non-empty, `rpc_base = "{base_path}/rpc"` (e.g. `/hero_codescalers/ui/rpc`); when empty (direct UDS access), `rpc_base = ""` so the browser falls through to same-origin `/rpc` served by the local `rpc_proxy_handler`. - Added a 3-line `//` comment above the block explaining the sibling-shortcut convention and pointing at the `hero_web_prefix` skill. - Extended the module-level `//!` docstring with a "Reverse-proxy prefix" note (template prefix rule, RPC_BASE rule, X-Forwarded-Prefix source). **`crates/hero_codescalers_ui/scripts/test-router-prefix.sh`** (new, executable) - Curl-driven end-to-end smoke test through hero_router's TCP listener — validates HTML loading, the inline `BASE_PATH`/`RPC_BASE` JS values, a static asset, `/health`, `.well-known/heroservice.json`, and a sibling-shortcut JSON-RPC round-trip. - Banner forbids netcat / direct ui.sock probing. Env vars: `ROUTER_HOST` (127.0.0.1), `ROUTER_PORT` (9988), `SERVICE` (hero_codescalers), `WEBNAME` (ui). - Color helpers and assertion style mirror the existing `scripts/test-users-ui.sh`. - 6 assertions, fail-fast with red summary, green summary on success. **`Makefile`** (+4 / -1) - New `test-router` target invoking `bash crates/hero_codescalers_ui/scripts/test-router-prefix.sh`, placed adjacent to `test-server` and `test-ui`. - `test-router` added to `.PHONY`. **`CLAUDE.md`** (+4 / -0) - New "Reverse-proxy / hero_router prefix" subsection at the end of Architecture: documents the `/hero_codescalers/ui` mount, the `X-Forwarded-Prefix` injection, the sibling-shortcut RPC rewrite, and the `make test-router` validation step. **`crates/hero_codescalers_ui/templates/*.html`** — no changes Audit confirmed every absolute URL in `base.html` and `index.html` is already prefixed with `{{ base_path }}` and the inline `<script>` block stamps both `BASE_PATH` and `RPC_BASE` from the Tera variables. **`crates/hero_codescalers_ui/static/js/*.js`** — no changes Verified `dashboard.js` uses `RPC_BASE + '/rpc'` and `BASE_PATH + '/health'` consistently; `connection-status.js` only fetches `opts.healthUrl`; the hash router never touches the path. ### Tests - `cargo check --workspace`: pass - `cargo test --workspace --lib`: pass (2 lib crates, all green) - `bash -n scripts/test-router-prefix.sh`: pass ### Manual validation (post-deploy) Run this once `hero_router` and `hero_codescalers` are running on this machine: make test-router Then load `http://<router-host>:9988/hero_codescalers/ui/` in a browser and confirm: - The dashboard renders (no 404s in the network tab). - The connection-status dot turns green. - Switching tabs / triggering RPCs (e.g. opening Sessions to call `session.list`) succeeds with no `rpcCall failed` console errors. - Direct UDS access to the UI socket still works for both HTML and `/rpc`. ### Acceptance criteria mapping - UI loads through hero_router: covered by Step 1 fix + assertion 1 of `make test-router`. - All UI routes work with the injected prefix: covered by template/JS audit (Steps 2–3) plus assertions 3, 4, 5 of `make test-router`. - No direct socket bypass: explicit banner in the smoke script forbids it; the script only exercises hero_router's TCP entry.
Author
Owner

Closing this. The earlier commit was reverted in 71512f6. Approach was wrong: it added a custom bash smoke script and Makefile target instead of relying on the existing hero_router alignment. No code change is required here beyond what hero_router already does.

Closing this. The earlier commit was reverted in 71512f6. Approach was wrong: it added a custom bash smoke script and Makefile target instead of relying on the existing hero_router alignment. No code change is required here beyond what hero_router already does.
Sign in to join this conversation.
No labels
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_codescalers#19
No description provided.