## 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
115 lines
6.9 KiB
Markdown
115 lines
6.9 KiB
Markdown
# Implementation Plan: Tenant Action Taxonomy and Lifecycle-Safe Visibility
|
|
|
|
**Branch**: `145-tenant-action-taxonomy-lifecycle-safe-visibility` | **Date**: 2026-03-15 | **Spec**: [spec.md](./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 `/admin` plane 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 `OperationRun` workflow is introduced; existing run-producing actions stay under their current contracts.
|
|
- Badge semantics: tenant lifecycle badges already route through `BadgeCatalog` and `TenantStatusBadge`; design will reuse that path.
|
|
- UI naming: action labels will remain `Verb + Object` and 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)
|
|
|
|
```text
|
|
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)
|
|
|
|
```text
|
|
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.
|