Skip to content

fix: browser automation production-review findings (not_relevant guard, credential re-save, connections load state) - #3509

Merged
tofikwest merged 7 commits into
mainfrom
fix/browser-automation-prod-review
Jul 27, 2026
Merged

fix: browser automation production-review findings (not_relevant guard, credential re-save, connections load state)#3509
tofikwest merged 7 commits into
mainfrom
fix/browser-automation-prod-review

Conversation

@tofikwest

@tofikwest tofikwest commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Fixes for findings from the browser-automations production review (follow-ups to #3417).

Scheduled runs vs human task decisions

  • Scheduled browser runs no longer overwrite a task a person marked not_relevant — the guard is an atomic conditional update (status NOT IN in the WHERE clause), so a concurrent human decision can't be clobbered between a read and a write. Worker-level tests cover both the done and failed transitions.

Credential re-save keeps the vault tidy

  • Re-saving a connection's login (e.g. after a password rotation) now updates the existing 1Password item in place instead of creating a new item and repointing the profile. The op:// reference stays stable — a scheduled run mid-flight resolves current values — and superseded items no longer accumulate in the org vault.
  • A password-only re-save keeps the stored authenticator seed, so unattended 2FA sign-ins keep working; removing 2FA stays an explicit action via the dedicated TOTP endpoints.
  • If the stored item was deleted directly in 1Password, the flow falls back to creating a fresh item as before.

Connections list: loading/error are no longer rendered as "no connections"

  • useBrowserProfiles now uses the same SWR pattern as the sibling task hooks, exposing isLoading/isError and keeping the last good list when a refresh fails.
  • BrowserAutomations shows a retryable error card when the initial connections load fails, instead of the onboarding/empty states (which invited reconnecting an already-connected vendor and misresolved connection status in the composer and list). The connect and auth flows stay reachable — they don't depend on the list.

Tests

  • apps/api: npx jest src/browserbase src/trigger — credential-storage suite 12/12 (4 new re-save cases), worker guard tests pass.
  • apps/app: task-page browser-automations suites 96/96, incl. 4 new useBrowserProfiles cases.
  • Typecheck clean on all changed files (remaining reds are pre-existing on main, in untouched files).

Summary by cubic

Fixes production-review issues in browser automations: scheduled runs can’t overwrite human “not relevant” decisions, credential re-saves update the existing 1Password item with stable op:// references, and connection list load failures show a retryable error without blocking flows.

  • Bug Fixes
    • Scheduled runs use a single atomic update that skips not_relevant, done, and failed, so human decisions aren’t clobbered.
    • Re-saving connection credentials updates the existing 1Password item in place, keeps the stored TOTP seed unless a new one is provided, propagates vault write failures (no fallback replacement), and only creates a new item when the stored one is unreadable/deleted.
    • useBrowserProfiles switches to SWR with isLoading/isError, keeps the last good list on refresh failures, and the UI renders a retryable error card on initial load failure; execution/connect/auth flows remain accessible while the list loads.

Written for commit d6e1678. Summary will update on new commits.

Review in cubic

A scheduled browser automation flipped any non-done/non-failed task to done or
failed — including tasks a human deliberately marked not_relevant (with a
justification). That silently destroyed the compliance decision. Guard both the
done and failed transitions with isTaskStatusProtectedFromAutomation, matching
the codebase norm (cloud-security skips not_relevant as user intent). +tests.
The status check and the update were separate queries, so a human marking a task
not_relevant between them could still be overwritten. Move the guard into the
WHERE clause of an atomic updateMany (excluding done/failed + not_relevant), and
derive statusChangedToFailed from whether a row actually changed.
Assert the worker's done and failed transitions both go through updateMany with a
status filter that excludes not_relevant (and done/failed), and that a zero-count
result is treated as no transition — so a regression in either atomic filter is
caught instead of silently letting not_relevant be overwritten.
Re-saving a connection's login used to create a brand-new vault item and
repoint the profile at it, leaving the superseded item — still holding a
real username, password, and TOTP seed — orphaned in the org vault forever
(connection deletion only cleans the currently referenced item).

Update the existing item in place instead: the op:// reference stays stable,
so a scheduled run mid-flight still resolves current secrets, and no stale
copies accumulate. A password-only re-save now also keeps the stored
authenticator seed (dropping automatic 2FA stays an explicit action via the
TOTP endpoints) instead of silently disabling unattended sign-ins. Falls
back to creating a fresh item when the stored one is unreadable (e.g.
deleted directly in 1Password).
A failed GET /v1/browserbase/profiles left the hook's list empty with no
signal, indistinguishable from "no connections yet": the onboarding state
invited reconnecting an already-connected vendor, and connection resolution
(reconnect mode, composer binding, list status) silently misresolved.

Convert useBrowserProfiles to the SWR pattern used by the sibling task
hooks: loading and error are now exposed, a failed refresh keeps the last
good list, and BrowserAutomations renders a retryable error state instead
of the misleading empty states when the initial load fails. fetchProfiles
keeps its never-reject contract — callers await it mid-flow (e.g. right
after connecting a vendor).
@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
comp-framework-editor Ready Ready Preview, Comment Jul 27, 2026 2:30pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
app Skipped Skipped Jul 27, 2026 2:30pm
portal Skipped Skipped Jul 27, 2026 2:30pm

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

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.

All reported issues were addressed across 9 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/api/src/browserbase/browser-credential-storage.service.ts
Comment thread apps/app/src/app/(app)/[orgId]/tasks/[taskId]/components/BrowserAutomations.tsx Outdated
…hable while loading

A failed 1Password write no longer falls back to creating a replacement
item: the original still exists, so the fallback would orphan it and
repoint the profile — the very leak the update-in-place change removes.
Only a failed READ (item deleted directly in 1Password) creates a
replacement now; write errors surface to the caller and the retry hits
the same item.

The profiles loading gate moves below the execution/connect/auth
branches, which don't need the list — resuming a connect flow no longer
blanks while connections load.
@vercel
vercel Bot temporarily deployed to Preview – portal July 27, 2026 14:29 Inactive
@vercel
vercel Bot temporarily deployed to Preview – app July 27, 2026 14:29 Inactive
@tofikwest
tofikwest merged commit 02746c3 into main Jul 27, 2026
10 checks passed
@tofikwest
tofikwest deleted the fix/browser-automation-prod-review branch July 27, 2026 14:30
claudfuen pushed a commit that referenced this pull request Jul 27, 2026
# [3.109.0](v3.108.2...v3.109.0) (2026-07-27)

### Bug Fixes

* **api:** don't let scheduled browser runs overwrite not_relevant tasks ([#3507](#3507)) ([99393e5](99393e5))
* browser automation production-review findings (not_relevant guard, credential re-save, connections load state) ([#3509](#3509)) ([02746c3](02746c3))

### Features

* browser automations for scheduled, credential-backed evidence capture ([#3417](#3417)) ([411a83b](411a83b))
@claudfuen

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.109.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants