@@ -427,7 +427,8 @@ func TestCreateCedarEntities(t *testing.T) {
427427 factory := NewEntityFactory ("" )
428428
429429 // Create Cedar entities (no groups for these test cases)
430- entities , err := factory .CreateEntitiesForRequest (tc .principal , tc .action , tc .resource , tc .claimsMap , tc .attributes , nil , "" )
430+ entities , err := factory .CreateEntitiesForRequest (
431+ tc .principal , tc .action , tc .resource , tc .claimsMap , tc .attributes , nil , "" )
431432
432433 // Check error expectations
433434 if tc .expectErr {
@@ -594,3 +595,71 @@ func TestCreateEntitiesForRequest_MCPParent(t *testing.T) {
594595 })
595596 }
596597}
598+
599+ func TestCreateEntitiesForRequest_BackendParent (t * testing.T ) {
600+ t .Parallel ()
601+
602+ factory := NewEntityFactory ("" )
603+ tests := []struct {
604+ name string
605+ serverName string
606+ backendID string
607+ wantParentCount int
608+ }{
609+ {
610+ name : "MCP and Backend parents" ,
611+ serverName : "main-vmcp" ,
612+ backendID : "github-mcp" ,
613+ wantParentCount : 2 ,
614+ },
615+ {
616+ name : "empty BackendID keeps only MCP parent" ,
617+ serverName : "main-vmcp" ,
618+ wantParentCount : 1 ,
619+ },
620+ {
621+ name : "Backend parent does not require MCP parent" ,
622+ backendID : "github-mcp" ,
623+ wantParentCount : 1 ,
624+ },
625+ }
626+
627+ for _ , tt := range tests {
628+ t .Run (tt .name , func (t * testing.T ) {
629+ t .Parallel ()
630+
631+ var extraResourceParents []cedar.EntityUID
632+ if tt .backendID != "" {
633+ extraResourceParents = append (extraResourceParents ,
634+ cedar .NewEntityUID (EntityTypeBackend , cedar .String (tt .backendID )))
635+ }
636+
637+ entities , err := factory .CreateEntitiesForRequest (
638+ "Client::user1" ,
639+ "Action::call_tool" ,
640+ "Tool::renamed-search" ,
641+ map [string ]interface {}{"sub" : "user1" },
642+ map [string ]interface {}{"name" : "renamed-search" },
643+ nil ,
644+ tt .serverName ,
645+ extraResourceParents ... ,
646+ )
647+ require .NoError (t , err )
648+ assert .Len (t , entities , 3 ,
649+ "request entities must contain only the principal, action, and resource" )
650+
651+ toolUID := cedar .NewEntityUID ("Tool" , cedar .String ("renamed-search" ))
652+ toolEntity , ok := entities [toolUID ]
653+ require .True (t , ok )
654+ assert .Equal (t , tt .wantParentCount , toolEntity .Parents .Len ())
655+
656+ if tt .backendID != "" {
657+ backendUID := cedar .NewEntityUID (EntityTypeBackend , cedar .String (tt .backendID ))
658+ assert .True (t , toolEntity .Parents .Contains (backendUID ),
659+ "Tool must carry the trusted Backend parent UID" )
660+ assert .NotContains (t , entities , backendUID ,
661+ "request-time Backend parents must not be materialized as entities" )
662+ }
663+ })
664+ }
665+ }
0 commit comments