[nu-demo] hero_router clobbers client X-Hero-Context header with state.context #125
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?
Symptom
Every non-root-context query returned root's data. Contexts dropdown in the UI showed "4x Root" instead of Default/Geomind/Incubaid/ThreeFold, and per-context business/identity/etc data leaked across contexts.
Root cause
hero_router/crates/hero_router/src/server/routes.rslines 553, 1145, 1215, 1266, 1335 unconditionally inject("X-Hero-Context", state.context.to_string())into the upstream request headers. This overwrites any client-suppliedX-Hero-Context, so the value always falls back to the router's own context (0 = root).Demo workaround (applied 2026-04-23)
Patched all 5 sites in
hero_router/crates/hero_router/src/server/routes.rsto preserve the client's header, using.or_else(|| state.context.to_string())so state.context is only used when the client did not provide one. Rebuilt and restarted hero_router.Proper fix
Make client-header-wins the default upstream. The client's
X-Hero-Contextmust always take precedence;state.contextis only the fallback when absent. Add a test that sendsX-Hero-Context: 2and asserts the upstream receives2, not the router's state.context value.Filed 2026-04-23 nu-shell demo bring-up. Signed-off-by: mik-tf
Fixed in hero_router commit
fe1cbd6ondevelopment.Five sites in
server/routes.rsupdated — all non-admin proxy paths now respect the client'sX-Hero-Contextinstead of clobbering it withstate.context:/<service>/rpc/<service>/restand/<service>/api/<service>/<webname>(web/ui fallback)The
/adminbranch (L1245) intentionally keeps passingstate.context.to_string()directly — that path is already gated tostate.context == 0and must NEVER honor a client-supplied context that could escape the gate.Helper added —
resolve_hero_context(headers, default_context)returns the client'sX-Hero-Contextwhen present and non-empty (trims surrounding whitespace), falls back todefault_contextotherwise.Tests added (5 cases at the bottom of routes.rs):
resolve_uses_client_header_when_present— the home#125 regressionresolve_falls_back_when_header_missingresolve_falls_back_when_header_empty(covers""and" ")resolve_trims_whitespaceresolve_passes_through_non_numeric_stringsVerification:
cargo fmt --check,cargo check,cargo clippy --all-targets -- -D warningsclean. All 5 new tests pass + 74 pre-existing.Composes with the home#129 chain — together with home#129(a) (hero_rpc OServer::register registry-persist) and home#129(b) (hero_skills service_osis env passthrough), this completes the full context-routing flow that home#151 was a symptom of.
Meta-tracker: home#193.
Signed-off-by: mik-tf