Commit Graph
1420 Commits
Author SHA1 Message Date
zeekay 3ee4b67877 merge: @luxfi/brand as canonical Lux brand source 2026-05-21 16:50:39 -07:00
zeekay 1c95699b99 app/bridge: read Lux brand from @luxfi/brand (single source of truth)
Replace the five hardcoded Lux strings/colors in the Lux tenant build
with reads from @luxfi/brand's brand.json:

  name           "Lux Bridge"                  -> `${shortName} Bridge`
  primaryColor   "#5b8def"                     -> brand.primaryColor (#000000)
  secondaryColor "#7a9ff5"                     -> theme.dark.accent1
  supportEmail   "[email protected]"         -> brand.supportEmail
  apiHost / docsUrl literal lux.network        -> derived from appDomain/docsDomain

Use the `@luxfi/brand/brand.json` subpath rather than the package's
main entry: the npm-published @luxfi/[email protected] omits its .d.ts shipping
artefacts, but brand.json is included and TypeScript infers full literal
types under `resolveJsonModule`. This also keeps the package as the
single source of truth — a brand block bump in @luxfi/brand propagates
here on the next install with no string copies.

Each lookup keeps a hard fallback string so the build never breaks when
@luxfi/brand omits a field in a future version. The fallbacks match the
pre-cutover hardcodes (lux.network defaults).

Tenant build verified:
  pnpm --filter @luxbridge/lux-tenant typecheck   clean
  pnpm --filter @luxbridge/lux-tenant build       clean (bundles brand.json)
  pnpm --filter @luxfi/bridge typecheck           clean (SDK unchanged)

SDK sweep clean: no hardcoded Lux brand overrides under pkg/bridge/src/app/.
The two remaining matches are:
  - pkg/bridge/src/app/styles/theme.css   header comment naming the SDK
  - pkg/bridge/src/app/lib/chains.ts:29   `name: 'Lux Network'` chain identity
    on `lux:96369` (structurally identical to `'Ethereum'` on `evm:1`).

DEADBEEF audit unchanged: 1 occurrence, gated behind `import.meta.env.DEV`
in pkg/bridge/src/app/hooks/useWallet.ts:32.
2026-05-21 16:47:21 -07:00
zeekay e6baaaffdc merge: bridge-ui vite spa manifest alignment (fix/bridge-ui-vite-spa-manifests) v1.1.2 2026-05-21 16:41:26 -07:00
zeekay 708a735d4a merge: ci build-ui + postinstall hardening (fix/build-ui-and-postinstall) 2026-05-21 16:41:26 -07:00
zeekay a1b9eca952 fix(opnet-watcher): drop ../bridge relative replace, bump luxfi/bridge to v1.1.1 2026-05-21 16:38:10 -07:00
zeekay 19aeb6a211 build: drop || true from root postinstall
The patch-hanzogui-exports.cjs script is the only supported way to
make `pnpm install && pnpm exec vite build` succeed against the broken
@hanzo/[email protected] publish. Swallowing its exit code with `|| true`
hides the only signal we have that the workaround stopped applying —
e.g. if a future pnpm release changes traversal semantics or upstream
republishes the SDK and the patcher trips on an unexpected layout, the
install would still report success and the failure would surface much
later at the vite build step with a confusing module-resolution error.

Verified `rm -rf node_modules && pnpm install --frozen-lockfile`
completes end-to-end with the script exiting 0
(`patched 240 package(s); fixed 41 source file(s)`). Red Phase 3 R2 nit.
v1.1.1
2026-05-21 16:35:19 -07:00
zeekay abb83626c9 manifests: align bridge-ui with Vite SPA (ghcr.io/hanzoai/spa, :80)
bridge-ui ships as a prebuilt Vite SPA inside ghcr.io/hanzoai/spa
(see app/bridge/Dockerfile final stage), not a Next.js dev container.
The compose + k8s manifests were still describing the old Next shape:
containerPort 3000, `npm run dev`, /app/.next volume mount, and
NEXT_PUBLIC_* env vars. None of that exists in the image anymore.

- compose.testnet.yml / compose.mainnet.yml: port 3001:80 (was 3001:3000);
  drop command + .next mount; swap NEXT_PUBLIC_* for VITE_BRIDGE_* env
  (the names app/bridge/src/bridge.config.ts reads).
- k8s/mpc-deployment.yaml: containerPort 80 (was 3000); Service
  targetPort 80 (was 3000 — broken since the static-SPA cutover); swap
  NEXT_PUBLIC_* for VITE_BRIDGE_* on the Deployment env.
- compose.yml: keep local hot-reload UX by mounting the repo root and
  running `pnpm -C app/bridge dev --host 0.0.0.0 --port 3001` against
  node:22-alpine. Dev port moves 3000 -> 3001 to match the published
  SPA convention across envs.
- scripts/start-local.sh: update printed UI URL to :3001.

compose.infra.yml and compose.local.yml don't define bridge-ui — left
untouched. scripts/launch-mpc-bridge.sh already prints :3001 and has no
Next-specific config; check-ci-status.sh only references bridge-ui as a
GHCR package name (image preserved per spec). Both verified clean.

Validated:
- docker compose -f compose.{yml,testnet,mainnet,infra,local}.yml config -q
- kubectl --dry-run=client apply -f k8s/mpc-deployment.yaml
2026-05-21 16:34:08 -07:00
zeekay a065556107 ci: build + publish bridge-ui image alongside bridge + bridge/server
Adds a third matrix entry to docker.yml so app/bridge/Dockerfile is
built and pushed to ghcr.io/luxfi/bridge-ui on every main/dev/test push
and v* tag. Multi-arch (linux/amd64 + linux/arm64) and tag policy are
inherited from the shared hanzoai/.github docker-build.yml reusable
workflow (same as the existing bridge + bridge/server entries).

The bridge-ui image is referenced by compose.yml, compose.testnet.yml,
compose.mainnet.yml, and k8s/mpc-deployment.yaml. Without this job the
image was orphaned — the Makefile build-ui target was the only producer
and no workflow invoked it.
2026-05-21 16:33:21 -07:00
zeekay 300354cb5a merge: swarm/integration → main (phase1-3 + @luxfi/logo) 2026-05-21 16:28:44 -07:00
zeekay 6b3c51aa78 app/bridge: wire @luxfi/logo as canonical Lux logo source
The Lux tenant config now imports getColorSVG() from @luxfi/logo
(https://github.com/luxfi/logo) and inlines it as a data URL on the
BrandConfig.logoUrl field. Replaces the prior env-var-only path with
a deterministic, single source of truth — the @luxfi/logo package.

Consumers can still override at deploy time via VITE_BRIDGE_LOGO_URL.

No other bridge code touches Lux branding — the SDK stays
jurisdiction-neutral.
2026-05-21 16:28:37 -07:00
zeekay aba2019111 merge: phase1 SDK config blocks (auth/kms/wallet/mpc + PQ protocol union)
# Conflicts:
#	pnpm-lock.yaml
2026-05-21 16:26:47 -07:00
zeekay a8f8c13af2 merge: phase3-r2 stack (inline UI + cleanup + Tamagui swap) 2026-05-21 16:26:18 -07:00
zeekay 59b227ec55 docs: document the react-native-web alias requirement for @luxfi/bridge consumers (red nit)
Red flagged a P1 documentation gap: downstream tenants of @luxfi/bridge
(starting with zooai/bridge) need the same react-native-web alias +
TAMAGUI_TARGET define that app/bridge/vite.config.ts uses, or Rolldown
fails to resolve react-native from Tamagui's runtime. Adding:

- pkg/bridge/README.md: new "Consuming this SDK from a Vite app" stanza
  with the canonical resolve.alias + dedupe + define block
- app/bridge/vite.config.ts: header note pointing downstream consumers
  at the README

No code changes. No new dependencies.
2026-05-21 16:18:48 -07:00
zeekay 93b0e311ce phase3-r2: swap <button> and <input> primitives onto @hanzo/gui
Mechanical primitive rotation across the inlined bridge UI:

  - 4 <button> sites -> @hanzo/gui Button
    * WalletConnect: Connect Wallet button
    * WalletConnect: Connected address pill (disconnect)
    * SwapForm: Reverse-chains button (the central ⇄)
    * SwapForm: Submit/bridge button

  - 1 <input> site -> @hanzo/gui Input
    * AssetInput: amount field (uses onChangeText, the Tamagui-native
      string handler, instead of the React onChange(e) signature)

Inline-style props (style={...}) are preserved verbatim on the new
components -- they round-trip through Tamagui's web-mode style merge.
Phase 3 R2.5 will lift those into theme tokens.

Out-of-scope per the R2 dispatch:
  - <select> (ChainSelector, AssetInput asset picker) -- stays native
  - Card / Stack / Text / Header / Footer -- still plain HTML
  - title="..." HTML tooltips dropped: Tamagui Button's stack-based
    types do not expose the DOM title attribute. aria-label is
    preserved on every site so screen-reader behavior is unchanged.

Verification:
  - cd pkg/bridge && pnpm typecheck  -> clean
  - cd app/bridge && pnpm build      -> clean (750 modules)
  - Bundle size (app/bridge index chunk): 25.99 kB -> 106.83 kB raw
    (gzip 9.01 -> 38.86 kB). Delta is the Tamagui runtime; expected
    and within the dispatch's "~150 KB acceptable" budget.
2026-05-21 16:10:00 -07:00
zeekay 85dbb8b345 phase3-r2: wire @hanzo/gui as a runtime dependency
The SDK now ships with @hanzo/gui + @hanzogui/{core,helpers,constants,
themes,animate,animate-presence,button,input} as direct dependencies
(moved out of the optional peerDependencies block). Phase 3 R2 starts
swapping native primitives onto Tamagui-based @hanzo/gui components,
so consumers no longer have to install those packages themselves.

Three plumbing changes make this actually bundle in a consumer:

  1. scripts/patch-hanzogui-exports.cjs (vendored from lux/exchange):
     the published @hanzo/[email protected] + @hanzogui/*@7.0.0 packages ship
     without a populated dist/, so their package.json main/module/exports
     point at folders that do not exist. The patch rewrites those entries
     to point at the included src/ at install time. Root postinstall hook
     runs it deterministically on every pnpm install.

  2. app/bridge/vite.config.ts: alias react-native -> react-native-web,
     dedupe react/react-dom/react-native-web, set TAMAGUI_TARGET=web and
     __DEV__=false. Minimum viable Tamagui wiring (mirrors the wiring
     lux/exchange ships in a much larger config).

  3. app/bridge/package.json: add react-native-web@^0.19.0 dependency
     so the alias above resolves.

Result: pnpm install in a fresh checkout produces a working build with
zero manual setup. `pnpm build` in app/bridge succeeds.
2026-05-21 16:09:47 -07:00
zeekay 486b201bb0 pkg/bridge/app/hooks/useWallet: gate stub wallet behind import.meta.env.DEV (red review) 2026-05-21 16:00:46 -07:00
zeekay d8b1645c57 phase2-r2: regenerate pnpm-lock after workspace collapse
`pnpm install` after deleting app/bridge3 and renaming app/lux-bridge →
app/bridge prunes the dead workspace entries and refreshes hashes.

Verifies the new shape end-to-end:
  pnpm install        — clean
  pnpm -C app/bridge typecheck — clean
  pnpm -C app/bridge build     — produces dist/ (vite SPA, 435ms,
                                  pkg/bridge inlined components linked)
2026-05-21 15:17:59 -07:00
zeekay 52c437b00e phase2-r2: scrub bridge3 / @luxbridge/app / lux-bridge references
Sweep through configs, docs, and ignore files after the structural
collapse in the previous commit. Updates fall into three buckets:

1) Restore the Dockerfile for app/bridge/
   - app/bridge/Dockerfile: new file, Vite SPA → ghcr.io/hanzoai/spa,
     same shape as the pre-collapse legacy Dockerfile, build context
     is repo root so @luxfi/bridge (workspace:*) resolves.
   - cmd/bridge/Dockerfile: switch UI-build stage to the workspace
     build context so the new app/bridge (which depends on the
     sibling pkg/bridge package) actually installs.
   - Makefile build-ui target: drop the per-app build context for
     the same reason — context must be repo root.

2) Update workspace docs to the new layout
   - README.md: rename @luxbridge/app row → @luxbridge/lux-tenant,
     port 3000 → 3001 (the slim tenant's vite config uses 3001).
   - docs/LLM.md: drop the bridge3 row, rename app/bridge row to
     @luxbridge/lux-tenant, update dev port.
   - docs/{BRIDGE-STATUS,LOCAL-SETUP,CI-CD-DOCKER-IMAGES}.md:
     `docker build … ./app/bridge` → `… -f app/bridge/Dockerfile .`
     so docs reflect the workspace-rooted build context.
   - .github/workflows/publish.yml: drop @luxbridge/app and
     @luxbridge/app-v3 from the private-packages comment.

3) Delete AI-slop status reports + test harness
   - CI_STATUS_REPORT.md, DEPLOYMENT_STATUS.md, WORKFLOW_AUDIT.md,
     WORKFLOWS_SUMMARY.md — stale and referenced bridge3.
   - test-bridge-ui.js — top-level Puppeteer/Playwright probe of the
     deleted legacy UI; not a workspace test.
   - .dockerignore: drop the test-bridge-ui.js entry now that the
     file no longer exists.

Out of scope (untouched): pkg/bridge/src/{Bridge,config,types,mount}
and pkg/bridge/src/app/ — Phase 3 R2 is working there. The
`@luxbridge/app` mentions in those files are historical comments
explaining the prior workspace cycle, not live references.
2026-05-21 15:15:37 -07:00
zeekay 95a19813f4 phase2-r2: collapse to canonical app/bridge tenant
Phase 1.5 inlined the bridge UI into pkg/bridge/src/app/ and added a
slim consumer at app/lux-bridge/. With the @luxbridge/app workspace
cycle severed there is no longer any reason to keep two tenant
directories or the legacy 400-file UI under app/bridge/.

This commit picks Path A:
  - delete legacy app/bridge/ (406-file @luxbridge/app, now lives in
    pkg/bridge/src/app/ as 16-file inlined SDK UI)
  - delete unused app/bridge3/ (Remix @luxbridge/app-v3, never shipped)
  - move app/lux-bridge/ → app/bridge/ (canonical tenant dir matches
    bridge.lux.network DNS; "lux-bridge" was a temporary worktree name
    needed while the legacy dir still existed)
  - delete root Dockerfile.bridge-ui (referenced deleted app/bridge3
    paths and the old Next.js standalone output; superseded by
    app/bridge/Dockerfile which builds the Vite SPA into ghcr.io/hanzoai/spa)

After this commit:
  - one and only one bridge tenant: app/bridge/ (slim, consumes @luxfi/bridge)
  - SDK: pkg/bridge/ (publishes @luxfi/bridge with inlined UI)
  - zero references to @luxbridge/app or @luxbridge/app-v3
  - zero references to app/bridge3 or app/lux-bridge
2026-05-21 15:10:50 -07:00
zeekay 8aaa483452 feat(app/lux-bridge): slim SDK consumer for bridge.lux.network
The new @luxbridge/lux-tenant package is a thin Vite SPA that imports
@luxfi/bridge + @luxfi/brand and renders <Bridge config={...} />. It
is the deployable artefact behind bridge.lux.network and the
smoke-test surface that proves the SDK bundle isn't a stub:

  $ cd app/lux-bridge && pnpm build
  dist/index.html                   0.71 kB
  dist/assets/index-yIcXWMx5.css    0.89 kB
  dist/assets/index-CN78T0a_.js    25.96 kB   ← real React, not 91 bytes
  dist/assets/client-BZEUzgg-.js  134.47 kB

The 25.96 KB chunk contains real `createRoot`, `mountBridge`,
`BridgeApp`, `SwapForm`, `ChainSelector`, `AssetInput`,
`WalletConnect`, `TransferStatus`, `Header`, `useSwap`, `useWallet`,
`useTransfers` — verified via sourcemap inspection.

This package coexists with the legacy heavy `app/bridge` tree (65
components, full @luxbridge/app on `main`). Once Phase 2's branch
lands, the heavy tree is retired and `app/lux-bridge` (or whatever
Phase 2 renamed it to) becomes the canonical Lux-branded tenant.

Brand config (Lux-specific only):
  - name:          'Lux Bridge'
  - primaryColor:  #5b8def
  - secondaryColor: #7a9ff5
  - supportEmail:  [email protected]
  - docsUrl:       https://docs.lux.network/bridge

The brand block is the only Lux-specific surface in this package;
everything else is the jurisdiction-neutral @luxfi/bridge SDK.
2026-05-21 15:04:01 -07:00
zeekay d07b70d192 feat(pkg/bridge): sever @luxbridge/app workspace cycle (v1.0.1)
Bridge.tsx no longer lazy-imports @luxbridge/app — it imports the
inlined `BridgeApp` from `./app/` directly. The workspace dep on
`@luxbridge/app` is removed from pkg/bridge/package.json, and the
type shim `src/luxbridge-app.d.ts` plus the tsconfig path alias are
gone with it.

Phase 2 produced a 91-byte JS bundle because its slimmed `app/bridge`
package re-exported `App: FC = () => null` to satisfy this lazy
import. With the cycle severed, that workaround is unnecessary and
the SDK's bundle is what a tenant build actually consumes — see the
new app/lux-bridge consumer (next commit) emitting a 25.96 KB chunk
with real `BridgeApp`, `createRoot`, and all UI strings.

package.json deltas:
  - version: 1.0.0 -> 1.0.1
  - dependencies: drop @luxbridge/app + @luxbridge/settings (both
    workspace-only)
  - peerDependencies: add @hanzo/gui ^7 + the @hanzogui/* v7
    primitive set as OPTIONAL peers. Phase 3 R2 will swap the
    inline-styled primitives in src/app/components/ for these; until
    then they're optional so `pnpm add @luxfi/bridge` doesn't drag
    in 30 unused packages.

tsconfig.json: drop the `@luxbridge/app` path mapping.

README.md: replace the workspace-internals diagram with the actual
inline layout under src/app/.
2026-05-21 15:03:38 -07:00
zeekay 9b12b124eb feat(pkg/bridge): inline bridge UI under src/app/
Phase 1.5 — sever the @luxbridge/app workspace cycle that Phase 2
exposed as a P0 blank-page bug. The SDK now ships its own bridge UI
inline; there is no runtime dependency on any sibling tenant package.

Layout:

  pkg/bridge/src/app/
    BridgeApp.tsx           top-level <BridgeApp/>
    components/             Header, SwapForm, ChainSelector, AssetInput,
                            WalletConnect, TransferStatus, Card
    hooks/                  useWallet, useSwap, useTransfers
    lib/                    chains, assets, format
    styles/theme.css        minimal CSS variables (brand-* hooks)

Features covered:
  - Header with brand block + wallet connect
  - Swap form: From/To chain selector, asset input + select, quote
    panel (rate / fee / ETA), reverse button, submit
  - Wallet connect button + connected-address pill
  - Transfer status feed with MPC-phase rendering (pending → signing
    → broadcasting → completed)

Design constraints:
  - PQ-safe: no classical-crypto assumptions anywhere. The MPC signer
    layer (wired in Phase 3 R3) plugs Ringtail-lattice + ECDSA-CMP
    hybrid; nothing here defeats post-quantum.
  - Leaderless / permissionless: chain + asset registries are static
    client-side data, not bound to any central authority. Quotes are
    deterministic display mocks; the real backend (also leaderless)
    arrives in Phase 3 R3.
  - Phase 3 R2 swap target: components are seam-isolated so swapping
    inline-styled `<div>` / native `<select>` for @hanzo/gui v7
    primitives is mechanical. The shape of BridgeApp.tsx stays stable.

Stats: 15 new files, 1336 LoC. Renders identical output to the
former @luxbridge/app App component for the four MVP features.
2026-05-21 15:03:16 -07:00
zeekay 3d0da53ddd docs+manifest: align protocol references with new union (NIT from red review) 2026-05-21 14:57:19 -07:00
zeekay e03574dc57 pkg/{bridge,threshold}: protocol union — drop lss+ringtail, add pulsar/corona/magnetar/doerner (PQ-safe leaderless)
Align the SDK Protocol union with the canonical thresholdd protocol set
(cggmp21, frost, pulsar, corona, bls, doerner) plus magnetar from the
study/ research variant. lss and ringtail are removed entirely — lss
never had a leaderless-safe round and ringtail folded into the pulsar/
corona lattice family.

Classical: cggmp21 (ECDSA secp256k1), frost (EdDSA ed25519), bls, doerner (2-of-2).
Post-quantum: pulsar (MLWE), corona (RLWE), magnetar (research variant).

- pkg/bridge/src/types.ts: BridgeMPCConfig.protocol widened with JSDoc
- pkg/threshold/src/types.ts: Protocol type widened with matching JSDoc
- pkg/threshold/src/client.test.ts: 'lss' callsites → 'cggmp21'
- pkg/bridge/src/__tests__/config.test.ts: parametric it.each test
  walking all 7 protocols, confirms setConfig({mpc:{protocol}}) accepts each

Verified: pnpm typecheck + pnpm test green on pkg/bridge (14/14) and
pkg/threshold (8/8).
2026-05-21 14:47:20 -07:00
zeekay 09ca480783 pkg/bridge: widen MPC protocol union, add setConfig precedence guard (red review)
- BridgeMPCConfig.protocol now mirrors @luxfi/threshold Protocol union:
  'lss' | 'cggmp21' | 'frost' | 'bls' | 'ringtail'
- setConfig throws on conflicting clientId / iamOrg between top-level
  legacy fields and auth.{clientId,orgSlug} so misconfigured tenants
  fail loudly at boot rather than silently picking one source.
- vitest wired into pkg/bridge with 7 tests covering precedence guard.
2026-05-21 14:26:02 -07:00
zeekay 0b4e889b91 feat(pkg/bridge): add auth/kms/wallet/mpc config blocks to BridgeConfig
Extend the @luxfi/bridge SDK contract so tenant apps wire identical
auth/KMS/wallet/MPC config across `<Exchange>` and `<Bridge>`. The new
blocks intentionally mirror the canonical `<Exchange>` prop shape from
@luxfi/exchange — same field names, same semantics.

New optional types in pkg/bridge/src/types.ts:
- BridgeAuthConfig  (provider, issuer, clientId, idHost?, orgSlug?)
- BridgeKMSConfig   (url)
- BridgeWalletConfig (walletConnectProjectId?, defaultChainId?, supportedChainIds?)
- BridgeMPCConfig   (publicUrl, privateUrl?, protocol?)

BridgeConfig gains optional `auth`, `kms`, `wallet`, `mpc` fields.
Legacy `clientId` / `iamOrg` flagged @deprecated but preserved — no
existing consumer breaks.

Bridge.tsx + mount.ts comments updated to note the full config (incl.
new blocks) is seeded synchronously via setConfig before children read.
No runtime code change required — setConfig already stores the whole
object, so new fields automatically flow through to getConfig consumers.

README updated with a complete tenant example wiring all four new
blocks, plus per-block field tables.

Typecheck: clean (tsc --noEmit).
2026-05-21 14:17:45 -07:00
zeekay 25b02b3884 revert app/lux-shim — superseded by SDK-consumer pattern
Tenants now consume @luxfi/bridge as an SDK (see zooai/bridge for the
canonical pattern). No per-tenant overlay image, no brand.json runtime
fetch. Each tenant's repo is a thin React app that imports the SDK +
their brand package and renders <Bridge config={...} />.

Lux-side brand lives in @luxfi/brand and is consumed at build time by
the Lux tenant app (currently app/bridge3, soon a peer @luxfi/bridge
consumer tracking the same pattern as @zooai/bridge).
2026-05-21 14:07:57 -07:00
zeekay 778ff148c3 feat(pkg/bridge): add @luxfi/bridge SDK + publish workflow
Rationalize the bridge workspace around one canonical SDK entry:

  - @luxfi/bridge        (NEW)  public SDK consumers import
  - @luxbridge/*          private workspace internals
  - @luxfi/{core,threshold,utila} generic Lux building-block libs

@luxfi/bridge re-exports mountBridge(), <Bridge />, BridgeConfig, and
BrandConfig. The runtime lazy-imports @luxbridge/app as the actual UI
implementation. Mirrors the mountExchange() pattern from
@partner/exchange — declarative config-in, brand metadata applied
to document, React tree rendered into #bridge-root.

Workspace housekeeping:
  - pkg/settings: 0.1.0 -> 1.0.0, marked private
  - pkg/ui (ui-automation), app/server, app/bridge3: marked private
  - app/explorer: 0.1.0 -> 1.0.0
  - root bridge package: 1.0.0 -> 1.1.0
  - app/bridge: add main/types/exports so the SDK can dynamic-import the App component

Publish workflow at .github/workflows/publish.yml fires on v* tag push,
runs pnpm publish -r --access public --no-git-checks. pnpm skips
private packages automatically. Public packages: @luxfi/bridge, @luxfi/core,
@luxfi/threshold, @luxfi/utila.
v1.1.0
2026-05-21 14:02:03 -07:00
zeekay fe99553df7 app/lux-shim: brand-pinned overlay image for bridge.lux.network
Mirrors zoo/bridge/app/ pattern — a thin Docker overlay on top of the
bridge3 base image that bakes the Lux brand into the deployable
artefact. The bridge3 app already defaults to Lux branding via
brand.ts; this shim makes the brand explicit at the image layer so
bridge.lux.network and bridge.zoo.network have identical structure
and one-file-only differences.

Produces ghcr.io/luxfi/bridge:latest. New tenant white labels follow
the same five-minute drop-in pattern: copy app/lux-shim/ to
<org>/bridge/app/, swap public/brand.json, update Dockerfile labels.
2026-05-21 13:58:46 -07:00
zeekay fdecd91e6a deploy: wire LP-4200 PQCrypto + 0x04xx DEX/bridge precompile constants
Adds a canonical precompile address constants module the UI can consume
when constructing chain-native bridge / PQ verification calls. Mirrors
the source-of-truth address scheme from ~/work/lux/precompile/dex/types.go
(0x0400-0x044F) and ~/work/lux/precompile/{mldsa,mlkem,slhdsa,pulsar,
p3q,corona,magnetar,hqc}/contract.go (LP-4200 unified PQCrypto block at
0x012201-0x012208). hasNativePrecompiles() guards the seven Lux chain
IDs that expose the native verifier set; non-Lux chains continue to use
the user-facing teleporter contracts from settings.ts unchanged.

LUX_STRICT_PQ_BRIDGE profile (v1.0.7) consumes the same address space
on the node side; the UI now has a matching constant set.
v1.0.9
2026-05-19 11:31:03 -07:00
zeekayandGitHub c09c6eac62 chore: bump Go toolchain to 1.26.3 (#383)
Pin Go version to 1.26.3 across go.mod, CI workflows, and Dockerfiles
for canonical alignment with the rest of the luxfi/* stack.
v1.0.8
2026-05-16 16:42:28 -07:00
zeekayandGitHub 071a7f21b0 Merge pull request #382 from luxfi/licensing/canonical-pointer
docs: add LICENSING.md pointer to canonical Lux IP strategy
2026-05-15 16:40:59 -07:00
zeekay 0f9bec4f21 docs: add LICENSING.md pointing at canonical Lux IP strategy
Single LICENSING.md file referencing the canonical three-tier IP and
licensing strategy at github.com/luxfi/.github/blob/main/profile/README.md.

LICENSE file is unchanged; this only adds a navigational pointer.
2026-05-15 16:40:28 -07:00
zeekay ab9ce8c6d8 go.mod: bump go directive to 1.26.3 (security advisory) 2026-05-12 20:54:59 -07:00
zeekay 96215e2f7d bridge: enforce LUX_STRICT_PQ_BRIDGE profile
Adds BridgeProfile + LuxStrictPQBridgeProfile (Pulsar-M-65 on both sides,
STARK_FRI_SHA3_PQ proofs, ML-DSA-87 admin, ML-DSA-65 multisig pause).
Forbids ECDSA admin, BLS aggregate, KZG commitments, Groth16 wrappers,
and pairing precompiles in strict mode.

post_quantum_end_to_end label exposed via RPC + block-explorer metadata.

Classical-compat bridges remain available under BridgeClassicalCompat
profile but are explicitly labeled non-E2E-PQ.

Integration sites:
- bridge/profile.go is the bridge-package audit gate (mirrors consensus
  type, owns the bridge_classical_compat_total counter).
- opnet-watcher/signer.go: SignRaw, SignTransaction, signEthMessage now
  consult profile.RefuseClassicalAdmin before any ecrecover / EIP-191 /
  secp256k1 sign — strict-PQ refuses, classical-compat increments
  the metric.
- cmd/bridge/api.go: exposes bridge_getProfile JSON-RPC, GET
  /v1/bridge/profile, and /metrics (Prometheus, including
  bridge_classical_compat_total{primitive=...}).
- --profile flag (BRIDGE_PROFILE env) selects strict-pq | classical-compat
  on both cmd/bridge and opnet-watcher.

Patch-bump.
v1.0.7
2026-05-10 20:07:49 -07:00
zeekay 6cec4cd00a merge ci/canonical-docker-build: unified Go binary + brand scrub + canonical docker-build 2026-05-06 09:15:21 -07:00
zeekay a47f58bc54 feat(bridge): unified Go binary — embedded SPA + native networks/tokens/limits, proxied swap/quote/rate
Mirrors the luxfi/explorer pattern: cmd/bridge/main.go embeds the SPA
build via go:embed and exposes /v1/bridge/* on a single port. Read paths
(networks, tokens, exchanges, limits) are answered natively from a YAML
config — no Postgres. MPC-heavy paths (quote, rate, swaps, explorer)
reverse-proxy to the legacy Node backend until the native port lands.

Image: cmd/bridge/Dockerfile produces ~25 MB distroless.
Config: cmd/bridge/networks.example.yaml.
Migration target: Hanzo Base (SQLite) + luxfi/mpc direct calls.
2026-05-05 21:24:03 -07:00
zeekay c5aa121e31 bridge: remove Liquidity branding cross-contamination
Drop the Liquidity / Liquidity Testnet network entries (chain IDs
8675309/8675310 with rpc.*.redacted.com nodes and LQDTY/USDL/BTCL/ETHL
currency lists) from the Lux teleport bridge UI's mainnet and sandbox
network constants. Liquidity is an external white-label deployment
that can register itself at runtime; it must not be hardcoded into
the OSS Lux bridge UI.
2026-05-05 19:22:17 -07:00
zeekay 0027ee5a27 bridge: scrub Avalabs IP brand refs 2026-05-05 16:22:42 -07:00
zeekayandGitHub dfc8e1a021 ci: migrate to canonical docker-build reusable (#381)
- Add workflow-sanity.yml to enforce canonical CI contract
- Consolidate docker.yml to matrix-build bridge + bridge/server images
- Delete docker-publish.yml (duplicate of docker.yml with stale lux-build runner)
- Strip bespoke docker buildx from server.yml (now handled by docker.yml matrix)

Refs: hanzoai/.github canonical Docker CI contract.
2026-04-23 19:18:06 -07:00
zeekay 403e333149 ci: migrate to canonical docker-build reusable
- Add workflow-sanity.yml to enforce canonical CI contract
- Consolidate docker.yml to matrix-build bridge + bridge/server images
- Delete docker-publish.yml (duplicate of docker.yml with stale lux-build runner)
- Strip bespoke docker buildx from server.yml (now handled by docker.yml matrix)

Refs: hanzoai/.github canonical Docker CI contract.
2026-04-23 19:17:14 -07:00
zeekay fbd08c4e1f rewrite(bridge): Next.js → Vite 8 SPA + hanzoai/spa
- Convert app/bridge/ from Next.js 14 app-router to Vite 8 SPA.
- New entry: index.html → src/main.tsx → src/App.tsx (wouter router).
- src/pages/{HomePage,AuthPage,CampaignsPage,CampaignDetailPage,SalonPage,
  SwapPage,TeleporterSwapPage,UtilaSwapPage,TransactionsPage,NotFoundPage}.tsx.
- src/shims/next-{link,image,navigation,dynamic,headers,server,font/google,mdx}
  + sentry-nextjs map Next.js APIs onto wouter + plain DOM so existing
  components compile unchanged. Aliased in vite.config.ts.
- Dockerfile (root + app/bridge): FROM node:22-alpine AS build → vite build →
  FROM ghcr.io/hanzoai/spa COPY dist /public.
- Delete app-router dir, next.config.js, next-env.d.ts, middleware.ts,
  sentry.*.ts. Keep app/explorer/ and docs/ untouched (still Next.js).

Tenant route resolution:
  src/app/api/tenant/route.ts was a 17-line edge handler that called
  lib/tenant.fetchTenant(). fetchTenant() only reads env vars and fetches a
  public IAM /api/get-organization endpoint. No secrets. Moved to client:
  lib/tenant.ts now reads import.meta.env.VITE_* and is called directly from
  main.tsx + TenantProvider. No sidecar needed.

TODO:
  - `pnpm install` in CI to pick up wouter, vite, @vitejs/plugin-react,
    @sentry/browser (added to package.json).
  - Pre-existing viem/teleport tsc errors remain (ignored as before via esbuild).
  - Storybook config still references @storybook/nextjs — rewire to
    @storybook/react-vite separately.
2026-04-19 00:05:10 -07:00
zeekay cc67d9eb05 fix: remove local replace, use published luxfi/crypto v1.17.55 2026-04-12 14:07:43 -07:00
zeekay ffbabc0552 ci: enable dual-arch (amd64+arm64) — AWS Graviton runners live 2026-04-09 23:17:50 -07:00
zeekay 1e0f173645 ci: amd64-only until ARM runners online 2026-04-09 22:43:07 -07:00
zeekay 007dc5051f ci: fix workflow job refs, use default shared runners 2026-04-09 22:37:10 -07:00
zeekay e8b7d04fa8 ci: add dev/test branches and v* tag triggers 2026-04-09 22:21:37 -07:00
zeekay 23456e17d3 ci: migrate to shared docker-build workflow (native multi-arch, semver) 2026-04-09 21:58:27 -07:00
zeekay a523dfd646 feat: all 19 chain plugins fully implemented — zero stubs
Every chain plugin now has real PollDeposits + QueryBacking:

EVM (generic):     eth_getLogs + eth_call — 15 chains
OP_NET:            Bitcoin L1 via JSON-RPC block scanning
Solana:            Anchor event parsing from program logs
TON:               BOC cell parsing + VarUInteger16 amounts
Lux:               Warp-aware EVM plugin (eth_getLogs)
Sui:               suix_queryEvents + MoveEventType filter
NEAR:              query call_function view + block/chunk fallback
Cosmos:            Tendermint tx_search + abci_query
XRPL:              account_tx + Payment/DestinationTag parsing
Stellar:           Horizon REST operations + memo recipient
Cardano:           Blockfrost API + lovelace balance
Algorand:          Algod API + application global state
ICP:               HTTP gateway JSON query interface
Polkadot:          Substrate chain_getBlock + SCALE decoding
Aptos:             REST event API + BridgeStore resource
StarkNet:          starknet_getEvents + felt conversion
Stacks:            Stacks API + Clarity value parsing
Fuel:              GraphQL receipts + LOG_DATA parsing
Tezos:             Tezos RPC + Michelson parameter parsing

97 tests pass. No external dependencies added.
2026-04-06 23:56:25 -07:00
zeekay b153c5d6a2 fix: seen map pruning to prevent unbounded memory growth
Add pruneSeen() that caps nonce tracking at 10000 entries per chain.
Called on every checkpoint save. Since nonces are monotonic, only
recent nonces need tracking — old ones are definitionally confirmed.

2 new tests verify pruning behavior.
2026-04-06 23:44:16 -07:00