From 040355d4f6df02f6b7cf7dbe15eda0d65c666fdd Mon Sep 17 00:00:00 2001 From: Katy Bowman Date: Thu, 14 May 2026 10:23:51 -0400 Subject: [PATCH 1/4] feat: remove cached netrc account on logout --- package-lock.json | 100 ------------------- src/commands/auth/logout.ts | 9 +- src/lib/accounts/accounts.ts | 4 + test/unit/commands/auth/logout.unit.test.ts | 31 +++++- test/unit/lib/accounts/accounts.unit.test.ts | 44 ++++++++ 5 files changed, 84 insertions(+), 104 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3d5b096ed9..c7bb155089 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6561,27 +6561,6 @@ "node": ">=8.0.0" } }, - "node_modules/@sentry/node/node_modules/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.214.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.214.0.tgz", - "integrity": "sha512-kIN8nTBMgV2hXzV/a20BCFilPZdAIMYYJGSgfMMRm/Xa+07y5hRDS2Vm12A/z8Cdu3Sq++ZvJfElokX2rkgGgw==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "@opentelemetry/core": "2.6.1", - "@opentelemetry/otlp-exporter-base": "0.214.0", - "@opentelemetry/otlp-transformer": "0.214.0", - "@opentelemetry/resources": "2.6.1", - "@opentelemetry/sdk-trace-base": "2.6.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation": { "version": "0.214.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.214.0.tgz", @@ -6599,47 +6578,6 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@sentry/node/node_modules/@opentelemetry/otlp-exporter-base": { - "version": "0.214.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.214.0.tgz", - "integrity": "sha512-u1Gdv0/E9wP+apqWf7Wv2npXmgJtxsW2XL0TEv9FZloTZRuMBKmu8cYVXwS4Hm3q/f/3FuCnPTgiwYvIqRSpRg==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "@opentelemetry/core": "2.6.1", - "@opentelemetry/otlp-transformer": "0.214.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/otlp-transformer": { - "version": "0.214.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.214.0.tgz", - "integrity": "sha512-DSaYcuBRh6uozfsWN3R8HsN0yDhCuWP7tOFdkUOVaWD1KVJg8m4qiLUsg/tNhTLS9HUYUcwNpwL2eroLtsZZ/w==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "@opentelemetry/api-logs": "0.214.0", - "@opentelemetry/core": "2.6.1", - "@opentelemetry/resources": "2.6.1", - "@opentelemetry/sdk-logs": "0.214.0", - "@opentelemetry/sdk-metrics": "2.6.1", - "@opentelemetry/sdk-trace-base": "2.6.1", - "protobufjs": "^7.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, "node_modules/@sentry/node/node_modules/@opentelemetry/resources": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.6.1.tgz", @@ -6656,44 +6594,6 @@ "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, - "node_modules/@sentry/node/node_modules/@opentelemetry/sdk-logs": { - "version": "0.214.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.214.0.tgz", - "integrity": "sha512-zf6acnScjhsaBUU22zXZ/sLWim1dfhUAbGXdMmHmNG3LfBnQ3DKsOCITb2IZwoUsNNMTogqFKBnlIPPftUgGwA==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "@opentelemetry/api-logs": "0.214.0", - "@opentelemetry/core": "2.6.1", - "@opentelemetry/resources": "2.6.1", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/sdk-metrics": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.6.1.tgz", - "integrity": "sha512-9t9hJHX15meBy2NmTJxL+NJfXmnausR2xUDvE19XQce0Qi/GBtDGamU8nS1RMbdgDmhgpm3VaOu2+fiS/SfTpQ==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "@opentelemetry/core": "2.6.1", - "@opentelemetry/resources": "2.6.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.9.0 <1.10.0" - } - }, "node_modules/@sentry/node/node_modules/@opentelemetry/sdk-trace-base": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.1.tgz", diff --git a/src/commands/auth/logout.ts b/src/commands/auth/logout.ts index f7049c7528..2cd439a9b8 100644 --- a/src/commands/auth/logout.ts +++ b/src/commands/auth/logout.ts @@ -1,7 +1,7 @@ - import {Command} from '@heroku-cli/command' import {ux} from '@oclif/core/ux' +import AccountsModule from '../../lib/accounts/accounts.js' import Git from '../../lib/git/git.js' export default class Logout extends Command { @@ -11,9 +11,10 @@ export default class Logout extends Command { static promptFlagActive = false async run() { - this.parse(Logout) + await this.parse(Logout) ux.action.start('Logging out') + const cachedNetrcAccount = await AccountsModule.currentNetrc() await this.heroku.logout() const git = new Git() @@ -24,6 +25,10 @@ export default class Logout extends Command { // ignore } + if (cachedNetrcAccount) { + await AccountsModule.remove(cachedNetrcAccount) + } + await this.config.runHook('recache', {type: 'logout'}) ux.action.stop() } diff --git a/src/lib/accounts/accounts.ts b/src/lib/accounts/accounts.ts index 9773c41c87..04d5761949 100644 --- a/src/lib/accounts/accounts.ts +++ b/src/lib/accounts/accounts.ts @@ -100,6 +100,10 @@ export class AccountsWrapper implements IAccountsWrapper { return authEntry?.account ?? null } + return this.currentNetrc() + } + + async currentNetrc(): Promise { const netrcInstance = await this.initNetrc() if (netrcInstance.machines['api.heroku.com']) { const current = this.listNetrc().find(a => a.username === netrcInstance.machines['api.heroku.com'].login) diff --git a/test/unit/commands/auth/logout.unit.test.ts b/test/unit/commands/auth/logout.unit.test.ts index 236380a7d3..02963b1e9d 100644 --- a/test/unit/commands/auth/logout.unit.test.ts +++ b/test/unit/commands/auth/logout.unit.test.ts @@ -2,21 +2,25 @@ import {expect} from 'chai' import sinon from 'sinon' import Logout from '../../../../src/commands/auth/logout.js' +import AccountsModule from '../../../../src/lib/accounts/accounts.js' import Git from '../../../../src/lib/git/git.js' import {runCommand} from '../../../helpers/run-command.js' describe('auth:logout', function () { let eraseCredentialsStub: sinon.SinonStub let removeCredentialHelperStub: sinon.SinonStub + let currentNetrcStub: sinon.SinonStub + let removeStub: sinon.SinonStub beforeEach(function () { eraseCredentialsStub = sinon.stub(Git.prototype, 'eraseCredentials').resolves() removeCredentialHelperStub = sinon.stub(Git.prototype, 'removeCredentialHelper').resolves() + currentNetrcStub = sinon.stub(AccountsModule, 'currentNetrc').resolves(null) + removeStub = sinon.stub(AccountsModule, 'remove').resolves() }) afterEach(function () { - eraseCredentialsStub.restore() - removeCredentialHelperStub.restore() + sinon.restore() }) it('shows cli logging user out', async function () { @@ -43,4 +47,27 @@ describe('auth:logout', function () { expect(error).to.be.undefined }) + + it('checks for cached netrc account', async function () { + await runCommand(Logout, []) + + expect(currentNetrcStub.calledOnce).to.be.true + }) + + it('removes cached netrc account when present', async function () { + currentNetrcStub.resolves('my-account') + + await runCommand(Logout, []) + + expect(removeStub.calledOnce).to.be.true + expect(removeStub.firstCall.args[0]).to.equal('my-account') + }) + + it('does not remove account when no cached netrc account', async function () { + currentNetrcStub.resolves(null) + + await runCommand(Logout, []) + + expect(removeStub.called).to.be.false + }) }) diff --git a/test/unit/lib/accounts/accounts.unit.test.ts b/test/unit/lib/accounts/accounts.unit.test.ts index d7d98ec5b3..7b851a4f76 100644 --- a/test/unit/lib/accounts/accounts.unit.test.ts +++ b/test/unit/lib/accounts/accounts.unit.test.ts @@ -232,6 +232,50 @@ describe('accounts', function () { }) }) + describe('currentNetrc()', function () { + let fakeNetrc: {machines: Record, save: sinon.SinonStub} + + function setNetrc(value: typeof fakeNetrc | undefined) { + (AccountsModule as unknown as {netrc: typeof fakeNetrc | undefined}).netrc = value + } + + beforeEach(function () { + fakeNetrc = {machines: {}, save: sinon.stub().resolves()} + setNetrc(fakeNetrc) + fsReadFileStub.withArgs(sinon.match(/my-account$/), 'utf8') + .returns('username: user@example.com\npassword: secret\n') + fsReaddirStub.returns(['my-account', 'other-account']) + fsReadFileStub.withArgs(sinon.match(/other-account$/), 'utf8') + .returns('username: other@example.com\npassword: secret\n') + }) + + afterEach(function () { + setNetrc(null as unknown as typeof fakeNetrc) + }) + + it('returns account name when api.heroku.com machine exists and matches', async function () { + fakeNetrc.machines['api.heroku.com'] = {login: 'user@example.com', password: 'secret'} + + const result = await AccountsModule.currentNetrc() + + expect(result).to.equal('my-account') + }) + + it('returns null when api.heroku.com machine does not exist', async function () { + const result = await AccountsModule.currentNetrc() + + expect(result).to.equal(null) + }) + + it('returns null when no account matches the login', async function () { + fakeNetrc.machines['api.heroku.com'] = {login: 'nomatch@example.com', password: 'secret'} + + const result = await AccountsModule.currentNetrc() + + expect(result).to.equal(null) + }) + }) + describe('remove', function () { let unlinkStub: sinon.SinonStub let osHomeStub: sinon.SinonStub From c6aa14ea7a3f69c62ab7085dda864fdebfd20aa5 Mon Sep 17 00:00:00 2001 From: Katy Bowman Date: Thu, 14 May 2026 10:48:43 -0400 Subject: [PATCH 2/4] fix: remove netrc cache on logout without env var --- src/commands/auth/logout.ts | 2 +- src/lib/accounts/accounts.ts | 6 ++++ test/unit/commands/auth/logout.unit.test.ts | 10 +++---- test/unit/lib/accounts/accounts.unit.test.ts | 31 +++++++++++++++----- 4 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/commands/auth/logout.ts b/src/commands/auth/logout.ts index 2cd439a9b8..0222ccbc91 100644 --- a/src/commands/auth/logout.ts +++ b/src/commands/auth/logout.ts @@ -26,7 +26,7 @@ export default class Logout extends Command { } if (cachedNetrcAccount) { - await AccountsModule.remove(cachedNetrcAccount) + AccountsModule.removeNetrc(cachedNetrcAccount) } await this.config.runHook('recache', {type: 'logout'}) diff --git a/src/lib/accounts/accounts.ts b/src/lib/accounts/accounts.ts index 04d5761949..580eec8941 100644 --- a/src/lib/accounts/accounts.ts +++ b/src/lib/accounts/accounts.ts @@ -14,8 +14,10 @@ export interface AccountEntry { export interface IAccountsWrapper { list(): Promise current(heroku: APIClient): Promise + currentNetrc(): Promise add(name: string, username: string, password: string): void remove(name: string): void + removeNetrc(name: string): void set(account: AccountEntry, dataDir: string): Promise getStorageConfig(): ReturnType writeLoginState(dataDir: string, name: string): Promise @@ -136,6 +138,10 @@ export class AccountsWrapper implements IAccountsWrapper { return } + this.removeNetrc(name) + } + + removeNetrc(name: string) { const basedir = path.join(this.configDir(), 'accounts') fs.unlinkSync(path.join(basedir, name)) } diff --git a/test/unit/commands/auth/logout.unit.test.ts b/test/unit/commands/auth/logout.unit.test.ts index 02963b1e9d..746c303866 100644 --- a/test/unit/commands/auth/logout.unit.test.ts +++ b/test/unit/commands/auth/logout.unit.test.ts @@ -10,13 +10,13 @@ describe('auth:logout', function () { let eraseCredentialsStub: sinon.SinonStub let removeCredentialHelperStub: sinon.SinonStub let currentNetrcStub: sinon.SinonStub - let removeStub: sinon.SinonStub + let removeNetrcStub: sinon.SinonStub beforeEach(function () { eraseCredentialsStub = sinon.stub(Git.prototype, 'eraseCredentials').resolves() removeCredentialHelperStub = sinon.stub(Git.prototype, 'removeCredentialHelper').resolves() currentNetrcStub = sinon.stub(AccountsModule, 'currentNetrc').resolves(null) - removeStub = sinon.stub(AccountsModule, 'remove').resolves() + removeNetrcStub = sinon.stub(AccountsModule, 'removeNetrc') }) afterEach(function () { @@ -59,8 +59,8 @@ describe('auth:logout', function () { await runCommand(Logout, []) - expect(removeStub.calledOnce).to.be.true - expect(removeStub.firstCall.args[0]).to.equal('my-account') + expect(removeNetrcStub.calledOnce).to.be.true + expect(removeNetrcStub.firstCall.args[0]).to.equal('my-account') }) it('does not remove account when no cached netrc account', async function () { @@ -68,6 +68,6 @@ describe('auth:logout', function () { await runCommand(Logout, []) - expect(removeStub.called).to.be.false + expect(removeNetrcStub.called).to.be.false }) }) diff --git a/test/unit/lib/accounts/accounts.unit.test.ts b/test/unit/lib/accounts/accounts.unit.test.ts index 7b851a4f76..9dc6dd9cae 100644 --- a/test/unit/lib/accounts/accounts.unit.test.ts +++ b/test/unit/lib/accounts/accounts.unit.test.ts @@ -276,7 +276,7 @@ describe('accounts', function () { }) }) - describe('remove', function () { + describe('removeNetrc()', function () { let unlinkStub: sinon.SinonStub let osHomeStub: sinon.SinonStub let existsSyncStub: sinon.SinonStub @@ -287,14 +287,14 @@ describe('accounts', function () { existsSyncStub = sinon.stub(fs, 'existsSync') }) - it('should remove the account file with the given name', async function () { + it('should remove the account file with the given name', function () { const accountName = 'test-account' const basedir = '/user/home' osHomeStub.returns(basedir) existsSyncStub.returns(false) - await AccountsModule.remove(accountName) + AccountsModule.removeNetrc(accountName) expect(unlinkStub.calledOnce).to.be.true expect(unlinkStub.firstCall.args[0]).to.equal( @@ -302,12 +302,29 @@ describe('accounts', function () { ) }) - it('should throw an error if the file cannot be removed', async function () { + it('should throw an error if the file cannot be removed', function () { const accountName = 'non-existent-account' const error = new Error('File not found') unlinkStub.throws(error) - await expect(AccountsModule.remove(accountName)).to.be.rejectedWith(Error) + expect(() => AccountsModule.removeNetrc(accountName)).to.throw(Error) + }) + }) + + describe('remove', function () { + let removeNetrcStub: sinon.SinonStub + + beforeEach(function () { + removeNetrcStub = sinon.stub(AccountsModule, 'removeNetrc') + }) + + it('should call removeNetrc when no credential store', async function () { + const accountName = 'test-account' + + await AccountsModule.remove(accountName) + + expect(removeNetrcStub.calledOnce).to.be.true + expect(removeNetrcStub.firstCall.args[0]).to.equal(accountName) }) describe('with credentialStore', function () { @@ -336,12 +353,12 @@ describe('accounts', function () { expect(removeAuthStub.firstCall.args[1]).to.deep.equal(['api.heroku.com', 'git.heroku.com']) }) - it('should not call unlinkSync when credentialStore is set', async function () { + it('should not call removeNetrc when credentialStore is set', async function () { const accountName = 'test-account@example.com' await AccountsModule.remove(accountName) - expect(unlinkStub.called).to.be.false + expect(removeNetrcStub.called).to.be.false }) it('should throw an error if removeAuth fails', async function () { From d9de3f19847690c1e2207e91a756f95b99735151 Mon Sep 17 00:00:00 2001 From: Katy Bowman Date: Thu, 14 May 2026 10:52:17 -0400 Subject: [PATCH 3/4] update package-lock --- package-lock.json | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index c7bb155089..b9d02d9c74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6561,6 +6561,21 @@ "node": ">=8.0.0" } }, + "node_modules/@sentry/node/node_modules/@opentelemetry/core": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.1.tgz", + "integrity": "sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation": { "version": "0.214.0", "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.214.0.tgz", @@ -6579,12 +6594,12 @@ } }, "node_modules/@sentry/node/node_modules/@opentelemetry/resources": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.6.1.tgz", - "integrity": "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", + "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.6.1", + "@opentelemetry/core": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -6595,13 +6610,13 @@ } }, "node_modules/@sentry/node/node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.1.tgz", - "integrity": "sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", + "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.6.1", - "@opentelemetry/resources": "2.6.1", + "@opentelemetry/core": "2.7.1", + "@opentelemetry/resources": "2.7.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { From 32068d247364dafa3e4d4b19a85293be639a1dd3 Mon Sep 17 00:00:00 2001 From: Katy Bowman Date: Thu, 14 May 2026 10:55:27 -0400 Subject: [PATCH 4/4] revert package-lock changes --- package-lock.json | 115 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index b9d02d9c74..3d5b096ed9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6561,19 +6561,25 @@ "node": ">=8.0.0" } }, - "node_modules/@sentry/node/node_modules/@opentelemetry/core": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.7.1.tgz", - "integrity": "sha512-QAqIj32AtK6+pEVNG7EOVxHdE06RP+FM5qpiEJ4RtDcFIqKUZHYhl7/7UY5efhwmwNAg7j8QbJVBLxMerc0+gw==", + "node_modules/@sentry/node/node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.214.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.214.0.tgz", + "integrity": "sha512-kIN8nTBMgV2hXzV/a20BCFilPZdAIMYYJGSgfMMRm/Xa+07y5hRDS2Vm12A/z8Cdu3Sq++ZvJfElokX2rkgGgw==", "license": "Apache-2.0", + "optional": true, + "peer": true, "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" + "@opentelemetry/core": "2.6.1", + "@opentelemetry/otlp-exporter-base": "0.214.0", + "@opentelemetry/otlp-transformer": "0.214.0", + "@opentelemetry/resources": "2.6.1", + "@opentelemetry/sdk-trace-base": "2.6.1" }, "engines": { "node": "^18.19.0 || >=20.6.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@opentelemetry/api": "^1.3.0" } }, "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation": { @@ -6593,13 +6599,54 @@ "@opentelemetry/api": "^1.3.0" } }, + "node_modules/@sentry/node/node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.214.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.214.0.tgz", + "integrity": "sha512-u1Gdv0/E9wP+apqWf7Wv2npXmgJtxsW2XL0TEv9FZloTZRuMBKmu8cYVXwS4Hm3q/f/3FuCnPTgiwYvIqRSpRg==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@opentelemetry/core": "2.6.1", + "@opentelemetry/otlp-transformer": "0.214.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@sentry/node/node_modules/@opentelemetry/otlp-transformer": { + "version": "0.214.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.214.0.tgz", + "integrity": "sha512-DSaYcuBRh6uozfsWN3R8HsN0yDhCuWP7tOFdkUOVaWD1KVJg8m4qiLUsg/tNhTLS9HUYUcwNpwL2eroLtsZZ/w==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@opentelemetry/api-logs": "0.214.0", + "@opentelemetry/core": "2.6.1", + "@opentelemetry/resources": "2.6.1", + "@opentelemetry/sdk-logs": "0.214.0", + "@opentelemetry/sdk-metrics": "2.6.1", + "@opentelemetry/sdk-trace-base": "2.6.1", + "protobufjs": "^7.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, "node_modules/@sentry/node/node_modules/@opentelemetry/resources": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.7.1.tgz", - "integrity": "sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.6.1.tgz", + "integrity": "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.7.1", + "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": { @@ -6609,14 +6656,52 @@ "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, + "node_modules/@sentry/node/node_modules/@opentelemetry/sdk-logs": { + "version": "0.214.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.214.0.tgz", + "integrity": "sha512-zf6acnScjhsaBUU22zXZ/sLWim1dfhUAbGXdMmHmNG3LfBnQ3DKsOCITb2IZwoUsNNMTogqFKBnlIPPftUgGwA==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@opentelemetry/api-logs": "0.214.0", + "@opentelemetry/core": "2.6.1", + "@opentelemetry/resources": "2.6.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@sentry/node/node_modules/@opentelemetry/sdk-metrics": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.6.1.tgz", + "integrity": "sha512-9t9hJHX15meBy2NmTJxL+NJfXmnausR2xUDvE19XQce0Qi/GBtDGamU8nS1RMbdgDmhgpm3VaOu2+fiS/SfTpQ==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "@opentelemetry/core": "2.6.1", + "@opentelemetry/resources": "2.6.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" + } + }, "node_modules/@sentry/node/node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.7.1.tgz", - "integrity": "sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.6.1.tgz", + "integrity": "sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw==", "license": "Apache-2.0", "dependencies": { - "@opentelemetry/core": "2.7.1", - "@opentelemetry/resources": "2.7.1", + "@opentelemetry/core": "2.6.1", + "@opentelemetry/resources": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "engines": {