Implements LIST `$expand` parity with GET by forwarding caller-provided, contract-allowlisted expands. Key changes: - Entra Admin Roles scan now requests `expand=principal` for role assignments so `principal.displayName` can render. - `$expand` normalization/sanitization: top-level comma split (commas inside balanced parentheses preserved), trim, dedupe, allowlist exact match, caps (max 10 tokens, max 200 chars/token). - Diagnostics when expands are removed/truncated (non-prod warning, production low-noise). Tests: - Adds/extends unit coverage for Graph contract sanitization, list request shaping, and the EntraAdminRolesReportService. Spec artifacts included under `specs/112-list-expand-parity/`. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #136
44 lines
1.9 KiB
Markdown
44 lines
1.9 KiB
Markdown
# Data Model — Graph Contracts: LIST `$expand` Parity Fix
|
|
|
|
## Summary
|
|
No database schema changes. This feature changes how list queries are constructed and sanitized for Microsoft Graph.
|
|
|
|
## Key entities & shapes
|
|
|
|
### Graph contract (`config/graph_contracts.php`)
|
|
Per `policyType` contract keys relevant to this feature:
|
|
- `resource` (string): Graph resource path (e.g. `directory/roleAssignments`)
|
|
- `allowed_select` (string[]): allowlisted `$select` fields
|
|
- `allowed_expand` (string[]): allowlisted `$expand` expansions (exact-match)
|
|
|
|
### Query options (caller input)
|
|
Options are passed as an `array $options` into `GraphClientInterface::listPolicies($policyType, $options)`.
|
|
Relevant keys:
|
|
- `select` (string|string[]): optional `$select` input
|
|
- `expand` (string|string[]): optional `$expand` input
|
|
- `filter` (string): optional `$filter`
|
|
- `top` (int): optional `$top`
|
|
- `platform` (string): optional platform filter for contract-specific endpoints
|
|
- plus tenant/auth context from `MicrosoftGraphOptionsResolver`
|
|
|
|
### Sanitized query (outbound)
|
|
`GraphContractRegistry::sanitizeQuery($policyType, $query)` returns:
|
|
- `query` (array): sanitized query map, where `$select` and `$expand` are sent as comma-separated strings
|
|
- `warnings` (string[]): human-readable warnings for capability safety
|
|
|
|
### Entra role assignment record
|
|
`entraRoleAssignments` list response item is expected to include:
|
|
- `roleDefinitionId` (string)
|
|
- `principalId` (string)
|
|
- `principal` (object, when expanded)
|
|
- `displayName` (string)
|
|
- `@odata.type` (string)
|
|
|
|
## State transitions
|
|
None. This is a read-only integration-layer capability change.
|
|
|
|
## Validation rules
|
|
- `$expand` values must match `allowed_expand` exactly.
|
|
- `$expand` normalization: trim, split on top-level commas only (string input; do not split inside balanced parentheses), drop empty, dedupe.
|
|
- Safety caps: max 10 allowed expands; max 200 chars per token.
|