feat(comments): canvas commenting and historical version replay - #78691
Conversation
|
React Doctor found 3 issues in 1 file · 3 warnings. 3 warnings
Reviewed by React Doctor for commit |
🤖 CI report
|
| File | Size | Δ vs base |
|---|---|---|
posthog-app/_parent/products/signals/frontend/inbox/InboxScene.js |
706.8 KiB | 🔺 +706.8 KiB (new) |
posthog-app/src/scenes/inbox/InboxScene.js |
removed | 🟢 -706.8 KiB (-100.0%) |
posthog-app/_parent/products/signals/frontend/inbox/components/config/scouts/ScoutCreateModal.js |
8.0 KiB | 🔺 +8.0 KiB (new) |
posthog-app/src/scenes/inbox/components/config/scouts/ScoutCreateModal.js |
removed | 🟢 -8.0 KiB (-100.0%) |
Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report
✅ Eager graph — within budget
How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.
| Root | Eager (shipped) | Δ vs base | Budget |
|---|---|---|---|
entry (logged-out pages, app bootstrap)src/index.tsx |
1.26 MiB · 22 files | no change | ███░░░░░░░ 27.9% of 4.51 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
8.18 MiB · 3,050 files | 🔺 +23 B (+0.0%) | ████████░░ 84.2% of 9.71 MiB |
🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
Largest files eagerly shipped from src/index.tsx
| Size | File |
|---|---|
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 24.6 KiB | ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js |
| 6.3 KiB | ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js |
| 4.5 KiB | ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js |
| 3.9 KiB | ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js |
| 1.4 KiB | ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js |
| 1.3 KiB | src/RootErrorBoundary.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 789 B | src/scenes/ChunkLoadErrorBoundary.tsx |
| 762 B | src/index.tsx |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 285.5 KiB | ../node_modules/.pnpm/posthog-js@1.410.1/node_modules/posthog-js/dist/rrweb.js |
| 267.7 KiB | ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js |
| 238.4 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 231.5 KiB | ../node_modules/.pnpm/posthog-js@1.410.1/node_modules/posthog-js/dist/module.js |
| 154.3 KiB | ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js |
| 126.8 KiB | ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js |
| 105.0 KiB | src/lib/api.ts |
| 95.2 KiB | ../packages/quill/packages/quill/dist/index.js |
| 93.3 KiB | ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js |
| 90.6 KiB | ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js |
Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479
✅ Toolbar bundle — eager 2.20 MiB within budget
What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.
| Metric | Size | Δ vs base | Budget |
|---|---|---|---|
| Eager (shipped) entry + static imports |
2.20 MiB · 17 files | no change | ████░░░░░░ 38.4% of 5.72 MiB |
| Deferred (lazy) | 2.08 MiB · 33 files | no change | n/a — loads on demand |
Loader dist/toolbar.js |
1.1 KiB | no change | █░░░░░░░░░ 5.8% of 19.5 KiB |
Largest eagerly-shipped chunks
| Size | File |
|---|---|
| 723.0 KiB | dist/toolbar/toolbar-app-M7B2P2W4.css |
| 552.3 KiB | dist/toolbar/chunk-chunk-LINCPQWW.js |
| 484.6 KiB | dist/toolbar/chunk-chunk-5HONEO7J.js |
| 133.6 KiB | dist/toolbar/chunk-chunk-PSGMVXK7.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-T5KY5WYR.js |
| 71.0 KiB | dist/toolbar/toolbar-app-BIMPVI2A.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-27JL52RE.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-QQAXO5G5.js |
| 20.9 KiB | dist/toolbar/chunk-chunk-B5MOUYTE.js |
| 12.2 KiB | dist/toolbar/chunk-chunk-PIK3PADE.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — 🔺 +805 B (+0.0%)
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1394.88 MiB · 🔺 +805 B (+0.0%)
538c939 to
d2e8ed3
Compare
2dfc4a7 to
96555fa
Compare
👀 Auto-assigned reviewersThese soft owners were skipped because they only have minor changes here. Nothing blocks merge, so self-assign if you'd like a look:
Soft owners come from each directory's |
91a7f56 to
0ce7924
Compare
0ce7924 to
f8b6aea
Compare
PR overviewThis pull request adds commenting to freeform canvases and supports replaying historical canvas versions when users open version-linked comments. One issue has been addressed, but a significant security risk remains in historical replay. A malicious collaborator can cause superseded source code to execute when another user opens a linked comment in normal view mode, allowing queries with the viewer’s credentials and potential data exfiltration. Open issues (1)
Fixed/addressed: 1 · PR risk: 8/10 |
f8b6aea to
5d4b14c
Compare
puemos
left a comment
There was a problem hiding this comment.
Merge Confidence: 3.0/5 - Moderate
"Needs attention - review carefully"
Assessment
- ✓ Untrusted iframe→host frames are properly bounded: quote ≤10k, comment ids ≤128 chars, highlight arrays ≤500,
end > startrefined, all parsed before dispatch in canvasHostMessageRouter - ✓ Broad test coverage for the new surface — schema bounds, both canvas hosts' selection/highlight/clear paths, CanvasSelectionCommentAction, the side-panel tab switch and the header comment count
- ✓ Replacing source-render with retained build artifacts genuinely fixes the old 'Multi-file version' dead end for historical browsing
- ⚠
const browsing = !!browseVersionIddrops the previousinteractive &&gate, so the browse banner's Revert button (itself ungated) can render for viewers of a canvas mounted withinteractive={editing}— reachable via the new comment→version jump - ⚠ Historical artifacts render
lifecycle.artifactUrldirectly instead of going throughusePinnedArtifact, whose docs state every refetch mints a fresh signed URL — a poll or focus refetch will reload the historical iframe and drop its state - ⚠ Sandbox click handler intercepts in the capture phase and preventDefault/stopPropagation on any hit inside a highlight rect, so a comment on a button or link label disables that control
- ⚠
commentTaskIdis derived with different precedence in WebsiteLayout (generationTaskId) vs FreeformCanvasView (effectiveTaskId); taskId is part of the comments query key, so the header badge and panel can address different comment sets - ⚠ Full-document text index rebuilt on a 500ms MutationObserver loop plus a whole-body stringify per selectionchange — standing main-thread cost inside user canvases
- ⚠ sandboxRuntime.test.ts asserts on generated source substrings (including negative identifier matches) rather than runtime behaviour
Review: Canvas text comments: in-iframe selection anchors, highlight rendering, and artifact-based version browsing
Adds text-anchored comments to freeform canvases. Five new postMessage frames (text-selection, text-selection-cleared, comment-activate; set-comment-highlights, clear-text-selection) carry bounded, zod-validated selection anchors between the sandbox/artifact iframes and the host; the sandbox gains a selection reporter, a CSS Custom Highlight renderer and a capture-phase click handler. The side panel becomes Chat/Comments tabs, the breadcrumb grows an open-thread count, and historical version browsing switches from re-rendering the version's source to loading that version's retained build artifact (new optional version_id on the builds endpoint plus historicalCanvasBuild).
Main risks: (1) browsing lost its interactive gate, surfacing the mutating Revert button in view mode; (2) the historical artifact bypasses usePinnedArtifact, so signed-URL churn on refetch reloads the iframe; (3) the sandbox click handler swallows clicks on interactive elements overlapping a highlight; (4) commentTaskId is derived two different ways, and it's part of the comments query key. Secondary: a 500ms mutation-driven full-document re-index inside user canvases, and sandbox tests that assert on generated source strings.
8214026 to
d2d17ee
Compare
Layer 2 of 3 (stacked on posthog-code/comments-backend). Anchored comment primitives (text/region/document), the composer, thread cards, artifact and document comment surfaces, mentions, comment navigation, and the merged task + comment Activity feed. Consumes the generated types from layer 1. Flag-gating on posthog-code-comments is a required follow-up before ready-for-review — see the PR description checklist. Generated-By: PostHog Code Task-Id: f7eb12dd-00a4-4293-a013-8156f71c4e2a
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Layer 3 of 3 (stacked on posthog-code/comments-desktop-core). Canvas selection comments, the sandbox iframe message boundary, the comments side panel, and replay of the reviewed historical canvas version. Reuses the comment primitives from layer 2. Flag-gating on posthog-code-comments (CanvasSidePanel, CanvasSelectionCommentAction) is a required follow-up before ready-for-review — see the PR description checklist. Generated-By: PostHog Code Task-Id: f7eb12dd-00a4-4293-a013-8156f71c4e2a
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Generated-By: PostHog Code Task-Id: f0ed2ac4-cacd-44a9-b6a5-ab46f42f4c49
Pin historical build URLs, keep view-only history non-mutating, bound highlight work, and align comment task selection across canvas surfaces. Reuse canvas lifecycle queries, preserve interactive controls under highlights, and add focused regression coverage. Generated-By: PostHog Code Task-Id: 0c91c718-a903-4ae7-849f-0a38831d1db7
26db098 to
69316e0
Compare
|
😎 Stack merged successfully - details. |
|
Stacked PR 79009 failed testing in the merge queue. Please investigate the failure and re-submit the stack. |
|
/trunk merge |
|
This pull request was merged into |
Problem
Canvas reviewers can leave feedback, but they cannot anchor it to a selection or return to the reviewed canvas version.
This is layer 3 of stack #78692, based on #78690. The sandbox boundary is the main review risk.
Changes
posthog-code-commentsgates the canvas comment surfaces.sequenceDiagram actor Reviewer participant Comments as Comments or Activity participant Builds as Canvas builds API participant Canvas as Canvas iframe Reviewer->>Comments: Open a canvas comment Comments->>Builds: Request the saved version Builds-->>Canvas: Return the immutable build Canvas-->>Reviewer: Show the reviewed version and threadScreenshot not included. This session validated the behavior through tests and builds without a seeded commented canvas.
How did you test this code?
👉 Stay up-to-date with PostHog coding conventions for a smoother review.
Automatic notifications
Docs update
None.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
PostHog Code implemented this as the canvas layer of stack #78692. The final review pass pinned historical artifacts, bounded highlight work, and removed view-mode mutations.
Skills invoked:
/stacking-prs,/writing-tests,/writing-user-facing-copy,/writing-code-comments, and/writing-pr-descriptions.