TenantAtlas/specs/261-provider-missing-policy-visibility/tasks.md
Ahmed Darrazi 91f327a7c2
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m40s
feat(specs/261): add provider missing policy visibility
2026-05-01 22:17:29 +02:00

20 KiB

Tasks: Provider-Missing Policy Visibility & Restore Continuity v1

Input: Design documents from /specs/261-provider-missing-policy-visibility/
Prerequisites: plan.md, spec.md, research.md, data-model.md, quickstart.md, contracts/provider-missing-policy-visibility.openapi.yaml

Tests (TEST-GOV-001): REQUIRED (Pest). Keep proof in the targeted fast-feedback and confidence feature/unit lanes already named in specs/261-provider-missing-policy-visibility/plan.md and specs/261-provider-missing-policy-visibility/quickstart.md. Prefer focused coverage in apps/platform/tests/Feature/Jobs/PolicySyncProviderMissingSemanticsTest.php, apps/platform/tests/Feature/Jobs/PolicySyncIgnoredRevivalTest.php, apps/platform/tests/Feature/PolicySyncServiceTest.php, apps/platform/tests/Feature/PolicySyncStartSurfaceTest.php, apps/platform/tests/Feature/Filament/PolicyProviderMissingUiTest.php, apps/platform/tests/Feature/BulkDeletePoliciesTest.php, apps/platform/tests/Feature/BulkUnignorePoliciesTest.php, apps/platform/tests/Feature/BulkExportToBackupTest.php, apps/platform/tests/Feature/Filament/BackupCreationTest.php, apps/platform/tests/Feature/Filament/BackupSetPolicyPickerTableTest.php, apps/platform/tests/Feature/Filament/RestoreItemSelectionTest.php, and apps/platform/tests/Unit/Badges/PolicyBadgesTest.php. Do not add browser or heavy-governance coverage for this slice. Operations: No new OperationRun family is introduced. Existing policy sync and current backup/export surfaces keep their shared start UX only when an action is still allowed. Provider-missing current backup/export blocks must stop before run creation and explain why locally. RBAC: Preserve current workspace/tenant deny-as-not-found 404 boundaries, retain 403 for in-scope capability failures on existing policy, backup, and restore actions, and do not introduce new capability strings or role checks. UI / Surface Guardrails: This is review-mandatory work across native Filament policy, backup, and restore surfaces. Keep standard-native-filament relief for the policy and backup screens and shared-detail-family proof for restore continuity. Explicitly prove one dominant next action per changed surface, diagnostics-secondary ordering, hidden or capability-gated support detail, and no duplicate visible decision summary. Do not add a new page, diagnostics shell, panel, or asset. Filament UI Action Surfaces: No new Filament Resource, Page, RelationManager, panel, or provider work is introduced. apps/platform/app/Filament/Resources/PolicyResource.php, apps/platform/app/Filament/Resources/BackupSetResource.php, and apps/platform/app/Filament/Resources/RestoreRunResource.php remain the only affected operator-facing surfaces. Organization: Tasks are grouped by user story so each slice stays independently verifiable. Recommended delivery order is Phase 1 -> Phase 2 -> US1 -> US2 -> US3 -> final polish and validation because provider-presence truth must exist before backup/restore and audit behavior can be finished safely.

Test Governance Checklist

  • Lane assignment stays fast-feedback plus confidence and remains the narrowest sufficient proof for the changed behavior.
  • New or changed tests stay in focused Feature and Unit files only; no browser or heavy-governance family is added.
  • Shared helpers, factories, seeds, fixtures, and support defaults remain cheap by default.
  • Planned validation commands stay limited to the targeted Sail test commands already captured in specs/261-provider-missing-policy-visibility/plan.md and specs/261-provider-missing-policy-visibility/quickstart.md.
  • The declared surface test profile stays standard-native-filament plus shared-detail-family where restore continuity needs explicit proof.
  • Any follow-up or wording note resolves in this feature as document-in-feature or follow-up-spec, not as implicit scope creep.

Phase 1: Setup (Shared Inventory)

Purpose: Lock the concrete source seams and narrow proof commands before implementation starts.

  • T001 [P] Verify the source-truth inventory across apps/platform/app/Models/Policy.php, apps/platform/app/Services/Intune/PolicySyncService.php, apps/platform/app/Services/Intune/BackupService.php, apps/platform/app/Filament/Resources/PolicyResource.php, apps/platform/app/Filament/Resources/BackupSetResource.php, apps/platform/app/Filament/Resources/RestoreRunResource.php, and apps/platform/app/Jobs/Operations/PolicyBulkDeleteWorkerJob.php
  • T002 [P] Verify the focused validation commands and proof lanes in specs/261-provider-missing-policy-visibility/plan.md and specs/261-provider-missing-policy-visibility/quickstart.md
  • T003 [P] Verify the badge and audit seams across apps/platform/tests/Unit/Badges/PolicyBadgesTest.php, apps/platform/app/Support/Audit/AuditActionId.php, and the current policy sync test family

Checkpoint: The narrow seam inventory and proving commands are locked before runtime code changes begin.


Phase 2: Foundational (Blocking Proof Anchors)

Purpose: Make the failing proof and shared state vocabulary explicit before touching shared runtime truth.

CRITICAL: No user story work should begin until this phase is complete.

  • T004 [P] Lock sync-state proof across apps/platform/tests/Feature/Jobs/PolicySyncProviderMissingSemanticsTest.php, apps/platform/tests/Feature/Jobs/PolicySyncIgnoredRevivalTest.php, apps/platform/tests/Feature/PolicySyncServiceTest.php, apps/platform/tests/Feature/PolicySyncEnrollmentConfigurationTypeCollisionTest.php, and apps/platform/tests/Feature/Jobs/AppProtectionPolicySyncFilteringTest.php
  • T005 [P] Lock policy-surface and badge proof across apps/platform/tests/Feature/Filament/PolicyProviderMissingUiTest.php, apps/platform/tests/Feature/PolicyGeneralViewTest.php, and apps/platform/tests/Unit/Badges/PolicyBadgesTest.php, including one dominant next action, diagnostics-secondary ordering, and no duplicate visible decision summary
  • T006 [P] Lock current-backup and restore-continuity proof across apps/platform/tests/Feature/BulkExportToBackupTest.php, apps/platform/tests/Feature/Filament/BackupCreationTest.php, apps/platform/tests/Feature/Filament/BackupSetPolicyPickerTableTest.php, apps/platform/tests/Feature/Filament/RestoreItemSelectionTest.php, and apps/platform/tests/Feature/RestoreUnknownPolicyTypeSafetyTest.php

Checkpoint: Failing proof files and state-vocabulary expectations are explicit and ready for bounded implementation work.


Phase 3: User Story 1 - Distinguish provider missing from local ignore (Priority: P1) 🎯 MVP

Goal: Make policy sync and policy surfaces tell the truth about provider-missing versus locally ignored state.

Independent Test: Sync a previously observed policy out of the supported provider result set while keeping another policy locally ignored, then verify policy list/detail surfaces show distinct states and sync no longer auto-clears local ignore.

Tests for User Story 1

  • T007 [P] [US1] Add sync-state coverage for provider-missing detection, reappearance, and no-auto-revive behavior in apps/platform/tests/Feature/Jobs/PolicySyncProviderMissingSemanticsTest.php, apps/platform/tests/Feature/Jobs/PolicySyncIgnoredRevivalTest.php, and apps/platform/tests/Feature/PolicySyncServiceTest.php
  • T008 [P] [US1] Add policy UI and badge coverage for provider-missing versus ignored states in apps/platform/tests/Feature/Filament/PolicyProviderMissingUiTest.php, apps/platform/tests/Feature/PolicyGeneralViewTest.php, and apps/platform/tests/Unit/Badges/PolicyBadgesTest.php, including dominant-action, diagnostics-secondary, and duplicate-summary assertions

Implementation for User Story 1

  • T009 [US1] Add missing_from_provider_at persistence and provider-presence helpers in apps/platform/database/migrations/*_add_missing_from_provider_at_to_policies_table.php and apps/platform/app/Models/Policy.php
  • T010 [US1] Update sync and type-filter semantics in apps/platform/app/Services/Intune/PolicySyncService.php so provider absence sets/clears missing_from_provider_at, supported-type reclassification stops using ignored_at, and local ignore survives reappearance
  • T011 [US1] Update policy filters, badges, helper copy, and action availability in apps/platform/app/Filament/Resources/PolicyResource.php and any related policy page helpers so provider-missing state is distinct from local ignore
  • T012 [US1] Reconcile local ignore regression expectations in apps/platform/tests/Feature/BulkDeletePoliciesTest.php, apps/platform/tests/Feature/BulkUnignorePoliciesTest.php, apps/platform/tests/Feature/PolicySyncStartSurfaceTest.php, apps/platform/tests/Feature/Jobs/AppProtectionPolicySyncFilteringTest.php, and apps/platform/tests/Feature/PolicySyncEnrollmentConfigurationTypeCollisionTest.php

Checkpoint: User Story 1 is independently functional and policy surfaces no longer collapse provider absence into local ignore.


Phase 4: User Story 2 - Keep current backup/export honest while preserving restore continuity (Priority: P1)

Goal: Stop treating provider-missing policies as current snapshot candidates while keeping historical restore paths available.

Independent Test: Mark a policy provider-missing, verify current backup/export selection blocks or excludes it, then verify historical restore selection still offers the related backup item with continuity messaging.

Tests for User Story 2

  • T013 [P] [US2] Add current backup/export eligibility coverage in apps/platform/tests/Feature/BulkExportToBackupTest.php, apps/platform/tests/Feature/Filament/BackupCreationTest.php, and apps/platform/tests/Feature/Filament/BackupSetPolicyPickerTableTest.php, including the combined ignored-plus-missing case where provider_missing is primary and local ignore is secondary context
  • T014 [P] [US2] Add restore continuity coverage for provider-missing policies in apps/platform/tests/Feature/Filament/RestoreItemSelectionTest.php and any required restore safety regression assertions in apps/platform/tests/Feature/RestoreUnknownPolicyTypeSafetyTest.php, including calm continuity messaging without duplicating current-state blocker summaries

Implementation for User Story 2

  • T015 [US2] Update current backup/export policy selection in apps/platform/app/Services/Intune/BackupService.php so provider-missing policies remain visible but blocked from fresh capture
  • T016 [US2] Update backup selection/picker messaging in apps/platform/app/Filament/Resources/BackupSetResource.php and related backup creation helpers so provider-missing policies explain why fresh capture is unavailable without masquerading as ignored, while the combined state keeps local ignore as secondary context only
  • T017 [US2] Update historical restore option builders and descriptions in apps/platform/app/Filament/Resources/RestoreRunResource.php so provider-missing policies remain selectable from backup history with continuity messaging

Checkpoint: User Story 2 is independently functional and backup versus restore truth is no longer conflated.


Phase 5: User Story 3 - Audit transitions and preserve safe recovery paths (Priority: P2)

Goal: Make provider-missing and reappeared transitions auditable while keeping existing safe sync-retry behavior on the shared action surface.

Independent Test: Run sync through missing and reappeared transitions, verify audit evidence is emitted, and confirm existing sync-retry surfaces remain truthful without creating new run behavior.

Tests for User Story 3

  • T018 [P] [US3] Add audit-transition coverage in apps/platform/tests/Feature/Jobs/PolicySyncProviderMissingSemanticsTest.php and any existing audit assertions that cover policy sync transitions
  • T019 [P] [US3] Add sync-action and authorization continuity assertions in apps/platform/tests/Feature/PolicySyncStartSurfaceTest.php, apps/platform/tests/Feature/Filament/PolicyProviderMissingUiTest.php, apps/platform/tests/Feature/Filament/BackupSetPolicyPickerTableTest.php, and apps/platform/tests/Feature/Filament/RestoreItemSelectionTest.php

Implementation for User Story 3

  • T020 [US3] Add or reuse audit action identifiers and emit provider-missing/reappeared events in apps/platform/app/Support/Audit/AuditActionId.php plus the existing audit logger call sites reached from policy sync
  • T021 [US3] Reconcile sync-retry/export action truth in apps/platform/app/Filament/Resources/PolicyResource.php, apps/platform/tests/Feature/PolicySyncStartSurfaceTest.php, and related policy action tests so blocked current backup/export does not create a run and allowed sync retry still uses the shared path

Checkpoint: User Story 3 is independently functional and provider-presence transitions are auditable without new lifecycle or run infrastructure.


Phase 6: Polish & Cross-Cutting Validation

Purpose: Clean shared wording and run the narrow validation workflow.

  • T022 [P] Reconcile any remaining provider-missing wording, badge labels, helper copy, dominant-action hierarchy, diagnostics-secondary ordering, raw/support gating, and duplicate-summary removal across apps/platform/app/Filament/Resources/PolicyResource.php, apps/platform/app/Filament/Resources/BackupSetResource.php, apps/platform/app/Filament/Resources/RestoreRunResource.php, and any touched localization or UI helper files
  • T023 Run formatting for touched PHP files with export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent
  • T024 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Jobs/PolicySyncProviderMissingSemanticsTest.php tests/Feature/Jobs/PolicySyncIgnoredRevivalTest.php tests/Feature/Jobs/AppProtectionPolicySyncFilteringTest.php tests/Feature/PolicySyncServiceTest.php tests/Feature/PolicySyncEnrollmentConfigurationTypeCollisionTest.php tests/Feature/PolicySyncStartSurfaceTest.php
  • T025 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/PolicyProviderMissingUiTest.php tests/Feature/PolicyGeneralViewTest.php tests/Feature/BulkDeletePoliciesTest.php tests/Feature/BulkUnignorePoliciesTest.php tests/Unit/Badges/PolicyBadgesTest.php
  • T026 [P] Run export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/BulkExportToBackupTest.php tests/Feature/Filament/BackupCreationTest.php tests/Feature/Filament/BackupSetPolicyPickerTableTest.php tests/Feature/Filament/RestoreItemSelectionTest.php tests/Feature/RestoreUnknownPolicyTypeSafetyTest.php
  • T027 Run final residue searches for sync-driven ignored_at writes, expected missing_from_provider_at query usage, and the absence of SoftDeletes, purge-flow additions, new deletion actions, or lifecycle-framework drift across apps/platform/app/ and apps/platform/tests/

Dependencies & Execution Order

Phase Dependencies

  • Setup (Phase 1): Starts immediately and locks the seam inventory plus validation commands.
  • Foundational (Phase 2): Depends on Setup and blocks story work until failing proof and state vocabulary are explicit.
  • User Story 1 (Phase 3): Depends on Foundational and is the MVP entry point because provider-presence truth is the base behavior.
  • User Story 2 (Phase 4): Depends on User Story 1 because backup and restore behavior consume the new provider-presence truth.
  • User Story 3 (Phase 5): Depends on User Story 1 and should land after User Story 2 so audit and action continuity match the finished current-state and historical-state behavior.
  • Polish (Phase 6): Depends on all desired user stories being complete so wording and residue checks run against the final shape.

User Story Dependencies

  • US1: No dependencies beyond Foundational.
  • US2: Depends on US1.
  • US3: Depends on US1 and should follow US2.

Within Each User Story

  • Add or update story tests first and confirm they fail before implementation is considered complete.
  • Keep ignored_at and missing_from_provider_at orthogonal rather than introducing a combined stored enum.
  • Reuse existing policy, backup, and restore surfaces instead of adding a new provider-missing registry or diagnostics page.
  • Keep provider-deleted taxonomy, multi-object rollout, and broader lifecycle work out of scope.

Parallel Opportunities

  • T001, T002, and T003 can run in parallel during Setup.
  • T004, T005, and T006 can run in parallel during Foundational work.
  • T007 and T008 can run in parallel for User Story 1 before T009 through T012.
  • T013 and T014 can run in parallel for User Story 2 before T015 through T017.
  • T018 and T019 can run in parallel for User Story 3 before T020 and T021.
  • T024, T025, and T026 can run in parallel during final validation.

Parallel Example: User Story 1

# User Story 1 tests in parallel
T007 apps/platform/tests/Feature/Jobs/PolicySyncProviderMissingSemanticsTest.php + apps/platform/tests/Feature/Jobs/PolicySyncIgnoredRevivalTest.php + apps/platform/tests/Feature/PolicySyncServiceTest.php
T008 apps/platform/tests/Feature/Filament/PolicyProviderMissingUiTest.php + apps/platform/tests/Feature/PolicyGeneralViewTest.php + apps/platform/tests/Unit/Badges/PolicyBadgesTest.php

# User Story 1 implementation after the tests are in place
T009 apps/platform/database/migrations/*_add_missing_from_provider_at_to_policies_table.php + apps/platform/app/Models/Policy.php
T010 apps/platform/app/Services/Intune/PolicySyncService.php
T011 apps/platform/app/Filament/Resources/PolicyResource.php

Parallel Example: User Story 2

# User Story 2 tests in parallel
T013 apps/platform/tests/Feature/BulkExportToBackupTest.php + apps/platform/tests/Feature/Filament/BackupCreationTest.php + apps/platform/tests/Feature/Filament/BackupSetPolicyPickerTableTest.php
T014 apps/platform/tests/Feature/Filament/RestoreItemSelectionTest.php + apps/platform/tests/Feature/RestoreUnknownPolicyTypeSafetyTest.php

# User Story 2 implementation after the tests are in place
T015 apps/platform/app/Services/Intune/BackupService.php
T016 apps/platform/app/Filament/Resources/BackupSetResource.php
T017 apps/platform/app/Filament/Resources/RestoreRunResource.php

Implementation Strategy

MVP First (User Stories 1 and 2)

  1. Complete Phase 1: Setup.
  2. Complete Phase 2: Foundational.
  3. Complete Phase 3: User Story 1.
  4. Complete Phase 4: User Story 2.
  5. Run T023, T024, T025, and T026 before widening into audit and action-continuity cleanup.

Incremental Delivery

  1. Introduce provider-presence truth on Policy and stop sync from mutating ignored_at for provider absence.
  2. Update policy UI to reflect the corrected state vocabulary.
  3. Update backup selection so fresh capture uses provider-present truth only.
  4. Update restore selection so historical backup continuity remains available.
  5. Add audit continuity and finish with narrow validation commands.

Parallel Team Strategy

  1. One contributor can own the sync/model/policy surface slice (US1) while another prepares backup/restore tests (US2) after Phase 2.
  2. After US1 lands, backup and restore implementation can proceed without reopening state vocabulary.
  3. A final pass can add audit continuity plus residue cleanup and run the targeted Sail commands.

Notes

  • Suggested MVP scope: Phase 1 through Phase 4 only. Current backup/export truth is not honest until both US1 and US2 land together.
  • Explicit non-goals remain: SoftDeletes, provider-deleted taxonomy, ghost-policy registry, multi-object lifecycle rollout, workspace/tenant lifecycle semantics, and new browser or heavy-governance proof.
  • Follow-up candidates remain the same as the prepared spec: the broader lifecycle taxonomy and an explicit provider-deleted distinction.
  • All tasks above follow the required checklist format with task ID, optional parallel marker, story label where applicable, and concrete file paths.