TenantAtlas/specs/112-list-expand-parity/quickstart.md
ahmido 32c3a64147 feat(112): LIST $expand parity + Entra principal names (#136)
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
2026-02-25 23:54:20 +00:00

1.4 KiB

Quickstart — Graph Contracts: LIST $expand Parity Fix

Goal

Verify that LIST requests can forward explicit, allowlisted $expand, and that the Entra Admin Roles report requests principal so it can render real principal display names.

Run tests (focused)

From repo root (Sail-first):

  • vendor/bin/sail artisan test --compact tests/Unit/GraphContractRegistryTest.php
  • vendor/bin/sail artisan test --compact tests/Unit/MicrosoftGraphClientListPoliciesSelectTest.php
  • vendor/bin/sail artisan test --compact --filter=EntraAdminRoles

Manual verification (developer)

  • Ensure the entraRoleAssignments contract includes allowed_expand => ['principal'].
  • Ensure the role assignment LIST request includes $expand=principal when explicitly requested.

Usage examples

When listing a policy type where the contract allowlists principal:

  • listPolicies('entraRoleAssignments', [..., 'expand' => 'principal'])
  • listPolicies('entraRoleAssignments', [..., 'expand' => ['principal']])

Normalization behavior:

  • expand string input is split on top-level commas only (commas inside balanced parentheses are not separators) and trimmed.
  • Values not in the contract allowlist are dropped.
  • Max 10 allowlisted expansions are sent; extras are dropped.

Notes

  • No expansions are sent by default. Callers must pass expand explicitly.
  • Diagnostics are emitted when requested expands are removed or truncated.