- Created docs/PERMISSIONS.md with complete permission requirements - Added logging for 403 errors in ScopeTagResolver - Updated README with link to permissions documentation Issue: Scope tags show 'Unknown (ID: 0)' due to missing permission Required: DeviceManagementRBAC.Read.All with admin consent User must: 1. Go to Azure Portal → App Registration 2. Add DeviceManagementRBAC.Read.All permission 3. Grant admin consent 4. Wait 5-10 min for propagation 5. Clear cache: php artisan cache:clear
229 lines
7.6 KiB
Markdown
229 lines
7.6 KiB
Markdown
# Feature 005: Policy Lifecycle Management
|
|
|
|
## Overview
|
|
Implement proper lifecycle management for policies that are deleted in Intune, including soft delete, UI indicators, and orphaned policy handling.
|
|
|
|
## Problem Statement
|
|
Currently, when a policy is deleted in Intune:
|
|
- ❌ Policy remains in TenantAtlas database indefinitely
|
|
- ❌ No indication that policy no longer exists in Intune
|
|
- ❌ Backup Items reference "ghost" policies
|
|
- ❌ Users cannot distinguish between active and deleted policies
|
|
|
|
**Discovered during**: Feature 004 manual testing (user deleted policy in Intune)
|
|
|
|
## Goals
|
|
- **Primary**: Implement soft delete for policies removed from Intune
|
|
- **Secondary**: Show clear UI indicators for deleted policies
|
|
- **Tertiary**: Maintain referential integrity for Backup Items and Policy Versions
|
|
|
|
## Scope
|
|
- **Policy Sync**: Detect missing policies during `SyncPoliciesJob`
|
|
- **Data Model**: Add `deleted_at`, `deleted_by` columns (Laravel Soft Delete pattern)
|
|
- **UI**: Badge indicators, filters, restore capability
|
|
- **Audit**: Log when policies are soft-deleted and restored
|
|
|
|
---
|
|
|
|
## User Stories
|
|
|
|
### User Story 1 - Automatic Soft Delete on Sync
|
|
|
|
**As a system administrator**, I want policies deleted in Intune to be automatically marked as deleted in TenantAtlas, so that the inventory reflects the current Intune state.
|
|
|
|
**Acceptance Criteria:**
|
|
1. **Given** a policy exists in TenantAtlas with `external_id` "abc-123",
|
|
**When** the next policy sync runs and "abc-123" is NOT returned by Graph API,
|
|
**Then** the policy is soft-deleted (sets `deleted_at = now()`)
|
|
|
|
2. **Given** a soft-deleted policy,
|
|
**When** it re-appears in Intune (same `external_id`),
|
|
**Then** the policy is automatically restored (`deleted_at = null`)
|
|
|
|
3. **Given** multiple policies are deleted in Intune,
|
|
**When** sync runs,
|
|
**Then** all missing policies are soft-deleted in a single transaction
|
|
|
|
---
|
|
|
|
### User Story 2 - UI Indicators for Deleted Policies
|
|
|
|
**As an admin**, I want to see clear indicators when viewing deleted policies, so I understand their status.
|
|
|
|
**Acceptance Criteria:**
|
|
1. **Given** I view a Backup Item referencing a deleted policy,
|
|
**When** I see the policy name,
|
|
**Then** it shows a red "Deleted" badge next to the name
|
|
|
|
2. **Given** I view the Policies list,
|
|
**When** I enable the "Show Deleted" filter,
|
|
**Then** deleted policies appear with:
|
|
- Red "Deleted" badge
|
|
- Deleted date in "Last Synced" column
|
|
- Grayed-out appearance
|
|
|
|
3. **Given** a policy was deleted,
|
|
**When** I view the Policy detail page,
|
|
**Then** I see:
|
|
- Warning banner: "This policy was deleted from Intune on {date}"
|
|
- All data remains readable (versions, snapshots, metadata)
|
|
|
|
---
|
|
|
|
### User Story 3 - Restore Workflow
|
|
|
|
**As an admin**, I want to restore a deleted policy from backup, so I can recover accidentally deleted configurations.
|
|
|
|
**Acceptance Criteria:**
|
|
1. **Given** I view a deleted policy's detail page,
|
|
**When** I click the "Restore to Intune" action,
|
|
**Then** the restore wizard opens pre-filled with the latest policy snapshot
|
|
|
|
2. **Given** a policy is successfully restored to Intune,
|
|
**When** the next sync runs,
|
|
**Then** the policy is automatically undeleted in TenantAtlas (`deleted_at = null`)
|
|
|
|
---
|
|
|
|
## Functional Requirements
|
|
|
|
### Data Model
|
|
|
|
**FR-005.1**: Policies table MUST use Laravel Soft Delete pattern:
|
|
```php
|
|
Schema::table('policies', function (Blueprint $table) {
|
|
$table->softDeletes(); // deleted_at
|
|
$table->string('deleted_by')->nullable(); // admin email who triggered deletion
|
|
});
|
|
```
|
|
|
|
**FR-005.2**: Policy model MUST use `SoftDeletes` trait:
|
|
```php
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
class Policy extends Model {
|
|
use SoftDeletes;
|
|
}
|
|
```
|
|
|
|
### Policy Sync Behavior
|
|
|
|
**FR-005.3**: `PolicySyncService::syncPolicies()` MUST detect missing policies:
|
|
- Collect all `external_id` values returned by Graph API
|
|
- Query existing policies for this tenant: `whereNotIn('external_id', $currentExternalIds)`
|
|
- Soft delete missing policies: `each(fn($p) => $p->delete())`
|
|
|
|
**FR-005.4**: System MUST restore policies that re-appear:
|
|
- Check if policy exists with `Policy::withTrashed()->where('external_id', $id)->first()`
|
|
- If soft-deleted: call `$policy->restore()`
|
|
- Update `last_synced_at` timestamp
|
|
|
|
**FR-005.5**: System MUST log audit entries:
|
|
- `policy.deleted` (when soft-deleted during sync)
|
|
- `policy.restored` (when re-appears in Intune)
|
|
|
|
### UI Display
|
|
|
|
**FR-005.6**: PolicyResource table MUST:
|
|
- Default query: exclude soft-deleted policies
|
|
- Add filter "Show Deleted" (includes `withTrashed()` in query)
|
|
- Show "Deleted" badge for soft-deleted policies
|
|
|
|
**FR-005.7**: BackupItemsRelationManager MUST:
|
|
- Show "Deleted" badge when `policy->trashed()` returns true
|
|
- Allow viewing deleted policy details (read-only)
|
|
|
|
**FR-005.8**: Policy detail view MUST:
|
|
- Show warning banner when policy is soft-deleted
|
|
- Display deletion date and reason (if available)
|
|
- Disable edit actions (policy no longer exists in Intune)
|
|
|
|
---
|
|
|
|
## Non-Functional Requirements
|
|
|
|
**NFR-005.1**: Soft delete MUST NOT break existing features:
|
|
- Backup Items keep valid foreign keys
|
|
- Policy Versions remain accessible
|
|
- Restore functionality works for deleted policies
|
|
|
|
**NFR-005.2**: Performance: Sync detection MUST NOT cause N+1 queries:
|
|
- Use single `whereNotIn()` query to find missing policies
|
|
- Batch soft-delete operation
|
|
|
|
**NFR-005.3**: Data retention: Soft-deleted policies MUST be retained for audit purposes (no automatic purging)
|
|
|
|
---
|
|
|
|
## Implementation Plan
|
|
|
|
### Phase 1: Data Model (30 min)
|
|
1. Create migration for `policies` soft delete columns
|
|
2. Add `SoftDeletes` trait to Policy model
|
|
3. Run migration on dev environment
|
|
|
|
### Phase 2: Sync Logic (1 hour)
|
|
1. Update `PolicySyncService::syncPolicies()`
|
|
- Track current external IDs from Graph
|
|
- Soft delete missing policies
|
|
- Restore re-appeared policies
|
|
2. Add audit logging
|
|
3. Test with manual deletion in Intune
|
|
|
|
### Phase 3: UI Indicators (1.5 hours)
|
|
1. Update `PolicyResource`:
|
|
- Add "Show Deleted" filter
|
|
- Add "Deleted" badge column
|
|
- Modify query to exclude deleted by default
|
|
2. Update `BackupItemsRelationManager`:
|
|
- Show "Deleted" badge for `policy->trashed()`
|
|
3. Update Policy detail view:
|
|
- Warning banner for deleted policies
|
|
- Disable edit actions
|
|
|
|
### Phase 4: Testing (1 hour)
|
|
1. Unit tests:
|
|
- Test soft delete on sync
|
|
- Test restore on re-appearance
|
|
2. Feature tests:
|
|
- E2E sync with deleted policies
|
|
- UI filter behavior
|
|
3. Manual QA:
|
|
- Delete policy in Intune → sync → verify soft delete
|
|
- Re-create policy → sync → verify restore
|
|
|
|
**Total Estimated Duration**: ~4-5 hours
|
|
|
|
---
|
|
|
|
## Risks & Mitigations
|
|
|
|
| Risk | Mitigation |
|
|
|------|------------|
|
|
| Foreign key constraints block soft delete | Laravel soft delete only sets timestamp, constraints remain valid |
|
|
| Bulk delete impacts performance | Use chunked queries if tenant has 1000+ policies |
|
|
| Deleted policies clutter UI | Default filter hides them, "Show Deleted" is opt-in |
|
|
|
|
---
|
|
|
|
## Success Criteria
|
|
1. ✅ Policies deleted in Intune are soft-deleted in TenantAtlas within 1 sync cycle
|
|
2. ✅ Re-appearing policies are automatically restored
|
|
3. ✅ UI clearly indicates deleted status
|
|
4. ✅ Backup Items and Versions remain accessible for deleted policies
|
|
5. ✅ No breaking changes to existing features
|
|
|
|
---
|
|
|
|
## Related Features
|
|
- Feature 004: Assignments & Scope Tags (discovered this issue during testing)
|
|
- Feature 001: Backup/Restore (must work with deleted policies)
|
|
|
|
---
|
|
|
|
**Status**: Planned (Post-Feature 004)
|
|
**Priority**: P2 (Quality of Life improvement)
|
|
**Created**: 2025-12-22
|
|
**Author**: AI + Ahmed
|
|
**Next Steps**: Implement after Feature 004 Phase 3 testing complete
|