@@ -673,21 +673,38 @@ test("POST /v1/tokens/path", async (t) => {
673673} ) ;
674674
675675test ( "POST /v1/tokens/workspace-path" , async ( t ) => {
676- async function seedWorkspace (
677- app : ReturnType < typeof createTestApp > ,
678- workspaceId = "ws_tokens_route" ,
679- orgId = "org_tokens_route" ,
680- ) : Promise < void > {
681- await seedWorkspaceContext ( app , {
682- id : workspaceId ,
683- workspaceId,
684- orgId,
685- scopes : [ ] ,
686- roles : [ ] ,
676+ await t . test ( "requires workspaceId" , async ( ) => {
677+ const { app, authHeaders } = await createHarness ( {
678+ authClaims : {
679+ scopes : [
680+ "relayauth:api-key:manage:*" ,
681+ "relayfile:fs:read:*" ,
682+ "relayfile:fs:write:*" ,
683+ ] ,
684+ } ,
687685 } ) ;
688- }
686+ const orgApiKey = await issueApiKey ( app , authHeaders , [
687+ "relayauth:api-key:manage:*" ,
688+ "relayfile:fs:read:*" ,
689+ "relayfile:fs:write:*" ,
690+ ] ) ;
689691
690- await t . test ( "mints a short-lived relay_pa directly from an org api key" , async ( ) => {
692+ const response = await requestRoute ( app , "POST" , "/v1/tokens/workspace-path" , {
693+ body : {
694+ paths : [ "/github/repos/AgentWorkforce/cloud/issues/123/**" ] ,
695+ scopes : [ "relayfile:fs:write:/github/repos/AgentWorkforce/cloud/issues/123/**" ] ,
696+ } ,
697+ headers : {
698+ "x-api-key" : orgApiKey . key ,
699+ } ,
700+ } ) ;
701+
702+ await assertJsonResponse < ErrorBody > ( response , 400 , ( body ) => {
703+ assert . equal ( body . code , "workspaceId_required" ) ;
704+ } ) ;
705+ } ) ;
706+
707+ await t . test ( "mints a short-lived relay_pa directly from an org api key without a seeded workspace row" , async ( ) => {
691708 const { app, authHeaders } = await createHarness ( {
692709 authClaims : {
693710 scopes : [
@@ -697,7 +714,6 @@ test("POST /v1/tokens/workspace-path", async (t) => {
697714 ] ,
698715 } ,
699716 } ) ;
700- await seedWorkspace ( app ) ;
701717 const orgApiKey = await issueApiKey ( app , authHeaders , [
702718 "relayauth:api-key:manage:*" ,
703719 "relayfile:fs:read:*" ,
@@ -706,7 +722,7 @@ test("POST /v1/tokens/workspace-path", async (t) => {
706722
707723 const response = await requestRoute ( app , "POST" , "/v1/tokens/workspace-path" , {
708724 body : {
709- workspaceId : "ws_tokens_route" ,
725+ workspaceId : " ws_tokens_route " ,
710726 agentName : "cloud-team-member" ,
711727 paths : [ "/github/repos/AgentWorkforce/cloud/issues/123/**" ] ,
712728 scopes : [ "relayfile:fs:write:/github/repos/AgentWorkforce/cloud/issues/123/**" ] ,
@@ -732,6 +748,7 @@ test("POST /v1/tokens/workspace-path", async (t) => {
732748 const accessClaims = decodeJwtJsonSegment < RelayAuthTokenClaims > ( body . accessToken , 1 ) ;
733749 assert . equal ( accessClaims . sub , "agent_cloud-team-member" ) ;
734750 assert . equal ( accessClaims . wks , "ws_tokens_route" ) ;
751+ assert . equal ( accessClaims . org , "org_tokens_route" ) ;
735752 assert . equal ( accessClaims . meta ?. tokenClass , "path" ) ;
736753 assert . equal ( accessClaims . meta ?. workspaceTokenId , undefined ) ;
737754 assert . equal ( accessClaims . parentTokenId , undefined ) ;
@@ -743,52 +760,71 @@ test("POST /v1/tokens/workspace-path", async (t) => {
743760 assert . ok ( accessClaims . exp - accessClaims . iat <= 120 , "direct path access TTL should honor short ttlSeconds" ) ;
744761 } ) ;
745762
746- await t . test ( "caps direct path token TTL at the agent-token maximum " , async ( ) => {
763+ await t . test ( "stamps the authenticated org even when the workspaceId is associated with another org " , async ( ) => {
747764 const { app, authHeaders } = await createHarness ( {
748765 authClaims : {
766+ org : "org_a" ,
749767 scopes : [
750768 "relayauth:api-key:manage:*" ,
751769 "relayfile:fs:read:*" ,
752770 "relayfile:fs:write:*" ,
753771 ] ,
754772 } ,
755773 } ) ;
756- await seedWorkspace ( app ) ;
774+ await seedWorkspaceContext ( app , {
775+ id : "ws_owned_by_org_b" ,
776+ workspaceId : "ws_owned_by_org_b" ,
777+ orgId : "org_b" ,
778+ scopes : [ ] ,
779+ roles : [ ] ,
780+ } ) ;
781+ const orgApiKey = await issueApiKey ( app , authHeaders , [
782+ "relayauth:api-key:manage:*" ,
783+ "relayfile:fs:read:*" ,
784+ "relayfile:fs:write:*" ,
785+ ] ) ;
757786
758787 const response = await requestRoute ( app , "POST" , "/v1/tokens/workspace-path" , {
759788 body : {
760- workspaceId : "ws_tokens_route " ,
789+ workspaceId : "ws_owned_by_org_b " ,
761790 paths : [ "/github/repos/AgentWorkforce/cloud/issues/123/*" ] ,
762- ttlSeconds : 7200 ,
791+ scopes : [ "relayfile:fs:write:/github/repos/AgentWorkforce/cloud/issues/123/*" ] ,
792+ } ,
793+ headers : {
794+ "x-api-key" : orgApiKey . key ,
763795 } ,
764- headers : authHeaders ,
765796 } ) ;
766797
767798 const body = await assertJsonResponse < WorkspacePathTokenPair > ( response , 201 ) ;
768799 const accessClaims = decodeJwtJsonSegment < RelayAuthTokenClaims > ( body . accessToken , 1 ) ;
769- assert . ok ( accessClaims . exp - accessClaims . iat <= 3600 , "direct path access TTL should cap at 1h" ) ;
800+ assert . equal ( accessClaims . org , "org_a" ) ;
801+ assert . equal ( accessClaims . wks , "ws_owned_by_org_b" ) ;
802+ assert . equal ( body . workspaceId , "ws_owned_by_org_b" ) ;
770803 } ) ;
771804
772- await t . test ( "rejects a workspace outside the caller org " , async ( ) => {
805+ await t . test ( "caps direct path token TTL at the agent-token maximum " , async ( ) => {
773806 const { app, authHeaders } = await createHarness ( {
774807 authClaims : {
775- scopes : [ "relayauth:api-key:manage:*" , "relayfile:fs:write:*" ] ,
808+ scopes : [
809+ "relayauth:api-key:manage:*" ,
810+ "relayfile:fs:read:*" ,
811+ "relayfile:fs:write:*" ,
812+ ] ,
776813 } ,
777814 } ) ;
778- await seedWorkspace ( app , "ws_other_org" , "org_other" ) ;
779815
780816 const response = await requestRoute ( app , "POST" , "/v1/tokens/workspace-path" , {
781817 body : {
782- workspaceId : "ws_other_org " ,
818+ workspaceId : "ws_tokens_route " ,
783819 paths : [ "/github/repos/AgentWorkforce/cloud/issues/123/*" ] ,
784- scopes : [ "relayfile:fs:write:/github/repos/AgentWorkforce/cloud/issues/123/*" ] ,
820+ ttlSeconds : 7200 ,
785821 } ,
786822 headers : authHeaders ,
787823 } ) ;
788824
789- await assertJsonResponse < ErrorBody > ( response , 404 , ( body ) => {
790- assert . equal ( body . code , "workspace_not_found" ) ;
791- } ) ;
825+ const body = await assertJsonResponse < WorkspacePathTokenPair > ( response , 201 ) ;
826+ const accessClaims = decodeJwtJsonSegment < RelayAuthTokenClaims > ( body . accessToken , 1 ) ;
827+ assert . ok ( accessClaims . exp - accessClaims . iat <= 3600 , "direct path access TTL should cap at 1h" ) ;
792828 } ) ;
793829
794830 await t . test ( "rejects requested scopes outside the org api-key grant" , async ( ) => {
@@ -797,7 +833,6 @@ test("POST /v1/tokens/workspace-path", async (t) => {
797833 scopes : [ "relayauth:api-key:manage:*" , "relayfile:fs:read:*" ] ,
798834 } ,
799835 } ) ;
800- await seedWorkspace ( app ) ;
801836
802837 const response = await requestRoute ( app , "POST" , "/v1/tokens/workspace-path" , {
803838 body : {
@@ -819,7 +854,6 @@ test("POST /v1/tokens/workspace-path", async (t) => {
819854 scopes : [ "relayauth:api-key:manage:*" , "relayfile:fs:write:*" ] ,
820855 } ,
821856 } ) ;
822- await seedWorkspace ( app ) ;
823857
824858 const degenerate = await requestRoute ( app , "POST" , "/v1/tokens/workspace-path" , {
825859 body : {
0 commit comments