Strips etnaTimestamp from both top-level networkUpgrades/upgradeConfig
and the embedded cChainGenesis config blob in all three envs
(mainnet, testnet, devnet). Required for compatibility with
luxfi/evm v0.19.0 which enforces DisallowUnknownFields and has
renamed Etna -> Quasar.
Per universe-wide policy, hanzo workloads ship on DOKS only. DO App Platform
was decommissioned February 2026 — all hanzo-apps/hanzo-platform/operator
specs here have been superseded by infra/k8s/. Removing the stale specs to
keep the only-one-way invariant.
Switch from gcr.io/distroless/static-debian12:nonroot to FROM scratch.
CA certs, tzdata, /etc/passwd and /etc/group (nonroot uid/gid 65532)
are copied from the build stage.
Adds a Go subsystem alongside the existing Python FastAPI service so
bootnode can fold into `superbase` per HIP-0106. The Python service in
`api/bootnode/` stays untouched.
What landed:
- `schema/bootnode.zap` — public typed surface (chains, RPC, tokens,
NFTs, transfers, smart wallets, ERC-4337, gas, webhooks, fleets,
nodes, usage). No `.capnp` anywhere — ZAP only, per brand policy.
- `zap/gen/` — hand-rolled Go bindings that match what `zapc generate`
emits, so `go build` works without zapc installed locally.
- `api/mount.go` — the HIP-0106 contract:
func Mount(r chi.Router, deps Deps) error
mounts every FastAPI-parity route group through `api/handlers/`.
- `api/deps.go` — cross-subsystem ZAP client interfaces (IAM, KMS,
Base, O11y, Commerce). No business logic, no hard imports — keeps
the Bootnode module independent of sibling subsystems until they
ship their typed clients.
- `api/handlers/` — 149 chi routes mounted (Python has 150). Each
handler body is a 501 stub with a `TODO(bootnode-port)` pointing at
the Python file + symbol to port.
- `api/middleware/` — IAM-backed auth, OTEL-friendly telemetry,
per-org rate limit (stub).
- `api/store/` — per-tenant SQLite access via `deps.Base.Open(orgID,
"bootnode")` per HIP-0302.
- `api/web3/` — chain registry + RPC pool surface (production version
prefers luxfi/* over upstream go-ethereum).
- `cmd/bootnode/main.go` — standalone shim; same `api.Mount` superbase
calls in production.
- `docs/PYTHON_TO_GO_PORT.md` — endpoint-by-endpoint port map.
Build: `go build ./...` and `go vet ./...` clean. Standalone shim
smokes 200 on /health, /ready, /v1/chains; 401 on auth-required
endpoints with no JWT; 501 on every TODO route.
Out of scope (not in this commit):
- Handler bodies (Phase 2 — porting in RPC → tokens → NFTs → ...
priority order).
- superbase wiring (lands when the superbase repo opens its main).
- Python service removal (stays until handlers reach prod parity).
Required for hanzoai/.github/.github/workflows/docker-build.yml@main —
without it the workflow_call dies as startup_failure with no jobs
dispatched. Caller permissions are a CEILING.
Replaces all ghcr.io/hanzoai/<svc>:latest pins with the latest published
semver tag for each service. Per CLAUDE.md auto-bump policy: mutable
branch tags (:latest, :main, :dev) are deprecated for cluster pins —
only immutable semver permitted.
Bulk update across services with published v* tags. Services without a
published semver remain on :latest until their release pipeline cuts a
v* tag.
generateMetadata() already used the host header, but RootLayout itself
read only process.env.BRAND with a hard-coded "bootnode" fallback. That
made the body theme/SSR brand drift from the metadata brand on per-host
deploys. Make RootLayout async and reuse the host detection so both
paths agree.
GHCR 403s on first-push package creation for ghcr.io/hanzoai/bootnode-web.
Push web build to the existing bootnode package with tag-suffix=-web,
api with tag-suffix=-api, so they coexist without colliding tags.
Deployment image becomes:
ghcr.io/hanzoai/bootnode:vX.Y.Z-web
ghcr.io/hanzoai/bootnode:sha-XXXXXXX-web
Update K8s deployments via kubectl set image after CI succeeds.
The zoo brand config in web/lib/brand.ts references /logo/zoo-icon.svg,
/logo/zoo-logo.svg, /logo/zoo-logo-white.svg but only the references
existed — the files were missing, producing 404s on web3.zoo.ngo and
zoo.cloud. Added the canonical Zoo CMYK Venn mark from
zoo.industries/public/zoo-logo.svg.
- web/lib/brand.ts: detect zoo.cloud as zoo brand (alongside zoo.ngo, zoo.network)
- infra/k8s/ingress.yaml: add zoo.cloud + www.zoo.cloud as additional hosts on
bootnode-zoo-ingress (TLS SAN via cert-manager, rules → bootnode-web-zoo:3001)
Makes zoo.cloud serve the same Bootnode platform as web3.zoo.ngo with Zoo brand.
Migrate every ingress resource from nginx annotations to
traefik.ingress.kubernetes.io for hanzoai/ingress controller.
Update network policies to match hanzo-ingress pod selector.
Update operator config to use className: hanzo.
NEXT_PUBLIC_BRAND gets baked at build time by Next.js, always resolving
to the Dockerfile default ("bootnode"). Use headers() + Host-based
detection in generateMetadata() so cloud.lux.network shows "Lux Cloud"
at request time, not "Bootnode".
Root cause: ghcr-secret was expired/missing, causing ImagePullBackOff
on all web portal pods. Now auto-refreshes using GITHUB_TOKEN on each
deploy. Also cleans up stale pending pods from previous failed rollouts.
Instead of storing DIGITALOCEAN_ACCESS_TOKEN and cluster names as
GitHub Secrets, authenticate to KMS at deploy time and fetch them
from /deploy path. Falls back to GitHub Secrets if KMS is unavailable.
Matches the pattern used by hanzo/app and other Hanzo services:
only KMS_CLIENT_ID + KMS_CLIENT_SECRET stored in GitHub.
The build-and-push and deploy jobs were duplicated in ci.yml with missing
REGISTRY env vars, causing Docker login failures. docker-release.yml is
the canonical deploy pipeline (triggers on CI workflow_run completion).
- Add Explorer product page with branded block explorer deployment, contract
verification, Etherscan-compatible API, and multi-chain support
- Add MPC product page with deep Lux MPC integration: CGGMP21 (ECDSA),
FROST (EdDSA), LSS resharing, 15+ chain support, threshold signing API
- Update landing page with 6-product grid (Node, Data, Wallets, Explorer,
MPC, Rollups) and 8 API cards including Explorer API and MPC Signing
- Update navbar and command menu with Explorer and MPC products
- Add Lux fleet management dashboard, observability, and services pages
- Add AI chat component and unified navigation with org switcher
- Add Kubernetes operator (Rust) for multi-chain node lifecycle management
- Add Lux Helm charts with genesis configs for devnet/testnet/mainnet
- Add docker-release.yml CI/CD pipeline for automated DOKS deployment
- Add monitoring, network policies, web deployments, and ingress updates
- Refactor API: fleet management, billing tracker, observability endpoints
- Update brand config, API client, and infrastructure manifests
The K8s DATABASE_URL env var uses postgresql:// which makes
create_async_engine try to load psycopg2 (sync driver). Add
_ensure_async_dsn() to convert postgresql:// and postgres:// to
postgresql+asyncpg:// at engine creation time. asyncpg is already
in dependencies.
Add BOOTNODE_GHCR_PAT secret-based login to push API and web images
to the canonical ghcr.io/bootnode/bootnode registry in addition to
ghcr.io/hanzoai/bootnode. Also add provenance=false/sbom=false to web
build to avoid attestation timeouts on linux/amd64.
capnp.AsyncIoStream.create_server() must be called from within an active
KJ event loop context. Wrap the entire serve lifecycle in a background
asyncio Task that runs under `async with capnp.kj_loop()`, fixing the
startup error: "The KJ event-loop is not running on this thread".
The server now signals readiness via `_running=True` after bind and
the caller polls for up to 1 s before raising if startup fails.
uv sync resolves ALL extras including hanzo (which depends on
hanzo-kms, not published to PyPI) even with --no-extra flag.
Switch to uv pip install -e ".[dev]" which only resolves the
specified extras.
CI was failing because `uv sync` installs all extras including hanzo-kms
which isn't on PyPI. Switch to `uv sync --extra dev` for test jobs.
Add bootnode API deployment manifest for the hanzo namespace (separate
from the bootnode namespace deployment).