- Create /dashboard/organization/billing page with plan comparison
- Wire up disabled "Manage Subscription" button to new billing page
- Fix analytics nav billing link to point to organization/billing
- Shows current plan, usage stats, and upgrade via Commerce checkout
- All 4 tiers displayed: Free, PAYG, Growth, Enterprise
All dashboard pages now use NEXT_PUBLIC_API_URL with localhost fallback
for local dev. Fixes tokens, volumes, storage, clusters, monitoring,
infrastructure, and usage pages for production deployment.
- 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.
- Fix Lux brand IAM URL: lux.id → iam.lux.network (matches actual deployment)
- Use getBrand().iam.url for IAM URL in HanzoLoginButton (brand-aware auth)
- Fix missing newline at EOF in unified-navigation.tsx
- Update LLM.md with Commerce billing and IAM documentation
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.
- Add pars brand config to brand.ts (persian blue + gold, cloud.pars.network)
- Add pars domain detection in getBrandKey()
- Add pars to server-side brand map in layout.tsx
- Replace lux-icon.svg wordmark with upside-down triangle (from @luxfi/logo)
- Add pars logo assets (8-pointed star icon, logo, white variant)
- Dashboard and navigation use dark-mode-aware CSS vars (bg-background,
bg-sidebar, border-border) instead of hardcoded bg-gray-50/bg-white
- isProductionMode() now recognizes 127.0.0.1 and private IPs as local
so login no longer redirects to lux.id on localhost
- Add /dashboard/infrastructure/monitoring page with node health
summary cards, CPU/memory/disk usage bars, 15s auto-refresh
- Quick login button uses [email protected] / admin credentials
- Add apiUrl/wsUrl to brand config for runtime resolution
- Auth and OAuth callback now use brand's apiUrl instead of baked env var
- Pin node:22-alpine to specific digest for supply chain security
Updated all container image references across compose, K8s manifests,
cloud deploy scripts, and tests to use the ghcr.io/hanzoai/bootnode
registry format.
The layout.tsx was missing bootnode case in brand switch,
causing it to fall through to Hanzo. Added bootnode and
changed default from Hanzo to Bootnode.
Build distinct images with NEXT_PUBLIC_BRAND baked in at build time:
- web-latest (bootnode brand for bootno.de)
- web-hanzo-latest (hanzo brand for web3.hanzo.ai)
Next.js NEXT_PUBLIC_* vars are embedded at build, not runtime.
- Split web deployment into hanzo-web3 and bootnode-web
- hanzo-web3: web3.hanzo.ai, auth via hanzo.id
- bootnode-web: bootno.de, auth via iam.bootno.de
- Updated CI to deploy both frontends
- Changed image registry to ghcr.io/bootnode/bootnode
- Updated ingress for both domains with separate TLS certs
CI pushes to ghcr.io/hanzoai/bootnode, but manifests were
referencing hanzoai/bootnode which defaults to docker.io.
This caused deployments to use stale images from docker.io.
- Add CDN-Cache-Control header (60s) for HTML pages
- Keep long cache (1 year) for immutable static assets
- Prevents Cloudflare from serving stale branded content
The hanzo-kms and hanzo-iam packages are not published to PyPI,
causing uv lock to fail. In production K8s, secrets are injected
as env vars directly by the KMS operator.
- 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
- Update layout.tsx with brand-aware metadata (title, OG, icons)
- Change default brand from bootnode to hanzo in brand.ts
- Update homepage, product pages with brand-aware text
- Replace api.bootnode.dev URLs with api.hanzo.ai
- Update llms.txt route to use brand system
- Update security, privacy pages with Hanzo branding
- Update code-demo, unified-navigation with brand logos
- Update footer status link to status.hanzo.ai
- 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
Added the following Hanzo services to compose.yml:
- IAM: Multi-tenant identity (hanzo.id, lux.id, zoo.id, pars.id)
- KMS: Secrets management and encryption
- Platform: Service orchestration and deployment
- Console: Admin dashboard with AI backend
- Console Worker: Background job processor
- Commerce: Multi-tenant e-commerce platform
- Analytics: Multi-tenant analytics platform
All services share the existing infrastructure:
- PostgreSQL for operational data
- Redis for caching and queues
- ClickHouse (datastore) for analytics
To start Hanzo services:
docker compose --profile hanzo up -d
Added IAM service to the compose stack:
- Uses ghcr.io/hanzoai/iam:latest image
- Shares PostgreSQL and Redis with other services
- Available on port 8001
- Multi-tenant support for hanzo.id, lux.id, zoo.id, pars.id
- Use profile 'hanzo' to enable: docker compose --profile hanzo up