100 Commits
Author SHA1 Message Date
zeekay 51460827d4 Merge the forge's lux/universe into GitHub's, the one main from here
The two mains shared no history, so this is a per-file three-way merge:
for each file the 65 forge-only commits touched (by patch-id), the base is
the newest version both histories held. 105 files merged or took one side
cleanly, 48 were already identical, and the 45 true conflicts and 31
modify/delete pairs were resolved by what runs on the cluster:

- The forge wins where it is live: explorer 1.5.56 (digest 45db11ff) and
  its archive readers, explore-fe-hanzo's ConfigMap env (AI coin,
  /v1/indexer/hanzo, /v1/chain/hanzo/rpc), exchange-api reading
  luxd-archive, and explore-fe-{lux,zoo}-testnet, pinned to what they run
  (v2.8.5-lux / v2.8.4-lux).
- GitHub wins where it is live: explore-fe-lux v2.8.5-lux, explore-fe-zoo
  v2.8.4-lux, bankd v1.0.18, lux-build's routes.
- The forge's retirement of workloads that run nowhere stands: lux-mainnet
  dex, lux-hb2, lux-market, traffic, wallet-web; the lux-testnet frontends,
  indexer, exchange and gateways; lux-operator. deploy/lux-testnet/luxd.yaml
  stays, since roll_luxd.sh reads it.
- GitHub's deletions stand: lux-finance and lux-financial (static sites
  now), the k8s/ operator manifests, .hanzo/workflows/cicd.yml.
- Paths are /v1/chain/C/rpc where the forge had written /v1/chain/c. All
  four spellings answer; this one is the documented form. The forge's
  /{network}/v1 doc lines are dropped: a network is a host, and the prefix
  404s.

Dry-run against the running objects (server-side, as CD applies), the
merged explorer shows no change where GitHub's showed 152 lines, and no
other live workload moves further from what runs. Every deploy/*/*.yaml
renders with charts/app; price.yaml, which failed on GitHub, now renders.

Claude-Session: https://claude.ai/code/session_01TzirYkGmD88w4GipqivUtV
2026-09-23 20:20:03 -07:00
zeekayandHanzo Dev 935887cd24 explorer 1.5.56 fills the heights it skipped, and Hanzo's coin is AI
explorer 1.5.56 embeds indexer v1.5.12: a null block from a lagging hanzod
seat is retried rather than stored as an empty block, and a start-up audit
indexed the 525 Hanzo heights earlier runs had skipped.

Chain 36963's native coin is AI, never HANZO: the Hanzo explorer page and the
compose explorers for Hanzo mainnet, testnet and devnet now say so.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 20:09:14 -07:00
zeekayandHanzo Dev fa27df3a25 explore-fe-hanzo pins v1.1.32, the image running
The Hanzo explorer was re-applied twice on 2026-09-24 from outside this repo
(v1.1.30, then v1.1.32), after this file had pinned v2.8.5-lux. explore.hanzo.ai
and explore.hanzo.network are Hanzo's names and explore-hanzo.lux.network now
redirects to explore.hanzo.ai, so this pin follows the running image rather than
the Lux release.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 19:53:26 -07:00
zeekayandHanzo Dev 8c6119f357 Lux zones match the live DNS; KMS scripts name their endpoint; explorer rollouts keep a pod serving
k8s/dns is re-exported from the live zones: bridge.lux.network, the ACME TXT
left for bridge, bridge-api, mpc and api.mpc, lux.chat's Azure asuid records and
the GoDaddy _domainconnect CNAMEs on lux.review and lux.training are gone, and
lux.build lists the AWS ingress it has pointed at since 2026-09-19.

kms.lux.cloud has no AWS backend: Lux's own KMS (lux-kms-go) runs on no cluster
here. kms-gen-validator-keys.sh and kms-seed.sh no longer default to it; they
require KMS_API_URL, because a default that does not resolve turned every key
push into a "SKIP" line. NETWORKS.yaml stops listing mpc-api.lux.network,
mpc.lux.network and kms.lux.cloud for the MPC topology.

explore-fe-lux and explore-fe-zoo run one replica each; with maxUnavailable 1 a
rollout stopped the only pod before its replacement was Ready, and the explorer
answered 503 until it was. maxUnavailable is 0 now, as applied live.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 19:45:42 -07:00
zeekay d60e35d8e2 The Hanzo explorer runs v1.1.32, which asks hanzod no P-Chain questions
hanzod runs Hanzo's own committee and no P-Chain, so every platform.* read
v1.1.30 sent answered "no such chain: P". v1.1.32 (luxfi/explore 546ed00dc)
sends none there and drops the validators and chains pages and nav entries.
Applied to lux-mainnet; the live Deployment matches this file.

Claude-Session: https://claude.ai/code/session_011Ge9UnfkEK37Lapx5nfPQK
2026-09-23 19:42:32 -07:00
zeekayandHanzo Dev b1059c5e6f Lux's chain archives are declared for CD
deploy/lux-{mainnet,testnet}/luxd-archive.yaml are charts/app values for
the two luxd archives that serve api.lux.network, api.lux.cloud and
api.lux-test.network. They replace the hand-applied k8s/ manifests and
deploy/lux-api/route.yaml, which declared the same objects.

Rendered and dry-run against the running objects (server-side, the way
CD applies), a sync adds the chart's labels, its config checksum and
HANZO_VERSION, and nothing else: same container, genesis, chain config,
volumes and routes. So cd.automated is off until someone syncs one.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 19:31:29 -07:00
zeekay cabba0ea44 The explorer and the Hanzo page read Hanzo's chain at /v1/chain/hanzo
Claude-Session: https://claude.ai/code/session_011Ge9UnfkEK37Lapx5nfPQK
2026-09-23 18:43:13 -07:00
zeekayandClaude Opus 5.5 dce75a3bf2 lux.network: bridge returns as a redirect, ama is gone
bridge.lux.network points at the AWS ingress again, where it redirects to the
bridge in the Lux wallet; forty-nine Lux pages link to it. ama.lux.network
forwarded to a Calendly URL that Calendly reports as not valid, and no page
links to it; the record and its page rule are deleted.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 17:04:22 -07:00
zeekayandClaude Opus 5.5 4f5e4ed702 The Lux and Hanzo explorers run v2.8.5-lux
v2.8.5-lux lists only chains that have an explorer: the SPC and Pars cards
linked names that do not resolve, and every page load asked api.pars.network
for validators and got 502. The Hanzo explorer was still on v1.1.30; it runs
the same image as Lux and Zoo now, from ghcr.io/hanzoai. The Lux testnet
explorer (explore-fe-lux-testnet, not declared here) runs the same image.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 17:03:20 -07:00
zeekayandClaude Opus 5.5 8d75b93694 explore-fe-zoo runs v2.8.4-lux and reports to Zoo's Insights key
On the Zoo explorer the validators page counts only Zoo, /dex answers 404, and
the footer links point at the zooai org and Zoo's own accounts. Applied on AWS
with the same image digest and env.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 16:36:40 -07:00
zeekayandClaude Opus 5.5 8290a9ff38 chain-tip reports how old each Lux chain's newest block is
An RPC that answers eth_chainId says nothing about whether the chain still makes
blocks, and the status page could not tell a halted chain from a live one.
chain-tip answers /v1/tip/<chain> with height, timestamp and age_seconds for
lux-mainnet and lux-testnet, read from their luxd-archive Services. The chains
are fixed in its env; a request names a chain, never a URL. ClusterIP only.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 16:31:58 -07:00
zeekayandClaude Opus 5.5 7c0a15f780 trade runs on AWS: /v1/trade reads the C-Chain from luxd-archive
The Service and route were live with no Deployment behind them, so every
/v1/trade path on api.lux.network and api.lux.cloud answered 503. lux-chain,
the in-cluster name LUX_RPC used, no longer exists; luxd-archive is the Service
the public /v1/chain route serves. The pods run on the apps node, beside the
other lux-mainnet frontends.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 16:11:18 -07:00
zeekay 0e234e6086 Declare game.lux.network
Created live in Cloudflare the same way as the other Sites plane hosts:
proxied, to the AWS ingress.  Its route is hanzo universe's lux-game.

Claude-Session: https://claude.ai/code/session_019ABm6hF8RNyUFpbjQWqfxY
2026-09-23 14:54:17 -07:00
zeekayandHanzo Dev c824445f45 lux.cloud names every host it serves; the wildcard is gone
explore, api-explore and cdn.lux.cloud were answered only through *.lux.cloud,
which also answered admin, kms and s3.lux.cloud with a 404 after their own
records were deleted. The three served hosts now have records of their own.


Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 13:27:32 -07:00
zeekayandHanzo Dev f88620848e iam: lux-ci, Lux's own CI identity; lux-cloud keeps the callback it holds
lux-ci is a service client (client_credentials only) in org lux. A KMS
login with it yields an org-lux token, so bin/kms reads /orgs/lux
HANZO_DEPLOY_TOKEN and a site publishes under lux/<slug>. It is set as a
repo-level secret where a repo must stop inheriting the lux forge org's
KMS_CLIENT_ID/SECRET, which are a Hanzo identity.

lux-cloud's live registration also holds https://lux.id/callback, which
its hosts do not derive. The upsert replaces the URI list, so it is
declared as a redirect exception rather than deleted by this converge.


Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 13:24:43 -07:00
zeekayandClaude Opus 5.5 b9ffdcd688 The Lux zone files are exports of the live zones
Every web record names the AWS ingress, and names with nothing behind them
are gone: dead Cloudflare tunnels (dchain, 01-05.luxno.de), disabled Vercel
and Netlify deployments, the Stripe checkout, GoDaddy parking, unactivated
Google custom URLs, the devnet hosts (no Lux devnet runs), bridge, mpc,
liquid, the SPC and Pars explorers, kms/s3/admin.lux.cloud and
v1.lux.exchange. status.lux.financial is new.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 13:24:00 -07:00
zeekayandClaude Opus 5.5 508c1dd1ef api.lux-test.network answers JSON-RPC at its root; SPC, Pars and the fleet lose their public names
api.lux-test.network/ returned 404 while api.lux.network/ is the C-chain
endpoint; the testnet route now carries the same root rule.

explore-fe-spc and explore-fe-pars (lux-mainnet) are gone: neither chain has
a node for the explorer to index. lux-fleet keeps running with no public
host: api.cloud.lux.network was two labels under lux.network, past the edge
certificate, so no browser could complete a handshake.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 13:23:20 -07:00
zeekayandHanzo Dev 10475386cd lux.tel is the sites plane's; the lux fleet stops claiming it
hanzoai/universe charts/app/values/hanzo/hanzo-domains.yaml routes lux.tel,
www.lux.tel and console.lux.tel to cloud, which serves project tel. Two
more claims lived here: deploy/lux-tel (a static route off /var/www/tel,
priority 100) and k8s/lux-k8s/tel (Deployment + Ingress on
ghcr.io/luxfi/tel:0.1.1, referenced by no kustomization). Both go, so one
declaration claims those hosts.

lux-fleet deletes the Application with preserveResourcesOnDeletion and
no delete verb on the cluster, so removing the file removes nothing live.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 12:08:25 -07:00
zeekayandHanzo Dev 30b9890bac The explorer's testnets and exchange-api read their archive nodes
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 06:21:30 -07:00
zeekayandHanzo Dev 3d9a6b421b The chains answer straight from luxd; the rpc door is gone
The door existed to keep mainnet's admin API off the public path while its
import needed it on and a restart was not yet safe. Both are over: the
import finished at 1,082,780 and 1.37.9 restarts cleanly, so mainnet now runs
with the admin API off like the others. luxd itself refuses admin_, debug_,
personal_ and txpool_ (none are enabled) and answers CORS, which is
everything the door did.

Routes name luxd-archive:9630. Mainnet restarted into this shape at the tip
and was answering at 1,082,780 with history, state and every sampled
transaction intact. The door had capped an in-cluster indexer at 2.5 blocks/s
against 167 direct.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 06:21:01 -07:00
zeekayandClaude Opus 5.5 476105fb46 E2E installs its browsers into node_modules
The lockfile pins Playwright 1.58.2; the runner image carries 1.58.0's
chromium in /opt/playwright, read-only to the job, so installing the pinned
build failed with EACCES there. PLAYWRIGHT_BROWSERS_PATH=0 puts it in
node_modules, which the job owns, on any runner.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 06:17:18 -07:00
zeekayandHanzo Dev f0aa891b2b The lux explorer indexes straight from the archive node
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 06:09:18 -07:00
zeekayandClaude Opus 5.5 731898397c Jobs that asked for lux-build-amd64 name the fleet with self-hosted
The fleet mints a runner only for a job that names self-hosted or a
linux-<arch> label. A job asking for lux-build-amd64 alone was never given
one, and it still matched runners minted for other jobs that named
[self-hosted, lux-build-amd64], so it took theirs and left them queued.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 06:05:26 -07:00
zeekayandClaude Opus 5.5 85a385ebf6 E2E's setup-node caches nothing by leaving cache unset
setup-node v4 reads `cache` as a package-manager name, so `cache: false`
asked it to cache for a manager called "false" and it failed the step
with "Caching for 'false' is not supported". Leaving the input unset is how
v4 caches nothing, which is what the setting meant.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 05:57:59 -07:00
zeekayandClaude Opus 5.5 894fa7ccde E2E uploads its results with upload-artifact v4
GitHub fails any job that references actions/upload-artifact v3 at
"Set up job", before a step runs, so every E2E leg failed without
testing anything. v4 takes the same name, path and retention-days.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 05:54:08 -07:00
zeekayandClaude Opus 5.5 54e357c199 render puts its tool directory on PATH before installing helm
get-helm-3 installs into HELM_INSTALL_DIR and then runs `helm` from PATH to
check the install, so with the directory not yet on PATH it reported
"helm not found" and failed a good install.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 05:48:21 -07:00
zeekayandHanzo Dev de7e584037 The explorer indexes on the apps node
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 05:47:59 -07:00
zeekayandHanzo Dev aab76ddaa9 explorer 1.5.55: the index writes no longer lose to its own readers
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 05:42:34 -07:00
zeekayandHanzo Dev a32988281e lux-bank runs bankd v1.0.18, and Lux ID is the one sign-in the suite proves
bankd v1.0.18 takes only a lux.id access token issued to lux-financial for
the lux org, maps only a member of the admin org to _superusers, and listens
on HTTP alone. Its pod reads none of the bank-secrets keys, so the five env
references to them are gone.

bank-docs states the amd64 node selector its pod already runs with.

e2e/40-lux-financial proves the one way in: neither console serves a password
input or ships a credential in its JS; every sign-in screen hands off to lux.id
with client lux-financial, PKCE S256 and the console's /auth/callback; bankd
answers 404 on every password and Base sign-in route, the code exchange takes
only lux-financial by code or refresh, and a token lux.id did not issue to
lux-financial reads as anonymous. The password-form sign-in and the seeded
ledger totals it asserted are deleted: neither exists.

k8s/lux-k8s/{bank-api,bank-dash,bank-docs,bank-sandbox,bankd,financial} and
scripts/seed-bank-admin.ts are deleted. deploy/lux-bank declares the bank,
lux.financial is a static site, and no host those files name resolves.


Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 05:39:03 -07:00
zeekayandClaude Opus 5.5 fb9e35f11a CI installs its tools where an unprivileged runner can write, and every job names the fleet
The render job piped get-helm-3 into bash, which reaches /usr/local/bin through
sudo, and then imported yaml from a system python that has none; on the lux
fleet the runner is unprivileged and sudo cannot work, so the job failed at its
first step. helm now lands in RUNNER_TEMP and PyYAML in a venv there.

E2E jobs asked for lux-build-amd64 alone. The fleet mints a runner only for a
job naming self-hosted or a linux-<arch> label, so those jobs were never
picked up. They name [self-hosted, lux-build-amd64], as render does, and
install chromium without --with-deps: the runner image carries its libraries.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 05:32:05 -07:00
zeekayandHanzo Dev 50ee742177 Lux archives run 1.37.9, where a restart mid-import resumes
1.37.8 wrote the acceptor tip for a whole import round before committing that
round's tries one block at a time, so a restart partway through left a tip
above the last accepted block, naming blocks with no state, and the C-Chain
could not initialize ("required historical state unavailable (reexec=2)").
1.37.9 (luxfi/evm v1.104.56) writes tip and trie together per block, and moves
a stale tip back to the accepted block on boot.

Measured on live lux-mainnet: stopped mid-import on 1.37.8 at 217,500 with the
tip at 220,000; on 1.37.9 the C-Chain came up at 217,500 immediately and the
luxd-import Job resumed with no wipe. The pod may now be restarted at any point.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 02:25:32 -07:00
zeekayandHanzo Dev ded0b1364b Lux archives run 1.37.8, where an import accepts what it inserts
luxfi/evm#152's cause was the import skipping the per-block accept step (tx
index and trie commit), so every 1.37.7-imported chain answered about one
transaction in two hundred by hash and could not survive a restart. On
1.37.8 lux-testnet answers all 219 by hash, with receipts.

Mainnet is re-imported from an empty database under 1.37.8, driven by the
luxd-import Job, which is a one-off and not in the kustomization. The pod
must not be deleted while it runs: 1.37.8 still cannot initialize a C-Chain
restarted DURING an import. After a completed import, restarts are safe.

The mainnet node asks for 1000m. The chains node is shared, and under
contention CPU divides by request; at 300m the import got a tenth of a core.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 01:39:48 -07:00
zeekayandClaude Opus 5.5 568a55cc40 Lux Financial's consoles sign in through lux-financial, and lux-bank runs v1.0.16
The customer app and the admin console share one public PKCE client,
lux-financial, registered for app.lux.financial and admin.lux.financial with
tokens that live an hour and refresh for a day. lux.financial itself is static
files with no sign-in, so its redirect goes. lux-bank stays bankd's service
identity.

bankd and bank-dash are pinned to v1.0.16 by digest: no password route, no
password form. bank-dash carries only the env its server reads. admin is a
static site, so the Deployment declarations for a bank-admin pod go, in deploy/
and in the k8s/ reference tree.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-23 00:58:44 -07:00
zeekayandHanzo Dev d1674203f0 explorer 1.5.54: pools keep their value while a chain re-imports
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 00:38:24 -07:00
zeekayandHanzo Dev 9137becf73 Brand explorer pages say what their RPC is, now that zoo and hanzo answer
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 00:28:43 -07:00
zeekayandHanzo Dev 5079e447d3 explore.zoo-test.network shows zoo testnet; lux testnet also answers on explore.lux-test.network
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 00:26:26 -07:00
zeekayandHanzo Dev 492138f860 The lux explorer reads the venue the imported chain holds
WLUX, both factories, the quoter and the router are the addresses with code on
96369 now that its history is the one imported from luxfi/state.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 00:13:35 -07:00
zeekay 62bb1e0a11 lux.finance and lux.financial are files, so neither has an app here
Both hosts are one static export of luxfi/financial, served from
s3://hanzo-sites/lux/financial by the lux-financial router in the edge's
sites table (hanzoai/universe infra/lan/ingress.yaml).

lux-finance served lux.finance from a September export in the node-local
/var/www store, and that build crashed in every browser ("Cannot read
properties of undefined (reading 'type')"). lux-financial ran the same era
as a Next server pod behind lux.financial. Both are gone from the cluster.
2026-09-22 23:53:53 -07:00
zeekay 8a65db078a Lux mainnet and testnet are served from their archives on AWS
The canonical C-Chains are the RLP archives, 1,082,781 blocks on mainnet and
218 on testnet. Each runs as luxd-archive on the chains node and answers
publicly through the rpc door, which passes only eth_/net_/web3_ methods and
answers admin_, debug_, personal_ and txpool_ itself.

Testnet is frozen: its database is an emptyDir rebuilt from the archive
inside VM initialization on every boot, so its admin API is never on and no
restart depends on state surviving one. Mainnet is too large for that and
is imported once with admin_importChain; its admin API is behind the door,
and the pod is OnDelete and must not be deleted until luxfi/evm#152 is fixed
(after an import, a restart leaves the C-Chain unable to initialize).

Genesis is declared. The luxd-genesis ConfigMaps now hold the documents the
archives chain to: mainnet block 0 0x3f4fa2a0…, testnet 0x1c5fe377…,
each verified by booting it. The testnet document here before was a
different one (gasLimit 0x3b9aca00) that refuses every archived block, and
the mainnet one carried a C-Chain genesis that hashes to 0x43befc4e….

api.lux.network and api.lux.cloud route /v1/chain and / to the door at
priority 300, above the unified api-* router, and no longer point at
validators on the LAN.

The five-validator luxd sets are 0. They start from a genesis the archive
does not chain to and import nothing, so any block they made would fork
it. They come back on the canonical genesis once #152 is fixed.
2026-09-22 23:53:53 -07:00
zeekayandHanzo Dev fb53a71dbf The explorer indexes lux and zoo testnet; explore-test.lux.network shows lux testnet
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-22 23:51:43 -07:00
zeekayandHanzo Dev b171666579 explorer 1.5.53: brand pages get their live stream and a real block time
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-22 23:44:27 -07:00
zeekayandClaude Opus 5.5 1aedb563ec bankd runs v1.0.15, pinned by digest
lux-bank/bankd serves ghcr.io/luxfi/bank:v1.0.15, a single linux/amd64
manifest at sha256:a1197959: v1.0.14 with the sandbox login bounded per
client address and per account, answering 429 with Retry-After past
either budget.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016dDw5Lp9sZFctwvZLn4nVz
2026-09-22 23:43:49 -07:00
zeekayandClaude Opus 5.5 d3db69745e lux-safe-cgw runs on AWS, so the LAN runs none
safe-cgw.lux.network is served by two replicas on AWS, declared by the overlay
hanzoai/universe infra/aws/values/hanzo/lux-safe-cgw.yaml over this file, which
also pins v0.1.6 by digest.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016dDw5Lp9sZFctwvZLn4nVz
2026-09-22 23:41:52 -07:00
zeekayandClaude Opus 5.5 fb11830b57 bankd runs v1.0.14, pinned by digest
lux-bank/bankd serves ghcr.io/luxfi/bank:v1.0.14, a single linux/amd64
manifest at sha256:d8df6cff. The values file named v1.0.11.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016dDw5Lp9sZFctwvZLn4nVz
2026-09-22 23:38:02 -07:00
zeekayandHanzo Dev e382b39c48 lux-docs: serve docs.lux.network on port 3000
Declare the container port, /health probes, requests, and the
docs.lux.network route. Drop the ghcr-luxfi-fresh pull secret, which
no cluster holds.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-22 23:32:17 -07:00
zeekayandHanzo Dev bf7c9b6f9d The explorer indexes zoo and hanzo, whose nodes now answer
The backend's values were deleted as a copy while it was paused for the lux
mainnet import; it kept running from a live config with one chain, because on
09-09 only lux answered. Zoo (200200) and hanzo (36963) answer in-cluster now,
so they get rows: zoo's venue contracts and 2T genesis are read on its chain,
hanzo's new chain has no venue yet.

The frontends' wallet RPC pointed at api.zoo.ngo (served by cloud, not the
chain) and /v1/chain/hanzo (a 404); both now name the chain endpoint.


Co-authored-by: Hanzo Dev <[email protected]>
2026-09-22 23:31:40 -07:00
zeekayandHanzo Dev aab4e7346a zerocopy: pin the image digest and pull with ghcr-secret
latest now names sha256:d34e9c1c (amd64+arm64); the digest fixes which
bytes run. ghcr-pull exists in no cluster; ghcr-secret is the credential
the other lux apps pull with.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-22 23:31:05 -07:00
zeekayandClaude Opus 5.5 6f39fc6878 The Lux explorer and exchange API run on AWS
explorer, explore-fe-lux and lux-ns/exchange-api now run on the AWS
cluster. The chain is reached through the `rpc` door in lux-mainnet, the
explorer index sits on the data node's gp3 volume, and explore-env-lux is
declared here instead of hand-applied.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016dDw5Lp9sZFctwvZLn4nVz
2026-09-22 23:24:18 -07:00
zeekayandHanzo Dev 1331b8ecae foundation: pull with the credential the cluster has
imagePullSecrets named ghcr-pull, a Secret that exists in no cluster --
the pods sat in ImagePullBackOff on the LAN and again on AWS. ghcr-secret
is the one every other lux-* app pulls with.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-22 22:17:20 -07:00
zeekayandHanzo Dev c23995b3e8 the demo keeps nothing, so it claims nothing
A 20Gi RWO claim takes local-path on k3s, which puts the volume on one
node and pins the pod there — the image is a multi-arch index and the
claim was the only reason it never ran on the other node.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 17:28:09 -07:00
zeekayandHanzo Dev 425b96f66e the cluster is named, not addressed by a gone account
Every provenance line and manifest still named a DigitalOcean context, and
the ARC values described a pool that died with it. A cluster gets a name
here; the address it answers on belongs to the private record.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 16:15:33 -07:00
zeekayandHanzo Dev 1b61aeb6a1 lux.finance answers where lux.financial does
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 13:44:07 -07:00
zeekayandHanzo Dev 25f09006d4 Drop the explorer copies with no live host
Five explore-fe-* deployments and two explorers serve one function. Three
hosts answer 200 -- lux, hanzo and pars -- and are kept. explore.spc.network
does not resolve at all and explorer.lux.network answers 502, so those two
carry a pod each for nobody.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-15 20:53:17 -07:00
zeekayandHanzo Dev 8acf6bc502 Retire the workloads already scaled to zero
Each of these declares replicas: 0 -- no pod, no endpoint, no caller, and no
record of when it was parked. A declaration that runs nothing is not a
deployment, it is a note nobody can date, and it keeps a slot in every fleet
listing and every sync. Git history holds them if one was paused rather than
retired.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-15 20:49:35 -07:00
zeekayandHanzo Dev 134289b57f Drop lux-mainnet work-board: a second copy nothing routes to
work.hanzo.network is served by hanzo-mainnet/work-board and answers 200. This
deployment carries the same image behind a Service with no Ingress, and
work.lux.network answers 404 — so it has taken a pod and an amd64 node slot
without ever having a caller.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-15 16:55:54 -07:00
zeekayandHanzo Dev 305ac2deeb price: drop the KMS host and credential the chart no longer takes
Chart 0.1.14 rejects kms.hostAPI and kms.credentialsSecret, so the
Application could not render at all and sat in Unknown. Where KMS is and
which identity reads it come from the operator's environment.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 22:58:18 -07:00
zeekayandHanzo Dev 662a7dd97e Delete the second edge router instead of parking it
edge.yaml states the invariant: exactly one ziti edge router, advertising a
publicly resolvable address. zrok grants every identity `#all` edge routers, so
the controller hands out whichever are online and one unreachable router poisons
the pool for every external client. hanzo-zt-router was removed for exactly this
— a ClusterIP edge router — and removed rather than zeroed, because a zeroed
Deployment is one `kubectl scale` from re-breaking every laptop. This one is the
same shape: :3022 behind ClusterIP 10.43.53.162.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 21:14:14 -07:00
zeekayandHanzo Dev eaedaf69ca Delete the second edge router instead of parking it
edge.yaml states the invariant: exactly one ziti edge router, advertising a
publicly resolvable address. zrok grants every identity `#all` edge routers, so
the controller hands out whichever are online and one unreachable router poisons
the pool for every external client. hanzo-zt-router was removed for exactly this
— a ClusterIP edge router — and removed rather than zeroed, because a zeroed
Deployment is one `kubectl scale` from re-breaking every laptop. This one is the
same shape: :3022 behind ClusterIP 10.43.53.162.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 21:14:13 -07:00
zeekayandHanzo Dev 5d21f1581a Zero the zt router while its controller is unreachable
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 21:12:06 -07:00
zeekayandHanzo Dev f8e59db7db Zero the zt router while its controller is unreachable
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 21:12:03 -07:00
zeekayandHanzo Dev 119c08ff42 Zero the testnet DEX nothing resolves
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 20:57:17 -07:00
zeekayandHanzo Dev fb662be64d Zero the testnet DEX nothing resolves
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 20:57:09 -07:00
zeekayandHanzo Dev b8f39d9332 Place pods on the architecture their image was built for
144 of the 185 images this estate runs publish amd64 alone, and evo is the one
amd64 node. Where the image is an index containerd refuses it and the pod sits
in ImagePullBackOff; where it is a bare manifest there is no platform check, so
spark's qemu-x86_64 binfmt runs it emulated until it faults. work-board is at
678 restarts that way and testnet's exchange-api at 617.

lux-testnet serves one route, chain-api, and it answers from luxd-archive. The
five deployments zeroed here have no route and no caller.

status.hanzo.ai, status.lux.network and status.zoo.network are served from
hanzo/ and zoo/. The lux-system copies duplicate them and have been unrouted
and unready since the migration. maintenance-page goes with them: nothing
routes to it and its page was never written.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 20:40:53 -07:00
zeekayandHanzo Dev be3d3de8bc Place pods on the architecture their image was built for
144 of the 185 images this estate runs publish amd64 alone, and evo is the one
amd64 node. Where the image is an index containerd refuses it and the pod sits
in ImagePullBackOff; where it is a bare manifest there is no platform check, so
spark's qemu-x86_64 binfmt runs it emulated until it faults. work-board is at
678 restarts that way and testnet's exchange-api at 617. trade.yaml already
states the constraint for dex; these state it for the rest.

lux-testnet serves one route, chain-api, and it answers from luxd-archive. The
five deployments zeroed here have no route and no caller.

status.hanzo.ai, status.lux.network and status.zoo.network are served from
hanzo/ and zoo/. The lux-system copies duplicate them and have been unrouted
and unready since the migration. maintenance-page goes with them: nothing
routes to it and its page was never written.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 20:39:32 -07:00
zeekayandHanzo Dev 89696311dd exchange-api: declare the ghcr pull secret for lux-ns
lux-ns holds no KMS identity, so exchange-api ImagePullBackOff'd on
ghcr.io/luxfi/exchange-api with no dockerconfigjson in the namespace.
Project the shared hanzo ghcr-secret (reads luxfi images) as a
dockerconfigjson pull secret, matching how every other namespace
declares one.


Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 20:36:57 -07:00
zeekayandHanzo Dev 8d364cb0e8 Give the wallet the brand that makes it Lux's
One build serves every label and this file is the only thing that
distinguishes them, so without it the pod waited forty-three hours on a
ConfigMap that could not arrive. Content is the wallet repo's own default
brand.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 20:21:23 -07:00
zeekay 755d21c133 Give the wallet the brand that makes it Lux's
One build serves every label and this file is the only thing that
distinguishes them, so without it the pod waited forty-three hours on a
ConfigMap that could not arrive. Content is the wallet repo's own default
brand.

Claude-Session: https://claude.ai/code/session_018U2e2U4PPc8UaXYyeT9iNu
2026-09-10 20:21:21 -07:00
zeekayandHanzo Dev 0308a08144 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	deploy/lux-mainnet/luxd.yaml

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 18:14:15 -07:00
zeekayandHanzo Dev 469e99db88 lux testnet's C-chain has a public address again
api.lux-test.network reached the ingress and answered 404 — no route claimed it,
because the testnet's luxd StatefulSet never came up. The chain now lives in an
archive node on evo (218 blocks, full historical state), and this routes the
public contract /v1/chain/c/rpc to it. Admin and debug are off on that node.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 18:13:54 -07:00
zeekayandHanzo Dev d1e1c5e7e4 pin: commit as Zach Kelling, Hanzo Dev as co-author
Pins were authored by lux-ci <[email protected]>, so every deploy the pipeline
moved stayed off the owner's history. Pinned-by still says whether CI or a
person ran it.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 14:34:33 -07:00
zeekayandHanzo Dev 1233b5c1d4 trade: v1.14.56, and one prefix
The pin was two versions behind the surface. The binary's paths moved under a
single namespace, so the router named both shapes as a union while the pin sat
on the older one — a route may lead a pin only that far, and only for as long
as the older spellings still answer.

They no longer do. v1.14.56 is published, the deployment is running it, and a
token list answers at /v1/trade: 403 rows on Ethereum, WETH priced at 2460.35
from a v3 pool read against USDC. So the older spellings come off here, in the
commit that retires the version that served them, and the router now describes
the same service the pin does.

strip-role goes with them. It blanked a claim in a request header because a
handler behind it once read one; nothing reads it now, and a middleware kept
for a handler that does not exist is a rule whose reason a later reader cannot
check.

The digest moves with the tag. A digest naming the old image under a new tag
makes the tag decorative and the pin a guess.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 14:28:16 -07:00
zeekayandHanzo Dev ed41deb1e1 The edge publishes the paths the service answers
A prefix in the router that no handler stands behind is a public address whose
reply is whatever binary happens to be at the other end, and the list was
written against a different version than the one pinned here. Nothing in this
tree reads /v1/history and the current source serves no such path, so
publishing it can only reach an older handler.

The remaining legacy prefixes come off in the commit that moves the pin, which
is when the router and the binary describe the same service again.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 13:44:23 -07:00
zeekayandHanzo Dev f5761a7033 exchange-api: tolerate the CI taint on the only node it can run on
The image is amd64-only, so it must run on evo, and evo carries
hanzo.ai/no-ci=true:NoSchedule to keep CI off the production node. The chart
defaults the matching toleration from 0.1.14, but the render CD produced for
this app did not carry it -- the amd64 pod sat Pending on "untolerated
taint(s)" while the two emulated ones on spark kept dying. The workload states
the toleration itself now, so scheduling does not depend on which chart
artifact was cut.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 13:24:06 -07:00
zeekayandHanzo Dev 5424ee8f31 exchange-api: schedule where its image exists
ghcr.io/luxfi/exchange-api is published for linux/amd64 alone. Unpinned, both
replicas landed on the arm64 node, where the kubelet ran them under the
qemu-x86_64 binfmt handler and each died before it could listen -- QEMU
internal SIGSEGV -- so the Service had no ready endpoint and exchange.lux.cloud
answered 503 the moment it was routed. Pinned to amd64; emulation is not a
scheduling strategy.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 13:13:06 -07:00
zeekayandHanzo Dev f261295123 exchange-api answers on exchange.lux.cloud
v1.lux.exchange reads every market, chart, quote and swap through
exchange.lux.cloud, and the only object that ever named that host was a
hand-applied Ingress under k8s/lux-ns that nothing reconciles. Live, nothing
routed it: the host answered 404 and every chart on the exchange was empty.

One rule to exchange-api:4000. The old Ingress listed six prefixes and sent
them all to the same backend, so the bare host says the same thing. exchange-gw
is not in the path -- the edge is the ingress, the service is this one.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 12:58:12 -07:00
zeekayandHanzo Dev 789d95effe api.lux.network: pass /v1/bc through as well
v1.lux.exchange is built against api.lux.network/v1/bc/C/rpc, the path luxd
served before v1.36.179. The lux-api rules matched /v1/chain and / only, so the
exchange's balance and chain calls have answered 404 since the endpoint moved
to the sync node. The sync node is on .148 and serves /v1/bc natively, so the
rule passes it through untouched. Moving the node to .181 either adds the
reverse rewrite here or rebuilds v1 against /v1/chain; the second is the one
path the fleet keeps.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 12:55:17 -07:00
zeekayandHanzo Dev 056eeff305 explorer: index the real chain, not the stopped fork
cchain read lux-chain, the Service whose EndpointSlice named the five docker
validators. Those were a fork of mainnet and are stopped, so every poll was
`connection refused` and the explorer showed the fork's 59 blocks frozen. It
reads luxd-rpc now -- the sync node holding the real chain, mid-import at
437,500 and climbing -- at the /v1/bc path its v1.36.148 build serves.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 13:10:28 -07:00
zeekayandHanzo Dev 61abbb3bfd api.lux.network answers from the node that holds the real chain
Both lux-api rules now send to luxd-rpc, the Service that selects the sync
node, and not to lux-chain, whose hand-made EndpointSlice named the five docker
validators on evo. Those five were a fork of mainnet -- same genesis, a
different block 1, real transactions on both sides -- and they are stopped.
Serving a partially imported real chain beats serving a complete wrong one.

bc-path rewrites /v1/chain/c/... to /v1/bc/C/... because the sync node is on
luxd v1.36.148, which serves the EVM at the old path, while every caller of
api.lux.network speaks the /v1/chain path that v1.36.181 serves. It is the one
thing to delete when the node moves to .181.

Recorded here and applied live by hand: lux-mainnet-luxd has never been synced,
and syncing it now would stand a second luxd beside the hand-applied sync
StatefulSet. When that app is adopted, it carries this route.


Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 13:09:08 -07:00
zeekayandHanzo Dev 359b5bc194 api.lux.network answers from the node that holds the real chain
Both lux-api rules now send to luxd-rpc, the Service that selects the sync
node, and not to lux-chain, whose hand-made EndpointSlice named the five docker
validators on evo. Those five were a fork of mainnet -- same genesis, a
different block 1, real transactions on both sides -- and they are stopped.
Serving a partially imported real chain beats serving a complete wrong one.

bc-path rewrites /v1/chain/c/... to /v1/bc/C/... because the sync node is on
luxd v1.36.148, which serves the EVM at the old path, while every caller of
api.lux.network speaks the /v1/chain path that v1.36.181 serves. It is the one
thing to delete when the node moves to .181.

Recorded here and applied live by hand: lux-mainnet-luxd has never been synced,
and syncing it now would stand a second luxd beside the hand-applied sync
StatefulSet. When that app is adopted, it carries this route.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 13:07:45 -07:00
zeekay 4e0a772011 our runners persist, so a dependency cache is a tar of what is already there 2026-09-09 06:45:41 -07:00
zeekayandHanzo Dev 51dfe1b982 traffic: one key, one name, across every chain
CI/CD / render (push) Failing after 0s
lux-mainnet alone named a `traffic-key` secret that exists in no namespace, so
its sender could never start -- CreateContainerConfigError, and a chain with no
sender stays flat. lux-testnet, lux-devnet, lux-hb2 and hanzo-mainnet all read
lux-deployer/LUX_MNEMONIC already; mainnet now does too.

Index 0 of that mnemonic is funded on all three chains, and TRAFFIC_WALLETS
derives the rest so value circulates instead of piling up in one account.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 02:05:22 -07:00
zeekayandHanzo Dev b6735574bc traffic: give the sender the chain list it mounts
CI/CD / render (push) Failing after 0s
The volume named traffic-chains-gc7kb89hm9, a hash-suffixed ConfigMap no
generator in this repo produces, so it never existed and the pod has sat in
ContainerCreating -- MountVolume.SetUp failed, configmap not found -- for as
long as the Deployment has. A chain with no sender does not build blocks, which
is why mainnet has been flat.

The list names lux-chain, the address that answers eth_chainId 0x17871 and a
rising height. luxd-rpc fronts the StatefulSet whose bootstrap peers no longer
accept a connection, so every path under it is 404.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 01:45:33 -07:00
zeekayandHanzo Dev 655f5a3a5c Zoo and Hanzo have their own networks, so the P-chain does not carry them
Asked to register both with CreateChainTx on Lux mainnet. Neither was created,
and the record now says why rather than leaving the next reader to rediscover it.

Each brand already holds a chain identity elsewhere: hanzod serves 36963 on its
own primary network, bootstrapped, and Zoo's C-chain carries 13,348 blocks on
network 200200 since the 2026-07-14 cutover. A CreateChainTx here would mint a
second identity for the same brand and orphan that history. It also could not
have run: platformvm now serves one handler at /ops and nothing at the chain
base, so the JSON-RPC client both tools open with returns 404 before it reads
anything, and every genesis allocation that could pay the fee is either staked
or behind a mnemonic that is not on this machine.

Records the eleven blockchain ids the primary network does carry, read from the
P-chain rather than from a manifest. T is gone; F and M are there in its place,
which the 2026-06-02 inventory predates. Marks that inventory and the brand-L2
follow-on it promised as superseded, since both still read as the plan.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 01:41:46 -07:00
zeekayandHanzo Dev 9ab3ac661d The trading surface is eight paths, and the indexer answers the rest
/v1/trade carries venues, quote, quotes, swap and the four allowance paths, and
api/openapi.yaml in luxfi/dex describes exactly those — a test there holds the
document to the route table in both directions.

The other half is not missing, it moved. Enumerating a chain — tokens, pools,
positions, TVL, price history — is an index read, and api-explore.lux.cloud
answers it: 16 pools and $39.9M of TVL for 96369 with real symbols and
decimals, measured. Those paths were on the gateway too and answered 500 on
every request, because a quoting surface reads one pool by address and cannot
walk every pool on Ethereum. A screen wanting a market list asks the indexer; a
screen wanting a price for a size asks the gateway.

The swap is built by the venue that gave the price, against the router it read,
and the record of that is the eth_call replay on 96369's live SwapRouter02
returning the quoted amount exactly. Permit2 is not deployed on 96369, so both
permit2 paths answer 404 there naming the reason rather than calldata addressed
to an empty account.

Also records why the route names both path shapes today and why strip-role
stays: both are properties of the image the pin still names, and both come out
in the commit that moves it.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 01:21:54 -07:00
zeekayandHanzo Dev 13db918809 The one amd64 node is the build machine, so say so
evo carries hanzo.ai/no-ci=true:NoSchedule and evo is the only amd64 node this
cluster has. The image is a single amd64 manifest, so nodeSelector arch=amd64
and this toleration are one statement: without the second, the workload has
nowhere at all to run.

NoSchedule does not evict, which is what made that invisible. Two replicas kept
answering while a surge pod sat Pending for three minutes — 0/2 nodes available,
one wrong architecture and one tainted — and the surface would have stayed up
until the first restart, reboot or rollout and then had nowhere to come back to.
Forty-five pods already carry this toleration, including the CD control plane
and the hanzod validators.

Verified by rolling both replicas out and back: quotes answer on 1, 8453 and
96369, /v1/chain/C/rpc is 0x17871, preflight 204.

The fix that removes the need is upstream: the published image is one amd64
manifest rather than an index, so nothing about this workload could schedule on
spark even if the taint went away.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 01:21:06 -07:00
zeekayandHanzo Dev a772db1e7d The route names both path shapes until the pin can move
/v1/trade is where this surface is going: one prefix, the whole thing under it,
and the nine-clause allowlist retired along with the /v1/admin handlers it was
written to keep off the internet. That end state is right and the file now says
so.

It cannot be the whole rule yet. The pin is v1.14.40 and v1.14.40 answers the
older spellings; every v1.14.4x tag cut for the new shape has had its image
build cancelled, so there is nothing published to move the pin to. For fifteen
minutes this route named /v1/trade alone and lux.exchange got a hanzoai/cloud
404 for every quote it asked — a surface reachable, running, and addressed by a
name it does not answer to.

So both are named, which is a union and therefore safe in both directions, and
the nine come out in the same commit that moves the pin past the version serving
them. strip-role stays for the same reason: v1.14.40 still authorises
/v1/admin/* on a header the caller writes, and no rule here should be the only
thing standing between that and the internet.

Measured after: 1 WETH -> 2514.355261 USDC on Ethereum, 2514.426028 on Base,
1 WLUX -> 0.997001483075056760 LUSD on 96369, /v1/chain/C/rpc still 0x17871.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 01:15:38 -07:00
zeekayandHanzo Dev 601747ac26 LLM.md: the chain segment answers, and the trading surface is beside it
The RPC paragraph had it exactly backwards — it said /v1/bc/C/rpc returned 200
and /v1/chain/C/rpc returned 404, which stopped being true when
deploy/lux-api/route.yaml landed. Measured both, and the bare host, and wrote
the readings down.

Adds the trading surface on the same two hosts: where its declaration lives, the
three priorities that share those hosts, and where the router that answers
everything else actually comes from — the ingress file provider, which is
enabled and whose routers are easy to look for in the wrong repository.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 00:27:57 -07:00
zeekayandHanzo Dev faf177aa97 explorers: stop showing Lux's chain under four other brands
CI/CD / render (push) Failing after 0s
zoo, hanzo, spc and pars each declared their own chain id and ticker while
naming api.lux.network/v1/chain/c/rpc as their RPC, so every one of them served
Lux C-Chain blocks relabelled -- the same block 59 and the same miner
0xf66b0259... appearing as ZOO, PARS and SPC. Presenting another chain's
transactions as your own is worse than presenting none.

Each now names its own chain. None of the four answers yet, because those chains
are not running, so the pages show nothing -- which is true -- and they start
working the day their chain does, with no further edit here.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 00:25:24 -07:00
zeekayandHanzo Dev 0bf2051754 api.lux.cloud and api.lux.network answer the trading surface
`ghcr.io/luxfi/dex` carries a second binary, `gateway`, and nothing ran it, so
every quote a Lux interface asked for reached nothing. It runs here as `trade`
— not `gateway`, because this namespace already has one in front of the
validators' RPC.

Two routers on one host and the chain's is the more specific: /v1/chain keeps
priority 300 and this takes 200, above the bare-host router in the ingress file
provider that has been answering these paths out of hanzoai/cloud.

The paths are an allowlist. `PathPrefix(/v1)` would be shorter and would publish
/v1/admin/pool/freeze, which the binary authorises on a request header the
caller writes; those handlers stay reachable from inside the cluster and from
nowhere else, and the header is stripped on the way in as well.

96369 is read through the V3 quoter that landed with the AMM today, and read
over the cluster Service rather than back through Cloudflare — same endpoint,
15ms instead of 149ms, and no dependency on the edge that is serving the answer.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 00:18:29 -07:00
zeekayandHanzo Dev 1953a3a3d3 explorer: name the venue this chain now has
The AMM landed on 96369 on 2026-09-09 (luxfi/standard script/venue.ts,
recorded at deployments/venue/96369.json), so the four fields this file
left unset because nothing was deployed here have addresses to carry:
the two factories whose PairCreated and PoolCreated the subgraph trusts,
the quoter that prices a concentrated route, and the SwapRouter02 a swap
is addressed to.

Changing either factory changes the store's source fingerprint, so the
indexer drops its derived rows and re-reads from block 0 rather than
looking for events already behind its cursor. Applied and restarted: it
read blocks 1..59, 255 events, and values 16 pools at $39,899,893.58 with
LUX at one dollar.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 00:05:41 -07:00
zeekayandHanzo Dev 4a3c9b3d95 explorers: read the chain each one is for, at the path it is served on
CI/CD / render (push) Failing after 0s
Every card on all five explorers was a skeleton that never resolved. The UI
reads a Blockscout-shaped API, and this backend mounts one per chain at
/v1/indexer/<slug>; with NEXT_PUBLIC_API_BASE_PATH "/" the page asked for
/stats, /main-page/blocks and /config/backend-version, which 404, while the
same paths under the prefix answer 200.

All five also named the same slug's host as their own APP_HOST, so each brand
described itself as explore.lux.network. Each now names its own chain and its
own host: zoo reads zoo, hanzo reads hanzo, pars reads pars, spc reads spc.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-09 00:02:04 -07:00
zeekayandHanzo Dev 4b54255f8b go 1.26.8
CI/CD / render (push) Failing after 0s
One toolchain across the estate. The tree carried 1.26.0, .1, .3, .4 and .5
at once, so which compiler built a binary depended on which repo it came
from.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 23:59:46 -07:00
zeekayandHanzo AI 7245a0be3a explore routes: name the Service port, not the container port
CI/CD / render (push) Failing after 0s
Each explore-fe Service publishes ui:80 -> 3000, so a router that asks for 3000
is answered with `service port not found: 3000` and the host serves 404. The
five routers now name 80.

Co-authored-by: Hanzo AI <[email protected]>
2026-09-08 22:48:49 -07:00
zeekayandHanzo AI 15dda3bedf explorer: read the chain that answers, and let the browsers reach the frontends
CI/CD / render (push) Failing after 0s
The four headline cards on explore.lux.network were zeros because the indexer
was pointed at luxd-rpc, and luxd-rpc fronts a StatefulSet whose five bootstrap
addresses are DigitalOcean droplets that no longer accept a connection. That
node never names a frontier, never creates the C-chain, and answers 404 for
every path under /v1/chain/c/rpc; the indexer read nothing from it and reported
`indexed: true` over an empty database. lux-chain answers eth_chainId 0x17871
and a height, so it is what cchain reads now. public_rpc gains the /rpc the
browser needs -- the path it named 404s, so every RPC-backed control on the
page had nothing to dial.

The five explore-fe deployments had no way in. Each host resolves to Cloudflare
and Cloudflare handed the request to an ingress with no router that matched,
which is the 404 they have all been serving. Each brand now names its own hosts,
carried over from the by-hand ingress-chains.yaml minus explore.spc.network,
which does not resolve.

The explorer pod's `explore` sidecar was explore-fe-lux a second time -- same
image, same digest, same brand -- published on a Service port no router named.
The indexer keeps the job only it does.

Co-authored-by: Hanzo AI <[email protected]>
2026-09-08 22:33:11 -07:00
zeekayandHanzo AI 8ed9b670fb pars runs the explorer everyone else runs
CI/CD / render (push) Failing after 0s
It pulled ghcr.io/parsdao/explore, an image whose repository does not
resolve, and sat in ImagePullBackOff while the other four chains ran the
same luxfi/explore image branded by their own configmap. A second image for
a frontend that is already configured per chain is a second thing to keep
current, and this one was never current.

Co-authored-by: Hanzo AI <[email protected]>
2026-09-08 22:15:28 -07:00
zeekayandHanzo AI 3f7935d61a The explorer can land on the only node that can run it
CI/CD / render (push) Failing after 0s
evo carries hanzo.ai/no-ci=true:NoSchedule and is the cluster's only
amd64 node, so an amd64 workload that does not tolerate it has nowhere
to go:

  0/2 nodes are available: 1 node(s) didn't match Pod's node
  affinity/selector, 1 node(s) had untolerated taint(s)

The 175 pods already on evo predate the taint -- NoSchedule does not
evict -- so none of them tolerates it either, and nothing new can land
beside them. The taint is hand-applied and declared in no repo.

It exists to keep CI runners off the box, which is a fair thing to want.
This is not CI; it is the chain's explorer, and amd64-only. It says so
here rather than being held out by a rule aimed at something else.

Co-authored-by: Hanzo AI <[email protected]>
2026-09-08 22:13:26 -07:00
zeekayandHanzo AI e68b17ff9b the explorer frontends declare the environment they run with
CI/CD / render (push) Failing after 0s
Each of these mounts a configmap named explore-env-<chain> that was declared
nowhere: the deployments referenced it, nothing created it, and every
frontend sat in CreateContainerConfigError. The same shape as the chain
nodes, whose genesis and startup config never migrated either.

The values are the RUNTIME set only. luxfi/explore's .env.example.lux mixes
build-time and runtime variables in one file — NEXT_PUBLIC_BRAND is read by
`pnpm build`, and the branding, marketplace and homepage URLs were dropped
from the image — so feeding that file to a container fails the validator on
congruity, then on deprecation, then on unknown names.

Co-authored-by: Hanzo AI <[email protected]>
2026-09-08 21:49:45 -07:00
zeekayandHanzo AI 187b257c08 The sandbox login stops being guessable
CI/CD / render (push) Failing after 0s
/v1/bank/config answers demoLogin: true with demoEmail: [email protected]
to anyone who asks, and the deployed build falls back to a hardcoded
password when BANK_DEMO_PASSWORD is unset. That fallback is the estate's
documented org convention, so the advertised email and the password were
a pair anyone could assemble -- from the moment api.lux.financial was
routed, which was an hour ago.

The value is a Secret in the namespace, not a line in this file: the
reference belongs in git and the credential does not. It should move to
KMS with the rest.

This keeps the demo working. Turning BANK_SANDBOX off would close the
same door by removing the thing the host exists to show.

Co-authored-by: Hanzo AI <[email protected]>
2026-09-08 21:30:56 -07:00
zeekayandHanzo AI 9f6a427f18 api.lux.financial answers, so the admin console can sign in
CI/CD / render (push) Failing after 0s
The console at admin.lux.financial builds absolute URLs against this
host -- const zm="https://api.lux.financial" in its bundle, with no
same-origin path to proxy -- so it rendered and could not sign in while
nothing named the host.

app.lux.financial deliberately did not get this: dashd proxies /v1 to
this Service inside the cluster, so the dash works without the bank's
API being published. That is why it was routed first and alone, and why
this is a separate decision recorded separately.

What this publishes was read off the running pod, not assumed:
/v1/bank/health and /v1/bank/config answer 200, /v1/bank/overview 401,
and /api/collections -- the Base admin surface underneath bankd -- 404.
The framework's own console is not reachable through this route.

Co-authored-by: Hanzo AI <[email protected]>
2026-09-08 21:02:31 -07:00
zeekayandHanzo Dev d3e1c25f4c api-explore.lux.cloud and api-explore.lux.network answer the indexer
Both hosts reach this ingress and, with no router naming them, got Go's
`404 page not found` from an empty route table — which is what every
lux.exchange screen that reads an indexer has been drawing.

The indexer is `explorer`, and there is only one. luxfi/indexer builds a single
binary whose own package doc says it "serves only the /v1/indexer/* HTTP API. No
graph engine", so it cannot answer /v1/graph/cchain/amm/graphql at any version
— the only thing the exchange asks an indexer for. luxfi/explorer composes that
same daemon package with the graph engine and mounts both dispatchers. So
lux-indexer.yaml goes: it declared a second deployment for the half this one
already serves, at replicas 0, against a Service (luxd-headless) that does not
exist. Nothing named lux-indexer runs in this namespace.

One chain in the config, because one chain answers. `/v1/chain/C/rpc` on a
mainnet validator returns 0x17871; P X A B Z T D G by name are 404, so are the
four L2 blockchain ids this file carried, and so are api.pars.network,
api.zoo.ngo, api.hanzo.network and api.osage.network. Q, K and M are served and
are not EVM. A row for a chain that is not there polls a 404 forever and decodes
plain text as JSON-RPC.

The chain is reached at `lux-chain.lux-mainnet.svc`, the selector-less Service
whose endpoints are the LAN validators, declared once in deploy/lux-api — so the
public route and this process reach the chain the same way. `luxd-rpc` selects on
a label a gate writes onto luxd PODS, and the validators are not pods here.

Measured after: 20 blocks and 780 transactions ingested from an empty volume in
7s, and lux.exchange/explore draws gLUX off four queries at ~110ms each.

Addresses are read off this chain rather than inherited. native is WLUX at
0x66dbed95… (symbol() answers, 2874 bytes); the 0x4888E4a2… this file named
holds no code here. factory_v2 and factory_v3 are dropped for the same reason —
they name the one contract a subgraph trusts, and neither is deployed on this
chain, so the AMM indexer watches the settlement precompile at 0x9999 and
answers an empty venue for the contract AMM that is not there.

lux-testnet and lux-devnet still carry lux-indexer.yaml. The same reasoning
applies and their chains have not been measured.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 19:52:57 -07:00