TenantAtlas/specs/172-deferred-operator-surfaces-retrofit/research.md
ahmido 671abbed53 feat: retrofit deferred operator surfaces (#203)
## Summary
- retrofit the tenant detail recent-operations and verification surfaces to keep one clear primary inspect path per state
- keep onboarding workflow actions on the wizard step while moving previous-run and advanced monitoring links into diagnostics-only technical details
- add focused spec 172 design artifacts, feature coverage, and a dedicated browser smoke test for the deferred operator surface retrofit

## Testing
- `vendor/bin/sail artisan test --compact tests/Browser/Spec172DeferredOperatorSurfacesSmokeTest.php tests/Browser/OnboardingDraftRefreshTest.php tests/Browser/OnboardingDraftVerificationResumeTest.php`

## Notes
- base branch: `dev`
- branch head: `172-deferred-operator-surfaces-retrofit`
- browser smoke pack passed locally after the final changes

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #203
2026-04-02 09:22:44 +00:00

6.1 KiB

Research: Deferred Operator Surfaces Retrofit

Decision 1: Treat the tenant detail view, not /admin/t/{tenant}, as the primary tenant-plane retrofit surface

  • Decision: Scope the tenant-plane retrofit to the embedded widgets on ViewTenant and keep the table-based recent-operations widget on /admin/t/{tenant} out of scope.
  • Rationale: Repo inspection shows the deferred embedded operation surfaces live on app/Filament/Resources/TenantResource/Pages/ViewTenant.php, while app/Filament/Pages/TenantDashboard.php already uses a declaration-backed table widget with row-click inspection. Mixing both into one slice would blur two different action-surface models.
  • Alternatives considered: Retrofit the tenant dashboard table widget in the same spec. Rejected because it is already governed as a table surface and would expand the slice beyond the deferred embedded-surface problem.

Decision 2: Keep /admin/operations and /admin/operations/{run} as the canonical inspect destinations

  • Decision: Reuse the existing admin-plane operations collection and detail routes for embedded drill-ins rather than creating tenant-scoped operations routes or a parallel tenant viewer.
  • Rationale: OperationRunLinks already centralizes these destinations, and the spec explicitly forbids route or lifecycle changes. The missing behavior is scope-truth before navigation, not a missing destination.
  • Alternatives considered: Add tenant-scoped operations routes or query-prefiltered viewers. Rejected because that would introduce new routing, new navigation semantics, and more RBAC surface area than this retrofit requires.

Decision 3: Use a state-driven CTA hierarchy instead of adding new embedded controls

  • Decision: Model each embedded surface around a small CTA matrix: no run means one workflow-start action, an existing run means one primary inspect action, and any broader collection or monitoring links become explicitly secondary.
  • Rationale: The current drift comes from equal-weight CTAs such as View all operations alongside per-row Open operation or inline Start verification beside an existing Open operation. A state matrix solves that with minimal code churn.
  • Alternatives considered: Keep all current links and only rename them. Rejected because naming alone would not remove the competing-action problem described by Spec 172.

Decision 4: Let the owning page or wizard keep rerun controls while embedded surfaces focus on inspection

  • Decision: On tenant detail, the existing page-level Verify configuration header action remains the rerun/start path when a verification run already exists, while the embedded widget focuses on inspecting the current run. On onboarding, the step-level workflow controls (Start verification or Refresh) remain the next-step controls, while report/technical-details links stay inspection-oriented.
  • Rationale: The rerun affordance already exists on the owning surfaces. Reusing it avoids adding a second equal-weight CTA inside the embedded report widgets.
  • Alternatives considered: Keep rerun/start controls inline inside every embedded surface state. Rejected because it produces the same CTA competition the feature is meant to eliminate.
  • Decision: Retain any broader monitoring/admin operation link only in low-emphasis technical-details or diagnostics areas, and only when the operator can access that destination.
  • Rationale: The technical-details modal already has an explicit advanced-monitoring affordance. Keeping it secondary preserves operator clarity without removing legitimate escalation paths for power users.
  • Alternatives considered: Show advanced monitoring links beside every primary inspect CTA. Rejected because it weakens the single-primary-action rule and increases scope ambiguity.

Decision 6: Narrow governance through focused tests and baseline-exemption notes, not through a new widget framework

  • Decision: Reuse the existing ActionSurfaceExemptions and ActionSurfaceContractTest model, tighten the relevant exemption wording if needed, and add focused widget/onboarding coverage instead of introducing widget-specific actionSurfaceDeclaration() plumbing.
  • Rationale: Embedded widgets and report partials do not fit the existing table/page declaration model cleanly, and the codebase already recognizes that ManagedTenantOnboardingWizard is covered through dedicated conformance tests.
  • Alternatives considered: Add a new generic embedded-surface declaration framework. Rejected because one concrete retrofit does not justify a new abstraction under ABSTR-001 and BLOAT-001.

Decision 7: Verify behavior with focused Pest and Livewire tests instead of broad string guards

  • Decision: Extend the existing widget and onboarding feature tests to assert CTA count, scope cues, and advanced-link visibility directly on rendered surfaces.
  • Rationale: The business truth here is UI hierarchy and scope behavior, not just string presence. Focused rendered-surface tests are more precise than grep-style bans and align with TEST-TRUTH-001.
  • Alternatives considered: Add a repo-wide architecture or grep-style rule forbidding specific link combinations. Rejected because valid out-of-scope surfaces and diagnostics would require an exception list that encodes the same complexity this slice is avoiding.

Decision 8: Make scope explicit through placement and nearby copy rather than scope-first labels

  • Decision: Any remaining collection drill-in from a tenant-detail surface should communicate broader admin scope through placement or helper text, not by inventing scope-first primary labels.
  • Rationale: UI-NAMING-001 forbids making scope the primary verb-object label. The operator still needs to understand when a link leaves the tenant-local shell, but that should come from context and secondary explanation.
  • Alternatives considered: Rename the main CTA to Open admin operations. Rejected because it over-rotates toward implementation language and conflicts with the repo's operator-facing naming rules.