fix(service_router): use svc_mycelium_address helper, not raw /7 scan #121
No reviewers
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_skills!121
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/service-router-mycelium-address"
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?
Summary
service_router start's auto-detector (svx_mycelium_node_addr) scansip -6 addrand filters for/7 scope globaladdresses to pick a mycelium IP. On multi-user dev boxes this only ever matches the host's canonical mycelium node ID — each user's per-bridge address is a /64 subnet under that /7 prefix and never matches the filter.Result on a shared dev box: every user who runs
service_router startbinds their UI to the host IP instead of their ownmulti_user_add-provisioned bridge IP.End-user impact
A browser from the user's laptop connects to the dev box over mycelium using the user's bridge IP (the one documented in
~/hero/cfg/hero_cfg.toml). But the router is actually bound to the host IP. If the user has setADMIN_SECRETSin hero_router's admin UI to their own bridge IP, the router'sserve_tcp_with_admin_listaccept loop silently TCP-RSTs requests. Symptom:ERR_CONNECTION_RESETin the browser, or a WebSocket reconnect loop that looks like a hero_router code regression but is actually an IP mismatch at the hero_skills module layer.This class of failure ate most of a debugging day during PR #115's validation on a shared dev box.
Fix — two commits
1.
fix(service_router): use svc_mycelium_address helper, not raw /7 scanPrefer the
ipv6_addressfield from~/hero/cfg/hero_cfg.toml(written bymulti_user_addat provisioning time) via the sharedsvc_mycelium_addresshelper inlib.nu:546. That helper already existed but had no consumers —service_livekitandservice_collabeffectively use the same source via$env.MYCELIUM_IP(populated byhero_loaderfrom the same hero_cfg.toml), so this aligns hero_router with the established pattern.The legacy raw
/7scan is preserved as a fallback for hosts without hero_cfg.toml (single-user installs, pre-provisioning bootstrap). Strict expansion — nothing that worked before stops working.2.
fix(lib): svc_mycelium_config silently returned {} due to invalid hasWhile testing the first commit on the dev box, the router still auto-detected the host IP. Turns out
svc_mycelium_confighad been silently broken since it was written:| hasand| typeare not valid nushell commands — both raise parse errors. Both were inside an outertry/catchthat swallowed the error and made the helper return{}for every caller. That's why the helper appeared unused — it was unusable.The
service_routerchange in commit 1 was the first attempt to actually read from it, so the bug surfaced immediately:Fixed by replacing with the idiomatic nu form:
get -o <key>returnsnullfor missing keys instead of throwing, and| default {}keeps the contract intact.openon a.tomlfile always returns a record, so no separate type-check is needed.Testing
service_router.nuandlib.nu— clean.hero_cfg.toml:svc_mycelium_address falsenow returns543:66c5:6430:8f31:1::1as expected.service_router startauto-binds to[543:66c5:6430:8f31:1::1]:9988(the user's bridge IP from hero_cfg.toml) instead of[543:66c5:6430:8f31:5293:1ad9:694a:70f3]:9988(host IP, previous buggy behavior).Scope
Two files, two small commits. No API changes. Every existing caller of
svc_mycelium_config/svc_mycelium_address(currently onlyservice_routerafter this PR) now receives the correct value. Zero effect on single-user hosts without hero_cfg.toml — falls back to the legacy scan.hasa7595dbc20`($content | has mycelium)` and `($content | type)` are not valid nushell commands — they raise parse errors. Both were inside a try/catch block, which swallowed the error and made svc_mycelium_config return {} for every caller. svc_mycelium_address (the only consumer) therefore always returned "". This went unnoticed because svc_mycelium_address had no consumers in the tree until PR #121, which wires service_router up to use it. The router PR then appeared to fall back to the legacy /7 scan in all cases, masking the fact that the helper it was calling was broken. Fix: use `get -o mycelium | default {}` — the idiomatic nu form that returns null for missing keys instead of throwing, combined with `default {}` to produce the same empty-record fallback the original intended. `open` on a .toml file always returns a record, so no type-check is needed. Verified: with a test hero_cfg.toml the helper now returns the configured ipv6_address correctly.