Skip to content

Fix connect-secret rollback error copy - #86

Merged
kentcdodds merged 13 commits into
mainfrom
cursor/connect-secret-page-8a3a
Mar 28, 2026
Merged

kentcdodds merged 13 commits into
mainfrom
cursor/connect-secret-page-8a3a

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Mar 28, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • avoid claiming the secret was rolled back when connector config update fails on a no-connector path
  • stop deleting pre-existing secrets when connector config persistence fails during an update
  • require a real appId for app-scoped /connect/secret sessions and reject invalid or incompatible secret scopes
  • refresh stale generated UI sessions on retryable session errors and document the appId query parameter in the secret guide
  • add focused unit coverage for connector failure messaging and connect-secret handler scope guards

Testing

  • npm exec vitest run --project node-unit packages/worker/client/routes/connect-secret-errors.node.test.ts packages/worker/src/app/handlers/connect-secret.node.test.ts
  • npm run typecheck
  • npm run build
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Guided, multi-step "Connect secret" web workflow to create or update secrets (input, review, confirm, save, success/error).
    • Session-based auth and session validation throughout the flow.
    • Connector configuration support with scope-aware behavior, customizable allowed hosts and capabilities.
    • New API endpoints powering the connect-secret flow.
  • Improvements

    • Clearer connector configuration failure messages and rollback handling.
  • Documentation

    • Added a static "Connect secret" guide describing the workflow and URL/query usage.
  • Tests

    • Unit tests for connector error message formatting.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@coderabbitai

coderabbitai Bot commented Mar 28, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new /connect/secret feature: a client-side multi-step Remix route for creating/updating secrets, server-side UI and API handlers for session-backed initialization and persistence, route registrations, and a new MCP capability returning a static guide for the feature.

Changes

Cohort / File(s) Summary
Client route & registration
packages/worker/client/routes/connect-secret.tsx, packages/worker/client/routes/index.tsx
New Remix client route ConnectSecretRoute implements a URL-query-driven multi-step create/update secret UI, session token initialization via /connect/secret.json, secret value submission, connector config update, and error/rollback handling; route added to client routes map.
Server handlers & routing
packages/worker/src/app/handlers/connect-secret.ts, packages/worker/src/app/router.ts, packages/worker/src/app/routes.ts
Added createConnectSecretHandler (UI handler enforcing auth and rendering layout) and createConnectSecretApiHandler (GET returns generated UI session token/endpoints; POST validates payload/session, verifies session token, resolves secret, persists secret and optional connector config); registered new routes for /connect/secret and /connect/secret.json (including POST).
MCP capability & domain registration
packages/worker/src/mcp/capabilities/coding/generated-ui-secret-guide.ts, packages/worker/src/mcp/capabilities/coding/domain.ts
New read-only capability generated_ui_secret_guide returning a static title+body guide for using /connect/secret; capability registered in the coding domain capabilities.
Client error helper & tests
packages/worker/client/routes/connect-secret-errors.ts, packages/worker/client/routes/connect-secret-errors.node.test.ts
Added formatConnectorConfigFailureMessage utility to format connector-config failure text with rollback context; accompanying unit tests covering rolled-back and non-rolled-back messages.

Sequence Diagram

sequenceDiagram
    participant Browser as Client (Browser)
    participant UI as Server UI Handler (/connect/secret)
    participant API as Server API Handler (/connect/secret.json)
    participant Session as Session Manager
    participant Store as Secret Storage

    Browser->>UI: GET /connect/secret?name&scope&connector...
    UI->>Session: validate user session
    Session-->>UI: session valid / redirect
    UI-->>Browser: render page (form or update-confirm)
    Browser->>API: GET /connect/secret.json?scope&name&connector
    API->>Session: create/verify generated UI session token
    Session-->>API: token + sessionId + endpoints
    API-->>Browser: return JSON (sessionToken, endpoints)
    Browser->>Browser: user fills & confirms
    Browser->>API: POST /connect/secret.json {name, scope, sessionToken, value?, connector?, allowedHosts?, allowedCapabilities?}
    API->>Session: verify sessionToken / app user
    Session-->>API: verification result
    alt verified
        API->>Store: resolve existing secret (by name/scope) and save value (if provided)
        Store-->>API: resolved/saved
        API->>Store: save connector config (normalize allowedHosts/capabilities)
        Store-->>API: config saved
        API-->>Browser: { ok: true }
    else verification failed
        API-->>Browser: 401/403 JSON error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

Poem

🐰
I hop through queries, name in paw,
I fetch a token, check the law,
Review then save — a careful feat,
Secrets snug, connectors meet,
A tiny hop — the flow's complete!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'Fix connect-secret rollback error copy' describes a minor copy fix, but the changeset implements a comprehensive new feature adding a /connect/secret Remix route with client-driven UI, server handlers, session management, and a new MCP capability—far exceeding what the title conveys. Update the title to reflect the main change, such as 'Add connect secret page with Remix route and server handlers' or 'Implement /connect/secret route for guided secret input'.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/connect-secret-page-8a3a

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.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds

Copy link
Copy Markdown
Owner Author

@cursoragent could this not just be a regular remix route? I don't mind a bit of duplication with the generated UI code. This is an official route, not generated ui.

Also, do we have the right query params and is there a capability added for agents to know how to generate a URL for this route? They should use this route whenever they have a need for the user to provide a secret. It should optionally have a prefilled set of allowed hosts and allowed capabilities as well.

@cursor

cursor Bot commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

Taking a look!

Open in Web Open in Cursor 

cursoragent and others added 2 commits March 28, 2026 16:30
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
&scope=user
&dashboardUrl=https://linear.app/settings/api
&instructions=Go to Linear Settings → API → Personal API Keys → Create key
&allowedCapabilities=linear_issue_list,linear_issue_create

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@cursoragent make sure the agent understands that allowedCapabilities should only be capabilities which Kody actually has. I don't want the agent to make up capabilities that don't exist.

@cursor cursor Bot Mar 28, 2026 •

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.

I updated the connect-secret guide to explicitly warn that allowedCapabilities must only include real, registered Kody capabilities (no made-up names) and pushed the change. The PR description now reflects that clarification.

No further code changes are pending.

Open in Web Open in Cursor 

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds
kentcdodds marked this pull request as ready for review March 28, 2026 17:52
@github-actions

github-actions Bot commented Mar 28, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-86.kentcdodds.workers.dev

Worker: kody-pr-86
D1: kody-pr-86-db
KV: kody-pr-86-oauth-kv

Mocks:

@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: 3

🧹 Nitpick comments (2)
packages/worker/client/routes/connect-secret.tsx (2)

300-309: Consider handling partial failure more gracefully.

If saveSecretValue succeeds but updateConnectorConfig fails, the secret is saved but the user sees an error. On retry, they may encounter the "Secret already exists" flow. This is an edge case but could cause user confusion.

Consider either:

  1. Showing a specific message when connector config fails but secret was saved
  2. Checking for existing secret before retry to inform the user their secret was saved
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/worker/client/routes/connect-secret.tsx` around lines 300 - 309,
Split the combined try into two phases so partial success is detected: first
call saveSecretValue(params, session, state.secretValue) and if it succeeds then
call updateConnectorConfig(params, session) in a separate try/catch; on
updateConnectorConfig failure setState with step: 'error' plus a specific
message/flag (e.g. partialSaved or error: 'Connector config update failed;
secret saved') so the UI can show that the secret exists, and optionally expose
a retry path that checks for an existing secret (use an API/helper like
getSecret or checkSecretExists before retrying) to avoid "Secret already exists"
confusion. Ensure setState usage and error branching are updated where
saveSecretValue and updateConnectorConfig are referenced.

601-608: Consider disabling the save button during the saving step to prevent double submission.

When state.step === 'saving', the "Save secret" button remains enabled (only confirmedReview is checked). Users could click multiple times, triggering duplicate save requests.

♻️ Proposed fix to disable during save
 									<button
 										type="button"
 										css={primaryButtonCss}
-										disabled={!state.confirmedReview}
+										disabled={!state.confirmedReview || state.step === 'saving'}
 										on={{ click: () => void handleSave() }}
 									>
 										Save secret
 									</button>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/worker/client/routes/connect-secret.tsx` around lines 601 - 608, The
Save button can be clicked multiple times because only state.confirmedReview
controls disabled; update the button logic (the element using primaryButtonCss
and onClick -> handleSave) to also disable when state.step === 'saving' (e.g.,
set disabled to !state.confirmedReview || state.step === 'saving') and ensure
handleSave is a no-op or ignored when state.step === 'saving' to prevent
duplicate submissions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/worker/client/routes/connect-secret.tsx`:
- Around line 186-213: The saveSecretValue function is missing the required
action field in the POST body which causes the API to reject requests; update
saveSecretValue (taking ConnectSecretParams and ConnectSecretSession and posting
to session.endpoints.secrets) to include action: 'save' in the JSON body along
with name, value, description, and scope so the handler (account-secrets) can
dispatch correctly.

In `@packages/worker/src/app/handlers/connect-secret.ts`:
- Line 9: Remove the unused import buildAccountSecretPath from the top of
connect-secret.ts to fix the TypeScript build failure; locate the import
statement "import { buildAccountSecretPath } from
'@kody-internal/shared/account-secret-route.ts'" in connect-secret.ts and delete
it (or remove buildAccountSecretPath from the named import) so no unused symbol
remains.
- Around line 53-56: The call to buildConnectSecretAppId in connect-secret.ts is
unresolved; fix it by either importing the exported helper or implementing it
locally: locate the existing utility that constructs connect-secret app IDs
(matching the signature buildConnectSecretAppId({ connector, name }) and
returning a string), add an import for buildConnectSecretAppId at the top of the
file, or add a small local function with that exact name and signature that
returns the intended appId string; ensure the symbol is exported from its module
if you add it there so the import resolves and TypeScript compiles.

---

Nitpick comments:
In `@packages/worker/client/routes/connect-secret.tsx`:
- Around line 300-309: Split the combined try into two phases so partial success
is detected: first call saveSecretValue(params, session, state.secretValue) and
if it succeeds then call updateConnectorConfig(params, session) in a separate
try/catch; on updateConnectorConfig failure setState with step: 'error' plus a
specific message/flag (e.g. partialSaved or error: 'Connector config update
failed; secret saved') so the UI can show that the secret exists, and optionally
expose a retry path that checks for an existing secret (use an API/helper like
getSecret or checkSecretExists before retrying) to avoid "Secret already exists"
confusion. Ensure setState usage and error branching are updated where
saveSecretValue and updateConnectorConfig are referenced.
- Around line 601-608: The Save button can be clicked multiple times because
only state.confirmedReview controls disabled; update the button logic (the
element using primaryButtonCss and onClick -> handleSave) to also disable when
state.step === 'saving' (e.g., set disabled to !state.confirmedReview ||
state.step === 'saving') and ensure handleSave is a no-op or ignored when
state.step === 'saving' to prevent duplicate submissions.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: f520e857-c9f4-41db-8152-bac014df3487

📥 Commits

Reviewing files that changed from the base of the PR and between c604dbf and 13040dc.

📒 Files selected for processing (7)
  • packages/worker/client/routes/connect-secret.tsx
  • packages/worker/client/routes/index.tsx
  • packages/worker/src/app/handlers/connect-secret.ts
  • packages/worker/src/app/router.ts
  • packages/worker/src/app/routes.ts
  • packages/worker/src/mcp/capabilities/coding/domain.ts
  • packages/worker/src/mcp/capabilities/coding/generated-ui-secret-guide.ts

Comment thread packages/worker/client/routes/connect-secret.tsx
Comment thread packages/worker/src/app/handlers/connect-secret.ts Outdated
Comment thread packages/worker/src/app/handlers/connect-secret.ts Outdated
Comment thread packages/worker/client/routes/connect-secret.tsx Outdated
Comment thread packages/worker/src/app/handlers/connect-secret.ts
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Comment thread packages/worker/client/routes/connect-secret.tsx
Comment thread packages/worker/src/app/handlers/connect-secret.ts Outdated
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

@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.

♻️ Duplicate comments (2)
packages/worker/client/routes/connect-secret.tsx (1)

186-213: ⚠️ Potential issue | 🔴 Critical

Missing action field in POST body will cause API rejection.

The saveSecretValue function posts to the secrets endpoint without the required action: 'save' field. Based on past review verification, the account-secrets handler reads the action field from the request body and returns { ok: false, error: 'Invalid action.' } with status 400 when no valid action is provided.

🐛 Proposed fix
 		body: JSON.stringify({
+			action: 'save',
 			name: params.name,
 			value,
 			description: params.description,
 			scope: params.scope,
 		}),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/worker/client/routes/connect-secret.tsx` around lines 186 - 213, The
POST body sent by saveSecretValue lacks the required action field so the
account-secrets API rejects it; update saveSecretValue to include action: 'save'
in the JSON body (alongside name, value, description, scope) so the
account-secrets handler recognizes the request, and keep the existing error
handling in place if the response indicates failure.
packages/worker/src/app/handlers/connect-secret.ts (1)

52-55: ⚠️ Potential issue | 🔴 Critical

buildConnectSecretAppId is undefined — build failure.

The function buildConnectSecretAppId is called but never defined or imported. The TypeScript compiler confirms this causes a build failure.

You need to either:

  1. Import the function from an existing module, or
  2. Define it locally in this file
🐛 Proposed fix (local definition)
+function buildConnectSecretAppId(input: {
+	connector: string | null
+	name: string | null
+}): string | null {
+	if (!input.connector && !input.name) return null
+	return `connect-secret:${input.connector ?? 'unknown'}:${input.name ?? 'unknown'}`
+}
+
 export function createConnectSecretApiHandler(env: Env) {

Note: Adjust the implementation to match the expected app ID format used elsewhere in the codebase.

#!/bin/bash
# Search for similar buildAppId functions to determine the expected pattern
rg -n "buildAppId|build.*AppId" --type ts -A 3 | head -40

# Check if there's an existing function that should be imported
rg -n "export.*function.*AppId|export const.*AppId" --type ts
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/worker/src/app/handlers/connect-secret.ts` around lines 52 - 55, The
call to buildConnectSecretAppId in connect-secret.ts is failing because
buildConnectSecretAppId is not defined or imported; fix by either importing
buildConnectSecretAppId from the module that exports it (search for an existing
build*AppId helper and add an import) or implement a local function named
buildConnectSecretAppId that accepts ({ connector, name }: { connector: string;
name: string }) and returns the app ID string in the same format used elsewhere
(matching other build*AppId helpers); update the call site that uses scope,
connector, and name to rely on the imported or newly defined
buildConnectSecretAppId.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/worker/client/routes/connect-secret.tsx`:
- Around line 186-213: The POST body sent by saveSecretValue lacks the required
action field so the account-secrets API rejects it; update saveSecretValue to
include action: 'save' in the JSON body (alongside name, value, description,
scope) so the account-secrets handler recognizes the request, and keep the
existing error handling in place if the response indicates failure.

In `@packages/worker/src/app/handlers/connect-secret.ts`:
- Around line 52-55: The call to buildConnectSecretAppId in connect-secret.ts is
failing because buildConnectSecretAppId is not defined or imported; fix by
either importing buildConnectSecretAppId from the module that exports it (search
for an existing build*AppId helper and add an import) or implement a local
function named buildConnectSecretAppId that accepts ({ connector, name }: {
connector: string; name: string }) and returns the app ID string in the same
format used elsewhere (matching other build*AppId helpers); update the call site
that uses scope, connector, and name to rely on the imported or newly defined
buildConnectSecretAppId.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 692453bd-4c12-4f88-9f1a-00c8115d23a4

📥 Commits

Reviewing files that changed from the base of the PR and between a8bbde8 and bfbd7e2.

📒 Files selected for processing (2)
  • packages/worker/client/routes/connect-secret.tsx
  • packages/worker/src/app/handlers/connect-secret.ts

Comment thread packages/worker/client/routes/connect-secret.tsx Outdated
Comment thread packages/worker/client/routes/connect-secret.tsx
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds

Copy link
Copy Markdown
Owner Author

@cursoragent please check CI on this PR and fix any issues. Also address any valid feedback on this PR

@cursor

This comment has been minimized.

Comment thread packages/worker/client/routes/connect-secret.tsx
Comment thread packages/worker/client/routes/connect-secret.tsx
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Comment thread packages/worker/src/app/handlers/connect-secret.ts Outdated

@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: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/worker/client/routes/connect-secret.tsx`:
- Around line 216-244: The current flow saves the secret first then calls
updateConnectorConfig(), which can fail and leave a partial state; change the
client-server contract so the client sends the secret and connector config
together and the server performs a single atomic operation instead of two
separate requests (modify the POST payload sent by handleSave() to include
connector data and update the server handler to persist both or roll back on
failure). If changing the server endpoint is not possible immediately, implement
rollback on connector-config failure by calling the secret-delete endpoint from
updateConnectorConfig() (or return a distinct partial-success error) so the UI
can surface a clear partial-success/rollback state; target symbols: handleSave,
updateConnectorConfig.
- Around line 246-250: ConnectSecretRoute currently keeps state and session in
closure and initialize() only updates parts, causing secretValue/confirmation
flags to leak and stale async inits to overwrite newer ones; modify initialize()
(and any async init logic used in the blocks around lines referenced) to
immediately reset state = { ...defaultState } and set session = null when the
incoming query/search changes (compare against lastSearch), then bump a local
initVersion token (or capture a unique local version) before awaiting async work
and ignore any async results whose captured version does not match the current
token so stale completions are discarded; update lastSearch after committing the
reset so subsequent runs see the new value.

In `@packages/worker/src/app/handlers/connect-secret.ts`:
- Around line 84-85: The handler reads requestedAllowedCapabilities via
readOptionalStringArray(body, 'allowedCapabilities') and persists them to the
connector config; you must validate each requested capability against the
canonical set of registered capabilities (the app's capability registry or
constant) before saving and reject the request with a 400 if any unknown names
are present. Update the connect-secret handler (and the same logic used around
the save flow at the second occurrence) to compute unknown =
requestedAllowedCapabilities.filter(c => !registeredCapabilities.has(c)), and
when unknown.length > 0 return a 400 response listing the invalid names instead
of proceeding to persist the config.
- Around line 47-58: The GET branch wrongly references session.sessionId which
isn't declared there; update the appId computation to derive the app identifier
from the request instead of using the POST-only session variable—e.g. replace
"const appId = scope === 'app' ? session.sessionId : null" with code that reads
the app id from the URL (e.g. url.searchParams.get('appId')) or another
request-specific source, keeping the rest of the flow that calls readSecretScope
and createGeneratedUiAppSession intact.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0c94c430-57dc-4e1b-ab18-83ca21214e3e

📥 Commits

Reviewing files that changed from the base of the PR and between bfbd7e2 and 28b6f4e.

📒 Files selected for processing (2)
  • packages/worker/client/routes/connect-secret.tsx
  • packages/worker/src/app/handlers/connect-secret.ts

Comment thread packages/worker/client/routes/connect-secret.tsx
Comment thread packages/worker/client/routes/connect-secret.tsx
Comment thread packages/worker/src/app/handlers/connect-secret.ts
Comment thread packages/worker/src/app/handlers/connect-secret.ts
@kentcdodds

Copy link
Copy Markdown
Owner Author

@cursoragent please check CI on this PR and fix any issues. Also address any valid feedback on this PR

@cursor

This comment has been minimized.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Comment thread packages/worker/src/app/routes.ts
Comment thread packages/worker/client/routes/connect-secret.tsx Outdated
@kentcdodds

Copy link
Copy Markdown
Owner Author

@cursoragent please check CI on this PR and fix all issues. Also address any valid feedback on this PR

@cursor

cursor Bot commented Mar 28, 2026 •

Copy link
Copy Markdown
Contributor

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Review UI disappears during saving step
    • Included the saving step in the review visibility condition so the review UI stays visible while the save is in flight.
  • ✅ Fixed: allowedCapabilities displayed but never persisted to server
    • Sent allowedCapabilities in the client payload and stored them in the connector config on the server, preserving the reviewed capability list.

Create PR

Open in Web Open in Cursor 

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Comment thread packages/worker/client/routes/connect-secret.tsx
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@cursor cursor Bot changed the title Add connect secret page Fix connect-secret rollback error copy Mar 28, 2026

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Comment thread packages/worker/src/app/handlers/connect-secret.ts Outdated
Comment thread packages/worker/client/routes/connect-secret.tsx

@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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/worker/client/routes/connect-secret.tsx`:
- Around line 275-277: The cached closure variable session (and related state
like lastSearch/initVersion) is reused across retries, but generated UI sessions
expire after 60 minutes; on auth failures (401 or explicit session-expired),
clear the cached session and force a re-init so a fresh generated session is
minted instead of reusing the stale token. Concretely: inside handleErrorBack
and any error paths that detect 401/session-expired (also where session is
referenced around the other noted blocks), set session = null (and optionally
reset lastSearch or bump initVersion) and then route the flow to the existing
init logic that creates a new generated UI session so the subsequent retry uses
a fresh token.
- Around line 352-379: The rollback currently deletes the secret for all
failures; change the logic so rollbackSecretValue(params, session) is only
invoked when the secret was newly created (not when updating an existing
secret). Update the call site in the catch block of updateConnectorConfig to
check a creation flag (e.g., params.isNewSecret or a new createdSecretId) before
calling rollbackSecretValue, and if the connector was an update (existing
secret), skip deletion and setState to an error that notes connector-config
failed but the original secret was retained; if needed, extend
rollbackSecretValue to accept a flag like { deleteOnlyIfNew: true } or add a
helper (e.g., shouldRollbackSecret(params)) so rollbackSecretValue will not
delete secrets that were pre-existing. Ensure references to
updateConnectorConfig, rollbackSecretValue, params.connector (or new
params.isNewSecret/createdSecretId), and formatConnectorConfigFailureMessage are
updated accordingly.

In `@packages/worker/src/app/handlers/connect-secret.ts`:
- Around line 80-81: The code currently reads scope with readScope and trusts
the body value (sessionToken via readString), which allows unknown or mismatched
scopes to slip through; change readScope handling to fail closed by validating
the parsed scope against allowed values and returning a 400/error on unknown
values, and when handling POSTs that use sessionToken verify the requested scope
is compatible with the verified session (e.g., if session.app_id is null, reject
requests asking for 'app' scope, and if session.app_id is set ensure the scope
matches that app), updating the logic around the scope variable and the POST
handling to reject incompatible or misspelled scopes instead of silently falling
back to 'user'.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 66c34459-08cc-4ef6-b5ed-fd0195830d95

📥 Commits

Reviewing files that changed from the base of the PR and between 28b6f4e and 1dffc3b.

📒 Files selected for processing (6)
  • packages/worker/client/routes/connect-secret-errors.node.test.ts
  • packages/worker/client/routes/connect-secret-errors.ts
  • packages/worker/client/routes/connect-secret.tsx
  • packages/worker/src/app/handlers/connect-secret.ts
  • packages/worker/src/app/router.ts
  • packages/worker/src/app/routes.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/worker/client/routes/connect-secret-errors.node.test.ts
  • packages/worker/src/app/router.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/worker/src/app/routes.ts

Comment thread packages/worker/client/routes/connect-secret.tsx
Comment thread packages/worker/client/routes/connect-secret.tsx
Comment thread packages/worker/src/app/handlers/connect-secret.ts
@kentcdodds

Copy link
Copy Markdown
Owner Author

@cursoragent please take a look at the feedback on this pull request and address valid feedback.

@cursor

cursor Bot commented Mar 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Triaged the PR feedback and fixed the still-valid connect-secret issues: app-scoped sessions now require a real appId, invalid or mismatched scopes fail closed, and stale generated-UI session errors reinitialize the flow instead of reusing a bad token.connect-secret.ts:49-84 connect-secret.ts:137-164 connect-secret.tsx:157-164 connect-secret.tsx:294-335 connect-secret.tsx:406-412
  • Prevented destructive rollback on secret updates by only deleting newly created secrets when connector-config persistence fails, and clarified the failure copy for rolled-back, saved-only, and updated-secret-retained outcomes.connect-secret.tsx:370-402 connect-secret-errors.ts:1-18
  • Updated the /connect/secret capability guide to document appId for scope=app, and added focused node tests for the handler guards and connector-failure messaging.generated-ui-secret-guide.ts:52-76 connect-secret.node.test.ts:123-188 connect-secret-errors.node.test.ts:1-35

Testing

  • No manual UI testing: these are query-param, session, and error-path fixes with no meaningful visual change, so focused node tests plus typecheck/build were the highest-signal validation.
  • ⚠️ gh pr checks 86 (required GitHub checks are passing; only Cursor Bugbot is still pending)
  • ✅ npm exec vitest run --project node-unit packages/worker/client/routes/connect-secret-errors.node.test.ts packages/worker/src/app/handlers/connect-secret.node.test.ts
  • ✅ npm run typecheck
  • ✅ npm run build
Open in Web Open in Cursor 

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds
kentcdodds merged commit e95bb97 into main Mar 28, 2026
9 checks passed
@kentcdodds
kentcdodds deleted the cursor/connect-secret-page-8a3a branch March 28, 2026 21:52
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.

2 participants