Skip to content

feat(sentry): Read every org that installs the public integration - #2565

Draft
sentry-junior[bot] wants to merge 1 commit into
mainfrom
feat/sentry-multi-org-installs
Draft

sentry-junior[bot] wants to merge 1 commit into
mainfrom
feat/sentry-multi-org-installs

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Proof of concept for #2559. Junior reads any Sentry org that installs its public integration, using that org's own installation token. The internal integration keeps working next to it, so prod can move over without a cutover.

Installations

  • New plugin table junior_sentry_installations (install uuid, org slug), with the plugin's first migration. Core does not read it.
  • installation.created saves the org and exchanges the grant code for the first token. A Sentry retry does not exchange the code again, and an uninstalled installation is never added back. installation.deleted keeps the row with no org.

Tokens

  • After the first token, Junior mints new ones with a client JWT signed with the client secret, so it stores no refresh token. Tokens stay in the plugin cache. Each mint deletes the previous token, so the cache's load lock makes all instances share one token.
  • A token is minted again 30 minutes before its 8h expiry.

Reads (grantForEgress)

  • The org in /organizations/{org}/, /projects/{org}/… or /teams/{org}/… selects the installation. The grant carries leaseScope: installation:<uuid>. The grant is still org-read, so the host does not keep the headers.
  • A path with no org (/issues/{id}/) uses the only installation. With more than one installation, Junior denies it and asks for the org-scoped path.
  • If SENTRY_READ_TOKEN is set, it covers every read that no installation covers. Without it, reads of an org with no installation are denied with EgressPolicyDenied. They never fall back to user OAuth (feat(sentry): Read other orgs with the user's OAuth token #2457).
  • Writes stay on user OAuth.

Webhooks

  • Each delivery is checked against SENTRY_APP_CLIENT_SECRET and then SENTRY_WEBHOOK_SECRET. A public-integration delivery must come from an active installation. Installation webhooks are only accepted from the public integration.

New env vars: SENTRY_APP_CLIENT_ID, SENTRY_APP_CLIENT_SECRET.

Prod rollout (no big-bang migration)

  1. Deploy this change. With only the current env vars, behavior does not change.
  2. Create an unpublished public integration owned by sentry, with read-only permissions, the issue webhook and Alert Rule Action. Set the webhook URL to /api/webhooks/sentry, with no redirect URL. Set the two new env vars, redeploy, then install it in sentry.
  3. Reads of sentry now use the installation token. SENTRY_READ_TOKEN still covers anything else.
  4. Move the alert rule and workflow actions from junior-c01117 to the new app. Both secrets verify webhooks while this happens. Issue events from both integrations have the same eventKey. I expect them to dedupe, but I have not checked this in prod.
  5. Turn off the internal integration's issue webhook, then remove SENTRY_READ_TOKEN and SENTRY_WEBHOOK_SECRET.

Must land before a second org is installed

  • An org event filter, with org-wide events requiring it, plus a backfill of org: sentry on existing org-wide Sentry automations. Today an automation without an identifier runs for every installed org.
  • The checkResource trigger check from Support every GitHub App installation #2404, so saving a trigger for an org with no installation fails.
  • The Sentry skill should always pass ORG/, and should list installed orgs instead of using sentry org list.

Not in this POC

  • Admin dashboard page listing installations (same pattern as junior-google's setup page).
  • Refreshing the cache when an upstream 401 comes back. A 409 from two mints at once fails that one request.
  • Org renames. The slug is saved at install time.

Tests: pnpm --filter @sentry/junior-sentry test / lint / typecheck, plus migration-metadata:check and test-architecture:check. Not tested against a real Sentry public integration yet.

via @dcramer.

--

View Session [Sentry]

Add installations of a Sentry public integration next to the internal
integration. The installation webhook saves the org and exchanges the
grant code. Org-scoped reads use the token of that org's installation,
minted again with a client JWT when the cached token nears expiry.
The internal integration token still covers reads that no installation
covers, so prod can move from one to the other without a cutover.

Refs #2559

Co-Authored-By: David Cramer <23610+dcramer@users.noreply.github.com>
Co-Authored-By: Burak Yigit Kaya <burak.kaya@sentry.io>
@vercel

vercel Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
junior-docs Ready Ready Preview Nov 2, 2026 9:31pm UTC

Request Review

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

5 screenshot changes — 5 changed · 0 added · 0 removed

Review screenshots in Frameshift

Conversation Child Agent Drawer · Desktop
Conversation Child Agent Drawer · Desktop
Changed
Conversation Child Agent Drawer · Mobile
Conversation Child Agent Drawer · Mobile
Changed
Conversation Share Details · Desktop
Conversation Share Details · Desktop
Changed
Conversation Sidebar Collapsed · Desktop
Conversation Sidebar Collapsed · Desktop
Changed
Settings Mcp · Desktop
Settings Mcp · Desktop
Changed

This branch was successfully deployed

1 active deployment
Preview – junior-docs — 845072e9 Deployed Nov 2, 2026 by vercel[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.

1 participant