Skip to content

Scope repo entity-source lookups by user in the query - #925

Merged
kody-bot merged 1 commit into
mainfrom
cursor/sentry-k1-kody-mcp-caller-errors-6045
Jul 24, 2026
Merged

kody-bot merged 1 commit into
mainfrom
cursor/sentry-k1-kody-mcp-caller-errors-6045

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Jul 24, 2026 •

Copy link
Copy Markdown
Owner

Summary

Review follow-up to #923, which merged before I could fold this in. CodeRabbit raised a valid point on that PR that I agree with.

resolveRepoSourceReference and repo_show_publish_note loaded an entity source by id and then compared source.user_id in application code:

const source = await getEntitySourceById(input.db, input.sourceId)
if (!source || source.user_id !== input.userId) throw ...

AGENTS.md asks for every read path to be scoped by userId, and the repo already has getEntitySourceByIdForUser for exactly this. #922 applied the same change to resolveOwnedPackageSource; these two were the remaining instances on caller-supplied ids.

Behaviour is unchanged — another user's source was already rejected. The difference is that it is now filtered by the query rather than fetched and then discarded, so there is no window where a row belonging to someone else is in hand.

Also adds coverage for the missing-identity branch of resolveRepoSourceReference (Repo source identity is required.), which #923 converted to McpCallerError without a test — CodeRabbit's nitpick on the same review, and a fair one.

Scope note

getEntitySourceById remains in use elsewhere (repo-session-do.ts, jobs/service.ts, package-runtime/**, and others). Those resolve ids from our own records rather than from caller input, and converting them is a broader change than this review point warrants. Left alone deliberately.

Validation

npm run validate green in full: format:check, lint (1 pre-existing warning in sentry-tunnel.node.test.ts, 0 errors), typecheck, 1295 unit tests across 400 files, 18 Playwright E2E, 2 MCP E2E, backup:build, primitives:check, migrations:check.

The repo_show_publish_note cross-user test now asserts the lookup returns nothing for the caller, rather than returning another user's row for the handler to reject — which is the actual contract after this change.

System recap — composes existing primitives (low risk)

Mode: recap · Base: main @ 28452280 · Head: 7085f365

Classification: composes — swaps two call sites onto an existing user-scoped data-access helper. No primitive changes shape or behaviour; no schema change.

Primitives touched

Primitive Group Impact
capability-registry assistant composes — repo target resolution and publish-note lookups use the user-scoped helper
d1-app-db storage composes — the user_id predicate moves into the entity_sources query

System map

Repo capabilities resolve a source through the user-scoped helper, so ownership is enforced by the query instead of a post-read comparison.

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
  capabilityRegistry["capability-registry<br/>Capability registry"]:::touched
  d1AppDb["d1-app-db<br/>D1 app database"]:::touched
  capabilityRegistry -->|"getEntitySourceByIdForUser filters entity_sources by user_id"| d1AppDb
  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

Invariants

Strengthens per-user isolation: entity_sources reads on caller-supplied ids now carry the userId predicate in SQL, so a row belonging to another user is never returned to application code on these paths.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • Bug Fixes
    • Improved repository source access checks to ensure sources are scoped to the requesting user.
    • Prevented unauthorized or missing sources from being resolved or accessed.
    • Added clearer validation when repository source identity information is missing.
  • Tests
    • Expanded coverage for user-scoped access, missing sources, authorization failures, session handling, and publishing workflows.

Review follow-up. resolveRepoSourceReference and repo_show_publish_note loaded
a source by id and then compared source.user_id in app code. Use the existing
getEntitySourceByIdForUser helper so the user predicate is part of the query,
matching what #922 did for resolveOwnedPackageSource. Behaviour is unchanged;
another user's source now simply is not returned rather than being returned
and rejected.

Also covers the missing-identity branch of resolveRepoSourceReference, which
the previous commit converted without a test.
@coderabbitai

coderabbitai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Repository capabilities now retrieve entity sources through the caller-scoped getEntitySourceByIdForUser helper. Tests update mocks and add coverage for missing source identity, ownership scoping, and unauthorized source handling.

Changes

Repository source ownership

Layer / File(s) Summary
User-scoped source resolution
packages/worker/src/mcp/capabilities/repo/repo-resolve-target.ts, packages/worker/src/mcp/capabilities/repo/repo-resolve-target.node.test.ts, packages/worker/src/mcp/capabilities/repo/repo-show-publish-note.ts, packages/worker/src/mcp/capabilities/repo/repo-show-publish-note.node.test.ts
Source resolution passes the caller’s user ID to getEntitySourceByIdForUser, preserves the not-found error, and tests missing identity and cross-user lookup behavior.
Repository capability test migration
packages/worker/src/mcp/capabilities/repo/repo-open-session.node.test.ts, packages/worker/src/mcp/capabilities/repo/repo-workflow.node.test.ts
Session and workflow tests update their hoisted mocks, module wiring, resets, and entity-source stubs to use the user-scoped lookup.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: scoping repo entity-source lookups by user.
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-k1-kody-mcp-caller-errors-6045

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.

@github-actions

Copy link
Copy Markdown
Contributor

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

Worker: kody-pr-925
D1: kody-pr-925-db
KV: kody-pr-925-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: 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/repo/repo-show-publish-note.node.test.ts`:
- Around line 140-143: Update the assertion for getEntitySourceByIdForUser in
the isolation test to verify the complete lookup input, including the caller’s
expected userId alongside source-1. Preserve the existing expectation that the
first argument is accepted and ensure the assertion fails when userId is omitted
or incorrect.
🪄 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 Plus

Run ID: 8342ebbb-c899-4bc1-886a-88bb3b0d6b9e

📥 Commits

Reviewing files that changed from the base of the PR and between 2845228 and 7085f36.

📒 Files selected for processing (6)
  • packages/worker/src/mcp/capabilities/repo/repo-open-session.node.test.ts
  • packages/worker/src/mcp/capabilities/repo/repo-resolve-target.node.test.ts
  • packages/worker/src/mcp/capabilities/repo/repo-resolve-target.ts
  • packages/worker/src/mcp/capabilities/repo/repo-show-publish-note.node.test.ts
  • packages/worker/src/mcp/capabilities/repo/repo-show-publish-note.ts
  • packages/worker/src/mcp/capabilities/repo/repo-workflow.node.test.ts

Comment on lines +140 to +143
expect(mockModule.getEntitySourceByIdForUser).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({ id: 'source-1' }),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Assert the caller’s userId in this isolation test.

The test only verifies id, so it would still pass if the lookup received an omitted or incorrect userId. Assert the complete scoped lookup contract.

As per coding guidelines, every Kody multi-user read path must be scoped by userId.

Proposed test fix
 expect(mockModule.getEntitySourceByIdForUser).toHaveBeenCalledWith(
 	expect.anything(),
-	expect.objectContaining({ id: 'source-1' }),
+	{ id: 'source-1', userId: 'user-1' },
 )
📝 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
expect(mockModule.getEntitySourceByIdForUser).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({ id: 'source-1' }),
)
expect(mockModule.getEntitySourceByIdForUser).toHaveBeenCalledWith(
expect.anything(),
{ id: 'source-1', userId: 'user-1' },
)
🤖 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/repo/repo-show-publish-note.node.test.ts`
around lines 140 - 143, Update the assertion for getEntitySourceByIdForUser in
the isolation test to verify the complete lookup input, including the caller’s
expected userId alongside source-1. Preserve the existing expectation that the
first argument is accepted and ensure the assertion fails when userId is omitted
or incorrect.

Source: Coding guidelines

@kody-bot
kody-bot merged commit 36edd71 into main Jul 24, 2026
5 checks passed
@kody-bot
kody-bot deleted the cursor/sentry-k1-kody-mcp-caller-errors-6045 branch July 24, 2026 22:32
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