Skip to content

feat: flags and rpc for frontend code search tool#116098

Merged
shruthilayaj merged 11 commits into
masterfrom
shruthi/feat/send-org-flags-in-request
May 22, 2026
Merged

feat: flags and rpc for frontend code search tool#116098
shruthilayaj merged 11 commits into
masterfrom
shruthi/feat/send-org-flags-in-request

Conversation

@shruthilayaj
Copy link
Copy Markdown
Member

@shruthilayaj shruthilayaj commented May 22, 2026

  • When the flag is enabled, sets enable_frontend_code_search: true in seer chat request
  • The frontend code search needs to know the feature flags enabled for an org - so this PR adds a get_organization_features RPC endpoint that returns all active api_expose=True flags. Seer can call this on demand to validate what features are enabled in the user's Sentry frontend

@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label May 22, 2026
shruthilayaj and others added 7 commits May 22, 2026 12:01
… request

Add GetOrgFeatureFlagsTest covering prefix stripping, inactive exclusion, and sort
order. Mock features.all to a controlled 2-flag subset so each test runs against
a deterministic set rather than all 100+ api-exposed features.

Add CollectUserOrgContextTest coverage for the new org_features key across the
member and non-member return paths. Patch _get_org_feature_flags at the context
test boundary to keep those tests focused on dict shape rather than flag logic.

Add TestSeerAgentClient tests verifying that enable_frontend_code_search is
included in the chat request payload when the seer-agent-source-code-search
flag is active, and omitted when it is not.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
…ookup

Move OrganizationFeature import to module top per project conventions.

Use a set for features_to_check so that discard() replaces list.remove(),
eliminating the ValueError risk when batch_has returns a key that was not
in the original input (e.g. with a custom entity handler), and reducing
removal from O(n) to O(1) per item.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
…valuation

Move feature flag evaluation out of the chat request path and into a dedicated
Seer RPC endpoint (get_organization_features). Previously all api-exposed org
feature flags were evaluated on every chat request, contributing ~600ms p90
latency. Seer can now fetch flags on demand via the existing org-scoped RPC
surface when it needs to validate what the user can see in the frontend.

Remove _get_org_feature_flags and its call from collect_user_org_context.
Add get_organization_features to seer_rpc.py and register it in the
public_org_seer_method_registry. Update tests accordingly.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
…ests

Replace two standalone tests for enable_frontend_code_search with inline
assertions in existing tests. The inactive-flag case is now checked in
test_start_run_basic; the active-flag case is checked in
test_start_run_with_categories. Also restore test_collect_context_with_non_member_returns_default
to the original exact-dict assertion.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
@shruthilayaj shruthilayaj marked this pull request as ready for review May 22, 2026 17:29
@shruthilayaj shruthilayaj requested a review from a team as a code owner May 22, 2026 17:29
Comment thread src/sentry/seer/endpoints/seer_rpc.py
Comment thread src/sentry/seer/endpoints/seer_rpc.py
The method was only registered on the org-scoped public RPC surface but missing
from seer_method_registry, so service-authenticated Seer calls to the internal
endpoint could not invoke it. Add it alongside its peer methods and add a test
confirming it is reachable via the signed internal RPC path.
… flag evaluation

The org serializer passes actor=user when computing organization.features, so
evaluating without an actor can diverge from what the frontend shows for
user-scoped Flagpole rules. Add an optional user_id parameter and resolve it
via user_service (cross-silo safe) to use as actor, matching the serializer.
Falls back to no actor when user_id is omitted or the user doesn't exist.
@shruthilayaj shruthilayaj changed the title feat: send available feature flags in seer req feat: flags and rpc for frontend code search tool May 22, 2026
@shruthilayaj shruthilayaj enabled auto-merge (squash) May 22, 2026 18:01
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 86b9c95. Configure here.

if features.has(name, organization, actor=actor, skip_entity=True):
feature_set.add(name[len(_ORGANIZATION_SCOPE_PREFIX) :])

return {"features": list(sorted(feature_set))}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Duplicated feature-checking logic from organization serializer

Low Severity

The new get_organization_features function duplicates the batch-then-fallback feature-checking logic already present in src/sentry/api/serializers/models/organization.py (lines 462–497), including the _ORGANIZATION_SCOPE_PREFIX constant, the features.all() + batch_has + has(skip_entity=True) pattern, and the prefix-stripping step. Extracting this shared logic into a common utility would reduce the maintenance burden and the risk of the two implementations diverging.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 86b9c95. Configure here.

@@ -87,6 +88,7 @@
# Common to Seer features
"get_organization_project_ids": map_org_id_param(get_organization_project_ids),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caller-controlled user_id in get_organization_features lets org members evaluate api-exposed feature flags as arbitrary users

OrganizationSeerRpcEndpoint._dispatch_to_local_method only strips organization_id from the caller-supplied arguments dict before forwarding to get_organization_features, so an authenticated org member can include an arbitrary user_id in the request body. That id is loaded via user_service.get_user and used as the actor for features.batch_has/features.has, allowing the caller to learn which api_expose_only org feature flags evaluate true for any user id (e.g. flags gated on staff/superuser/per-user rollout). The dispatch should ignore caller-supplied user_id and pass request.user.id instead.

Evidence
  • get_organization_features(*, org_id, user_id=None) in seer_rpc.py resolves actor = user_service.get_user(user_id=user_id) and uses it for every features.batch_has / features.has call.
  • OrganizationSeerRpcEndpoint._dispatch_to_local_method (organization_seer_rpc.py) only does arguments.pop("organization_id", None) and then method(**arguments) with organization_id reinjected; user_id from the request body is forwarded unchanged.
  • The registered wrapper map_org_id_param(get_organization_features) (utils.py) renames organization_idorg_id and forwards all other kwargs (return func(**kwargs)), so the attacker-controlled user_id reaches the sink.
  • Request args are taken from request.data.get("args", {}) in post(), fully attacker-controlled JSON; the endpoint requires only org-member scope (SeerRpcPermission org:read/write/admin) plus the organizations:seer-public-rpc feature.
  • Disclosed surface is limited to api_expose_only=True org-prefixed flags, but per-user gating (staff/superuser/rollout) means the result still leaks info about arbitrary users.

Identified by Warden security-review · 4HU-EW8

@shruthilayaj shruthilayaj merged commit 868510e into master May 22, 2026
83 checks passed
@shruthilayaj shruthilayaj deleted the shruthi/feat/send-org-flags-in-request branch May 22, 2026 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants