Skip to content

chore(scopes): clean up duplicated scope picker row logic - #112124

Merged
trunk-io[bot] merged 3 commits into
masterfrom
alex/scope-access-row-model
Oct 7, 2026
Merged

trunk-io[bot] merged 3 commits into
masterfrom
alex/scope-access-row-model

Conversation

@a-lider

@a-lider a-lider commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The personal API key scope picker and the OAuth consent screen show the same group control, but each page describes a row in its own way.

Each page also needs its own adapter component around the shared control.

Follows #110525.

Changes

  • One row shape for both pages, ScopePickerRow, with a disabled reason per level.
  • The group rules live once in lib/scopes, and the three per-page adapters are deleted.
  • Layout is the same. Only the tooltip on a group's selected level is a bit different.
image
  • The tooltip quotes each row's own reason, on both pages:
image

How did you test this code?

Test rationale: four clamp cases and one group case in the scopes test, as pure tests of the shared helpers. The regression they catch is the clamp direction: the key modal only ever lowers a row, the consent screen also raises a required one, and a single rule has to do both. The existing OAuth group action test keeps covering the logic end to end, with two tooltip strings updated and the app loaded so its name reaches the row reasons.

Run locally: the scopes, key logic, consent logic, and CLI authorize Jest suites.

Release status

  • No feature flag controls this change
  • This change is behind a feature flag and is not available to users
  • This change makes a previously flagged feature available to everyone

Automatic notifications

  • Publish to changelog?

Docs update

None.

🤖 Agent context

Started as a fix for two review comments on #110525 (the tooltip reason and a duplicated level-order map). Fixing them properly meant one row model for both pickers, which is a larger diff than that PR should carry, so it is its own PR.

@a-lider a-lider self-assigned this Oct 5, 2026
@a-lider
a-lider added this pull request to stack #112126 October 5, 2026 20:07
@greptile-apps

greptile-apps Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Retrigger

[Medium risk] Refactors scope picker components to reduce duplication.

The PR appears safe to merge; no new actionable issue or outstanding previous finding remains.

Reviews (2) · Last reviewed commit: "chore(scopes): name the scope picker row..."

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

✅ Trunk lane — non-backend lane

This PR is assigned to the non-backend lane. It does not run backend Python tests and may merge in parallel with PRs in other lanes.

⚠️ Complexity (TypeScript) — 8 functions above the limit (max 32)

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

Function Location Complexity Limit
OAuthAuthorize frontend/src/scenes/oauth/OAuthAuthorize.tsx:131 32 10
RenderStatus frontend/src/scenes/settings/user/PersonalAPIKeys.tsx:318 17 10
EditKeyModal frontend/src/scenes/settings/user/PersonalAPIKeys.tsx:38 15 10
<anonymous> frontend/src/scenes/oauth/oauthAuthorizeLogic.ts:839 13 10
handleAuthorize frontend/src/scenes/oauth/oauthAuthorizeLogic.ts:947 13 10
loadAllTeamsSuccess frontend/src/scenes/oauth/oauthAuthorizeLogic.ts:655 12 10
setEditingKeyId frontend/src/scenes/settings/user/personalAPIKeysLogic.tsx:744 12 10
describeOAuthError frontend/src/scenes/oauth/oauthAuthorizeLogic.ts:119 11 10
✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

🚨 Comment density — 8% of added code lines are comments (25 of 314)

This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.

Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.

Files with the most added comment lines:

File Comment lines Added lines
frontend/src/lib/scopes.tsx 16 76
frontend/src/scenes/oauth/oauthAuthorizeLogic.ts 3 27
frontend/src/lib/components/ScopeAccessRow/ScopeAccessRow.tsx 2 11
frontend/src/lib/scopes.test.ts 2 40
frontend/src/lib/components/ScopeAccessRow/ScopeAccessGroup.tsx 1 32
frontend/src/scenes/settings/user/personalAPIKeysLogic.tsx 1 17

This check does not block merging. It updates on every push and clears when the share drops.

⚠️ Bundle size — 🔺 +95.5 KiB (+0.1%)

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 76.42 MiB · 🔺 +95.5 KiB (+0.1%)

File Size Δ vs base
render-query/src/render-query/render-query.js 25.50 MiB 🔺 +49.2 KiB (+0.2%)
posthog-app/_parent/products/business_intelligence/frontend/BusinessIntelligenceScene.js 87.6 KiB 🔺 +14.3 KiB (+19.6%)
posthog-app/_parent/products/replay_vision/frontend/replay_scanners/components/variants/VariantsTab.js 14.0 KiB 🔺 +14.0 KiB (new)
posthog-app/src/scenes/saved-insights/SavedInsights.js 106.0 KiB 🔺 +13.4 KiB (+14.5%)
posthog-app/src/scenes/insights/InsightScene.js 53.7 KiB 🔺 +4.0 KiB (+8.0%)
posthog-app/src/layout/today/TodayProductsSidebar.js 3.9 KiB 🔺 +3.9 KiB (new)
posthog-app/_parent/products/alerts/frontend/views/InsightAlerts.js 13.3 KiB 🔺 +3.3 KiB (+33.4%)
posthog-app/src/layout/today/TodayToolsSidebar.js removed 🟢 -3.1 KiB (-100.0%)
posthog-app/src/scenes/product-tours/ProductTour.js 177.6 KiB 🟢 -3.0 KiB (-1.7%)
toolbar/src/toolbar/surveys/chunk-SurveySidebar.js 85.6 KiB 🟢 -3.0 KiB (-3.4%)
posthog-app/src/scenes/feature-flags/FeatureFlag.js 130.4 KiB 🟢 -3.0 KiB (-2.2%)
posthog-app/src/layout/today/TodayLibrarySidebar.js removed 🟢 -2.4 KiB (-100.0%)
posthog-app/_parent/products/managed_migrations/frontend/ManagedMigration.js 31.1 KiB 🔺 +2.1 KiB (+7.2%)
posthog-app/src/layout/today/TodayMoreSidebar.js removed 🟢 -2.0 KiB (-100.0%)
posthog-app/_parent/products/autoresearch/frontend/AutoresearchScene.js 16.0 KiB 🔺 +1.7 KiB (+11.9%)
exporter/src/queries/schema.js 1.25 MiB 🔺 +1.6 KiB (+0.1%)
posthog-app/src/queries/schema.js 1.25 MiB 🔺 +1.6 KiB (+0.1%)
exporter/src/exporter/scenes/ExporterNotebookScene.js 3.73 MiB 🔺 +1.6 KiB (+0.0%)
posthog-app/src/scenes/marketing-analytics/MarketingAnalyticsScene.js 156.2 KiB 🔺 +1.5 KiB (+1.0%)
posthog-app/_parent/products/cross_project_dashboards/frontend/CrossProjectDashboardScene.js 36.6 KiB 🔺 +1.4 KiB (+4.1%)
exporter/_parent/products/workflows/frontend/Workflows/Workflow.js 126.3 KiB 🔺 +1.4 KiB (+1.1%)
posthog-app/_parent/products/autoresearch/frontend/AutoresearchPipelineScene.js 55.5 KiB 🔺 +1.1 KiB (+2.1%)
posthog-app/_parent/products/tracing/frontend/TracingScene.js 188.5 KiB 🔺 +1013 B (+0.5%)

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.65 MiB · 23 files 🔺 +6.9 KiB (+0.4%) █████████░ 89.5% of 1.84 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
3.78 MiB · 669 files 🔺 +49.8 KiB (+1.3%) █████████░ 93.8% of 4.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.67 MiB · 2,420 files 🔺 +54.7 KiB (+0.7%) █████████░ 92.0% of 8.34 MiB
dashboard scene
src/scenes/dashboard/Dashboard.tsx
9.91 MiB · 3,500 files 🔺 +51.1 KiB (+0.5%) █████████░ 90.7% of 10.92 MiB
today home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
7.69 MiB · 2,432 files 🔺 +55.8 KiB (+0.7%) █████████░ 89.6% of 8.58 MiB
events scene
src/scenes/activity/explore/EventsScene.tsx
9.53 MiB · 3,352 files 🔺 +57.0 KiB (+0.6%) █████████░ 90.7% of 10.51 MiB
replay detail scene
src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
12.24 MiB · 4,159 files 🔺 +56.6 KiB (+0.5%) ████████░░ 77.9% of 15.72 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ 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
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json 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
🟢 products/dashboards/frontend/widgets/previews/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 zod/v4/locales/de.js stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/today/TodayReportPage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/activity/explore/EventsScene.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/index.tsx
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
839 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
221.0 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
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
99.7 KiB src/lib/api.ts
92.6 KiB src/products.tsx
68.7 KiB src/lib/lemon-ui/icons/icons.tsx
40.7 KiB src/lib/utils/eventUsageLogic.ts
38.7 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
29.0 KiB ../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/schemas.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
221.0 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
153.7 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
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.7 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.6 KiB src/products.tsx
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
221.0 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
181.9 KiB src/queries/validators.js
153.7 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
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.7 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.6 KiB src/products.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
221.0 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
153.7 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
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.7 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.6 KiB src/products.tsx
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
221.0 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
181.9 KiB src/queries/validators.js
153.7 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
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.7 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.6 KiB src/products.tsx
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
316.0 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
221.0 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
181.9 KiB src/queries/validators.js
153.7 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
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.7 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/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.23 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.23 MiB · 19 files 🔺 +15.8 KiB (+0.7%) ████░░░░░░ 39.0% of 5.72 MiB
Deferred (lazy) 2.11 MiB · 44 files 🟢 -2.3 KiB (-0.1%) n/a — loads on demand
Loader dist/toolbar.js 1.2 KiB no change █░░░░░░░░░ 6.0% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
858.2 KiB dist/toolbar/toolbar-app-TSGDYHMJ.css
668.2 KiB dist/toolbar/chunk-chunk-BEZ7CL3W.js
259.4 KiB dist/toolbar/chunk-chunk-5UE4YDI5.js
138.2 KiB dist/toolbar/chunk-chunk-XAXXAOIM.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
75.2 KiB dist/toolbar/toolbar-app-EGGUVSAV.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-5QWWC4HC.js
21.0 KiB dist/toolbar/chunk-chunk-47SXFC7V.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 — 🔺 +2.20 MiB (+0.2%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1004.27 MiB · 🔺 +2.20 MiB (+0.2%)

✅ Playwright — all passed

All tests passed.

View test results →

✅ Hogbox preview — ready, open the preview

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds: a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit 5b5c1a0 · box box-dd1702a8bdcb · ready in 1030s (push → usable) · build log · rebuilds on every push, torn down on close

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: PostHog/posthog/.coderabbit.yaml
  • Review profile: QUIET
  • Plan: Enterprise
  • Run ID: 5a4a1cb1-8de1-48bc-9d98-9e3fdb10deaa
📥 Commits

Reviewing files that changed from the base of the PR and between a67fd26 and 5b5c1a0.

📒 Files selected for processing (6)
  • frontend/src/lib/components/ScopeAccessRow/ScopeAccessGroup.tsx
  • frontend/src/lib/components/ScopeAccessRow/ScopeAccessRow.tsx
  • frontend/src/lib/integrations/PosthogConnect.tsx
  • frontend/src/scenes/authentication/cli/CLIAuthorize.tsx
  • frontend/src/scenes/oauth/OAuthAuthorize.tsx
  • frontend/src/scenes/settings/project/ProjectSecretAPIKeys.tsx

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.


📝 Walkthrough

Walkthrough

The change adds shared scope row and group models, access-level helpers, and reusable controls. OAuth authorization and personal API key editing now use the shared models and controls instead of local implementations. PostHog Connect, CLI authorization, and project secret API key interfaces adapt their scope rows to the shared row control. Tests cover level clamping, group-level selection, and tooltip reasons.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 5b5c1

This refactor consolidates the scope picker logic and keeps the layout the same. No concrete regression was found, so the merge risk is low. A typecheck and a quick manual check of the project secret API key picker would add confidence.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 5b5c1

The reviewed frontend flows preserve their existing permission limits and submission ownership. No introduced permission expansion was identified. Server-side enforcement was not independently verified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — A defect in the shared contract could affect permission selection across several credential and consent interfaces. Existing wildcard grants can have broad data access, but the inspected shared controls emit selection events rather than introducing a credential issuer or changing tenant-ownership fields.

Trust Boundaries and Controls

  • observed — User selections and OAuth scope metadata feed frontend scope construction. OAuth re-clamps selections before effective grant construction. Personal-key group updates use current row capabilities, and submission filters unavailable object keys while preserving wildcard access. These are client-side constraints; they do not establish authorization enforcement against forged requests at the server boundary.

Resilience and Maintainability Implications

  • observed — OAuth scope reload clears bulk and per-object selections, and subsequent selections are clamped against current scope metadata. Personal-key editing resets from the selected key; group changes resolve current rows and ignore unknown keys. The existing save path awaits the API result before success-state updates. These observations support local reset and recovery behavior, not backend atomicity or idempotency guarantees.
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description explains the problem, changes, screenshots, test rationale, release status, and docs update. It mostly follows the template. The release status uses checkboxes instead of the required …
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@trunk-io

trunk-io Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

View Full Report ↗︎ ⋅ Docs

Base automatically changed from alex/api-key-scope-groups to master October 6, 2026 16:27
@trunk-io

trunk-io Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

😎 Stack merged successfully - details.

…ckers

The consent screen and the key modal each described a picker row in its own
way, so each kept its own clamp, group level, and tooltip, plus an adapter
around the shared group control. Both now build the same row model, with a
disabled reason per level, and lib/scopes holds the clamp, group level, and
tooltip once. The three adapters are gone, and the tooltip names each row's
own reason, such as a project scoped key, instead of blaming the level.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FunWqqcMYpKX4EaFAzwbD
@a-lider
a-lider force-pushed the alex/scope-access-row-model branch from 13daba9 to 14abe92 Compare October 6, 2026 17:13
@hosthog

hosthog Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

HostHog preview — posthog-desktop-web

The previews for this PR have been torn down and no longer serve.

ScopeAccessRowModel and ScopeAccessGroupModel become ScopePickerRow and
ScopePickerGroup, the helpers drop the stray 'access', and the component that
renders a row from the model becomes ScopePickerRowItem. No behavior change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FunWqqcMYpKX4EaFAzwbD
@a-lider a-lider changed the title chore(scopes): share one row model between the OAuth and key scope pickers chore(scopes): clean up duplicated scope picker row logic Oct 6, 2026
@a-lider
a-lider marked this pull request as ready for review October 6, 2026 20:06
@a-lider
a-lider requested a review from a team October 6, 2026 20:06
@parameterai

parameterai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Risk: No findings

This increment finishes the scope-picker deduplication: ScopeAccessRow now takes the shared ScopePickerRow model directly, the ScopePickerRowItem adapter is deleted, and the four consumer pages (OAuth consent, CLI authorize, project secret keys, PostHog Connect) build rows inline. The refactor is behavior-preserving on every path I traced — disabled reasons, submit serialization, and callback signatures all match the pre-refactor behavior — and I found no new security issues.

Sentinel reviewed 5b5c1a0 · Review settings

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested review from a team, MattBro, fercgomes and rafaeelaudibert and removed request for a team October 6, 2026 20:07

@rafaeelaudibert rafaeelaudibert left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thank you! much nicer

The row control takes a ScopePickerRow and reports the scope object with the
level. The model-to-props wrapper is gone, and every picker builds a row: the
consent screen and the key modal from their logics, the project secret key,
CLI authorize, and PostHog Connect pickers inline from the same fields they
already computed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014FunWqqcMYpKX4EaFAzwbD
@a-lider

a-lider commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

5b5c1a0 extends the cleanup to the row control itself.

Also cleaned up

  • ScopeAccessRow now takes a ScopePickerRow and reports the scope object with the level. Its eight flat props are gone.
  • ScopePickerRowItem, the model-to-props wrapper, is deleted. The group and the consent screen render the row directly.
  • The three other scope pickers build a row from the fields they already computed: project secret API keys, CLI authorize, and PostHog Connect. No copy or behavior change on any of them.

So every picker in the app now describes a row the same way.

Tested locally on the running stack, by hand:

  • Project secret API keys: rows render with the right disabled segments, Read selects on Endpoint, the disabled Write shows "Not available for project secret API keys".
  • PostHog Connect: the dialog lists every scope, search narrows to Query, Read selects, Write stays disabled.
  • CLI authorize: the Agent CLI preset applies, Survey at Write shows the feature flag warning, switching it to Read removes the warning and flips the preset to a custom selection.
  • OAuth consent and the key modal were checked earlier on this branch.

Jest suites for all five pickers pass locally. Not run locally: typecheck and Storybook.

@a-lider

a-lider commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

/trunk merge

@trunk-io
trunk-io Bot merged commit 0864177 into master Oct 7, 2026
@trunk-io
trunk-io Bot deleted the alex/scope-access-row-model branch October 7, 2026 13:48
@deployment-status-posthog

deployment-status-posthog Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-10-07 14:17 UTC Run
prod-us ✅ Deployed 2026-10-07 14:35 UTC Run
prod-eu ✅ Deployed 2026-10-07 14:34 UTC Run

This branch was successfully deployed

1 active deployment
preview-pr-112124 — 5b5c1a0e Deployed Oct 7, 2026 by github-actions[bot]
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.

3 participants