14 KiB
| description |
|---|
| Task list for Stored Reports Surface v1 |
Tasks: Stored Reports Surface v1
Input: Design documents from specs/277-stored-reports-surface/
Prerequisites: specs/277-stored-reports-surface/spec.md, specs/277-stored-reports-surface/plan.md, specs/277-stored-reports-surface/checklists/requirements.md, specs/277-stored-reports-surface/research.md, specs/277-stored-reports-surface/data-model.md, specs/277-stored-reports-surface/quickstart.md, specs/277-stored-reports-surface/contracts/tenant-stored-reports-surface.logical.openapi.yaml
Tests: REQUIRED (Pest). Keep proof bounded to focused Feature coverage in apps/platform/tests/Feature/StoredReports/, a narrow update to apps/platform/tests/Feature/EntraAdminRoles/AdminRolesSummaryWidgetTest.php, and the required UI smoke coverage in apps/platform/tests/Browser/Spec277StoredReportsSurfaceSmokeTest.php.
Operations: No new OperationRun family. Existing scan and generation actions remain on their current surfaces.
RBAC: Wrong-tenant or non-member access remains 404; in-scope actors missing the relevant report-family capability remain 403; collection visibility requires at least one supported report-family capability.
Shared Pattern Reuse: Reuse StoredReport, ArtifactTruthPresenter, centralized badge semantics, and the current admin-roles widget launch seam. Do not create a report registry, analytics console, or second lifecycle system.
Filament / Panel Guardrails: Filament remains v5 on Livewire v4. Provider registration remains unchanged in apps/platform/bootstrap/providers.php. The new stored-report resource is not globally searchable and adds no new asset strategy.
Organization: Tasks are grouped by user story so browse, detail, and canonical drilldown behavior stay independently implementable and testable. This package productizes existing stored-report truth and stops before generic reporting scope.
Review Outcome: acceptable-special-case
Workflow Outcome: keep
Test-governance Outcome: keep
Test Governance Checklist
- Lane assignment stays
fast-feedbackandconfidenceand remains the narrowest sufficient proof. - New or changed tests stay in
apps/platform/tests/Feature/StoredReports/,apps/platform/tests/Feature/EntraAdminRoles/, and the required narrow browser smoke file only. - Shared helpers stay cheap by default; stored-report setup should reuse the current factory and tenant fixtures.
- Planned validation commands cover register behavior, entitlement behavior, detail presentation, widget drilldown, and the required narrow browser smoke without widening into heavy-governance lanes.
- The declared surface test profile remains
standard-native-filamentandshared-detail-familyonly. - Any drift toward a report engine, cross-tenant hub, or generic registry resolves as
reject-or-split, not hidden scope.
Phase 1: Setup (Shared Context)
Purpose: Confirm the current stored-report, artifact-truth, and launch seams before runtime changes begin.
- T001 Review
specs/277-stored-reports-surface/spec.md,specs/277-stored-reports-surface/plan.md,specs/277-stored-reports-surface/checklists/requirements.md,specs/277-stored-reports-surface/research.md,specs/277-stored-reports-surface/data-model.md, andspecs/277-stored-reports-surface/quickstart.mdtogether so the slice stays on existing stored-report truth. - T002 [P] Confirm the current stored-report truth and lifecycle anchors in
apps/platform/app/Models/StoredReport.php,apps/platform/database/factories/StoredReportFactory.php, andapps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php. - T003 [P] Confirm the current repo-real launch seam in
apps/platform/app/Filament/Widgets/Tenant/AdminRolesSummaryWidget.phpandapps/platform/resources/views/filament/widgets/tenant/admin-roles-summary.blade.php. - T004 [P] Confirm the current tenant-panel read-only resource patterns in
apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php,apps/platform/app/Filament/Resources/ReviewPackResource.php, and their related feature tests.
Phase 2: Foundational (Blocking Prerequisites)
Purpose: Lock authorization, test coverage, and setup before the new surface is built.
Critical: No user-story work should begin until this phase is complete.
- T005 [P] Add failing feature coverage in
apps/platform/tests/Feature/StoredReports/StoredReportEntitlementEnforcementTest.phpfor collection visibility, direct-detail access, family-filtered rows, and404versus403semantics. - T006 [P] Add failing feature coverage in
apps/platform/tests/Feature/StoredReports/StoredReportResourceTest.phpfor tenant-scoped list behavior, current versus historical visibility, search, filter options, and honest empty-state behavior. - T007 [P] Add failing feature coverage in
apps/platform/tests/Feature/StoredReports/StoredReportDetailPresentationTest.phpfor allowed current permission-posture detail, allowed historical Entra admin-roles detail, collapsed raw payload disclosure, and integrity-anchor rendering when present. - T008 [P] Prepare the minimal widget test fixtures or helpers in
apps/platform/tests/Feature/EntraAdminRoles/AdminRolesSummaryWidgetTest.phpfor a report-present state and a capability-blocked state so US3 can add one bounded assertion set. - T009 Add
Capabilities::PERMISSION_POSTURE_VIEWinapps/platform/app/Support/Auth/Capabilities.phpand map it inapps/platform/app/Services/Auth/RoleCapabilityMap.phpwith bounded read-only role coverage. - T010 Keep stored-report test setup cheap by extending
apps/platform/database/factories/StoredReportFactory.phponly as needed for current and historical supported-family fixtures.
Checkpoint: Authorization and proving seams are ready for the stored-report resource implementation.
Phase 3: User Story 1 - Browse current stored reports for one tenant (Priority: P1)
Goal: Entitled actors can browse current and historical stored reports for the active tenant in one first-class register.
Independent Test: Open /admin/t/{tenant}/stored-reports, confirm current and historical behavior, and verify family-aware visibility and filters.
Tests for User Story 1
- T011 [P] [US1] Extend
apps/platform/tests/Feature/StoredReports/StoredReportResourceTest.phpto cover clickable-row inspection, history toggle behavior, and family-aware filter visibility on the tenant panel.
Implementation for User Story 1
- T012 [US1] Create
apps/platform/app/Filament/Resources/StoredReportResource.phpwith tenant ownership,isGloballySearchable = false, family-awarecanViewAny()behavior, and a read-only action-surface declaration. - T013 [US1] Create
apps/platform/app/Filament/Resources/StoredReportResource/Pages/ListStoredReports.phpwith a tenant-scoped query, report-family filters, history visibility, search, clickable rows, and no row or bulk mutation actions. - T014 [US1] Add bounded family-summary extraction on the stored-report resource or list page using current payload shapes and existing artifact-truth badges rather than a shared registry.
- T015 [US1] Wire the list empty state to an honest next step such as the tenant overview, without implying the stored-report surface can generate reports itself.
Checkpoint: The tenant panel has one calm stored-report register that stays tenant-scoped, read-only, and family-aware.
Phase 4: User Story 2 - Inspect a retained report without false calmness (Priority: P1)
Goal: Entitled actors can inspect one stored report and immediately understand what it says, whether it is current or historical, and when it was measured.
Independent Test: Open one current permission-posture report and one historical Entra admin-roles report and verify lifecycle truth, measured time, bounded summary, and progressive disclosure.
Tests for User Story 2
- T016 [P] [US2] Extend
apps/platform/tests/Feature/StoredReports/StoredReportDetailPresentationTest.phpto cover the one-primary-action rule, current-report jump on historical rows, and the absence of speculative unsupported-family rendering in v1.
Implementation for User Story 2
- T017 [US2] Create
apps/platform/app/Filament/Resources/StoredReportResource/Pages/ViewStoredReport.phpas a read-only view page using infolist sections for artifact truth, family summary, lineage, and collapsed raw payload. - T018 [US2] Reuse
ArtifactTruthPresenter::forStoredReport()in the detail surface and keep any “current report” lookup local toStoredReportResourceandViewStoredReportinstead of broadening the artifact envelope. - T019 [US2] Keep the detail page to one dominant next action,
Open current report, only when the viewed row is historical, and keep all mutation actions out of scope.
Checkpoint: Stored-report detail behaves like a true inspection surface rather than a pseudo-editor or diagnostics dump.
Phase 5: User Story 3 - Follow stored-report truth from the tenant admin-roles widget (Priority: P2)
Goal: The current admin-roles widget launch seam points to the canonical stored-report detail route instead of leaving operators in a fragmented local view.
Independent Test: Launch the current Entra admin-roles report from AdminRolesSummaryWidget and confirm the canonical tenant stored-report detail route opens.
Tests for User Story 3
- T020 [P] [US3] Extend
apps/platform/tests/Feature/EntraAdminRoles/AdminRolesSummaryWidgetTest.phpto prove canonical stored-report drilldown and capability-gated absence without widening the proving suite.
Implementation for User Story 3
- T021 [US3] Update
apps/platform/app/Filament/Widgets/Tenant/AdminRolesSummaryWidget.phpandapps/platform/resources/views/filament/widgets/tenant/admin-roles-summary.blade.phpsoviewReportUrlresolves to the canonical tenant stored-report detail route when the actor can view Entra admin roles. - T022 [US3] Keep convergence bounded to
AdminRolesSummaryWidget; do not add new stored-report links toEvidenceSnapshotResource,ReviewPackResource, orTenantReviewResourcein v1. - T023 [US3] Ensure generated detail URLs preserve tenant-panel routing semantics and that direct detail access keeps family-aware authorization behavior.
Checkpoint: The admin-roles widget definitely launches the canonical detail route, and any additional convergence remains bounded to repo-real affordances.
Phase 6: Polish & Cross-Cutting Validation
Purpose: Validate the bounded slice and stop before reporting-platform scope creeps in.
- T024 [P] Run
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/StoredReports/StoredReportResourceTest.php tests/Feature/StoredReports/StoredReportEntitlementEnforcementTest.php. - T025 [P] Run
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/StoredReports/StoredReportDetailPresentationTest.php tests/Feature/EntraAdminRoles/AdminRolesSummaryWidgetTest.php. - T026 [P] Run
cd apps/platform && ./vendor/bin/sail pinton the touched application and test files;./vendor/bin/sail pint --dirtyreported no tracked dirty files because several feature files were new. - T027 [P] Review touched code to confirm Filament stays on Livewire v4, provider registration remains unchanged in
apps/platform/bootstrap/providers.php, the new resource stays out of global search, no new asset strategy appears, and no report engine or analytics scope slipped in. - T028 [P] Record the final guardrail and test-governance outcome in the active feature close-out without widening into cross-tenant browse, raw export, or generic report-framework work.
Dependencies & Execution Order
Phase Dependencies
- Phase 1 (Setup): no dependencies; start immediately.
- Phase 2 (Foundational): depends on Phase 1 and blocks all user stories.
- Phase 3 (US1): depends on Phase 2 and establishes the primary browse surface.
- Phase 4 (US2): depends on Phase 2 and should ship with US1 so the register opens into a finished detail surface.
- Phase 5 (US3): depends on Phase 2 and should follow once the canonical detail route exists.
- Phase 6 (Polish): depends on all desired user stories being complete.
User Story Dependencies
- US1 (P1): independently testable after Phase 2 and delivers the primary operator value.
- US2 (P1): independently testable after Phase 2 and should ship with US1 so the browse surface is meaningful.
- US3 (P2): independently testable after Phase 2 and can follow once the canonical detail route is in place.
Within Each User Story
- Write the listed Pest coverage first and make it fail for the intended gap.
- Keep implementation inside the resource, widget, capability, and existing report-truth seams named above.
- Re-run the narrowest relevant validation command after each story checkpoint before moving on.
Implementation Strategy
Suggested MVP Scope
- MVP = US1 + US2 together. The feature only closes the operator gap when the register and detail surface both exist.
Incremental Delivery
- Complete Phase 1 and Phase 2.
- Deliver US1 so operators can browse current and historical stored reports.
- Deliver US2 so the browse surface opens into a trustworthy detail surface.
- Deliver US3 by wiring the canonical detail route into the current admin-roles widget seam.
- Finish with the focused validation and guardrail review in Phase 6.
Team Strategy
- Settle capability and test shape first.
- Parallelize failing test authoring within the stored-report feature family before runtime edits.
- Serialize merges around
StoredReportResource,ViewStoredReport, andAdminRolesSummaryWidgetso route and vocabulary drift does not spread.
Deferred Follow-Ups / Non-Goals
- report generation, scheduling, or rerun actions from the stored-report surface
- raw payload download or export
- cross-tenant or workspace-wide stored-report browsing
- customer-facing stored-report consumption
- generic report registry, renderer framework, or analytics console