Skip to content

Enforce user-scoped Kody package names - #454

Merged
kentcdodds merged 4 commits into
mainfrom
cursor/enforce-package-user-scope-6071
May 12, 2026
Merged

kentcdodds merged 4 commits into
mainfrom
cursor/enforce-package-user-scope-6071

Conversation

@kentcdodds

@kentcdodds kentcdodds commented May 12, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Require saved Kody package names to use the authenticated user's username scope.
  • Apply the scope check to package_save, repo session checks/publish, repo command checks/publishes, and external package publish flows.
  • Add focused coverage for manifest validation, package save rejection before persistence, and package publish scope plumbing.

Testing

  • npx vitest run --project node-unit "packages/worker/src/package-registry/manifest.node.test.ts"
  • npx vitest run --project workers-unit "packages/worker/src/mcp/observability.workers.test.ts"
  • npx vitest run --project node-unit "packages/worker/src/mcp/capabilities/packages/publish-external-push.node.test.ts" "packages/worker/src/mcp/capabilities/repo/repo-workflow.node.test.ts"
  • npm run typecheck
  • npm run validate
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Enforced package scope: packages must match the authenticated user’s namespace during save, checks, and publishing (including external publishes and repo workflows).
  • Bug Fixes

    • Stricter validation to prevent mismatched scoped package names.
    • Expanded test coverage for scope validation and related publish/check flows.

Review Change Stack

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

coderabbitai Bot commented May 12, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c52dc2b-30eb-44b8-b777-97802b75c941

📥 Commits

Reviewing files that changed from the base of the PR and between 7ef2283 and 3ff1c5f.

📒 Files selected for processing (7)
  • packages/worker/src/mcp/capabilities/packages/publish-external-push.node.test.ts
  • packages/worker/src/mcp/capabilities/packages/save-package.ts
  • packages/worker/src/mcp/capabilities/repo/repo-run-commands.ts
  • packages/worker/src/mcp/capabilities/repo/repo-workflow.node.test.ts
  • packages/worker/src/mcp/observability.workers.test.ts
  • packages/worker/src/repo/repo-session-do.ts
  • packages/worker/src/repo/repo-session-rpc.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/worker/src/mcp/capabilities/packages/publish-external-push.node.test.ts
  • packages/worker/src/mcp/capabilities/repo/repo-workflow.node.test.ts
  • packages/worker/src/mcp/capabilities/repo/repo-run-commands.ts
  • packages/worker/src/mcp/observability.workers.test.ts
  • packages/worker/src/repo/repo-session-do.ts
  • packages/worker/src/repo/repo-session-rpc.ts

📝 Walkthrough

Walkthrough

Threads an optional expectedPackageScope (derived from the MCP user's DB row) through manifest parsing, repo checks, repo-session RPCs, and publish flows, and adds manifest scope validation plus updated tests/mocks asserting the scoped behavior.

Changes

Package scope validation and threading

Layer / File(s) Summary
User scope lookup and manifest validators
packages/worker/src/package-registry/user-scope.ts, packages/worker/src/package-registry/manifest.ts
Adds getMcpUserPackageScope to derive/normalize the MCP username from D1 and assertAuthoredPackageJsonNameScope plus optional expectedPackageScope support in parseAuthoredPackageJson to enforce manifest scope.
Manifest validation tests
packages/worker/src/package-registry/manifest.node.test.ts
Updates tests to pass expectedPackageScope into parseAuthoredPackageJson and assert failure when manifest scope doesn't match the expected user scope.
RPC payload type extensions
packages/worker/src/repo/repo-session-rpc.ts
Adds optional expectedPackageScope?: string to runCommands, runChecks, publishSession, and publishFromExternalRef RPC payload types.
Repo checks and external publish
packages/worker/src/repo/checks.ts, packages/worker/src/repo/external-publish.ts
runRepoChecks and publishFromExternalRef accept expectedPackageScope and forward it into parseAuthoredPackageJson.
RepoSession handlers and manifest reading
packages/worker/src/repo/repo-session-do.ts
readManifestFromWorkspace, runCommands, runChecks, publishSession, and publishFromExternalRef accept and forward expectedPackageScope for package entity kinds.
MCP capabilities scope lookup and threading
packages/worker/src/mcp/capabilities/packages/publish-external-push.ts, packages/worker/src/mcp/capabilities/repo/repo-run-checks.ts, packages/worker/src/mcp/capabilities/repo/repo-publish-session.ts, packages/worker/src/mcp/capabilities/repo/repo-run-commands.ts
Each capability imports getMcpUserPackageScope, computes expectedPackageScope from the MCP DB for package sessions, and forwards it to RPC/session calls when applicable.
Save package scope parsing
packages/worker/src/mcp/capabilities/packages/save-package.ts
package_save computes expectedPackageScope from DB and supplies it to parseAuthoredPackageJson when parsing the root package.json.
Tests and DB mocking
packages/worker/src/mcp/capabilities/repo/repo-workflow.node.test.ts, packages/worker/src/mcp/capabilities/packages/publish-external-push.node.test.ts, packages/worker/src/mcp/observability.workers.test.ts
Mocks now provide APP_DB.prepare().bind().first() returning user rows, fixtures are updated to @user/*, and test expectations assert expectedPackageScope in RPC calls and validate rejection for mismatched package scopes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

  • kentcdodds/kody#352: Extends external-publish flows and relates to publishFromExternalRef threading.
  • kentcdodds/kody#259: Earlier manifest validation work touching package-registry/manifest.ts.
  • kentcdodds/kody#306: Related repo checks flow changes affecting runRepoChecks and repo-session wiring.

Poem

🐰 I hop through DB and code so neat,
I fetch your username, trim and greet,
I bind the scope, I check the name,
So package scopes behave the same,
A tiny rabbit seals the feat!

🚥 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 'Enforce user-scoped Kody package names' directly and clearly describes the main objective of this pull request—requiring Kody packages to use the authenticated user's username scope.
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.

✏️ 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/enforce-package-user-scope-6071

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.

cursoragent and others added 2 commits May 12, 2026 18:58
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds
kentcdodds marked this pull request as ready for review May 12, 2026 19:22
@github-actions

github-actions Bot commented May 12, 2026 •

Copy link
Copy Markdown
Contributor

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

Worker: kody-pr-454
D1: kody-pr-454-db
KV: kody-pr-454-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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/worker/src/mcp/capabilities/packages/publish-external-push.node.test.ts (1)

158-167: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add an assertion for expectedPackageScope in publish RPC call.

The new behavior depends on forwarding scope, but this assertion block doesn’t verify it. Adding it will protect against regression of the enforcement wiring.

Test assertion tweak
 expect(mockModule.publishFromExternalRef).toHaveBeenCalledWith(
   expect.objectContaining({
     sourceId: 'source-1',
     userId: 'user-1',
     newCommit: 'commit-new',
     expectedHead: 'commit-new',
     allowForce: false,
     rebuildPackageArtifacts: false,
+    expectedPackageScope: 'user',
   }),
 )
🤖 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/packages/publish-external-push.node.test.ts`
around lines 158 - 167, Update the test assertion for
mockModule.publishFromExternalRef to also verify the forwarded package scope by
adding expectedPackageScope to the expect.objectContaining payload; inside the
expect(...) for publishFromExternalRef include expectedPackageScope: <the test's
forwarded scope value or the variable expectedPackageScope> so the RPC call
check covers scope forwarding as well.
packages/worker/src/mcp/capabilities/repo/repo-run-commands.ts (1)

83-90: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Scoped manifest validation is skipped for repo_run_commands check runs.

At Line 83, sessionRpc.runCommands runs checks without expectedPackageScope, while Line 107 only applies scope during publishSession. This means run_checks: true + publish: false can report passing checks without username-scope validation.

Suggested direction
+ const expectedPackageScope =
+   validatedSession.entity_type === 'package'
+     ? await getMcpUserPackageScope(ctx.env.APP_DB, user)
+     : undefined

  const result = await sessionRpc.runCommands({
    sessionId: validatedSession.id,
    userId: user.userId,
    commands: args.commands,
    dryRun: args.dry_run,
    runChecks: args.run_checks,
    publish: false,
+   expectedPackageScope,
  })

  // ...
  publish = await sessionRpc.publishSession({
    sessionId: validatedSession.id,
    userId: user.userId,
    rebuildPackageArtifacts: false,
-   expectedPackageScope:
-     validatedSession.entity_type === 'package'
-       ? await getMcpUserPackageScope(ctx.env.APP_DB, user)
-       : undefined,
+   expectedPackageScope,
  })

And in RepoSessionBase.runCommands, thread expectedPackageScope into this.runChecks(...) when checks are requested.

Also applies to: 107-110

🤖 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-run-commands.ts` around lines
83 - 90, The runCommands call in repo-run-commands.ts currently invokes
sessionRpc.runCommands({..., runChecks: args.run_checks, publish: false })
without passing expectedPackageScope, allowing check runs to skip
username-scoped manifest validation; update the call site to include
expectedPackageScope (the same scope used by publishSession) when
args.run_checks is true, and update RepoSessionBase.runCommands /
RepoSessionBase.runChecks to accept and thread an expectedPackageScope parameter
into this.runChecks(...) so scoped manifest validation is enforced during
non-publish check runs as well.
🧹 Nitpick comments (1)
packages/worker/src/mcp/capabilities/packages/save-package.ts (1)

12-17: ⚡ Quick win

Prefer a single validation path via parseAuthoredPackageJson({ expectedPackageScope }).

You can remove the extra post-parse assertion and let parse enforce scope directly to avoid duplicated validation paths.

Suggested refactor
-import {
-	assertAuthoredPackageJsonNameScope,
-	parseAuthoredPackageJson,
-} from '#worker/package-registry/manifest.ts'
+import { parseAuthoredPackageJson } from '#worker/package-registry/manifest.ts'
 import { getMcpUserPackageScope } from '#worker/package-registry/user-scope.ts'

 ...
-			const manifest = parseAuthoredPackageJson({
+			const expectedPackageScope = await getMcpUserPackageScope(
+				ctx.env.APP_DB,
+				user,
+			)
+			const manifest = parseAuthoredPackageJson({
 				content: packageJsonContent,
 				manifestPath: 'package.json',
+				expectedPackageScope,
 			})
-			assertAuthoredPackageJsonNameScope({
-				manifest,
-				expectedPackageScope: await getMcpUserPackageScope(
-					ctx.env.APP_DB,
-					user,
-				),
-				manifestPath: 'package.json',
-			})

Also applies to: 79-90

🤖 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/packages/save-package.ts` around lines
12 - 17, Replace the two-step scope validation (calling parseAuthoredPackageJson
then assertAuthoredPackageJsonNameScope) with a single call to
parseAuthoredPackageJson that enforces scope by passing expectedPackageScope
(computed via getMcpUserPackageScope) as an argument; remove usages of
assertAuthoredPackageJsonNameScope in save-package.ts and update both
occurrences (the initial parse block and the second block around lines 79-90) so
parseAuthoredPackageJson({ expectedPackageScope }) performs the scope check and
returns the parsed manifest used by buildSavedPackageEmbedText.
🤖 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.

Outside diff comments:
In
`@packages/worker/src/mcp/capabilities/packages/publish-external-push.node.test.ts`:
- Around line 158-167: Update the test assertion for
mockModule.publishFromExternalRef to also verify the forwarded package scope by
adding expectedPackageScope to the expect.objectContaining payload; inside the
expect(...) for publishFromExternalRef include expectedPackageScope: <the test's
forwarded scope value or the variable expectedPackageScope> so the RPC call
check covers scope forwarding as well.

In `@packages/worker/src/mcp/capabilities/repo/repo-run-commands.ts`:
- Around line 83-90: The runCommands call in repo-run-commands.ts currently
invokes sessionRpc.runCommands({..., runChecks: args.run_checks, publish: false
}) without passing expectedPackageScope, allowing check runs to skip
username-scoped manifest validation; update the call site to include
expectedPackageScope (the same scope used by publishSession) when
args.run_checks is true, and update RepoSessionBase.runCommands /
RepoSessionBase.runChecks to accept and thread an expectedPackageScope parameter
into this.runChecks(...) so scoped manifest validation is enforced during
non-publish check runs as well.

---

Nitpick comments:
In `@packages/worker/src/mcp/capabilities/packages/save-package.ts`:
- Around line 12-17: Replace the two-step scope validation (calling
parseAuthoredPackageJson then assertAuthoredPackageJsonNameScope) with a single
call to parseAuthoredPackageJson that enforces scope by passing
expectedPackageScope (computed via getMcpUserPackageScope) as an argument;
remove usages of assertAuthoredPackageJsonNameScope in save-package.ts and
update both occurrences (the initial parse block and the second block around
lines 79-90) so parseAuthoredPackageJson({ expectedPackageScope }) performs the
scope check and returns the parsed manifest used by buildSavedPackageEmbedText.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7d65a6d3-e69f-4a37-b24e-96310900c54f

📥 Commits

Reviewing files that changed from the base of the PR and between f2ddf85 and 7ef2283.

📒 Files selected for processing (15)
  • packages/worker/src/mcp/capabilities/packages/publish-external-push.node.test.ts
  • packages/worker/src/mcp/capabilities/packages/publish-external-push.ts
  • packages/worker/src/mcp/capabilities/packages/save-package.ts
  • packages/worker/src/mcp/capabilities/repo/repo-publish-session.ts
  • packages/worker/src/mcp/capabilities/repo/repo-run-checks.ts
  • packages/worker/src/mcp/capabilities/repo/repo-run-commands.ts
  • packages/worker/src/mcp/capabilities/repo/repo-workflow.node.test.ts
  • packages/worker/src/mcp/observability.workers.test.ts
  • packages/worker/src/package-registry/manifest.node.test.ts
  • packages/worker/src/package-registry/manifest.ts
  • packages/worker/src/package-registry/user-scope.ts
  • packages/worker/src/repo/checks.ts
  • packages/worker/src/repo/external-publish.ts
  • packages/worker/src/repo/repo-session-do.ts
  • packages/worker/src/repo/repo-session-rpc.ts

@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 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7ef2283. Configure here.

Comment thread packages/worker/src/repo/repo-session-do.ts
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds
kentcdodds merged commit 1211f40 into main May 12, 2026
5 checks passed
@kody-bot
kody-bot deleted the cursor/enforce-package-user-scope-6071 branch July 21, 2026 18:56
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