From 63a9070cabf7f47b3759c618664fd83eb245260d Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Tue, 28 Jul 2026 08:00:28 +0200 Subject: [PATCH 1/2] fix(frontend): keep the public wallet config in the repo, not in deployment secrets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The guard delegation section needs a Citrea RPC URL and a WalletConnect project id. Both are public by nature: they are baked into the browser bundle and visible to anyone who opens the dashboard. Wiring them through repository secrets was therefore the wrong mechanism — it implied they were sensitive, and it made the delegate button depend on deployment configuration that a local or fork build cannot have. They are now Dockerfile defaults, exactly like VITE_API_BASE_URL above them, and both workflows stop passing them. A plain `docker build` now produces a working delegate button, and a deployment that wants a different endpoint or project can still override either with --build-arg. The RPC default is the same public endpoint the backend uses; it answers browser requests directly (access-control-allow-origin: *), so it needs no proxy. Verified by building the image without any build-arg and confirming both values are present in the emitted bundle. --- .github/workflows/frontend-dev.yaml | 8 +------- .github/workflows/frontend-prd.yaml | 8 +------- frontend/.env.example | 23 ++++++++++++++--------- frontend/Dockerfile | 10 ++++++++-- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/.github/workflows/frontend-dev.yaml b/.github/workflows/frontend-dev.yaml index 4bd6e93..4854337 100644 --- a/.github/workflows/frontend-dev.yaml +++ b/.github/workflows/frontend-dev.yaml @@ -26,9 +26,7 @@ jobs: uses: actions/checkout@v4 - name: Build Docker image - # Unset secrets are not a build failure: wallet config is read lazily inside the guard section, - # so the dashboard still renders and the delegate button shows "wallet delegation unavailable". - run: docker build --build-arg VITE_DEPLOYMENT_ENV=dev --build-arg VITE_RPC_URL=${{ secrets.VITE_RPC_URL }} --build-arg VITE_WAGMI_ID=${{ secrets.VITE_WAGMI_ID }} -f frontend/Dockerfile -t ${{ env.DOCKER_TAGS }} . + run: docker build --build-arg VITE_DEPLOYMENT_ENV=dev -f frontend/Dockerfile -t ${{ env.DOCKER_TAGS }} . deploy: name: Deploy Frontend to DEV @@ -56,12 +54,8 @@ jobs: push: true tags: ${{ env.DOCKER_TAGS }} platforms: linux/arm64 - # Unset secrets are not a build failure: wallet config is read lazily inside the guard section, - # so the dashboard still renders and the delegate button shows "wallet delegation unavailable". build-args: | VITE_DEPLOYMENT_ENV=dev - VITE_RPC_URL=${{ secrets.VITE_RPC_URL }} - VITE_WAGMI_ID=${{ secrets.VITE_WAGMI_ID }} - name: Install cloudflared run: | diff --git a/.github/workflows/frontend-prd.yaml b/.github/workflows/frontend-prd.yaml index 9eaf5a0..8327de0 100644 --- a/.github/workflows/frontend-prd.yaml +++ b/.github/workflows/frontend-prd.yaml @@ -26,9 +26,7 @@ jobs: uses: actions/checkout@v4 - name: Build Docker image - # Unset secrets are not a build failure: wallet config is read lazily inside the guard section, - # so the dashboard still renders and the delegate button shows "wallet delegation unavailable". - run: docker build --build-arg VITE_DEPLOYMENT_ENV=prd --build-arg VITE_RPC_URL=${{ secrets.VITE_RPC_URL }} --build-arg VITE_WAGMI_ID=${{ secrets.VITE_WAGMI_ID }} -f frontend/Dockerfile -t ${{ env.DOCKER_TAGS }} . + run: docker build --build-arg VITE_DEPLOYMENT_ENV=prd -f frontend/Dockerfile -t ${{ env.DOCKER_TAGS }} . deploy: name: Deploy Frontend to PRD @@ -56,12 +54,8 @@ jobs: push: true tags: ${{ env.DOCKER_TAGS }} platforms: linux/arm64 - # Unset secrets are not a build failure: wallet config is read lazily inside the guard section, - # so the dashboard still renders and the delegate button shows "wallet delegation unavailable". build-args: | VITE_DEPLOYMENT_ENV=prd - VITE_RPC_URL=${{ secrets.VITE_RPC_URL }} - VITE_WAGMI_ID=${{ secrets.VITE_WAGMI_ID }} - name: Install cloudflared run: | diff --git a/frontend/.env.example b/frontend/.env.example index 5c02ea5..eb0d551 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -2,13 +2,18 @@ VITE_API_BASE_URL=http://localhost:3001 # or for remote backend # VITE_API_BASE_URL=https://dev.monitoring.juicedollar.com/api -# Wallet / Guard Delegation section (required for the Delegate button). Read fail-loud in -# src/lib/wagmi.ts — a missing value throws inside the lazy WalletProvider boundary (no silent -# fallback), so the rest of the read-only dashboard keeps running. Only the Delegate button uses -# these; the read path (signer / voting-power % / gas / helpers) comes from the backend /guard -# endpoint and works without them. +# Wallet config for the Guard Delegation section. Both values are PUBLIC — they are baked into the +# browser bundle and visible to anyone who opens the dashboard — so they are NOT deployment secrets: +# the shipped defaults live in frontend/Dockerfile and can be overridden per build with --build-arg. +# Set them here only for the local dev server, or to point at a different endpoint or project. +# +# They are read fail-loud in src/lib/wagmi.ts, but the failure stays contained: a missing value throws +# inside the lazy WalletProvider boundary, so the read-only dashboard keeps working and only the +# Delegate button shows "wallet delegation unavailable". The status half (signer, voting power, +# qualification, helper count, gas) comes from the backend /guard endpoint and needs neither value. -# Citrea RPC URL for the wagmi http() transport (browser-visible — use a public/rate-limited endpoint). -VITE_RPC_URL=https://your-citrea-rpc-provider.com -# WalletConnect / Web3Modal project id (reuse the dapp's id). -VITE_WAGMI_ID=your-walletconnect-project-id +# Citrea RPC URL for the wagmi http() transport. The public endpoint the backend uses also answers +# browser requests, so it works here as-is. +VITE_RPC_URL=https://rpc.citreascan.com +# WalletConnect project id — identifies the dapp to the relay, public by design. +VITE_WAGMI_ID=b49c3a590c4407316a6fd6eae6531e90 diff --git a/frontend/Dockerfile b/frontend/Dockerfile index d599bbd..1342364 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -12,9 +12,15 @@ ARG VITE_API_BASE_URL=/api ENV VITE_API_BASE_URL=$VITE_API_BASE_URL ARG VITE_DEPLOYMENT_ENV ENV VITE_DEPLOYMENT_ENV=$VITE_DEPLOYMENT_ENV -ARG VITE_RPC_URL +# Wallet config for the guard delegation section. Both values are PUBLIC by nature — they are baked +# into the browser bundle and visible to anyone who opens the dashboard — so they belong here as +# defaults rather than in deployment secrets, the same way VITE_API_BASE_URL does above. Override per +# build with --build-arg if a deployment needs a different endpoint or project. +# The Citrea RPC is the same public endpoint the backend uses and answers browser requests +# (access-control-allow-origin: *). The WalletConnect project id identifies the dapp to the relay. +ARG VITE_RPC_URL=https://rpc.citreascan.com ENV VITE_RPC_URL=$VITE_RPC_URL -ARG VITE_WAGMI_ID +ARG VITE_WAGMI_ID=b49c3a590c4407316a6fd6eae6531e90 ENV VITE_WAGMI_ID=$VITE_WAGMI_ID RUN npm run build From e5f8abc13af89851aab9aaa397a7bb0522a058f3 Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Tue, 28 Jul 2026 08:17:17 +0200 Subject: [PATCH 2/2] docs(frontend): name the coupling between the backend network and the baked RPC URL The delegate action builds its chain from the chain id the backend reports, while the RPC URL is now a fixed default in this image. Repointing the backend at another network without overriding the build-arg in the same breath leaves the wallet transport pointed at Citrea while the declared chain id says otherwise, and that combination builds silently. Naming the coupling where the override lives is cheaper than a runtime cross-check and does not add a mechanism whose own failure modes would need reviewing. --- frontend/Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 1342364..a10663d 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -18,6 +18,11 @@ ENV VITE_DEPLOYMENT_ENV=$VITE_DEPLOYMENT_ENV # build with --build-arg if a deployment needs a different endpoint or project. # The Citrea RPC is the same public endpoint the backend uses and answers browser requests # (access-control-allow-origin: *). The WalletConnect project id identifies the dapp to the relay. +# +# COUPLING: the delegate action builds its chain from the chain id the BACKEND reports at /guard, while +# this RPC URL is fixed here. Repointing the backend at another network (BLOCKCHAIN_ID / RPC_URL) without +# overriding VITE_RPC_URL in the same breath leaves the wallet transport talking to Citrea while the +# declared chain id says otherwise — transactions can look unconfirmed in the UI. Change both together. ARG VITE_RPC_URL=https://rpc.citreascan.com ENV VITE_RPC_URL=$VITE_RPC_URL ARG VITE_WAGMI_ID=b49c3a590c4407316a6fd6eae6531e90