## Summary - finalize the restore create wizard productization across safety, validation, preview, and confirmation steps - refine the restore presenter output and Blade component rendering for clearer proof, scope, resolver, and execution-readiness states - add and update feature and browser coverage plus Spec 333 artifacts and screenshots ## Testing - Not run as part of this commit/PR task Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #403
23 KiB
23 KiB
Restore Preview Step Audit - Spec 333
Executive Summary
- readiness: not ready
- top findings:
- P0: Step 04 can show
Next gate: Confirmationwhile execution readiness is unavailable andcanProceedToConfirmis false. Browser verification confirmedNextstays on Step 04 and raisesExecution blocked, so progression is protected, but the visible gate is contradictory. - P1: Preview rows do not carry an explicit review reason. Operators must infer why review is needed from generic row chips.
- P1: Assignment and scope-tag preview data is repo-backed only as booleans and aggregate counts, not as detailed diffs.
- P2:
Nextremains visually enabled before preview and after blocked execution readiness; enforcement happens through the wizard validation hook. - P2: Preview copy still exposes implementation terms such as
normalized diffand uses preview notifications that say items "will be updated during execution."
- P0: Step 04 can show
- recommended implementation strategy: keep changes narrow in the presenter and preview Blade. Fix gate wording/action state first, then add a derived
review_reasonrow contract from already-available preview fields. Do not add new persisted entities for assignment or scope-tag details until the diff generator can produce them.
Repo Safety
- command snapshot:
git status --short --branchgit diff --name-only
- branch:
333-restore-create-ux-final-productization - base commit recorded before audit:
3bbea1bd feat: productize restore wizard preview safety gates and process flow (#399) - dirty files existed before this audit and were treated as protected user/agent work.
- runtime files that looked related to Spec 333 and were not edited by this audit:
apps/platform/app/Filament/Resources/RestoreRunResource.phpapps/platform/app/Filament/Resources/RestoreRunResource/Pages/CreateRestoreRun.phpapps/platform/app/Filament/Resources/RestoreRunResource/Presenters/RestoreRunCreatePresenter.phpapps/platform/app/Support/RestoreSafety/RestoreSafetyResolver.phpapps/platform/resources/views/filament/forms/components/restore-run-preview.blade.phpapps/platform/resources/views/filament/forms/components/restore-run-confirm-panel.blade.phpapps/platform/resources/views/filament/forms/components/restore-run-safety-*.blade.phpapps/platform/tests/Browser/Spec333RestoreCreateUxFinalProductizationSmokeTest.phpapps/platform/tests/Feature/Filament/Spec333RestoreCreateUxFinalProductizationTest.php
- dirty files not to touch during this audit:
- existing Spec 332 screenshots and tests
- existing runtime PHP, Blade, and test changes
- any staged or untracked runtime files
- files created by this audit:
specs/333-restore-create-ux-final-productization/artifacts/restore-preview-step-audit.md- screenshots under
specs/333-restore-create-ux-final-productization/artifacts/screenshots/preview-audit/
Repo Truth
Data sources
- Backup item and restore source:
backup_items.payload,backup_items.assignments,backup_items.metadata.scope_tag_ids. - Current target state: latest
policy_versions.snapshot,policy_versions.assignments,policy_versions.scope_tags. - Preview generation:
App\Services\Intune\RestoreDiffGenerator::generate(). - Preview state in wizard:
preview_summary,preview_diffs,preview_ran_at,preview_basis,preview_invalidation_reasons. - Presenter contract:
RestoreRunCreatePresenter::make()andpreviewSummary(). - Visible UI:
restore-run-preview.blade.php. - Gate/proof data:
RestoreSafetyResolver,PreviewIntegrityState,ChecksIntegrityState,ExecutionReadinessState, process-flow and proof partials.
Diff data availability
- repo-verified: per-policy
diff.summary.added,removed,changed. - repo-verified: bounded raw diff arrays exist in
diff.added,diff.removed,diff.changed, but current Step 04 does not render raw diff details by default. - repo-verified:
diff_omittedanddiff_truncatedexist for limit handling. - derived from existing model:
needsAttentionDiffsis derived from diff counts,assignments_changed, andscope_tags_changed. - not available: row-level human review reason as a first-class field.
Assignment and scope-tag availability
- repo-verified:
assignments_changedboolean per preview entry. - repo-verified: aggregate
assignments_changedpolicy count in preview summary. - repo-verified:
scope_tags_changedboolean per preview entry. - repo-verified: aggregate
scope_tags_changedpolicy count in preview summary. - not available: assignment added/removed/changed counts.
- not available: scope-tag added/removed/changed counts.
- deferred: mapping-specific assignment/scope-tag explanation in preview rows.
Preview action availability
- repo-verified:
RestoreDiffGeneratoremitsaction = updatewhen a current version exists andaction = createotherwise. - foundation-real but not generated here: Blade contains a
deletelabel path, but the generator path audited here does not produce deletes. - derived from existing model: UI displays unchanged rows as
No policy changeseven though generator action can still beupdate. - not available: a persisted no-op action type.
Review, warning, and blocker categories
- repo-verified: validation blockers/warnings come from check summary and check results.
- repo-verified: execution readiness can block confirmation even when validation and preview are current.
- repo-verified: preview/check integrity states are
not_generated,invalidated,stale, andcurrent. - derived from existing model:
canProceedToConfirm = checksAreCurrent && previewIsCurrent && executionAllowed. - current gap:
nextGateLabelcurrently returnsConfirmationwhen checks and preview are current, even ifexecutionAllowedis false.
Browser Fixture / URLs
- local target:
http://localhost/admin - fixture used for reachable diff state:
- workspace:
spec332-audit-dbdw18 - environment:
spec332-audit-env-tazinm - user:
spec332-audit-i5optd@example.test - backup set:
18(Spec332 Audit Usable Backup)
- workspace:
- route pattern used:
/admin/local/smoke-login?...&redirect=/admin/workspaces/spec332-audit-dbdw18/environments/spec332-audit-env-tazinm/restore-runs/create?backup_set_id=18
- capture method:
- Integrated Browser was used to navigate and verify interactions.
- In-app screenshot capture timed out on
Page.captureScreenshot, so image files were captured with the repo-installed Playwright package inapps/platform.
- no restore run was created.
Reachable states
- Preview generated with differences: reachable.
- Needs attention: reachable.
- Safety/proof disclosure: reachable.
- Dark mode: reachable.
- Next before preview: reachable; visually enabled, halted by hook.
- Next after generated preview with execution unavailable: reachable; visually enabled, halted by hook.
Not reachable states
- Preview generated with no changes: not reachable with current workspace-scoped fixtures. No-change local backups exist in legacy non-workspace-scoped data (
backup_set_id4/14), but not in the Spec 332/333 scoped route. - Preview with assignment changes: data exists in
backup_set_id19, but browser flow stops at Step 03 with a validation blocker:1 group assignment targets are missing in the tenant and require mapping (or skip). - Preview with scope-tag changes: repo-supported by generator fields, but no current scoped browser fixture was found.
- Preview blocked/unavailable on Step 04: not directly reachable because Step 03 validation blockers halt progression before Step 04. The presenter can render unavailable states from state, but the wizard path did not expose them without adding fixtures.
Screenshot Index
| State | Screenshot | Notes |
|---|---|---|
| Preview generated summary | screenshots/preview-audit/01-preview-generated-summary.png |
Diff state with current preview, execution unavailable |
| Needs attention | screenshots/preview-audit/02-preview-needs-attention.png |
Row shows policy diff, assignments, scope tags |
| Details expanded | screenshots/preview-audit/03-preview-details-expanded.png |
All reviewed items opened |
| All reviewed collapsed | screenshots/preview-audit/04-preview-all-reviewed-collapsed.png |
Default collapsed disclosure |
| No changes | not captured | No workspace-scoped no-change fixture found |
| Assignment change | not captured | Existing fixture blocked by missing group mapping at validation |
| Scope-tag change | not captured | No scoped browser fixture found |
| Blocked preview | not captured | Wizard halts before Step 04 for blocker fixture |
| Safety/proof disclosure | screenshots/preview-audit/09-preview-safety-proof-disclosure.png |
Safety gates and proof opened |
| Dark mode | screenshots/preview-audit/10-preview-dark-mode.png |
Step 04 summary in dark theme |
Current UI Assessment
Decision Summary
- Strong: summary-first layout is clear, quiet, and scannable.
- Strong: counts for policies reviewed, changed, unchanged, review, assignments, scope tags, blockers, warnings, and next gate are visible above details.
- Gap:
Next gatecan sayConfirmationwhileExecutionsaysUnavailableandNextis blocked. - Gap: the primary next action text says to resolve Microsoft permission readiness, but the metric card still says
Confirmation. - Gap:
Nextis visually enabled before preview and when execution readiness blocks confirmation.
Preview Details
- Strong: details are not a card flood on desktop; changed items render in a table-like hierarchy with clear labels.
- Strong: raw JSON/provider payloads are hidden by default.
- Gap: row does not include a
Review reason. - Gap:
Update existingis clearer thanUpdate, but it still does not explain what changed by itself. - Gap: unchanged rows still have an underlying generated action of
update; the UI derivesNo policy changes, but the contract is not explicit in data.
Needs Attention
- Strong: changed rows are separated from unchanged rows.
- Gap: the warning text is generic:
Review policy diff, assignments, and scope tags before confirmation. - Gap: if only one dimension changed, the row still references all dimensions instead of the precise reason.
All Reviewed Items
- Strong: collapsed by default and not dominant.
- Strong: useful as a complete audit list.
- Gap: because changed rows are already shown above, the disclosure duplicates data. That is acceptable if the later implementation keeps it compact.
Safety / Proof Disclosure
- Strong: visible but below the preview decision and details.
- Strong: full safety/proof content is progressively disclosed.
- Gap:
Preview evidenceappears both in the preview summary and in the lower evidence/proof section, which can blur whether it means diff evidence or gate evidence. - Gap:
Execution unavailableis visible, but its relationship toNext gate: Confirmationis contradictory.
Buttons / Interactions
| Action | Visible state | Expected behavior | Actual behavior | Preserves state? | Gate effect | Label clear? | Severity | Recommended fix |
|---|---|---|---|---|---|---|---|---|
| Next before preview | Visible and enabled | Should be disabled or clearly blocked until preview exists | Click stays on Step 04 through validation hook | yes | no gate advance | weak | P2 | Disable or relabel with preview requirement |
| Next after preview, execution unavailable | Visible and enabled | Should not advertise Confirmation if execution readiness blocks confirmation | Click stays on Step 04 and shows Execution blocked |
yes | no gate advance | contradictory | P0 | Set next gate/action to prerequisites blocked, or disable Next |
| Back | Visible | Return to Step 03 preserving state | Works in normal wizard flow | yes | previous step | clear | P3 | No change |
| Cancel | Visible earlier in wizard | Navigate away/cancel create flow | Standard Filament behavior | n/a | exits flow | clear | P3 | No change |
| Generate preview | Visible before preview | Generate current preview | Works | yes | preview current | clear enough | P2 | Avoid normalized diff helper copy |
| Regenerate preview | Visible after preview | Refresh preview for current basis | Works | yes | preview refreshed | clear | P3 | Keep |
| Clear | Visible after preview | Clear preview state | Visible; not tested to avoid losing audit state | likely yes | preview not generated | acceptable | P3 | Label could be Clear preview for specificity |
| All reviewed items disclosure | Visible after preview | Expand complete list | Works | yes | none | clear | P3 | Keep collapsed |
| View safety gates and restore proof | Visible after preview | Expand safety/proof details | Works | yes | none | mostly clear | P2 | Avoid duplicate proof terminology if proof is incomplete |
| Diagnostics | Present in partials/tests, not prominent in captured state | Show technical details only on demand | Not a dominant control in Step 04 | yes | none | acceptable | P3 | Keep behind disclosure |
Copy / Terminology
Problematic or mixed terms found:
Generate a normalized diff preview before confirmation.- classification: P2 copy issue
- reason:
normalized diffis implementation language.
1 policy will be updated during execution.- classification: P2/P1 depending context
- reason: generated from preview stage; not create/no-op aware and implies execution certainty.
Next gate: Confirmation- classification: P0 in the verified fixture
- reason: contradicted by
Execution unavailableand blockedNext.
Execution unavailable- classification: repo-safe, but relationship to confirmation is unclear.
Update existing- classification: acceptable label, but insufficient without review reason.
- Not observed in Step 04 capture:
Graph works againtechnical startabilitywrite-gatehard-blocker
Preview Row Contract Recommendation
| Column | Data source | Available? | Classification | Fallback if missing | Recommended label |
|---|---|---|---|---|---|
| Policy | preview_diffs[].display_name, policy_identifier, policy_type, platform |
yes | repo-verified | policy identifier plus type | Policy |
| Restore action | preview_diffs[].action plus derived unchanged state |
partial | repo-verified for create/update, derived for no-change | Review required |
Restore action |
| Policy diff | preview_diffs[].diff.summary |
yes | repo-verified | Diff unavailable |
Policy diff |
| Assignments | preview_diffs[].assignments_changed |
yes, boolean only | repo-verified | Unavailable |
Assignments |
| Scope tags | preview_diffs[].scope_tags_changed |
yes, boolean only | repo-verified | Unavailable |
Scope tags |
| Review reason | derived from diff counts, assignment boolean, scope-tag boolean, action, degraded/source states | not stored | derived from existing model | Review preview evidence before confirmation |
Review reason |
| Row action | no row-level action currently exists | no | not available | use disclosure only | Action only if an actual action is added |
Recommended derived review reasons:
Policy settings differ from current target state.Assignments differ from current target state.Scope tags differ from current target state.Target policy is missing and would be created if restore proceeds.No restore changes detected.Preview detail is unavailable because the diff was omitted by limits.
State Matrix
| State | Validation state | Preview data state | Expected status | Expected next gate | Expected primary action | Can continue? | Proof claims allowed? | Current UI | Gap |
|---|---|---|---|---|---|---|---|---|---|
| Preview not generated | current checks | none | preview required | Preview | Generate preview | no | validation proof only | Shows Next gate: Preview; Next enabled but halted |
Button state weak |
| Preview generated, no changes | current checks | current, no changed rows | preview current | Confirmation if execution allowed, otherwise prerequisites | Continue only if execution allowed | only if execution allowed | not browser-reached | Needs fixture | |
| Preview generated, changes | current checks | current, changed rows | preview current | Confirmation if execution allowed, otherwise prerequisites | Review rows | only if execution allowed | preview proof only | Shows changes clearly | Missing review reason |
| Preview generated, needs attention | current checks | current, needs attention | review required | Confirmation if execution allowed, otherwise prerequisites | Review reasons | only if execution allowed | preview proof only | Generic review text | Row reason missing |
| Preview generated, blocker | blocked checks or execution blocked | current or unavailable | blocked | Resolve blockers | Resolve blockers | no | no execution proof | Shows Confirmation in verified execution-blocked fixture |
P0 gate contradiction |
| Preview stale after scope/mapping change | check or preview basis mismatch | stale/invalidated | regenerate required | Validation or Preview | rerun checks/preview | no | prior proof only as stale | repo-supported | Not browser-captured |
| Validation blocked | blocked | none/current irrelevant | blocked | Validation | resolve blockers | no | no execution proof | browser reached on group mapping backup at Step 03 | Step 04 not reachable |
| Validation passed with warnings | current with warnings | current or none | review warnings | Preview/Confirmation depending preview and execution | review warnings | maybe | warning proof only | repo-supported | Not browser-captured |
| Validation passed clean | current clean | current | ready if execution allowed | Confirmation | continue | yes only if execution allowed | preview/check proof allowed, no execution proof | execution still unavailable in fixture | Gate wording conflict |
Findings
P0 Blockers
- Step 04 shows the wrong next gate when execution readiness blocks confirmation.
- Evidence: browser fixture shows
Next gate: Confirmation,Execution: Unavailable, and primary textresolve Microsoft permission readiness before confirmation. - Actual click behavior:
Nextremains on Step 04 and showsExecution blocked. - Risk: operator sees a contradictory decision state.
- Recommended fix:
nextGateLabelmust account for! executionAllowed; usePrerequisitesorExecution readinessinstead ofConfirmation, and make the primary action match.
- Evidence: browser fixture shows
P1 High
- Preview rows lack explicit review reason.
- Evidence: row shows
Update existing,0 added,0 removed,1 changed,No change,No change. - Risk: review intent remains implicit and brittle for assignment/scope-tag-only changes.
- Recommended fix: add a derived
Review reasonfield/column in presenter or view helpers.
- Evidence: row shows
- Assignment and scope-tag detail is not available beyond boolean change flags.
- Evidence: generator emits
assignments_changedandscope_tags_changed, plus aggregate counts. - Risk: UI can truthfully say changed/no change, but not explain which assignments or tags changed.
- Recommended fix: do not invent detail. Label as changed/no change/mapping required/unavailable until generator supports detailed normalized diffs.
- Evidence: generator emits
- Preview notification overstates execution certainty.
- Evidence:
1 policy will be updated during execution. - Risk: preview stage is not execution, and action mix can include create/no-change.
- Recommended fix:
Preview found 1 policy with restore differences.
- Evidence:
P2 Medium
Nextis visually enabled when the next action is blocked by missing preview or execution readiness.- Evidence: browser click before preview stays on Step 04; after preview and execution unavailable stays on Step 04.
- Recommended fix: disable or change label/helper when
canProceedToConfirmis false.
normalized diffcopy is developer-facing.- Evidence: helper text says
Generate a normalized diff preview before confirmation. - Recommended fix:
Generate a preview of policy, assignment, and scope-tag changes before confirmation.
- Evidence: helper text says
Preview evidenceis used for both diff currentness and lower proof/gate area.- Risk: evidence language can imply more proof than exists.
- Recommended fix: use
Preview statusfor currentness andSafety gatesfor lower proof area.
- Browser fixture coverage is incomplete for no-change, assignment-change-after-mapping, scope-tag-change, stale, and blocked Step 04 states.
- Recommended fix: add focused browser fixtures or component-state browser harness only after the UI contract is finalized.
P3 Polish
Clearshould beClear previewfor specificity.All reviewed itemsis useful but duplicates changed rows; keep it collapsed and compact.- The row layout is acceptable on desktop, but mobile cards should keep fixed label/value spacing to avoid repeated card bulk.
Recommended Implementation Plan
- narrow changes only:
- presenter gate logic
- preview row contract helpers
- preview Blade labels/copy
- focused tests
- files to touch later:
apps/platform/app/Filament/Resources/RestoreRunResource/Presenters/RestoreRunCreatePresenter.phpapps/platform/resources/views/filament/forms/components/restore-run-preview.blade.phpapps/platform/app/Filament/Resources/RestoreRunResource.phponly for action label/helper/disabled-state adjustments- existing Spec 333 feature/browser tests
- tests to add/update later:
- presenter test for
executionAllowed=falseproducing non-Confirmation next gate - feature test for derived review reasons across policy diff, assignment change, scope-tag change, create, and no-change rows
- browser smoke for blocked
Nextstate and clean preview state if fixtures are added
- presenter test for
- screenshots to update later:
- no-change state
- assignment-change state after mapping/skip fixture
- scope-tag-change state
- blocked/prerequisite state
DoD for Later Implementation
Next gatenever saysConfirmationunlesscanProceedToConfirmis true.Nextbehavior and visible label/helper match the current gate.- Preview rows include:
- Policy
- Restore action
- Policy diff
- Assignments
- Scope tags
- Review reason
- Assignment and scope-tag columns do not imply unavailable detail.
- Raw JSON/provider payloads remain hidden by default.
- Copy avoids implementation terms and false execution/recovery proof claims.
- Tests cover Filament/Livewire v5/v4 component behavior through Livewire components, not static resource classes.
- No global assets are introduced;
filament:assetsdeployment requirement remains unchanged.
Filament v5 Audit Notes
- Livewire compliance: application is on Livewire
4.1.4, satisfying Filament v5's Livewire v4 requirement. - Provider registration: panel/provider registration remains in
apps/platform/bootstrap/providers.php; this audit made no provider changes. - Global search:
RestoreRunResource::getPages()includes aviewpage, satisfying the v5 hard rule if the resource is globally searchable. - Destructive actions: Step 04 generate/regenerate/clear preview actions are not destructive restore execution actions. The dangerous execution gate remains later in the wizard and must continue to require confirmation and authorization.
- Asset strategy: no Filament assets were added. Deployment
php artisan filament:assetsremains unchanged. - Testing plan for later implementation: use Pest/Livewire component tests for wizard state and Filament action tests for Step 04 actions.