GeezerVison is showing github.com — feat(vscode): select org explicitly by jdalton · Pull Request #83 · SocketDev/socket-vscode
Conversation
LLM Description written by Codex: GPT-6
Prepares the VS Code extension for organization-scoped package intelligence: users can select an accessible organization, and credential changes clear stale results. Existing token-only sessions keep working.
This prerequisite does not switch package requests to the new API or apply organization policy to the current package view. Package requests still use the existing API. A separate integration will use the selected organization after the new API is deployed and SDK support is released.
The extension exposes socket-security.orgSlug, validates the selected slug against accessible organizations, and invalidates stale authentication and manager results when credentials or organization context changes.
Pending local gate fixes: the signed commit in this PR's remote head does not yet contain the following corrections. They are committed locally as a9c3ca85662487ca9aea924f03013df5abc3dfdc but could not be pushed because mandatory pre-push validation rejected the unrelated base workflow lint issue described below:
- Lockfile metadata for six hydrated hook importers.
- Six repo-owned imports changed to the canonical fail-soft runner path in
test-extension, fuzz, and install-claude-plugins scripts.
Validation and coverage
Remote head 1555d380413a535fe9022222872d54bf0472bd90 had 62 focused tests pass across 5 files, source type check pass, and git diff --check pass. Its remote CI setup failed on all operating systems because the hydrated claude-md-rule-add-guard importer lacked @socketsecurity/lib-stable@catalog: in the lockfile. The local pending lockfile correction passes frozen install with pinned pnpm 12.10.1.
The local pending imports pass script --describe and --help checks, repo source type check, and git diff --check. Full pnpm run check:types on the original remote head was blocked by missing generated ignored scripts/fleet/process/run-main.mts.
The push hook also reports an unrelated lint failure: .github/workflows/publish-npm.yml: run name must use the validated publish task name contract. Fix the canonical label and sync its copies. This issue is in the base and remains unresolved.
pnpm test could not run because another shared heavy job occupied the host. No real VS Code extension-host test ran; SecretStorage behavior was not verified in the host.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
cursor
Bot
left a comment
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this 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 using high effort and found 2 potential issues.

Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Org selection unused by package fetches
- Package fetches now send the organization resolved by getAuthenticatedContext to the org-scoped purl endpoint when socket-security.orgSlug selects an accessible org.

Or push these changes by commenting:
Preview (260a33cf1b)
diff --git a/src/api.mts b/src/api.mts
--- a/src/api.mts
+++ b/src/api.mts
@@ -23,6 +23,7 @@
}
export type PackageRequestOptions = {
+ orgSlug?: string | undefined
signal?: AbortSignal | undefined
timeout?: number | undefined
}
@@ -236,17 +237,25 @@
options?: PackageRequestOptions | undefined,
): AsyncGenerator {
const sdk = createSocketSdk(apiKey, options)
+ const { orgSlug } = {
+ __proto__: null,
+ ...options,
+ } as PackageRequestOptions
const batchSize = 1024
+ const query = { alerts: true, compact: false }
for (let index = 0, { length } = purls; index < length; index += batchSize) {
const components = purls
.slice(index, index + batchSize)
.map(purl => ({ __proto__: null, purl }))
- const result = await sdk.batchPackageFetch(
- { components },
- { alerts: true, compact: false },
- )
+ const result = orgSlug
+ ? await sdk.batchOrgPackageFetch(orgSlug, { components }, query)
+ : await sdk.batchPackageFetch({ components }, query)
if (!result.success) {
- throw createPackageRequestError(result)
+ throw createPackageRequestError({
+ error: '',
+ status: result.status,
+ success: false,
+ })
}
yield* result.data
}
diff --git a/src/ui/purl-alerts-and-scores/manager.mts b/src/ui/purl-alerts-and-scores/manager.mts
--- a/src/ui/purl-alerts-and-scores/manager.mts
+++ b/src/ui/purl-alerts-and-scores/manager.mts
@@ -3,12 +3,15 @@
import { logger } from '../../infra/log.mts'
import path from 'node:path'
import { mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
-import { getAPIKey } from '../../auth.mts'
+import { getAPIKey, getAuthenticatedContext } from '../../auth.mts'
import {
isPackageDisplayDataRenderable,
streamPackageScores,
} from '../../api.mts'
-import type { PackageScoreAndAlerts } from '../../api.mts'
+import type {
+ PackageRequestOptions,
+ PackageScoreAndAlerts,
+} from '../../api.mts'
import { safeDeleteSync } from '@socketsecurity/lib/fs/safe'
import { isObject } from '@socketsecurity/lib/objects/predicates'
import { worstArtifactsByPurl } from './select-artifacts.mts'
@@ -168,6 +171,33 @@
#generation = 0
#contextReady = true
private constructor() {}
+ async #resolvePackageFetchRequest(
+ signal: AbortSignal,
+ timeout: number,
+ ): Promise<{
+ apiKey: string | undefined
+ options: PackageRequestOptions
+ }> {
+ const transport = { signal, timeout }
+ const configuredSlug = vscode.workspace
+ .getConfiguration()
+ .get('socket-security.orgSlug')
+ if (typeof configuredSlug !== 'string' || configuredSlug.length === 0) {
+ return { apiKey: await getAPIKey(), options: transport }
+ }
+ const authenticated = await getAuthenticatedContext()
+ if (!authenticated) {
+ return { apiKey: await getAPIKey(), options: transport }
+ }
+ return {
+ apiKey: authenticated.accessToken,
+ options: {
+ orgSlug: authenticated.organization.slug,
+ signal,
+ timeout,
+ },
+ }
+ }
clear(requeueActive = true) {
this.#generation += 1
if (!requeueActive) {
@@ -280,17 +310,21 @@
)
})
try {
- const apiKey = await getAPIKey()
+ const request = await this.#resolvePackageFetchRequest(
+ controller.signal,
+ this.timeout,
+ )
if (controller.signal.aborted || generation !== this.#generation) {
return
}
// logger.info(`Requesting Socket API for PURLs: ${[...thesePendingUpdates].join(', ')}`)
// Bound the SDK request with the same ceiling the AbortController timer
// uses so a hung connection can't leave entries pending forever.
- const scores = streamPackageScores(apiKey, [...thesePendingUpdates], {
- signal: controller.signal,
- timeout: this.timeout,
- })
+ const scores = streamPackageScores(
+ request.apiKey,
+ [...thesePendingUpdates],
+ request.options,
+ )
// The /v0/purl endpoint can stream MULTIPLE artifacts for the same
// input PURL (e.g. a PyPI sdist and wheel of one version) with
// different scores and alerts. Buffer them all, then collapse to the
diff --git a/test/repo/unit/api.test.mts b/test/repo/unit/api.test.mts
--- a/test/repo/unit/api.test.mts
+++ b/test/repo/unit/api.test.mts
@@ -404,6 +404,22 @@
expect(seen.map(s => s.score.overall)).toEqual([42, 99])
})
+ test('requests the organization purl endpoint for a selected org', async () => {
+ const purl = 'pkg:npm/[email protected]' as SimPURL
+ const scope = nock(API_ORIGIN)
+ .post('/v0/orgs/example-org/purl', { components: [{ purl }] })
+ .query({ alerts: 'true', compact: 'false' })
+ .reply(200, `${artifactLine(purl, 0.5)}\n`)
+
+ const seen = await collectPackageScores(
+ streamPackageScores(TOKEN, [purl], { orgSlug: 'example-org' }),
+ )
+
+ expect(seen).toHaveLength(1)
+ expect(seen[0]?.score.overall).toBe(0.5)
+ expect(scope.isDone()).toBe(true)
+ })
+
test('requests /v0/purl with the pending purls in the body', async () => {
const purl = 'pkg:npm/[email protected]' as SimPURL
let sentBody: unknown
diff --git a/test/repo/unit/ui/purl-alerts-and-scores/manager-cache-requests.test.mts b/test/repo/unit/ui/purl-alerts-and-scores/manager-cache-requests.test.mts
--- a/test/repo/unit/ui/purl-alerts-and-scores/manager-cache-requests.test.mts
+++ b/test/repo/unit/ui/purl-alerts-and-scores/manager-cache-requests.test.mts
@@ -4,11 +4,15 @@
import type { logger as realLogger } from '../../../../../src/infra/log.mts'
import type { SimPURL } from '../../../../../src/ui/externals/parse-externals.mts'
import { PURLDataCache } from '../../../../../src/ui/purl-alerts-and-scores/manager.mts'
+import { setStubWorkspaceState } from '../../../../stubs/vscode.mts'
-const { getAPIKey, streamPackageScores } = vi.hoisted(() => ({
- getAPIKey: vi.fn(),
- streamPackageScores: vi.fn(),
-}))
+const { getAPIKey, getAuthenticatedContext, streamPackageScores } = vi.hoisted(
+ () => ({
+ getAPIKey: vi.fn(),
+ getAuthenticatedContext: vi.fn(),
+ streamPackageScores: vi.fn(),
+ }),
+)
vi.mock(import('node:fs'), async importOriginal => ({
...(await importOriginal()),
@@ -20,7 +24,10 @@
writeFileSync: vi.fn(),
}))
vi.mock(import('../../../../../src/api.mts'), () => ({ streamPackageScores }))
-vi.mock(import('../../../../../src/auth.mts'), () => ({ getAPIKey }))
+vi.mock(import('../../../../../src/auth.mts'), () => ({
+ getAPIKey,
+ getAuthenticatedContext,
+}))
vi.mock(import('../../../../../src/infra/log.mts'), () => ({
logger: {
debug: vi.fn(),
@@ -60,6 +67,8 @@
vi.useFakeTimers()
vi.setSystemTime(new Date('2026-01-01T00:00:00Z'))
getAPIKey.mockReset().mockResolvedValue('test-placeholder-token')
+ getAuthenticatedContext.mockReset().mockResolvedValue(undefined)
+ setStubWorkspaceState({})
streamPackageScores.mockReset().mockImplementation(async function* (
...request: [string, SimPURL[]]
) {
@@ -141,6 +150,37 @@
expect(entry.pkgData).toEqual(packageScore(purl))
})
+ test('sends the selected organization slug with the package request', async () => {
+ setStubWorkspaceState({
+ configuration: { 'socket-security.orgSlug': 'example-org' },
+ })
+ getAuthenticatedContext.mockResolvedValue({
+ accessToken: 'test-placeholder-token',
+ organization: {
+ id: 'example-org',
+ image: undefined,
+ name: 'Example Organization',
+ plan: 'team',
+ slug: 'example-org',
+ },
+ })
+ const purl = 'pkg:npm/[email protected]'
+ const entry = cache.watch(purl)
+ await flushRequests()
+
+ expect(getAPIKey).not.toHaveBeenCalled()
+ expect(streamPackageScores).toHaveBeenCalledWith(
+ 'test-placeholder-token',
+ [purl],
+ {
+ orgSlug: 'example-org',
+ signal: expect.any(AbortSignal),
+ timeout: cache.timeout,
+ },
+ )
+ expect(entry.pkgData).toEqual(packageScore(purl))
+ })
+
test('uses anonymous lookup without a token and clears the timer', async () => {
getAPIKey.mockResolvedValueOnce(undefined)
const purl = 'pkg:npm/[email protected]'
You can send follow-ups to the cloud agent here.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 1555d38. Configure here.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Reviewers
At least 1 approving review is required to merge this pull request.
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|