Zoo had exactly one working OAuth client (zoo-cloud) and no declaration of it anywhere. This ports the Lux shape into this repo: the brand-neutral mechanism stays in hanzoai/iam (internal/provision), Zoo owns its DATA here, and `make iam-provision` is the only supported way that data reaches the IdP. ISSUER. id.zoo.network serves iss=https://zoolabs.id — host and issuer really do disagree, and it is resolved in favour of zoolabs.id: IAM_ISSUER_MAP already maps all three Zoo hosts to it, discovery agrees from either host, every sibling brand's issuer is its <brand>.id apex (hanzo.id / lux.id / pars.id) with id.<brand>.network as the alias, and zoo.id has no DNS at all so it cannot be the issuer. The remaining defect is the DISCOVERY DOCUMENT (OIDC Discovery §4.3 wants issuer == fetch prefix), which is a frontend/ingress fix, not a data one. Reasoning is in the file header, not just here. Five clients, each declared only on evidence measured against the live surface: zoo-cloud, zoo-wallet, zoo-dao, zoo-explore, zoo-id. Hosts that carry no OAuth wiring, hosts served by shared Hanzo backends, and hosts with no DNS are listed too, so each omission is a recorded decision. Two defects fixed rather than described: cert. The upsert copies req.Cert verbatim on CREATE, so an omitted cert means an EMPTY cert, and a client with no cert cannot mint an id_token — the login dies AFTER a successful code exchange. Four Zoo clients were in exactly that state. Every app now names cert-zoo (convention cert-<org>: lux-cloud has cert-lux, hanzo-cloud has cert-hanzo); for zoo-cloud it is a no-op. cloud.zoo.network is no longer declared. It has an ingress but NO DNS record at 1.1.1.1 or 8.8.8.8, so no browser can reach it; a redirect URI for a host that cannot exist is the drift this document exists to prevent. Lux keeps cloud.lux.network because that host does resolve. Image pin moved forward to sha-f9813f6: sha-4bec5ef predates the `cert` field and the strict parser rejects the document outright. f9813f6 is a strict descendant of the public-client fixes and of 4b0f4e93, and is the newest sha- tag in GHCR that resolves to a known commit. PROVEN, not asserted: - converge run twice; the five records are byte-identical apart from updatedAt, and no client secret was issued (all five stay public/PKCE) - real login as [email protected] -> authorization code -> PKCE token exchange with NO client secret, on all five clients - id_token minted for each: kid=cert-zoo, iss=https://zoolabs.id, aud=<the client>, and the signature verifies against the published JWKS - the dropped redirect now correctly 400s: invalid redirect_uri Co-authored-by: Hanzo Dev <[email protected]>
88 lines
4.1 KiB
Makefile
88 lines
4.1 KiB
Makefile
# Zoo Universe — thin wrapper over the lux CLI.
|
|
#
|
|
# All per-env parameters (networkID, ports, dataDir, genesis path) live
|
|
# in chain.yaml. This Makefile carries only the brand name and the env
|
|
# list. Verbs delegate to the lux CLI which resolves `<brand>/<env>` to
|
|
# a RuntimeProfile via the brand registry (~/work/<brand>/universe).
|
|
#
|
|
# Equivalent invocations (Make is optional):
|
|
# make up env=devnet ≡ lux up zoo/devnet
|
|
# make cycle env=mainnet ≡ lux cycle zoo/mainnet
|
|
|
|
SHELL := /bin/bash
|
|
.DEFAULT_GOAL := help
|
|
|
|
BRAND := zoo
|
|
ENVS := localnet devnet testnet mainnet
|
|
LUX := lux
|
|
|
|
# Single parametric verbs: `make up env=devnet`, etc.
|
|
.PHONY: up down snap cycle ps ctx
|
|
up : ; @$(LUX) up $(BRAND)/$(env)
|
|
down : ; @$(LUX) down $(BRAND)/$(env)
|
|
snap : ; @$(LUX) snap $(BRAND)/$(env)
|
|
cycle : ; @$(LUX) cycle $(BRAND)/$(env)
|
|
ps : ; @$(LUX) ps
|
|
ctx : ; @$(LUX) ctx
|
|
|
|
# Fanout: cycle every env in sequence.
|
|
.PHONY: cycle-all
|
|
cycle-all: ; @for e in $(ENVS); do $(LUX) cycle $(BRAND)/$$e || exit 1; done
|
|
|
|
# DOKS cluster overlays (separate concern: K8s, not chain lifecycle).
|
|
KCTX := do-sfo3-zoo-k8s
|
|
.PHONY: k8s-apply k8s-pods
|
|
k8s-apply: ; @kubectl --context $(KCTX) apply -k k8s/zoo-$(env)/
|
|
k8s-pods : ; @kubectl --context $(KCTX) -n zoo-$(env) get pods -o wide
|
|
|
|
# IAM — Zoo's identity app graph (deterministic, from this repo only).
|
|
#
|
|
# infra/k8s/iam/provision.yaml is the ONE source of truth for Zoo's OAuth
|
|
# clients. These targets are the ONLY supported way to change them — never
|
|
# hand-edit an application in a console, or the next converge silently reverts
|
|
# it and the drift is invisible until a login breaks.
|
|
#
|
|
# IAM_CTX/IAM_NS are hanzo-k8s/hanzo, NOT the Zoo cluster: the IdP that answers
|
|
# zoolabs.id runs there, and so does the service token it authenticates with.
|
|
IAM_DOC := infra/k8s/iam/provision.yaml
|
|
IAM_CTX := do-sfo3-hanzo-k8s
|
|
IAM_NS := hanzo
|
|
|
|
.PHONY: iam-provision iam-provision-plan iam-provision-logs
|
|
|
|
iam-provision-plan: ## Derive Zoo's OAuth clients and print them; writes nothing
|
|
@kubectl --context $(IAM_CTX) -n $(IAM_NS) run zoo-iam-plan-$$$$ --rm -i --restart=Never \
|
|
--image=$$(awk -F'image: ' '/image: ghcr.io/{print $$2; exit}' infra/k8s/iam/provision-job.yaml) \
|
|
--overrides='{"spec":{"imagePullSecrets":[{"name":"ghcr-secret"}]}}' \
|
|
--command -- /iam2 provision --config=/dev/stdin --url=https://zoolabs.id --dry-run < $(IAM_DOC)
|
|
|
|
iam-provision: ## Converge zoolabs.id onto provision.yaml (idempotent; never rotates a secret)
|
|
@kubectl --context $(IAM_CTX) -n $(IAM_NS) create configmap zoo-iam-provision \
|
|
--from-file=provision.yaml=$(IAM_DOC) --dry-run=client -o yaml | \
|
|
kubectl --context $(IAM_CTX) apply -f -
|
|
@kubectl --context $(IAM_CTX) -n $(IAM_NS) delete job zoo-iam-provision --ignore-not-found
|
|
@kubectl --context $(IAM_CTX) apply -f infra/k8s/iam/provision-job.yaml
|
|
@kubectl --context $(IAM_CTX) -n $(IAM_NS) wait --for=condition=complete job/zoo-iam-provision --timeout=180s \
|
|
|| { echo "provision did not complete — logs:"; $(MAKE) iam-provision-logs; exit 1; }
|
|
@$(MAKE) iam-provision-logs
|
|
|
|
iam-provision-logs: ## Show what the last converge actually did
|
|
@kubectl --context $(IAM_CTX) -n $(IAM_NS) logs job/zoo-iam-provision --tail=100 2>/dev/null || true
|
|
|
|
.PHONY: help
|
|
help: ## Show this help
|
|
@printf " Chain verbs (env=<localnet|devnet|testnet|mainnet>)\n"
|
|
@printf " make up env=devnet boot zoo/<env>\n"
|
|
@printf " make down env=devnet stop zoo/<env>\n"
|
|
@printf " make snap env=devnet snapshot zoo/<env>\n"
|
|
@printf " make cycle env=devnet boot → deploy → stop → snap\n"
|
|
@printf " make cycle-all cycle every env\n"
|
|
@printf " make ps / make ctx registry inspection\n"
|
|
@printf "\n K8s (DOKS $(KCTX))\n"
|
|
@printf " make k8s-apply env=mainnet apply k8s/zoo-<env>/ overlay\n"
|
|
@printf " make k8s-pods env=mainnet list pods in namespace\n"
|
|
@printf "\n IAM (zoolabs.id, via $(IAM_CTX)/$(IAM_NS))\n"
|
|
@printf " make iam-provision-plan derive OAuth clients, write nothing\n"
|
|
@printf " make iam-provision converge zoolabs.id onto $(IAM_DOC)\n"
|
|
@printf " make iam-provision-logs what the last converge did\n"
|