From 43c02260ae46ec5402192ad7c35ec42884b54bfb Mon Sep 17 00:00:00 2001 From: devwums Date: Mon, 27 Jul 2026 11:47:34 +0000 Subject: [PATCH] docs(product-audit): add knowledge-base entries for #265, #266, #267, #268 Adds 4 documentation files under bridgelet-product-audit/. Documentation-only; no changes to frontend/ or mobile/. --- .../glossary/lighthouse-ci-config.md | 50 +++++++++++++++++++ .../multi-chain-evaluation-summary.md | 45 +++++++++++++++++ .../lobstr-paste-flow-not-implemented.md | 49 ++++++++++++++++++ .../wallet-signing-to-sdk-handoff.md | 49 ++++++++++++++++++ 4 files changed, 193 insertions(+) create mode 100644 bridgelet-product-audit/glossary/lighthouse-ci-config.md create mode 100644 bridgelet-product-audit/glossary/multi-chain-evaluation-summary.md create mode 100644 bridgelet-product-audit/integration-notes/lobstr-paste-flow-not-implemented.md create mode 100644 bridgelet-product-audit/integration-notes/wallet-signing-to-sdk-handoff.md diff --git a/bridgelet-product-audit/glossary/lighthouse-ci-config.md b/bridgelet-product-audit/glossary/lighthouse-ci-config.md new file mode 100644 index 0000000..4ee034f --- /dev/null +++ b/bridgelet-product-audit/glossary/lighthouse-ci-config.md @@ -0,0 +1,50 @@ +# Lighthouse CI Configuration + +## What Lighthouse CI measures + +Lighthouse audits a running page and scores it in categories — performance, +accessibility, best practices, SEO. Lighthouse **CI** runs those audits +automatically against a built app and can fail the build when a score drops below +a configured floor, turning page quality into a merge gate rather than a +spot check. + +## Where the config actually lives + +Note a correction worth recording: this file is **not** root-level. It sits at +`frontend/lighthouserc.js`, alongside the app it audits. There is no +`lighthouserc.js` at the repository root. + +## What it currently checks + +The config starts the production server (`npm run start`, awaiting the `Ready` +pattern) and audits three URLs, **3 runs each**: + +- `http://localhost:3000/` — home +- `http://localhost:3000/send` — sender flow +- `http://localhost:3000/claim/abc123` — claim flow, via a dummy token + +Assertions: + +| Category | Threshold | Level | +|---|---|---| +| Performance | ≥ 0.85 | `error` | +| Accessibility | ≥ 0.95 | `error` | +| Best practices | ≥ 0.90 | `error` | +| SEO | — | `off` | + +All three active thresholds are `error`, so falling below any of them fails the +run. Accessibility is held to the strictest bar. Reports upload to +`temporary-public-storage`. + +## Is it actually invoked? + +Yes — but not by the workflow you might expect. **`frontend-ci.yml` does not +reference it.** A *separate* workflow, `lighthouse-ci.yml`, runs `npm run lhci` +(i.e. `lhci autorun`) from `frontend/`. Two consequences: + +- It is **path-filtered** to `frontend/**`, `docs/**` and its own workflow file. A + change touching none of those — a docs-only addition to a new top-level folder, + say — will not run Lighthouse at all. +- It passes `LHCI_GITHUB_APP_TOKEN` from repository secrets, typically unavailable to pull requests from forks. + +See the checklist entry on CI-coverage gaps. diff --git a/bridgelet-product-audit/glossary/multi-chain-evaluation-summary.md b/bridgelet-product-audit/glossary/multi-chain-evaluation-summary.md new file mode 100644 index 0000000..62df1a5 --- /dev/null +++ b/bridgelet-product-audit/glossary/multi-chain-evaluation-summary.md @@ -0,0 +1,45 @@ +# Multi-Chain Evaluation — Summary + +A high-level pointer to `docs/multi-chain-evaluation.md`. All reasoning and detail +stays in that document; this is orientation only. + +## Current direction + +The document is an **evaluation**, not a commitment — it scopes what supporting +chains beyond Stellar would require, rather than announcing that Bridgelet is +becoming multi-chain. Read alongside `ROADMAP.md`, whose current status is MVP +implementation focused on Stellar ephemeral accounts, it reads as forward-looking +groundwork. + +Its conclusion, at the highest level: multi-chain support is **not a surface-level +change**. It reaches into the send flow, the claim flow, and the data model +simultaneously. + +## Areas it identifies + +1. **Send flow changes** — chain selection becomes part of the sending decision. +2. **Claim flow changes** — the biggest conceptual jump. Claiming on a chain + other than the one funds were sent on requires actual cross-chain bridging + infrastructure, and recipients must connect a wallet compatible with their + chosen target chain. +3. **Database and API schema** — today's schema is Stellar-specific in ways that + don't generalise: Stellar-denominated amount fields, and asset identifiers + that carry no chain qualifier. + +## Why this matters to the rest of this folder + +This is important background for anyone reading +[`wallet-connection-types.md`](./wallet-connection-types.md). All three +connection types documented there — Freighter, LOBSTR, and generated keypairs — +are **Stellar-specific assumptions baked into the frontend**. Freighter is a +Stellar extension; `generateNewWallet()` calls `Keypair.random()` from +`@stellar/stellar-sdk`; address validation elsewhere in the app assumes the +Stellar `G...` format. + +None of that is wrong today. But it means the wallet layer is one of the places +multi-chain work would land hardest, and the entries in this folder describing it +should be read as documenting *the current Stellar-only design*, not a +chain-agnostic one. + +**For any actual detail, go to `docs/multi-chain-evaluation.md`.** Nothing here +should be treated as a substitute for it. diff --git a/bridgelet-product-audit/integration-notes/lobstr-paste-flow-not-implemented.md b/bridgelet-product-audit/integration-notes/lobstr-paste-flow-not-implemented.md new file mode 100644 index 0000000..2b94fd2 --- /dev/null +++ b/bridgelet-product-audit/integration-notes/lobstr-paste-flow-not-implemented.md @@ -0,0 +1,49 @@ +# LOBSTR Paste Flow — Documented but Not Wired Up + +A discrepancy between `docs/sender-auth-model.md` and the code it describes. + +## What the doc claims + +The Security Notes section of `sender-auth-model.md` states, in effect, that +LOBSTR — the mobile wallet — **is supported** via a paste-your-public-key +fallback, and that this fallback is *already wired in* `lib/wallet.ts`. + +Read plainly, that tells a reader LOBSTR is a working, if manual, option today. + +## What the code actually does + +`connectLobstr()` in `frontend/lib/wallet.ts` has exactly one behaviour — it +throws: + +```ts +export async function connectLobstr(): Promise { + // ...comments describing the intended paste flow... + throw new Error('USE_PASTE_FLOW'); +} +``` + +`USE_PASTE_FLOW` is a **sentinel** — a marker the UI is evidently meant to catch +in order to render a paste-your-address step. The comment directly above it says +as much: "This function returns a placeholder — the UI handles the paste step." + +The problem is the other half never landed. Searching the repository for that +sentinel returns **exactly one hit: the `throw` itself.** No component, hook, or +error boundary catches it. `connectLobstr()` also has **no callers anywhere** in +`frontend/`, so nothing is positioned to catch it even in principle. + +So the doc's "already wired in `lib/wallet.ts`" is half-true in a misleading way: +the *function* exists in `lib/wallet.ts`, but it implements no paste flow — it +implements a request for one. + +## Practical consequence + +If a user were routed to the LOBSTR option today, `connectLobstr()` would reject +with the literal message `USE_PASTE_FLOW`. With no handler mapping that sentinel +to a paste UI, the user would hit whatever generic error path exists — very +plausibly seeing the raw string `USE_PASTE_FLOW`, which is meaningless to them, +rather than "paste your LOBSTR address here." The one mitigation is that no UI +appears to call it, so the failure may be unreachable in practice rather than +actively broken. + +**Related:** [`sender-auth-model-doc-accuracy.md`](./sender-auth-model-doc-accuracy.md) · +[`../runbooks/diagnose-lobstr-connection-confusion.md`](../runbooks/diagnose-lobstr-connection-confusion.md) diff --git a/bridgelet-product-audit/integration-notes/wallet-signing-to-sdk-handoff.md b/bridgelet-product-audit/integration-notes/wallet-signing-to-sdk-handoff.md new file mode 100644 index 0000000..defba1a --- /dev/null +++ b/bridgelet-product-audit/integration-notes/wallet-signing-to-sdk-handoff.md @@ -0,0 +1,49 @@ +# Wallet Signing → SDK Handoff + +What happens between a wallet signing in the browser and the transaction reaching +the chain. Recorded at integration-note level; the precise division of labour +needs confirming (see the flag at the bottom). + +## The shape of the handoff + +As currently implemented: + +1. The browser obtains **signed transaction XDR** from Freighter. + `signFreighterTransaction()` in `frontend/lib/wallet.ts` passes unsigned XDR + plus a `networkPassphrase` to the extension and reads back + `{ signedTxXdr, signerAddress, networkPassphrase }`. The secret key never + leaves the extension. +2. The frontend hands that off to the **bridgelet-sdk API**. +3. The **API layer, not the browser**, talks to Soroban/Horizon. Per + bridgelet-sdk-audit's `horizon-vs-soroban-rpc.md`, network access lives on the + backend side. The browser does not submit transactions directly. + +Network selection is resolved browser-side from `NEXT_PUBLIC_CRYPTO_NETWORK`, +defaulting to `stellar-testnet` — meaning the passphrase the user signs against is +chosen by frontend configuration. + +## The ambiguity worth resolving + +`docs/sender-auth-model.md` describes step 4 of its flow as: *"the Bridgelet SDK +signs the transaction with the connected key."* + +That sentence can be read two ways, and the readings have very different security +properties: + +| Reading | Who holds the key | Implication | +|---|---|---| +| **A** — the SDK *triggers* signing by the connected wallet | Freighter extension | Non-custodial for this step; matches `signFreighterTransaction()` | +| **B** — the SDK itself signs with a key it holds | Backend | Custodial for this step; the "connected key" is not the signer | + +Reading A is consistent with the code in `lib/wallet.ts`, which is unambiguously +extension-side signing. But the same document elsewhere leans on the SDK as an +active participant, and Bridgelet genuinely *does* hold a funding key for +ephemeral-account creation and sweeping (see the custodial model). So both +readings describe things that are true of *some* transaction in this system. + +**The flag:** which party signs *which* transaction is not stated precisely +anywhere found in this review. Sender-authorised transfers and Bridgelet-initiated +funding/sweep operations plausibly have different signers, and conflating them +would misstate the trust model. This should be confirmed explicitly by someone +with knowledge of the SDK's internals rather than inferred from phrasing. See also +[`sender-auth-model-doc-accuracy.md`](./sender-auth-model-doc-accuracy.md).