Caught on a second pass: grep -I treats these as binary and skipped them, so the
first sweep reported clean while they still named a host that no longer resolves.
Squash of the local main lineage onto the canonical origin/main. Net tree only
(62 files): stale docs pages removed, tenant config + tests updated, minor Go
fixes, refreshed opnet-watcher build. No third-party white-label branding in
code or history.
Co-authored-by: Hanzo Dev <[email protected]>
* docs: fold loose docs/*.md into Nextra content/docs/ tree (issue #391)
The four MPC-migration .md files plus BRIDGE-STATUS / LOCAL-SETUP /
DEPLOYMENT / CI-CD-DOCKER-IMAGES were already deleted in 2b9f899 (v1.1.12).
The remaining loose docs at docs/ root (INTEGRATIONS, LUX-ID-INTEGRATION,
operator-runbook, operator-deploy-phase-1-4) were still current but lived
outside the Nextra page tree, so the site only ever served Home + Architecture.
Move them into docs/content/docs/*.mdx so the Nextra build can surface them:
docs/INTEGRATIONS.md -> docs/content/docs/integrations.mdx
docs/LUX-ID-INTEGRATION.md -> docs/content/docs/lux-id-integration.mdx
docs/operator-runbook.md -> docs/content/docs/operator-runbook.mdx
docs/operator-deploy-phase-1-4.md -> docs/content/docs/operator-deploy.mdx
docs/LLM.md stays at docs/ root because it's the symlink target for
AGENTS.md (and any future CLAUDE.md / GEMINI.md), per the .gitignore.
Content of the moved files is unchanged in this commit.
* docs: wire content/docs/* into Nextra pages, refresh _meta + index (issue #391)
Add Nextra page wrappers for each moved doc so the site sidebar surfaces the
full set:
docs/pages/integrations.mdx -> imports content/docs/integrations.mdx
docs/pages/lux-id-integration.mdx -> imports content/docs/lux-id-integration.mdx
docs/pages/operator-runbook.mdx -> imports content/docs/operator-runbook.mdx
docs/pages/operator-deploy.mdx -> imports content/docs/operator-deploy.mdx
Refresh docs/pages/_meta.json to list the new pages in display order:
Home -> Architecture -> Integrations -> Operator Runbook -> Deploy Guide
-> Lux ID -> (External) LLM Knowledge Base, GitHub.
Refresh docs/pages/index.mdx:
- replace the legacy "make up && make start-mpc-nodes" quickstart (predates
the unified Go binary) with the docker run pattern for ghcr.io/luxfi/bridge.
- point SDK consumers at pkg/bridge README + mountBridge.
- call out the post-quantum-safe protocol options (pulsar, corona, magnetar)
alongside the classical cggmp21/doerner/frost/bls set.
- link docs/LLM.md as the canonical AI/onboarding source of truth.
Build verified: pnpm install && pnpm build prerenders 8 static pages
(index, docs, integrations, lux-id-integration, operator-runbook,
operator-deploy, plus _app and 404).
* docs: update README/LLM.md/REQUIREMENTS pointers for the new layout (issue #391)
The loose docs/*.md set at docs/ root was folded into docs/content/docs/*.mdx
in the previous two commits. Update the three places that still point at the
old paths or describe the old layout:
- README.md: drop the direct link to docs/LUX-ID-INTEGRATION.md; point
readers at the Nextra site (`pnpm --filter @luxfi/bridge-docs build`)
and call out the new content/docs/ + pages/ split.
- docs/LLM.md: refresh "Key Documentation Files" to list every
content/docs/*.mdx page and explain why docs/LLM.md stays at root.
- REQUIREMENTS.md: update the §4 tree comment and the §7 row 1.5 status
note so they reflect the v1.1.13 fold.
No file content moves in this commit — pointers only.
* docs: regenerate docs/out static site for the 8-page Nextra build (issue #391)
`docs/out/` is the static export served at the GitHub Pages mirror. Rebuild
it with `pnpm --filter @luxfi/bridge-docs build` so the artifact contains
all six content pages (index, docs, integrations, lux-id-integration,
operator-runbook, operator-deploy) plus _app and 404.
No source code or docs content changes in this commit — build artefacts only.
Rule: luxfi/bridge ships ONLY the Lux brand. Foreign-org bridge tenants
(Hanzo, Zoo, Pars, SPC, ) live in their own repos as thin
shims that consume @luxfi/bridge plus their own brand package.
- rm manifests/tenants/{hanzo,zoo,pars,spc}.yaml (carried foreign-brand
logos/colors/names into a Lux repo)
- REQUIREMENTS.md: drop tenant goal, drop Phase 2
Zoo-tenant stand-up + Hanzo-as-tenant deliverables, drop
@zooai/brand / @hanzoai/brand publication tasks; scope tenant work
to Lux only and embed target to luxfi/exchange
- docs/LLM.md (symlinked as CLAUDE.md/AGENTS.md/QWEN.md/GEMINI.md):
drop @zooai/brand / @hanzoai/brand from the architecture legend;
rewrite "Hanzo-side bridge" section as "foreign-brand tenants live
in their own repos"
- add app/bridge/public/.well-known/bridge.json declaring brandId=lux,
domain bridge.lux.network, peers [] (federation peers via runtime
ConfigMap), capabilities [bridge, mpc], apiVersion 1
- add BRAND-AUDIT.md documenting findings + actions
Kept (not org brand): "Liquid <TOKEN>" wrapped-asset names are Lux's
own bridge token brand (Liquid BTC, Liquid ETH, ...), wrapper minted
on Lux C-Chain per manifests/schema.yaml. Kept (chain identity):
manifests/tenants/lux.yaml, manifests/chains/*, chain RPC config,
teleporter contracts.
User directive (2026-05-24): 'no capnp-es must be zap-es ... keep all
zap brand neutral in ~/work/zap, zap-proto github etc ... should be
npm @zap-proto matching'.
Audit confirmed:
- The bridge has ZERO capnp-es references (every wire call is JSON
over HTTP via fetch). Bridge is clean.
- Canonical ZAP repo is ~/work/zap (not ~/work/lux/zap or
~/work/hanzo/zap — those are forks slated for consolidation upstream).
- TS implementation lives at ~/work/zap/zap-js (package name
@zap-proto/zap). It already exists as pure TS — no source file
imports capnp-es, despite the dep being listed in package.json
(stale entry, removal queued for next ZAP TS publish).
- WASM binding: @zap-proto/wasm at ~/work/zap/zap-wasm.
- npm @zap-proto/* scope is the canonical brand-neutral home.
This commit just adds a doc section so the next dev (or me, next
session) doesn't accidentally ERR_PNPM_ADDING_TO_ROOT Running this command will add the dependency to the workspace root, which might not be what you want - if you really meant it, make it explicit by running this command again with the -w flag (or --workspace-root). If you don't want to see this warning anymore, you may set the ignore-workspace-root-check setting to true. when a future bridge
surface needs binary RPC. The rule is:
use @zap-proto/zap (pure TS, no third-party Cap'n Proto dep)
do NOT publish @luxfi/zap-* or @hanzoai/zap-* (forks the wire format)
source-of-truth for wire format: ~/work/zap/README.md +
~/work/zap/zap-js/src/protocol.ts
User directive: 'drop LUX_ keep it brand neutral do not use nats/consul
must use standalone ~/work/lux/mpc with our native ~/work/lux/consensus
or b/m-chains'.
This commit lands all three asks.
────────────────────────────────────────────────────────────────────────
Brand neutralization
────────────────────────────────────────────────────────────────────────
Env vars renamed (LUX_* → BRIDGE_*):
LUX_IAM_ISSUER → BRIDGE_IAM_ISSUER
LUX_KMS_URL → BRIDGE_KMS_URL
LUX_KMS_ORG → BRIDGE_KMS_ORG
LUX_KMS_CLIENT_ID → BRIDGE_IAM_CLIENT_ID
LUX_KMS_CLIENT_SECRET → BRIDGE_IAM_CLIENT_SECRET
LUX_MPC_URL → BRIDGE_MPC_URL
(+ BRIDGE_MPC_WALLET_ID new — default wallet for native sign)
Client classes renamed (Lux* → brand-neutral):
LuxIAMClient → IAMClient
LuxKMSClient → KMSSecretClient (avoids collision w/ AWS SDK's KMSClient)
LuxMPCClient → MPCClient
Audience strings renamed (lux-* → bare service name):
'lux-kms' → 'kms'
'lux-mpc' → 'mpc'
File renames:
src/clients/lux-iam.ts → src/clients/iam.ts
src/clients/lux-kms.ts → src/clients/kms.ts
src/clients/lux-mpc.ts → src/clients/mpc.ts
(+ matching __tests__/ files)
────────────────────────────────────────────────────────────────────────
NATS + Consul: gone
────────────────────────────────────────────────────────────────────────
Deletions:
- app/server/src/services/mpc-service.ts (498 LOC NATS+Consul wrapper)
- app/server/src/utils/trigger-keygen.ts (dev script, NATS)
- app/server/src/scripts/trigger-keygen.ts (dev script, NATS)
- app/server/src/scripts/test-signing.ts (dev script, NATS)
- app/server/src/types/nats.d.ts (vendored type stubs)
- consul + nats sections of app/server/src/types/index.d.ts
- nats + consul devDependencies in app/server/package.json
- NATS + Consul + Vault containers in compose.local.yml
Rewritten:
- app/server/src/domain/mpc-bridge.ts (497 → 197 LOC)
Preserves the public surface (bridgeMPC.initialize() /
.generateMPCSignature() / .completeSwap() / .getHealthStatus())
so domain/mpc-modern.ts callers stay untouched. Internally:
- One MPCClient HTTP call replaces the NATS publish + subscribe
pub/sub dance. mpcd handles the threshold round atomically.
- Consul KV completion marker replaced with Prisma's
Swap.metadata_sequence_number update (single source of truth).
- Lazy IAM + MPCClient construction so the bridge boots cleanly
when BRIDGE_MPC_URL / BRIDGE_IAM_* are unset (standalone mode).
Sign calls return a clear error rather than crashing the
process.
- app/server/src/server.ts startup: no more mpcService.initialize();
bridgeMPC.initialize() now soft-fails (logger.warn) on missing
env. /health endpoint reads through bridgeMPC.getHealthStatus()
which reports { online: 0, total: 0, standalone: true } when
MPCClient isn't configured.
- compose.local.yml: replaces 6-service NATS/Consul/Vault topology
with bare 3-service (iam + iam-db + bridge postgres). Out-of-band
mpcd + KMS instructions documented in the file header.
────────────────────────────────────────────────────────────────────────
docs/LLM.md
────────────────────────────────────────────────────────────────────────
All LUX_* env mentions retargeted to BRIDGE_*. The 'Native Lux services'
section now describes the HTTP-only, env-neutral integration pattern.
Standalone mode section unchanged in shape but with refreshed env names.
────────────────────────────────────────────────────────────────────────
Tests + typecheck
────────────────────────────────────────────────────────────────────────
SDK pkg/bridge: 58 / 58
Server app/server: 123 / 123 (no regression — same set as v1.1.21
with renamed env vars)
Typecheck: clean on both packages
────────────────────────────────────────────────────────────────────────
Net effect
────────────────────────────────────────────────────────────────────────
Bridge backend is now genuinely brand-neutral:
- No 'LUX_' in any env var (the BRIDGE_ prefix is service-scoped, not
brand-scoped; same prefix the SDK uses for runtime config)
- No NATS, no Consul anywhere in the codebase or compose files
- Native m-chain signing goes through HTTP to mpcd (the canonical
~/work/lux/mpc daemon, github.com/luxfi/mpc), one round-trip per
sign, with the same wire protocol as ~/work/lux/kms/pkg/mpc/client.go
- Standalone mode preserved: when BRIDGE_MPC_URL is unset, the bridge
runs without crashing; sign calls return a clear error
User asked 'make sure that bridge can work standalone? ~/work/hanzo/teleport
and ~/work/hanzo/bridge' — both Hanzo paths confirmed not to exist; the
canonical Lux bridge is split across ~/work/lux/teleport (Warp 2.0
protocol, LP-021v2 / LP-7330) and ~/work/lux/bridge (UI + SDK + shim
server, this repo).
This commit answers the 'standalone' part:
compose.standalone.yml — bare three-service topology:
- postgres (state)
- bridge-server (API, optional LUX_* env stubs commented)
- bridge-ui (Vite SPA via ghcr.io/luxfi/bridge image with BRIDGE_* env)
NO Casdoor, NO Vault, NO NATS, NO Consul, NO 3-node MPC cluster.
Every external Lux service is OPTIONAL at runtime — the backend
graceful-degrades when the corresponding env block is unset and picks
the integration up when it appears.
docs/LLM.md gains:
- 'Standalone mode' section: docker compose recipe, what's
intentionally NOT in standalone compose + why (one-line per service)
- 'Hanzo-side bridge / teleport — does not exist' subsection: makes
explicit that there is no ~/work/hanzo/teleport / ~/work/hanzo/bridge.
If a Hanzo-branded tenant is needed, the right play is a Hanzo
tenant build under app/ (mirror of app/bridge/) consuming @luxfi/bridge
+ @hanzoai/brand. SDK is the integration point; tenants are thin.
Verification: bridge backend already swallows MPC / IAM / NATS init
failures (logger.warn instead of fatal). Only Postgres is a hard dep,
which compose.standalone.yml provides. Full SQLite-only mode would
require a Prisma provider swap + per-table audit; that's a separate
session and standalone compose covers the immediate ask.
No code-runtime changes — the existing graceful-degradation paths in
app/server already supported this topology; this commit just makes
the recipe explicit + documented.
User asked for native ~/work/lux/mpc + ~/work/lux/kms integration and
'pure b-chain/m-chain via mpc/kms software frontend'. Delivers the
canonical-Lux-services HTTP clients on the bridge backend.
Three new client modules in app/server/src/clients/:
lux-iam.ts LuxIAMClient — OAuth2 client_credentials minter against
Lux IAM (https://iam.lux.network). Per-audience cache
with early refresh; one cache slot per (aud=lux-kms,
aud=lux-mpc) downstream service. invalidate() on 401.
Mirrors ~/work/lux/kms/pkg/iamclient/client.go in TS.
lux-kms.ts LuxKMSClient.getSecret(path) — reads from ~/work/lux/kms
(https://kms.lux.network) at
/v1/kms/orgs/{org}/secrets/{path...}. Bearer JWT auth via
LuxIAMClient. Unwraps either raw text/* or JSON envelope
{ value | secret } responses. KMSError carries httpStatus
+ path for the caller to switch on.
lux-mpc.ts LuxMPCClient — the canonical m-chain entrypoint. Speaks
the same wire protocol as ~/work/lux/kms/pkg/mpc/client.go
(~/work/lux/mpc/cmd/mpcd HTTP API). Methods:
keygen({ vaultId, name, keyType, protocol })
→ POST /v1/vaults/{id}/wallets (DKG)
sign({ walletId, keyType, message })
→ POST /v1/transactions (type=sign,
base64 payload)
status() → GET /v1/status
Supports the full Lux protocol set: cggmp21 / frost /
bls / sr25519 / doerner / pulsar / corona / magnetar.
Per-call 120s timeout matches mpcd's threshold ceiling.
────────────────────────────────────────────────────────────────────────
fetchCosignerSecret — now KMS-backed
────────────────────────────────────────────────────────────────────────
domain/cosigners.ts::fetchCosignerSecret routes through LuxKMSClient
when LUX_KMS_URL + LUX_IAM_* are set. Path layout:
utila: bridge/cosigners/utila/{envSafe(org_id)}/sa_pem
fireblocks: bridge/cosigners/fireblocks/{envSafe(api_key)}/secret_pem
404 from KMS → quietly falls back to UTILA_COSIGNER_PEM__/
FIREBLOCKS_COSIGNER_PEM__ env vars (dev-only). Any other KMS error is
rethrown so the dispatcher surfaces it as a 'failed' (retryable)
CosignResult. _resetKmsClientForTests() lets tests rebuild the cached
client after mutating process.env.
────────────────────────────────────────────────────────────────────────
docs/LLM.md
────────────────────────────────────────────────────────────────────────
- New 'Native Lux services' section: documents IAM + KMS + MPC env
config and the audience scoping. Production MUST set the LUX_KMS_*
block; env-var fallback is dev-only.
- New 'Lux software frontends' section: lists the three operator UIs
(~/work/lux/mpc/dashboard Next.js, ~/work/lux/kms/frontend Vite) and
notes the f-chain frontend does NOT exist yet.
- New 'f-chain frontend — what it would look like' section: scaffolds
the proposed @luxfi/fchain-dashboard layout (cluster status, pubkey
registry, encrypt-session history, reshare history, health probe)
with the exact /v1/fhe/* endpoints each widget would consume. Note
that the bridge tenant's TRANSFERS panel currently surfaces per-swap
fchain attestation status (no separate UI needed for that scope).
────────────────────────────────────────────────────────────────────────
tests — 18 new
────────────────────────────────────────────────────────────────────────
+ clients/__tests__/lux-iam.test.ts (7 cases)
+ clients/__tests__/lux-kms.test.ts (6 cases)
+ clients/__tests__/lux-mpc.test.ts (8 cases — keygen / sign / status
/ 401 invalidate / abort)
+ domain/__tests__/cosigners-kms-secret-fetch.test.ts (7 cases —
KMS happy path, env-var fallback, 404 fallthrough, 5xx propagate,
cloud_hsm/fchain defensive guard)
Updated two pre-existing tests (cosigners-utila + cosigners-fireblocks
env-var-missing cases) to match the new 'cosigner secret unavailable'
error string from the refactored fetchCosignerSecret.
────────────────────────────────────────────────────────────────────────
final counts
────────────────────────────────────────────────────────────────────────
pkg/bridge SDK: 58 / 58
app/server: 95 → 123 (+28)
Typecheck: clean
Every cosigner adapter (utila / fireblocks / gcp_kms / aws_kms /
azure_key_vault / vault_transit / fchain) is a real network call.
fetchCosignerSecret routes through real Lux KMS.
Native m-chain signing wired via LuxMPCClient (caller integration in
domain/mpc-modern.ts is the next planned step — clients are now in
place and tested).
User pointed out that @luxfi/brand should be used 'for all lux apps /
projects' — confirming the canonical brand sourcing principle. Audit
pass against the bridge stack found two leaks of Lux-specific identity
INTO the jurisdiction-neutral SDK:
1. `pkg/bridge/package.json` declared `@luxfi/brand` as a direct
dependency — but the SDK source never imports it. Dead dep and a
layering violation: Zoo / Hanzo / any white-label consumer of
`@luxfi/bridge` shouldn't pull Lux brand metadata into their bundle.
Dropped.
2. `pkg/bridge/src/app/lib/wagmi-config.ts` had a hardcoded SSR
fallback URL `https://bridge.lux.network` for the WalletConnect
metadata block. On client-side hydration this is overridden by
`window.location.origin`, but the first SSR-render frame was
leaking the Lux hostname into Zoo / Hanzo tenant builds.
Replaced with `deriveAppOrigin(cfg.apiHost)` — strips the leading
`api.` subdomain from the configured API host so the fallback is
tenant-derived. `api.bridge.lux.network` → `bridge.lux.network`,
`api.bridge.zoo.network` → `bridge.zoo.network`. Catch-all
fallback is `https://localhost` if the URL fails to parse.
3. `docs/LLM.md` gains a 'Canonical brand sourcing' subsection
documenting the principle:
- `@luxfi/brand` (~/work/lux/brand) is the ONLY source of Lux
brand identity for ALL Lux-ecosystem apps (bridge, exchange,
id, pay, etc.)
- SDK is jurisdiction-neutral; tenants supply brand at mount time
- App-specific endpoints (api.bridge.lux.network) are independent
of brand.json's appDomain (lux.exchange)
- Other Lux apps follow the same pattern; any hardcoded brand
string in a Lux app is a leak — file as a follow-up issue.
SDK 1.0.3 -> 1.0.4. Additive + neutralization only — no functional
behavior change for Lux consumers; Zoo / Hanzo SSR frames now show
their own hostname instead of bridge.lux.network.
Tests: 58/58 SDK unchanged.
- README.md: replace stale 'Bridge UI → Bridge Server → MPC Nodes' diagram
with the v1.1.x topology (inlined UI, direct threshold integration,
layered cosigners). Remove dead links to docs that v1.1.12 deleted
(MPC-GO-INTEGRATION, CI-CD-DOCKER-IMAGES). Add pointer to issue #392
for the new bridge dev.
- docs/LLM.md: refresh 'Key Documentation Files' list to remove the
deleted MPC-GO/DEPLOYMENT/MIGRATION-TO-GO references; document the
Nextra site path (`docs/pages/*.mdx`); reframe the migration-files
history as a v1.1.12 deletion event with the commit hash.
- docs/content/docs/index.mdx: refresh the architecture diagram inside
the Nextra site itself so the public docs match the new topology.
Add the protocol class table (classical vs PQ-safe lattice) and the
optional-layered-cosigners line. The diagram now matches LLM.md and
the top-level README — three places, one story.
Closes the remainder of #391.
Fact-check pass against actual repo state, fixing five stale claims that
referenced an architecture that hasn't existed since phase 1.5:
1. app/bridge3/ (@luxbridge/app-v3) — DOES NOT EXIST. Folded into
pkg/bridge/src/app/ at 45e08a1 ('feat(pkg/bridge): inline bridge UI
under src/app/'). Bridge.tsx no longer lazy-imports any sibling
workspace package; the cycle that produced the blank-page bug is gone.
2. app/bridge/ — collapsed at 84810b8 ('phase2-r2: collapse to canonical
app/bridge tenant') from a multi-variant Next.js setup to a single
@luxbridge/lux-tenant (Vite + ~120 LOC).
3. Frontend stack — Vite + React 18.3.1 + Tamagui (@hanzo/gui v7), NOT
Next.js 14. SDK ships TypeScript source directly; consumer Vite
bundles it.
4. @luxfi/threshold — consumed BOTH by app/server and by the SDK
directly (pkg/bridge/src/app/lib/mpc-session.ts since phase 3 R3),
not server-only as the prior diagram showed.
5. Service ports — tenant UI is 3001 (Vite), not 3000.
Adds:
- System architecture ASCII diagram reflecting the inlined UI +
direct threshold + layered-cosigner topology.
- 'Optional layered cosigners' subsection documenting Utila +
Fireblocks layering pattern (since SDK v1.0.3).
- 'Explorer migration' section — app/explorer/ (Next.js) is on a
deprecation path; canonical replacement is ghcr.io/luxfi/explorer
(single Go binary embedding luxfi/indexer + luxfi/graph + luxfi/explore
via go:embed). Same pattern as LiquidGraph cutover in liquidity/universe.
- Publishing status — @luxfi/bridge + threshold still 404 on npm as of
2026-05-22; likely missing NPM_TOKEN secret OR unavailable lux-build
runner pool. v1.1.10 fail-fast guard will surface either clearly.
- 'History — what got folded together' subsection so the prior
architecture changes are findable from the docs (commit refs included).
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.