## Summary
Implements Spec 145 for tenant action taxonomy and lifecycle-safe visibility.
This PR:
- adds a central tenant action policy surface and supporting value objects
- aligns tenant list, detail, edit, onboarding, and widget surfaces around lifecycle-safe actions
- standardizes operator-facing lifecycle wording around View, Resume onboarding, Archive, Restore, and Complete onboarding
- tightens onboarding and tenant lifecycle authorization semantics, including honest 404 vs 403 behavior
- updates related regression coverage and spec artifacts for Spec 145
- fixes follow-on full-suite regressions uncovered during validation, including onboarding browser flows, provider consent fixtures, workspace redirect DI expectations, and critical table/action/UI expectation drift
## Validation
Executed and passed:
- vendor/bin/sail bin pint --dirty --format agent
- vendor/bin/sail artisan test --compact
Result:
- 2581 passed
- 8 skipped
- 13534 assertions
## Notes
- Base branch: dev
- Feature branch commit: a33a41b
- Filament v5 / Livewire v4 compliance preserved
- No panel provider registration changes; Laravel 12 provider registration remains in bootstrap/providers.php
- No new globally searchable resource behavior added in this slice
- Destructive lifecycle actions remain confirmation-gated and authorization-protected
Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #174
6.9 KiB
Implementation Plan: Tenant Action Taxonomy and Lifecycle-Safe Visibility
Branch: 145-tenant-action-taxonomy-lifecycle-safe-visibility | Date: 2026-03-15 | Spec: spec.md
Input: Feature specification from /specs/145-tenant-action-taxonomy-lifecycle-safe-visibility/spec.md
Summary
Spec 145 hardens tenant action semantics by separating lifecycle truth from surface-specific action assembly. The implementation will keep lifecycle as the source of truth in the existing TenantLifecycle, TenantOperabilityService, and onboarding lifecycle services, while introducing a central tenant-action policy/resolver layer that decides which actions are visible, enabled, labeled, and auditable for each surface.
The change scope is primarily Filament admin behavior, not data ownership or provider integration. The plan therefore focuses on consolidating duplicated action logic across TenantResource, ViewTenant, EditTenant, onboarding pages, and tenant-linked widgets; preserving existing audit action IDs and badge mappings; and adding focused Pest coverage for lifecycle-specific action visibility, label honesty, and 404 versus 403 authorization semantics.
Technical Context
Language/Version: PHP 8.4.15 with Laravel 12, Filament v5, Livewire v4.0+
Primary Dependencies: Filament Actions/Tables/Infolists, Laravel Gates/Policies, UiEnforcement, WorkspaceUiEnforcement, ActionSurfaceDeclaration, BadgeCatalog, TenantOperabilityService, OnboardingLifecycleService
Storage: PostgreSQL for tenants, onboarding sessions, audit logs, operation runs, and workspace membership data
Testing: Pest 4 feature tests, Livewire component tests, and unit tests run through Laravel Sail
Target Platform: Laravel Sail containerized admin web application on macOS development and Linux container deployment
Project Type: Laravel monolith web application
Performance Goals: Keep action availability and labeling local, synchronous, and DB-backed at render time; preserve DB-only admin rendering with no new external calls for action visibility decisions
Constraints: No new ownership boundaries; no raw capability strings; preserve deny-as-not-found for non-members and 403 for in-scope capability denial; destructive-like actions keep ->requiresConfirmation(); onboarding completion remains workflow-contextual and must not become a generic tenant-table mutation
Scale/Scope: One core tenant resource plus supporting pages, one onboarding wizard, shared RBAC/UI enforcement helpers, existing badge and audit registries, and focused regression suites under tests/Feature/Rbac, tests/Feature/Onboarding, tests/Feature/TenantRBAC, and tests/Unit/Tenants
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
Pre-Phase 0 Gate: PASS
- Inventory-first: no change to inventory, backups, or snapshot ownership; feature is semantics/UI-policy only.
- Read/write separation: archive and restore remain explicit tenant lifecycle mutations with confirmation, audit logging, and test coverage.
- Graph contract path: no new Microsoft Graph calls are introduced; existing verification and provider actions remain out of scope for contract changes.
- Deterministic capabilities: capability checks continue through canonical registries and existing resolver services.
- RBAC-UX planes: feature stays within the admin
/adminplane and preserves 404 versus 403 semantics. - Workspace and tenant isolation: action legitimacy remains based on workspace membership, tenant entitlement, capability, lifecycle, and page context rather than remembered tenant context.
- Destructive confirmations:
Archive,Restore, and any future force-delete exposure remain confirmation-gated. - Global search safety: no new global-search surface is introduced, but any touched tenant actions must remain non-member-safe.
- Run observability / Ops-UX: no new
OperationRunworkflow is introduced; existing run-producing actions stay under their current contracts. - Badge semantics: tenant lifecycle badges already route through
BadgeCatalogandTenantStatusBadge; design will reuse that path. - UI naming: action labels will remain
Verb + Objectand align with existing audit vocabulary. - Filament Action Surface Contract: in-scope list/detail/onboarding surfaces already declare action surfaces or are governed by the same contract; plan will consolidate action inventories without violating row-action limits.
- UX-001: no layout redesign; only action grouping, visibility, and naming semantics are being hardened.
Post-Phase 1 Re-check: PASS
- Design keeps lifecycle state in existing domain models and introduces only derived policy/value-object artifacts.
- Design does not require a new table, queue, external dependency, or provider contract.
- Design preserves Filament v5 / Livewire v4 action semantics and keeps panel-provider registration unchanged in
bootstrap/providers.php. - Design keeps onboarding completion inside onboarding workflow context and avoids collapsing onboarding and archive/restore into a single mutation path.
Project Structure
Documentation (this feature)
specs/145-tenant-action-taxonomy-lifecycle-safe-visibility/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── tenant-action-taxonomy.openapi.yaml
└── tasks.md
Source Code (repository root)
app/
├── Filament/
│ ├── Resources/
│ │ ├── TenantResource.php
│ │ └── TenantResource/Pages/
│ │ ├── EditTenant.php
│ │ ├── ListTenants.php
│ │ └── ViewTenant.php
│ ├── Pages/
│ │ └── Workspaces/ManagedTenantOnboardingWizard.php
│ └── Widgets/Tenant/
├── Models/
│ ├── Tenant.php
│ └── TenantOnboardingSession.php
├── Policies/
│ └── TenantOnboardingSessionPolicy.php
├── Services/
│ ├── Onboarding/
│ └── Tenants/TenantOperabilityService.php
├── Support/
│ ├── Audit/AuditActionId.php
│ ├── Badges/
│ ├── Rbac/
│ ├── Tenants/
│ └── Ui/ActionSurface/
└── Providers/
└── AuthServiceProvider.php
routes/
└── web.php
tests/
├── Feature/
│ ├── Onboarding/
│ ├── Rbac/
│ ├── TenantRBAC/
│ └── 144/
└── Unit/
└── Tenants/
Structure Decision: Use the existing Laravel monolith structure. Central lifecycle truth remains in app/Support/Tenants and app/Services/Tenants; surface-specific action assembly is refactored in-place across Filament resources/pages and onboarding workflow pages; regression coverage extends existing Pest suites instead of creating a parallel test namespace.
Complexity Tracking
No constitution violations or exemptions are required for this plan.