@sentry/junior-sentry 0.236.0 → 0.237.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @sentry/junior-sentry
2
2
 
3
- Sentry investigations (per-user OAuth) and signed issue webhooks (internal integration) for Junior.
3
+ Sentry investigations (per-user OAuth plus optional org read access) and signed issue webhooks (internal integration) for Junior.
4
4
 
5
5
  ```bash
6
6
  pnpm add @sentry/junior @sentry/junior-sentry
@@ -32,6 +32,10 @@ Verified CLI surface (check live `sentry --help` before blocking):
32
32
  - `sentry alert metrics list|view|create|edit|delete`
33
33
  - `sentry api <endpoint>` fallback
34
34
 
35
+ ## Org read access
36
+
37
+ Set `SENTRY_READ_TOKEN` to a read-only internal integration token. Junior then uses it for Sentry API reads (`GET`, `HEAD`, `OPTIONS`), including Explore queries, scheduled tasks, and event automations. Writes and `/api/0/users/` requests still use the requesting user's OAuth token.
38
+
35
39
  ## Issue webhooks
36
40
 
37
41
  Use a **Sentry internal integration** (not a public app install flow):
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Sentry plugin runtime boundary.
3
3
  *
4
- * This package owns per-user Sentry OAuth, CLI setup, internal-integration
5
- * issue webhook normalization, and Sentry resource identities. Junior core owns
6
- * watches and event automations.
4
+ * This package owns per-user Sentry OAuth, org read access, CLI setup,
5
+ * internal-integration issue webhook normalization, and Sentry resource
6
+ * identities. Junior core owns watches and event automations.
7
7
  */
8
8
  import { type PluginRegistration } from "@sentry/junior-plugin-api";
9
9
  /** Register Sentry runtime metadata and signed event ingress. */
package/dist/index.js CHANGED
@@ -9,6 +9,62 @@ import {
9
9
  import {
10
10
  defineJuniorPlugin
11
11
  } from "@sentry/junior-plugin-api";
12
+
13
+ // src/org-read.ts
14
+ var SENTRY_API_DOMAINS = ["sentry.io", "us.sentry.io", "de.sentry.io"];
15
+ var ORG_READ_GRANT = "org-read";
16
+ var LEASE_MS = 60 * 60 * 1e3;
17
+ var READ_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
18
+ function orgReadToken() {
19
+ return process.env.SENTRY_READ_TOKEN?.trim() || void 0;
20
+ }
21
+ function isOrgReadRequest(request) {
22
+ if (!READ_METHODS.has(request.method.toUpperCase())) {
23
+ return false;
24
+ }
25
+ const url = new URL(request.url);
26
+ if (!SENTRY_API_DOMAINS.includes(url.hostname)) {
27
+ return false;
28
+ }
29
+ const [api, version, resource] = url.pathname.split("/").filter(Boolean);
30
+ return api === "api" && version === "0" && !!resource && resource !== "users";
31
+ }
32
+ function sentryGrantForEgress(ctx) {
33
+ if (!orgReadToken() || !isOrgReadRequest(ctx.request)) {
34
+ return void 0;
35
+ }
36
+ return {
37
+ name: ORG_READ_GRANT,
38
+ access: "read",
39
+ reason: "sentry.org-read"
40
+ };
41
+ }
42
+ function issueSentryCredential(ctx) {
43
+ if (ctx.grant.name !== ORG_READ_GRANT) {
44
+ throw new Error(
45
+ `Sentry plugin cannot issue unknown grant "${ctx.grant.name}".`
46
+ );
47
+ }
48
+ const token = orgReadToken();
49
+ if (!token) {
50
+ return {
51
+ type: "unavailable",
52
+ message: "Sentry org read access requires SENTRY_READ_TOKEN."
53
+ };
54
+ }
55
+ return {
56
+ type: "lease",
57
+ lease: {
58
+ expiresAt: new Date(Date.now() + LEASE_MS).toISOString(),
59
+ headerTransforms: SENTRY_API_DOMAINS.map((domain) => ({
60
+ domain,
61
+ headers: { Authorization: `Bearer ${token}` }
62
+ }))
63
+ }
64
+ };
65
+ }
66
+
67
+ // src/index.ts
12
68
  function sentryPlugin() {
13
69
  return defineJuniorPlugin({
14
70
  packageName: "@sentry/junior-sentry",
@@ -36,7 +92,7 @@ function sentryPlugin() {
36
92
  credentials: {
37
93
  authTokenEnv: "SENTRY_AUTH_TOKEN",
38
94
  authTokenPlaceholder: "host_managed_credential",
39
- domains: ["sentry.io", "us.sentry.io", "de.sentry.io"],
95
+ domains: SENTRY_API_DOMAINS,
40
96
  type: "oauth-bearer"
41
97
  },
42
98
  description: "Investigate Sentry telemetry, manage alerting, and receive issue webhooks",
@@ -44,6 +100,7 @@ function sentryPlugin() {
44
100
  envVars: {
45
101
  SENTRY_CLIENT_ID: {},
46
102
  SENTRY_CLIENT_SECRET: {},
103
+ SENTRY_READ_TOKEN: {},
47
104
  SENTRY_WEBHOOK_ORG: {},
48
105
  SENTRY_WEBHOOK_SECRET: {}
49
106
  },
@@ -64,6 +121,8 @@ function sentryPlugin() {
64
121
  ]
65
122
  },
66
123
  hooks: {
124
+ grantForEgress: sentryGrantForEgress,
125
+ issueCredential: issueSentryCredential,
67
126
  routes(ctx) {
68
127
  return [
69
128
  createSentryWebhookRoute({
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Sentry org read access.
3
+ *
4
+ * An internal integration token can read the Sentry organization that
5
+ * installed the integration. Junior uses it for Sentry API reads. Writes use
6
+ * the requesting user's OAuth token.
7
+ */
8
+ import type { EgressHookContext, IssueCredentialHookContext, PluginCredentialResult, PluginGrant } from "@sentry/junior-plugin-api";
9
+ export declare const SENTRY_API_DOMAINS: string[];
10
+ /**
11
+ * Select the org read grant for Sentry API reads.
12
+ *
13
+ * Return undefined for other requests so the host uses the user's OAuth token.
14
+ */
15
+ export declare function sentryGrantForEgress(ctx: EgressHookContext): PluginGrant | undefined;
16
+ /** Issue the org read token for the org read grant. */
17
+ export declare function issueSentryCredential(ctx: IssueCredentialHookContext): PluginCredentialResult;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior-sentry",
3
- "version": "0.236.0",
3
+ "version": "0.237.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -27,7 +27,7 @@
27
27
  ],
28
28
  "dependencies": {
29
29
  "zod": "^4.5.4",
30
- "@sentry/junior-plugin-api": "0.236.0"
30
+ "@sentry/junior-plugin-api": "0.237.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@oxlint/plugins": "1.79.0",