feat(canvas): publish by default and let space members edit canvases - #94530
Conversation
|
😎 Merged successfully - details. |
|
React Doctor found 1 issue in 1 file · 1 warning. 1 warning
Reviewed by React Doctor for commit |
🤖 CI report
|
| File | Comment lines | Added lines |
|---|---|---|
products/desktop/packages/ui/src/features/canvas/freeform/CanvasSidePanel.tsx |
8 | 37 |
products/desktop/packages/ui/src/features/canvas/freeform/FreeformCanvasView.tsx |
8 | 101 |
products/canvas/backend/presentation/views.py |
5 | 39 |
This check does not block merging. It updates on every push and clears when the share drops.
✅ Bundle size — no change
Uncompressed size of every built .js bundle, compared against the base branch.
Total: 68.63 MiB · no change
No file changed by more than 1000 B.
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.50 MiB · 22 files | no change | ███░░░░░░░ 33.2% of 4.51 MiB |
logged-out boot: index + App + bootApp (preloaded by every page, including /login)src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts |
5.26 MiB · 669 files | no change | █████████░ 93.5% of 5.63 MiB |
authenticated shell (every logged-in page)src/scenes/AuthenticatedShell.tsx |
7.67 MiB · 2,677 files | no change | █████████░ 87.4% of 8.77 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/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 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
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts 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 |
| 1.0 KiB | src/index.tsx |
| 912 B | ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js |
| 854 B | src/scenes/ChunkLoadErrorBoundary.tsx |
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
| Size | File |
|---|---|
| 281.2 KiB | ../node_modules/.pnpm/posthog-js@1.428.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 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 |
| 255.2 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 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 |
| 104.4 KiB | src/lib/api.ts |
| 79.1 KiB | src/products.tsx |
| 68.8 KiB | src/lib/lemon-ui/icons/icons.tsx |
| 62.5 KiB | src/lib/utils/eventUsageLogic.ts |
| 38.8 KiB | ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js |
| 33.9 KiB | ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js |
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
| Size | File |
|---|---|
| 281.2 KiB | ../node_modules/.pnpm/posthog-js@1.428.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs |
| 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 |
| 255.2 KiB | src/taxonomy/core-filter-definitions-by-group.json |
| 153.8 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 |
| 104.4 KiB | src/lib/api.ts |
| 95.8 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 |
| 79.1 KiB | src/products.tsx |
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.29 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.29 MiB · 18 files | no change | ████░░░░░░ 40.0% of 5.72 MiB |
| Deferred (lazy) | 2.11 MiB · 45 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 |
|---|---|
| 756.4 KiB | dist/toolbar/toolbar-app-TJXV6LBK.css |
| 608.2 KiB | dist/toolbar/chunk-chunk-LKX5I3GN.js |
| 484.7 KiB | dist/toolbar/chunk-chunk-D33R7XDZ.js |
| 136.6 KiB | dist/toolbar/chunk-chunk-WN3QUMO3.js |
| 131.8 KiB | dist/toolbar/chunk-chunk-FDH2IBXT.js |
| 72.2 KiB | dist/toolbar/toolbar-app-HBJK7QTG.js |
| 69.0 KiB | dist/toolbar/chunk-chunk-TSAL54PB.js |
| 35.6 KiB | dist/toolbar/chunk-chunk-YH72TXO5.js |
| 21.0 KiB | dist/toolbar/chunk-chunk-3YHN5KR6.js |
| 6.8 KiB | dist/toolbar/chunk-chunk-DV7IWQNF.js |
Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile
✅ Dist folder size — no change
Total size of the built frontend/dist folder (all assets), compared against the base branch.
Total: 1458.81 MiB · no change
ℹ️ MCP UI apps size — 33 app(s), 17665.2 KB JS
Built size of each MCP UI app (main.js + styles.css).
| App | JS | CSS |
|---|---|---|
| debug | 600.0 KB | 195.2 KB |
| action | 458.2 KB | 195.2 KB |
| action-list | 564.9 KB | 195.2 KB |
| cohort | 457.2 KB | 195.2 KB |
| cohort-list | 563.8 KB | 195.2 KB |
| email-template | 457.0 KB | 195.2 KB |
| error-details | 472.9 KB | 195.2 KB |
| error-issue | 457.9 KB | 195.2 KB |
| error-issue-list | 564.7 KB | 195.2 KB |
| experiment | 562.0 KB | 195.2 KB |
| experiment-list | 565.6 KB | 195.2 KB |
| experiment-results | 567.1 KB | 195.2 KB |
| feature-flag | 567.6 KB | 195.2 KB |
| feature-flag-list | 571.4 KB | 195.2 KB |
| feature-flag-testing | 461.4 KB | 195.2 KB |
| inline-scan | 457.7 KB | 195.2 KB |
| insight-actors | 563.0 KB | 195.2 KB |
| invite-email-preview | 456.4 KB | 195.2 KB |
| llm-costs | 560.0 KB | 195.2 KB |
| session-recording | 459.0 KB | 195.2 KB |
| survey | 458.8 KB | 195.2 KB |
| survey-global-stats | 562.7 KB | 195.2 KB |
| survey-list | 565.5 KB | 195.2 KB |
| survey-stats | 562.7 KB | 195.2 KB |
| trace-span | 457.6 KB | 195.2 KB |
| trace-span-list | 564.7 KB | 195.2 KB |
| vision-observation-list | 563.9 KB | 195.2 KB |
| workflow | 457.5 KB | 195.2 KB |
| workflow-list | 564.2 KB | 195.2 KB |
| loops-review | 461.9 KB | 195.2 KB |
| query-results | 756.3 KB | 195.2 KB |
| render-ui | 839.5 KB | 195.2 KB |
| visual-review-snapshots | 462.0 KB | 195.2 KB |
⚠️ Backend coverage — 98.0% of changed backend lines covered — 1 uncovered
🧪 Backend test coverage
Patch coverage — changed backend lines (products + core): ████████████████████ 98.0% (74 / 75)
| File | Patch | Uncovered changed lines |
|---|---|---|
products/canvas/backend/presentation/views.py |
93.8% | 396 |
🤖 Agents: add a test covering the lines above, or note why under "How did you test this code?". Machine-readable gap list: the patch-coverage artifact on this run (gh run download 34158534015 -n patch-coverage), or the coverage-data block at the end of this comment.
Per-product line coverage (touched products)
| Product | Coverage | Lines |
|---|---|---|
platform_features |
██░░░░░░░░░░░░░░░░░░ 12.1% |
7 / 58 |
warehouse_sources_queue |
██████░░░░░░░░░░░░░░ 29.1% |
92 / 316 |
demo |
███████████░░░░░░░░░ 57.0% |
1,523 / 2,671 |
data_tools |
█████████████░░░░░░░ 66.2% |
90 / 136 |
ai_gateway |
███████████████░░░░░ 75.0% |
9 / 12 |
batch_exports |
████████████████░░░░ 79.8% |
19,412 / 24,337 |
apm |
█████████████████░░░ 83.3% |
1,234 / 1,481 |
wizard |
█████████████████░░░ 85.2% |
2,770 / 3,250 |
cdp |
█████████████████░░░ 85.3% |
4,338 / 5,083 |
signals |
█████████████████░░░ 85.5% |
36,410 / 42,588 |
product_tours |
██████████████████░░ 87.9% |
1,303 / 1,482 |
notebooks |
██████████████████░░ 88.5% |
11,861 / 13,409 |
data_warehouse |
██████████████████░░ 88.9% |
12,855 / 14,456 |
business_knowledge |
██████████████████░░ 89.2% |
4,458 / 4,997 |
cohorts |
██████████████████░░ 89.2% |
7,526 / 8,433 |
dashboards |
██████████████████░░ 89.6% |
6,812 / 7,606 |
engineering_analytics |
██████████████████░░ 90.1% |
8,391 / 9,310 |
streamlit_apps |
██████████████████░░ 90.2% |
2,500 / 2,773 |
tasks |
██████████████████░░ 90.2% |
65,476 / 72,561 |
data_modeling |
██████████████████░░ 90.4% |
9,362 / 10,360 |
links |
██████████████████░░ 90.6% |
183 / 202 |
managed_warehouse |
██████████████████░░ 90.7% |
9,406 / 10,367 |
exports |
██████████████████░░ 90.7% |
9,098 / 10,027 |
alerts |
██████████████████░░ 90.9% |
5,224 / 5,745 |
visual_review |
██████████████████░░ 91.0% |
6,896 / 7,577 |
mcp_analytics |
██████████████████░░ 91.2% |
4,402 / 4,828 |
conversations |
██████████████████░░ 91.2% |
21,607 / 23,684 |
canvas |
██████████████████░░ 91.2% |
5,016 / 5,497 |
error_tracking |
██████████████████░░ 92.0% |
13,477 / 14,651 |
notifications |
██████████████████░░ 92.4% |
1,110 / 1,201 |
early_access_features |
███████████████████░ 92.5% |
1,323 / 1,430 |
managed_migrations |
███████████████████░ 92.6% |
1,556 / 1,681 |
slack_app |
███████████████████░ 92.8% |
12,596 / 13,578 |
surveys |
███████████████████░ 93.1% |
6,170 / 6,630 |
mcp_registry |
███████████████████░ 93.2% |
1,463 / 1,570 |
web_analytics |
███████████████████░ 93.3% |
19,313 / 20,695 |
stamphog |
███████████████████░ 93.3% |
6,533 / 6,999 |
context_layer |
███████████████████░ 93.3% |
2,594 / 2,779 |
reminders |
███████████████████░ 93.4% |
468 / 501 |
posthog_ai |
███████████████████░ 93.5% |
1,385 / 1,481 |
mcp_store |
███████████████████░ 93.5% |
8,053 / 8,611 |
marketing_analytics |
███████████████████░ 93.5% |
17,381 / 18,585 |
ai_observability |
███████████████████░ 93.8% |
18,194 / 19,402 |
autoresearch |
███████████████████░ 93.9% |
443 / 472 |
approvals |
███████████████████░ 93.9% |
3,560 / 3,793 |
billing_alerts |
███████████████████░ 94.0% |
2,069 / 2,200 |
endpoints |
███████████████████░ 94.2% |
8,904 / 9,456 |
review_hog |
███████████████████░ 94.3% |
10,205 / 10,817 |
tracing |
███████████████████░ 94.5% |
2,709 / 2,868 |
legal_documents |
███████████████████░ 94.7% |
2,073 / 2,190 |
workflows |
███████████████████░ 94.7% |
11,782 / 12,436 |
access_control |
███████████████████░ 94.9% |
6,052 / 6,378 |
customer_analytics |
███████████████████░ 95.1% |
19,279 / 20,274 |
annotations |
███████████████████░ 95.2% |
795 / 835 |
product_analytics |
███████████████████░ 95.3% |
19,348 / 20,304 |
actions |
███████████████████░ 95.4% |
740 / 776 |
replay_vision |
███████████████████░ 95.5% |
22,721 / 23,789 |
skills |
███████████████████░ 95.6% |
5,526 / 5,781 |
experiments |
███████████████████░ 95.6% |
30,240 / 31,626 |
messaging |
███████████████████░ 95.8% |
3,671 / 3,830 |
logs |
███████████████████░ 95.9% |
13,786 / 14,368 |
growth |
███████████████████░ 96.0% |
7,719 / 8,044 |
feature_flags |
███████████████████░ 96.3% |
20,574 / 21,361 |
revenue_analytics |
███████████████████░ 96.3% |
1,841 / 1,911 |
user_interviews |
███████████████████░ 96.5% |
2,639 / 2,735 |
warehouse_sources |
███████████████████░ 97.2% |
409,550 / 421,452 |
data_quality |
████████████████████ 97.5% |
4,217 / 4,323 |
analytics_platform |
████████████████████ 98.1% |
2,286 / 2,330 |
metrics |
████████████████████ 98.2% |
3,564 / 3,628 |
data_catalog |
████████████████████ 98.3% |
3,258 / 3,313 |
pulse |
████████████████████ 98.4% |
2,017 / 2,049 |
live_debugger |
████████████████████ 99.2% |
613 / 618 |
field_notes |
████████████████████ 99.4% |
158 / 159 |
Report-only. Patch coverage = changed backend lines covered vs origin/master. Sorted lowest first.
Known gaps: lines covered only by Temporal tests show as uncovered; core line numbers may drift if master changed the same file.
ℹ️ Docs preview — preview build triggered
Docs from this PR will be published at posthog.com.
| Project | Preview | Updated (UTC) |
|---|---|---|
| posthog.com | Open preview | Sep 7, 2026, 8:13 PM |
The preview should be ready in about 10 minutes. Open the preview at /handbook/engineering/.
HostHog preview —
|
Prompt To Fix All With AI### Issue 1
products/desktop/packages/ui/src/features/canvas/freeform/FreeformCanvasView.tsx:1095-1099
**Wrong space in task link**
A task-bound sandbox can publish a version for a public canvas even when its task belongs to another space. This link combines the version's task ID with the canvas's current `channelId`, so “View task” opens that task under the wrong space name and navigation context.
### Issue 2
products/canvas/backend/presentation/views.py:259-269
**Sandbox publish action omitted**
`publish_current_version` is missing from `_EDITOR_ACTIONS`. A task-bound sandbox therefore cannot rebuild the current version of another creator's public canvas, even though the other publish and edit actions now support shared public canvases.
```suggestion
_EDITOR_ACTIONS = {
"partial_update",
"publish",
"publish_current_version",
"edit",
"draft",
"promote",
"revert",
"build_action",
"publish_layout",
"patch_layout",
}
```
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "chore: update OpenAPI generated types" | Re-trigger Greptile |
PR overviewAll previously flagged issues have been addressed. No open security concerns remain on this pull request. Security reviewNo open security issues remain on this pull request. Fixed/addressed: 1 · PR risk: 0/10 |
Agent runs publish a live version unless the user asks for a draft. In a public space, any member can publish, edit, draft, promote, and revert a canvas; rename, move, pin, and delete stay with the creator. The version history shows who published each version and links its task. Opening a canvas starts from the composer instead of reopening the run that built it. Generated-By: PostHog Desktop Task-Id: 2c919e95-48ce-46a9-8c4b-ac1bce3f56a6
1b235ac to
51a93f7
Compare
Generated-By: PostHog Desktop Task-Id: ca319c99-7c81-4866-ad13-2493b13dad82
There was a problem hiding this comment.
Approved.
This is an authorization change (who can publish/edit/rename canvases), but the author is on the owning team, which satisfies the independent-assurance bar for risky territory. The two bot-flagged concerns (missing sandbox rebuild permission, non-creator rename bypass) are both fixed in the current diff with tests confirming the fix, so no unresolved substantive issue remains.
- Author wrote 57% of the modified lines and has 37 merged PRs in these paths (familiarity MODERATE).
- 👍 on the PR from greptile-apps[bot].
- 3 of the 12 changed files are governed by
products/desktop/AGENT_APPROVALS.md.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 281L, 7F substantive, 529L/12F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1d-complex (529L, 12F, cross-cutting, feat) |
| stamphog 2.0.0b4 | .stamphog/policy.yml @ c2da259 · reviewed head c2da259 |
Generated-By: PostHog Desktop Task-Id: ca319c99-7c81-4866-ad13-2493b13dad82
A new stamphog review started for this PR — the fresh verdict replaces this approval.
There was a problem hiding this comment.
Approved.
Changes the canvas access-control model (who can publish/edit/rename/delete), which is auth-sensitive territory, but the sole owning team (team-posthog-desktop) authored it, a security-focused bot reviewer explicitly confirmed no open concerns, and the diff shows both issues Greptile raised (missing sandbox rebuild permission, task-link space mismatch) have been fixed. Tests were extended to cover the new permission boundaries.
- Author wrote 57% of the modified lines and has 37 merged PRs in these paths (familiarity MODERATE).
- 👍 on the PR from greptile-apps[bot].
- 3 of the 12 changed files are governed by
products/desktop/AGENT_APPROVALS.md.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 281L, 7F substantive, 530L/12F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1d-complex (530L, 12F, cross-cutting, feat) |
| stamphog 2.0.0b4 | .stamphog/policy.yml @ 2a9df7f · reviewed head 2a9df7f |
|
/trunk merge |
Problem
Space members must ask the creator to change a shared canvas. Canvas edits also reopen an old session and require a separate publish step.
Why: Members need to edit shared content directly, with version history for recovery and attribution.
Changes
Release safety: Desktop uses existing endpoints and version fields. Either half can ship first; the backend controls write access. Personal-space and team boundaries remain unchanged.
Editing flow
Before:
flowchart LR edit[Edit canvas] --> session{{Previous session}} --> draft[Draft] --> review[Creator promotes] classDef phBlue fill:#1d4aff,stroke:#1d4aff,color:#fff; classDef phYellow fill:#f9bd2b,stroke:#f9bd2b,color:#000; classDef phGray fill:#e5e7eb,stroke:#c7ccd1,color:#000; class session phBlue; class edit,review phYellow; class draft phGray;After:
flowchart LR edit[Edit canvas] --> session{{New session}} --> publish[Publish version] classDef phBlue fill:#1d4aff,stroke:#1d4aff,color:#fff; classDef phYellow fill:#f9bd2b,stroke:#f9bd2b,color:#000; class session phBlue; class edit,publish phYellow;Screenshots are not included. The version menu and chat empty state still need a manual desktop check; this update fixes permissions and navigation.
How did you test this code?
hogli test products/canvas/backend/tests/test_canvas_api.pyand the desktop canvas freeform Vitest tests.hogli build:openapi, and strict preflight.Automatic notifications
Docs update
docs/internal/canvas-collaboration.mdcovers permissions, publishing, recovery, sessions, and release checks. Canvas skills describe publishing by default.🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Claude Code and Codex in PostHog Desktop. The follow-up resolves review findings and preserves the shared access mixin from the base branch.
Skills:
/posthog-desktop,/improving-drf-endpoints,/writing-tests,/implementing-mcp-tools,/running-ci-preflight,/writing-user-facing-copy,/writing-code-comments, and/writing-pr-descriptions.Created with PostHog Desktop