Skip to content

Deslop round 2: real bug fixes — env binding stripping, D1 param limit, silent catches, missing 401 handling - #672

Merged
kentcdodds merged 11 commits into
mainfrom
cursor/deslop-round-two-4ed0
Jul 8, 2026
Merged

kentcdodds merged 11 commits into
mainfrom
cursor/deslop-round-two-4ed0

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Jul 8, 2026 •

Copy link
Copy Markdown
Owner

Summary

Round two of the AI-slop audit (follow-up to #668). This round is mostly behavior fixes rather than pure deduplication: silent failure paths, an env-schema bug that stripped Cloudflare bindings, a D1 bound-parameter limit bug on admin pages, and a repeated failed-load retry bug across seven client routes. A final round-4 sweep (after merging main with #669) added fixes in memory search, email storage, and jobs.

High-severity fixes

  • Env schema stripped non-schema bindings (packages/worker/src/app/env.ts): getEnv returned parseSafe(EnvSchema, env).value, which drops any binding not listed in the schema — including REPO_SESSION, OAUTH_PROVIDER, REMOTE_CONNECTOR_SESSION, and ASSETS. Account deletion was silently failing to purge repo sessions and revoke OAuth grants because handlers saw undefined bindings behind as unknown as Env casts. getEnv now validates in place and returns the original Env; router.ts and ~10 handler factories drop their AppEnv → Env casts and take Env directly.
  • D1 too many SQL variables on full admin pages: pageSize=100 made loadCurrentMonthRollups bind 101 parameters (100 user ids + month), over D1's 100-parameter cap, so /admin/usage.json?pageSize=100 returned 500. New @kody-internal/shared/chunk.ts (chunkArray + maxD1BoundParameters) chunks the IN (...) lists here and in loadRolesByUserIds.
  • Same D1 overflow in memory search (round 4): the vectorize-first path from Scale hardening: R2 email blobs, derived usage rollups, bounded cron/DO work, cheap search paths #669 hydrates up to 100 vector hits via listMemoriesByIds, which binds 103–104 parameters (userId + ids + statuses) — semantic matches on older memories would fail the whole search. Now chunked with headroom for the fixed bindings.
  • Admin user creation could lose stable_user_id (admin-user-creation.ts): the follow-up UPDATE ... .catch(() => undefined) meant a user could be created with no stable id and no error. The INSERT now sets stable_user_id directly.
  • Failed-load retry bug in 7 client routes: lastLoadedHref was assigned before the fetch, so a failed load latched the URL and revisiting the route never retried. New #client/route-load-latch.ts (with unit tests) marks a URL loaded only on success; applied to account, account-integrations, account-mcp-servers, account-remote-connectors, account-package-invocation-tokens, account-two-factor, account-passkeys. Per Bugbot's review: a one-shot stale-refresh signal (same-path reload whose loader failed) now overrides the failure latch instead of being blocked by it.

Silent-failure and error-handling fixes

  • Legacy stable_user_id fallbacks in entitlements/service.ts and email/platform-address.ts caught all D1 errors; now they only fall back on the known missing-column error and rethrow everything else.
  • email/inbound.ts audit-trail writes used .catch(() => undefined) seven times; failures are now logged (warnRejectionAuditWriteFailed).
  • email/repo.ts (round 4): deleteEmailMessageById swallowed D1 read failures with .catch(() => null) before deleting the row — a transient error would orphan the raw-MIME R2 blob forever. The read now propagates so the delete aborts and can retry.
  • package-service.ts no longer clears alarm state in memory when deleteAlarm() fails.
  • mcp/tools/execute.ts gets an outer error boundary so setup failures return a structured MCP error instead of an unhandled rejection; run-kody-registry.ts warns instead of silently hiding missing MCP servers.
  • Corrupt stored JSON no longer fails whole responses: community/snapshot.ts treats bad KV snapshots as a cache miss; tags_json parsing centralized in @kody-internal/shared/tags-json.ts; (round 4) email/repo.ts address/header columns, jobs/repo.ts schedule/params/history columns, and memory tags_json/source_uris_json all degrade to safe defaults instead of throwing on one bad row.
  • mcp/tools/search.ts value-entity detail no longer reports false "not found" from a stale in-memory snapshot; falls back to a direct getValue.

Auth/session correctness

  • handlers/verify.ts forwarded raw redirectTo (open-redirect shape); now normalized via the shared normalizeRedirectTo.
  • Missing 401 → /login redirects added: passkey register/delete, community report submit, admin invites/community-reports mutations, and all six secrets.json POSTs in connect-oauth.tsx; 2FA cancel no longer continues after a 401.
  • updated_at writes in account-profile.ts / password-reset.ts now use shared utcSqliteTimestamp instead of two hand-rolled .replace('T', ' ').slice(0, 19) copies.

Dedupe / tooling

  • Shared displayNameFromEmail, readPagination, parseTagsJson, seed-SQL builders (tools/seed-sql.ts), consolidated readiness waits in tools/mcp-test-support.ts, deduped signup/login in e2e/playwright-utils.ts (with the WebAuthn localhost cookie requirement now documented), fail helper deduped in CI tools, clean exit code on signal shutdown in wrangler-env.ts, community/repo.ts local chunkValues replaced with shared chunkArray.

Notes for review

System recap — extends app-ui/entitlements error contracts (medium risk)

Mode: recap · Base: main @ 924c6246 · Head: 90a82d15

Classification: extends — no new primitives, but app-ui's env handling and several error contracts change behavior (fail-closed instead of fail-silent). One new shared utility module (chunk.ts), not a system primitive.

Primitives touched

Primitive Group Impact
app-ui surfaces extends — getEnv returns full Env (bindings no longer stripped); handlers take Env directly; 401 redirects and load-latch fixes in client routes
entitlements auth extends — legacy fallback narrowed to missing-column errors only
email assistant extends — audit write failures logged; blob-key read no longer swallowed on delete; stored-JSON parses guarded
mcp-server surfaces extends — execute tool gains outer error boundary; search value detail falls back to live read
memories assistant composes — vector-hit hydration chunked to D1 parameter cap; stored-JSON parses guarded
jobs assistant composes — stored-JSON parses guarded
usage-metering runtime composes — rollup reads chunked to D1 parameter cap (keeps #669's KV cache)
rbac auth composes — role lookups chunked to D1 parameter cap
account-export assistant composes — deletion/export now sees REPO_SESSION / OAUTH_PROVIDER bindings
d1-app-db storage composes — no schema change; queries chunked

System map

flowchart LR
	appUi["app-ui"]:::extended
	entitlements["entitlements"]:::extended
	email["email"]:::extended
	mcpServer["mcp-server"]:::extended
	memories["memories"]:::touched
	jobs["jobs"]:::touched
	usageMetering["usage-metering"]:::touched
	rbac["rbac"]:::touched
	accountExport["account-export"]:::touched
	d1AppDb["d1-app-db"]:::untouched
	shared["@kody-internal/shared (chunk, tags-json, date-keys)"]:::touched
	appUi --> entitlements
	appUi --> accountExport
	appUi --> d1AppDb
	usageMetering --> d1AppDb
	rbac --> d1AppDb
	memories --> d1AppDb
	jobs --> d1AppDb
	mcpServer --> shared
	email --> 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

Per-user isolation untouched: no query, Durable Object id, or vector path changed its userId scoping. The env fix strengthens account-deletion guarantees (sessions purged, OAuth grants revoked — previously silently skipped).

Testing

  • ✅ npm run validate — format:check, lint, typecheck, 699 unit tests (205 files), Playwright E2E, MCP E2E all green (run after merging latest main, including Scale hardening: R2 email blobs, derived usage rollups, bounded cron/DO work, cheap search paths #669's rollup caching, and again after the round-4 fixes; one flaky E2E run passed clean on retry and Nx flagged the task as flaky)
  • ✅ New unit tests: packages/shared/src/chunk.node.test.ts, packages/worker/client/route-load-latch.node.test.ts (including the stale-refresh-vs-failure-latch case from Bugbot's review)
  • ✅ Reproduced the D1 too many SQL variables failure via /admin/usage.json?pageSize=100 before the chunking fix; green after
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Added shared pagination handling for admin screens and chunked large IN (...) queries to respect D1 limits.
    • Introduced route load latch coordination for more reliable client refreshes during navigation and stale-data cases.
    • Added shared utilities for UTC SQLite timestamps and safer tags parsing.
  • Bug Fixes

    • Expired/unauthorized (401) flows now redirect to login more consistently across multiple pages/actions.
    • Corrupt stored JSON and snapshot payloads no longer break rendering, degrading safely instead.
  • Tests

    • Added/updated unit and E2E coverage for new chunking and route-load latch behaviors.
  • Chores

    • Improved warnings/logging and consolidated shared SQL/seeding helpers.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026 •

Copy link
Copy Markdown

Review Change Stack

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: 84e8b466-281c-4a10-863e-dfc998793446

📥 Commits

Reviewing files that changed from the base of the PR and between 90a82d1 and 73de898.

📒 Files selected for processing (6)
  • packages/worker/client/route-load-latch.node.test.ts
  • packages/worker/client/route-load-latch.ts
  • packages/worker/src/mcp/tools/execute.ts
  • tools/mcp-test-support.ts
  • tools/seed-sql.ts
  • tools/seed-test-data.node.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/worker/client/route-load-latch.node.test.ts
  • packages/worker/src/mcp/tools/execute.ts
  • tools/mcp-test-support.ts
  • packages/worker/client/route-load-latch.ts

📝 Walkthrough

Walkthrough

This PR adds a route-load latch for account client routes, introduces 401-based login redirects in several client actions, migrates worker handlers from AppEnv to Env, centralizes shared chunking/pagination/JSON/timestamp helpers, consolidates E2E seed SQL and auth setup, refactors MCP search/execute paths, and hardens multiple resilience and tooling flows.

Changes

Client Route Load Latch & 401 Redirects

Layer / File(s) Summary
Route load latch module and tests
packages/worker/client/route-load-latch.ts, packages/worker/client/route-load-latch.node.test.ts
New createRouteLoadLatch tracks loaded/failed/seen hrefs and exposes needsLoad, covered by tests for navigation, failure, and stale-refresh scenarios.
Latch wiring in account, integrations, mcp-servers routes
packages/worker/client/routes/account.tsx, packages/worker/client/routes/account-integrations.tsx, packages/worker/client/routes/account-mcp-servers.tsx
Route components use loadLatch instead of lastLoadedHref to gate loads and record success/failure.
Latch wiring in tokens/passkeys/remote-connectors/two-factor routes
packages/worker/client/routes/account-package-invocation-tokens.tsx, packages/worker/client/routes/account-passkeys.tsx, packages/worker/client/routes/account-remote-connectors.tsx, packages/worker/client/routes/account-two-factor.tsx
Applies the same latch pattern plus 401/null-payload guards in two-factor and passkeys handlers.
Admin invites request guard and 401 handling
packages/worker/client/routes/admin-invites.tsx
Adds loadRequestId race-guard and 401-redirect on admin actions.
401 redirects in reports, community-detail, connect-oauth
packages/worker/client/routes/admin-community-reports.tsx, packages/worker/client/routes/community-detail.tsx, packages/worker/client/routes/connect-oauth.tsx
Multiple fetch flows now redirect to /login on 401 instead of continuing generic error handling.

Worker AppEnv → Env Migration

Layer / File(s) Summary
getEnv, handler bundle, and router wiring
packages/worker/src/app/env.ts, packages/worker/src/app/handler.ts, packages/worker/src/app/router.ts
getEnv validates and returns the raw Env; router/handler typing switches from AppEnv casts to Env.
Handler-level env updates
packages/worker/src/app/handlers/*.ts, packages/worker/src/app/email-change.ts, packages/worker/src/app/email-verification.ts, packages/worker/src/app/auth-redirect.ts
Individual handlers accept env: Env directly and use env.APP_DB/env.COOKIE_SECRET/env.CLOUDFLARE_*.
Shared display-name helper
packages/worker/src/app/username.ts, packages/worker/src/app/request-auth-cache.ts, packages/worker/src/mcp-auth-user-context.ts
displayNameFromEmail replaces local implementations.

Shared Utilities & Consumers

Layer / File(s) Summary
chunk/date/tags/pagination utilities
packages/shared/src/chunk.ts, packages/shared/src/chunk.node.test.ts, packages/shared/src/date-keys.ts, packages/shared/src/tags-json.ts, packages/worker/src/app/query-params.ts
New chunkArray, maxD1BoundParameters, utcSqliteTimestamp, parseTagsJson, readPagination.
Admin loaders adopt pagination/chunking
packages/worker/src/app/admin-usage-data.ts, packages/worker/src/app/admin-users-data.ts, packages/worker/src/app/admin-system-email-data.ts
D1 pagination and IN (...) chunking use shared helpers.
stable_user_id set at user creation
packages/worker/src/app/admin-user-creation.ts
INSERT now includes stable_user_id, removing the follow-up update.
parseTagsJson/chunkArray/utcSqliteTimestamp consumers
packages/worker/src/community/repo.ts, packages/worker/src/package-registry/repo.ts, packages/worker/src/package-registry/service.ts, packages/worker/src/app/handlers/account-profile.ts, packages/worker/src/mcp/memory/repo.ts
Local implementations replaced by shared helpers.

E2E Seed SQL & Auth Flow

Layer / File(s) Summary
Shared seed SQL builders
tools/seed-sql.ts, e2e/d1-utils.ts, tools/seed-test-data.ts, tsconfig-tools.json, tools/mcp-test-support.ts
buildRoleAssignmentSql/buildSeedUserSql centralize seeding SQL.
E2E primary user provisioning simplification
e2e/auth-test-user.ts, e2e/playwright-utils.ts, e2e/smoke.spec.ts, e2e/ssr-hydration.spec.ts, e2e/community-frames.spec.ts
ensurePrimaryUserExists() drops its request param; signupOrLoginViaAuth centralizes /auth fallback.
MCP dev-server readiness refactor
tools/mcp-test-support.ts
Single waitForHttpReady() replaces two prior polling helpers.

MCP Search/Execute Refactor

Layer / File(s) Summary
Exported loadSearchRowsAndRegistry
packages/worker/src/mcp/tools/search.ts
New env/callerContext-based signature plus direct getValue fallback.
Meta search delegation
packages/worker/src/mcp/capabilities/meta/search.ts
Delegates to the shared helper instead of local assembly.
Execute tool error wrapping
packages/worker/src/mcp/tools/execute.ts
Outer try/catch converts setup errors into structured MCP error responses.

Worker Resilience Fixes

Layer / File(s) Summary
Entitlements cache bounding & fallback tightening
packages/worker/src/entitlements/service.ts, packages/worker/src/email/platform-address.ts
Bounded cache eviction; legacy fallback restricted to missing-column errors.
Inbound email audit logging
packages/worker/src/email/inbound.ts
Silent audit-write failures now logged via warnRejectionAuditWriteFailed.
JSON parsing hardening & error propagation
packages/worker/src/community/snapshot.ts, packages/worker/src/email/repo.ts, packages/worker/src/jobs/repo.ts, packages/worker/src/mcp/memory/json-string-array.ts, packages/worker/src/mcp/run-kody-registry.ts, packages/worker/src/package-runtime/package-service.ts
Corrupt JSON degrades gracefully; some previously-swallowed errors now propagate or log.

Dev Tooling

Layer / File(s) Summary
cli.ts mock server simplification
cli.ts
Removes attachOptionalMocksInParallel; awaits attachCloudflareMock directly; adjusts announce logic.
Shared fail() helper & shutdown exit code
tools/ci/sync-worker-secrets.ts, wrangler-env.ts
Imports shared fail(); signal-triggered shutdown now exits 0.

Estimated code review effort: 4 (Complex) | ~75 minutes

Possibly related PRs

  • kentcdodds/kody#451: Both change the E2E primary-user seeding path in e2e/auth-test-user.ts.
  • kentcdodds/kody#605: Both modify packages/worker/src/app/env.ts's getEnv logic.
  • kentcdodds/kody#608: Both modify client-side account route hydration/load-queuing logic in packages/worker/client/routes/account-*.tsx.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is specific and accurately reflects the main bug-fix themes in the changeset.
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/deslop-round-two-4ed0

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 July 8, 2026 09:41
Comment thread packages/worker/client/route-load-latch.ts
@github-actions

github-actions Bot commented Jul 8, 2026 •

Copy link
Copy Markdown
Contributor

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

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

Mocks:

…memory hydration IN list, guard stored-JSON parses (email, jobs, memory), stop orphaning R2 blobs on delete, reuse shared chunkArray
try {
const href = readCurrentRouterHref(handle)
const search = new URL(href, 'http://localhost').search
lastLoadedHref = href

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.

401 load leaves retry loop

Low Severity

New 401 handlers redirect to login and return without resetting in-flight mutation state. actionState stays 'acting' and reportState stays 'submitting', so buttons stay disabled if the redirect is slow or blocked.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 90a82d1. Configure here.

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

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/email/repo.ts (1)

905-923: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Delete the raw MIME blob before removing the row.

This still deletes the DB row before a best-effort R2 delete. If input.blobs.delete(rawMimeKey) fails, the row is gone and the raw MIME key is no longer retryable, orphaning sensitive email content. This contradicts the retention policy used in packages/worker/src/email/system-email.ts:264-285.

Proposed fix
-	await input.db
-		.prepare(`DELETE FROM email_messages WHERE id = ?`)
-		.bind(input.messageId)
-		.run()
 	if (rawMimeKey != null && input.blobs) {
-		await input.blobs.delete(rawMimeKey).catch((error: unknown) => {
-			console.warn('email-raw-mime-blob-delete-failed', rawMimeKey, error)
-		})
+		await input.blobs.delete(rawMimeKey)
 	}
+	await input.db
+		.prepare(`DELETE FROM email_messages WHERE id = ?`)
+		.bind(input.messageId)
+		.run()
🤖 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/email/repo.ts` around lines 905 - 923, Delete the raw
MIME blob before removing the `email_messages` row in the delete flow inside
`deleteEmailMessage` (the block that reads `raw_mime_key` and calls
`input.blobs.delete`). Reorder the operations so the R2 delete happens first and
only proceed with the SQL `DELETE FROM email_messages` after the blob removal
succeeds; keep the row lookup/guard around `input.blobs` and preserve the
best-effort warning log for blob delete failures so the delete remains retryable
if the blob removal errors.
packages/worker/client/routes/account-package-invocation-tokens.tsx (1)

399-408: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Ignore failures from stale token loads before updating the current view.

The success path drops results after the URL changes, but the catch path still sets error UI and markFailed(href) for the old token route.

🐛 Proposed fix
 		} catch (error) {
 			if (signal.aborted) return
 			if (loadStartedAtMutationVersion !== mutationVersion) return
+			if (href !== readCurrentRouterHref(handle)) return
 			status = 'error'
 			message =
 				error instanceof Error
 					? error.message
 					: 'Unable to load package invocation tokens.'
🤖 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/client/routes/account-package-invocation-tokens.tsx` around
lines 399 - 408, The stale-load guard in the token loading catch path is
incomplete, so old route failures still update the current error UI and call
loadLatch.markFailed(href). Update the error handling in the token loader to
mirror the success-path check by bailing out before setting status/message or
marking failed when the loadStartedAtMutationVersion no longer matches
mutationVersion, and keep the existing signal.aborted guard in the same flow.
🧹 Nitpick comments (1)
packages/worker/src/package-runtime/package-service.ts (1)

397-406: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

clearAlarm error propagation in finalizeServiceRun path gets effectively swallowed.

The change is correct — if deleteAlarm() fails, the in-memory state (lines 400-402) is not cleared, keeping the snapshot accurate. However, when clearAlarm() is called from finalizeServiceRun (line 475) within runServiceInBackground, a thrown error falls into the catch block (line 558), which calls finalizeServiceRun again — but that call early-returns because currentRunId was already nulled (line 453). The error is lost in this path.

This is a pre-existing architectural concern (not introduced by this change — previously the error was swallowed by .catch() and the in-memory state was incorrectly cleared). The new behavior is strictly better. Consider adding a console.warn or structured log when clearAlarm() throws so the stale-alarm condition is at least observable.

🤖 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/package-runtime/package-service.ts` around lines 397 -
406, The clearAlarm failure path in finalizeServiceRun is still effectively
silent when runServiceInBackground catches the error and retries
finalizeServiceRun, so add an explicit warning/log at the clearAlarm call site
or inside clearAlarm itself to surface deleteAlarm failures. Use the package
service methods clearAlarm, finalizeServiceRun, and runServiceInBackground to
place the log where the error is first thrown, and include enough context to
identify the stale-alarm condition without changing the existing error
propagation behavior.
🤖 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/client/route-load-latch.ts`:
- Around line 21-23: The route load latch currently only records failures in
markFailed() and leaves lastLoadedHref stale, so a failed refresh can keep a
route incorrectly marked as already loaded. Update route-load-latch.ts so the
failure path invalidates the loaded href state as well, and add a regression
test covering markLoaded('/a'), markFailed('/a'), navigating to '/b', then back
to '/a' where needsLoad() should return true. Use the existing needsLoad(),
markLoaded(), and markFailed() flow to verify the latch resets correctly after a
failed refresh.

In `@packages/worker/src/mcp/tools/execute.ts`:
- Around line 179-199: The outer error handling in execute() is classifying
every thrown failure as a platform sandbox failure, but bundling the
user-provided code in runModuleWithRegistry can throw and should be treated as a
user-code error. Update the execute tool flow so bundling failures are converted
into the existing result.error path, or explicitly detect bundling-related
throws before the outer catch, and keep sandboxError false only for true
platform/setup failures. Use the execute() wrapper, runModuleWithRegistry, and
the result.error handling path to locate the fix.
- Around line 311-329: The success event is being emitted before response
formatting in execute(), so a later failure in limitExecutionResultValue() can
leave a false success log. Move the logMcpEvent call in execute() to after the
response payload has been fully formatted, ideally after
limitExecutionResultValue() and raw content extraction succeed, so the success
outcome is only recorded once the return data is ready.

In `@tools/mcp-test-support.ts`:
- Around line 478-480: The readiness check currently only respects the global
deadline before calling fetch, so a stalled response can hang past
defaultWaitTimeoutMs. Update the readiness helper that performs await
fetch(input.url) and input.isReady(response) to bound each fetch attempt with
its own timeout or abort signal derived from the remaining deadline, and make
sure the per-attempt timeout is enforced even after the TCP connection is
established.

In `@tools/seed-sql.ts`:
- Around line 30-32: The seed SQL generated by the SQL builder in
tools/seed-sql.ts is missing stable_user_id, so update the insert logic in the
seed helper that builds the users VALUES statement to include the derived stable
user ID alongside username, email, password_hash, and email_verified_at. Make
sure the same deterministic value used by the signup path is included in the
seed output so tool/E2E fixtures match the production schema and no longer
depend on the legacy fallback.

In `@tsconfig-tools.json`:
- Line 40: Remove the inline comment from the JSON in tsconfig-tools.json so the
file remains valid for Biome parsing and static analysis. Update the JSON entry
directly where the comment appears, keeping the surrounding tsconfig-tools
configuration intact and preserving the referenced modules/settings without any
comment text.

---

Outside diff comments:
In `@packages/worker/client/routes/account-package-invocation-tokens.tsx`:
- Around line 399-408: The stale-load guard in the token loading catch path is
incomplete, so old route failures still update the current error UI and call
loadLatch.markFailed(href). Update the error handling in the token loader to
mirror the success-path check by bailing out before setting status/message or
marking failed when the loadStartedAtMutationVersion no longer matches
mutationVersion, and keep the existing signal.aborted guard in the same flow.

In `@packages/worker/src/email/repo.ts`:
- Around line 905-923: Delete the raw MIME blob before removing the
`email_messages` row in the delete flow inside `deleteEmailMessage` (the block
that reads `raw_mime_key` and calls `input.blobs.delete`). Reorder the
operations so the R2 delete happens first and only proceed with the SQL `DELETE
FROM email_messages` after the blob removal succeeds; keep the row lookup/guard
around `input.blobs` and preserve the best-effort warning log for blob delete
failures so the delete remains retryable if the blob removal errors.

---

Nitpick comments:
In `@packages/worker/src/package-runtime/package-service.ts`:
- Around line 397-406: The clearAlarm failure path in finalizeServiceRun is
still effectively silent when runServiceInBackground catches the error and
retries finalizeServiceRun, so add an explicit warning/log at the clearAlarm
call site or inside clearAlarm itself to surface deleteAlarm failures. Use the
package service methods clearAlarm, finalizeServiceRun, and
runServiceInBackground to place the log where the error is first thrown, and
include enough context to identify the stale-alarm condition without changing
the existing error propagation behavior.
🪄 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: 1a4ab74a-6590-4c92-8481-a23428284f04

📥 Commits

Reviewing files that changed from the base of the PR and between 924c624 and 90a82d1.

📒 Files selected for processing (70)
  • cli.ts
  • e2e/auth-test-user.ts
  • e2e/community-frames.spec.ts
  • e2e/d1-utils.ts
  • e2e/playwright-utils.ts
  • e2e/smoke.spec.ts
  • e2e/ssr-hydration.spec.ts
  • packages/shared/src/chunk.node.test.ts
  • packages/shared/src/chunk.ts
  • packages/shared/src/date-keys.ts
  • packages/shared/src/tags-json.ts
  • packages/worker/client/route-load-latch.node.test.ts
  • packages/worker/client/route-load-latch.ts
  • packages/worker/client/routes/account-integrations.tsx
  • packages/worker/client/routes/account-mcp-servers.tsx
  • packages/worker/client/routes/account-package-invocation-tokens.tsx
  • packages/worker/client/routes/account-passkeys.tsx
  • packages/worker/client/routes/account-remote-connectors.tsx
  • packages/worker/client/routes/account-two-factor.tsx
  • packages/worker/client/routes/account.tsx
  • packages/worker/client/routes/admin-community-reports.tsx
  • packages/worker/client/routes/admin-invites.tsx
  • packages/worker/client/routes/community-detail.tsx
  • packages/worker/client/routes/connect-oauth.tsx
  • packages/worker/src/app/admin-system-email-data.ts
  • packages/worker/src/app/admin-usage-data.ts
  • packages/worker/src/app/admin-user-creation.ts
  • packages/worker/src/app/admin-users-data.ts
  • packages/worker/src/app/auth-redirect.ts
  • packages/worker/src/app/email-change.ts
  • packages/worker/src/app/email-verification.ts
  • packages/worker/src/app/env.ts
  • packages/worker/src/app/handler.ts
  • packages/worker/src/app/handlers/account-email-change.ts
  • packages/worker/src/app/handlers/account-passkeys.ts
  • packages/worker/src/app/handlers/account-profile.ts
  • packages/worker/src/app/handlers/account-resend-verification.ts
  • packages/worker/src/app/handlers/account-two-factor.ts
  • packages/worker/src/app/handlers/auth-page.ts
  • packages/worker/src/app/handlers/auth.ts
  • packages/worker/src/app/handlers/password-reset.ts
  • packages/worker/src/app/handlers/verify.ts
  • packages/worker/src/app/handlers/webauthn.ts
  • packages/worker/src/app/query-params.ts
  • packages/worker/src/app/request-auth-cache.ts
  • packages/worker/src/app/router.ts
  • packages/worker/src/app/username.ts
  • packages/worker/src/community/repo.ts
  • packages/worker/src/community/snapshot.ts
  • packages/worker/src/email/inbound.ts
  • packages/worker/src/email/platform-address.ts
  • packages/worker/src/email/repo.ts
  • packages/worker/src/entitlements/service.ts
  • packages/worker/src/jobs/repo.ts
  • packages/worker/src/mcp-auth-user-context.ts
  • packages/worker/src/mcp/capabilities/meta/search.ts
  • packages/worker/src/mcp/memory/json-string-array.ts
  • packages/worker/src/mcp/memory/repo.ts
  • packages/worker/src/mcp/run-kody-registry.ts
  • packages/worker/src/mcp/tools/execute.ts
  • packages/worker/src/mcp/tools/search.ts
  • packages/worker/src/package-registry/repo.ts
  • packages/worker/src/package-registry/service.ts
  • packages/worker/src/package-runtime/package-service.ts
  • tools/ci/sync-worker-secrets.ts
  • tools/mcp-test-support.ts
  • tools/seed-sql.ts
  • tools/seed-test-data.ts
  • tsconfig-tools.json
  • wrangler-env.ts

Comment thread packages/worker/client/route-load-latch.ts
Comment thread packages/worker/src/mcp/tools/execute.ts
Comment on lines 311 to +329
logMcpEvent({
category: 'mcp',
tool: 'execute',
toolName: 'execute',
outcome: 'failure',
outcome: 'success',
durationMs,
baseUrl,
hasUser,
registeredCapabilityCount,
sandboxError: true,
errorName,
errorMessage,
cause: result.error,
sandboxError: false,
context: activeStorageId ? { storageId: activeStorageId } : undefined,
})
const limitedResult = limitExecutionResultValue(
result.result,
responseLimit ?? defaultExecutionResponseLimitBytes,
)
const rawContent = limitedResult.truncated
? null
: extractRawContent(limitedResult.value)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the success log still precedes result limiting/formatting.
sed -n '300,335p' packages/worker/src/mcp/tools/execute.ts
sed -n '945,993p' packages/worker/src/mcp/executor.ts

Repository: kentcdodds/kody

Length of output: 2580


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== execute.ts around the success log =="
sed -n '300,360p' packages/worker/src/mcp/tools/execute.ts

echo
echo "== executor.ts around response formatting helpers =="
rg -n "function (limitExecutionResultValue|extractRawContent|formatLimitedExecutionOutput)|const (limitExecutionResultValue|extractRawContent|formatLimitedExecutionOutput)" packages/worker/src/mcp/executor.ts packages/worker/src/mcp/tools/execute.ts
sed -n '1,260p' packages/worker/src/mcp/executor.ts

Repository: kentcdodds/kody

Length of output: 9256


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== execute.ts try/catch around success path =="
sed -n '240,380p' packages/worker/src/mcp/tools/execute.ts

echo
echo "== executor.ts helper bodies =="
sed -n '920,1045p' packages/worker/src/mcp/executor.ts

Repository: kentcdodds/kody

Length of output: 6780


Move the success log after response formatting.

limitExecutionResultValue() can throw on non-serializable results (for example, circular data or BigInt), so emitting outcome: 'success' before that step can produce a success event followed by a failure path. Format the response first, then log success once the return payload is ready.

🤖 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/execute.ts` around lines 311 - 329, The success
event is being emitted before response formatting in execute(), so a later
failure in limitExecutionResultValue() can leave a false success log. Move the
logMcpEvent call in execute() to after the response payload has been fully
formatted, ideally after limitExecutionResultValue() and raw content extraction
succeed, so the success outcome is only recorded once the return data is ready.

Comment thread tools/mcp-test-support.ts
Comment thread tools/seed-sql.ts Outdated
Comment thread tsconfig-tools.json
"./tools/**/*.ts",
"./packages/shared/src/**/*.ts"
"./packages/shared/src/**/*.ts",
// Worker app modules imported by the seeding tools.

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 inline comment from this JSON file.

Biome reports this line as a parse error, so tsconfig-tools.json currently fails the configured static analysis.

Proposed fix
-		// Worker app modules imported by the seeding tools.
 		"./packages/worker/src/app/username.ts",
📝 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
// Worker app modules imported by the seeding tools.
🧰 Tools
🪛 Biome (2.5.1)

[error] 40-40: Expected an array, an object, or a literal but instead found '// Worker app modules imported by the seeding tools.'.

(parse)


[error] 40-40: End of file expected

(parse)

🤖 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 `@tsconfig-tools.json` at line 40, Remove the inline comment from the JSON in
tsconfig-tools.json so the file remains valid for Biome parsing and static
analysis. Update the JSON entry directly where the comment appears, keeping the
surrounding tsconfig-tools configuration intact and preserving the referenced
modules/settings without any comment text.

Source: Linters/SAST tools

…ing throws as sandbox errors, bound readiness fetch attempts, seed stable_user_id

@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 using default effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

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 73de898. Configure here.

needsStaleRefresh) &&
typeof document !== 'undefined'
) {
status !== 'loading' && !loadLatch.isLoadedFor(currentHref)

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.

Unused variable left behind after latch refactor

Low Severity

isRefreshingForLocationChange is computed but never read. All six other routes refactored in this PR dropped this intermediate variable entirely and rely solely on loadLatch.needsLoad(...). This route accidentally kept the now-dead assignment, adding confusion about whether it participates in the load decision.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 73de898. Configure here.

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