TenantAtlas/specs/192-record-header-discipline/research.md
ahmido 9f6985291e feat: implement spec 192 record page header discipline (#226)
## Summary
- implement Spec 192 across the targeted Filament record, detail, and edit pages with explicit action-surface inventory and guard coverage
- add the focused Spec 192 browser smoke, feature tests, and spec artifacts under `specs/192-record-header-discipline`
- improve unhandled promise rejection diagnostics by correlating 419s to the underlying Livewire request URL
- disable panel-wide database notification polling on the admin, tenant, and system panels and cover the mitigation with focused tests

## Validation
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/DatabaseNotificationsPollingTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/DatabaseNotificationsPollingTest.php tests/Feature/Filament/UnhandledRejectionLoggerAssetTest.php tests/Feature/Filament/FilamentNotificationsAssetsTest.php tests/Feature/Workspaces/ManagedTenantsLivewireUpdateTest.php tests/Feature/Filament/AdminSmokeTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- manual integrated-browser verification of the Spec 192 surfaces and the notification-polling mitigation

## Notes
- Livewire v4 / Filament v5 compliance remains unchanged.
- Provider registration stays in `bootstrap/providers.php`.
- No Global Search behavior was expanded.
- No destructive action confirmation semantics were relaxed.
- The full test suite was not run in this PR.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #226
2026-04-11 21:20:41 +00:00

6.2 KiB

Research: Record Page Header Discipline & Contextual Navigation

Rationale

The codebase already has the right implementation primitives for this cleanup: page-private action builders, UiEnforcement for per-action RBAC handling, ActionGroup for secondary grouping, and RelatedNavigationResolver for contextual navigation. The spec needs discipline and regression protection, not a new registry, interface, or placement engine.

Alternatives considered

  • Add a HeaderActionResolver or HeaderActionRegistry: rejected because the repo already has several coordination abstractions and this feature does not justify another one.
  • Add an ActionPlacement enum or interface hierarchy: rejected because the placement decisions remain page- and state-sensitive and would ossify too early.

Decision: Keep contextual navigation close to the relevant content instead of leaving it in the flat header lane

Rationale

Several touched pages already use related-navigation helpers or related-context rendering. The narrowest fix is to move pure navigation out of equal-weight header placement and into summary, field, badge, status, or related-context placement outside the header, using the existing related-navigation patterns rather than inventing new local UI concepts.

Alternatives considered

  • Keep Open ... and View ... actions in the primary header but restyle them: rejected because the problem is semantic weight, not only button color.
  • Remove related navigation entirely: rejected because the navigation is still useful; it just belongs closer to its context.

Decision: Treat the tenant admin resource view as an explicit workflow-heavy special-type exception

Rationale

ViewTenant is not a simple record detail. It already acts as a workflow hub for verification, RBAC refresh, onboarding recovery, provider entry points, and lifecycle actions. The correct move is to keep it grouped and internally ordered, document it as a special type, and prevent it from silently bypassing the standard-page rule.

Alternatives considered

  • Force ViewTenant into the same single-next-step shape as simple record pages: rejected because it would misrepresent a multi-purpose operational hub.
  • Leave ViewTenant undocumented as an exception: rejected because silent exceptions cause future drift and inconsistent review standards.

Decision: Use existing calm pages as reference patterns and preserve no-op surfaces

Rationale

The repo already contains pages that model the intended calmness well enough for this spec: ViewBackupSet, ViewBaselineSnapshot, ViewReviewPack, ViewAlertDestination, ViewPolicyVersion, and ViewWorkspace. These pages should be preserved unless a minor alignment issue is found, because the goal is discipline, not cosmetic uniformity.

Alternatives considered

  • Rebuild every in-scope page to the same visible pattern: rejected because it would create churn without additional operator value.
  • Ignore no-op pages and only document the problem pages: rejected because the spec requires an explicit project-wide classification matrix.

Decision: Drive standard-page remediation with page-local state and existing action methods

Rationale

The heaviest remediations, especially ViewBaselineProfile and ViewTenantReview, already express their action logic through page-private methods or explicit action blocks. The cleanest implementation is to keep that local state logic and only change placement and grouping. This preserves existing authorization, notifications, run links, and confirmations.

Alternatives considered

  • Rebuild header logic around a shared presenter object: rejected because the same state machine is not yet shared across enough pages to justify a new layer.
  • Push all actions into a single generic More dropdown: rejected because the spec requires structured grouping and a visible next step, not a junk drawer.

Decision: Build regression protection on top of the existing action-surface guard and focused page tests

Rationale

The repo already has ActionSurfaceValidator, ActionSurfaceContractTest, ActionSurfaceValidatorTest, FilamentTableStandardsGuardTest, focused Livewire page tests, and browser smoke coverage. The narrowest regression strategy is to extend those existing layers with Spec 192 expectations: a whitelisted header-discipline guard, page-level visibility assertions on the remediated screens, and one browser smoke path for visible hierarchy.

Alternatives considered

  • Add a new standalone framework for header-discipline validation: rejected because the existing ActionSurfaceValidator and guard test style already provide the right enforcement hook.
  • Rely on manual review only: rejected because header-sprawl regressions are exactly the kind of drift CI should catch.

Decision: Keep testing layered but lightweight

Rationale

Three test layers are enough for this feature:

  • static or discovery-based guard coverage for the classification and header-discipline contract,
  • focused Livewire/Pest page tests for state-driven primary-action visibility and grouped-secondary behavior,
  • one browser smoke suite proving the visible hierarchy on remediated pages, the explicit special-type exception, and a no-regression baseline over the compliant reference set.

This matches existing repo patterns and avoids over-testing presentation indirection.

Alternatives considered

  • Browser-test every permutation of every page: rejected because it would be expensive and redundant with feature tests.
  • Add only guard tests: rejected because page-level state transitions still need runtime assertions.

Decision: No new asset or provider work is needed

Rationale

The cleanup stays entirely within existing Filament v5 header action surfaces. No panel providers, custom assets, or lazy-loaded scripts are required. Existing deployment handling of cd apps/platform && php artisan filament:assets remains unchanged.

Alternatives considered

  • Introduce custom header components or new assets for grouped actions: rejected because native Filament header actions and ActionGroup already satisfy the need.