feat/004-assignments-scope-tags #4

Merged
ahmido merged 41 commits from feat/004-assignments-scope-tags into dev 2025-12-23 21:49:59 +00:00
Showing only changes of commit 28f440718a - Show all commits

View File

@ -183,12 +183,18 @@ ### Restore with Group Mapping
**FR-004.11**: System MUST persist group mapping selections in RestoreRun metadata for audit and rerun purposes. **FR-004.11**: System MUST persist group mapping selections in RestoreRun metadata for audit and rerun purposes.
**FR-004.12**: When restoring assignments, system MUST: **FR-004.12**: When restoring assignments, system MUST:
1. Replace source group IDs with mapped target group IDs 1. Replace source group IDs with mapped target group IDs in assignment objects
2. Skip assignments marked "Skip" 2. Skip assignments marked "Skip" in group mapping
3. Preserve include/exclude intent and filters 3. Preserve include/exclude intent and filters
4. Call POST `/deviceManagement/configurationPolicies/{id}/assign` (not PATCH) with complete mapped assignments array (replaces all assignments atomically) 4. Execute restore via DELETE-then-CREATE pattern:
5. Handle 204 No Content or 200 OK as success - Step 1: GET existing assignments from target policy
6. Log Graph request-id and client-request-id on failure - Step 2: DELETE each existing assignment (via DELETE `/assignments/{id}`)
- Step 3: POST each new/mapped assignment (via POST `/assignments`)
5. Handle failures gracefully:
- 204 No Content on DELETE = success
- 201 Created on POST = success
- Log request-id/client-request-id on any failure
6. Continue with remaining assignments if one fails (fail-soft)
**FR-004.13**: System MUST handle assignment restore failures gracefully: **FR-004.13**: System MUST handle assignment restore failures gracefully:
- Log per-assignment outcome (success/skip/failure) - Log per-assignment outcome (success/skip/failure)
@ -274,26 +280,31 @@ ### Endpoints to Add (Production-Tested Strategies)
- Client-side filter to extract assignments - Client-side filter to extract assignments
- **Reason**: Known Graph API quirks with assignment expansion on certain template families - **Reason**: Known Graph API quirks with assignment expansion on certain template families
2. **POST** `/deviceManagement/configurationPolicies/{id}/assign` (POST only, NOT PATCH) 2. **Assignment CRUD Operations** (Standard Graph Pattern)
- Body: `{ assignments: [assignment objects] }`
- Returns: 204 No Content or 200 OK - **POST** `/deviceManagement/configurationPolicies/{id}/assignments`
- **Note**: This is an action endpoint, replaces entire assignments array - Body: Single assignment object
- Example payload: - Returns: 201 Created with assignment object
- Example:
```json ```json
{ {
"assignments": [
{
"id": "00000000-0000-0000-0000-000000000000",
"target": { "target": {
"@odata.type": "#microsoft.graph.groupAssignmentTarget", "@odata.type": "#microsoft.graph.groupAssignmentTarget",
"groupId": "abc-123-def" "groupId": "abc-123-def"
}, },
"intent": "apply" "intent": "apply"
} }
]
}
``` ```
- **PATCH** `/deviceManagement/configurationPolicies/{id}/assignments/{assignmentId}`
- Body: Assignment object (partial update)
- Returns: 200 OK with updated assignment
- **DELETE** `/deviceManagement/configurationPolicies/{id}/assignments/{assignmentId}`
- Returns: 204 No Content
- **Restore Strategy**: DELETE all existing assignments, then POST new ones (atomic via transaction pattern)
3. **POST** `/directoryObjects/getByIds` (Stable Group Resolution) 3. **POST** `/directoryObjects/getByIds` (Stable Group Resolution)
- Body: `{ "ids": ["id1", "id2"], "types": ["group"] }` - Body: `{ "ids": ["id1", "id2"], "types": ["group"] }`
- Returns: `{ value: [{ id, displayName, ... }] }` - Returns: `{ value: [{ id, displayName, ... }] }`
@ -316,11 +327,20 @@ ### Graph Contract Updates
```php ```php
'settingsCatalogPolicy' => [ 'settingsCatalogPolicy' => [
// ... existing // ... existing config
'assignments_path' => '/deviceManagement/configurationPolicies/{id}/assignments',
'assign_method' => 'POST', // Assignments CRUD (standard Graph pattern)
'assign_path' => '/deviceManagement/configurationPolicies/{id}/assign', 'assignments_list_path' => '/deviceManagement/configurationPolicies/{id}/assignments',
'assignments_create_path' => '/deviceManagement/configurationPolicies/{id}/assignments',
'assignments_create_method' => 'POST',
'assignments_update_path' => '/deviceManagement/configurationPolicies/{id}/assignments/{assignmentId}',
'assignments_update_method' => 'PATCH',
'assignments_delete_path' => '/deviceManagement/configurationPolicies/{id}/assignments/{assignmentId}',
'assignments_delete_method' => 'DELETE',
// Scope Tags
'supports_scope_tags' => true, 'supports_scope_tags' => true,
'scope_tag_field' => 'roleScopeTagIds', // array in policy payload
], ],
``` ```