zoo.exchange/config.json shipped "iamHost":"https://iam.zoo.network" to every browser. That host has no ingress, no Traefik router and no IAM_ISSUER_MAP entry anywhere; its DNS A record pointed at the lux-k8s LB, which answered the handshake with CN=INGRESS DEFAULT CERT. So every IAM call from the Zoo Exchange SPA — mainnet and testnet — died before the first byte of HTTP. A client written against a route that never existed. zoolabs.id is Zoo's identity origin and already serves both halves: the login SPA at / and the IAM API at /v1/iam, /oauth, /.well-known (routers zoolabs-id + zoolabs-id-iam-api in the hanzoai/ingress file provider). Its discovery doc reports issuer=https://zoolabs.id with a reachable 9-key JWKS, so fetching discovery from that origin is self-consistent — which is what a strict OIDC client checks. SPA_ID_HOST was already zoolabs.id. There is no iam.<brand> host in the design. iam.hanzo.ai is the one legacy IAM host, kept because the shared Google/GitHub OAuth clients register exactly one callback against it; every brand otherwise reaches IAM through its own id origin. iam.zoo.network / iam.pars.network are being retired to NXDOMAIN, and the orphaned hanzo/iam-multi Ingress that claimed them is deleted. Co-authored-by: Hanzo Dev <[email protected]>
70 lines
2.6 KiB
YAML
70 lines
2.6 KiB
YAML
# exchange.zoo-test.network — Zoo testnet exchange (hanzoai/spa @zooai/exchange).
|
|
#
|
|
# Deployed into the existing `zoo` namespace (reuses ghcr-zoo pull secret and
|
|
# the KMS-synced zoo-exchange-secrets). Points at the LIVE zoo testnet C-Chain
|
|
# (chainId 200201 at api.zoo-test.network). Mirrors zoo-mainnet but with the
|
|
# testnet chain + RPC host.
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: zoo-exchange-testnet
|
|
labels: { app: zoo-exchange-testnet, brand: zoo, env: testnet }
|
|
spec:
|
|
replicas: 2
|
|
selector:
|
|
matchLabels: { app: zoo-exchange-testnet }
|
|
strategy:
|
|
type: RollingUpdate
|
|
rollingUpdate: { maxSurge: 1, maxUnavailable: 0 }
|
|
template:
|
|
metadata:
|
|
labels: { app: zoo-exchange-testnet, brand: zoo, env: testnet }
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: ghcr-zoo
|
|
- name: ghcr-secret
|
|
containers:
|
|
- name: spa
|
|
image: ghcr.io/zooai/exchange:latest
|
|
imagePullPolicy: Always
|
|
ports:
|
|
- { containerPort: 3000, name: http }
|
|
envFrom:
|
|
- secretRef: { name: zoo-exchange-secrets }
|
|
env:
|
|
- { name: PORT, value: "3000" }
|
|
- { name: ROOT, value: /public }
|
|
- { name: SPA_BRAND_NAME, value: "Zoo Exchange (Testnet)" }
|
|
- { name: SPA_DEFAULT_CHAIN, value: "200201" }
|
|
- { name: SPA_RPC_HOST, value: "https://api.zoo-test.network" }
|
|
- { name: SPA_API_HOST, value: "https://api.zoo-test.network" }
|
|
- { name: SPA_GATEWAY_HOST, value: "https://api.zoo-test.network" }
|
|
# zoolabs.id, not iam.zoo.network — see the zoo-mainnet overlay for why
|
|
# (iam.zoo.network never had a router; IAM calls died at the handshake).
|
|
- { name: SPA_IAM_HOST, value: "https://zoolabs.id" }
|
|
- { name: SPA_ID_HOST, value: "https://zoolabs.id" }
|
|
- { name: SPA_KMS_HOST, value: "https://kms.zoo.network" }
|
|
- { name: SPA_INSIGHTS_HOST, value: "https://insights.hanzo.ai" }
|
|
readinessProbe:
|
|
httpGet: { path: /health, port: http }
|
|
initialDelaySeconds: 2
|
|
periodSeconds: 5
|
|
livenessProbe:
|
|
httpGet: { path: /health, port: http }
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 10
|
|
resources:
|
|
requests: { cpu: "50m", memory: "64Mi" }
|
|
limits: { cpu: "500m", memory: "256Mi" }
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: zoo-exchange-testnet
|
|
labels: { app: zoo-exchange-testnet, brand: zoo, env: testnet }
|
|
spec:
|
|
type: ClusterIP
|
|
selector: { app: zoo-exchange-testnet }
|
|
ports:
|
|
- { name: http, port: 3000, targetPort: http, protocol: TCP }
|