@sentry/junior 0.43.0 → 0.44.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/dist/app.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  runNonInteractiveCommand,
32
32
  sandboxSkillDir,
33
33
  sandboxSkillFile
34
- } from "./chunk-YSXHRIWR.js";
34
+ } from "./chunk-QAMTCT2R.js";
35
35
  import {
36
36
  CredentialUnavailableError,
37
37
  buildOAuthTokenRequest,
@@ -8622,26 +8622,28 @@ function resolveSandboxEgressProviderForHost(host) {
8622
8622
  (entry) => entry.domains.some((domain) => matchesSandboxEgressDomain(host, domain))
8623
8623
  )?.provider;
8624
8624
  }
8625
- function proxyUrl(sandboxId) {
8625
+ function proxyUrl(egressId) {
8626
8626
  const baseUrl = resolveBaseUrl();
8627
8627
  if (!baseUrl) {
8628
8628
  return void 0;
8629
8629
  }
8630
8630
  const url = new URL(
8631
- `${SANDBOX_EGRESS_PROXY_PATH}/${encodeURIComponent(sandboxId)}`,
8631
+ `${SANDBOX_EGRESS_PROXY_PATH}/${encodeURIComponent(egressId)}`,
8632
8632
  baseUrl
8633
8633
  );
8634
8634
  return url.toString();
8635
8635
  }
8636
- function buildSandboxEgressNetworkPolicy(sandboxId) {
8637
- const forwardURL = proxyUrl(sandboxId);
8638
- if (!forwardURL) {
8639
- return void 0;
8640
- }
8636
+ function buildSandboxEgressNetworkPolicy(egressId) {
8641
8637
  const entries = providerEntries();
8642
8638
  if (entries.length === 0) {
8643
8639
  return void 0;
8644
8640
  }
8641
+ const forwardURL = proxyUrl(egressId);
8642
+ if (!forwardURL) {
8643
+ throw new Error(
8644
+ "Cannot determine base URL for sandbox credential egress (set JUNIOR_BASE_URL or deploy to Vercel)"
8645
+ );
8646
+ }
8645
8647
  const allow = {
8646
8648
  "*": []
8647
8649
  };
@@ -8671,11 +8673,11 @@ import { randomUUID as randomUUID3 } from "crypto";
8671
8673
  var SANDBOX_EGRESS_SESSION_PREFIX = "sandbox-egress-session";
8672
8674
  var SANDBOX_EGRESS_LEASE_PREFIX = "sandbox-egress-lease";
8673
8675
  var DEFAULT_SESSION_TTL_MS = 30 * 60 * 1e3;
8674
- function sessionKey2(sandboxId) {
8675
- return `${SANDBOX_EGRESS_SESSION_PREFIX}:${sandboxId}`;
8676
+ function sessionKey2(egressId) {
8677
+ return `${SANDBOX_EGRESS_SESSION_PREFIX}:${egressId}`;
8676
8678
  }
8677
- function leaseKey(sandboxId, provider, session) {
8678
- return `${SANDBOX_EGRESS_LEASE_PREFIX}:${sandboxId}:${provider}:${session.requesterId}:${session.activationId}`;
8679
+ function leaseKey(egressId, provider, session) {
8680
+ return `${SANDBOX_EGRESS_LEASE_PREFIX}:${egressId}:${provider}:${session.requesterId}:${session.activationId}`;
8679
8681
  }
8680
8682
  function parseSession(value) {
8681
8683
  if (!value || typeof value !== "object") {
@@ -8730,19 +8732,19 @@ async function upsertSandboxEgressSession(input) {
8730
8732
  expiresAtMs: now + ttlMs,
8731
8733
  activationId: randomUUID3()
8732
8734
  };
8733
- await state.set(sessionKey2(input.sandboxId), session, ttlMs);
8735
+ await state.set(sessionKey2(input.egressId), session, ttlMs);
8734
8736
  }
8735
- async function clearSandboxEgressSession(sandboxId) {
8737
+ async function clearSandboxEgressSession(egressId) {
8736
8738
  const state = getStateAdapter();
8737
8739
  await state.connect();
8738
- await state.delete(sessionKey2(sandboxId));
8740
+ await state.delete(sessionKey2(egressId));
8739
8741
  }
8740
- async function getSandboxEgressSession(sandboxId) {
8742
+ async function getSandboxEgressSession(egressId) {
8741
8743
  const state = getStateAdapter();
8742
8744
  await state.connect();
8743
- return parseSession(await state.get(sessionKey2(sandboxId)));
8745
+ return parseSession(await state.get(sessionKey2(egressId)));
8744
8746
  }
8745
- async function setSandboxEgressCredentialLease(sandboxId, session, lease) {
8747
+ async function setSandboxEgressCredentialLease(egressId, session, lease) {
8746
8748
  const leaseExpiresAtMs = Date.parse(lease.expiresAt);
8747
8749
  if (!Number.isFinite(leaseExpiresAtMs) || leaseExpiresAtMs <= Date.now()) {
8748
8750
  return;
@@ -8753,17 +8755,17 @@ async function setSandboxEgressCredentialLease(sandboxId, session, lease) {
8753
8755
  );
8754
8756
  const state = getStateAdapter();
8755
8757
  await state.connect();
8756
- await state.set(leaseKey(sandboxId, lease.provider, session), lease, ttlMs);
8758
+ await state.set(leaseKey(egressId, lease.provider, session), lease, ttlMs);
8757
8759
  }
8758
- async function getSandboxEgressCredentialLease(sandboxId, provider, session) {
8760
+ async function getSandboxEgressCredentialLease(egressId, provider, session) {
8759
8761
  const state = getStateAdapter();
8760
8762
  await state.connect();
8761
- return parseLease(await state.get(leaseKey(sandboxId, provider, session)));
8763
+ return parseLease(await state.get(leaseKey(egressId, provider, session)));
8762
8764
  }
8763
- async function clearSandboxEgressCredentialLease(sandboxId, provider, session) {
8765
+ async function clearSandboxEgressCredentialLease(egressId, provider, session) {
8764
8766
  const state = getStateAdapter();
8765
8767
  await state.connect();
8766
- await state.delete(leaseKey(sandboxId, provider, session));
8768
+ await state.delete(leaseKey(egressId, provider, session));
8767
8769
  }
8768
8770
 
8769
8771
  // src/chat/sandbox/http-error-details.ts
@@ -9620,10 +9622,10 @@ function createSandboxSessionManager(options) {
9620
9622
  appliedNetworkPolicyKey = void 0;
9621
9623
  };
9622
9624
  const createSandboxName = () => `${SANDBOX_NAME_PREFIX}${randomUUID4()}`;
9623
- const rememberNetworkPolicy = (networkPolicy) => {
9624
- appliedNetworkPolicyKey = networkPolicy ? JSON.stringify(networkPolicy) : void 0;
9625
+ const preflightNetworkPolicy = (sandboxName) => {
9626
+ return options?.createNetworkPolicy?.(sandboxName);
9625
9627
  };
9626
- const rememberSandbox = async (nextSandbox, rememberOptions) => {
9628
+ const rememberSandbox = async (nextSandbox) => {
9627
9629
  sandbox = nextSandbox;
9628
9630
  sandboxIdHint = nextSandbox.sandboxId;
9629
9631
  toolExecutors = void 0;
@@ -9632,11 +9634,6 @@ function createSandboxSessionManager(options) {
9632
9634
  ...dependencyProfileHash ? { sandboxDependencyProfileHash: dependencyProfileHash } : {}
9633
9635
  };
9634
9636
  await options?.onSandboxAcquired?.(acquired);
9635
- if (rememberOptions?.recordNetworkPolicy) {
9636
- rememberNetworkPolicy(
9637
- options?.createNetworkPolicy?.(nextSandbox.sandboxId)
9638
- );
9639
- }
9640
9637
  return nextSandbox;
9641
9638
  };
9642
9639
  const failSetup = (error) => {
@@ -9653,7 +9650,7 @@ function createSandboxSessionManager(options) {
9653
9650
  };
9654
9651
  const refreshNetworkPolicy = async (targetSandbox) => {
9655
9652
  const networkPolicy = options?.createNetworkPolicy?.(
9656
- targetSandbox.sandboxId
9653
+ targetSandbox.sandboxEgressId
9657
9654
  );
9658
9655
  if (!networkPolicy) {
9659
9656
  return;
@@ -9709,7 +9706,7 @@ function createSandboxSessionManager(options) {
9709
9706
  const createSandboxFromSnapshot = async (snapshotId, sandboxCredentials, initialSandboxName) => {
9710
9707
  for (let attempt = 0; attempt < SNAPSHOT_BOOT_RETRY_COUNT; attempt += 1) {
9711
9708
  const sandboxName = attempt === 0 ? initialSandboxName : createSandboxName();
9712
- const networkPolicy = options?.createNetworkPolicy?.(sandboxName);
9709
+ const networkPolicy = preflightNetworkPolicy(sandboxName);
9713
9710
  try {
9714
9711
  return createSandboxInstance(
9715
9712
  await Sandbox.create({
@@ -9748,7 +9745,7 @@ function createSandboxSessionManager(options) {
9748
9745
  const createSandboxFromResolvedSnapshot = async (params) => {
9749
9746
  const { runtime, snapshot, sandboxCredentials, sandboxName } = params;
9750
9747
  if (!snapshot.snapshotId) {
9751
- const networkPolicy = options?.createNetworkPolicy?.(sandboxName);
9748
+ const networkPolicy = preflightNetworkPolicy(sandboxName);
9752
9749
  return createSandboxInstance(
9753
9750
  await Sandbox.create({
9754
9751
  timeout: timeoutMs,
@@ -9819,11 +9816,12 @@ function createSandboxSessionManager(options) {
9819
9816
  return failSetup(error);
9820
9817
  }
9821
9818
  try {
9819
+ await refreshNetworkPolicy(createdSandbox);
9822
9820
  await syncSkills(createdSandbox);
9823
9821
  } catch (error) {
9824
9822
  return failSetup(error);
9825
9823
  }
9826
- return await rememberSandbox(createdSandbox, { recordNetworkPolicy: true });
9824
+ return await rememberSandbox(createdSandbox);
9827
9825
  };
9828
9826
  const discardHintIfProfileChanged = () => {
9829
9827
  if (sandbox || !sandboxIdHint || dependencyProfileHash === options?.sandboxDependencyProfileHash) {
@@ -9976,7 +9974,8 @@ function createSandboxSessionManager(options) {
9976
9974
  }
9977
9975
  return {
9978
9976
  bash: async (input) => {
9979
- await options?.beforeCommand?.(activeSandboxId);
9977
+ const commandEgressId = sandboxInstance.sandboxEgressId;
9978
+ await options?.beforeCommand?.(commandEgressId);
9980
9979
  let timedOut = false;
9981
9980
  let timeoutId;
9982
9981
  let commandFinished = false;
@@ -9985,7 +9984,7 @@ function createSandboxSessionManager(options) {
9985
9984
  return;
9986
9985
  }
9987
9986
  commandFinished = true;
9988
- await options?.afterCommand?.(activeSandboxId);
9987
+ await options?.afterCommand?.(commandEgressId);
9989
9988
  };
9990
9989
  const finishCommandBestEffort = async () => {
9991
9990
  try {
@@ -10126,15 +10125,15 @@ function createSandboxExecutor(options) {
10126
10125
  let referenceFiles = [];
10127
10126
  const traceContext = options?.traceContext ?? {};
10128
10127
  const credentialEgress = options?.credentialEgress;
10129
- const syncSandboxEgressSession = credentialEgress ? async (sandboxId) => {
10128
+ const syncSandboxEgressSession = credentialEgress ? async (egressId) => {
10130
10129
  await upsertSandboxEgressSession({
10131
- sandboxId,
10130
+ egressId,
10132
10131
  requesterId: credentialEgress.requesterId,
10133
10132
  ttlMs: options?.timeoutMs
10134
10133
  });
10135
10134
  } : void 0;
10136
- const clearSandboxEgressSessionForCommand = credentialEgress ? async (sandboxId) => {
10137
- await clearSandboxEgressSession(sandboxId);
10135
+ const clearSandboxEgressSessionForCommand = credentialEgress ? async (egressId) => {
10136
+ await clearSandboxEgressSession(egressId);
10138
10137
  } : void 0;
10139
10138
  const sessionManager = createSandboxSessionManager({
10140
10139
  sandboxId: options?.sandboxId,
@@ -14724,41 +14723,21 @@ async function getJwks(issuer) {
14724
14723
  });
14725
14724
  return jwks;
14726
14725
  }
14727
- function expectedVercelOidcAudience() {
14728
- const audience = process.env.VERCEL_OIDC_AUDIENCE?.trim();
14729
- if (!audience) {
14730
- throw new Error("VERCEL_OIDC_AUDIENCE is required for sandbox egress OIDC");
14731
- }
14732
- return audience;
14733
- }
14734
- function validateVercelSandboxOidcClaims(payload, sandboxId) {
14735
- const expectedTeamId = process.env.VERCEL_TEAM_ID?.trim();
14736
- const expectedProjectId = process.env.VERCEL_PROJECT_ID?.trim();
14737
- if (!expectedProjectId) {
14738
- throw new Error("VERCEL_PROJECT_ID is required for sandbox egress OIDC");
14739
- }
14740
- if (expectedTeamId && (typeof payload.owner_id !== "string" || payload.owner_id !== expectedTeamId)) {
14741
- throw new Error("Vercel OIDC token belongs to a different team");
14742
- }
14743
- if (typeof payload.project_id !== "string" || payload.project_id !== expectedProjectId) {
14744
- throw new Error("Vercel OIDC token belongs to a different project");
14745
- }
14746
- if (payload.sandbox_id !== sandboxId) {
14726
+ function validateSandboxClaim(payload, egressId) {
14727
+ if (payload.sandbox_id !== egressId) {
14747
14728
  throw new Error("Vercel OIDC token belongs to a different sandbox");
14748
14729
  }
14749
14730
  }
14750
- async function verifyVercelSandboxOidcToken(token, sandboxId) {
14731
+ async function verifyVercelSandboxOidcToken(token, egressId) {
14751
14732
  const unverified = decodeJwt(token);
14752
14733
  if (typeof unverified.iss !== "string") {
14753
14734
  throw new Error("Vercel OIDC token did not include an issuer");
14754
14735
  }
14755
- const audience = expectedVercelOidcAudience();
14756
14736
  const jwks = await getJwks(unverified.iss);
14757
14737
  const verified = await jwtVerify(token, jwks, {
14758
- issuer: unverified.iss,
14759
- audience
14738
+ issuer: unverified.iss
14760
14739
  });
14761
- validateVercelSandboxOidcClaims(verified.payload, sandboxId);
14740
+ validateSandboxClaim(verified.payload, egressId);
14762
14741
  return verified.payload;
14763
14742
  }
14764
14743
 
@@ -14810,9 +14789,9 @@ function normalizePort(value) {
14810
14789
  const port = Number.parseInt(trimmed, 10);
14811
14790
  return port >= 1 && port <= 65535 ? trimmed : void 0;
14812
14791
  }
14813
- function upstreamPath(request, sandboxId) {
14792
+ function upstreamPath(request, egressId) {
14814
14793
  const url = new URL(request.url);
14815
- const prefix = `${ROUTE_PREFIX}/${encodeURIComponent(sandboxId)}`;
14794
+ const prefix = `${ROUTE_PREFIX}/${encodeURIComponent(egressId)}`;
14816
14795
  if (url.pathname === prefix) {
14817
14796
  return `/${url.search}`;
14818
14797
  }
@@ -14821,7 +14800,7 @@ function upstreamPath(request, sandboxId) {
14821
14800
  }
14822
14801
  return void 0;
14823
14802
  }
14824
- function buildUpstreamUrl(request, sandboxId) {
14803
+ function buildUpstreamUrl(request, egressId) {
14825
14804
  const forwardedHost = request.headers.get(FORWARDED_HOST_HEADER);
14826
14805
  if (!forwardedHost?.trim()) {
14827
14806
  return { ok: false, error: "Missing forwarded host" };
@@ -14843,7 +14822,7 @@ function buildUpstreamUrl(request, sandboxId) {
14843
14822
  if (forwardedPort && !port) {
14844
14823
  return { ok: false, error: "Invalid forwarded port" };
14845
14824
  }
14846
- const path11 = upstreamPath(request, sandboxId);
14825
+ const path11 = upstreamPath(request, egressId);
14847
14826
  if (!path11) {
14848
14827
  return { ok: false, error: "Invalid egress route" };
14849
14828
  }
@@ -14889,9 +14868,9 @@ function responseHeaders(upstream) {
14889
14868
  });
14890
14869
  return headers;
14891
14870
  }
14892
- async function credentialLease(sandboxId, provider, session) {
14871
+ async function credentialLease(egressId, provider, session) {
14893
14872
  const cached = await getSandboxEgressCredentialLease(
14894
- sandboxId,
14873
+ egressId,
14895
14874
  provider,
14896
14875
  session
14897
14876
  );
@@ -14914,7 +14893,7 @@ async function credentialLease(sandboxId, provider, session) {
14914
14893
  expiresAt: lease.expiresAt,
14915
14894
  headerTransforms
14916
14895
  };
14917
- await setSandboxEgressCredentialLease(sandboxId, session, cachedLease);
14896
+ await setSandboxEgressCredentialLease(egressId, session, cachedLease);
14918
14897
  return cachedLease;
14919
14898
  }
14920
14899
  function hasTransformForHost(lease, host) {
@@ -14922,7 +14901,7 @@ function hasTransformForHost(lease, host) {
14922
14901
  (transform) => matchesSandboxEgressDomain(host, transform.domain)
14923
14902
  );
14924
14903
  }
14925
- async function proxySandboxEgressRequest(request, sandboxId, deps = {}) {
14904
+ async function proxySandboxEgressRequest(request, egressId, deps = {}) {
14926
14905
  const oidcToken = request.headers.get(OIDC_TOKEN_HEADER)?.trim();
14927
14906
  if (!oidcToken) {
14928
14907
  return jsonError("Missing Vercel Sandbox OIDC token", 401);
@@ -14930,7 +14909,7 @@ async function proxySandboxEgressRequest(request, sandboxId, deps = {}) {
14930
14909
  try {
14931
14910
  await (deps.verifyOidc ?? verifyVercelSandboxOidcToken)(
14932
14911
  oidcToken,
14933
- sandboxId
14912
+ egressId
14934
14913
  );
14935
14914
  } catch (error) {
14936
14915
  logWarn(
@@ -14943,7 +14922,7 @@ async function proxySandboxEgressRequest(request, sandboxId, deps = {}) {
14943
14922
  );
14944
14923
  return jsonError("Invalid Vercel Sandbox OIDC token", 401);
14945
14924
  }
14946
- const upstreamResult = buildUpstreamUrl(request, sandboxId);
14925
+ const upstreamResult = buildUpstreamUrl(request, egressId);
14947
14926
  if (!upstreamResult.ok) {
14948
14927
  return jsonError(upstreamResult.error, 400);
14949
14928
  }
@@ -14952,13 +14931,13 @@ async function proxySandboxEgressRequest(request, sandboxId, deps = {}) {
14952
14931
  if (!provider) {
14953
14932
  return jsonError("No provider owns forwarded host", 403);
14954
14933
  }
14955
- const session = await getSandboxEgressSession(sandboxId);
14934
+ const session = await getSandboxEgressSession(egressId);
14956
14935
  if (!session) {
14957
14936
  return jsonError("Sandbox egress session is not authorized", 403);
14958
14937
  }
14959
14938
  let lease;
14960
14939
  try {
14961
- lease = await credentialLease(sandboxId, provider, session);
14940
+ lease = await credentialLease(egressId, provider, session);
14962
14941
  } catch (error) {
14963
14942
  if (error instanceof CredentialUnavailableError) {
14964
14943
  return new Response(
@@ -14983,7 +14962,18 @@ ${error.message}`,
14983
14962
  redirect: "manual"
14984
14963
  });
14985
14964
  if (AUTH_REJECTION_STATUS.has(upstream.status)) {
14986
- await clearSandboxEgressCredentialLease(sandboxId, provider, session);
14965
+ logWarn(
14966
+ "sandbox_egress_upstream_auth_rejected",
14967
+ {},
14968
+ {
14969
+ "app.credential.provider": provider,
14970
+ "http.request.method": request.method,
14971
+ "http.response.status_code": upstream.status,
14972
+ "server.address": upstreamUrl.hostname
14973
+ },
14974
+ "Sandbox egress upstream auth rejected"
14975
+ );
14976
+ await clearSandboxEgressCredentialLease(egressId, provider, session);
14987
14977
  }
14988
14978
  return new Response(upstream.body, {
14989
14979
  status: upstream.status,
@@ -14993,8 +14983,8 @@ ${error.message}`,
14993
14983
  }
14994
14984
 
14995
14985
  // src/handlers/sandbox-egress-proxy.ts
14996
- async function ALL(request, sandboxId) {
14997
- return await proxySandboxEgressRequest(request, sandboxId);
14986
+ async function ALL(request, egressId) {
14987
+ return await proxySandboxEgressRequest(request, egressId);
14998
14988
  }
14999
14989
 
15000
14990
  // src/chat/slack/context.ts
@@ -18373,11 +18363,11 @@ async function createApp(options) {
18373
18363
  app.post("/api/internal/turn-resume", (c) => {
18374
18364
  return POST(c.req.raw, waitUntil);
18375
18365
  });
18376
- app.all("/api/internal/sandbox-egress/:sandboxId", (c) => {
18377
- return ALL(c.req.raw, c.req.param("sandboxId"));
18366
+ app.all("/api/internal/sandbox-egress/:egressId", (c) => {
18367
+ return ALL(c.req.raw, c.req.param("egressId"));
18378
18368
  });
18379
- app.all("/api/internal/sandbox-egress/:sandboxId/*", (c) => {
18380
- return ALL(c.req.raw, c.req.param("sandboxId"));
18369
+ app.all("/api/internal/sandbox-egress/:egressId/*", (c) => {
18370
+ return ALL(c.req.raw, c.req.param("egressId"));
18381
18371
  });
18382
18372
  app.post("/api/webhooks/:platform", (c) => {
18383
18373
  return POST2(c.req.raw, c.req.param("platform"), waitUntil);
@@ -563,6 +563,9 @@ function getVercelSandboxCredentials() {
563
563
  function createSandboxInstance(sandbox) {
564
564
  return {
565
565
  sandboxId: sandbox.name,
566
+ get sandboxEgressId() {
567
+ return sandbox.currentSession().sessionId;
568
+ },
566
569
  fs: sandbox.fs,
567
570
  extendTimeout(duration) {
568
571
  return sandbox.extendTimeout(duration);
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  disconnectStateAdapter,
3
3
  resolveRuntimeDependencySnapshot
4
- } from "../chunk-YSXHRIWR.js";
4
+ } from "../chunk-QAMTCT2R.js";
5
5
  import {
6
6
  getPluginProviders,
7
7
  getPluginRuntimeDependencies,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/junior",
3
- "version": "0.43.0",
3
+ "version": "0.44.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"