Skip to content

feat(ambient-ui): status bar with connection context switching#1626

Merged
mergify[bot] merged 4 commits into
mainfrom
jsell/ambient-ui-statusbar
Jun 1, 2026
Merged

feat(ambient-ui): status bar with connection context switching#1626
mergify[bot] merged 4 commits into
mainfrom
jsell/ambient-ui-statusbar

Conversation

@jsell-rh
Copy link
Copy Markdown
Contributor

@jsell-rh jsell-rh commented Jun 1, 2026

Summary

  • Status bar: persistent bottom-of-page bar showing API server connection status and URL
  • Connection context switching: single-click URL → popover with URL + token fields to connect to remote API servers
  • Popover UX: labeled fields, collapsible Authentication section, token visibility toggle, Connect/Restore Default buttons
  • Custom context indicator: blue plug icon + "Custom Server" label when overriding default
  • Cache invalidation: removeQueries + refetchQueries ensures fresh data after context switch
  • Navigation: redirects to / on context change to avoid stale entity references

Spec updated with "Status Bar" and "Connection Context Switching" requirements.

Architecture

  • src/lib/runtime-config.ts — shared module for runtime-mutable API server URL + custom token
  • src/app/api/config/route.ts — GET/PUT/DELETE for connection context (token stored server-side, never exposed)
  • BFF proxy reads from runtime config: custom token > SSO JWT > dev-mode token
  • src/hooks/use-connection-status.ts — polls /api/healthz every 10s

Test plan

  • 171 tests pass, 0 type errors
  • Default state: green dot + URL + chevron in status bar
  • Click URL → popover with Connection form
  • Enter remote URL + JWT token → click Connect → data loads from remote
  • Blue plug icon + "Custom Server" shown in status bar
  • Click URL again → popover shows "Restore Default" banner
  • Restore Default → reverts to local, navigates to /
  • Hard refresh preserves custom context (server-side storage)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Persistent bottom Status Bar showing live connection state and allowing editing of API server URL and optional bearer token.
    • Popover-based UI for editing connection context and restoring defaults; connection changes trigger refresh/navigation as needed.
    • Periodic connection health polling with last-checked timestamps.
  • Tests

    • Added tests covering connection status behaviors.
  • Documentation

    • Updated spec to describe Status Bar behavior and custom-context UX.
  • Chores

    • Added popover UI dependency.

@netlify
Copy link
Copy Markdown

netlify Bot commented Jun 1, 2026

Deploy Preview for cheerful-kitten-f556a0 canceled.

Name Link
🔨 Latest commit f19070e
🔍 Latest deploy log https://app.netlify.com/projects/cheerful-kitten-f556a0/deploys/6a1dbdf33373e60008be558e

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Warning

Review limit reached

@jsell-rh, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 6 minutes and 28 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 63aee9a6-acf9-41a8-b2f1-e7abcca57487

📥 Commits

Reviewing files that changed from the base of the PR and between b110c07 and f19070e.

⛔ Files ignored due to path filters (1)
  • components/ambient-ui/package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
📒 Files selected for processing (12)
  • components/ambient-ui/package.json
  • components/ambient-ui/src/app/(dashboard)/layout.tsx
  • components/ambient-ui/src/app/api/ambient/v1/[...path]/route.ts
  • components/ambient-ui/src/app/api/config/route.ts
  • components/ambient-ui/src/components/nav-header.tsx
  • components/ambient-ui/src/components/status-bar.tsx
  • components/ambient-ui/src/components/ui/popover.tsx
  • components/ambient-ui/src/hooks/__tests__/use-connection-status.test.ts
  • components/ambient-ui/src/hooks/use-connection-status.ts
  • components/ambient-ui/src/lib/runtime-config.ts
  • components/ambient-ui/src/lib/session.ts
  • specs/ambient-ui/ambient-ui.spec.md
📝 Walkthrough

Walkthrough

Adds a persistent bottom StatusBar with editable API server context, a runtime-config module and /api/config route, a health-check hook plus tests, Radix popover wrappers, and updates the ambient proxy to use the runtime-configured upstream URL and optional custom token.

Changes

Runtime-configurable API server with connection status display

Layer / File(s) Summary
Runtime configuration state and API route
components/ambient-ui/src/lib/runtime-config.ts, components/ambient-ui/src/app/api/config/route.ts
Adds module-level runtime state and RuntimeConfig type with getRuntimeConfig(), setCustomContext(), resetContext(). /api/config exposes GET (read), PUT (validate & update apiServerUrl/customToken), DELETE (reset).
Ambient proxy reads runtime-config and token
components/ambient-ui/src/app/api/ambient/v1/[...path]/route.ts
Proxy now reads getRuntimeConfig().apiServerUrl, constructs upstream using that value, prefers config.customToken over resolveAccessToken(request), and only strips sha256~ access tokens when no customToken is used.
Connection status polling hook and tests
components/ambient-ui/src/hooks/use-connection-status.ts, components/ambient-ui/src/hooks/__tests__/use-connection-status.test.ts
Adds ConnectionStatus type and useConnectionStatus() that polls /api/healthz every 10s (React Query), mapping to checking/connected/disconnected with lastChecked timestamp. Tests cover initial state, success, non-OK, and network error.
Popover primitive and StatusBar component
components/ambient-ui/src/components/ui/popover.tsx, components/ambient-ui/src/components/status-bar.tsx
Adds Radix Popover wrappers and StatusBar with useApiServerConfig (fetch/update/reset), UI for editing URL/token, show/hide token toggle, live-region announcements, and cache invalidation/navigation on updates.
Dashboard layout, nav header, dependency & spec
components/ambient-ui/package.json, components/ambient-ui/src/app/(dashboard)/layout.tsx, components/ambient-ui/src/components/nav-header.tsx, specs/ambient-ui/ambient-ui.spec.md
Adds @radix-ui/react-popover dependency; dashboard layout now renders StatusBar (adds pb-10); NavHeader breadcrumb markup simplified and previous connected-status indicator removed; spec updated to require bottom-fixed Status Bar and connection-context behavior.

Possibly related PRs


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Security And Secret Handling ❌ Error /api/config endpoints lack explicit authentication checks despite modifying user state. Iron-session provides implicit isolation but best practice requires explicit auth verification. Add explicit auth verification in /api/config route (e.g., verify session.accessToken exists) consistent with /api/ambient/v1/* routes.
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title follows Conventional Commits format (feat(scope): description) and accurately describes the main feature: status bar with connection context switching.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Performance And Algorithmic Complexity ✅ Passed No meaningful performance regressions: polling efficient (10s, no retry), React Query caching appropriate, no N+1 patterns, no unbounded growth, no expensive loops.
Kubernetes Resource Safety ✅ Passed No Kubernetes resources present. This PR adds React/NextJS UI components and APIs—no k8s manifests, RBAC, Secrets, or resource configs found. Check inapplicable.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jsell/ambient-ui-statusbar
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch jsell/ambient-ui-statusbar

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
specs/ambient-ui/ambient-ui.spec.md (1)

746-749: ⚡ Quick win

Add explicit confidentiality requirement for custom token handling.

This section should explicitly state that custom tokens are never returned by config read APIs, never rendered back after save, and must be redacted in logs/telemetry. The feature introduces sensitive credential input, so this needs to be normative in the spec.

Also applies to: 793-798

🤖 Prompt for 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.

In `@specs/ambient-ui/ambient-ui.spec.md` around lines 746 - 749, Add a normative
confidentiality clause to the "status bar" custom-connection text stating that
any user-provided bearer token is treated as sensitive: the token MUST NOT be
returned by any config read API, MUST NOT be rendered back to the UI after save
(only an obfuscated indicator may be shown), and MUST be redacted in all logs
and telemetry; apply the same explicit requirements to the related section
referenced (lines 793-798) so both the custom connection and any config
storage/inspection behavior include these three mandates.
🤖 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 `@components/ambient-ui/src/app/api/config/route.ts`:
- Around line 15-23: The PUT handler currently calls request.json() directly (in
function PUT) which will throw on empty/invalid JSON and cause a 500; wrap the
request.json() call in a try/catch inside PUT, and on parse failure return a
Response.json({ error: 'Invalid JSON' }, { status: 400 }) (or similar
bad-request message) so malformed payloads produce a 400 instead of an
exception; keep the existing object/null type check after successful parsing.

In `@components/ambient-ui/src/lib/runtime-config.ts`:
- Around line 3-29: The module currently stores apiServerUrl and customToken in
process-global variables (apiServerUrl, customToken) and exposes setters
(setCustomContext, resetContext) which makes overrides global; change the API to
avoid module-level state by making runtime config per-request or per-session:
remove or stop using the mutable top-level variables and instead accept
overrides via parameters or a request/context object (e.g., add an optional
overrides argument to getRuntimeConfig or read from a per-request
store/session), update callers to pass the per-user url/token instead of calling
setCustomContext/resetContext, and keep defaultApiServerUrl derived from
env.API_SERVER_URL while computing isCustomContext from the passed-in overrides.
Ensure functions referenced (getRuntimeConfig, setCustomContext, resetContext,
apiServerUrl, customToken) are adjusted accordingly so no process-global
override is used.
- Around line 22-25: setCustomContext currently only updates
apiServerUrl/customToken when passed truthy strings, so an empty string can't
clear a previously set customToken; change setCustomContext to accept explicit
clears and assign overrides whenever a value is provided (not only truthy):
update the signature to allow token: string | null | undefined and url: string |
null | undefined, and replace the truthy checks with explicit undefined checks
(e.g. if (url !== undefined) apiServerUrl = url; if (token !== undefined)
customToken = token;) so passing null or '' will clear the override while
leaving undefined unchanged.

In `@specs/ambient-ui/ambient-ui.spec.md`:
- Around line 761-763: The spec step "WHEN the user double-clicks the URL" is
inconsistent with the PR intent for a single-click interaction; update the spec
to require a single click (replace "double-clicks" with "clicks" in the step)
and keep the rest of the acceptance criteria (status bar expands to show
editable URL and Token with URL pre-populated). Also add a brief accessibility
note to the same scenario indicating the interaction must work via keyboard
(Enter/Space focus) and touch so tests and discoverability align with the
implementation.

---

Nitpick comments:
In `@specs/ambient-ui/ambient-ui.spec.md`:
- Around line 746-749: Add a normative confidentiality clause to the "status
bar" custom-connection text stating that any user-provided bearer token is
treated as sensitive: the token MUST NOT be returned by any config read API,
MUST NOT be rendered back to the UI after save (only an obfuscated indicator may
be shown), and MUST be redacted in all logs and telemetry; apply the same
explicit requirements to the related section referenced (lines 793-798) so both
the custom connection and any config storage/inspection behavior include these
three mandates.
🪄 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: CHILL

Plan: Enterprise

Run ID: a95c0196-25f6-4180-914f-6e83eda10423

📥 Commits

Reviewing files that changed from the base of the PR and between 7040604 and 4a1d4f9.

⛔ Files ignored due to path filters (1)
  • components/ambient-ui/package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
📒 Files selected for processing (11)
  • components/ambient-ui/package.json
  • components/ambient-ui/src/app/(dashboard)/layout.tsx
  • components/ambient-ui/src/app/api/ambient/v1/[...path]/route.ts
  • components/ambient-ui/src/app/api/config/route.ts
  • components/ambient-ui/src/components/nav-header.tsx
  • components/ambient-ui/src/components/status-bar.tsx
  • components/ambient-ui/src/components/ui/popover.tsx
  • components/ambient-ui/src/hooks/__tests__/use-connection-status.test.ts
  • components/ambient-ui/src/hooks/use-connection-status.ts
  • components/ambient-ui/src/lib/runtime-config.ts
  • specs/ambient-ui/ambient-ui.spec.md

Comment thread components/ambient-ui/src/app/api/config/route.ts
Comment thread components/ambient-ui/src/lib/runtime-config.ts Outdated
Comment thread components/ambient-ui/src/lib/runtime-config.ts Outdated
Comment thread specs/ambient-ui/ambient-ui.spec.md Outdated
@jsell-rh jsell-rh force-pushed the jsell/ambient-ui-statusbar branch 2 times, most recently from b110c07 to efb6410 Compare June 1, 2026 17:08
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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 `@specs/ambient-ui/ambient-ui.spec.md`:
- Around line 761-767: Update the spec wording to match the implemented popover
interaction: replace "the status bar expands to show two editable fields" with
"a popover opens anchored to the status bar showing two editable fields (URL and
Token)" and explicitly note that the URL field is pre-populated, the Token field
is empty with placeholder text (e.g., "Bearer token"), pressing Enter on either
field confirms changes, pressing Escape or clicking outside the popover cancels
and closes it, and the popover is rendered via the `@radix-ui/react-popover`
pattern described in the PR summary ("opens a popover with connection fields").
🪄 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: CHILL

Plan: Enterprise

Run ID: 9c9068c2-4a2a-453f-91c4-ec072914cdb4

📥 Commits

Reviewing files that changed from the base of the PR and between 4a1d4f9 and b110c07.

⛔ Files ignored due to path filters (1)
  • components/ambient-ui/package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
📒 Files selected for processing (11)
  • components/ambient-ui/package.json
  • components/ambient-ui/src/app/(dashboard)/layout.tsx
  • components/ambient-ui/src/app/api/ambient/v1/[...path]/route.ts
  • components/ambient-ui/src/app/api/config/route.ts
  • components/ambient-ui/src/components/nav-header.tsx
  • components/ambient-ui/src/components/status-bar.tsx
  • components/ambient-ui/src/components/ui/popover.tsx
  • components/ambient-ui/src/hooks/__tests__/use-connection-status.test.ts
  • components/ambient-ui/src/hooks/use-connection-status.ts
  • components/ambient-ui/src/lib/runtime-config.ts
  • specs/ambient-ui/ambient-ui.spec.md
🚧 Files skipped from review as they are similar to previous changes (9)
  • components/ambient-ui/src/app/(dashboard)/layout.tsx
  • components/ambient-ui/src/hooks/use-connection-status.ts
  • components/ambient-ui/src/app/api/ambient/v1/[...path]/route.ts
  • components/ambient-ui/src/components/status-bar.tsx
  • components/ambient-ui/src/hooks/tests/use-connection-status.test.ts
  • components/ambient-ui/src/components/ui/popover.tsx
  • components/ambient-ui/src/app/api/config/route.ts
  • components/ambient-ui/src/components/nav-header.tsx
  • components/ambient-ui/src/lib/runtime-config.ts

Comment on lines +761 to +767
- WHEN the user clicks the URL
- THEN the status bar expands to show two editable fields: URL and Token
- AND the URL field is pre-populated with the current URL
- AND the Token field is empty with placeholder text (e.g., "Bearer token")
- AND pressing Enter on either field confirms the change
- AND pressing Escape cancels and collapses back to the default view

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Spec/implementation mismatch: popover vs inline expansion.

Line 762 states "the status bar expands to show two editable fields," but the PR summary and implementation use a popover overlay (per @radix-ui/react-popover dependency and PR description: "opens a popover with connection fields"). Update the spec to describe the popover interaction pattern for consistency with the implementation.

📝 Suggested spec correction
 #### Scenario: Enter custom context
 
 - GIVEN the status bar displays the default API server URL
 - WHEN the user clicks the URL
-- THEN the status bar expands to show two editable fields: URL and Token
+- THEN a popover opens above the status bar with two editable fields: URL and Token
 - AND the URL field is pre-populated with the current URL
 - AND the Token field is empty with placeholder text (e.g., "Bearer token")
 - AND pressing Enter on either field confirms the change
-- AND pressing Escape cancels and collapses back to the default view
+- AND pressing Escape cancels and closes the popover
🤖 Prompt for 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.

In `@specs/ambient-ui/ambient-ui.spec.md` around lines 761 - 767, Update the spec
wording to match the implemented popover interaction: replace "the status bar
expands to show two editable fields" with "a popover opens anchored to the
status bar showing two editable fields (URL and Token)" and explicitly note that
the URL field is pre-populated, the Token field is empty with placeholder text
(e.g., "Bearer token"), pressing Enter on either field confirms changes,
pressing Escape or clicking outside the popover cancels and closes it, and the
popover is rendered via the `@radix-ui/react-popover` pattern described in the PR
summary ("opens a popover with connection fields").

Add a persistent bottom-of-page status bar showing API server connection
status and URL. Supports switching between default SSO context and custom
remote connections with user-provided bearer tokens.

Status bar:
- Connection status indicator (green/red dot + label) polling /api/healthz
- API server URL in monospace, double-click to edit
- Custom context: URL + token fields, amber override indicator, Reset button
- Context switches invalidate all cached data (projects, sessions)

BFF proxy:
- Auth priority: custom token > SSO session JWT > dev-mode token
- Runtime-mutable API server URL via /api/config (GET/PUT/DELETE)
- Custom token stored server-side, never exposed in API responses

Spec updated with Status Bar and Connection Context Switching requirements.

171 tests, 0 type errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jsell-rh jsell-rh force-pushed the jsell/ambient-ui-statusbar branch from efb6410 to f19070e Compare June 1, 2026 17:14
@mergify mergify Bot added the queued label Jun 1, 2026
@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented Jun 1, 2026

Merge Queue Status

  • Entered queue2026-06-01 17:29 UTC · Rule: default
  • Checks skipped · PR is already up-to-date
  • Merged2026-06-01 17:29 UTC · at f19070e693be0a112f39892d0e3ca11c496bc4ea · squash

This pull request spent 33 seconds in the queue, including 5 seconds running CI.

Required conditions to merge

@mergify mergify Bot merged commit e86b1fe into main Jun 1, 2026
27 of 55 checks passed
@mergify mergify Bot deleted the jsell/ambient-ui-statusbar branch June 1, 2026 17:29
@mergify mergify Bot removed the queued label Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant