@@ -638,6 +638,7 @@ export async function handleWorkflowRun(
638638 // cold-start bootstrap failure must not turn that into a 500.
639639 environment : ( ) => getWorkflowRuntimeEnvironment ( options ) ,
640640 params : body ?. params ?? { } ,
641+ projectId : body ?. project_id ?? null ,
641642 background : body ?. background ?? false ,
642643 interactive : body ?. interactive === true ,
643644 // The server's own import site, so a test that mocks it still governs.
@@ -1179,13 +1180,19 @@ export async function handleWorkflowImportBundle(
11791180 return errorResponse ( 405 , "Method not allowed" ) ;
11801181 }
11811182 const userId = getUserId ( request , options . userIdHeader ?? "x-user-id" ) ;
1183+ let projectId =
1184+ new URL ( request . url ) . searchParams . get ( "project_id" ) ?? "default" ;
11821185
11831186 let zipBytes : Uint8Array | null = null ;
11841187 const contentType = request . headers . get ( "content-type" ) ?? "" ;
11851188 if ( contentType . toLowerCase ( ) . includes ( "multipart/form-data" ) ) {
11861189 try {
11871190 const fd = await request . formData ( ) ;
11881191 const file = fd . get ( "file" ) as File | null ;
1192+ const formProjectId = fd . get ( "project_id" ) ;
1193+ if ( typeof formProjectId === "string" && formProjectId ) {
1194+ projectId = formProjectId ;
1195+ }
11891196 if ( file ) {
11901197 zipBytes = new Uint8Array ( await file . arrayBuffer ( ) ) ;
11911198 }
@@ -1201,6 +1208,13 @@ export async function handleWorkflowImportBundle(
12011208 if ( ! zipBytes ) {
12021209 return errorResponse ( 400 , "A .nodetool bundle file is required" ) ;
12031210 }
1211+ if ( projectId !== "default" ) {
1212+ try {
1213+ await Project . requireOwned ( userId , projectId ) ;
1214+ } catch {
1215+ return errorResponse ( 400 , "Project not found" ) ;
1216+ }
1217+ }
12041218
12051219 let result : Awaited < ReturnType < typeof importWorkflowBundle > > ;
12061220 try {
@@ -1211,6 +1225,7 @@ export async function handleWorkflowImportBundle(
12111225 name : fileName ,
12121226 content_type : assetType ,
12131227 parent_id : userId ,
1228+ project_id : projectId ,
12141229 size : bytes . byteLength
12151230 } ) ) as Asset ;
12161231 const storedName = getAssetFileName ( asset . id , asset . content_type ) ;
@@ -1623,6 +1638,7 @@ export async function handleExtractAudio(
16231638 content_type : "audio/wav" ,
16241639 parent_id : source . id ,
16251640 workflow_id : source . workflow_id ?? null ,
1641+ project_id : source . project_id ,
16261642 node_id : null ,
16271643 job_id : null ,
16281644 metadata : null ,
0 commit comments