- 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.
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.
- Remove hardcoded Secret from bootnode-deployment.yaml (conflicted with ExternalSecret)
- Fix Postgres/Redis pods to read passwords from KMS-managed bootnode-secrets
- Expand ExternalSecret from 7 to 30 secrets with UPPERCASE_UNDERSCORE keys matching Pydantic
- Enable hanzo-kms SDK as optional dependency for direct KMS access outside K8s
- Improve inject_secrets() startup logging to indicate active secrets path
- Rewrite secrets.yaml as documentation-only with flow diagram and setup guide
- Fix compose.yml Bitcoin healthcheck to use env vars instead of hardcoded password
- Replace eval() with json.loads() in usage tracker (security fix)
- Webhook verification fails-closed in production when secret missing
- Add Commerce env vars to K8s deployment (URL, API key, webhook secret)
- Expose ZAP port 9999 in Dockerfile and K8s service
- Replace Stripe env vars with Square in compose.yml
- Update privacy/terms pages: Stripe→Square via Hanzo Commerce
- Add full billing API client module to web/lib/api.ts (17 endpoints)
- Fix hardcoded localhost URLs in dashboard/analytics/organization pages
- Add production webhook rejection test (57 tests passing)
P0: config.py defined hanzo_commerce_* but billing code accessed
settings.commerce_* — causes AttributeError at runtime. Renamed fields
with AliasChoices for backward compat with HANZO_COMMERCE_* env vars.
P1: deps.py silently swallowed JWT errors (bare pass) — now logs them.
Virtual API key used fake UUID for missing projects — now raises 404.
Updated secrets.yaml to replace stale Stripe references with Commerce.
Update K8s manifests (Ingress hosts, CRD API groups, CORS origins),
ZAP schemas, pyproject.toml URLs, SDK docs import paths, e2e test
emails, and K8s annotations to use the canonical bootno.de domain.
- OAuth callback accepts redirect_uri from frontend to derive correct
IAM client_id per network (all use lux-web3 shared app)
- Token verification accepts tokens from any known IAM app audience
- Frontend sends redirect_uri in callback POST body
- Login page uses proper /login/oauth/authorize URL with client_id
- Brand configs unified to use lux-web3 IAM app for all networks
- Removed dead code (duplicate get_current_user, unreachable methods)
- IAM init data updated with cloud redirect URIs for pars/zoo/hanzo
The networks module imported get_current_user from bootnode.api.deps
where it doesn't exist — it's in bootnode.core.iam. This broke the
entire API startup (uvicorn can't import bootnode.main:app).
New /v1/networks endpoint orchestrates deploying a complete
white-label blockchain cloud portal:
- K8s deployment + service for bootnode-web with brand env vars
- Ingress with TLS + CORS for cloud.{domain} and api.cloud.{domain}
- IAM integration for SSO
- Scale and teardown endpoints
CI deploy step now restarts all cloud-web deployments (lux, pars,
zoo, hanzo) when new images are pushed.
The CORSMiddleware was initialized with only bootnode.dev origin.
Added all cloud.*.network domains and ALLOWED_ORIGINS env var
for extending origins without code changes.
Updated all container image references across compose, K8s manifests,
cloud deploy scripts, and tests to use the ghcr.io/hanzoai/bootnode
registry format.
- Link Hanzo IAM users to Commerce customers via hanzo_id
- Auto-create Commerce customer on first billing access
- New unified billing endpoints:
- GET /billing/account - unified user with IAM + Commerce data
- GET /billing/account/subscriptions - all subscriptions
- GET /billing/account/invoices - all invoices
- GET /billing/account/payment-methods - payment methods
- POST /billing/account/sync - sync IAM to Commerce
- POST /billing/account/subscribe - create subscription
- Support for hanzo.id, zoo.id, lux.id, pars.id orgs
- Add k8s configs for production deployment
- Use shared postgres/datastore in hanzo namespace
- Fix image registry to ghcr.io/hanzoai/bootnode
- Add deploy script with shared infra support
- Simplify compose.yml for local development