TenantAtlas/specs/146-central-tenant-status-presentation/plan.md
2026-03-16 19:17:35 +01:00

10 KiB

Implementation Plan: Central Tenant Status Presentation

Branch: 146-central-tenant-status-presentation | Date: 2026-03-16 | Spec: specs/146-central-tenant-status-presentation/spec.md Input: Feature specification from /specs/146-central-tenant-status-presentation/spec.md

Note: This template is filled in by the /speckit.plan command. See .specify/scripts/ for helper scripts.

Summary

Standardize tenant lifecycle rendering behind one authoritative presentation contract that extends the existing TenantLifecycle + BadgeCatalog architecture with explicit lifecycle semantics, helper copy, and invalid-data handling. Roll the shared contract through tenant list/detail summary surfaces, archived-tenant banner copy, choose-tenant and onboarding-linked surfaces, and the tenantless operations viewer plus its enterprise-detail summary payload so draft, onboarding, active, and archived always render intentionally, never as Unknown, and never get conflated with provider, verification, RBAC, or run status domains.

Technical Context

Language/Version: PHP 8.4.15
Primary Dependencies: Laravel 12, Filament 5, Livewire 4, Tailwind CSS 4
Storage: PostgreSQL (existing tenant and operation records only; no schema changes planned)
Testing: Pest 4 feature and unit tests, including Filament and Livewire coverage
Target Platform: Laravel Sail web application on Filament admin and workspace-canonical UI surfaces
Project Type: Web application monolith
Performance Goals: No render-time external calls, no material query-count regression on list/detail/viewer surfaces, and no extra polling or background work introduced
Constraints: Preserve Spec 143 lifecycle semantics and Spec 145 action semantics; do not change authorization, lifecycle transitions, selector inclusion rules, or tenant/workspace ownership; centralize badge semantics under BADGE-001; invalid fallback must be reserved for truly non-canonical data only
Scale/Scope: Workspace-owned tenant lifecycle presentation across tenant management, choose-tenant, onboarding-linked tenant references, and the tenantless operations viewer plus its OperationRunResource enterprise-detail summary payload, plus regression coverage for the primary surfaces

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

  • Inventory-first: PASS. This is presentation-only work over existing tenant and canonical records. No snapshot/backfill/write behavior changes.
  • Read/write separation: PASS. No new writes, previews, confirmations, queues, or audits are introduced.
  • Graph contract path: PASS. No Microsoft Graph calls are added or changed.
  • Deterministic capabilities: PASS. No capability derivation changes.
  • RBAC-UX: PASS. Authorization planes, 404/403 semantics, membership checks, and capability enforcement remain unchanged. Canonical viewers continue to rely on existing record-level authorization before any tenant lifecycle is shown.
  • Workspace isolation: PASS. No workspace-scoping changes.
  • RBAC-UX destructive confirmation: PASS. No new destructive actions.
  • RBAC-UX global search: PASS. This plan may touch global lifecycle presentation only if an already-authorized tenant result is rendered; it does not widen search behavior.
  • Tenant isolation: PASS. No cross-tenant access changes.
  • Run observability: PASS. No OperationRun creation, mutation, or monitoring behavior changes.
  • Ops-UX 3-surface feedback: PASS. Not applicable because no OperationRun workflow changes are introduced.
  • Ops-UX lifecycle/service ownership: PASS. No OperationRun transition changes.
  • Ops-UX summary counts/guards/system runs: PASS. Not applicable.
  • Automation/data minimization: PASS. No new jobs, locks, or logging paths.
  • Badge semantics (BADGE-001): PASS WITH REQUIRED CENTRALIZATION. The implementation must extend the existing BadgeCatalog / BadgeRenderer path instead of adding local lifecycle maps.
  • UI naming (UI-NAMING-001): PASS. Operator vocabulary remains Draft, Onboarding, Active, and Archived.
  • Filament UI Action Surface Contract: PASS. Presentation-only changes on existing surfaces; no action-surface exemption needed.
  • Filament UI UX-001 (Layout & IA): PASS. Existing layouts remain intact; lifecycle rendering changes must fit current table, infolist, and viewer structures.

Post-Design Re-check: PASS. Phase 1 design keeps lifecycle presentation read-only, tenant-safe, badge-centralized, and action-surface neutral.

Project Structure

Documentation (this feature)

specs/146-central-tenant-status-presentation/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│   └── tenant-lifecycle-presentation.openapi.yaml
└── tasks.md

Source Code (repository root)

app/
├── Filament/
│   ├── Pages/
│   │   ├── Operations/
│   │   └── Workspaces/
│   ├── Resources/
│   │   └── TenantResource.php
│   └── System/Pages/Directory/
├── Models/
│   └── Tenant.php
├── Services/
│   ├── Onboarding/
│   └── Tenants/
├── Support/
│   ├── Badges/
│   └── Tenants/
resources/
└── views/
    └── filament/
        ├── pages/
        └── widgets/
tests/
├── Feature/
│   ├── Filament/
│   ├── Onboarding/
│   └── Rbac/
└── Unit/

Structure Decision: Use the existing Laravel monolith structure and extend the current support-layer centralization points first: app/Support/Tenants for lifecycle semantics, app/Support/Badges for badge-level rendering, app/Filament/Resources/TenantResource.php and related pages for tenant surfaces, app/Filament/Pages/Operations for canonical viewer alignment, and focused Pest coverage in tests/Feature and tests/Unit.

Phase 0 Research Summary

  • Confirmed the canonical lifecycle already exists in App\Support\Tenants\TenantLifecycle with the exact four required values and labels.
  • Confirmed badge semantics are already centralized through BadgeCatalog, BadgeRenderer, and TenantStatusBadge, but today that path only standardizes badge label/color/icon, not helper copy or richer cross-surface presentation density.
  • Confirmed tenant list/detail and system directory tenant tables already use BadgeDomain::TenantStatus, while choose-tenant currently communicates lifecycle indirectly in prose, archived tenant context is surfaced through a dedicated banner view, and operation viewers derive lifecycle context through TenantOperabilityService plus OperationRunResource enterprise-detail payload data rather than a dedicated lifecycle presentation contract.
  • Confirmed Filament v5 supports badge presentation through shared text/badge semantics, which aligns with continuing to feed UI badges from one renderer rather than introducing per-surface mappings.

Phase 1 Design

Implementation Approach

  1. Introduce a dedicated tenant lifecycle presentation contract that sits on top of TenantLifecycle and returns:
    • canonical lifecycle value
    • canonical label
    • badge tone/icon data
    • concise helper text
    • detailed helper text
    • explicit invalid-data marker for non-canonical values only
  2. Keep BadgeCatalog / BadgeRenderer as the badge primitive for BADGE-001 compliance, but stop treating badge spec alone as the full lifecycle presentation contract.
  3. Route all in-scope lifecycle rendering through the same presentation source, with per-surface density adapters for:
    • table badge only
  • infolist badge plus helper text
  • tenant summary and archived-banner helper copy
  • selector/supporting prose
  • canonical viewer referenced-tenant banner or note
  1. Audit existing lifecycle render points and tenant-adjacent statuses before rollout so lifecycle remains clearly separate from provider app status, RBAC, verification, and run state and no valid-state local mapping survives outside the shared contract.
  2. Add regression tests that cover all four canonical lifecycle states plus invalid-data fallback behavior, including archived-banner and canonical-view summary surfaces.

Planned Workstreams

  • Workstream A: Central contract Create a single presentation object or presenter in the tenant/support layer that derives from TenantLifecycle and is reusable outside tables.
  • Workstream B: Tenant management surfaces Update tenant list/detail summary areas, archived-tenant banner content, and any onboarding-linked tenant cards/sections to use the richer contract while preserving current Filament layouts and actions.
  • Workstream C: Selector and operations viewer surfaces Update choose-tenant and tenantless operation viewer context copy, including referenced-tenant banners and the OperationRunResource enterprise-detail summary payload consumed by that viewer, to use canonical lifecycle wording when lifecycle is shown or described.
  • Workstream D: Regression hardening Add focused unit tests for exhaustive lifecycle mapping and feature tests for tenant index/detail summary areas, archived banner content, onboarding-linked surfaces, and operation viewers.

Testing Strategy

  • Add a focused unit test for the central lifecycle presentation contract covering draft, onboarding, active, archived, and explicit invalid fallback for non-canonical values.
  • Add a focused audit pass over the existing tenant lifecycle render points before rollout so every valid-state surface is routed through the shared contract.
  • Update or add tenant Filament feature tests to assert lifecycle labels on:
    • tenant index table
    • tenant detail identity and summary sections
    • archived tenant banner copy
    • choose-tenant empty or contextual copy where lifecycle is described
  • Update or add canonical viewer tests to assert onboarding and archived referenced tenants render intentional lifecycle context in both the tenantless viewer banner and the OperationRunResource-backed summary payload rendering.
  • Add at least one mixed-status assertion showing lifecycle remains distinct from provider or RBAC status on tenant detail.
  • Run the minimum focused Pest suite through Sail for the touched feature and unit tests.

Complexity Tracking

No constitution violations or exceptional complexity are planned at this stage.