feat: connection longevity + one-click 'Make permanent' 2FA - #3524
Merged
Conversation
Make it obvious, per connection, whether a saved vendor sign-in keeps running on its own — and give a one-click way to fix the ones that don't. Connections page: - Each connection now shows a longevity state read live from the vault: Stays signed in (password + authenticator), Signed in for now (password, no key — may pause when the vendor asks for a code), Signed in (SSO — occasional re-sign-in), or Reconnect needed. Each with a plain-language hint. - A dismissible banner nudges when connections can be made permanent. - A focused 'Make permanent' sheet stores the authenticator setup key (with per-vendor guidance, key validation, and a success state). We never change the vendor's 2FA — the user enables it and pastes the one-time setup key. - New batch endpoint GET /profiles/totp-statuses returns 2FA status for all password connections in one round-trip (reuses the live vault read; no schema change). Task flow: - The connection menu gains 'Keep signed in (2FA)', reusing the same sheet, so a connection can be made permanent without leaving the task. Tests: batch status service (per-connection, degrades unreadable items); row states + actions; sheet validation and save/success. API + app typecheck clean.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 11 files
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
- Scope the 2FA-status SWR cache to the org so switching orgs can't show another org's statuses. - Treat an unreadable/failed status as UNKNOWN, never 'no key': the batch endpoint omits connections it couldn't read (instead of reporting false), the hook surfaces its error, and rows show 'Status unavailable' with no 'Make permanent' prompt — so an outage never invites overwriting an existing key. The at-risk banner counts only confirmed 'no key' connections. - Bound the 1Password fan-out in the batch endpoint (was unbounded per org). - Refresh statuses after a connect/reconnect so a new row isn't stale. - Treat a never-verified session as 'reconnect', not 'stays signed in', even with a stored key. - Make the 'Make permanent' sheet resilient: a rejected save (or a failed status refresh after a successful save) returns to the form with an error instead of hanging on 'Saving…'; store the normalized Base32 key (spaces/hyphens stripped). - Remove the task-flow 'Keep signed in (2FA)' menu item: ConnectionManageMenu is not mounted anywhere and connection management deliberately lives on the Connections page, so it was dead code. Deferred: splitting the browser-auth-profiles controller (already over the file limit before this change) into a focused module.
…ller Moves the four TOTP routes (batch status, per-connection get/set/clear) out of BrowserAuthProfilesController into a dedicated BrowserAuthTotpController, bringing the profiles controller back under the 300-line limit and grouping the 2FA routes. Same paths, guards, permissions, and behavior — no route or contract change.
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Fix all with cubic | Re-trigger cubic
…e TOTP controller - setProfileTotp now validates and normalizes the key on the server (the client check is only UX): it accepts a Base32 secret or an otpauth:// URI and rejects a rotating one-time code or junk, so a direct API caller can't silently replace a working seed with something that can't generate codes — which would quietly break unattended 2FA. Extracted as normalizeTotpSecret with unit tests. - Add controller-level tests for BrowserAuthTotpController: organization + profile ids reach the storage service on all four routes, and reads require integration:read while writes require integration:update.
Strip trailing Base32 padding with a plain scan instead of a start-anchorless regex (which can backtrack polynomially on untrusted input), and bound the input length up front. Behavior is unchanged for valid keys; adds padding + long-input tests. Clears the CodeQL polynomial-regexp alert.
claudfuen
pushed a commit
that referenced
this pull request
Jul 29, 2026
# [3.111.0](v3.110.1...v3.111.0) (2026-07-29) ### Bug Fixes * **api:** classify the take-over method on an unclear outcome too ([539fdba](539fdba)) * **api:** only classify a switchable passkey when a code method exists ([#3528](#3528)) ([0d79093](0d79093)) * **app:** make a half-finished connect resumable, not a forced full-screen step ([#3525](#3525)) ([b1afcae](b1afcae)) * **cloud-security:** add missing logGroupName to CreateLogGroup remediation ([#3515](#3515)) ([76ae56c](76ae56c)) * harden sign-in classification + align take-over messaging ([#3527](#3527)) ([914cb1e](914cb1e)) * **integrations:** wrap aws add account form in dialog and scroll into view ([#3526](#3526)) ([07e91ae](07e91ae)), closes [#418](#418) * make the 2FA take-over universal — tailor guidance to what the page asks for ([#3520](#3520)) ([b12f3fe](b12f3fe)) * **policies:** remove archived policies from framework controls after unlinking ([#3513](#3513)) ([d639df2](d639df2)) * **training:** defer completion email and share canonical training IDs ([#3529](#3529)) ([fecb556](fecb556)) * **training:** remove rbac gate from mark-complete endpoint ([#3501](#3501)) ([8c5e98f](8c5e98f)), closes [#3455](#3455) ### Features * connection longevity + one-click 'Make permanent' 2FA ([#3524](#3524)) ([7345e3c](7345e3c)) * **policies:** add bulk upload for policy migration ([#3514](#3514)) ([1940f06](1940f06)) * **security-questionnaire:** add browser extension ([#3064](#3064)) ([e678421](e678421))
Contributor
|
🎉 This PR is included in version 3.111.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Implements the Browser Connections design (Claude Designer handoff): make it obvious, per connection, whether a saved vendor sign-in keeps running on its own, and give a one-click way to fix the ones that don't. No schema change.
Connections page (Settings → Browser Connections)
Task flow
Backend
GET /v1/browserbase/profiles/totp-statuses— 2FA status for all password connections in one round-trip (reuses the existing live vault read; no DB flag, so nothing can drift).Boundary (deliberate)
We do not enable 2FA on the vendor for the user (no MFA auto-enrollment). The flow only helps them store the key we need to generate codes.
Honesty note
'Permanent' holds only when the vendor's 2FA is an authenticator app (TOTP). SMS/email/passkey 2FA can't be automated — SSO and those cases are shown as needing occasional re-sign-in.
Tests
Follow-up (deferred, agreed)
The 'Where these connections run' tasks section (needs a tasks↔connections join endpoint).
Summary by cubic
Shows how long each browser connection will keep working and adds a one‑click “Make permanent” flow to store an authenticator setup key so runs can re‑sign in automatically. Validates and normalizes keys on the server and moves TOTP endpoints into a focused controller.
New Features
/v1/browserbase/profiles/totp-statusesreturns 2FA status for all password connections in one round‑trip; unreadable items are omitted (treated as unknown), requests use bounded concurrency, and the cache is scoped per org. Statuses refresh after connect/reconnect.Bug Fixes
otpauth://URI, rejects rotating codes and malformed/short keys, stores a normalized secret, and keeps the parser linear with an input‑length bound (resolves a CodeQL polynomial‑regexp alert).BrowserAuthTotpController(no path or contract change) and add controller tests to enforce RBAC and org/profile scoping; Make‑Permanent sheet recovers cleanly if save or refresh fails.Written for commit 72b3a2c. Summary will update on new commits.