@@ -602,7 +602,11 @@ export function registerProjectExportRoutes(app: Express, ctx: RegisterProjectEx
602602 async function authorizeExportRead (
603603 req : any ,
604604 res : any ,
605- options : { allowNavigationQuery ?: boolean ; toolEndpoint ?: string } = { } ,
605+ options : {
606+ allowNavigationQuery ?: boolean ;
607+ deriveWorkspaceFromProject ?: boolean ;
608+ toolEndpoint ?: string ;
609+ } = { } ,
606610 ) : Promise < AuthorizedExportRead | null > {
607611 const authorization = req . get ( 'authorization' ) ;
608612 if (
@@ -627,6 +631,14 @@ export function registerProjectExportRoutes(app: Express, ctx: RegisterProjectEx
627631 ) ;
628632 return authority ? { previewWorkspace : authority . workspace } : null ;
629633 }
634+ if ( options . deriveWorkspaceFromProject ) {
635+ const authority = await ctx . authorizeProjectToolRequest (
636+ res ,
637+ req . params . id ,
638+ { mode : 'read' } ,
639+ ) ;
640+ return authority ? { previewWorkspace : authority . workspace } : null ;
641+ }
630642 const authorized = await ctx . authorizeProjectRequest (
631643 req ,
632644 res ,
@@ -1392,7 +1404,10 @@ export function registerProjectExportRoutes(app: Express, ctx: RegisterProjectEx
13921404 // PNG and assemble a one-image-per-slide .pptx. Replaces the old "send a prompt
13931405 // to the agent and hope it runs python-pptx" path with a deterministic export.
13941406 app . post ( '/api/projects/:id/export/pptx' , async ( req , res ) => {
1395- const authority = await authorizeExportRead ( req , res , { toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT } ) ;
1407+ const authority = await authorizeExportRead ( req , res , {
1408+ deriveWorkspaceFromProject : true ,
1409+ toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT ,
1410+ } ) ;
13961411 if ( ! authority ) return ;
13971412 await handleScreenshotExport ( res , 'pptx' , req . params . id , { authority, body : req . body } ) ;
13981413 } ) ;
@@ -1401,7 +1416,10 @@ export function registerProjectExportRoutes(app: Express, ctx: RegisterProjectEx
14011416 // The print-ready vector PDF stays on POST /export/pdf; this is the "exactly
14021417 // what you see" counterpart that shares the slide renderer with PPTX.
14031418 app . post ( '/api/projects/:id/export/pdf-image' , async ( req , res ) => {
1404- const authority = await authorizeExportRead ( req , res , { toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT } ) ;
1419+ const authority = await authorizeExportRead ( req , res , {
1420+ deriveWorkspaceFromProject : true ,
1421+ toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT ,
1422+ } ) ;
14051423 if ( ! authority ) return ;
14061424 await handleScreenshotExport ( res , 'pdf' , req . params . id , { authority, body : req . body } ) ;
14071425 } ) ;
@@ -1411,7 +1429,10 @@ export function registerProjectExportRoutes(app: Express, ctx: RegisterProjectEx
14111429 // the whole document at natural size. Viewport-independent — unlike the
14121430 // host-compositor snapshot, the size never depends on the preview pane.
14131431 app . post ( '/api/projects/:id/export/image' , async ( req , res ) => {
1414- const authority = await authorizeExportRead ( req , res , { toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT } ) ;
1432+ const authority = await authorizeExportRead ( req , res , {
1433+ deriveWorkspaceFromProject : true ,
1434+ toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT ,
1435+ } ) ;
14151436 if ( ! authority ) return ;
14161437 await handleScreenshotExport ( res , 'image' , req . params . id , { authority, body : req . body } ) ;
14171438 } ) ;
@@ -1420,7 +1441,10 @@ export function registerProjectExportRoutes(app: Express, ctx: RegisterProjectEx
14201441 // embedded by the daemon. Remote HTTP(S) dependencies remain external and
14211442 // are listed in a machine-readable manifest inside the output.
14221443 app . post ( '/api/projects/:id/export/html' , async ( req , res ) => {
1423- const authority = await authorizeExportRead ( req , res , { toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT } ) ;
1444+ const authority = await authorizeExportRead ( req , res , {
1445+ deriveWorkspaceFromProject : true ,
1446+ toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT ,
1447+ } ) ;
14241448 if ( ! authority ) return ;
14251449 await handleStandaloneHtmlExport ( res , req . params . id , req . body ) ;
14261450 } ) ;
@@ -1438,7 +1462,10 @@ export function registerProjectExportRoutes(app: Express, ctx: RegisterProjectEx
14381462 if ( ! isExportFormat ( format ) ) {
14391463 return sendApiError ( res , 400 , 'BAD_REQUEST' , 'invalid export format' ) ;
14401464 }
1441- const authority = await authorizeExportRead ( req , res , { toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT } ) ;
1465+ const authority = await authorizeExportRead ( req , res , {
1466+ deriveWorkspaceFromProject : true ,
1467+ toolEndpoint : PROJECT_EXPORT_TOOL_ENDPOINT ,
1468+ } ) ;
14421469 if ( ! authority ) return ;
14431470 if ( format === 'html' ) {
14441471 return handleStandaloneHtmlExport ( res , req . params . id , {
0 commit comments