Implemented operations UI operator actions regression gate. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #436
754 lines
48 KiB
Markdown
754 lines
48 KiB
Markdown
# Feature Specification: Operations UI Operator Actions & Regression Gate
|
|
|
|
**Feature Branch**: `365-operations-ui-operator-actions-regression-gate`
|
|
**Created**: 2026-06-07
|
|
**Status**: Draft / Ready for implementation
|
|
**Input**: User description: "Spec 365 - Operations UI Operator Actions & Regression Gate"
|
|
|
|
## Spec Candidate Check *(mandatory - SPEC-GATE-001)*
|
|
|
|
- **Problem**: OperationRun truth, reconciliation results, restore safety, and outcome semantics now exist, but operators still need a single decision-first surface that answers what happened, what needs attention, and what can be safely done next.
|
|
- **Today's failure**: Operators can see run history and technical details, but safe action eligibility is not centralized. This creates risk of scattered UI conditions, unsafe retry affordances for high-risk operations, raw diagnostic leakage, and incomplete regression coverage across Specs 358-364.
|
|
- **User-visible improvement**: The Operations hub and OperationRun detail become actionable and calm: one primary safe action, clear reason, scope, outcome, related domain links, and diagnostics only on demand.
|
|
- **Smallest enterprise-capable version**: Add a central derived action eligibility resolver, wire safe reconcile/open-related/detail presentation on existing Operations surfaces, integrate retry only where a repo-verified safe retry seam exists, block high-risk retry/force-success, and add a regression gate matrix.
|
|
- **Explicit non-goals**: No new adapter system, no generic OperationRun retry engine without an existing safe dispatch seam, no restore retry/re-execute, no force complete, no delete/purge, no new top-level Operations pages, no new persisted OperationRun status/outcome family, no raw JSON as the default detail experience.
|
|
- **Permanent complexity imported**: One narrow action eligibility resolver/presenter family, localized action/summary copy, action metadata/audit convention for operator actions, and focused unit/feature/browser regression tests.
|
|
- **Why now**: Specs 358-364 established the canonical run, reconciliation, outcome, and high-risk restore semantics. Without this final UI/action gate, the program remains technically correct but not operator-ready.
|
|
- **Why not local**: Local Blade/Filament `if` conditions would duplicate safety logic and create drift between list/detail/action tests. Central eligibility is required by RBAC, scope isolation, high-risk guardrails, and one-primary-action consistency.
|
|
- **Approval class**: Core Enterprise / Workflow Compression.
|
|
- **Red flags triggered**: New resolver abstraction; operator-facing action surface; high-risk operation guard. Defense: the abstraction is derived, non-persisted, bounded to existing OperationRun truth, and has multiple concrete current-release cases across review, evidence, backup/sync, and restore.
|
|
- **Score**: Nutzen: 3 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 3 | Wiederverwendung: 1 | **Gesamt: 12/12**
|
|
- **Decision**: approve as a bounded completion spec for the OperationRun/Reconciliation program.
|
|
|
|
## Spec Scope Fields *(mandatory)*
|
|
|
|
- **Scope**: workspace
|
|
- **Primary Routes**:
|
|
- `/admin/workspaces/{workspace}/operations`
|
|
- tenantless OperationRun detail route resolved by `OperationRunLinks::tenantlessView()`
|
|
- existing related domain detail routes resolved by `OperationRunLinks` / `RelatedNavigationResolver`
|
|
- **Data Ownership**: Existing workspace-owned `operation_runs` and related domain records. No new table or independent persisted entity is introduced by this spec.
|
|
- **RBAC**: Workspace membership and environment entitlement remain required. Capability checks must use existing capability registry/policies first; any new capability constant must be added only after repo verification proves no existing capability fits.
|
|
|
|
For this workspace-scope spec:
|
|
|
|
- **Default filter behavior when tenant-context is active**: Existing workspace Operations routes remain workspace-scoped. Tenant-context routes may deep-link to the same run only through existing tenant/workspace-safe URL resolution and entitlement checks.
|
|
- **Explicit entitlement checks preventing cross-tenant leakage**: OperationRun view/action policy checks must preserve current 404 semantics for non-member or not-entitled scope and 403 semantics for members missing capability.
|
|
|
|
## UI Surface Impact *(mandatory - UI-COV-001)*
|
|
|
|
Does this spec add, remove, rename, or materially change any reachable UI surface?
|
|
|
|
- [ ] No UI surface impact
|
|
- [x] Existing page changed
|
|
- [ ] New page/route added
|
|
- [ ] Navigation changed
|
|
- [ ] Filament panel/provider surface changed
|
|
- [x] New modal/drawer/wizard/action added
|
|
- [x] New table/form/state added
|
|
- [ ] Customer-facing surface changed
|
|
- [x] Dangerous action changed
|
|
- [x] Status/evidence/review presentation changed
|
|
- [x] Workspace/environment context presentation changed
|
|
|
|
## UI/Productization Coverage *(mandatory when UI Surface Impact is not "No UI surface impact"; otherwise write `N/A - no reachable UI surface impact` plus rationale)*
|
|
|
|
- **Route/page/surface**:
|
|
- `apps/platform/app/Filament/Pages/Monitoring/Operations.php`
|
|
- `apps/platform/app/Filament/Resources/OperationRunResource.php`
|
|
- `apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php`
|
|
- OperationRun detail header actions, related action group, summary/evidence/technical detail sections.
|
|
- **Current or new page archetype**: Existing Strategic Surface: Operations Hub / monitoring-state page.
|
|
- **Design depth**: Strategic Surface.
|
|
- **Repo-truth level**: repo-verified.
|
|
- **Existing pattern reused**: `docs/ui-ux-enterprise-audit/page-reports/ui-003-operations.md`, `docs/ui-ux-enterprise-audit/target-experience-briefs/operations-hub.md`, `docs/ui/action-surface-contract.md`, existing Filament resource/page actions, existing OperationRun detail presenter sections.
|
|
- **New pattern required**: none. Add a bounded action eligibility resolver and presenter extension; no new UI framework.
|
|
- **Screenshot required**: yes during implementation for browser smoke. Store in `specs/365-operations-ui-operator-actions-regression-gate/artifacts/spec365-operations-ui-screenshots/` if screenshots are captured.
|
|
- **Page audit required**: no new page audit required during prep; update the existing Operations page report only if implementation materially changes the page contract beyond action/state presentation.
|
|
- **Customer-safe review required**: yes. Browser smoke must prove no default raw SQL/Graph/queue/secret/stack trace leakage.
|
|
- **Dangerous-action review required**: yes. Restore/high-risk operations must not show retry/re-execute/force-success actions.
|
|
- **Coverage files updated or explicitly not needed**:
|
|
- [ ] `docs/ui-ux-enterprise-audit/route-inventory.md`
|
|
- [ ] `docs/ui-ux-enterprise-audit/design-coverage-matrix.md`
|
|
- [ ] `docs/ui-ux-enterprise-audit/page-reports/...`
|
|
- [ ] `docs/ui-ux-enterprise-audit/strategic-surfaces.md`
|
|
- [ ] `docs/ui-ux-enterprise-audit/grouped-follow-up-candidates.md`
|
|
- [ ] `docs/ui-ux-enterprise-audit/unresolved-pages.md`
|
|
- [ ] `N/A - no reachable UI surface impact`
|
|
- **Coverage artifact decision**: Implementation must either update the existing Operations page report/design matrix or record a proportional no-update rationale in `tasks.md` close-out when visual structure remains pattern-compatible.
|
|
- **No-impact rationale when applicable**: N/A.
|
|
|
|
## Cross-Cutting / Shared Pattern Reuse *(mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write `N/A - no shared interaction family touched`)*
|
|
|
|
- **Cross-cutting feature?**: yes
|
|
- **Interaction class(es)**: status messaging, header actions, row/detail actions, related navigation, evidence/report links, audit/action metadata, diagnostic disclosure.
|
|
- **Systems touched**:
|
|
- `OperationUxPresenter`
|
|
- `OperationRunProgressContract`
|
|
- `OperationRunLinks`
|
|
- `RelatedNavigationResolver`
|
|
- `RelatedActionLabelCatalog`
|
|
- `AdapterRunReconciler`
|
|
- `OperationRunReconciliationRegistry`
|
|
- `OperationRunService`
|
|
- `OperationRunPolicy` / capability resolver
|
|
- `AuditRecorder` / workspace audit services
|
|
- **Existing pattern(s) to extend**: Existing Operations hub, OperationRun detail, related navigation/action label catalog, OperationRun reconciliation registry, central OperationRun service writes.
|
|
- **Shared contract / presenter / builder / renderer to reuse**: Reuse existing presenters/link resolvers first. Add `OperationRunActionEligibility` only for action decision derivation where no central action model exists.
|
|
- **Why the existing shared path is sufficient or insufficient**: Existing services own reconciliation writes, detail links, and UX summaries, but no single repo-verified layer answers "which operator action is allowed and primary for this run". That gap is safety-relevant across multiple run families.
|
|
- **Allowed deviation and why**: Add one derived eligibility resolver and small action DTO/presenter if needed; do not create a new registry, state enum, or persisted action table unless implementation proves existing audit metadata is insufficient and the spec is amended.
|
|
- **Consistency impact**: List/detail/browser tests must use the same primary action, disabled reason, high-risk guard, and related-link truth.
|
|
- **Review focus**: Verify there is no parallel local action logic in Blade/Filament closures and no broad retry/re-execute system hidden behind UI actions.
|
|
|
|
## OperationRun UX Impact *(mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an `OperationRun`; otherwise write `N/A - no OperationRun start or link semantics touched`)*
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: yes
|
|
- **Shared OperationRun UX contract/layer reused**: `OperationUxPresenter`, `OperationRunProgressContract`, `OperationRunLinks`, `OperationRunService`, `AdapterRunReconciler`.
|
|
- **Delegated start/completion UX behaviors**: Existing progress/status/detail links remain central. Reconcile uses `AdapterRunReconciler` and `OperationRunService`. Retry may create a new OperationRun only through a repo-verified safe retry/start seam; otherwise retry is unavailable with a disabled reason.
|
|
- **Local surface-owned behavior that remains**: Operation-specific inputs are out of scope. The Operations surface owns display hierarchy and invoking authorized actions only.
|
|
- **Queued DB-notification policy**: No new queued/running DB notification policy. Retry, if implemented through an existing start seam, must follow that seam's notification policy.
|
|
- **Terminal notification path**: Existing central lifecycle mechanism.
|
|
- **Exception required?**: none for reconcile/open-related. Generic retry is explicitly not approved unless an existing safe dispatch seam is verified or added through a bounded implementation decision with tests.
|
|
|
|
## Provider Boundary / Platform Core Check *(mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write `N/A - no shared provider/platform boundary touched`)*
|
|
|
|
- **Shared provider/platform boundary touched?**: yes, bounded to presentation of existing operation reason codes and provider failure summaries.
|
|
- **Boundary classification**: mixed. OperationRun/action eligibility is platform-core; provider reason codes remain provider-owned diagnostic data.
|
|
- **Seams affected**: Operator summaries, diagnostics, high-risk labels, related artifact labels, localization strings.
|
|
- **Neutral platform terms preserved or introduced**: operation, run, outcome, attention, reconcile, retry, verification, partial, blocked, related artifact, diagnostics.
|
|
- **Provider-specific semantics retained and why**: Existing Graph/provider reason codes may appear only in operator/support diagnostics, not customer-readable default copy.
|
|
- **Why this does not deepen provider coupling accidentally**: The resolver reads canonical OperationRun context and operation type; it does not call Graph, inspect raw payloads, or add provider-specific branching except for existing high-risk operation classification.
|
|
- **Follow-up path**: none unless implementation discovers provider-shaped UI copy that cannot be normalized without a separate provider guidance spec.
|
|
|
|
## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed; otherwise write `N/A`)*
|
|
|
|
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note |
|
|
|---|---|---|---|---|---|---|
|
|
| Operations hub list decision/action columns | yes | Native Filament table + existing shared presenters | status messaging, row/detail actions | page, table, row, URL-safe links | no | Existing strategic surface; no new page |
|
|
| OperationRun detail decision layout/header actions | yes | Native Filament resource/detail + existing custom detail sections | header actions, related links, diagnostics | detail, header, disclosure | no | Keep raw/support detail secondary/collapsed |
|
|
| Reconcile/Retry action modals | yes | Filament `Action` with confirmation/authorization | action safety, audit | detail/header action | no | Retry only repo-real non-high-risk seams |
|
|
| Related domain object action | yes | Existing link/action resolvers | navigation, evidence/report viewers | header/action group | no | Canonical metadata only |
|
|
|
|
## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*
|
|
|
|
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|
|
|---|---|---|---|---|---|---|---|
|
|
| Operations hub list | Primary Decision Surface | Operator scans current and recent operations for attention states | operation label, scope, status/outcome, freshness, primary reason, one primary safe action | diagnostic references, technical context, raw context only if permitted | Primary because it is the central monitoring surface for run follow-up | Follows Operations hub target experience | Removes button sprawl and repeated raw-state inspection |
|
|
| OperationRun detail | Primary Decision Surface for a selected run | Operator decides whether to reconcile, retry safely, open related result, or inspect details | status/outcome, scope, reason, summary, evidence, high-risk warning, primary action | reconciliation evidence, result coverage, provider reason codes, raw context behind support diagnostics | Primary for individual run decision; not a general governance inbox | Keeps one run decidable without cross-page reconstruction | Makes diagnostics secondary and prevents unsafe restore actions |
|
|
|
|
## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)*
|
|
|
|
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|
|
|---|---|---|---|---|---|---|---|
|
|
| Operations hub list | operator-MSP, support-platform | Status, outcome, freshness, scope, primary reason, primary action | reason codes and affected families when compact | raw context not shown | action chosen by eligibility resolver | raw JSON, SQL/provider traces, queue payloads | Same resolver feeds primary action and disabled reason |
|
|
| OperationRun detail | operator-MSP, support-platform | What happened, why it matters, current state, safe next action, evidence summary | reason codes, coverage, verification, lifecycle reconciliation | raw context collapsed and capability-gated | one primary action in header/decision section | raw payloads, stack traces, secrets, signed URLs | Summary states blocker once; evidence sections add proof only |
|
|
|
|
## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*
|
|
|
|
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
| Operations hub list | List / Table / Monitoring | Monitoring-state page | Open run or invoke one safe primary action | Row click opens OperationRun detail | required | More/detail header | N/A - no destructive actions in this spec | `/admin/workspaces/{workspace}/operations` | tenantless OperationRun view link | workspace/environment chips | Operation runs / Operation run | status, outcome, freshness, reason, scope, safe action | none |
|
|
| OperationRun detail | Detail / Workbench | Shared-detail-family | Reconcile, Retry when safe, or Open related object | Detail page itself | N/A | Header More/action group | N/A - no destructive actions in this spec | existing Operations hub | tenantless OperationRun view link | workspace/environment detail | Operation run | status, outcome, reason, evidence, high-risk guard | none |
|
|
|
|
## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*
|
|
|
|
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|
|
|---|---|---|---|---|---|---|---|---|---|---|
|
|
| Operations hub list | Tenant/MSP operator | Decide which run needs attention and what can be safely done next | Monitoring list | What needs action right now? | operation, scope, status, outcome, freshness, reason, primary action | reason codes, raw context, internal metadata | lifecycle, outcome, freshness, reconciliation, risk | TenantPilot only for reconcile metadata; Microsoft tenant only for repo-real retry start seams that explicitly do so | View related, Reconcile, Retry when safe, View details | none |
|
|
| OperationRun detail | Tenant/MSP operator and support operator | Decide final follow-up for one run | Decision detail | What happened, why does it matter, and what is the safe next step? | summary, scope, status/outcome, evidence, high-risk guard, primary action | provider codes, dispatch metadata, raw context gated/collapsed | lifecycle, outcome, data completeness, verification, risk | TenantPilot only for reconcile/action metadata; retry follows existing start seam | View related, Reconcile, Retry when safe, View diagnostics | Restore retry/re-execute and force success are forbidden |
|
|
|
|
## Proportionality Review *(mandatory when structural complexity is introduced)*
|
|
|
|
- **New source of truth?**: no. Eligibility is derived from existing OperationRun, policy, capability, adapter registry, and related metadata.
|
|
- **New persisted entity/table/artifact?**: no. Audit/action metadata may be written into existing audit systems or existing OperationRun context only if no better existing seam exists.
|
|
- **New abstraction?**: yes, a bounded `OperationRunActionEligibility` resolver and possibly a small action DTO/presenter.
|
|
- **New enum/state/reason family?**: no new persisted status/outcome family. Derived action ids and disabled reason keys may be localized strings/constants only.
|
|
- **New cross-domain UI framework/taxonomy?**: no. This extends the existing Operations/OperationRun UX.
|
|
- **Current operator problem**: Action safety and primary-action choice are currently not a single testable decision. High-risk restore states must fail closed everywhere.
|
|
- **Existing structure is insufficient because**: `OperationUxPresenter` and link resolvers can summarize and navigate, while `AdapterRunReconciler` can reconcile, but no existing layer combines operation type, status/outcome, freshness, adapter support, related metadata, RBAC, and scope into one action contract.
|
|
- **Narrowest correct implementation**: One resolver that returns `primary_action`, `secondary_actions`, `disabled_actions`, `disabled_reasons`, and `attention_reason`; Filament pages consume that output.
|
|
- **Ownership cost**: Unit tests for action decisions, feature tests for server-side action enforcement, browser smoke for representative states, and localization maintenance.
|
|
- **Alternative intentionally rejected**: Scattered UI `if` blocks and page-local action conditions. They would be faster but unsafe because direct action execution, disabled reasons, and list/detail actions could diverge.
|
|
- **Release truth**: Current-release truth. It uses existing Specs 358-364 behavior and does not speculate about a full governance inbox.
|
|
|
|
### Compatibility posture
|
|
|
|
This feature assumes a pre-production environment. Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec. Canonical replacement is preferred over preservation.
|
|
|
|
## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*
|
|
|
|
- **Test purpose / classification**: Unit, Feature, Browser.
|
|
- **Validation lane(s)**: fast-feedback for resolver/presenter tests, confidence for Filament/action/RBAC/audit tests, browser for Operations UI smoke.
|
|
- **Why this classification and these lanes are sufficient**: The highest risk is decision logic and server-side action enforcement, so unit and feature tests prove behavior. Browser smoke proves default-visible decision hierarchy and raw leakage guard on the real Filament surface.
|
|
- **New or expanded test families**:
|
|
- `Spec365OperationRunActionEligibilityTest`
|
|
- `Spec365OperationRunPrimaryActionTest`
|
|
- `Spec365HighRiskActionGuardTest`
|
|
- `Spec365OperationRunSummaryPresenterTest`
|
|
- `Spec365OperationRunActionsTest`
|
|
- `Spec365OperationRunActionRbacTest`
|
|
- `Spec365OperationRunActionAuditTest`
|
|
- `Spec365OperationRunRelatedLinksTest`
|
|
- `Spec365OperationRunRegressionGateTest`
|
|
- `Spec365OperationsUiOperatorActionsSmokeTest`
|
|
- **Fixture / helper cost impact**: Reuse existing OperationRun factories/helpers. Add only explicit Spec365 fixtures for canonical context states; no broad seeding defaults.
|
|
- **Heavy-family visibility / justification**: Browser smoke is explicit and limited to the Operations UI representative matrix.
|
|
- **Special surface test profile**: monitoring-state-page and shared-detail-family.
|
|
- **Standard-native relief or required special coverage**: Special coverage required for one primary action, high-risk guard, collapsed/gated diagnostics, raw leakage absence, and action denial.
|
|
- **Reviewer handoff**: Reviewers must verify that action visibility and direct action execution use the same resolver/policy rules, and that unsupported retry paths fail closed.
|
|
- **Budget / baseline / trend impact**: No expected material budget drift. Browser smoke may add one bounded feature-specific file.
|
|
- **Escalation needed**: document-in-feature if generic retry or OperationRun acknowledge is deferred because no repo-safe seam exists; follow-up-spec only if a generic retry framework is desired later.
|
|
- **Active feature PR close-out entry**: Guardrail + Smoke Coverage.
|
|
- **Planned validation commands**:
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec365`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec364`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec363`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec362`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec361`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec360`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec359`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec358`
|
|
- `cd apps/platform && ./vendor/bin/pint --dirty`
|
|
- `git diff --check`
|
|
|
|
## User Scenarios & Testing *(mandatory)*
|
|
|
|
### User Story 1 - Decide the safe next action for an OperationRun (Priority: P1)
|
|
|
|
As an operator, I can scan the Operations hub or open a run detail and immediately understand status, outcome, freshness, scope, primary reason, and the one safe next action.
|
|
|
|
**Why this priority**: This is the core productization step that makes Specs 358-364 usable and customer-safe.
|
|
|
|
**Independent Test**: Seed representative OperationRuns and verify the resolver, table/detail presentation, one primary action, and raw leakage guard.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a reconciled review-compose run with canonical related metadata, **When** the operator views it, **Then** the UI shows "Review already available" and "View review" as the primary action without "Waiting for worker" or duplicate-key leakage.
|
|
2. **Given** a partial sync run, **When** the operator views it, **Then** the UI shows completed-with-partial-results copy and a details-oriented primary action rather than retry as the default.
|
|
3. **Given** a fresh queued run, **When** the operator views it, **Then** no retry or reconcile action is offered.
|
|
|
|
### User Story 2 - Safely reconcile eligible stale or failed runs (Priority: P1)
|
|
|
|
As an authorized operator, I can trigger reconciliation only when an existing adapter, canonical proof, RBAC, and scope checks make the action safe.
|
|
|
|
**Why this priority**: Reconciliation exists but must be explicitly actionable without bypassing `OperationRunService`.
|
|
|
|
**Independent Test**: Directly call the Filament action/service path for eligible and unsupported runs and verify success/denial/audit metadata.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** an eligible stale review-compose run with adapter proof and a user with the required capability, **When** the operator selects Reconcile, **Then** `AdapterRunReconciler` and `OperationRunService` write canonical reconciliation and action audit metadata.
|
|
2. **Given** an unsupported operation type, **When** the user opens or directly calls Reconcile, **Then** the action is absent or unavailable and direct execution is denied.
|
|
3. **Given** a cross-workspace OperationRun, **When** a user attempts Reconcile, **Then** server-side authorization denies access using existing workspace isolation semantics.
|
|
|
|
### User Story 3 - Prevent unsafe retry and force-success actions (Priority: P1)
|
|
|
|
As an operator, I never see retry, re-execute, force complete, or mark succeeded actions for high-risk restore/destructive operations.
|
|
|
|
**Why this priority**: Restore/high-risk safety from Spec 364 must remain visible and enforced in the UI.
|
|
|
|
**Independent Test**: Validate eligibility and browser state for restore verification-required, blocked, partial, and failed runs.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a failed `restore.execute` run, **When** the operator views it, **Then** no retry/re-execute/force-success action is visible and the disabled reason states that high-risk operations cannot be retried from this view.
|
|
2. **Given** a restore verification-required run, **When** the operator views it, **Then** the primary action is "View restore details" and verification proof is visible before technical diagnostics.
|
|
3. **Given** any operation, **When** the UI renders actions, **Then** no Force Complete or Mark Succeeded action exists.
|
|
|
|
### User Story 4 - Retry only repo-verifiable safe non-high-risk operations (Priority: P2)
|
|
|
|
As an operator, I can retry a safe non-high-risk operation only when the repository already has, or this spec implements, a bounded dispatch seam that creates a new OperationRun with canonical dispatch/retry metadata.
|
|
|
|
**Why this priority**: Retry is useful, but a generic re-execution layer is outside the safe minimum.
|
|
|
|
**Independent Test**: Use one repo-verified retry/resume/start seam and prove dispatch context, source/new run relationship, idempotency, and audit. If no seam exists for a family, verify disabled/deferred state.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a failed non-high-risk operation with a repo-verified retry seam and an authorized user, **When** the operator selects Retry, **Then** a new OperationRun is started with `context.dispatch`, source/new retry metadata, and audit/action metadata.
|
|
2. **Given** a failed non-high-risk operation without a repo-verified retry seam, **When** the operator views it, **Then** Retry is unavailable with a clear disabled reason.
|
|
3. **Given** a completed/succeeded run, **When** the operator views it, **Then** Retry is not offered.
|
|
|
|
### User Story 5 - Open related domain evidence safely (Priority: P2)
|
|
|
|
As an operator, I can open the related review, evidence snapshot, review pack/report, backup, sync, or restore detail when canonical related metadata and authorization allow it.
|
|
|
|
**Why this priority**: Operators need proof and domain context without raw context inspection.
|
|
|
|
**Independent Test**: Build canonical `context.reconciliation.related` cases and verify same-scope link resolution and cross-scope denial.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a reconciled evidence snapshot run with canonical related metadata, **When** the operator views it, **Then** the primary or secondary action opens the evidence detail using existing link policies.
|
|
2. **Given** related metadata that points outside the workspace/environment scope, **When** the operator views it, **Then** the related action is hidden or disabled and direct access is denied.
|
|
|
|
### User Story 6 - Audit and localize operator actions (Priority: P3)
|
|
|
|
As an auditor or support operator, I can trace reconcile/retry action attempts and outcomes without exposing secrets, and labels/summaries are available in EN/DE.
|
|
|
|
**Why this priority**: Actionability must be audit-visible and customer-safe.
|
|
|
|
**Independent Test**: Execute actions and assert audit/action metadata includes actor, action, run id, workspace, environment, previous/new status/outcome, reason code, timestamp, and related new run id when retry starts a run.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** an authorized reconcile action, **When** it succeeds, **Then** audit/action metadata contains the required fields and no secrets.
|
|
2. **Given** a denied action attempt, **When** the user lacks capability or scope, **Then** the attempt is denied and either audit-visible or safely logged without leaking secrets.
|
|
3. **Given** EN and DE locale files, **When** the UI renders action labels and summary states, **Then** labels and disabled reasons are localized.
|
|
|
|
## Functional Requirements *(mandatory)*
|
|
|
|
### FR-001 - OperationRun Action Eligibility Resolver
|
|
|
|
The system MUST provide a central, unit-testable eligibility layer for OperationRun operator actions.
|
|
|
|
Inputs MUST include:
|
|
|
|
- operation type
|
|
- status
|
|
- outcome
|
|
- freshness state
|
|
- reconciliation state
|
|
- dispatch context
|
|
- results context
|
|
- restore context
|
|
- risk classification
|
|
- user capabilities
|
|
- workspace/environment scope
|
|
- related metadata
|
|
|
|
Outputs MUST include:
|
|
|
|
- `primary_action`
|
|
- `secondary_actions`
|
|
- `disabled_actions`
|
|
- `disabled_reasons`
|
|
- `attention_reason`
|
|
|
|
Acceptance:
|
|
|
|
- No action visibility is decided through scattered Blade-only or page-local `if` logic.
|
|
- High-risk restore is not retryable.
|
|
- Completed/succeeded runs do not receive Retry.
|
|
- Unsupported runs do not receive Reconcile.
|
|
- Eligible stale runs may offer Reconcile when adapter proof exists.
|
|
- Missing capability and cross-scope state fail closed.
|
|
- Disabled reasons are visible in tooltip, modal description, or decision detail.
|
|
|
|
### FR-002 - Safe Reconcile Action
|
|
|
|
Reconcile MUST appear only when an existing adapter supports the operation, canonical proof is sufficient, RBAC and scope pass, and the action can route through existing reconciliation seams.
|
|
|
|
Acceptance:
|
|
|
|
- Reconcile uses `OperationRunReconciliationRegistry` / `AdapterRunReconciler`.
|
|
- Reconcile writes through `OperationRunService`.
|
|
- Reconcile is RBAC protected, scope-safe, and idempotent.
|
|
- Review-compose, review-pack/report artifact, evidence snapshot, sync/capture/backup, and restore reconciliation are limited to the proof already defined by Specs 359, 361, 362, and 364.
|
|
- Unsupported and cross-scope runs cannot be reconciled.
|
|
- Action audit/metadata is written without secrets.
|
|
|
|
### FR-003 - Safe Retry Action for non-high-risk Runs
|
|
|
|
Retry MUST be offered only for non-high-risk operations with a repo-verified safe retry/start seam.
|
|
|
|
Candidate families MAY include review compose, evidence snapshot generation, review-pack/report generation, inventory/sync/capture, and backup capture only if implementation proves a safe, idempotent dispatch seam exists.
|
|
|
|
Retry MUST NOT be implemented for:
|
|
|
|
- `restore.execute`
|
|
- tenant mutation
|
|
- destructive mutation
|
|
- high-risk operation
|
|
- unknown operation
|
|
- completed/succeeded run
|
|
- unsupported operation without a safe retry seam
|
|
|
|
Acceptance:
|
|
|
|
- Retry eligibility is resolver-controlled.
|
|
- Retry starts a new OperationRun or uses an existing retry/resume seam with canonical `context.dispatch`.
|
|
- Source/new retry metadata is visible.
|
|
- Retry is audit-visible.
|
|
- High-risk restore shows an unavailable reason instead of a retry action.
|
|
- Unsupported retry paths fail closed and may be documented as deferred in `tasks.md`.
|
|
|
|
### FR-004 - No Force Complete Action
|
|
|
|
This spec MUST NOT introduce Force Complete, Mark Succeeded, Ignore Error and Complete, Manually Mark Restore Successful, Delete, Purge, or equivalent success-forcing actions.
|
|
|
|
Acceptance:
|
|
|
|
- No force-success action exists in action code, labels, localization, or tests.
|
|
- Restore/high-risk tests assert absence of force-success and retry/re-execute actions.
|
|
|
|
### FR-005 - Acknowledge / Mark Reviewed Action
|
|
|
|
Acknowledge is optional and MUST be implemented only if a clean existing audit/note seam exists.
|
|
|
|
Acceptance if implemented:
|
|
|
|
- Does not change `status` or `outcome`.
|
|
- Writes audit-visible note/action metadata.
|
|
- Is RBAC protected.
|
|
- UI distinguishes reviewed from resolved/succeeded.
|
|
|
|
If no clean seam exists, implementation MUST document deferral in `tasks.md` and not implement a local substitute.
|
|
|
|
### FR-006 - Open Related Domain Object Action
|
|
|
|
The system MUST offer safe related-object actions when canonical metadata supports them.
|
|
|
|
Sources:
|
|
|
|
- `context.reconciliation.related`
|
|
- other canonical related metadata already exposed by OperationRun helpers
|
|
- existing `OperationRunLinks` / `RelatedNavigationResolver` paths
|
|
|
|
Acceptance:
|
|
|
|
- Reconciled review opens Review.
|
|
- Evidence snapshot opens Evidence.
|
|
- Review-pack/report artifact opens the existing safe report/review-pack seam when canonical metadata exists.
|
|
- Restore opens restore details when the existing route/policy resolves same-scope proof.
|
|
- Cross-scope related objects are hidden/disabled and direct access is denied.
|
|
- No signed URL or raw payload is read from context.
|
|
|
|
### FR-007 - OperationRun Details Decision Layout
|
|
|
|
OperationRun detail MUST be decision-first:
|
|
|
|
- Header: operation label, status/outcome, scope, primary reason, primary action.
|
|
- Summary: what happened, why it matters, current state, next safe action.
|
|
- Evidence: reconciliation proof, result coverage, restore verification, provider reason codes where operator-safe.
|
|
- Details: dispatch metadata, duration, technical diagnostics.
|
|
- Raw context: internal/support capability only, collapsed by default.
|
|
|
|
Acceptance:
|
|
|
|
- Raw JSON is not the default experience.
|
|
- High-risk warnings are visible.
|
|
- Technical details are progressively disclosed.
|
|
- Customer-readable paths remain calm and free of raw implementation detail.
|
|
|
|
### FR-008 - Outcome-Specific Summary Cards
|
|
|
|
The UI/presenter MUST cover the main OperationRun outcome families:
|
|
|
|
- Queued fresh
|
|
- Queued longer than expected
|
|
- Running
|
|
- Running longer than expected
|
|
- Reconciled from adapter
|
|
- Report/review-pack already available
|
|
- Evidence snapshot already available
|
|
- Sync completed with partial results
|
|
- Sync blocked
|
|
- Backup completed with partial results
|
|
- Backup blocked
|
|
- Restore verification required
|
|
- Restore completed with partial results
|
|
- Restore blocked
|
|
- Failed by lifecycle reconciliation
|
|
|
|
Acceptance:
|
|
|
|
- Each family has EN/DE copy.
|
|
- Summary cards use presenter/contract output, not Blade special cases.
|
|
- Browser smoke covers representative states.
|
|
- Customer-facing defaults do not show raw technical errors.
|
|
|
|
### FR-009 - High-Risk Guard in UI
|
|
|
|
High-risk operations MUST be visually and functionally protected.
|
|
|
|
Acceptance:
|
|
|
|
- Restore, tenant mutation, destructive mutation, unknown/high-risk operations have no Retry/Re-execute/Force Complete primary action.
|
|
- Verification-required state emphasizes verification proof and "View restore details".
|
|
- Disabled reasons are visible.
|
|
- Browser and feature tests assert action absence/disabled state.
|
|
|
|
### FR-010 - RBAC / Capability Enforcement
|
|
|
|
All actions MUST be capability-first and server-side enforced.
|
|
|
|
Acceptance:
|
|
|
|
- Use existing policies, `OperationRunCapabilityResolver`, and `Capabilities` constants first.
|
|
- Do not use raw capability strings or role-string checks in feature code.
|
|
- If new capability constants are required, add the smallest number and test positive/negative behavior.
|
|
- User without capability cannot see or execute the action.
|
|
- Direct action execution without capability fails.
|
|
- Cross-workspace and cross-environment execution fails.
|
|
|
|
### FR-011 - Auditability for Operator Actions
|
|
|
|
Each operator action and relevant denied attempt MUST be audit-visible or safely logged.
|
|
|
|
Required fields:
|
|
|
|
- action
|
|
- operation_run_id
|
|
- workspace_id
|
|
- managed_environment_id when present
|
|
- actor_id
|
|
- previous status/outcome
|
|
- resulting status/outcome
|
|
- reason_code
|
|
- timestamp
|
|
- related new operation_run_id when retry starts one
|
|
|
|
Acceptance:
|
|
|
|
- Reconcile action is audit-visible.
|
|
- Retry action is audit-visible when implemented.
|
|
- Acknowledge action is audit-visible if implemented.
|
|
- Failed/denied action attempts are audit-visible or safely logged.
|
|
- No secrets, access tokens, raw payloads, or signed URLs are stored.
|
|
|
|
### FR-012 - Retry Metadata Contract
|
|
|
|
When retry starts a run, the source and new run relationship MUST be visible using canonical context/action metadata.
|
|
|
|
Example:
|
|
|
|
```json
|
|
{
|
|
"retry": {
|
|
"source_operation_run_id": 123,
|
|
"retry_operation_run_id": 124,
|
|
"requested_by_user_id": 5,
|
|
"requested_at": "2026-06-06T16:00:00+02:00",
|
|
"reason_code": "operator_retry_requested"
|
|
}
|
|
}
|
|
```
|
|
|
|
Acceptance:
|
|
|
|
- Old and new runs link to each other or one canonical direction is documented.
|
|
- New run has `context.dispatch`.
|
|
- UI can show "Retry started".
|
|
- No uncontrolled retry loops.
|
|
- High-risk runs do not receive retry metadata.
|
|
|
|
### FR-013 - Regression Gate Matrix
|
|
|
|
This spec MUST define and cover a final OperationRun state matrix.
|
|
|
|
Minimum matrix:
|
|
|
|
| Family | State |
|
|
|---|---|
|
|
| Queue | fresh queued |
|
|
| Queue | stale queued |
|
|
| Queue | stale running |
|
|
| Reconciliation | review already available |
|
|
| Reconciliation | report/review-pack already available |
|
|
| Reconciliation | evidence snapshot already available |
|
|
| Sync | partial |
|
|
| Sync | blocked |
|
|
| Backup | partial |
|
|
| Backup | blocked |
|
|
| Restore | verification required |
|
|
| Restore | partial |
|
|
| Restore | blocked |
|
|
| Restore | failed |
|
|
| RBAC | action denied |
|
|
| Scope | cross-workspace denied |
|
|
|
|
Acceptance:
|
|
|
|
- Matrix exists at `artifacts/spec365-regression-gate-matrix.md`.
|
|
- Browser smoke covers representative states.
|
|
- Feature tests cover action eligibility/enforcement.
|
|
- Spec 358-364 regressions remain green.
|
|
|
|
### FR-014 - No Raw Technical Leakage
|
|
|
|
Customer-readable and shared default surfaces MUST NOT show raw technical details.
|
|
|
|
Forbidden by default:
|
|
|
|
- `SQLSTATE`
|
|
- `Guzzle`
|
|
- stack trace
|
|
- Graph raw payload
|
|
- access token
|
|
- client secret
|
|
- queue payload
|
|
- serialized job
|
|
- internal constraint names such as `environment_reviews_fingerprint_mutable_unique`
|
|
|
|
Acceptance:
|
|
|
|
- Browser tests assert absence of forbidden strings.
|
|
- Operator-safe reason codes may appear in diagnostics.
|
|
- Raw context JSON is collapsed and capability-gated.
|
|
|
|
### FR-015 - No New Top-Level Sprawl
|
|
|
|
This spec MUST use existing Operations and related domain surfaces.
|
|
|
|
Acceptance:
|
|
|
|
- No new top-level page for stale, retry, reconcile, partial sync, restore verification, or similar states.
|
|
- Operations remains the central run surface.
|
|
- Related domain pages are linked.
|
|
- Navigation remains calm.
|
|
|
|
### FR-016 - Mutation Scope Disclosure
|
|
|
|
Every state-changing operator action MUST communicate before execution whether it affects TenantPilot only, the Microsoft tenant, or simulation only.
|
|
|
|
Acceptance:
|
|
|
|
- Reconcile copy/confirmation states that reconciliation writes TenantPilot OperationRun/action metadata only, unless an adapter/service explicitly performs a broader mutation that this spec permits.
|
|
- Retry copy/confirmation states the scope of the underlying safe retry/start seam before execution.
|
|
- High-risk or unknown mutation scope fails closed and does not expose the action.
|
|
- Feature or browser coverage proves the mutation-scope text is visible near the action, helper text, preview, or confirmation.
|
|
|
|
## Canonical Cutover Rules
|
|
|
|
- New UI/action code MUST read canonical OperationRun truth structures.
|
|
- New tests MUST be canonical-only.
|
|
- New action writes MUST use canonical audit/action metadata.
|
|
- Do not add new alias/fallback paths in Blade or presenters.
|
|
- Existing compatibility helpers may remain untouched, but Spec 365 code must not depend on legacy context paths.
|
|
|
|
## Action Eligibility Contract
|
|
|
|
The resolver SHOULD use a repo-conform name such as `OperationRunActionEligibility`.
|
|
|
|
It SHOULD expose derived actions such as:
|
|
|
|
- `view_related`
|
|
- `reconcile`
|
|
- `retry`
|
|
- `view_details`
|
|
- `view_diagnostics`
|
|
- `acknowledge` only if a clean existing seam exists
|
|
|
|
It MUST always treat the following as unavailable:
|
|
|
|
- `force_complete`
|
|
- `mark_succeeded`
|
|
- `delete`
|
|
- `purge`
|
|
- `retry_high_risk`
|
|
- `reexecute_restore`
|
|
|
|
## Localization Requirements
|
|
|
|
Add EN/DE localization keys for:
|
|
|
|
- action labels
|
|
- action descriptions
|
|
- success/error/unavailable messages
|
|
- disabled reasons
|
|
- high-risk guard messages
|
|
- outcome summary titles/descriptions
|
|
- audit/action metadata labels when surfaced
|
|
|
|
Example key families:
|
|
|
|
- `operations.actions.reconcile.*`
|
|
- `operations.actions.retry.*`
|
|
- `operations.actions.view_related.*`
|
|
- `operations.actions.disabled.*`
|
|
- `operations.summary.restore_verification_required.*`
|
|
- `operations.summary.partial.*`
|
|
|
|
## Nonfunctional Requirements
|
|
|
|
- **NFR-001 - Decision-first UX**: Every OperationRun detail answers what happened, why it matters, safe next action, and evidence.
|
|
- **NFR-002 - Fail closed**: If eligibility is uncertain, do not offer the action.
|
|
- **NFR-003 - No high-risk retry**: Restore/tenant mutation/destructive mutation are not retryable in this spec.
|
|
- **NFR-004 - No destructive actions**: No delete/purge/force-success actions.
|
|
- **NFR-005 - Idempotency**: Reconcile and retry actions must be safe against double execution. Buttons must be disabled/debounced while executing.
|
|
- **NFR-006 - Auditability**: Actions and relevant attempts must be traceable.
|
|
- **NFR-007 - Capability-first RBAC**: UI hiding is never the only control.
|
|
- **NFR-008 - Workspace/environment isolation**: No cross-scope action.
|
|
- **NFR-009 - Livewire v4 compatibility**: No Livewire v3 APIs such as `emit`, `emitTo`, or `dispatchBrowserEvent`.
|
|
- **NFR-010 - No asset changes**: No Filament/Tailwind/build asset changes unless repo verification proves they are required.
|
|
- **NFR-011 - Explicit mutation scope**: State-changing actions must show TenantPilot-only, Microsoft-tenant, or simulation-only scope before execution.
|
|
|
|
## Entities / Derived Contracts *(include if feature involves data)*
|
|
|
|
No new persisted entity is required.
|
|
|
|
Derived contracts:
|
|
|
|
- **OperationRunActionEligibilityResult**: primary action, secondary actions, disabled actions, disabled reasons, attention reason, diagnostics visibility.
|
|
- **OperationRunOperatorActionMetadata**: audit/action metadata written through existing audit or OperationRun context only when needed.
|
|
- **OperationRunDecisionSummary**: presenter output for default-visible summary/evidence/high-risk state.
|
|
|
|
Existing canonical context keys in scope:
|
|
|
|
- `context.dispatch`
|
|
- `context.reconciliation`
|
|
- `context.results`
|
|
- `context.coverage`
|
|
- `context.restore`
|
|
- `context.operator_actions` only if existing audit seam is insufficient and implementation records a bounded decision.
|
|
|
|
## Assumptions
|
|
|
|
- Filament v5.2.1 with Livewire v4.1.4 is the target UI stack.
|
|
- Laravel panel providers remain registered in `apps/platform/bootstrap/providers.php`; this spec does not add a panel provider.
|
|
- `OperationRunResource` remains not globally searchable unless a future implementation explicitly adds a View/Edit page compliant global-search contract. Current prep assumes global search stays disabled for OperationRun resource.
|
|
- Reconcile uses existing adapter registry and `OperationRunService`.
|
|
- Generic retry is not assumed. It is available only per operation family when implementation verifies or creates a safe, idempotent, audited start seam.
|
|
- OperationRun acknowledge is deferred unless implementation verifies a clean existing audit/note seam.
|
|
|
|
## Out of Scope
|
|
|
|
- New adapter framework or adapter families.
|
|
- New report/evidence reconciliation.
|
|
- New sync/backup/restore semantics.
|
|
- Restore retry/re-execute.
|
|
- Generic retry framework.
|
|
- Force complete, mark succeeded, delete, purge, cancel.
|
|
- Full decision-based governance inbox.
|
|
- New notification routing architecture.
|
|
- New customer review workspace.
|
|
- New top-level Operations pages.
|
|
- New assets or frontend build strategy.
|
|
|
|
## Success Metrics *(mandatory)*
|
|
|
|
- **SM-001**: For every covered matrix state, resolver returns at most one primary action.
|
|
- **SM-002**: High-risk restore/destructive operations expose zero retry/re-execute/force-success actions in unit, feature, and browser tests.
|
|
- **SM-003**: Eligible reconcile actions execute only through the existing reconciliation registry and `OperationRunService`.
|
|
- **SM-004**: Direct action execution without capability or scope fails server-side.
|
|
- **SM-005**: Browser smoke proves no raw technical leakage in default Operations UI.
|
|
- **SM-006**: Spec 358-364 regression tests remain green in the planned validation lane.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- **AC-001**: Action eligibility resolver exists.
|
|
- **AC-002**: Each relevant run state has at most one primary action.
|
|
- **AC-003**: Reconcile is only available when adapter, proof, RBAC, and scope pass.
|
|
- **AC-004**: Retry is only available for safe non-high-risk operations with a repo-verified seam.
|
|
- **AC-005**: Restore/high-risk operations are not retryable.
|
|
- **AC-006**: No Force Complete or Mark Succeeded action exists.
|
|
- **AC-007**: Related domain links use canonical metadata and existing link/policy seams.
|
|
- **AC-008**: RBAC is enforced server-side.
|
|
- **AC-009**: Scope isolation is enforced.
|
|
- **AC-010**: Operator actions are audit-visible.
|
|
- **AC-011**: Operation detail is decision-first.
|
|
- **AC-012**: Raw technical leakage is absent by default.
|
|
- **AC-013**: Regression gate matrix exists and is test-covered.
|
|
- **AC-014**: Specs 358-364 remain stable.
|
|
- **AC-015**: State-changing operator actions disclose mutation scope before execution.
|
|
|
|
## Filament v5 Output Contract
|
|
|
|
1. **Livewire v4.0+ compliance**: Required. This project uses Livewire v4.1.4. No Livewire v3 APIs.
|
|
2. **Provider registration location**: No panel provider changes. If any future provider change becomes necessary, Laravel 12 panel providers belong in `apps/platform/bootstrap/providers.php`.
|
|
3. **Globally searchable resources**: `OperationRunResource` currently disables global search. If changed later, it must have an Edit or View page and record title contract.
|
|
4. **Destructive actions**: This spec adds no destructive actions. Reconcile/retry are state-changing and must execute through `Action::make(...)->action(...)`, with confirmation where risk or current Filament action rules require it, explicit mutation-scope copy, plus server-side authorization and audit.
|
|
5. **Asset strategy**: No new assets. Deploy process only needs `cd apps/platform && php artisan filament:assets` if implementation registers Filament assets, which this spec does not plan.
|
|
6. **Testing plan**: Unit tests for resolver/primary action/high-risk guard/presenter; feature tests for actions/RBAC/scope/audit/related links; browser smoke for Operations list/detail representative states and raw leakage guard.
|