Skip to content

Harden VNC setup calls against expired auth - #294

Open
jamesachurchill wants to merge 5 commits into
ID-Robots:betafrom
jamesachurchill:baxter/issue-231
Open

Harden VNC setup calls against expired auth#294
jamesachurchill wants to merge 5 commits into
ID-Robots:betafrom
jamesachurchill:baxter/issue-231

Conversation

@jamesachurchill

@jamesachurchill jamesachurchill commented Aug 4, 2026

Copy link
Copy Markdown

Summary

  • add a shared setup JSON fetch helper that always requests JSON
  • detect both 401 responses and followed redirects whose final path is /login
  • stop VNC repair, reboot polling, and clipboard activity immediately when authentication expires
  • replace parse errors and misleading HTTP failures with a clear refresh/sign-in prompt

Testing

  • added unit coverage for a 401 response and a followed login redirect
  • added component coverage for initial VNC probing and stopping repair on auth expiry
  • bun run test:unit
  • bun run test:components
  • bun run build
  • targeted ESLint checks for changed files

Closes #231

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of expired authentication across setup, VNC, repair, reboot, and clipboard actions.
    • Displays a clear sign-in prompt and provides a reload option when authentication expires.
    • Redirects expired sessions to the sign-in page when appropriate.
    • Improved API error messages using structured server responses, with fallback messaging when needed.
    • Prevents further repair processing after authentication expires and clears affected session state.

yalexx and others added 4 commits July 22, 2026 21:46
* Harden gateway recovery after updates (ID-Robots#263)

* fix: migrate legacy openai/<gpt> model+fallbacks to codex on startup (ID-Robots#266)

ChatGPT-subscription boxes (Codex OAuth, no OpenAI API key) that stored
their active model or a fallback as `openai/gpt-5.5` (etc.) before the setup
UI routed ChatGPT picks through Codex hit `401 Missing bearer or basic
authentication in header` on api.openai.com/v1/responses β€” often only as a
FailoverError days into use, once the OAuth token first refreshes and the
failover chain reaches the keyless `openai/*` fallback.

The chat-model pick route already rewrites openai/<gpt> -> codex/<gpt>, but
only when the user re-picks the model; existing configs never re-pick, so an
updated box stays broken until manually re-selected. Migrate primary +
fallbacks in gateway-pre-start.sh on gateway start, guarded on "codex OAuth
present AND no OpenAI API key" so keyed / dual-auth boxes (where openai/* is a
valid route) are left untouched. Mirrors CODEX_SUPPORTED_MODEL_RE /
hasOpenAiApiKeyProfile / hasCodexOauthProfile in
src/app/setup-api/chat/model/route.ts.

Verified against 6 fixtures: openai->codex primary+fallback migrate; keyed
box untouched; non-supported (gpt-4o) primary left as-is; already-codex no-op;
no-codex-auth untouched; composes with the retired-Sonnet migration. bash -n
and py_compile pass.

Co-authored-by: Mike (IDRobots) <mike@idrobots.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* fix(3.1.10): responsive chat header pills (wrap instead of overlap on narrow chat) (ID-Robots#267)

* fix: chat header pills squeeze + truncate cleanly on narrow panels

On a narrow chat the provider / model / thinking selector pills overlapped
into an unreadable strip. Two parts:

1. .header-dropdown-trigger gets width:100% so the button fills its
   flex-shrinking .header-dropdown parent. Previously the button kept its
   content width and spilled past the shrunk parent, so overflow:hidden on
   .chat-header-pills clipped / overlapped the pills instead of the labels
   truncating. Now every pill gives ground evenly and its label ellipsizes
   (the chevron stays β€” it's reserved in the 24px right padding).

2. Single row (no wrap) + overflow:hidden, and the chat window clamps to
   MIN_CHAT_WIDTH (340px) on both resize paths + the rendered width, so the
   window stops shrinking once the pills reach a readable minimum instead of
   smashing them.

The open menu is portaled to <body> (HeaderDropdown), so clipping the row
can't hide it. Verified at 320-420px: even truncation, carets visible, zero
overlap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: open chat from mascot with a macOS-style animation, no corner flash

- Stop streaming the frozen mascot's position into mascotX while the chat is
  open (page.tsx). That nudged mascotX for a frame right after opening, so the
  popup flashed to the wrong corner before settling. mascotX is now captured
  once from the tap.
- Grow the popup OUT of the mascot: transform-origin pinned to the popup's
  bottom edge, aligned horizontally with the mascot, and scale 0.82 -> 1 on an
  easeOutExpo curve (cubic-bezier(0.16,1,0.3,1)) over 0.36s. Smooth, premium,
  emanates from where you tapped instead of scaling from the popup centre.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: bump SW cache clawbox-v3 -> v4 to invalidate stale assets on the 3.1.10 chat-UI changes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: keep chat popup header on-screen on short/zoomed viewports

The un-dragged popup anchors from the bottom (bottom:170 above the mascot,
bottom:65 in tray mode) but its maxHeight budget was a flat 100vh-60px, so on
viewports shorter than ~680px (small windows, browser zoom) a 500px-tall popup
shoved its whole header β€” pills, status dot, close button β€” off the TOP of the
screen (rect.y = -76 measured on a 594px viewport). Subtract the bottom anchor
from the height budget per mode (+12px top margin) so the header is always
visible and the popup just gets shorter instead.

Found by driving the real desktop over CDP and sampling the popup rect during
open; the same probe confirmed the mascot-open animation runs and there is no
left-corner flash.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Mike (IDRobots) <mike@idrobots.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Mike (IDRobots) <mike@idrobots.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Merges beta into main for the 3.1.11 release. The conflicts came from ID-Robots#264
(the 3.1.10 gateway-recovery squash landing on main) diverging from the same
work as it evolved on beta; every one resolved to the beta side. The
resulting tree is byte-identical to origin/beta -- the exact code verified
on hardware today.

What ships:

- codex: route codex turns through the app-server harness (ID-Robots#280). Without
  agentRuntime, core posts to /backend-api/responses -- a browser endpoint
  Cloudflare challenges -- and every turn dies with an HTML error page.
- codex: restore the credential ID-Robots#278 broke, and migrate legacy auth profiles
  into the sqlite store core actually reads (ID-Robots#279).
- codex: stop mirroring the rotating refresh token into every codex-home, so
  a single-use refresh token cannot be spent twice (ID-Robots#278).
- codex: default ChatGPT auth to gpt-5.5; unblock GPT-5.6 for entitled
  accounts (ID-Robots#275, ID-Robots#276).
- gateway: stop update/boot from bricking the box; parameterised health and
  recovery waits.
- memory: local embeddings so semantic memory works without an API key.
- docs/site: point references at clawbox.com; measured Wi-Fi and local-model
  performance figures.

Hardware verification (2026-07-28, boxes .52 and todor):

- HTML/Cloudflare failure reproduced on the old build, fixed by the update
- 401 profile=- auth failure reproduced, fixed by the update
- forced OAuth token rotation x2 on both boxes -- codex survived both
- 3.1.10 -> 3.1.11 through the shipped updater: pass
- 3.1.5 -> 3.1.11 through the shipped updater incl. reboot: pass, ~4 min
- CI: 1499 unit tests, E2E, E2E-install in a real systemd container

Known, not a regression (present in 3.1.10, fix queued for 3.1.12): the Codex
model picker offers gpt-5.4/gpt-5.4-mini, which free-tier ChatGPT accounts
cannot run -- upstream 400s with no failover. The default is gpt-5.5, which
every tier runs, so this only bites a user who picks an older model by hand.
Release v3.1.11 β€” promote beta to main
@jamesachurchill
jamesachurchill requested a review from a team as a code owner August 4, 2026 00:58
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

πŸ“ Walkthrough

Walkthrough

VNC setup requests now use fetchSetupJson. The helper detects 401 responses and login redirects. VNCApp displays an expired-authentication state, clears operation state, and stops repair, reboot, polling, and clipboard flows.

Changes

VNC authentication handling

Layer / File(s) Summary
Setup fetch result contract
src/lib/fetch-setup-json.ts, src/tests/unit/fetch-setup-json.test.ts
Added typed fetch results, JSON negotiation, 401 detection, login-redirect detection, tolerant parsing, and unit coverage.
VNC availability and expired-auth state
src/components/VNCApp.tsx, src/tests/components/vnc-app.test.tsx
VNC availability checks now use structured results. Authentication expiry clears VNC state and renders a sign-in refresh action. Component tests cover the 401 path.
Repair, reboot, and clipboard flows
src/components/VNCApp.tsx, src/tests/components/vnc-app.test.tsx
Repair, reboot polling, and clipboard requests now handle structured API errors and stop when authentication expires. Repair expiry coverage verifies that later requests do not run.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant VNCApp
  participant fetchSetupJson
  participant SetupAPI
  VNCApp->>fetchSetupJson: Send setup request with JSON Accept header
  fetchSetupJson->>SetupAPI: Request setup endpoint
  SetupAPI-->>fetchSetupJson: Return 401 or redirect to /login
  fetchSetupJson-->>VNCApp: Return auth-expired result
  VNCApp->>VNCApp: Clear operation state and stop repair or polling
Loading

Suggested reviewers: georgik77, krasimirkralev, yalexx

πŸš₯ Pre-merge checks | βœ… 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
βœ… Passed checks (4 passed)
Check name Status Explanation
Linked Issues check βœ… Passed The changes address all issue #231 requirements, including JSON headers, 401 and login-redirect detection, flow stoppage, clipboard handling, and tests.
Out of Scope Changes check βœ… Passed The changes are limited to setup JSON fetching, VNC authentication-expiry handling, and related unit and component tests.
Title check βœ… Passed The title clearly summarizes the main change: protecting VNC setup calls against expired authentication.
Description check βœ… Passed The description explains the change, links the issue, and lists targeted tests, but omits the template's type and checklist sections.
✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

πŸ€– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/fetch-setup-json.ts`:
- Around line 9-12: Update redirectedToLogin to classify any redirect pathname
ending with "/login", including base-path routes such as "/clawbox/login", while
preserving the existing redirect and URL guards. Add a unit test covering a
login URL mounted below the origin root.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6fea7c94-9937-4423-b240-333795042d9b

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 8cb6a43 and 173ed39.

πŸ“’ Files selected for processing (4)
  • src/components/VNCApp.tsx
  • src/lib/fetch-setup-json.ts
  • src/tests/components/vnc-app.test.tsx
  • src/tests/unit/fetch-setup-json.test.ts

Comment thread src/lib/fetch-setup-json.ts Outdated
@jamesachurchill

Copy link
Copy Markdown
Author

Prior art and current-version verification

This PR supersedes the unmerged work in #253. That PR proposed the same core approachβ€”request JSON, detect both 401 and followed redirects ending at /login, and stop VNC repair/reboot/clipboard flows on authentication expiryβ€”but was closed during queue cleanup because it had become stale and conflicted with beta.

This implementation applies that design to the current codebase and additionally:

  • preserves existing request headers through one shared setup-JSON fetch helper;
  • classifies non-JSON and non-success responses without leaking parse errors into the UI;
  • centrally latches authentication expiry so polling and repeated clipboard work stop consistently;
  • adds component coverage proving the initial availability probe and repair flow halt on expiry.

Compatibility was reverified against current ClawBox main (v3.1.11, 8cb6a433) and beta (aeb34cdf). On main, all 1,471 unit tests and 32 component tests passed, followed by TypeScript and the production build. The patch also cherry-picked cleanly onto current beta; its 13 targeted tests and production build passed.

Both branches pin OpenClaw 2026.7.1. This change is confined to the ClawBox setup UI/middleware boundary and does not call or modify the OpenClaw runtime.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

πŸ¦€ ClawReview

Claws waving β€” here's what this change is about.

This PR fixes the VNC app's handling of expired sessions by replacing all five raw fetch calls (initial probe, repair trigger, reboot, reboot polling, clipboard) with a new shared helper β€” fetchSetupJson β€” that sets Accept: application/json and detects both 401 responses and already-followed redirects to /login. When auth expires, all VNC activity stops immediately and a clear 'Refresh to sign in again' button surfaces instead of confusing parse errors or misleading HTTP status messages. The helper lives in src/lib/ and is shaped for reuse across other setup-api callers.

At a glance

  • πŸ”§ Fix Β· touches VNCApp + new shared setup-api fetch helper
  • Base branch: main Β· +150 source / +117 tests across 4 files
  • 🟑 targets main but touches device code β€” convention is beta-first (main carries tagged releases)
  • 🟑 title doesn't follow type: description (feat/fix/chore/docs/…)
  • βœ… source changes come with test changes

Good to know

  • ℹ️ fetchSetupJson is a new shared utility in src/lib/ β€” other components still calling raw fetch() against /setup-api/ endpoints could be migrated to it in a follow-up.
  • 🟑 PR targets main directly; project convention is to land device-side changes on the beta branch first (main carries tagged releases).
  • ℹ️ Comes with both unit tests for the new helper and component tests covering the initial VNC probe and the repair-flow auth-expiry path.

β€” ClawReview πŸ¦€, your resident reef crab. Just orientation β€” CodeRabbit does the line-by-line, humans do the merge. Conventions: docs.

@github-actions github-actions Bot added the area: ui Auto-triage area label Aug 5, 2026
@KrasimirKralev
KrasimirKralev changed the base branch from main to beta August 6, 2026 18:55
@KrasimirKralev

Copy link
Copy Markdown
Contributor

Retargeted main β†’ beta. This changes device UI code (src/components/VNCApp.tsx), which per our workflow flows through beta first and reaches main via a release, not directly. Please rebase onto beta if the diff needs it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ui Auto-triage area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Harden VNC UI setup API calls against expired auth redirects

3 participants