Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 271 additions & 0 deletions RELATIONSHIP_MEMBERS_PROPOSAL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
# Enhanced Relationship Member Types Proposal

## Executive Summary

This proposal outlines the implementation of enhanced relationship member types for Microsoft Graph Bicep Types, transitioning from simple string arrays to rich object structures for improved object referencing, filtering, and type-based operations while maintaining backward compatibility.

## Status: ✅ IMPLEMENTED

**Implementation Date:** October 24, 2025
**Implementation Status:** Complete and Production Ready
**Test Coverage:** 11/11 tests passing
**Backward Compatibility:** Maintained for v1.0 API

## Problem Statement

The current relationship member implementation uses simple string arrays containing only object IDs. This approach has several limitations:

1. **Limited Type Information**: No way to determine object type (user, group, servicePrincipal)
2. **Filtering Constraints**: Cannot filter relationship members by type
3. **Object Dereferencing**: No human-readable identifiers for object lookup
4. **Template Referencing**: Limited ability to reference objects in templates

### Real-World Scenarios

**Scenario 1: App Ownership Assignment**
- Want to set app owners based on security group members
- Security groups may contain other groups, but groups cannot own apps
- Need to filter out group objects before assignment

**Scenario 2: User Lookup Operations**
- Want to look up user names in a security group
- Group may contain both users and service principals
- Need to differentiate object types for proper dereferencing

**Scenario 3: Template-based Object Referencing**
- Need to reference existing objects in templates
- Require unique identifiers beyond just object IDs
- Want human-readable names for better template maintainability

## Solution Overview

Implement enhanced relationship member types that provide rich object metadata while maintaining backward compatibility through version-based conditional logic.

### Enhanced Relationship Member Schema

```typescript
{
id: string, // Required: The object ID
type: string, // Read-only: Object type (user, group, servicePrincipal, etc.)
displayName: string, // Read-only: Human-readable name
userPrincipalName: string, // Read-only: For users - their UPN
appId: string, // Read-only: For service principals - their app ID
uniqueName: string // Read-only: Unique name for template referencing
}
```

### Version Strategy

- **Enhanced Versions**: `beta/1.1.0-preview` and `v1.0/1.1.0-preview`
- **Legacy Versions**: `v1.0/1.0.0` (maintains string arrays)
- **Detection Logic**: `isEnhancedRelationshipVersion()` function

## Implementation Details

### Core Files Modified

#### 1. swaggerWriter.ts
**Location:** `src/swagger-generation/src/swaggerWriter.ts`

**Changes:**
- Added `isEnhancedRelationshipVersion()` detection function
- Implemented conditional `microsoft.graph.relationshipMember` definition
- Enhanced `microsoft.graph.relationship` with version-specific structures

**Key Implementation:**
```typescript
// Enhanced RelationshipMember type for enhanced versions
if (isEnhanced) {
baseDefinitions["microsoft.graph.relationshipMember"] = {
type: "object",
properties: {
id: { type: "string", description: "The unique identifier of the relationship member." },
type: { type: "string", description: "The type of the relationship member...", readOnly: true },
displayName: { type: "string", description: "The display name...", readOnly: true },
userPrincipalName: { type: "string", description: "The user principal name...", readOnly: true },
appId: { type: "string", description: "The application ID...", readOnly: true },
uniqueName: { type: "string", description: "A unique name for referencing...", readOnly: true }
},
required: ["id"]
};
}
```

#### 2. generate.ts
**Location:** `src/generator/src/generate.ts`

**Changes:**
- Updated `extensionConfigForGeneration` with v1.1.0 configuration
- Enhanced `shouldIncludeFilePath` with v1.1.0 patterns
- Updated `buildTypeIndex` for v1.1.0 version handling

#### 3. index.ts (swagger-generation)
**Location:** `src/swagger-generation/src/index.ts`

**Changes:**
- Fixed `writeSwaggerReadMeFile` to include v1.1.0 AutoRest configuration
- Added v1.1.0 section to readme template
- Ensured proper AutoRest setup for all API versions

### Test Coverage

#### Test Suite: swaggerWriter.test.ts
**Location:** `src/swagger-generation/tests/swaggerWriter.test.ts`

**Coverage:**
1. **Enhanced Beta Test**: Validates `beta/1.1.0-preview` with full relationship member objects
2. **Enhanced v1.1.0 Test**: Validates `v1.0/1.1.0-preview` with full relationship member objects
3. **Legacy v1.0 Test**: Validates `v1.0/1.0.0` maintains simple string arrays

**Test Results:** ✅ 11/11 tests passing

## API Version Comparison

### Enhanced Versions (beta/1.1.0-preview, v1.0/1.1.0-preview)

```json
{
"microsoft.graph.relationshipMember": {
"type": "object",
"properties": {
"id": { "type": "string", "description": "The unique identifier..." },
"type": { "type": "string", "readOnly": true, "description": "The type of the relationship member..." },
"displayName": { "type": "string", "readOnly": true, "description": "The display name..." },
"userPrincipalName": { "type": "string", "readOnly": true, "description": "The user principal name..." },
Comment thread
eketo-msft marked this conversation as resolved.
"appId": { "type": "string", "readOnly": true, "description": "The application ID..." },
"uniqueName": { "type": "string", "readOnly": true, "description": "A unique name..." }
},
"required": ["id"]
},
"microsoft.graph.relationship": {
"properties": {
"relationships": {
"type": "array",
"items": { "$ref": "#/definitions/microsoft.graph.relationshipMember" },
"description": "The list of relationship members with their IDs and types."
}
}
}
}
```

### Legacy Version (v1.0/1.0.0)

```json
{
"microsoft.graph.relationship": {
"properties": {
"relationships": {
"type": "array",
"items": { "type": "string" },
"description": "The list of object ids to be included in the relationship."
}
}
}
}
```

## Usage Examples

### Scenario 1: Type-based Filtering
```bicep
// Filter out groups when setting app owners
resource myApp 'Microsoft.Graph/applications@beta' = {
owners: {
relationships: filter(securityGroup.members, member => member.type != 'group')
}
}
```

### Scenario 2: User Identification
```bicep
// Get user information from mixed security group
resource myGroup 'Microsoft.Graph/groups@beta' existing = {
name: 'my-security-group'
}

// Extract users for name lookup
var users = filter(myGroup.members, member => member.type == 'user')
// Access: member.displayName, member.userPrincipalName
```

### Scenario 3: Service Principal Operations
```bicep
// Work with service principals in relationships
var servicePrincipals = filter(group.members, member => member.type == 'servicePrincipal')
// Access: member.appId for application operations
```

## Validation Results

### Production Validation
- ✅ **Beta Swagger**: `microsoftgraph-beta-1.1.0-preview.json` contains enhanced relationshipMember
- ✅ **v1.1 Swagger**: `microsoftgraph-v1.0-1.1.0-preview.json` contains enhanced relationshipMember
- ✅ **v1.0 Swagger**: `microsoftgraph-v1.0-1.0.0.json` maintains string arrays (no relationshipMember)

### Test Validation
```bash
npm test -- swaggerWriter.test.ts
# Result: 11 passed, 0 failed
```

### Generated Output Verification
```powershell
# Enhanced versions contain full object structure
Get-Content src\swagger-generation\output\microsoftgraph-beta-1.1.0-preview.json |
ConvertFrom-Json | Select-Object -ExpandProperty definitions |
Select-Object -ExpandProperty "microsoft.graph.relationshipMember"

# Legacy version uses simple strings
Get-Content src\swagger-generation\output\microsoftgraph-v1.0-1.0.0.json |
ConvertFrom-Json | Select-Object -ExpandProperty definitions |
Select-Object -ExpandProperty "microsoft.graph.relationship"
```

## Benefits Delivered

1. **Enhanced Type Information**: Full object metadata for intelligent operations
2. **Improved Filtering**: Type-based filtering capabilities for relationships
3. **Better Object Referencing**: Multiple identifiers (displayName, UPN, appId, uniqueName)
4. **Template Flexibility**: Rich object properties for template-based operations
5. **Backward Compatibility**: Zero impact on existing v1.0 implementations
6. **Production Ready**: Comprehensive test coverage and validation

## Migration Path

### For New Implementations
- Use enhanced versions (`beta/1.1.0-preview` or `v1.0/1.1.0-preview`)
- Leverage rich relationship member objects for advanced scenarios

### For Existing Implementations
- v1.0 implementations continue working unchanged
- Opt-in to enhanced versions when ready for advanced features
- No breaking changes in legacy API versions

## Technical Architecture

### Version Detection Logic
```typescript
function isEnhancedRelationshipVersion(config: Config): boolean {
return (config.APIVersion === 'beta' && config.ExtensionVersion === '1.1.0-preview') ||
(config.APIVersion === 'v1.0' && config.ExtensionVersion === '1.1.0-preview');
}
```

### Conditional Schema Generation
- Enhanced versions: Generate `microsoft.graph.relationshipMember` + enhanced `microsoft.graph.relationship`
- Legacy versions: Generate only `microsoft.graph.relationship` with string arrays
- All versions: Include `microsoft.graph.relationshipSemantics` for relationship handling

## Future Considerations

1. **Additional Object Properties**: Can extend relationshipMember with more Graph object properties
2. **Custom Unique Names**: Potential for user-defined unique name generation
3. **Type-specific Properties**: Could add type-specific property sets (e.g., group-specific properties)
4. **Cross-reference Capabilities**: Enhanced object dereferencing across relationship types

## Conclusion

The Enhanced Relationship Member Types implementation successfully addresses all identified limitations while maintaining full backward compatibility. The solution provides rich object metadata for advanced filtering, referencing, and type-based operations, enabling sophisticated Microsoft Graph Bicep template scenarios.

**Status: Production Ready** ✅
28 changes: 14 additions & 14 deletions generated/index.json
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
{
"resources": {
"Microsoft.Graph/groups@beta": {
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/18"
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/18"
},
"Microsoft.Graph/applications@beta": {
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/74"
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/74"
},
"Microsoft.Graph/servicePrincipals@beta": {
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/92"
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/92"
},
"Microsoft.Graph/applications/federatedIdentityCredentials@beta": {
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/97"
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/97"
},
"Microsoft.Graph/oauth2PermissionGrants@beta": {
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/101"
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/101"
},
"Microsoft.Graph/appRoleAssignedTo@beta": {
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/105"
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/105"
},
"Microsoft.Graph/users@beta": {
"$ref": "microsoftgraph/microsoft.graph/beta/0.1.9-preview/types.json#/110"
"$ref": "microsoftgraph/microsoft.graph/beta/1.0.1-preview/types.json#/110"
},
"Microsoft.Graph/groups@v1.0": {
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/13"
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/13"
},
"Microsoft.Graph/applications@v1.0": {
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/70"
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/70"
},
"Microsoft.Graph/servicePrincipals@v1.0": {
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/88"
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/88"
},
"Microsoft.Graph/applications/federatedIdentityCredentials@v1.0": {
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/93"
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/93"
},
"Microsoft.Graph/oauth2PermissionGrants@v1.0": {
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/97"
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/97"
},
"Microsoft.Graph/appRoleAssignedTo@v1.0": {
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/101"
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/101"
},
"Microsoft.Graph/users@v1.0": {
"$ref": "microsoftgraph/microsoft.graph/v1.0/0.1.9-preview/types.json#/106"
"$ref": "microsoftgraph/microsoft.graph/v1.0/1.0.1-preview/types.json#/106"
}
},
"resourceFunctions": {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"resources": {
"Microsoft.Graph/groups@beta": {
"$ref": "types.json#/23"
},
"Microsoft.Graph/applications@beta": {
"$ref": "types.json#/79"
},
"Microsoft.Graph/servicePrincipals@beta": {
"$ref": "types.json#/97"
},
"Microsoft.Graph/applications/federatedIdentityCredentials@beta": {
"$ref": "types.json#/103"
},
"Microsoft.Graph/oauth2PermissionGrants@beta": {
"$ref": "types.json#/107"
},
"Microsoft.Graph/appRoleAssignedTo@beta": {
"$ref": "types.json#/111"
},
"Microsoft.Graph/users@beta": {
"$ref": "types.json#/116"
}
},
"resourceFunctions": {},
"settings": {
"name": "MicrosoftGraphBeta",
"version": "1.1.0-preview",
"isSingleton": false,
"configurationType": {
"$ref": "types.json#/117"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Bicep Types
## microsoft.graph
### microsoft.graph/applications
* **Link**: [beta](types.md#resource-microsoftgraphapplicationsbeta)

### microsoft.graph/applications/federatedidentitycredentials
* **Link**: [beta](types.md#resource-microsoftgraphapplicationsfederatedidentitycredentialsbeta)

### microsoft.graph/approleassignedto
* **Link**: [beta](types.md#resource-microsoftgraphapproleassignedtobeta)

### microsoft.graph/groups
* **Link**: [beta](types.md#resource-microsoftgraphgroupsbeta)

### microsoft.graph/oauth2permissiongrants
* **Link**: [beta](types.md#resource-microsoftgraphoauth2permissiongrantsbeta)

### microsoft.graph/serviceprincipals
* **Link**: [beta](types.md#resource-microsoftgraphserviceprincipalsbeta)

### microsoft.graph/users
* **Link**: [beta](types.md#resource-microsoftgraphusersbeta)

Loading
Loading