26 Commits
Author SHA1 Message Date
zeekayandGitHub 76b6f5bf61 Web3/Bootnode: converge on @hanzo/iam (HIP-0111) — SPA PKCE FE + JWKS backend (#8)
* feat(web3): restore canonical @hanzo/iam SPA PKCE auth (HIP-0111)

The brand-neutral refactor regressed login to a hand-rolled OAuth authorize
URL (no PKCE, wrong path `${iamUrl}/oauth/authorize`) plus a backend
code-exchange POST to /v1/auth/oauth/callback — a route api-go does not
expose. Both break IAM login: the hand-rolled URL hits a path IAM serves
its 200 SPA catch-all for (silent breakage), and the callback 404s.

Restore the one canonical way per HIP-0111:
- lib/iam.ts: @hanzo/iam/browser IAM client, white-labelled by the active
  brand (serverUrl + clientId), PKCE S256, endpoints resolved via OIDC
  discovery. No hand-rolled authorize URL, no genericOAuth, no /api/auth.
- login: getIam().signinRedirect() in production (SDK owns PKCE + state).
- callback: getIam().handleCallback() does the PKCE token exchange
  client-side; the IAM access token becomes the session bearer.
- brand default: bootnode IAM is id.bootno.de / bootnode-platform (was
  hanzo.id / bootnode-web — wrong issuer + unregistered client).
- package.json: add @hanzo/iam ^0.11.0 (used but missing from deps).
- public/config.example.json: in-repo reference for the per-brand catalog
  (registered clientId per host) so the deploy provisions real clients.

Build + typecheck green.

* feat(api): validate IAM tokens via JWKS in production (HIP-0111)

The api-go backend only had an HS256 verifier (shared JWT_SECRET). After the
FE completes IAM PKCE it presents an IAM-issued RS256 access token, which the
HMAC verifier rejects (SigningMethodHMAC check) — IAM login fails at the API.

Converge on the canonical IAM validation path:
- iam/jwks.go: JWKSVerifier validates RS256/ES256 tokens against the issuer's
  JWKS, resolved via OIDC discovery ({issuer}/.well-known/openid-configuration
  -> jwks_uri). Keys cached, refreshed on unknown kid (rate-limited). stdlib
  only — no new dependency. Issuer is checked (WithIssuer).
- main.go: production selects JWKSVerifier(IAM_URL); dev keeps HS256 for the
  built-in email/password flow. One way per environment.
- config: ValidateSecrets() fails fast if production boots with placeholder/
  empty JWT_SECRET or API_KEY_SALT — secrets MUST come from KMS, never the
  in-code default. IsProduction() gates it.
- iam.go: drop redundant exp/iat int64 fields from Claims — duplicate json
  tags shadowed jwt.RegisteredClaims and silently disabled expiry validation
  (latent bug in the HS path too; now exp is enforced).

Tests: JWKS valid/expired/wrong-issuer/unknown-kid/HS-rejected + config
secret guard. go build + go vet + go test all green.

* harden(api): enforce JWT audience when IAM_CLIENT_ID is set

Adversarial review follow-up: without an aud check, a token minted for ANY
client of the same IAM issuer would be accepted. NewJWKS now takes the
expected audience (the deployment's IAM_CLIENT_ID); when set, tokens whose
aud does not match are rejected (token minted for a different client is no
longer accepted). Empty audience preserves issuer+signature-only behavior.

Test: matching aud passes, mismatched aud rejected.

* fix(web): sync lockfile for @hanzo/iam + remove invalid pnpm-workspace.yaml

test-web failed at `pnpm install --frozen-lockfile` for two reasons:

1. web/pnpm-workspace.yaml carried only `allowBuilds: {sharp: true}` — not a
   valid pnpm 9 field, and a workspace file without a `packages:` key makes
   pnpm 9 abort with ERR_PNPM_INVALID_WORKSPACE_CONFIGURATION (pre-existing
   on main). web/ is a single package, not a workspace, so the file is removed
   and sharp's build allowance moved to package.json `pnpm.onlyBuiltDependencies`.

2. This branch added `@hanzo/iam@^0.11.0` to package.json but never regenerated
   pnpm-lock.yaml, so --frozen-lockfile rejected the out-of-date lock.

Regenerated the lockfile (pnpm 9.15.9) — it now pins @hanzo/[email protected].0. Verified
locally: `pnpm install --frozen-lockfile` is clean and `pnpm run build`
(next build) compiles all routes incl. the refactored /login + /auth/callback.

---------

Co-authored-by: zeekay <[email protected]>
2026-06-25 15:13:17 -07:00
25e5943454 web: decomplect brand into runtime white-label config (mirror @hanzo/id) (#5)
* fix(web): use real Casdoor client zoo-console for Zoo brand IAM

The zoo brand preset used clientId "zoo-app-client-id", which is not a
registered Casdoor application — Casdoor's get-app-login returns
"Invalid client_id" for it, so login from zoo.cloud / web3.zoo.ngo via
zoolabs.id never completed.

Switch to "zoo-console" (org "zoo"), the actual registered app whose
redirectUris already include https://zoo.cloud/* and
https://zoolabs.id/callback, so the OAuth round-trip resolves with no
IAM-side changes required.

* web: static-export build for lux.cloud (Lux Cloud) Cloudflare Pages deploy

Deploy the web3 console as lux.cloud (Lux brand). Convert from SSR
(output: standalone) to static export so it serves as static assets on
Cloudflare Pages with no edge/Node runtime.

- next.config.ts: output "export" + images.unoptimized; drop headers()/
  redirects() (unsupported in export) — moved to public/_headers and
  public/_redirects for Pages.
- app/layout.tsx: bake brand from NEXT_PUBLIC_BRAND/BRAND; remove
  force-dynamic + headers() host detection (client still auto-detects brand
  from window.location.hostname via lib/brand.ts).
- app/api/health, app/llms.txt: mark route handlers force-static.
- Remove app/dashboard/api/keys route handler (backend proxy unsupported in
  export; the dashboard talks to brand.apiUrl directly).
- nodes/[id]: split into a server page.tsx (generateStaticParams) + client
  node-detail-client.tsx so the dynamic segment is export-compatible.
- unified-navigation.tsx: fix API Keys link to the real /dashboard/api-keys
  page (was pointing at the removed route handler).
- lib/brand.ts: point lux IAM clientId at the real Casdoor app "lux-cloud"
  (clientId lux-app-client-id does not exist in IAM).

Built with NEXT_PUBLIC_BRAND=lux, IAM lux.id / client lux-cloud; deployed to
CF Pages project lux-cloud, custom domain lux.cloud.

* web: decomplect brand into runtime white-label config

Remove the hardcoded 5-brand catalog from web/lib/brand.ts; resolve the
active brand at runtime by hostname from an external catalog
(window.__BRAND_CATALOG__ / /config.json), mirroring the @hanzo/id SPA.
Ship one neutral built-in bootnode fallback. Add BrandProvider that loads
the per-deploy catalog client-side after hydration.

---------

Co-authored-by: Antje Worring <[email protected]>

Co-authored-by: hanzo-dev <[email protected]>

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-17 23:45:10 -07:00
8fd3094e07 fix(brand): pars twitter handle + npm scope -> parsdao (parsnetwork is the stale name) (#4)
Co-authored-by: hanzo-dev <[email protected]>

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-16 23:43:03 -07:00
a7aa34604d fix(brand): pars skillsOrg parsnetwork -> parsdao (#3)
The skills GitHub org for pars is parsdao (DAO org, matching the luxfi/zooai/hanzoai
pattern); parsnetwork is not a tracked GitHub org.

Co-authored-by: hanzo-dev <[email protected]>

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-16 23:29:20 -07:00
5d3136b904 Lux/Zoo Cloud: static-export build + Zoo brand IAM clientId (⚠️ SSR→export config change) (#2)
* web: static-export build + Zoo/Lux brand IAM clientId fixes

Two source-only changes for the Lux/Zoo Cloud console (web/), with no
committed build output.

next.config.ts (SSR -> static export):
- output "standalone" -> "export" + images.unoptimized for Cloudflare Pages.
- Drop headers()/redirects() (unsupported in export); moved to public/_headers
  and public/_redirects for Pages. Keep poweredByHeader: false.

Static-export compatibility (no SSR/server runtime):
- layout.tsx: bake brand from NEXT_PUBLIC_BRAND/BRAND; drop force-dynamic +
  headers() host detection (client still auto-detects brand from
  window.location.hostname via lib/brand.ts).
- app/api/health, app/llms.txt: mark route handlers force-static.
- Remove app/dashboard/api/keys route handler (backend proxy unsupported in
  export; dashboard talks to brand.apiUrl directly).
- nodes/[id]: split into server page.tsx (generateStaticParams) + client
  node-detail-client.tsx so the dynamic segment is export-compatible.
- unified-navigation.tsx: point API Keys link at the real /dashboard/api-keys
  page (the removed route handler is gone).

IAM clientId fixes (real Casdoor apps):
- lux: "lux-app-client-id" -> "lux-cloud".
- zoo: "zoo-app-client-id" -> "zoo-console" (the old value is not a registered
  Casdoor client and returns "Invalid client_id", breaking zoo.cloud login).

* web: restore skillsOrg field on BrandConfig (fixes broken export)

The /agents page references brand.skillsOrg at 4 sites, but the field was
dropped from BrandConfig during the consolidate-bootnode merge (it had been
added in 3ef7773). This broke `next build` (output: export) on this branch
AND on main. Restores the field + each brand's GitHub skills org, exactly as
originally introduced.

---------

Co-authored-by: Antje Worring <[email protected]>

Co-authored-by: Hanzo Dev <[email protected]>
2026-06-16 23:26:25 -07:00
zeekay 1a534203ca chore(repo): merge bootnode-org/main back into the Hanzo-side work
These two repos share root commit 8999f3c3 ("Initial commit") but
diverged long ago — hanzoai/bootnode evolved the recent stack
(api-go, brand package, etc.) while bootnode-org/main retained the
mainline 2026 history (175 commits we don't have).

Brand-leak fix: this work belongs in github.com/bootnode/bootnode,
not github.com/hanzoai/bootnode. Per the no-cross-brand-leak policy,
merge both histories together and push the result back to
bootnode/bootnode as the canonical home.

After this lands:
- bootnode/bootnode is the canonical repo
- hanzoai/bootnode gets archived with a redirect notice
- @bootnode-io/brand npm package's `repository.url` already points at
  bootnode/bootnode (set in the earlier package.json scaffold)

# Conflicts:
#	.github/workflows/ci.yml
#	api/bootnode/api/__init__.py
#	api/bootnode/api/billing/__init__.py
#	api/bootnode/config.py
#	api/bootnode/core/billing/__init__.py
#	api/bootnode/db/models.py
#	api/bootnode/main.py
#	api/tests/test_billing.py
#	web/app/dashboard/infrastructure/page.tsx
#	web/app/dashboard/organization/billing/page.tsx
#	web/app/dashboard/organization/page.tsx
#	web/app/dashboard/page.tsx
#	web/app/layout.tsx
#	web/components/navbar.tsx
#	web/components/unified-navigation.tsx
#	web/lib/brand.ts
#	web/public/logo/zoo-icon.svg
#	web/public/logo/zoo-logo-white.svg
#	web/public/logo/zoo-logo.svg
#	web/tsconfig.tsbuildinfo
2026-05-19 10:23:43 -07:00
zeekay 1d316ce4e6 fix(brand): remove hardcoded Bootnode leaks (terms, navbar, ai-chat, region-data, wallets sdk sample) + zoo IAM → zoolabs.id
- web/lib/brand.ts: zoo iam.url + iam.domain → zoolabs.id (zoo.id is NXDOMAIN)
- web/components/navbar.tsx: brand-aware `npm i {sdk}` snippet
- web/components/ai-chat.tsx: brand-namespaced localStorage keys
- web/components/lux/region-data.ts: brand-namespaced localStorage keys
- web/app/products/wallets/page.tsx: brand-aware SDK class + package in sample
- web/app/terms/page.tsx: BOOTNODE → {brand.name.toUpperCase()} in legal text
- web/lib/sdk-package.ts: shared brand→pkg/client map (single source of truth)
2026-04-30 00:24:49 -07:00
zeekay efb0d61c10 feat(brand): route zoo.cloud through bootnode-web-zoo
- 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.
2026-04-29 15:37:15 -07:00
zeekay 0aa9c4e346 feat: add Explorer + MPC product pages, fleet management, operator, Helm charts, and CI/CD
- 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
2026-03-12 14:48:40 -07:00
zeekay 3ef7773718 feat: add /agents page and skillsOrg brand support
- New /agents marketing page for AI agent crypto integration
- Added skillsOrg field to BrandConfig for per-brand skills repos
- Added Agents link to navbar (desktop + mobile)
- Server-side brand detection via Host header in layout
2026-02-26 14:25:14 -08:00
zeekay 8edcaa614f fix: production billing hardening + Stripe→Commerce migration
- 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)
2026-02-12 11:22:03 -08:00
zeekay 32900a48a2 fix: brand IAM URLs and auth provider detection
- 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
2026-02-12 10:21:27 -08:00
zeekay bcc94c2fcb fix: multi-network OAuth login for all cloud portals
- 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
2026-02-11 18:44:57 -08:00
zeekay 9001bad2e2 Add pars brand and fix lux triangle icon
- 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)
2026-02-11 10:03:20 -08:00
zeekay 05a14c1f6b Merge remote-tracking branch 'hanzo/main'
# Conflicts:
#	api/bootnode/api/__init__.py
#	api/bootnode/api/billing/__init__.py
#	api/bootnode/core/billing/unified.py
#	infra/cloud/deploy.sh
#	infra/compose.yml
#	infra/k8s/api-deployment.yaml
#	infra/k8s/bootnode-deployment.yaml
#	infra/k8s/bootnode-operator.yaml
#	infra/k8s/hanzo-web3-deployment.yaml
#	infra/k8s/indexer-deployment.yaml
#	web/app/auth/callback/page.tsx
#	web/app/dashboard/infrastructure/nodes/page.tsx
#	web/app/dashboard/layout.tsx
#	web/app/login/page.tsx
#	web/components/unified-navigation.tsx
#	web/lib/auth.tsx
#	web/lib/brand.ts
#	web/public/logo/lux-icon.svg
#	web/tsconfig.tsbuildinfo
2026-02-10 20:51:48 -08:00
zeekay bf6459f5b0 feat: brand-aware IAM auth, centralized API helpers, real chain icons, developer workbench
- Fix OAuth login to use per-brand IAM endpoints (lux.id, hanzo.id, zoo.id, iam.bootno.de)
- Correct Casdoor client IDs to match init_data.json
- Add NEXT_PUBLIC_IAM_* env var overrides for K8s chart values
- Centralize getApiUrl() and getAuthHeaders() in lib/api.ts
- Replace emoji chain icons with real PNG logos from Lux exchange
- Add developer workbench component to dashboard layout
- Add network monitoring, billing, and infrastructure pages
2026-02-10 18:14:49 -08:00
zeekay 8999f3c369 fix: dark theme, local auth redirect, and monitoring page
- 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
2026-02-10 14:56:14 -08:00
zeekay fb1e5d96c5 feat: add Lux validator fleet management system
Full-stack fleet lifecycle management for Lux blockchain validators
deployed via Helm to DOKS clusters.

Backend (Python/FastAPI):
- HelmDeployer: async helm/kubectl CLI wrapper with temp file cleanup,
  per-release locking, and command injection protection
- LuxFleetManager: fleet CRUD, scale, rolling restart, node health
  probes via luxd RPC (health + C-chain block height)
- Fleet API: authenticated REST endpoints (ApiKeyDep) with RFC 1123
  input validation, kubeconfig error sanitization
- Pydantic models: 3 networks (mainnet/testnet/devnet), fleet status
  enums, helm values translation
- 110 unit tests (0.30s, all passing)

Frontend (TypeScript/Next.js):
- Fleet dashboard: cluster selector, stats banner, fleet cards with
  scale/restart/destroy operations, node status table, create dialog
- Interactive SVG world map: zero-dep Mercator projection with DOKS
  region markers, pulsing animations, P2P mesh lines, click-to-zoom
- DOKS region data: 11 regions with coordinates and API client
- Dark theme throughout
2026-02-10 13:40:28 -08:00
zeekay 6f2f8443ec fix: cloud.lux.network uses lux.id for IAM, not hanzo.id 2026-02-10 09:28:16 -08:00
zeekay f69a016d7c fix: runtime API URL resolution and pin Docker base image
- 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
2026-02-09 20:48:43 -08:00
zeekay 19415865d5 feat: white-label branding with Cmd+K, ecosystem footer, and auth fix
- Add runtime brand detection (single Docker image for all brands)
- Add Cmd+K command palette with brand-specific ecosystem links
- Add brand-specific footer ecosystem column with external links
- Fix login page React hook violation (useBrand called after return)
- Use brand IAM URL for auth redirect (all brands → hanzo.id)
- Add Lux Cloud brand logos
- Unify CI to build single universal web image
2026-02-09 20:05:27 -08:00
zeekay bb3c6906f3 fix: redirect /login to hanzo.id in production
Instead of showing a login page with multiple identity providers,
redirect directly to hanzo.id for a cleaner authentication flow.
2026-02-04 23:09:42 -08:00
zeekay d939c6b81f chore: update bootnode domain to bootno.de
- Change bootnode brand domain from bootnode.dev to bootno.de
- Update status URL and domain detection
2026-02-04 11:37:43 -08:00
zeekay 42f2dbbe06 fix: update branding to Hanzo for production deployment
- 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
2026-02-03 22:34:09 -08:00
zeekay d55d0b03cb feat: comprehensive bootnode platform updates
- Add brand assets and logos
- Add KMS integration for secure key management
- Add infrastructure configs (cloud providers, monitoring)
- Add indexer service with documentation
- Update K8s deployments and ingress
- Enhance dashboard pages (analytics, assets, infrastructure)
- Update auth and API components
- Add .gitignore for embedded repos
2026-02-03 12:48:01 -08:00
zeekay 73a3d23053 feat: production deployment with shared Hanzo infrastructure
- 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
2026-02-02 16:39:52 -08:00