Resolve platform scopes live in kody: package imports - #1337
Conversation
Static imports like 'kody:@kody/github/issues' now resolve from a platform account's current published version when the caller has no copy of their own (decision record 0014). Users get official helper packages with zero fork friction and operator fixes reach every ad hoc caller immediately. Bounds keeping isolation intact: - read-only source widening: only *which published source the bundler reads* changes; person-account scopes never resolve cross-user (structural account_type check) - resolved modules execute in the caller's runtime against the caller's secrets, storage grants, and entitlements - the caller's own copy always wins (fork-to-customize unchanged) - platform-owned dependency ids are excluded from packageStorage() grants, so live platform code stays stateless in the caller - static imports only: the dynamic hydration lane persists artifacts under the caller's identity, so platform targets get a teaching error - hidden platform packages resolve only for their owner - published-artifact fast path reads under the owner's identity Community fork policy follows: scanCrossScopeReferences accepts platform scopes so forks keep @kody/... references instead of rewriting them. Search surfacing is deferred (decision record): the package search plugin asserts caller ownership per row and vector scoring is per-user, so surfacing needs its own design. Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (6)
📝 WalkthroughWalkthroughPlatform accounts can provide live static package imports when callers lack local copies. Runtime loading preserves source ownership and excludes platform-owned storage grants. Search exposes platform packages, and community fork scanning preserves approved platform scopes. ChangesPlatform live packages
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant PackageImportResolution
participant PlatformPackageRegistry
participant ModuleGraph
participant StorageGrants
Caller->>PackageImportResolution: request static package import
PackageImportResolution->>PlatformPackageRegistry: resolve platform package
PlatformPackageRegistry-->>PackageImportResolution: package and source-owner metadata
PackageImportResolution->>ModuleGraph: load source under resolved owner
ModuleGraph->>StorageGrants: mark platform-owned dependency
StorageGrants-->>Caller: runtime graph without platform storage grant
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
Platform (built-in) packages now appear in search results alongside the caller's own packages, so agents discover them without knowing names in advance: - the search loader injects platform-account package rows (non-hidden, non-private) with a host-set platformScope marker; the caller's own copy of a name or kody id wins and replaces the platform row - the package plugin's ownership tripwire admits exactly those marked rows; unmarked foreign rows still fail the lane closed with the warning - slim matches and entity detail carry platformScope, and the next-step text tells agents the import resolves live with no fork needed - entity detail falls back to platform accounts when the caller owns no matching package; source and hosted-app URLs resolve under the platform owner - hydration loads package source under the record owner's id (identical for caller rows) - platform rows rank lexically only: the vector index is per-user, so platform packages have no vectors in the caller's namespace (noted in decision record 0014) Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7bb8e27. Configure here.
|
🔎 Preview deployed: https://kody-pr-1337.kody-a99.workers.dev Worker: Mocks:
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/worker/src/mcp/tools/search-entity-plugins/package.ts (1)
450-472: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse the platform owner for platform hosted URLs.
formatSlimMatchaddsplatformScope, buthostedUrlbelow still usesusername. For a platform package with an app, search returns a URL under the caller account instead of the platform account.Use
match.platformScope ?? usernameas the hosted URL owner.Proposed fix
const hostedAppOrigin = packageAppBaseUrl ?? baseUrl + const ownerUsername = match.platformScope ?? username const rootImportUsage = buildPackageRootImportUsage(match.name) @@ hostedUrl: - match.hasApp && username - ? buildPackageHostedUrl(hostedAppOrigin, username, match.kodyId) + match.hasApp && ownerUsername + ? buildPackageHostedUrl(hostedAppOrigin, ownerUsername, match.kodyId) : null,🤖 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/tools/search-entity-plugins/package.ts` around lines 450 - 472, Update hosted URL construction in formatSlimMatch to use match.platformScope ?? username as the owner, while preserving username for non-platform packages. Ensure platform packages with apps resolve URLs under the platform account.
🧹 Nitpick comments (1)
packages/worker/src/community/community-service.node.test.ts (1)
50-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExercise the allowlist at the
forkCommunityListingboundary.The mock returns
[]for every test, so the changed call inpackages/worker/src/community/service.tsnever receives a platform scope in this suite. The direct scanner test coversscanCrossScopeReferences, but it does not verify that the fork flow passes the database result through.Make
listPlatformAccountUsernamesconfigurable. Add a fork test with['kody']. Assert thatkody:@kody/...is omitted fromcrossScopeReferenceswhilekody:@owner/...remains reported.Suggested mock change
- listPlatformAccountUsernames: async () => [], + listPlatformAccountUsernames: vi.fn().mockResolvedValue([]),This verifies the fork-flow contract described in the PR objectives and the supplied downstream graph.
🤖 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/community/community-service.node.test.ts` around lines 50 - 53, Update the package-registry mock in the community service tests so listPlatformAccountUsernames is configurable per test, then add a forkCommunityListing test configured with ['kody']. Assert that kody:`@kody/`... is excluded from crossScopeReferences while kody:`@owner/`... remains reported, verifying the fork boundary passes the database allowlist through.
🤖 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 `@docs/use/packages.md`:
- Around line 147-156: Update the package-storage guidance in
docs/use/packages.md:147-156 so the declaring-package bucket rule explicitly
applies only to caller-owned packages, while platform-owned dependencies receive
no packageStorage() grant and fail closed. Repeat this no-grant and fail-closed
behavior in packages/worker/src/mcp/instructions/execute-tool-description.ts:17
within the sandbox guidance, preserving per-user isolation.
- Around line 147-156: Qualify live platform-package resolution by visibility
across all affected documentation and instruction text: in docs/use/packages.md
(147-156), describe only visible platform packages as live-resolvable and
discoverable in search; update execute-tool-description.ts (17-17) to replace
“for every user” with visibility-qualified wording; restrict the public-source
rationale in docs/contributing/decisions/0014-platform-live-packages.md (24-38)
to visible packages, explicitly state in (52-53) that hidden/private packages
remain owner-only, and clarify in docs/contributing/architecture/data-storage.md
(1331-1337) that callers without a local copy can resolve only visible platform
scopes, while preserving per-user isolation.
In `@packages/worker/src/mcp/tools/search-entity-plugins/package.ts`:
- Around line 227-236: The common scoring flow must keep platform package
ranking lexical-only. Update the logic around queryPackageVectorScores to
exclude platformScope rows from vector scoring, and assign those rows scores via
buildCandidateBaseScore({ lexical }) in every mode while preserving vector
scoring for non-platform rows.
In `@packages/worker/src/package-runtime/package-import-resolution.ts`:
- Around line 125-132: Update the platform-package resolution guard in the
visible resolver to return null when row is absent, hidden, or private by
checking row.isPrivate alongside row.hidden. Add a test that seeds a platform
package with is_private: 1 and verifies resolution returns null.
---
Outside diff comments:
In `@packages/worker/src/mcp/tools/search-entity-plugins/package.ts`:
- Around line 450-472: Update hosted URL construction in formatSlimMatch to use
match.platformScope ?? username as the owner, while preserving username for
non-platform packages. Ensure platform packages with apps resolve URLs under the
platform account.
---
Nitpick comments:
In `@packages/worker/src/community/community-service.node.test.ts`:
- Around line 50-53: Update the package-registry mock in the community service
tests so listPlatformAccountUsernames is configurable per test, then add a
forkCommunityListing test configured with ['kody']. Assert that kody:`@kody/`...
is excluded from crossScopeReferences while kody:`@owner/`... remains reported,
verifying the fork boundary passes the database allowlist through.
🪄 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: 4d804d20-1a14-4317-becf-44e7214bb8d4
📒 Files selected for processing (30)
docs/contributing/architecture/data-storage.mddocs/contributing/decisions/0014-platform-live-packages.mddocs/contributing/decisions/index.mddocs/use/packages.mdpackages/worker/src/community/community-flow-test-schema.tspackages/worker/src/community/community-service.node.test.tspackages/worker/src/community/fork-scan.node.test.tspackages/worker/src/community/fork-scan.tspackages/worker/src/community/service.tspackages/worker/src/mcp/capabilities/meta/search.node.test.tspackages/worker/src/mcp/instructions/execute-tool-description.tspackages/worker/src/mcp/run-kody-registry.tspackages/worker/src/mcp/tools/search-detail.node.test.tspackages/worker/src/mcp/tools/search-detail.tspackages/worker/src/mcp/tools/search-entity-plugins/package.tspackages/worker/src/mcp/tools/search-format-types.tspackages/worker/src/mcp/tools/search-handler.node.test.tspackages/worker/src/mcp/tools/search-loaders.tspackages/worker/src/mcp/tools/search-package-rows.tspackages/worker/src/mcp/tools/search-types.tspackages/worker/src/mcp/tools/search.node.test.tspackages/worker/src/package-registry/platform-packages.tspackages/worker/src/package-registry/scope-grants.tspackages/worker/src/package-runtime/module-graph-hydration.tspackages/worker/src/package-runtime/module-graph-import-rewriting.tspackages/worker/src/package-runtime/module-graph-workspace.tspackages/worker/src/package-runtime/module-graph.node.test.tspackages/worker/src/package-runtime/package-import-resolution.node.test.tspackages/worker/src/package-runtime/package-import-resolution.tspackages/worker/src/package-runtime/published-runtime-artifacts.ts
- private platform packages no longer resolve cross-user (isPrivate now checked alongside hidden at import resolution; search already excluded them) - platform search rows rank lexically in every mode: excluded from the Vectorize query and from the offline deterministic-embedding fallback, keeping online/offline ranking consistent with the documented contract - slim-match hostedUrl for platform packages with apps uses the platform account's username, matching entity detail - storage guidance in packages.md and the execute tool description now states platform-owned dependencies get no packageStorage() grant and fail closed Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

import gh from 'kody:@kody/github/issues'now works for every user without forking: when the caller has no package with that name and the scope's username belongs to a platform account (users.account_type = 'platform'), the import resolves live from the platform account's current published version — and platform packages appear in rankedsearchso agents discover them. Official helper packages ship once, update fleet-wide instantly for ad hoc callers, and never require codemodding thousands of forks. See decision recorddocs/contributing/decisions/0014-platform-live-packages.md.Isolation bounds (the important part)
account_type), not policy.packageStorage()grants (platformOwnedonBundleArtifactDependency), sopackageStorage()inside live platform code fails closed.platformScope; any other foreign row still fails the lane closed with the warning.What changed
resolveSavedPackageImportreturns a resolution (row,sourceOwnerUserId,platformScope) with the platform-scope fallback;ensurePackageLoaded, dependency recording, and the artifact fast path load under the resolved owner.platformScopeplus "no fork needed, resolves live" guidance, and entity detail falls back to platform accounts. Platform rows rank lexically only (the vector index is per-user); noted in the decision record for revisiting.scanCrossScopeReferencesgainsallowedForeignScopesand community fork passes the platform usernames, so forks keep@kody/...references instead of being told to rewrite them.data-storage.md,docs/use/packages.md, and the execute tool description.Testing
npm run validatefully green.packageStoragegrant exclusion for platform-owned deps, fork-scan allowlist behavior, and search ranking (platform row ranks withplatformScope; unmarked foreign rows still dropped with the tripwire warning).System recap — extends the packages primitive (medium risk)
Mode: recap · Base:
main@f84f38d6· Head:7bb8e27dClassification: extends — package import resolution gains a structural platform-scope lane and ranked search surfaces platform packages; no new primitive, the per-user isolation exception is documented in decision record 0014 as read-only source widening.
Primitives touched
packageskody:@imports; own copy winsmcp-servercapabilities-executeplatformOwned; storage grants exclude platform idscommunitySystem map
An agent searches "github", finds the
@kody/githubplatform package, and imports it: the bundler resolves the platform account's published source, the code runs in the caller's runtime, and storage grants exclude the platform package id.Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).
Invariants
account_type = 'platform'. Execution, secrets, storage, and entitlements stay caller-scoped; person-account scopes remain unrepresentable cross-user, and the search ownership tripwire admits only host-marked platform rows.Summary by CodeRabbit
New Features
Documentation