Commit Graph
5 Commits
Author SHA1 Message Date
zooqueenandHanzo Dev df50d16787 Render every console page with the brand of the host serving it
Hanzo CI/CD / cicd (push) Failing after 1h10m29s
CI/CD / cicd (push) Failing after 2h37m43s
A static export has no host when it prerenders, so BrandProvider renders the
tree only once the browser has resolved the host, pages that show the brand
are client components, the static head names no brand, and the title and
favicon come from the host. The chain page keeps its static params and
metadata on the server and renders its body on the client, with RPC endpoints
on the brand's API origin at /v1/rpc/{chain}/{network}.

Hanzo's API origin is web3.hanzo.ai itself. The node fleet view, its landing
strip and its nav link belong to the brand that operates a fleet, which is
Lux alone. llms.txt, one file for every host, names no brand and points at
each host's own /docs/api.

Marketing copy states no certification the company does not hold and no
unmeasured uptime, latency, volume or response-time figure. Every internal
link points at a page that exists, every catalog chain is prerendered, and
the routes test holds page bodies to zero dead links.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-15 12:01:27 -07:00
zeekayandHanzo Dev 1f30a4c21c fix(lux): the fleet is observed through lux-k8s, on /v1
luxd serves /v1 only — server/http/server.go pins baseURL="/v1" — so every
/ext call in this repo was a silent no-op. The fleet collector's _rpc()
returns None on non-200, so the lux.cloud dashboard rendered nodes_rpc_ok:0,
version:null and every node rpc_reachable:false while the fleet was in fact
running luxd/1.36.2 (mainnet), 1.36.24 (testnet), 1.36.25 (devnet).

Fixing the path alone would not have helped: the collector addressed each
validator by a hardcoded public LoadBalancer IP, and there are now zero
LoadBalancer Services in lux-mainnet/testnet/devnet. Those IPs time out. So
node addressing is no longer configured — it is derived from the cluster on
every collection, and the one way to reach a validator is the lux-k8s API
server's pod proxy, since luxd RPC is cluster-internal.

That collapses the old MODE A / MODE B split into a single path: read the CR
for the declared shape, the pods for phase/readiness/IP, then each pod's
JSON-RPC through the proxy. One credential authenticates both. Deleting the
endpoint ConfigMap and its 15 baked-in IPs removes the failure mode where
infrastructure moves and a dashboard quietly reports zeros.

Probes move to /v1/health/liveness, not /v1/health: a degraded-but-running
validator answers /v1/health with 503, so probing it would restart nodes that
are merely behind. Any fleet from charts/lux could never have gone Ready.

LuxNode.external_ip becomes .ip — with no public per-pod endpoint, the honest
value is the pod IP.

Avalanche endpoints keep /ext; that is their API, not ours.

Measured, with controls: pod-proxy POST /v1/info -> 200 on all 15 pods;
/ext/health -> 404; /zzz/health -> 404; nonexistent pod -> 404. A test asserts
every probe path is under /v1 and fails if /ext returns.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 19:18:04 -07:00
zeekayandHanzo Dev 88397558f2 refactor(console): the account cluster is the shared chrome, and identity has one table
Two duplications, both removed.

1. The header's account cluster was an email in a <span> and a Sign out button.
   It is now <OrgSwitcher/> + <UserMenu/> from @luxfi/ui — the same controls the
   MPC dashboard and lux.market render, reading the same IAM verbs
   (get-account, get-organizations, get-organization-projects), with the same
   phone sheet, which this bar had no equivalent of at all. Signed out they
   offer sign-in rather than showing an empty list that reads as an account with
   no organizations.

2. lib/brand.ts held a SECOND host→brand table. It kept what is genuinely its
   own — logos, taglines, palettes, footer links, the ecosystem launcher, the
   API origins that answer — and now takes issuer, client id and IAM host from
   @luxfi/ui/white-label, which is the same resolver every Lux surface already
   uses. Two copies of one fact is two things to get wrong, and these two DID
   disagree: this table had Zoo on zoolabs.id (right) and the shared one on
   id.zoo.network (an alias whose own discovery document names zoolabs.id, so a
   client on it rejects every token). The shared table is fixed; this file no
   longer has an opinion to be wrong about.

The bundler wiring for the gui engine comes from `withLuxUi` — the one place it
lives, rather than a hand-rolled transpile list per app.

`next build` passes (static export, every route emitted). `pnpm test` 26/26,
including the assertion that lux.cloud + lux-cloud + https://lux.cloud/auth/callback
— the one login that works today — is unchanged.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 14:59:30 -07:00
zeekayandHanzo Dev 3e7d212986 fix(console): one exported apiBase, and no relative /api/ paths
Three dashboard surfaces fetched a RELATIVE /api/v1/... path. That cannot
resolve in a static export — there is no server at that origin — so the
observability panel, the services grid and the AI chat were dead on every
deployed host. It also violates the v1-only rule: the prefix is /v1, never /api.
They now call the host-derived origin at /v1/...

Deleted app/api/health/route.ts, which emitted out/api/health — an /api/ path
SHIPPED INSIDE the artifact.

The deeper fix is the duplication. lib/fleet.ts kept a PRIVATE copy of the
"brand apiUrl, else build-time default" resolver. A second private copy of
exactly that logic, in lib/auth.tsx, shadowed its own import and called itself —
infinite recursion that killed every checkAuth/login/register on any host
classified as local, i.e. all of local development. That copy is already gone;
this removes the other one. apiBase now lives once, exported from lib/api.ts
beside getApiUrl, and fleet.ts imports it.

Left alone deliberately: the /api/v1 strings in app/products/mpc are curl
examples for a CUSTOMER's own host, not calls this app makes.

Console compiles clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-26 20:01:02 -07:00
zeekayandHanzo Dev 7d293212cb refactor: web/ is now console/ — bootnode/bootnode is the backend, bootnode/console the frontend
Names the two halves for what they are. The repo already holds both (12407e9 merged
bootnode/bootnode into this history); this makes the frontend directory say so, so the layout
reads the way the owner describes the system: backend and frontend separate, one repo.

git mv throughout — 187 renames, history preserved. Every path reference follows: hanzo.yml
build context and dockerfile, compose.yml, compose.prod.yml, start.sh, LLM.md,
infra/k8s/web-deployments.yaml, infra/cloud/deploy.sh, and the Dockerfile's own COPY paths.
Image and container names (bootnode-web, the -web tag suffix) are deliberately NOT renamed here:
those are a deploy contract the App CR and ingress bind to on port 3001, and breaking them is a
separate, staged change.

Console builds green after the move; the Go tree builds.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-26 17:47:51 -07:00