@@ -21,6 +21,9 @@ export class CodeThreatApiClient {
2121 private config = getConfig ( ) ;
2222
2323 constructor ( ) {
24+ // Reload config to pick up environment variables set by Azure extension
25+ this . config = getConfig ( ) ;
26+
2427 // Use environment variable or config for server URL
2528 const serverUrl = process . env . CT_SERVER_URL || this . config . serverUrl ;
2629 const timeout = parseInt ( process . env . CT_API_TIMEOUT || '30000' ) ;
@@ -42,10 +45,6 @@ export class CodeThreatApiClient {
4245 config . headers [ 'X-API-Key' ] = apiKey ;
4346 }
4447
45- if ( this . config . verbose ) {
46- console . log ( chalk . gray ( `→ ${ config . method ?. toUpperCase ( ) } ${ config . url } ` ) ) ;
47- }
48-
4948 return config ;
5049 } ) ;
5150
@@ -103,6 +102,7 @@ export class CodeThreatApiClient {
103102 */
104103 async importRepository ( options : {
105104 url : string ;
105+ organizationSlug ?: string ;
106106 name ?: string ;
107107 provider ?: Provider ;
108108 branch ?: string ;
@@ -111,9 +111,32 @@ export class CodeThreatApiClient {
111111 isPrivate ?: boolean ;
112112 description ?: string ;
113113 } ) : Promise < RepositoryImportResponse > {
114+ // Create request body - ensure organizationSlug is ALWAYS included
115+ const organizationSlug = options . organizationSlug || this . config . organizationSlug || process . env . CT_ORG_SLUG || '' ;
116+
117+ // Build clean request body without undefined values
118+ const requestBody : any = {
119+ url : options . url ,
120+ organizationSlug : organizationSlug
121+ } ;
122+
123+ // Only add optional fields if they have values
124+ if ( options . name ) requestBody . name = options . name ;
125+ if ( options . provider ) requestBody . provider = options . provider ;
126+ if ( options . branch ) requestBody . branch = options . branch ;
127+ if ( options . autoScan !== undefined ) requestBody . autoScan = options . autoScan ;
128+ if ( options . scanTypes ) requestBody . scanTypes = options . scanTypes ;
129+ if ( options . isPrivate !== undefined ) requestBody . isPrivate = options . isPrivate ;
130+ if ( options . description ) requestBody . description = options . description ;
131+
132+ // Validate organizationSlug is present
133+ if ( ! requestBody . organizationSlug ) {
134+ throw new Error ( 'Organization slug is required. Please set CT_ORG_SLUG environment variable or provide organizationSlug parameter.' ) ;
135+ }
136+
114137 const response = await this . client . post < ApiResponse < RepositoryImportResponse > > (
115138 '/api/v1/repositories/import' ,
116- options
139+ requestBody
117140 ) ;
118141
119142 return this . handleResponse ( response ) ;
@@ -135,6 +158,7 @@ export class CodeThreatApiClient {
135158 */
136159 async runScan ( options : {
137160 repositoryId : string ;
161+ organizationSlug ?: string ;
138162 branch ?: string ;
139163 scanTypes : ScanType [ ] ;
140164 wait ?: boolean ;
@@ -145,11 +169,37 @@ export class CodeThreatApiClient {
145169 commitSha ?: string ;
146170 metadata ?: Record < string , string > ;
147171 } ) : Promise < ScanRunResponse > {
172+ // Get organizationSlug from options, config, or environment
173+ const organizationSlug = options . organizationSlug || this . config . organizationSlug || process . env . CT_ORG_SLUG || '' ;
174+
175+ // Build clean request body without undefined values
176+ const requestBody : any = {
177+ repositoryId : options . repositoryId ,
178+ organizationSlug : organizationSlug ,
179+ scanTypes : options . scanTypes
180+ } ;
181+
182+ // Only add optional fields if they have values
183+ if ( options . branch ) requestBody . branch = options . branch ;
184+ if ( options . wait !== undefined ) requestBody . wait = options . wait ;
185+ if ( options . timeout !== undefined ) requestBody . timeout = options . timeout ;
186+ if ( options . pollInterval !== undefined ) requestBody . pollInterval = options . pollInterval ;
187+ if ( options . scanTrigger ) requestBody . scanTrigger = options . scanTrigger ;
188+ if ( options . pullRequestId ) requestBody . pullRequestId = options . pullRequestId ;
189+ if ( options . commitSha ) requestBody . commitSha = options . commitSha ;
190+ if ( options . metadata ) requestBody . metadata = options . metadata ;
191+
192+
193+ // Validate organizationSlug is present
194+ if ( ! requestBody . organizationSlug ) {
195+ throw new Error ( 'Organization slug is required. Please set CT_ORG_SLUG environment variable or provide organizationSlug parameter.' ) ;
196+ }
197+
148198 const response = await this . client . post < ApiResponse < ScanRunResponse > > (
149199 '/api/v1/scans/run' ,
150- options ,
200+ requestBody ,
151201 {
152- timeout : options . wait ? ( options . timeout || 1800 ) * 1000 + 30000 : 30000 , // Add 30s buffer for API processing
202+ timeout : options . wait ? ( options . timeout || 43200 ) * 1000 + 30000 : 30000 , // Default 12 hours for long scans, add 30s buffer for API processing
153203 }
154204 ) ;
155205
@@ -160,9 +210,15 @@ export class CodeThreatApiClient {
160210 * Get scan status
161211 */
162212 async getScanStatus ( scanId : string , includeLogs = false ) : Promise < ScanStatusResponse > {
213+ // Include organizationSlug if available
214+ const params : any = { includeLogs } ;
215+ if ( this . config . organizationSlug || process . env . CT_ORG_SLUG ) {
216+ params . organizationSlug = this . config . organizationSlug || process . env . CT_ORG_SLUG ;
217+ }
218+
163219 const response = await this . client . get < ApiResponse < ScanStatusResponse > > (
164220 `/api/v1/scans/${ scanId } /status` ,
165- { params : { includeLogs } }
221+ { params }
166222 ) ;
167223
168224 return this . handleResponse ( response ) ;
@@ -182,9 +238,16 @@ export class CodeThreatApiClient {
182238 ruleIds ?: string [ ] ;
183239 } ) : Promise < ScanResultsResponse > {
184240 const { scanId, ...params } = options ;
241+
242+ // Include organizationSlug if available
243+ const requestParams : any = { ...params } ;
244+ if ( this . config . organizationSlug || process . env . CT_ORG_SLUG ) {
245+ requestParams . organizationSlug = this . config . organizationSlug || process . env . CT_ORG_SLUG ;
246+ }
247+
185248 const response = await this . client . get < ApiResponse < ScanResultsResponse > > (
186249 `/api/v1/scans/${ scanId } /results` ,
187- { params }
250+ { params : requestParams }
188251 ) ;
189252
190253 return this . handleResponse ( response ) ;
@@ -246,10 +309,6 @@ export class CodeThreatApiClient {
246309 private handleResponse < T > ( response : AxiosResponse < ApiResponse < T > > ) : T {
247310 const { data } = response ;
248311
249- if ( this . config . verbose ) {
250- console . log ( chalk . gray ( 'Response data:' ) , JSON . stringify ( data , null , 2 ) ) ;
251- }
252-
253312 if ( ! data . success ) {
254313 throw new Error ( data . error ?. message || 'API request failed' ) ;
255314 }
@@ -265,10 +324,6 @@ export class CodeThreatApiClient {
265324 * Handle API errors with user-friendly messages
266325 */
267326 private handleApiError ( error : AxiosError ) : void {
268- if ( this . config . verbose ) {
269- console . error ( chalk . red ( 'API Error Details:' ) , error . response ?. data || error . message ) ;
270- }
271-
272327 if ( error . response ) {
273328 const status = error . response . status ;
274329 const data = error . response . data as any ;
0 commit comments