#10325·tldraw

Deep review of apps/dotcom for correctness bugs

Author: steveruizokCreated Aug 20, 2026Updated Sep 28, 2026
Labelsbugfixdotcom

Rollup for a deep review of apps/dotcom (client, sync-worker, image-resize-worker, zero-cache) and packages/dotcom-shared for correctness bugs: a file room admitting sockets with no auth checks when its row is missing, hard delete leaving the durable object half-alive and deleting other files' history, Zero mutator rejections being silently treated as success in the client, a stored analytics opt-out never reaching PostHog, bootstrap and loader failures rendering blank or generic pages, and a long tail of smaller edge cases.

The review landed as one umbrella PR, then as a per-bug split. The umbrella #10259 holds the full before/after write-up and was closed in favour of the split below.

PRs

Umbrella (closed, superseded by the split):

  • #10259 fix(dotcom): address findings from a full review of apps/dotcom

Sync-worker rooms and deletion:

  • #10297 fix(dotcom): fail closed when a file room has no database row
  • #10298 fix(dotcom): make file hard delete terminal and scope its R2 history cleanup
  • #10299 fix(dotcom): seed a late-found app file from its createSource

Sync-worker access and routes:

  • #10300 fix(dotcom): apply the same write gate to both asset upload paths
  • #10301 fix(dotcom-shared): require workspace access to pin and unpin files
  • #10302 fix(dotcom): store the migrated records under the server schema in createRoomSnapshot
  • #10303 fix(dotcom): gate social preview names on anonymous viewability
  • #10304 fix(dotcom): step room history by UTC calendar month and guard invalid offsets
  • #10305 fix(dotcom): return the invite handler's own 401 body and tolerate racing accepts
  • #10307 fix(dotcom): await the resolved slug's room before reading legacy room data

Sync-worker plumbing and workers:

  • #10306 fix(dotcom): destroy leaked postgres pools, bound the durable object pool's connect, and pass PushProcessor its log level
  • #10308 fix(dotcom): stop the image resize worker matching unparseable etags
  • #10309 chore(dotcom): delete dead sync-worker code

Client errors and bootstrap:

  • #10310 fix(dotcom): check Zero mutator results instead of catching promises that never reject
  • #10311 fix(dotcom): show an error page when app bootstrap fails instead of a blank page
  • #10312 fix(dotcom): honour a stored analytics opt-out after a reload
  • #10313 fix(dotcom): render loader error pages instead of throwing out of the error boundary

Client editor and routes:

  • #10314 fix(dotcom): don't render file-bound menu actions on legacy routes
  • #10315 fix(dotcom): build copy-to-workspace sources from route params and fix file-name fallbacks
  • #10316 fix(dotcom): keep a board loading through bad deep links, corrupt session state, and failed slurps
  • #10317 fix(dotcom): fix .tldr drop and upload edge cases

Client UI and cleanups:

  • #10318 fix(dotcom): keep the feedback dialog open when submission fails
  • #10319 fix(dotcom): cancel stale async work in /new and the locale loader
  • #10320 fix(dotcom): fix the export preview race, QR code caching, and last-published time in the share menu
  • #10321 fix(dotcom): fix sidebar file link deps and simplify the sidebar toggles and admin-rights hook
  • #10322 chore(dotcom): delete dead client code
  • #10323 chore(dotcom): declare missing dependencies
  • #10324 docs(dotcom): describe the outbox instead of the deleted replicator and user DO

Notes

  • The splits were cut from the umbrella so that the union reproduces it exactly and all 28 cherry-pick cleanly onto one branch, so they don't conflict with each other. TLFileDurableObject.ts is touched by #10297, #10298, #10299, and #10309; TldrawApp.ts by #10305, #10310, #10311, #10317, and #10322; worker.ts by #10300 and #10306 — different hunks, but whichever lands later in each group may need a trivial rebase.
  • #10072 (simplify/dotcom) touches many of the same files; whichever side lands second rebases.
  • Left for follow-ups (reported, not changed): server-side MAX_NUMBER_OF_FILES enforcement in the createFile mutator; capping or relocating the MCP shapeIds render token (URL length); OG-queue not_found vs KV eventual consistency; /import?url= auto-importing without confirmation; a server-side upload size cap (lives in worker-shared); poke-per-push churn, MCP measurement cache, snapshot double-serialization, associatePendingAssets full decode, and signalizeQuery structuredClone; the legacy page triplicates and the renderShapeSetScreenshot / access-gate dedupe; the "Try Again" i18n key rename (49 locale files); the unused POST /app/admin/delete_user route; remaining admin-route pool leaks (telemetry-only impact); FeatureFlagPoller identity invalidation and shouldEnableCommenting staff-check drift (plausible only).

This issue closes when the PRs above have landed or been closed.