TenantAtlas/specs/334-nested-filament-context-contract-hardening/tasks.md
ahmido f967db7983 Spec 334: harden nested Filament Livewire context contract (#395)
## Summary
- harden nested Filament and Livewire tenant-context handling across the backup schedule operation runs relation manager, managed-environment triage arrival continuity, the backup set policy picker table, and the Operate Hub shell
- add architecture, feature, and browser coverage for nested Filament tenant-context continuity and restore-run resource behavior
- add the Spec 334 artifacts (`spec.md`, `plan.md`, `tasks.md`, and the requirements checklist)

## Testing
- Not run as part of this commit/push/PR workflow

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #395
2026-05-24 21:33:19 +00:00

7.1 KiB

Tasks: Spec 334 - Nested Filament / Livewire Context Contract Hardening

  • Input: specs/334-nested-filament-context-contract-hardening/spec.md, specs/334-nested-filament-context-contract-hardening/plan.md
  • Prerequisites: spec.md, plan.md

Tests: Required. This is runtime-hardening for nested operator surfaces with authorization/scope impact.

Test Governance Checklist

  • Lane assignment is explicit and is the narrowest sufficient proof for the changed behavior.
  • New tests stay in the smallest honest family (Feature/Livewire + one architecture guard; browser smoke only for the two user-visible regressions).
  • New helpers/factories/seeds/context defaults stay cheap by default.
  • Planned validation commands cover the change without pulling in unrelated lane cost.
  • Any deviation resolves as document-in-feature, follow-up-spec, or reject-or-split.

Phase 1: Preparation And Repo Truth

Purpose: Confirm repo truth and capture the current failure paths before touching runtime code.

  • T001 Re-read spec.md, plan.md, and this tasks.md.
  • T002 Confirm working tree intent and record baseline commit (git status, git log -1).
  • T003 Verify confirmed scope file paths exist and inspect current context usage:
    • apps/platform/app/Livewire/BackupSetPolicyPickerTable.php
    • apps/platform/app/Filament/Resources/RestoreRunResource.php
    • apps/platform/app/Filament/Concerns/ResolvesPanelTenantContext.php
    • apps/platform/app/Filament/Resources/BackupScheduleResource/RelationManagers/BackupScheduleOperationRunsRelationManager.php
    • apps/platform/app/Filament/Widgets/ManagedEnvironment/ManagedEnvironmentTriageArrivalContinuity.php
    • apps/platform/app/Support/OperateHub/OperateHubShell.php
    • apps/platform/app/Support/Workspaces/WorkspaceContext.php
  • T004 Capture the current Add Policies modal failure path (tenantless modal → checkbox column hidden) and record the exact call chain and where tenant/context is read.
    • Captured via regression: apps/platform/tests/Feature/Filament/BackupSetPolicyPickerTableTest.php and browser smoke apps/platform/tests/Browser/Spec334NestedFilamentContextContractSmokeTest.php.
  • T005 Capture the current Restore Run Create wizard failure path (Livewire update request without route params → tenant resolver throws) and record the exact call chain and closure(s) involved.
    • Captured via regression: apps/platform/tests/Feature/Filament/RestoreRunResourceLivewireTenantContextTest.php (real Livewire update payload) + browser smoke apps/platform/tests/Browser/Spec334NestedFilamentContextContractSmokeTest.php.
  • T006 Decide whether any shared helper is justified (≥2 confirmed consumers). If not, keep fixes local to each surface + the existing shared seam.
    • No new helper introduced (ABSTR-001). Shared seam hardening applied in apps/platform/app/Support/OperateHub/OperateHubShell.php.

Phase 2: Guardrails And Regression Tests (before refactor)

Purpose: Lock “fail-closed and scoped” behavior and block unsafe tenant switching patterns before implementation refactors.

  • T007 Add an architecture guard test: apps/platform/tests/Architecture/FilamentTenantContextContractTest.php.
    • Detect and fail on unsafe Filament::setTenant($model->...) patterns in nested surfaces without explicit allowlist.
    • Keep an explicit allowlist limited to infrastructure-only context selection locations.
  • T008 Add a regression test covering Add Policies picker behavior when ambient tenant is null (authorized user still sees row selection and can select).
  • T009 Add a regression test covering Restore Run Create wizard Livewire update lifecycle (no crash when route params are missing; options are scoped).
  • T010 Add a regression test for BackupSchedule operation runs relation manager scope (owner record scopes query; ambient tenant missing/wrong does not broaden).
  • T011 Add a regression test for the triage widget context (record context preferred; ambient tenant is fallback; missing context fails closed).

Phase 3: Implement Nested Context Contract (confirmed surfaces only)

Purpose: Apply the contract to the confirmed high-risk surfaces without a broad tenancy rewrite.

  • T012 Harden apps/platform/app/Livewire/BackupSetPolicyPickerTable.php:
    • Resolve context from validated BackupSet ownership (workspace + managed environment).
    • Scope table query by resolved environment.
    • Re-resolve and re-authorize at mutation time (bulk action).
    • Never silently override mismatched ambient tenant.
  • T013 Harden apps/platform/app/Filament/Resources/RestoreRunResource.php:
    • Ensure option closures used during Livewire updates can resolve validated environment context without route params.
    • Livewire update context recovery is implemented in the shared seam: apps/platform/app/Support/OperateHub/OperateHubShell.php (validated referer path candidate for /livewire-*/update requests).
    • Referer is treated as a candidate only; access is still validated via workspace + membership + operability checks.
  • T014 Harden apps/platform/app/Filament/Concerns/ResolvesPanelTenantContext.php only if the seam is shared and the fix is not restore-specific.
    • No change required (the shared seam hardening in OperateHubShell unblocks the failing lifecycle).
  • T015 Harden apps/platform/app/Filament/Resources/BackupScheduleResource/RelationManagers/BackupScheduleOperationRunsRelationManager.php:
    • Prefer owner schedule record as primary context ($this->getOwnerRecord()).
    • Remove dependencies on ambient tenant where owner context exists.
  • T016 Harden apps/platform/app/Filament/Widgets/ManagedEnvironment/ManagedEnvironmentTriageArrivalContinuity.php:
    • Prefer widget record context.
    • Use one resolver consistently for visibility and mutation checks.
    • Fail closed when context is missing.

Phase 4: Browser Smoke (required because the original bugs were user-visible)

  • T017 Backup Set Add Policies smoke:
    • Open Backup Set detail → Add Policies.
    • Verify policies are visible and row selection checkbox column is visible.
    • Select one or more rows; verify “Add selected” path works.
  • T018 Restore Run Create wizard smoke:
    • Open Restore Runs → Create.
    • Trigger Livewire interactions (wizard next/previous, selections).
    • Verify no “no tenant context selected” crash.

Phase 5: Validation

  • T019 Run narrow tests first (confidence lane):
    • cd apps/platform && ./vendor/bin/sail artisan test tests/Architecture --filter='FilamentTenantContextContract' --compact
    • cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Filament --filter='BackupSetPolicyPicker|RestoreRun|BackupScheduleOperationRuns|Triage' --compact
  • T020 Run broader related suites only if needed (keep lane cost honest):
    • cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Filament --compact
  • T021 Run cd apps/platform && ./vendor/bin/sail pint --dirty and git diff --check.
  • T022 Report full-suite status honestly if not run.
    • Full suite not executed; this spec was validated via targeted Feature/Architecture tests + a dedicated browser smoke file.