## Summary - implement Spec 143 tenant lifecycle, operability, and tenant-context semantics across chooser, tenant management, onboarding, and canonical operation viewers - add centralized tenant lifecycle and operability support types, audit action coverage, and lifecycle-aware badge and action handling - add feature and unit coverage for tenant chooser eligibility, global search scoping, canonical operation access, onboarding authorization, and lifecycle presentation ## Testing - vendor/bin/sail artisan test --compact - vendor/bin/sail bin pint --dirty --format agent Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #172
6.4 KiB
6.4 KiB
Research: Tenant Lifecycle, Operability, and Context Semantics Foundation
Decision 1: Reuse the existing Tenant lifecycle states as the canonical domain source
- Decision: Keep
draft,onboarding,active, andarchivedonApp\Models\Tenantas the single canonical lifecycle vocabulary for tenant records, and build operability and context rules on top of that rather than introducing a second lifecycle store. - Rationale:
Tenantalready defines the lifecycle constants, soft-delete behavior, and current-selection safety (makeCurrent()rejects non-active tenants). The inconsistency is not missing states; it is inconsistent interpretation of those states across pages and helpers. - Alternatives considered:
- Add a second lifecycle table or projection. Rejected because it would duplicate the same tenant-state truth and increase reconciliation complexity.
- Derive tenant lifecycle entirely from onboarding session lifecycle. Rejected because onboarding drafts are workflow records and do not replace the durable tenant record.
Decision 2: Model operability separately from lifecycle
- Decision: Introduce a central operability layer that answers viewability, selector eligibility, action eligibility, onboarding resumability, and canonical monitoring referenceability independently of raw lifecycle.
- Rationale: Current code uses raw
where('status', 'active'),isActive(), or soft-delete checks in selectors, controllers, and actions. That pattern conflates lifecycle with every UX and authorization choice. - Alternatives considered:
- Continue using direct
status === 'active'checks with better comments. Rejected because it does not prevent future divergence. - Encode every decision directly into policies. Rejected because selector visibility, badge presentation, and page categorization are not purely authorization concerns.
- Continue using direct
Decision 3: Treat remembered tenant context as preference state, not route legitimacy
- Decision: Keep remembered tenant state in workspace context helpers, but treat it as filter and navigation preference only. Canonical workspace-owned record viewers must authorize by record and entitlement, not by active tenant equality.
- Rationale:
TenantlessOperationRunViewer::mount()currently aborts 404 when the active tenant differs from the run tenant even afterOperationRunPolicyalready authorizes the user. That is the concrete trust failure this foundation must eliminate. - Alternatives considered:
- Keep the viewer mismatch 404 and document it. Rejected because it makes a valid record appear missing and violates the spec’s canonical-record rule.
- Automatically switch the selected tenant when viewing a canonical record. Rejected because it mutates operator context as a side effect of inspection.
Decision 4: Keep onboarding workflow state distinct from tenant lifecycle
- Decision: Preserve
TenantOnboardingSessionas the owner of workflow progression, resumability, and checkpoint semantics, whileTenantowns lifecycle semantics for the durable tenant record. - Rationale: The codebase already uses
OnboardingLifecycleService,OnboardingDraftResolver, andTenantOnboardingSessionPolicyto manage workflow-specific state. Folding that into tenant lifecycle would blur durable domain state with wizard progression. - Alternatives considered:
- Collapse onboarding lifecycle into tenant status. Rejected because checkpoint-level progress, resumability, and versioning belong to the workflow record.
- Hide onboarding tenants until activation. Rejected because operators need to resume, inspect, and audit onboarding work before activation.
Decision 5: Extend centralized badge semantics instead of page-local mappings
- Decision: Use
BadgeCatalogandBadgeDomainas the only badge semantics extension point for tenant lifecycle presentation, and add exhaustive coverage tests there. - Rationale: Tenant status in
TenantResourcealready usesBadgeRenderer::label/color/icon(BadgeDomain::TenantStatus). The fix forUnknownrendering belongs in the badge domain mapping, not in per-page string conditionals. - Alternatives considered:
- Patch each affected page with its own match statement. Rejected because it recreates drift.
- Render raw status strings without badge mapping. Rejected because it breaks BADGE-001 and current UI consistency.
Decision 6: Anchor authorization in existing policies and capability registries
- Decision: Follow-up implementation work should keep server-side enforcement in
OperationRunPolicy, tenant policies, onboarding policies,CapabilityResolver,WorkspaceCapabilityResolver, andCapabilities, with any new lifecycle-aware decisions delegated through central helpers rather than raw capability strings. - Rationale: The repo already has a strong split between 404 membership failures and 403 capability failures. The problem is contextual misuse, not absence of enforcement primitives.
- Alternatives considered:
- Introduce route-local authorization closures. Rejected because it would increase duplication and drift.
- Rely on Filament visibility or disabling state alone. Rejected because the constitution explicitly forbids using UI as the security boundary.
Decision 7: Plan follow-up implementation around existing test clusters
- Decision: Target follow-up validation through existing Pest suites in
tests/Feature/Auth,tests/Feature/Monitoring,tests/Feature/Onboarding,tests/Feature/Filament,tests/Feature/Rbac,tests/Feature/TenantRBAC, plus focused unit coverage for onboarding and badge semantics. - Rationale: The repo already has dedicated tests for tenant chooser selection, tenant switcher scope, archived tenant access, onboarding authorization, canonical monitoring behavior, and operation-run viewing.
- Alternatives considered:
- Create a new isolated test suite just for lifecycle semantics. Rejected because the behavior is cross-cutting and should strengthen the existing regression clusters.
Filament and panel notes
- Filament v5 runs on Livewire v4 in this repository.
- Panel providers are registered in
bootstrap/providers.php, which already containsAdminPanelProvider,TenantPanelProvider, andSystemPanelProvider. - Relevant searchable-resource posture in current scope:
TenantResourcehas a resource view surface and can remain globally searchable if desired.OperationRunResourcehas global search disabled.- Workspace landing and onboarding wizard are pages, not resources.