Skip to content

feat(oauth): server-side scope assignment + /authorize enforcement#60477

Merged
MattBro merged 18 commits into
masterfrom
matt/oauth-app-scopes-foundation
Jun 1, 2026
Merged

feat(oauth): server-side scope assignment + /authorize enforcement#60477
MattBro merged 18 commits into
masterfrom
matt/oauth-app-scopes-foundation

Conversation

@MattBro
Copy link
Copy Markdown
Contributor

@MattBro MattBro commented May 28, 2026

Problem

OAuth scope assignment is client-driven today — the client puts a scope= parameter on /authorize and PostHog validates against the global OAUTH2_PROVIDER["SCOPES"] setting. There's no per-application ceiling, so privileged scopes (e.g. llm_gateway:read) need separate gates outside the scope system (the gateway's hardcoded application_id allowlist, the gateway-personal-api-key feature flag, the ALLOWED_PROVISIONING_SCOPES allowlist) that don't compose with self-serve registration.

The umbrella tracking issue (#60327) moves scope assignment to a server-stored ceiling on OAuthApplication.scopes. This PR delivers the first vertical slice end-to-end: the schema + constants + admin entry and the /authorize ceiling enforcement that consumes them, and refresh-path narrowing that caps refreshed tokens at the ceiling via get_original_scopes. Wildcard (*) token narrowing (#60330, coupled to #60342), the audit log, consent-UI granted-set display, and the agentic-provisioning direct-mint bypass (#60331) stay as their own follow-ups.

Changes

  • posthog/scopes.py — four new frozenset[str] constants for scope-string set arithmetic, alongside the existing *_SCOPE_OBJECTS sets. Naming convention (*_SCOPE_OBJECTS for objects, bare *_SCOPES for obj:action strings) documented inline.
    • ALL_SCOPES, PRIVILEGED_SCOPES = {"llm_gateway:read", "llm_gateway:write"}, OAUTH_HIDDEN_SCOPES (intersected with ALL_SCOPES), UNPRIVILEGED_SCOPES = ALL − PRIVILEGED − OAUTH_HIDDEN (broad default for empty-ceiling apps; OIDC scopes intentionally excluded — accepted at /authorize independently).
    • get_oauth_scopes_supported() refactored to derive from ALL_SCOPES - OAUTH_HIDDEN_SCOPES.
  • posthog/models/oauth.py:
    • OAuthApplication.scopes: ArrayField(CharField(max_length=100), default=list, db_default=[], blank=True, null=False). max_length=100 matches PersonalAPIKey.scopes. db_default=[] gives a persistent DEFAULT '{}'::varchar(100)[] NOT NULL.
    • OAuthAccessToken.label: CharField(max_length=40, default="", db_default="") — matches the PersonalAPIKey.label convention. Carried across refresh in a later slice.
  • posthog/migrations/1187_oauthaccesstoken_label_oauthapplication_scopes.py — generated migration. sqlmigrate confirms DEFAULT '' NOT NULL for label and DEFAULT '{}'::varchar(100)[] NOT NULL for scopes (persistent, no DROP DEFAULT).
  • posthog/admin/admins/oauth_admin.pyscopes added to the Authorization fieldset in both views.
  • posthog/api/oauth/views.pyOAuthValidator.validate_scopes override on the existing class OAuthValidator(OAuth2Validator). Resolution rule:
    • empty scope= → mutate request.scopes to effective | OIDC_ALLOWED (otherwise oauthlib's default-resolution leaves just ["openid"]).
    • in-set + openid/profile/email/introspection → grant as requested.
    • outside the union (including * when the app has a non-empty ceiling) → InvalidScopeError → RFC 6749 error=invalid_scope. GET = 302 redirect with error=invalid_scope in Location; POST = JSON redirect_to carrying the error.
    • Empty application.scopes resolves to UNPRIVILEGED_SCOPES; * is accepted in that mode for backward compat with the Code CLI.

Why the validator hook, not SCOPES_BACKEND_CLASS

Both receive application=request.client and both run inside create_authorization_response before any grant or token row is written (oauthlib/oauth2/rfc6749/grant_types/authorization_code.py:419). The discriminator: SCOPES_BACKEND_CLASS also drives oauth2_provider/views/base.py:162-163 (the consent template's scope catalog) and get_default_scopes resolution via the _DEFAULT_SCOPES __all__ branch (oauth2_provider/settings.py:235-246), so a per-app subclass entangles ceiling enforcement with UI enumeration and default-scope handling. Keeping enforcement on OAuthValidator puts it in the same class that already owns CIMD/DCR/impersonation/redirect-URI policy — one place to look for per-app gating.

Live-traffic safety

  • Existing scope="*" tokens keep working. get_original_scopes is now overridden to intersect refreshed scopes with the app ceiling, but * tokens are deliberately left untouched (narrowing one would empty it). So a long-lived * token keeps refreshing into a new * token until wildcard retirement (chore(oauth): retire the * wildcard #60342 / feat(oauth): narrow scopes on refresh + carry token name #60330). Non-* tokens are narrowed to the current ceiling on refresh.
  • DCR / CIMD apps default to scopes=[] → broad default → no behavior change.
  • _get_legacy_stripe_oauth_app lazy-creates with scopes=[] → broad default → legacy Stripe keeps working via the posthog/auth.py:87 bypass.
  • approval_prompt=auto when a stored token's scope is outside a newly-tightened ceiling: falls through to the consent screen, where the second create_authorization_response rejects with invalid_scope. Not a regression — degraded auto-approve. Worth a partner heads-up if anyone tightens a ceiling on a live app.

Behavioral change for existing users (deploy-coordinate item)

scope=llm_gateway:read and llm_gateway:write are newly rejected at /authorize for any app whose scopes field is not seeded with them. They were accepted by djoauth's default validator before this PR (they're in OAUTH2_PROVIDER["SCOPES"]); now they're in PRIVILEGED_SCOPES, which the broad-default UNPRIVILEGED_SCOPES excludes.

  • Existing access tokens keep working through the rollout — apps have no ceiling set yet, and an empty OAuthApplication.scopes is a no-op on refresh; * tokens are never narrowed (see feat(oauth): narrow scopes on refresh + carry token name #60330 / chore(oauth): retire the * wildcard #60342).
  • The hazard surfaces on the next /authorize redirect: any first-party app whose hardcoded scope= includes llm_gateway:read (wizard CLI, posthog_code CLI, toolbar, etc.) will get invalid_scope unless an admin has set its scopes field to include llm_gateway:read first.
  • Deploy coordination: before this lands on prod, admin-seed the first-party apps' scopes field with their current de-facto sets (including llm_gateway:* where applicable) in both US and EU. The RFC's migration step 2 covers exactly this; it needs to happen as part of the rollout.

scope=wizard_session:* newly rejected too (moved to OAUTH_HIDDEN_SCOPES). Practical impact is near-zero since wizard_session is alpha/PAT-only and OAuth clients shouldn't be requesting it, but flagging.

Empty scope= is unchanged — oauthlib's pre-call default-resolution still substitutes ["openid"] from DEFAULT_SCOPES before the override sees it, so the empty-request branch in the override is defensive and not the live path.

Out of scope (explicitly)

How did you test this code?

I'm an agent (Claude). Both automated and live-sandbox manual verification.

Automated

  • New TestScopeSets (12 tests, posthog/test/test_scopes.py): set algebra (UNPRIVILEGED excludes privileged / hidden / OIDC / internal; subset of ALL_SCOPES); the scopes module loads via runpy.run_path without Django (mirroring bin/build-mcp-oauth-scopes.py); every obj:action fits the 100-char field.
  • New model-default tests (4 tests, posthog/models/test/test_oauth.py): scopes defaults to [] and persists explicit lists; label defaults to "" and persists explicit values.
  • 6 new /authorize ceiling tests (posthog/api/oauth/test_views.py) covering the four resolution branches: reject-out-of-ceiling, accept-in-ceiling, empty-ceiling-falls-back-to-UNPRIVILEGED, OIDC + introspection bypass the ceiling, * rejected with explicit ceiling, * accepted with empty ceiling.
  • Regression on direct consumers — posthog/models/test/test_oauth.py (49), posthog/test/test_scopes.py (21), posthog/admin/test_oauth_admin.py, posthog/temporal/tests/test_oauth.py, posthog/api/oauth/test_dcr.py, posthog/api/oauth/test_cimd.py, ee/api/agentic_provisioning/test/test_resources.py, ee/api/agentic_provisioning/test/test_scope_validation.py — all green. Scope-sensitive test_views.py cases (test_full_oidc_flow, test_id_token_not_returned_without_openid_scope, test_scope_persistence_through_refresh, test_invalid_scope_validation_with_and_without_trailing_slash) green — zero flipped expectations.
  • python manage.py makemigrations --check --dry-run clean.
  • python manage.py analyze_migration_risklabel safe; scopes flagged "callable default list — verify stable" (it's stable).
  • python manage.py sqlmigrate posthog 1187 confirms expected SQL.
  • ruff check / ruff format clean.

Pre-existing on the local worktree (unrelated to this PR): test_views.py has ~10 TemplateDoesNotExist: index.html failures on the GET path that renders the React shell (the frontend isn't built in that checkout). Reproduced on master with my commits reverted; CI runs against a properly built frontend.

Manual e2e against a live sandbox

Spun up bin/sandbox create matt/oauth-app-scopes-foundation (port 48010). Verified the migration applied at the Postgres level:

SELECT column_name, data_type, column_default, is_nullable FROM information_schema.columns
 WHERE table_name='posthog_oauthapplication' AND column_name='scopes';
-- scopes | ARRAY | '{}'::character varying(100)[] | NO

SELECT column_name, data_type, column_default, is_nullable FROM information_schema.columns
 WHERE table_name='posthog_oauthaccesstoken' AND column_name='label';
-- label  | character varying | ''::character varying | NO

Existing app row (PostHog Streamlit Apps) backfilled to scopes=[].

Drove Chrome through /oauth/authorize against that app for every resolution branch by flipping OAuthApplication.scopes via Django shell and hitting the URL directly. PKCE: code_verifier=test_verifier_must_be_43_chars_long_xxxxxx.

# App ceiling scope= requested Result observed in browser
1 ["experiment:read"] experiment:write redirected to https://localhost/?error=invalid_scope
2 ["experiment:read"] experiment:read consent screen, "Read access to experiments"
3 ["experiment:read"] * redirected to https://localhost/?error=invalid_scope
4 ["experiment:read"] openid consent screen (OIDC bypassed the ceiling)
5 [] (broad default) llm_gateway:read redirected to https://localhost/?error=invalid_scope
6 [] (broad default) * consent screen, "Read and write access to all PostHog data" (Code CLI compat preserved)

All six match the pytest contract. The consent-screen renders (cases 2/4/6) confirm the validator returned True and oauthlib persisted request.scopes into the grant; the redirect-to-error=invalid_scope cases (1/3/5) confirm rejection lands as RFC 6749 error=invalid_scope on the GET branch. App state restored to is_first_party=True, scopes=[] after the run.

Publish to changelog?

no

Docs update

skip-inkeep-docs

🤖 Agent context

Authored by Claude Code (Opus 4.7).

Process:

  • Three parallel reviewer agents read the RFC against current master before any code was written and surfaced six premise corrections that affect scoping (baked into the parent tracking issues [Tracking] Server-side scope assignment for OAuthApplications (RFC #1103) #60327 / feat(oauth): enforce per-app scope ceiling at /authorize #60329).
  • After the first commit, /pr-ready self-review caught five items that fed into the second commit (rename namelabel, intersect OAUTH_HIDDEN_SCOPES with ALL_SCOPES, switch the import-without-Django test to runpy, align max_length, drop forward-looking help_text).
  • After Rafa's CHANGES_REQUESTED + greptile + veria-ai review, a third commit applied his suggestions (db_default=[], llm_gateway:write in PRIVILEGED_SCOPES, refactor get_oauth_scopes_supported, parameterize loop-tests, drop the label-explainer comment). One deviation flagged inline: kept blank=True because default=list produces [] which Django's Field.validate treats as blank, so blank=False rejects every OAuthApplication.save().
  • A second research pass (three more parallel agents — djoauth hook validation, /authorize flow trace, Rafa-pattern + audit-log-scope) settled the enforcement hook choice on OAuthValidator.validate_scopes over SCOPES_BACKEND_CLASS and confirmed the addition was small enough (~30 LOC + 6 tests, 0 flipped expectations) to fold into this PR rather than ship as a separate slice.

Key calls preserved on the record:

  • Kept OAUTH_HIDDEN_SCOPE_OBJECTS (object set) untouched rather than renaming per the RFC; renaming would have mixed scope-objects and scope-strings in one identifier. OAUTH_HIDDEN_SCOPES (string form) lives alongside.
  • OAuthApplication.scopes uses db_default=[] (literal) not db_default=list (callable) — Django's SQL adapter crashes on the callable form (cannot adapt type 'type'). The literal gives the same persistent DEFAULT '{}'::varchar(100)[] NOT NULL.
  • * rejection only when the app has a non-empty ceiling. Empty-ceiling apps (DCR/CIMD/legacy Stripe/Code CLI) still accept * until chore(oauth): retire the * wildcard #60342 lands.

Tooling: gh CLI, pytest, ruff, Django makemigrations / sqlmigrate / analyze_migration_risk, bin/sandbox for the live e2e, Chrome via the in-chrome MCP for driving /authorize.

Adds OAuthApplication.scopes ArrayField and OAuthAccessToken.name
CharField, plus scope-classification string constants in posthog.scopes
(ALL_SCOPES, PRIVILEGED_SCOPES, HIDDEN_SCOPES, UNPRIVILEGED_SCOPES).

No behavior change. The /authorize ceiling-enforcement override that
consumes these is the follow-up PR for #60329.

The existing object-set constants (INTERNAL_API_SCOPE_OBJECTS,
OAUTH_HIDDEN_SCOPE_OBJECTS) are left untouched so their consumers in
temporal/oauth.py, downgrade_scopes_to_read_only and the rbac/PAT
paths keep working. The new string-set constants are what
OAuthApplication.scopes / UNPRIVILEGED_SCOPES arithmetic uses.

OAuthAccessToken.name gets db_default="" so the Postgres-level
default survives external writers. OAuthApplication.scopes uses
default=list - Django backfills existing rows in the migration, and
there are no non-Django writers to posthog_oauthapplication today.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MattBro MattBro requested review from a team, fercgomes and rafaeelaudibert and removed request for a team May 28, 2026 16:41
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

Migration SQL Changes

Hey 👋, we've detected some migrations on this PR. Here's the SQL output for each migration, make sure they make sense:

posthog/migrations/1193_oauthaccesstoken_label_oauthapplication_scopes.py

BEGIN;
--
-- Add field label to oauthaccesstoken
--
ALTER TABLE "posthog_oauthaccesstoken" ADD COLUMN "label" varchar(40) DEFAULT '' NOT NULL;
--
-- Add field scopes to oauthapplication
--
ALTER TABLE "posthog_oauthapplication" ADD COLUMN "scopes" varchar(100)[] DEFAULT '{}'::varchar(100)[] NOT NULL;
COMMIT;

Last updated: 2026-06-01 14:24 UTC (9b52e0c)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

🔍 Migration Risk Analysis

We've analyzed your migrations for potential risks.

Summary: 0 Safe | 1 Needs Review | 0 Blocked

⚠️ Needs Review

May have performance impact

posthog.1193_oauthaccesstoken_label_oauthapplication_scopes
  └─ #1 ✅ AddField
     Adding NOT NULL field with constant default (safe in PG11+)
     model: oauthaccesstoken, field: label
  └─ #2 ⚠️ AddField
     Adding NOT NULL field with callable default (list) - verify it's stable
     model: oauthapplication, field: scopes, default: list

Last updated: 2026-06-01 14:24 UTC (9b52e0c)

- Rename OAuthAccessToken.name -> label to match the existing
  PersonalAPIKey.label convention; max_length 40 to match.
- Rename HIDDEN_SCOPES -> OAUTH_HIDDEN_SCOPES so the string-form
  mirrors the OAUTH_HIDDEN_SCOPE_OBJECTS source. Document the
  *_SCOPE_OBJECTS / bare *_SCOPES convention in posthog/scopes.py.
- Intersect OAUTH_HIDDEN_SCOPES with ALL_SCOPES so a future hidden
  object with a narrowed action set can't carry a phantom string.
- Rewrite the import-without-Django test to use runpy.run_path,
  matching bin/build-mcp-oauth-scopes.py. The previous subprocess
  test passed for the wrong reasons - import posthog.scopes runs
  posthog/__init__.py which pulls in Django anyway.
- Use API_SCOPE_ACTIONS in the OAUTH_HIDDEN_SCOPES test instead of
  hardcoded ("read", "write").
- Soften OAuthApplication.scopes help_text to flag that /authorize
  enforcement isn't live yet (lands in the follow-up PR).
- OAuthApplication.scopes inner CharField max_length 100 to match
  PersonalAPIKey.scopes (was 64).
- Comment OAuthApplication.scopes db_default omission rationale.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MattBro MattBro marked this pull request as ready for review May 28, 2026 17:05
@MattBro MattBro requested a review from a team May 28, 2026 17:06
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 28, 2026

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
posthog/scopes.py:159
**`llm_gateway:write` missing from `PRIVILEGED_SCOPES`**

`PRIVILEGED_SCOPES` only contains `"llm_gateway:read"`, but `llm_gateway` is in `API_SCOPE_OBJECTS` and both actions are in `API_SCOPE_ACTIONS`, so `"llm_gateway:write"` lands in `UNPRIVILEGED_SCOPES` and will be grantable via self-serve CIMD/DCR registration when the enforcement override ships. The test `test_all_scopes_contains_known_strings` explicitly asserts `"llm_gateway:write"` is in `ALL_SCOPES`, confirming the scope exists. If write access to the LLM gateway should be admin-only too, `PRIVILEGED_SCOPES` should include `"llm_gateway:write"` alongside `"llm_gateway:read"`.

### Issue 2 of 2
posthog/test/test_scopes.py:89-135
**Loops instead of parameterized tests**

Several `TestScopeSets` methods iterate hardcoded tuples inside a single test method (e.g. `test_unprivileged_scopes_excludes_oidc`, `test_unprivileged_scopes_covers_known_public_scopes`) rather than using `@parameterized.expand`, which is already used in the same file for `TestDowngradeScopesToReadOnly`. A failure inside the loop only reports one test name and stops at the first failing value, making it harder to see which scope caused the issue.

Reviews (1): Last reviewed commit: "chore(oauth): address pr-ready review fe..." | Re-trigger Greptile

Comment thread posthog/scopes.py Outdated
Comment thread posthog/test/test_scopes.py
Comment thread posthog/migrations/1187_oauthaccesstoken_label_oauthapplication_scopes.py Outdated
Comment thread posthog/models/oauth.py Outdated
Comment thread posthog/models/oauth.py Outdated
Comment thread posthog/scopes.py Outdated
Comment thread posthog/scopes.py
Copy link
Copy Markdown
Member

@rafaeelaudibert rafaeelaudibert left a comment

Choose a reason for hiding this comment

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

See comments above

- Add llm_gateway:write to PRIVILEGED_SCOPES (greptile + rafa).
- Refactor get_oauth_scopes_supported to derive from
  ALL_SCOPES - OAUTH_HIDDEN_SCOPES (rafa: replaced by the logic above).
- OAuthApplication.scopes: db_default=[] gives a persistent
  Postgres-level DEFAULT '{}'::varchar(100)[] (rafa's suggestion;
  db_default=list crashes Django's SQL adapter, the literal works).
  Help_text trimmed of forward-looking text per rafa. Kept blank=True
  because default=list produces [] which Django treats as blank;
  blank=False rejects every OAuthApplication.save().
- Drop the label-naming explainer comment (rafa).
- Parameterize the loop-based tests in TestScopeSets (greptile).
- Regenerate migration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread posthog/models/oauth.py
@veria-ai
Copy link
Copy Markdown

veria-ai Bot commented May 28, 2026

PR overview

This pull request adds server-side OAuth scope assignment and enforces requested scopes during the /authorize flow. It updates OAuth view logic to apply application-level scope ceilings when issuing tokens.

The PR has made progress with 2 issues already addressed, but one authorization gap remains open. Existing refresh tokens can still be exchanged for scopes that exceed a newly narrowed application scope ceiling, allowing continued access beyond what an admin currently permits. This should be tightened by intersecting refresh-token scopes with the current ceiling or rejecting refreshes when no allowed scopes remain.

Open issues (1)

Fixed/addressed: 2 · PR risk: 7/10

Missed re-running ruff format after the last makemigrations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the OAuthValidator.validate_scopes override that consumes the
OAuthApplication.scopes field this PR added.

Resolution:
- empty scope= -> grant the effective ceiling (mutate request.scopes
  so oauthlib's default-resolution doesn't fall back to just ["openid"]
  from DEFAULT_SCOPES)
- in-set + OIDC/introspection -> grant as requested
- outside the union -> InvalidScopeError -> RFC 6749 invalid_scope
  (GET = 302 with error=invalid_scope in Location; POST = JSON
  redirect_to carrying the error)

OIDC + introspection are accepted independently of the per-app
ceiling. They're identity/token-management scopes, not resource
permissions; rejecting them would break every /authorize since
DEFAULT_SCOPES = ["openid"].

`*` is rejected when the app has an explicit ceiling, accepted when
the ceiling is empty (broad-default). Existing Code CLI broad-default
behavior is preserved until wildcard retirement (#60342).

Live-traffic safety: refresh path uses get_original_scopes and
doesn't re-run validate_scopes, so existing scope="*" tokens keep
working until the refresh window expires. Refresh narrowing is the
explicit job of #60330 and stays separate. The agentic-provisioning
direct-mint at ee/api/agentic_provisioning/views.py:997 also bypasses
this hook (creates the token by hand); the inline ceiling check
there is #60331.

6 new tests in test_views.py cover the 4 resolution branches plus
the empty-ceiling fallback and wildcard handling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MattBro MattBro changed the title feat(oauth): foundation for server-side scope assignment feat(oauth): server-side scope assignment + /authorize enforcement May 28, 2026
MattBro and others added 2 commits May 29, 2026 10:28
ty type-check failure - the helper returns HttpResponse, not dict.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…es-foundation

# Conflicts:
#	posthog/api/oauth/views.py
#	posthog/migrations/max_migration.txt
Copy link
Copy Markdown
Member

@rafaeelaudibert rafaeelaudibert left a comment

Choose a reason for hiding this comment

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

Approving, but leaving one comment that should, hopefully, be fixed

Comment thread posthog/scopes.py
MattBro and others added 2 commits May 29, 2026 18:33
…es-foundation

# Conflicts:
#	posthog/migrations/max_migration.txt
get_oauth_scopes_supported() now derives from UNPRIVILEGED_SCOPES, so the
scopes_supported list published at /.well-known/oauth-authorization-server
(and the MCP protected-resource metadata generated from it) no longer
advertises llm_gateway:read / llm_gateway:write. Those are admin-granted
only and can't be obtained self-serve, so discovery shouldn't surface them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 29, 2026

Size Change: 0 B

Total Size: 80.9 MB

ℹ️ View Unchanged
Filename Size
frontend/dist-report/decompression-worker/src/scenes/session-recordings/player/snapshot-processing/decompressionWorker 2.85 kB
frontend/dist-report/exporter/_chunks/chunk 8.43 MB
frontend/dist-report/exporter/_parent/products/actions/frontend/pages/Action 25 kB
frontend/dist-report/exporter/_parent/products/actions/frontend/pages/Actions 1.33 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/AIObservabilityScene 118 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/AIObservabilitySessionScene 19.8 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/AIObservabilityTraceScene 130 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/AIObservabilityUsers 872 B
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/clusters/AIObservabilityClusterScene 21.7 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/clusters/AIObservabilityClustersScene 55.1 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/datasets/AIObservabilityDatasetScene 21 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/datasets/AIObservabilityDatasetsScene 3.64 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/evaluations/AIObservabilityEvaluation 59.9 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/evaluations/AIObservabilityEvaluationsScene 28.2 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/evaluations/EvaluationTemplates 915 B
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/LLMASessionFeedbackDisplay 5.19 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/playground/AIObservabilityPlaygroundScene 37.8 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/prompts/LLMPromptScene 29.2 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/prompts/LLMPromptsScene 4.83 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/skills/LLMSkillScene 929 B
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/skills/LLMSkillsScene 946 B
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/tags/AIObservabilityTag 27.4 kB
frontend/dist-report/exporter/_parent/products/ai_observability/frontend/tags/AIObservabilityTagsScene 7.31 kB
frontend/dist-report/exporter/_parent/products/business_knowledge/frontend/scenes/BusinessKnowledgeScene 19 kB
frontend/dist-report/exporter/_parent/products/conversations/frontend/components/Assignee/CyclotronJobInputAssignee 1.67 kB
frontend/dist-report/exporter/_parent/products/conversations/frontend/components/SlaBusinessHours/CyclotronJobInputBusinessHours 3.06 kB
frontend/dist-report/exporter/_parent/products/conversations/frontend/components/TicketTags/CyclotronJobInputTicketTags 1.06 kB
frontend/dist-report/exporter/_parent/products/conversations/frontend/scenes/settings/SupportSettingsScene 1.82 kB
frontend/dist-report/exporter/_parent/products/conversations/frontend/scenes/ticket/SupportTicketScene 33.9 kB
frontend/dist-report/exporter/_parent/products/conversations/frontend/scenes/tickets/SupportTicketsScene 1.07 kB
frontend/dist-report/exporter/_parent/products/customer_analytics/frontend/CustomerAnalyticsScene 53.1 kB
frontend/dist-report/exporter/_parent/products/customer_analytics/frontend/scenes/CustomerAnalyticsConfigurationScene/CustomerAnalyticsConfigurationScene 2.65 kB
frontend/dist-report/exporter/_parent/products/customer_analytics/frontend/scenes/CustomerJourneyBuilderScene/CustomerJourneyBuilderScene 2.18 kB
frontend/dist-report/exporter/_parent/products/customer_analytics/frontend/scenes/CustomerJourneyTemplatesScene/CustomerJourneyTemplatesScene 7.86 kB
frontend/dist-report/exporter/_parent/products/data_warehouse/DataWarehouseScene 46.8 kB
frontend/dist-report/exporter/_parent/products/data_warehouse/frontend/scenes/NewSourceScene/NewSourceScene 1.12 kB
frontend/dist-report/exporter/_parent/products/data_warehouse/frontend/scenes/SchemaScene/SchemaScene 24.4 kB
frontend/dist-report/exporter/_parent/products/data_warehouse/frontend/scenes/SourceScene/SourceScene 1.06 kB
frontend/dist-report/exporter/_parent/products/data_warehouse/frontend/scenes/SourcesScene/SourcesScene 6.31 kB
frontend/dist-report/exporter/_parent/products/deployments/frontend/Deployment 4.05 kB
frontend/dist-report/exporter/_parent/products/deployments/frontend/DeploymentProject 5.58 kB
frontend/dist-report/exporter/_parent/products/deployments/frontend/Deployments 9.31 kB
frontend/dist-report/exporter/_parent/products/early_access_features/frontend/EarlyAccessFeature 1.02 kB
frontend/dist-report/exporter/_parent/products/early_access_features/frontend/EarlyAccessFeatures 3.24 kB
frontend/dist-report/exporter/_parent/products/endpoints/frontend/EndpointScene 40.6 kB
frontend/dist-report/exporter/_parent/products/endpoints/frontend/EndpointsScene 24.5 kB
frontend/dist-report/exporter/_parent/products/error_tracking/frontend/scenes/ErrorTrackingFingerprintsScene/ErrorTrackingIssueFingerprintsScene 7.41 kB
frontend/dist-report/exporter/_parent/products/error_tracking/frontend/scenes/ErrorTrackingIssueScene/ErrorTrackingIssueScene 104 kB
frontend/dist-report/exporter/_parent/products/error_tracking/frontend/scenes/ErrorTrackingScene/ErrorTrackingScene 27.1 kB
frontend/dist-report/exporter/_parent/products/feature_flags/frontend/FeatureFlagTemplatesScene 7.38 kB
frontend/dist-report/exporter/_parent/products/games/368Hedgehogs/368Hedgehogs 5.61 kB
frontend/dist-report/exporter/_parent/products/games/FlappyHog/FlappyHog 6.12 kB
frontend/dist-report/exporter/_parent/products/legal_documents/frontend/scenes/LegalDocumentNewScene 59.7 kB
frontend/dist-report/exporter/_parent/products/legal_documents/frontend/scenes/LegalDocumentsScene 5.31 kB
frontend/dist-report/exporter/_parent/products/links/frontend/LinkScene 25.2 kB
frontend/dist-report/exporter/_parent/products/links/frontend/LinksScene 4.55 kB
frontend/dist-report/exporter/_parent/products/live_debugger/frontend/LiveDebugger 19.5 kB
frontend/dist-report/exporter/_parent/products/logs/frontend/LogsScene 17.9 kB
frontend/dist-report/exporter/_parent/products/logs/frontend/scenes/LogsAlertDetailScene/LogsAlertDetailScene 17.2 kB
frontend/dist-report/exporter/_parent/products/logs/frontend/scenes/LogsAlertNotificationDetailScene/LogsAlertNotificationDetailScene 8.49 kB
frontend/dist-report/exporter/_parent/products/logs/frontend/scenes/LogsSamplingDetailScene/LogsSamplingDetailScene 5.3 kB
frontend/dist-report/exporter/_parent/products/logs/frontend/scenes/LogsSamplingNewScene/LogsSamplingNewScene 2.25 kB
frontend/dist-report/exporter/_parent/products/managed_migrations/frontend/ManagedMigration 14.9 kB
frontend/dist-report/exporter/_parent/products/mcp_analytics/frontend/MCPAnalyticsScene 40.6 kB
frontend/dist-report/exporter/_parent/products/mcp_analytics/frontend/MCPAnalyticsToolDetail 18.5 kB
frontend/dist-report/exporter/_parent/products/metrics/frontend/MetricsScene 16.2 kB
frontend/dist-report/exporter/_parent/products/product_analytics/frontend/insights/stickiness/StickinessBarChart/StickinessBarChart 3.31 kB
frontend/dist-report/exporter/_parent/products/product_analytics/frontend/insights/stickiness/StickinessLineChart/StickinessLineChart 3.14 kB
frontend/dist-report/exporter/_parent/products/product_analytics/frontend/insights/trends/TrendsBarChart/TrendsBarChart 7.36 kB
frontend/dist-report/exporter/_parent/products/product_analytics/frontend/insights/trends/TrendsLifecycleChart/TrendsLifecycleChart 4.41 kB
frontend/dist-report/exporter/_parent/products/product_analytics/frontend/insights/trends/TrendsLineChart/TrendsLineChart 4.6 kB
frontend/dist-report/exporter/_parent/products/product_analytics/frontend/insights/trends/TrendsPieChart/TrendsPieChart 4.35 kB
frontend/dist-report/exporter/_parent/products/replay_vision/frontend/observations/ReplayObservation 8.14 kB
frontend/dist-report/exporter/_parent/products/replay_vision/frontend/replay_scanners/ReplayScanner 34 kB
frontend/dist-report/exporter/_parent/products/replay_vision/frontend/replay_scanners/ReplayScannersScene 11.6 kB
frontend/dist-report/exporter/_parent/products/replay_vision/frontend/replay_scanners/ScannerTemplatesScene 4.59 kB
frontend/dist-report/exporter/_parent/products/revenue_analytics/frontend/RevenueAnalyticsScene 26.5 kB
frontend/dist-report/exporter/_parent/products/session_summaries/frontend/SessionGroupSummariesTable 5.05 kB
frontend/dist-report/exporter/_parent/products/session_summaries/frontend/SessionGroupSummaryScene 19.2 kB
frontend/dist-report/exporter/_parent/products/tasks/frontend/SlackTaskContextScene 8.88 kB
frontend/dist-report/exporter/_parent/products/tasks/frontend/TaskDetailScene 23.8 kB
frontend/dist-report/exporter/_parent/products/tasks/frontend/TaskTracker 14.6 kB
frontend/dist-report/exporter/_parent/products/tracing/frontend/TracingScene 54.4 kB
frontend/dist-report/exporter/_parent/products/user_interviews/frontend/UserInterview 9.32 kB
frontend/dist-report/exporter/_parent/products/user_interviews/frontend/UserInterviewResponse 7.79 kB
frontend/dist-report/exporter/_parent/products/user_interviews/frontend/UserInterviews 6.08 kB
frontend/dist-report/exporter/_parent/products/visual_review/frontend/scenes/VisualReviewIndexScene 2.56 kB
frontend/dist-report/exporter/_parent/products/visual_review/frontend/scenes/VisualReviewRunScene 44.7 kB
frontend/dist-report/exporter/_parent/products/visual_review/frontend/scenes/VisualReviewRunsScene 7.32 kB
frontend/dist-report/exporter/_parent/products/visual_review/frontend/scenes/VisualReviewSettingsScene 11.1 kB
frontend/dist-report/exporter/_parent/products/visual_review/frontend/scenes/VisualReviewSnapshotHistoryScene 13.9 kB
frontend/dist-report/exporter/_parent/products/visual_review/frontend/scenes/VisualReviewSnapshotOverviewScene 19.6 kB
frontend/dist-report/exporter/_parent/products/workflows/frontend/TemplateLibrary/MessageTemplate 16.6 kB
frontend/dist-report/exporter/_parent/products/workflows/frontend/Workflows/WorkflowScene 111 kB
frontend/dist-report/exporter/_parent/products/workflows/frontend/WorkflowsScene 60.2 kB
frontend/dist-report/exporter/src/exporter/exporter 19.7 kB
frontend/dist-report/exporter/src/exporter/scenes/ExporterDashboardScene 2.02 kB
frontend/dist-report/exporter/src/exporter/scenes/ExporterHeatmapScene 19.9 kB
frontend/dist-report/exporter/src/exporter/scenes/ExporterInsightScene 3.02 kB
frontend/dist-report/exporter/src/exporter/scenes/ExporterInterviewScene 310 kB
frontend/dist-report/exporter/src/exporter/scenes/ExporterNotebookScene 2.71 MB
frontend/dist-report/exporter/src/exporter/scenes/ExporterRecordingScene 1.13 kB
frontend/dist-report/exporter/src/exporterSharedChunkAnchors 1.19 kB
frontend/dist-report/exporter/src/lib/components/Cards/TextCard/TextCardMarkdownEditor 11.3 kB
frontend/dist-report/exporter/src/lib/components/MonacoDiffEditor 471 B
frontend/dist-report/exporter/src/lib/lemon-ui/LemonMarkdown/MermaidDiagram 2.25 kB
frontend/dist-report/exporter/src/lib/lemon-ui/LemonTextArea/LemonTextAreaMarkdown 842 B
frontend/dist-report/exporter/src/lib/lemon-ui/Link/Link 359 B
frontend/dist-report/exporter/src/lib/monaco/CodeEditorInline 832 B
frontend/dist-report/exporter/src/lib/monaco/vimMode 211 kB
frontend/dist-report/exporter/src/lib/ui/Button/ButtonPrimitives 422 B
frontend/dist-report/exporter/src/queries/nodes/WebVitals/WebVitals 7.52 kB
frontend/dist-report/exporter/src/queries/nodes/WebVitals/WebVitalsPathBreakdown 4.09 kB
frontend/dist-report/exporter/src/queries/schema 853 kB
frontend/dist-report/exporter/src/scenes/approvals/changeRequestsLogic 884 B
frontend/dist-report/exporter/src/scenes/authentication/passkeyLogic 824 B
frontend/dist-report/exporter/src/scenes/data-pipelines/event-filtering/EventFilterScene 22.2 kB
frontend/dist-report/exporter/src/scenes/data-pipelines/TransformationsScene 6.54 kB
frontend/dist-report/exporter/src/scenes/insights/views/BoxPlot/BoxPlot 5.39 kB
frontend/dist-report/exporter/src/scenes/insights/views/CalendarHeatMap/CalendarHeatMap 8.84 kB
frontend/dist-report/exporter/src/scenes/insights/views/RegionMap/RegionMap 29.8 kB
frontend/dist-report/exporter/src/scenes/insights/views/WorldMap/WorldMap 1.04 MB
frontend/dist-report/exporter/src/scenes/models/ModelsScene 19 kB
frontend/dist-report/exporter/src/scenes/models/NodeDetailScene 17 kB
frontend/dist-report/monaco-editor-worker/src/lib/monaco/workers/monacoEditorWorker 288 kB
frontend/dist-report/monaco-json-worker/src/lib/monaco/workers/monacoJsonWorker 419 kB
frontend/dist-report/monaco-typescript-worker/src/lib/monaco/workers/monacoTsWorker 7.02 MB
frontend/dist-report/posthog-app/_chunks/chunk 8.63 MB
frontend/dist-report/posthog-app/_parent/products/actions/frontend/pages/Action 25.1 kB
frontend/dist-report/posthog-app/_parent/products/actions/frontend/pages/Actions 1.4 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/AIObservabilityScene 119 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/AIObservabilitySessionScene 19.8 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/AIObservabilityTraceScene 130 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/AIObservabilityUsers 906 B
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/clusters/AIObservabilityClusterScene 21.7 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/clusters/AIObservabilityClustersScene 55.1 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/datasets/AIObservabilityDatasetScene 21 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/datasets/AIObservabilityDatasetsScene 3.67 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/evaluations/AIObservabilityEvaluation 59.9 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/evaluations/AIObservabilityEvaluationsScene 28.2 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/evaluations/EvaluationTemplates 949 B
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/LLMASessionFeedbackDisplay 5.23 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/playground/AIObservabilityPlaygroundScene 37.8 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/prompts/LLMPromptScene 29.2 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/prompts/LLMPromptsScene 4.86 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/skills/LLMSkillScene 963 B
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/skills/LLMSkillsScene 980 B
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/tags/AIObservabilityTag 27.4 kB
frontend/dist-report/posthog-app/_parent/products/ai_observability/frontend/tags/AIObservabilityTagsScene 7.34 kB
frontend/dist-report/posthog-app/_parent/products/business_knowledge/frontend/scenes/BusinessKnowledgeScene 19 kB
frontend/dist-report/posthog-app/_parent/products/conversations/frontend/components/Assignee/CyclotronJobInputAssignee 1.71 kB
frontend/dist-report/posthog-app/_parent/products/conversations/frontend/components/SlaBusinessHours/CyclotronJobInputBusinessHours 3.09 kB
frontend/dist-report/posthog-app/_parent/products/conversations/frontend/components/TicketTags/CyclotronJobInputTicketTags 1.09 kB
frontend/dist-report/posthog-app/_parent/products/conversations/frontend/scenes/settings/SupportSettingsScene 1.85 kB
frontend/dist-report/posthog-app/_parent/products/conversations/frontend/scenes/ticket/SupportTicketScene 26.6 kB
frontend/dist-report/posthog-app/_parent/products/conversations/frontend/scenes/tickets/SupportTicketsScene 1.11 kB
frontend/dist-report/posthog-app/_parent/products/customer_analytics/frontend/CustomerAnalyticsScene 51.9 kB
frontend/dist-report/posthog-app/_parent/products/customer_analytics/frontend/scenes/CustomerAnalyticsConfigurationScene/CustomerAnalyticsConfigurationScene 2.68 kB
frontend/dist-report/posthog-app/_parent/products/customer_analytics/frontend/scenes/CustomerJourneyBuilderScene/CustomerJourneyBuilderScene 2.22 kB
frontend/dist-report/posthog-app/_parent/products/customer_analytics/frontend/scenes/CustomerJourneyTemplatesScene/CustomerJourneyTemplatesScene 7.9 kB
frontend/dist-report/posthog-app/_parent/products/data_warehouse/DataWarehouseScene 1.81 kB
frontend/dist-report/posthog-app/_parent/products/data_warehouse/frontend/scenes/NewSourceScene/NewSourceScene 1.18 kB
frontend/dist-report/posthog-app/_parent/products/data_warehouse/frontend/scenes/SchemaScene/SchemaScene 24.4 kB
frontend/dist-report/posthog-app/_parent/products/data_warehouse/frontend/scenes/SourceScene/SourceScene 1.1 kB
frontend/dist-report/posthog-app/_parent/products/data_warehouse/frontend/scenes/SourcesScene/SourcesScene 6.34 kB
frontend/dist-report/posthog-app/_parent/products/deployments/frontend/Deployment 4.08 kB
frontend/dist-report/posthog-app/_parent/products/deployments/frontend/DeploymentProject 5.61 kB
frontend/dist-report/posthog-app/_parent/products/deployments/frontend/Deployments 9.35 kB
frontend/dist-report/posthog-app/_parent/products/early_access_features/frontend/EarlyAccessFeature 1.2 kB
frontend/dist-report/posthog-app/_parent/products/early_access_features/frontend/EarlyAccessFeatures 3.28 kB
frontend/dist-report/posthog-app/_parent/products/endpoints/frontend/EndpointScene 40.7 kB
frontend/dist-report/posthog-app/_parent/products/endpoints/frontend/EndpointsScene 22.4 kB
frontend/dist-report/posthog-app/_parent/products/error_tracking/frontend/scenes/ErrorTrackingFingerprintsScene/ErrorTrackingIssueFingerprintsScene 7.48 kB
frontend/dist-report/posthog-app/_parent/products/error_tracking/frontend/scenes/ErrorTrackingIssueScene/ErrorTrackingIssueScene 103 kB
frontend/dist-report/posthog-app/_parent/products/error_tracking/frontend/scenes/ErrorTrackingScene/ErrorTrackingScene 27.2 kB
frontend/dist-report/posthog-app/_parent/products/feature_flags/frontend/FeatureFlagTemplatesScene 7.42 kB
frontend/dist-report/posthog-app/_parent/products/games/368Hedgehogs/368Hedgehogs 5.65 kB
frontend/dist-report/posthog-app/_parent/products/games/FlappyHog/FlappyHog 6.16 kB
frontend/dist-report/posthog-app/_parent/products/legal_documents/frontend/scenes/LegalDocumentNewScene 59.8 kB
frontend/dist-report/posthog-app/_parent/products/legal_documents/frontend/scenes/LegalDocumentsScene 5.35 kB
frontend/dist-report/posthog-app/_parent/products/links/frontend/LinkScene 25.2 kB
frontend/dist-report/posthog-app/_parent/products/links/frontend/LinksScene 4.58 kB
frontend/dist-report/posthog-app/_parent/products/live_debugger/frontend/LiveDebugger 19.5 kB
frontend/dist-report/posthog-app/_parent/products/logs/frontend/LogsScene 17.9 kB
frontend/dist-report/posthog-app/_parent/products/logs/frontend/scenes/LogsAlertDetailScene/LogsAlertDetailScene 17.3 kB
frontend/dist-report/posthog-app/_parent/products/logs/frontend/scenes/LogsAlertNotificationDetailScene/LogsAlertNotificationDetailScene 8.53 kB
frontend/dist-report/posthog-app/_parent/products/logs/frontend/scenes/LogsSamplingDetailScene/LogsSamplingDetailScene 5.34 kB
frontend/dist-report/posthog-app/_parent/products/logs/frontend/scenes/LogsSamplingNewScene/LogsSamplingNewScene 2.29 kB
frontend/dist-report/posthog-app/_parent/products/managed_migrations/frontend/ManagedMigration 14.9 kB
frontend/dist-report/posthog-app/_parent/products/mcp_analytics/frontend/MCPAnalyticsScene 40.6 kB
frontend/dist-report/posthog-app/_parent/products/mcp_analytics/frontend/MCPAnalyticsToolDetail 18.6 kB
frontend/dist-report/posthog-app/_parent/products/metrics/frontend/MetricsScene 16.2 kB
frontend/dist-report/posthog-app/_parent/products/product_analytics/frontend/insights/stickiness/StickinessBarChart/StickinessBarChart 3.34 kB
frontend/dist-report/posthog-app/_parent/products/product_analytics/frontend/insights/stickiness/StickinessLineChart/StickinessLineChart 3.18 kB
frontend/dist-report/posthog-app/_parent/products/product_analytics/frontend/insights/trends/TrendsBarChart/TrendsBarChart 7.4 kB
frontend/dist-report/posthog-app/_parent/products/product_analytics/frontend/insights/trends/TrendsLifecycleChart/TrendsLifecycleChart 4.45 kB
frontend/dist-report/posthog-app/_parent/products/product_analytics/frontend/insights/trends/TrendsLineChart/TrendsLineChart 4.64 kB
frontend/dist-report/posthog-app/_parent/products/product_analytics/frontend/insights/trends/TrendsPieChart/TrendsPieChart 4.38 kB
frontend/dist-report/posthog-app/_parent/products/replay_vision/frontend/observations/ReplayObservation 8.18 kB
frontend/dist-report/posthog-app/_parent/products/replay_vision/frontend/replay_scanners/ReplayScanner 34 kB
frontend/dist-report/posthog-app/_parent/products/replay_vision/frontend/replay_scanners/ReplayScannersScene 11.6 kB
frontend/dist-report/posthog-app/_parent/products/replay_vision/frontend/replay_scanners/ScannerTemplatesScene 4.63 kB
frontend/dist-report/posthog-app/_parent/products/revenue_analytics/frontend/RevenueAnalyticsScene 26.6 kB
frontend/dist-report/posthog-app/_parent/products/session_summaries/frontend/SessionGroupSummariesTable 5.09 kB
frontend/dist-report/posthog-app/_parent/products/session_summaries/frontend/SessionGroupSummaryScene 19.3 kB
frontend/dist-report/posthog-app/_parent/products/tasks/frontend/SlackTaskContextScene 8.91 kB
frontend/dist-report/posthog-app/_parent/products/tasks/frontend/TaskDetailScene 23.9 kB
frontend/dist-report/posthog-app/_parent/products/tasks/frontend/TaskTracker 14.7 kB
frontend/dist-report/posthog-app/_parent/products/tracing/frontend/TracingScene 54.5 kB
frontend/dist-report/posthog-app/_parent/products/user_interviews/frontend/UserInterview 9.35 kB
frontend/dist-report/posthog-app/_parent/products/user_interviews/frontend/UserInterviewResponse 7.83 kB
frontend/dist-report/posthog-app/_parent/products/user_interviews/frontend/UserInterviews 6.12 kB
frontend/dist-report/posthog-app/_parent/products/visual_review/frontend/scenes/VisualReviewIndexScene 2.59 kB
frontend/dist-report/posthog-app/_parent/products/visual_review/frontend/scenes/VisualReviewRunScene 44.7 kB
frontend/dist-report/posthog-app/_parent/products/visual_review/frontend/scenes/VisualReviewRunsScene 7.36 kB
frontend/dist-report/posthog-app/_parent/products/visual_review/frontend/scenes/VisualReviewSettingsScene 11.1 kB
frontend/dist-report/posthog-app/_parent/products/visual_review/frontend/scenes/VisualReviewSnapshotHistoryScene 13.9 kB
frontend/dist-report/posthog-app/_parent/products/visual_review/frontend/scenes/VisualReviewSnapshotOverviewScene 19.6 kB
frontend/dist-report/posthog-app/_parent/products/workflows/frontend/TemplateLibrary/MessageTemplate 16.7 kB
frontend/dist-report/posthog-app/_parent/products/workflows/frontend/Workflows/WorkflowScene 104 kB
frontend/dist-report/posthog-app/_parent/products/workflows/frontend/WorkflowsScene 60.3 kB
frontend/dist-report/posthog-app/src/index 61.1 kB
frontend/dist-report/posthog-app/src/layout/panel-layout/ai-first/tabs/NavTabChat 7.19 kB
frontend/dist-report/posthog-app/src/lib/components/Cards/TextCard/TextCardMarkdownEditor 11.3 kB
frontend/dist-report/posthog-app/src/lib/components/MonacoDiffEditor 471 B
frontend/dist-report/posthog-app/src/lib/lemon-ui/LemonMarkdown/MermaidDiagram 2.29 kB
frontend/dist-report/posthog-app/src/lib/lemon-ui/LemonTextArea/LemonTextAreaMarkdown 876 B
frontend/dist-report/posthog-app/src/lib/lemon-ui/Link/Link 359 B
frontend/dist-report/posthog-app/src/lib/monaco/CodeEditorInline 866 B
frontend/dist-report/posthog-app/src/lib/monaco/vimMode 211 kB
frontend/dist-report/posthog-app/src/lib/ui/Button/ButtonPrimitives 426 B
frontend/dist-report/posthog-app/src/queries/nodes/WebVitals/WebVitals 7.55 kB
frontend/dist-report/posthog-app/src/queries/nodes/WebVitals/WebVitalsPathBreakdown 4.12 kB
frontend/dist-report/posthog-app/src/queries/schema 853 kB
frontend/dist-report/posthog-app/src/scenes/activity/explore/EventsScene 3.32 kB
frontend/dist-report/posthog-app/src/scenes/activity/explore/SessionsScene 4.72 kB
frontend/dist-report/posthog-app/src/scenes/activity/live/LiveEventsTable 5.62 kB
frontend/dist-report/posthog-app/src/scenes/agentic/AgenticAuthorize 5.87 kB
frontend/dist-report/posthog-app/src/scenes/approvals/ApprovalDetail 16.6 kB
frontend/dist-report/posthog-app/src/scenes/approvals/changeRequestsLogic 918 B
frontend/dist-report/posthog-app/src/scenes/audit-logs/AdvancedActivityLogsScene 42.1 kB
frontend/dist-report/posthog-app/src/scenes/AuthenticatedShell 165 kB
frontend/dist-report/posthog-app/src/scenes/authentication/AccountConnected 3.36 kB
frontend/dist-report/posthog-app/src/scenes/authentication/AgenticAccountMismatch 2.77 kB
frontend/dist-report/posthog-app/src/scenes/authentication/CLIAuthorize 11.8 kB
frontend/dist-report/posthog-app/src/scenes/authentication/CLILive 4.4 kB
frontend/dist-report/posthog-app/src/scenes/authentication/credential-review/CredentialReview 3.98 kB
frontend/dist-report/posthog-app/src/scenes/authentication/EmailMFAVerify 3.4 kB
frontend/dist-report/posthog-app/src/scenes/authentication/InviteSignup 15.4 kB
frontend/dist-report/posthog-app/src/scenes/authentication/Login 10.2 kB
frontend/dist-report/posthog-app/src/scenes/authentication/Login2FA 5.11 kB
frontend/dist-report/posthog-app/src/scenes/authentication/passkeyLogic 858 B
frontend/dist-report/posthog-app/src/scenes/authentication/PasswordReset 4.74 kB
frontend/dist-report/posthog-app/src/scenes/authentication/PasswordResetComplete 3.38 kB
frontend/dist-report/posthog-app/src/scenes/authentication/signup/SignupContainer 28.6 kB
frontend/dist-report/posthog-app/src/scenes/authentication/signup/verify-email/VerifyEmail 5.16 kB
frontend/dist-report/posthog-app/src/scenes/authentication/TwoFactorReset 4.41 kB
frontend/dist-report/posthog-app/src/scenes/authentication/VercelConnect 5.37 kB
frontend/dist-report/posthog-app/src/scenes/authentication/VercelLinkError 2.64 kB
frontend/dist-report/posthog-app/src/scenes/billing/AuthorizationStatus 1.1 kB
frontend/dist-report/posthog-app/src/scenes/billing/Billing 867 B
frontend/dist-report/posthog-app/src/scenes/billing/BillingSection 21.2 kB
frontend/dist-report/posthog-app/src/scenes/cohorts/Cohort 28.4 kB
frontend/dist-report/posthog-app/src/scenes/cohorts/CohortCalculationHistory 6.61 kB
frontend/dist-report/posthog-app/src/scenes/cohorts/Cohorts 9.81 kB
frontend/dist-report/posthog-app/src/scenes/coupons/Coupons 1.1 kB
frontend/dist-report/posthog-app/src/scenes/dashboard/Dashboard 1.68 kB
frontend/dist-report/posthog-app/src/scenes/dashboard/dashboards/Dashboards 19.9 kB
frontend/dist-report/posthog-app/src/scenes/dashboard/dashboards/templates/DashboardTemplateCopyScene 6.09 kB
frontend/dist-report/posthog-app/src/scenes/data-management/DataManagementScene 1.02 kB
frontend/dist-report/posthog-app/src/scenes/data-management/definition/DefinitionEdit 17.2 kB
frontend/dist-report/posthog-app/src/scenes/data-management/definition/DefinitionView 24.4 kB
frontend/dist-report/posthog-app/src/scenes/data-management/MaterializedColumns/MaterializedColumns 12 kB
frontend/dist-report/posthog-app/src/scenes/data-management/variables/SqlVariableEditScene 7.63 kB
frontend/dist-report/posthog-app/src/scenes/data-pipelines/batch-exports/BatchExportScene 61 kB
frontend/dist-report/posthog-app/src/scenes/data-pipelines/DataPipelinesNewScene 2.69 kB
frontend/dist-report/posthog-app/src/scenes/data-pipelines/DestinationsScene 3.06 kB
frontend/dist-report/posthog-app/src/scenes/data-pipelines/event-filtering/EventFilterScene 22.3 kB
frontend/dist-report/posthog-app/src/scenes/data-pipelines/legacy-plugins/LegacyPluginScene 21 kB
frontend/dist-report/posthog-app/src/scenes/data-pipelines/TransformationsScene 2.3 kB
frontend/dist-report/posthog-app/src/scenes/data-pipelines/WebScriptsScene 2.92 kB
frontend/dist-report/posthog-app/src/scenes/data-warehouse/DataWarehouseScene 1.75 kB
frontend/dist-report/posthog-app/src/scenes/data-warehouse/editor/EditorScene 1.52 kB
frontend/dist-report/posthog-app/src/scenes/debug/DebugScene 20.3 kB
frontend/dist-report/posthog-app/src/scenes/debug/hog/HogRepl 7.75 kB
frontend/dist-report/posthog-app/src/scenes/experiments/Experiment 207 kB
frontend/dist-report/posthog-app/src/scenes/experiments/Experiments 20.9 kB
frontend/dist-report/posthog-app/src/scenes/experiments/SharedMetrics/SharedMetric 6.45 kB
frontend/dist-report/posthog-app/src/scenes/experiments/SharedMetrics/SharedMetrics 923 B
frontend/dist-report/posthog-app/src/scenes/exports/ExportsScene 4.36 kB
frontend/dist-report/posthog-app/src/scenes/feature-flags/FeatureFlag 144 kB
frontend/dist-report/posthog-app/src/scenes/feature-flags/FeatureFlags 1.12 kB
frontend/dist-report/posthog-app/src/scenes/groups/Group 15.6 kB
frontend/dist-report/posthog-app/src/scenes/groups/Groups 4.29 kB
frontend/dist-report/posthog-app/src/scenes/groups/GroupsNew 7.73 kB
frontend/dist-report/posthog-app/src/scenes/health-alerts/HealthAlertsScene 4.17 kB
frontend/dist-report/posthog-app/src/scenes/health/categoryDetail/HealthCategoryDetailScene 7.64 kB
frontend/dist-report/posthog-app/src/scenes/health/HealthScene 12.8 kB
frontend/dist-report/posthog-app/src/scenes/health/pipelineStatus/PipelineStatusScene 11.5 kB
frontend/dist-report/posthog-app/src/scenes/heatmaps/scenes/heatmap/HeatmapNewScene 5.41 kB
frontend/dist-report/posthog-app/src/scenes/heatmaps/scenes/heatmap/HeatmapRecordingScene 4.31 kB
frontend/dist-report/posthog-app/src/scenes/heatmaps/scenes/heatmap/HeatmapScene 6.94 kB
frontend/dist-report/posthog-app/src/scenes/heatmaps/scenes/heatmaps/HeatmapsScene 4.27 kB
frontend/dist-report/posthog-app/src/scenes/hog-functions/HogFunctionScene 59.9 kB
frontend/dist-report/posthog-app/src/scenes/inbox/InboxScene 63.3 kB
frontend/dist-report/posthog-app/src/scenes/insights/InsightQuickStart/InsightQuickStart 5.81 kB
frontend/dist-report/posthog-app/src/scenes/insights/InsightScene 34.8 kB
frontend/dist-report/posthog-app/src/scenes/insights/views/BoxPlot/BoxPlot 5.43 kB
frontend/dist-report/posthog-app/src/scenes/insights/views/CalendarHeatMap/CalendarHeatMap 4.87 kB
frontend/dist-report/posthog-app/src/scenes/insights/views/RegionMap/RegionMap 29.8 kB
frontend/dist-report/posthog-app/src/scenes/insights/views/WorldMap/WorldMap 5.16 kB
frontend/dist-report/posthog-app/src/scenes/instance/AsyncMigrations/AsyncMigrations 13.5 kB
frontend/dist-report/posthog-app/src/scenes/instance/DeadLetterQueue/DeadLetterQueue 5.77 kB
frontend/dist-report/posthog-app/src/scenes/instance/QueryPerformance/QueryPerformance 9 kB
frontend/dist-report/posthog-app/src/scenes/instance/SystemStatus/SystemStatus 17.4 kB
frontend/dist-report/posthog-app/src/scenes/IntegrationsRedirect/IntegrationsRedirect 1.11 kB
frontend/dist-report/posthog-app/src/scenes/marketing-analytics/MarketingAnalyticsScene 42.1 kB
frontend/dist-report/posthog-app/src/scenes/max/Max 1.06 kB
frontend/dist-report/posthog-app/src/scenes/models/ModelsScene 19.1 kB
frontend/dist-report/posthog-app/src/scenes/models/NodeDetailScene 17.1 kB
frontend/dist-report/posthog-app/src/scenes/moveToPostHogCloud/MoveToPostHogCloud 4.84 kB
frontend/dist-report/posthog-app/src/scenes/new-tab/NewTabScene 1.85 kB
frontend/dist-report/posthog-app/src/scenes/notebooks/NotebookCanvasScene 3.92 kB
frontend/dist-report/posthog-app/src/scenes/notebooks/NotebookPanel/NotebookPanel 5.98 kB
frontend/dist-report/posthog-app/src/scenes/notebooks/NotebookScene 9.29 kB
frontend/dist-report/posthog-app/src/scenes/notebooks/NotebooksScene 7.98 kB
frontend/dist-report/posthog-app/src/scenes/oauth/OAuthAuthorize 1.01 kB
frontend/dist-report/posthog-app/src/scenes/onboarding/coupon/OnboardingCouponRedemption 1.58 kB
frontend/dist-report/posthog-app/src/scenes/onboarding/Onboarding 792 kB
frontend/dist-report/posthog-app/src/scenes/onboarding/sdks/SdkDoctorScene 10.2 kB
frontend/dist-report/posthog-app/src/scenes/organization/ConfirmOrganization/ConfirmOrganization 4.91 kB
frontend/dist-report/posthog-app/src/scenes/organization/Create/Create 1.03 kB
frontend/dist-report/posthog-app/src/scenes/organization/Deactivated 1.51 kB
frontend/dist-report/posthog-app/src/scenes/organization/PendingDeletion 2.48 kB
frontend/dist-report/posthog-app/src/scenes/persons/PersonScene 20.1 kB
frontend/dist-report/posthog-app/src/scenes/persons/PersonsScene 6.12 kB
frontend/dist-report/posthog-app/src/scenes/PreflightCheck/PreflightCheck 5.95 kB
frontend/dist-report/posthog-app/src/scenes/product-tours/ProductTour 275 kB
frontend/dist-report/posthog-app/src/scenes/product-tours/ProductTours 5.06 kB
frontend/dist-report/posthog-app/src/scenes/project-homepage/ProjectHomepage 19.1 kB
frontend/dist-report/posthog-app/src/scenes/project/Create/Create 1.21 kB
frontend/dist-report/posthog-app/src/scenes/resource-transfer/ResourceTransfer 9.56 kB
frontend/dist-report/posthog-app/src/scenes/saved-insights/SavedInsights 1.04 kB
frontend/dist-report/posthog-app/src/scenes/session-recordings/detail/SessionRecordingDetail 2.14 kB
frontend/dist-report/posthog-app/src/scenes/session-recordings/file-playback/SessionRecordingFilePlaybackScene 4.85 kB
frontend/dist-report/posthog-app/src/scenes/session-recordings/kiosk/SessionRecordingsKiosk 10.3 kB
frontend/dist-report/posthog-app/src/scenes/session-recordings/player/snapshot-processing/DecompressionWorkerManager 329 B
frontend/dist-report/posthog-app/src/scenes/session-recordings/playlist/SessionRecordingsPlaylistScene 5.49 kB
frontend/dist-report/posthog-app/src/scenes/session-recordings/SessionRecordings 1.15 kB
frontend/dist-report/posthog-app/src/scenes/session-recordings/settings/SessionRecordingsSettingsScene 2.35 kB
frontend/dist-report/posthog-app/src/scenes/sessions/SessionProfileScene 15.6 kB
frontend/dist-report/posthog-app/src/scenes/settings/SettingsScene 3.94 kB
frontend/dist-report/posthog-app/src/scenes/sites/Site 1.57 kB
frontend/dist-report/posthog-app/src/scenes/startups/StartupProgram 21.6 kB
frontend/dist-report/posthog-app/src/scenes/StripeConfirmInstall/StripeConfirmInstall 3.92 kB
frontend/dist-report/posthog-app/src/scenes/subscriptions/SubscriptionScene 14.4 kB
frontend/dist-report/posthog-app/src/scenes/subscriptions/SubscriptionsScene 5.23 kB
frontend/dist-report/posthog-app/src/scenes/surveys/forms/SurveyFormBuilder 1.93 kB
frontend/dist-report/posthog-app/src/scenes/surveys/Survey 1.39 kB
frontend/dist-report/posthog-app/src/scenes/surveys/Surveys 26.8 kB
frontend/dist-report/posthog-app/src/scenes/surveys/wizard/SurveyWizard 72.8 kB
frontend/dist-report/posthog-app/src/scenes/themes/CustomCssScene 3.94 kB
frontend/dist-report/posthog-app/src/scenes/toolbar-launch/ToolbarLaunch 2.85 kB
frontend/dist-report/posthog-app/src/scenes/Unsubscribe/Unsubscribe 2.04 kB
frontend/dist-report/posthog-app/src/scenes/web-analytics/SessionAttributionExplorer/SessionAttributionExplorerScene 7.01 kB
frontend/dist-report/posthog-app/src/scenes/web-analytics/WebAnalyticsScene 13.3 kB
frontend/dist-report/posthog-app/src/scenes/wizard/Wizard 4.83 kB
frontend/dist-report/posthog-app/src/sharedChunkAnchors 1.19 kB
frontend/dist-report/render-query/src/render-query/render-query 27.4 MB
frontend/dist-report/toolbar/src/toolbar/toolbar 15.7 MB

compressed-size-action

Comment thread posthog/api/oauth/views.py
MattBro and others added 3 commits May 30, 2026 20:02
…es-foundation

Resolve scopes.py and test_scopes.py conflicts: keep UNPRIVILEGED_SCOPES-based
get_oauth_scopes_supported() body, fold master's signal_scout_internal rationale
into the docstring, and union both sides' scope test classes. signal_scout_internal
is already excluded via INTERNAL_API_SCOPE_OBJECTS -> ALL_SCOPES.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…copes

The refresh-token grant copied the prior access token's scopes verbatim and
never re-ran validate_scopes, so a token minted before an app's scope ceiling
was tightened kept refreshing into the old, broader set. Override
get_original_scopes on OAuthValidator to intersect the refreshed scopes with
the application's current OAuthApplication.scopes ceiling.

OIDC/introspection pass through, mirroring validate_scopes. Wildcard (*) tokens
and zero-overlap tokens are left untouched so refresh never yields an
empty-scope token; * retirement stays in #60330 (coupled to #60342).

Verified end-to-end against the oauthlib/DOT refresh path in a sandbox:
all five narrowing cases pass (narrow / preserve / empty-ceiling / zero-overlap
/ wildcard).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
return original_list

original_set = set(original_list)
if "*" in original_set:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium: Refresh token scope ceiling bypass

A client that already has a refresh token carrying * can keep refreshing into full-access tokens after an admin sets a narrower OAuthApplication.scopes ceiling. The no-overlap branch below has the same effect for non-wildcard scopes: an old insight:read refresh token remains refreshable even after the app ceiling is changed to only experiment:read; instead of returning the original scopes, the refresh should either issue only scopes within the current ceiling or reject/revoke the refresh token when nothing is allowed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 9b52e0c0c02 — the no-overlap case now raises InvalidGrantError (400 invalid_grant) instead of returning the original scopes, so a token whose scopes fall outside a tightened ceiling can't refresh; the client re-authorizes within the current ceiling. * tokens stay exempt (narrowing them empties the token) — that's tracked in #60330/#60342.

MattBro and others added 2 commits June 1, 2026 09:02
@tests-posthog
Copy link
Copy Markdown
Contributor

tests-posthog Bot commented Jun 1, 2026

Query snapshots: Backend query snapshots updated

Changes: 1 snapshots (0 modified, 1 added, 0 deleted)

What this means:

  • Query snapshots have been automatically updated to match current output
  • These changes reflect modifications to database queries or schema

Next steps:

  • Review the query changes to ensure they're intentional
  • If unexpected, investigate what caused the query to change

Review snapshot changes →

tests-posthog Bot and others added 3 commits June 1, 2026 13:32
…es-foundation

# Conflicts:
#	posthog/migrations/max_migration.txt
Previously the no-overlap case returned the original scopes unchanged, so a
token whose scopes no longer intersect a tightened OAuthApplication.scopes
ceiling kept refreshing into out-of-ceiling access. Raise InvalidGrantError
instead (RFC 6749 invalid_grant, 400) so the client re-authorizes and gets a
token within the current ceiling. Wildcard (*) tokens stay exempt — narrowing
them is #60330/#60342.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MattBro MattBro merged commit 9e4a7eb into master Jun 1, 2026
224 of 232 checks passed
@MattBro MattBro deleted the matt/oauth-app-scopes-foundation branch June 1, 2026 22:04
@deployment-status-posthog
Copy link
Copy Markdown

deployment-status-posthog Bot commented Jun 1, 2026

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-06-01 22:28 UTC Run
prod-us ✅ Deployed 2026-06-02 10:18 UTC Run
prod-eu ✅ Deployed 2026-06-02 10:20 UTC Run

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