TenantAtlas/specs/112-list-expand-parity/tasks.md
2026-02-26 00:48:25 +01:00

150 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
description: "Task list for Graph Contracts — LIST $expand Parity Fix"
---
# Tasks: Graph Contracts — LIST `$expand` Parity Fix
**Input**: Design documents from `specs/112-list-expand-parity/`
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
**Tests**: REQUIRED (Pest) — this feature changes runtime Graph request shapes.
## Phase 1: Setup (Shared)
**Purpose**: Confirm inputs and establish a baseline before changing runtime behavior.
- [X] T001 [Shared] Read implementation plan in specs/112-list-expand-parity/plan.md
- [X] T002 [P] [Shared] Verify $expand allowlist exists for Entra role assignments in config/graph_contracts.php
- [X] T003 [P] [Shared] Identify existing Graph tests to extend in tests/Unit/GraphContractRegistryTest.php and tests/Unit/MicrosoftGraphClientListPoliciesSelectTest.php
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Establish pre-change confidence and shared test baseline.
- [X] T004 [Shared] Run baseline focused tests listed in specs/112-list-expand-parity/quickstart.md
**Checkpoint**: Baseline established; safe to implement.
---
## Phase 3: User Story 1 — Admin roles report shows real principal names (Priority: P1) 🎯 MVP
**Goal**: Admin Roles report requests `principal` expansion and renders real principal display names when Graph provides them.
**Independent Test**: Simulate role assignment list retrieval and assert report output uses `principal.displayName` when present, else falls back to `Unknown`.
### Tests for User Story 1
- [X] T005 [P] [US1] Create report service test scaffolding in tests/Unit/EntraAdminRolesReportServiceTest.php (RefreshDatabase + mock GraphClientInterface)
- [X] T006 [US1] Implement tests asserting `entraRoleAssignments` call includes `expand => 'principal'` and payload uses principal display name in tests/Unit/EntraAdminRolesReportServiceTest.php
### Implementation for User Story 1
- [X] T007 [US1] Pass `expand => 'principal'` when fetching assignments in app/Services/EntraAdminRoles/EntraAdminRolesReportService.php
- [X] T008 [US1] Forward caller-provided `expand` into LIST query input in app/Services/Graph/MicrosoftGraphClient.php
- [X] T009 [US1] Normalize + cap `$expand` in app/Services/Graph/GraphContractRegistry.php (split string on top-level commas only; preserve commas inside balanced parentheses; trim, drop empty, dedupe, maxTokenLen=200, maxItems=10 after allowlist)
### Regression tests for User Story 1
- [X] T010 [US1] Add LIST `$expand` request-shape test coverage in tests/Unit/MicrosoftGraphClientListPoliciesSelectTest.php
- [X] T011 [US1] Add `$expand` normalization/cap test coverage in tests/Unit/GraphContractRegistryTest.php
- [X] T012 [US1] Run story tests in tests/Unit/EntraAdminRolesReportServiceTest.php plus Graph tests in tests/Unit/MicrosoftGraphClientListPoliciesSelectTest.php
**Checkpoint**: Entra Admin Roles report can render real principal names when upstream provides them.
---
## Phase 4: User Story 2 — Engineers can request explicit LIST expansions safely (Priority: P2)
**Goal**: LIST supports explicit expansions safely and discoverably (document option shape, allowlist enforcement).
**Independent Test**: Inspect outgoing LIST request and confirm `$expand` is included only when explicitly provided and allowlisted.
### Tests for User Story 2
- [X] T013 [P] [US2] Add test asserting LIST omits `$expand` when `expand` is not provided in tests/Unit/MicrosoftGraphClientListPoliciesSelectTest.php
- [X] T014 [P] [US2] Add tests asserting (a) disallowed expand tokens are removed (exact-match allowlist, no partial matches) and (b) allowlisted subquery/select-style expand tokens that contain commas inside parentheses are preserved as a single token (no naive comma-splitting) in tests/Unit/GraphContractRegistryTest.php
### Implementation for User Story 2
- [X] T015 [US2] Document supported `listPolicies()` options (select/expand/filter/top/platform + input shapes) in app/Services/Graph/GraphClientInterface.php
- [X] T016 [US2] Ensure `GraphContractCheck` query shape remains compatible (select + expand) in app/Console/Commands/GraphContractCheck.php
**Checkpoint**: Engineers can safely request allowlisted expansions on LIST without silent capability mismatch.
---
## Phase 5: User Story 3 — Misuse is detectable in non-production (Priority: P3)
**Goal**: When `$expand` is sanitized (removed or truncated), maintainers get a diagnostic signal in non-production with low noise in production.
**Independent Test**: Trigger mixed allowed/disallowed expand and assert a non-production warning is emitted with policy type + removed values.
### Tests for User Story 3
- [X] T017 [US3] Add Log::spy-based test for non-production diagnostics when `$expand` is sanitized in tests/Unit/GraphContractRegistryTest.php
- [X] T018 [US3] Add production-noise guard test (debug-level or suppressed warn) for `$expand` sanitization in tests/Unit/GraphContractRegistryTest.php
### Implementation for User Story 3
- [X] T019 [US3] Emit structured diagnostic logs when `$expand` is removed/truncated in app/Services/Graph/GraphContractRegistry.php
**Checkpoint**: Sanitization is visible during dev/staging without spamming production logs.
---
## Phase 6: Polish & Cross-Cutting Concerns
**Purpose**: Keep the change safe, consistent, and shippable.
- [X] T020 [Shared] Run formatting on touched files (Pint) after changes in app/Services/Graph/GraphContractRegistry.php
- [X] T021 [Shared] Run focused suite listed in specs/112-list-expand-parity/quickstart.md
---
## Dependencies & Execution Order
### Phase Dependencies
- Setup (Phase 1) → Foundational (Phase 2) → US1 (Phase 3) → US2 (Phase 4) → US3 (Phase 5) → Polish (Phase 6)
### User Story Dependencies
- US1 depends on LIST `$expand` parity (implemented as part of US1 via app/Services/Graph/MicrosoftGraphClient.php + app/Services/Graph/GraphContractRegistry.php).
- US2 extends US1 with discoverability + additional safety regression coverage.
- US3 depends on the sanitization logic (adds diagnostics + tests).
### Parallel Opportunities
- Phase 1: T002 and T003 can run in parallel.
- US1: T005 can be done in parallel with T008/T009 (different files).
- US2: T013 and T014 can run in parallel.
---
## Parallel Example: User Story 1
- In parallel:
- T005 (test scaffolding) in tests/Unit/EntraAdminRolesReportServiceTest.php
- T008 (LIST forwards expand) in app/Services/Graph/MicrosoftGraphClient.php
- T009 (sanitize/normalize/cap expand) in app/Services/Graph/GraphContractRegistry.php
---
## Implementation Strategy
### MVP First (User Story 1 Only)
1. Complete Phase 12
2. Complete US1 (Phase 3)
3. Stop and ship if acceptance + regression tests pass
### Then harden (US2 + US3)
- Add discoverability + extra regression guards (US2)
- Add diagnostics behavior + tests (US3)