Skip to content

Keep confidential platform OAuth staging mistakes off Sentry - #1350

Merged
kody-bot merged 1 commit into
mainfrom
cursor/sentry-triage-kody-cloudflare-7662130627-a9fe
Aug 9, 2026
Merged

kody-bot merged 1 commit into
mainfrom
cursor/sentry-triage-kody-cloudflare-7662130627-a9fe

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Aug 9, 2026 •

Copy link
Copy Markdown
Owner

What

Follow-up to #1345 / Sentry KODY-CLOUDFLARE-4G: classify caller-fixable upsertPlatformOauthApp rejects as PlatformOauthAppValidationError, and re-wrap them as McpCallerError in admin_platform_oauth_app_save.

Why

The single production event was an agent enabling a confidential platform app without a client secret (release before #1345). Staging without a secret while enabled: false already works; enabling without a secret is still a valid reject, but it must not open Sentry issues that look like platform bugs and trip triage.

Testing

  • Node unit: confidential secret lifecycle asserts PlatformOauthAppValidationError
  • Node unit: capability path asserts McpCallerError for enable-without-secret (default and staged→enable)
System recap — composes existing primitives (low risk)

Mode: recap · Base: main @ 9faafa09 · Head: 307b0445

Classification: composes — wires the existing McpCallerError / caller-failure observability path onto platform OAuth app input validation; no new primitives or auth semantics.

Primitives touched

Primitive Group Impact
integrations assistant composes — typed validation error for secretless confidential enable
rbac auth composes — admin save capability re-wraps validation as McpCallerError

System map

Admin MCP save validates platform OAuth apps and keeps staging mistakes off Sentry.

Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).

flowchart LR
	rbac["rbac<br/>Admin MCP save"]:::touched
	integrations["integrations<br/>Platform OAuth apps"]:::touched
	rbac -->|"upsert + wrap validation"| integrations
	classDef touched fill:#1a7f37,color:#fff
	classDef extended fill:#9a6700,color:#fff
	classDef added fill:#cf222e,color:#fff
	classDef untouched fill:#57606a,color:#fff
Loading
Open in Web Open in Cursor 

Summary by CodeRabbit

  • Bug Fixes
    • Improved validation for platform OAuth app settings, including required identifiers, URLs, and client secrets.
    • Prevented confidential OAuth apps from being enabled without a client secret.
    • Displayed clearer, actionable errors when OAuth app configuration is invalid.
    • Preserved the ability to save apps in a disabled state while configuration is completed.
    • Recorded failed OAuth app enablement attempts in the audit log.

Throw PlatformOauthAppValidationError for caller-fixable upsert
rejects, and re-wrap them as McpCallerError in
admin_platform_oauth_app_save so agent enable-without-secret mistakes
stay on mcp-event lines instead of opening Sentry triage issues.

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

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds a typed platform OAuth validation error. The admin save handler converts these validation failures into McpCallerError instances and adds coverage for confidential-app save and audit behavior.

Changes

Platform OAuth validation

Layer / File(s) Summary
Typed platform OAuth validation
packages/worker/src/integrations/platform-apps.ts, packages/worker/src/integrations/platform-apps.node.test.ts
upsertPlatformOauthApp now throws PlatformOauthAppValidationError for invalid OAuth app input. Integration tests assert the typed error.
MCP caller error translation
packages/worker/src/mcp/capabilities/admin/admin-platform-oauth-app-save.ts, packages/worker/src/mcp/capabilities/admin/admin-platform-oauth-app-capabilities.node.test.ts
The save handler maps validation errors to McpCallerError and preserves unrelated errors. Tests cover disabled staging, failed enabling, and audit-log entries.

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

Sequence Diagram(s)

sequenceDiagram
  actor Admin as Admin MCP caller
  participant SaveHandler as admin-platform-oauth-app-save
  participant Upsert as upsertPlatformOauthApp
  participant McpError as McpCallerError
  Admin->>SaveHandler: Save platform OAuth app
  SaveHandler->>Upsert: Upsert OAuth app
  Upsert-->>SaveHandler: PlatformOauthAppValidationError
  SaveHandler->>McpError: Wrap validation error as caller error
  SaveHandler-->>Admin: McpCallerError
Loading

Possibly related PRs

  • kentcdodds/kody#1343: Adds the admin platform integration save flow that this PR extends with typed OAuth validation errors.
  • kentcdodds/kody#1345: Directly relates to confidential-app validation in upsertPlatformOauthApp.
  • kentcdodds/kody#1203: Introduces similar McpCallerError handling for caller-fixable validation failures.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly states the main change: preventing confidential platform OAuth staging errors from reaching Sentry.
Description check ✅ Passed The description explains the intent, changes, rationale, testing, and system impact, although it uses What and Why instead of Intent and Summary headings.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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/sentry-triage-kody-cloudflare-7662130627-a9fe

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.

@kentcdodds
kentcdodds marked this pull request as ready for review August 9, 2026 22:05

@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
`@packages/worker/src/mcp/capabilities/admin/admin-platform-oauth-app-capabilities.node.test.ts`:
- Around line 201-205: Remove the duplicate `.all()` invocation from the
auditSqlite query in the failures initialization, so the prepared statement
calls `.all()` exactly once and its returned array is directly cast to the
expected type.
🪄 Autofix

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 Plus

Run ID: 966d545a-f4c8-4123-806d-c5108e83c3e7

📥 Commits

Reviewing files that changed from the base of the PR and between 9faafa0 and 307b044.

📒 Files selected for processing (4)
  • packages/worker/src/integrations/platform-apps.node.test.ts
  • packages/worker/src/integrations/platform-apps.ts
  • packages/worker/src/mcp/capabilities/admin/admin-platform-oauth-app-capabilities.node.test.ts
  • packages/worker/src/mcp/capabilities/admin/admin-platform-oauth-app-save.ts

Comment on lines +201 to +205
const failures = auditSqlite
.prepare(
`SELECT action, result FROM audit_events WHERE result = 'failure' ORDER BY id ASC`,
)
.all() as Array<{ action: string; result: string }>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Remove the duplicate .all() call.

Line 205 calls .all() on the array returned by the call above. Array has no .all() method. This prevents the test file from type checking.

Proposed fix
 	const failures = auditSqlite
 		.prepare(
 			`SELECT action, result FROM audit_events WHERE result = 'failure' ORDER BY id ASC`,
 		)
 		.all() as Array<{ action: string; result: string }>
-		.all() as Array<{ action: string; result: string }>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const failures = auditSqlite
.prepare(
`SELECT action, result FROM audit_events WHERE result = 'failure' ORDER BY id ASC`,
)
.all() as Array<{ action: string; result: string }>
const failures = auditSqlite
.prepare(
`SELECT action, result FROM audit_events WHERE result = 'failure' ORDER BY id ASC`,
)
.all() as Array<{ action: string; result: string }>
🤖 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
`@packages/worker/src/mcp/capabilities/admin/admin-platform-oauth-app-capabilities.node.test.ts`
around lines 201 - 205, Remove the duplicate `.all()` invocation from the
auditSqlite query in the failures initialization, so the prepared statement
calls `.all()` exactly once and its returned array is directly cast to the
expected type.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-1350.kody-a99.workers.dev

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

Mocks:

@kody-bot
kody-bot merged commit 38337a8 into main Aug 9, 2026
18 checks passed
@kody-bot
kody-bot deleted the cursor/sentry-triage-kody-cloudflare-7662130627-a9fe branch August 9, 2026 22:12
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.

3 participants