* Source: ~/work/lux/kms cmd/kms/main.go — Go-native, MPC-backed, ZapDB.
* Image: ghcr.io/luxfi/kms:server (built native amd64 in lux-k8s build pod;
CI was unblocked by switching from cross-org reusable workflow to a
self-contained build job and using hanzo-dev creds for GHCR write).
* Routes: /healthz + /v1/kms/* (auth/login, orgs/{org}/secrets, keys/*).
* Currently secrets-only (MPC_VAULT_ID empty). Threshold signing pending
mpcd ZAP-server registration on a dedicated port (P2P :9651 doesn't
accept ZAP client requests, only MPC-MPC handshakes).
* Coexists with the legacy ghcr.io/hanzoai/kms in `lux-kms` ns. Once
kms-operator is refactored to use luxfi/kms/pkg/client (PR pending),
KMSSecret CRDs migrate hostAPI → kms.lux-kms-go.svc.cluster.local
and the Infisical-fork is decommissioned.
* Source: ~/work/lux/kms cmd/kms/main.go — Go-native, MPC-backed, ZapDB.
* Image: ghcr.io/luxfi/kms:server (built native amd64 in lux-k8s build pod;
CI was unblocked by switching from cross-org reusable workflow to a
self-contained build job and using hanzo-dev creds for GHCR write).
* Routes: /healthz + /v1/kms/* (auth/login, orgs/{org}/secrets, keys/*).
* Currently secrets-only (MPC_VAULT_ID empty). Threshold signing pending
mpcd ZAP-server registration on a dedicated port (P2P :9651 doesn't
accept ZAP client requests, only MPC-MPC handshakes).
* Coexists with the legacy ghcr.io/hanzoai/kms in `lux-kms` ns. Once
kms-operator is refactored to use luxfi/kms/pkg/client (PR pending),
KMSSecret CRDs migrate hostAPI → kms.lux-kms-go.svc.cluster.local
and the Infisical-fork is decommissioned.
* apiVersion was wrong: kms.hanzo.ai/v1alpha1 doesn't exist in cluster.
Real CRD is secrets.lux.network/v1alpha1, owned by ghcr.io/luxfi/kms-operator.
* hostAPI added (required field) → kms.lux-kms.svc.cluster.local
(~/work/lux/kms Go-native server, MPC-backed via ~/work/lux/mpc).
* Project slug zoo-exchange (own project), env prod, path /.
No more shared hanzo-exchange/zoo subpath.
* Resource named zoo-exchange-kms-sync to match the *-kms-sync naming
convention used by analytics/billing/cloud/etc. across hanzo namespace.
* apiVersion was wrong: kms.hanzo.ai/v1alpha1 doesn't exist in cluster.
Real CRD is secrets.lux.network/v1alpha1, owned by ghcr.io/luxfi/kms-operator.
* hostAPI added (required field) → kms.lux-kms.svc.cluster.local
(~/work/lux/kms Go-native server, MPC-backed via ~/work/lux/mpc).
* Project slug zoo-exchange (own project), env prod, path /.
No more shared hanzo-exchange/zoo subpath.
* Resource named zoo-exchange-kms-sync to match the *-kms-sync naming
convention used by analytics/billing/cloud/etc. across hanzo namespace.
* Replaced init-container ConfigMap (sed URL rewrites + fetch interceptor +
CSP injection) with clean SPA wiring — secrets come from KMSSecret CRD
syncing /zoo path from hanzo-exchange KMS project to zoo-exchange-secrets
in the cluster.
* Image moves from ghcr.io/luxfi/exchange@sha256:9b97... (digest pin +
nodeAffinity hack) to ghcr.io/zooai/exchange:latest with normal pull.
* SPA_INSIGHTS_API_KEY arrives via envFrom: secretRef. SPA runtime
templates /config.json from SPA_* env at pod start; brand singleton
reads insightsApiKey at boot.
* Removed wildcard *.api.zoo.exchange Ingress + cert (no more fake
cloudflare-prefix subdomains — events go to insights.hanzo.ai directly).
* Replaced init-container ConfigMap (sed URL rewrites + fetch interceptor +
CSP injection) with clean SPA wiring — secrets come from KMSSecret CRD
syncing /zoo path from hanzo-exchange KMS project to zoo-exchange-secrets
in the cluster.
* Image moves from ghcr.io/luxfi/exchange@sha256:9b97... (digest pin +
nodeAffinity hack) to ghcr.io/zooai/exchange:latest with normal pull.
* SPA_INSIGHTS_API_KEY arrives via envFrom: secretRef. SPA runtime
templates /config.json from SPA_* env at pod start; brand singleton
reads insightsApiKey at boot.
* Removed wildcard *.api.zoo.exchange Ingress + cert (no more fake
cloudflare-prefix subdomains — events go to insights.hanzo.ai directly).
Lux-ecosystem KrakenD gateway (lux-mainnet/api-gateway-gateway) is now
documented as a shared multi-tenant backend. Any white-label app —
Zoo, Hanzo, Pars, <tenant>, third-party — points api.<their-domain>
at the same service via a 5-line Ingress + DNS A record. CORS is
wide-open (allow_origins=*) so browser SPAs from any origin work.
This commit:
- k8s/lux-mainnet/api-zoo-exchange-ingress.yaml — first WL ingress
(api.zoo.exchange → api-gateway-gateway:80, TLS via cert-manager)
- k8s/lux-mainnet/WHITE-LABEL-API.md — onboarding recipe + endpoint
list + backend topology diagram
zoo.exchange's SPA env (SPA_RPC_HOST, SPA_API_HOST, SPA_GATEWAY_HOST)
all now point at api.zoo.exchange. JS bundle was rewritten by the init
container to swap api.lux.network/* and gateway.{lux,uniswap}.org
references for api.zoo.exchange — zero third-party domains visible
in browser network tab.
Out-of-band: removed api.zoo.exchange from the conflicting
lux-ns/exchange-api Traefik IngressRoute so the standard Ingress
takes the route.
Lux-ecosystem KrakenD gateway (lux-mainnet/api-gateway-gateway) is now
documented as a shared multi-tenant backend. Any white-label app —
Zoo, Hanzo, Pars, <tenant>, third-party — points api.<their-domain>
at the same service via a 5-line Ingress + DNS A record. CORS is
wide-open (allow_origins=*) so browser SPAs from any origin work.
This commit:
- k8s/lux-mainnet/api-zoo-exchange-ingress.yaml — first WL ingress
(api.zoo.exchange → api-gateway-gateway:80, TLS via cert-manager)
- k8s/lux-mainnet/WHITE-LABEL-API.md — onboarding recipe + endpoint
list + backend topology diagram
zoo.exchange's SPA env (SPA_RPC_HOST, SPA_API_HOST, SPA_GATEWAY_HOST)
all now point at api.zoo.exchange. JS bundle was rewritten by the init
container to swap api.lux.network/* and gateway.{lux,uniswap}.org
references for api.zoo.exchange — zero third-party domains visible
in browser network tab.
Out-of-band: removed api.zoo.exchange from the conflicting
lux-ns/exchange-api Traefik IngressRoute so the standard Ingress
takes the route.
Zoo exchange moved out of lux-explorer namespace (reserved for unified
luxfi/explorer indexer+graph+explore) into its own 'zoo' namespace,
runtime switched from nginx → ghcr.io/hanzoai/spa:1.2.0.
- Init container pulls SPA bundle from pinned digest of cached
luxfi/exchange@sha256:9b9765e0…, patches index.html (Zoo title +
gateway.uniswap.org CSP), and rewrites 'gateway.lux.org' →
'gateway.uniswap.org' in all built JS/CSS/HTML (Statsig gating URL
fix — the .lux.org fork placeholder has no backing deployment).
- Main container runs hanzoai/spa with SPA_* env-var templating into
/config.json (brand, chain id, RPC/IAM/KMS/ID hosts).
- NodeAffinity to lux-nodes-vvfa0/kzit5/kzitk (cached image) pending
PAT refresh for ghcr-luxfi.
- Standard K8s Ingress + TLS via cert-manager letsencrypt.
- Old IngressRoute (lux-explorer/exchange-zoo) deleted out-of-band.
Dropping node affinity is safe once either (a) a fresh ghcr-luxfi PAT
lands in the lux-explorer ns secret, or (b) zooai/exchange:latest
finally builds successfully and we switch the init-container image.
Zoo exchange moved out of lux-explorer namespace (reserved for unified
luxfi/explorer indexer+graph+explore) into its own 'zoo' namespace,
runtime switched from nginx → ghcr.io/hanzoai/spa:1.2.0.
- Init container pulls SPA bundle from pinned digest of cached
luxfi/exchange@sha256:9b9765e0…, patches index.html (Zoo title +
gateway.uniswap.org CSP), and rewrites 'gateway.lux.org' →
'gateway.uniswap.org' in all built JS/CSS/HTML (Statsig gating URL
fix — the .lux.org fork placeholder has no backing deployment).
- Main container runs hanzoai/spa with SPA_* env-var templating into
/config.json (brand, chain id, RPC/IAM/KMS/ID hosts).
- NodeAffinity to lux-nodes-vvfa0/kzit5/kzitk (cached image) pending
PAT refresh for ghcr-luxfi.
- Standard K8s Ingress + TLS via cert-manager letsencrypt.
- Old IngressRoute (lux-explorer/exchange-zoo) deleted out-of-band.
Dropping node affinity is safe once either (a) a fresh ghcr-luxfi PAT
lands in the lux-explorer ns secret, or (b) zooai/exchange:latest
finally builds successfully and we switch the init-container image.
lux-build-linux-amd64 and lux-deploy-linux-amd64 were scaled to 0 in 6f76ace.
All caller workflows migrated to hanzo-build-linux-amd64 / hanzo-build-linux-arm64.
No remaining references in .github/workflows. Zero live consumers.
ArgoCD will reconcile and tear down the corresponding AutoscalingRunnerSet
resources after merge. lux-build-linux-arm64 remains active.
Co-authored-by: Hanzo Dev <[email protected]>
lux-build-linux-amd64 and lux-deploy-linux-amd64 were scaled to 0 in 6f76ace.
All caller workflows migrated to hanzo-build-linux-amd64 / hanzo-build-linux-arm64.
No remaining references in .github/workflows. Zero live consumers.
ArgoCD will reconcile and tear down the corresponding AutoscalingRunnerSet
resources after merge. lux-build-linux-arm64 remains active.
Co-authored-by: Hanzo AI <[email protected]>
All workflow callers across hanzo/lux/zoo/liquidity have been migrated
to the canonical hanzo ARC fleet:
- hanzo-build-linux-amd64 (DO ARC, max 30)
- hanzo-build-linux-arm64 (GKE T2A Ampere ARC, max 30)
- hanzo-deploy-linux-amd64 (DO ARC, max 20)
This scales the duplicate lux-build-linux-amd64 and lux-deploy-linux-amd64
scale sets to 0 (minRunners=0, maxRunners=0). Files kept in place so ops
can verify zero-pod state before a follow-up PR deletes them entirely.
One and only one ARC fleet. No duplicate scale sets.
Co-authored-by: Hanzo Dev <[email protected]>
All workflow callers across hanzo/lux/zoo/liquidity have been migrated
to the canonical hanzo ARC fleet:
- hanzo-build-linux-amd64 (DO ARC, max 30)
- hanzo-build-linux-arm64 (GKE T2A Ampere ARC, max 30)
- hanzo-deploy-linux-amd64 (DO ARC, max 20)
This scales the duplicate lux-build-linux-amd64 and lux-deploy-linux-amd64
scale sets to 0 (minRunners=0, maxRunners=0). Files kept in place so ops
can verify zero-pod state before a follow-up PR deletes them entirely.
One and only one ARC fleet. No duplicate scale sets.
Co-authored-by: Hanzo AI <[email protected]>
.bitcoin, .coin, .invest are not real TLDs — those ingress rules were
unreachable. Replace with bitcoin.lux.network / invest.lux.network /
coin.lux.network subdomains and add safe.lux.network.
DNS A records needed at lux.network zone (proxied or direct to
lux-k8s LB 134.199.138.27):
safe.lux.network A 134.199.138.27 (already exists, now live)
bitcoin.lux.network A 134.199.138.27 (pending)
invest.lux.network A 134.199.138.27 (pending)
coin.lux.network A 134.199.138.27 (pending)
.bitcoin, .coin, .invest are not real TLDs — those ingress rules were
unreachable. Replace with bitcoin.lux.network / invest.lux.network /
coin.lux.network subdomains and add safe.lux.network.
DNS A records needed at lux.network zone (proxied or direct to
lux-k8s LB 134.199.138.27):
safe.lux.network A 134.199.138.27 (already exists, now live)
bitcoin.lux.network A 134.199.138.27 (pending)
invest.lux.network A 134.199.138.27 (pending)
coin.lux.network A 134.199.138.27 (pending)
Fixes pod-network drops when hostNetwork ingress DaemonSet (hanzo-ingress
in lux-system) sends cross-node traffic to pod-CIDR backends in hanzo ns.
Cilium resolves source identity as remote-node for hostNetwork traffic,
which doesn't match pod-label selectors in standard NetworkPolicies.
fromEntities: [cluster, host, remote-node] covers all in-cluster sources.
Unblocks: lux.finance, lux.industries, blog.lux.network, blog.lux.network/api/search,
vote.lux.network (all were 504-ing at CF edge due to policy drops).
Fixes pod-network drops when hostNetwork ingress DaemonSet (hanzo-ingress
in lux-system) sends cross-node traffic to pod-CIDR backends in hanzo ns.
Cilium resolves source identity as remote-node for hostNetwork traffic,
which doesn't match pod-label selectors in standard NetworkPolicies.
fromEntities: [cluster, host, remote-node] covers all in-cluster sources.
Unblocks: lux.finance, lux.industries, blog.lux.network, blog.lux.network/api/search,
vote.lux.network (all were 504-ing at CF edge due to policy drops).