## Summary - remove deprecated baseline profile status alias constants and keep baseline lifecycle semantics on the canonical enum path - retire the dead tenant app-status badge/default-fixture residue from the active runtime support path - add the `234-dead-transitional-residue` spec, plan, research, data-model, quickstart, checklist, and task artifacts plus focused regression assertions ## Validation - not rerun during this PR creation step Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #270
20 KiB
Implementation Plan: Dead Transitional Residue Cleanup
Branch: 234-dead-transitional-residue | Date: 2026-04-23 | Spec: spec.md
Input: Feature specification from /specs/234-dead-transitional-residue/spec.md
Note: This plan keeps historical tenant app_status storage and historical migrations intact. It removes only dead runtime alias/support paths and tightens fixtures/tests so legacy values become explicit opt-in setup rather than ambient repo truth.
Summary
Remove the dead BaselineProfile::STATUS_* alias layer and retire tenant app-status residue from the centralized badge catalog, default test fixtures, browser smoke seed data, and legacy-facing tests. The implementation stays intentionally small: no schema change, no new status family, no operator-surface redesign, and no compatibility shim. The proof burden is that current tenant truth and baseline profile behavior remain unchanged while the dead semantics disappear from active runtime language.
Technical Context
Language/Version: PHP 8.4.15, Laravel 12, Filament v5, Livewire v4
Primary Dependencies: App\Models\BaselineProfile, App\Support\Baselines\BaselineProfileStatus, App\Support\Badges\BadgeCatalog, App\Support\Badges\BadgeDomain, Database\Factories\TenantFactory, App\Console\Commands\SeedBackupHealthBrowserFixture, existing tenant-truth and baseline-profile Pest tests
Storage: Existing PostgreSQL baseline_profiles and tenants tables; no new persistence and no schema migration in this slice
Testing: Pest v4 feature and unit tests through Laravel Sail
Validation Lanes: fast-feedback, confidence
Target Platform: Laravel admin web application in Sail containers with admin routes under /admin
Project Type: Monorepo with one Laravel runtime in apps/platform and spec artifacts at repository root
Performance Goals: Preserve current request/query behavior; cleanup must not add runtime branching, new queries, or new UI layers
Constraints: No schema change, no compatibility aliases, no new badge/readiness domain, no authorization changes, no global-search broadening, and no new operator-facing surface
Scale/Scope: One Eloquent model, one central badge registry path, one legacy badge mapper, one tenant factory, one browser fixture command, and focused tenant/baseline regression families
Filament v5 Implementation Contract
- Livewire v4.0+ compliance: Preserved. The cleanup does not introduce any legacy Livewire patterns and does not add new Filament component types.
- Provider registration location: Unchanged. Panel providers remain registered in
bootstrap/providers.php. - Global search coverage:
TenantResourceremains globally searchable and already has View/Edit pages.BaselineProfileResourcekeeps global search disabled via$isGloballySearchable = falseand already has View/Edit pages. This cleanup adds no new global-search exposure. - Destructive actions: No destructive action is introduced or changed. Existing tenant and baseline profile destructive flows remain on their current confirmation and authorization paths.
- Asset strategy: No new assets are planned. Deployment expectations remain unchanged, including
cd apps/platform && php artisan filament:assetsonly when future work adds registered assets. - Testing plan: Prove the cleanup with focused feature tests for tenant-truth continuity and baseline-profile list/view/edit/archive continuity, plus unit coverage for central badge-catalog cleanup.
UI / Surface Guardrail Plan
- Guardrail scope: no operator-facing surface change
- Native vs custom classification summary:
N/A - Shared-family relevance: none
- State layers in scope: none
- Handling modes by drift class or surface:
report-only - Repository-signal treatment:
review-mandatorybecause this is a repo-hygiene cleanup that removes active residue rather than hiding it - Special surface test profiles:
N/A - Required tests or manual smoke:
functional-core - Exception path and spread control: none
- Active feature PR close-out entry:
Guardrail
Shared Pattern & System Fit
- Cross-cutting feature marker: no
- Systems touched: centralized badge registry, baseline profile status model language, tenant default fixtures, browser smoke fixture command, and focused tenant/baseline regression files
- Shared abstractions reused:
BaselineProfileStatus,BadgeCatalog,BadgeDomain, and the existing tenant/baseline regression families - New abstraction introduced? why?: none
- Why the existing abstraction was sufficient or insufficient: Existing abstractions are sufficient because this work removes dead support paths instead of creating a new semantic or presentation layer.
- Bounded deviation / spread control: none
Constitution Check
GATE: Passed before Phase 0 research. Re-check after Phase 1 design: still passed with no new persistence, no new semantic family, and no operator-surface expansion.
| Gate | Status | Plan Notes |
|---|---|---|
| Inventory-first / read-write separation | PASS | No Graph path, no new mutation flow, and no snapshot or restore behavior change. |
| RBAC, workspace isolation, tenant isolation | PASS | No route, policy, capability, or resource visibility behavior changes are planned. |
| Run observability / Ops-UX lifecycle | PASS | No OperationRun is created or modified; this cleanup is outside queued or remote execution semantics. |
| Shared pattern first | PASS | The plan simplifies the central badge path by removing an unused legacy domain rather than bypassing it with a local mapping. |
| Proportionality / no premature abstraction | PASS | The plan removes existing residue and introduces no new abstraction, enum, registry, or persistence. |
| Persisted truth / behavioral state | PASS | Historical columns and migrations remain untouched; no new state or artifact is introduced. |
| Badge semantics / Filament-native discipline | PASS | Central badge semantics remain authoritative, and no page-local or view-local replacement badge language is added. |
| Filament v5 / Livewire v4 contract | PASS | Existing resources remain unchanged in behavior; provider registration and global-search posture stay compliant. |
| Test governance | PASS | Proof stays in focused feature/unit lanes with no heavy-family promotion and a net reduction in fixture-default ambiguity. |
Test Governance Check
- Test purpose / classification by changed surface:
Featurefor tenant-truth and baseline-profile continuity;Unitfor central badge-catalog cleanup - Affected validation lanes:
fast-feedback,confidence - Why this lane mix is the narrowest sufficient proof: The business truth is continuity after residue removal. Feature tests prove runtime behavior on current tenant and baseline flows, while one small unit slice proves the central badge cleanup without widening into browser or heavy-governance coverage.
- Narrowest proving command(s):
export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agentexport PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/TenantTruthCleanupSpec179Test.php tests/Feature/Filament/TenantLifecycleStatusDomainSeparationTest.phpexport PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Baselines/BaselineProfileArchiveActionTest.php tests/Feature/Filament/BaselineProfileListFiltersTest.php tests/Feature/Filament/BaselineProfileScopeV2PersistenceTest.php tests/Feature/Baselines/BaselineProfileWorkspaceOwnershipTest.php tests/Feature/Baselines/BaselineProfileAuthorizationTest.phpexport PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Badges/TenantBadgesTest.php tests/Unit/Badges/BadgeCatalogTest.phpexport PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd /Users/ahmeddarrazi/Documents/projects/wt-plattform && rg -n "BaselineProfile::STATUS_|TenantAppStatus|tenant_app_status" apps/platform/app apps/platform/tests apps/platform/database/factories && rg -n -- "app_status" apps/platform/app apps/platform/tests apps/platform/database/factories
- Fixture / helper / factory / seed / context cost risks: Low to moderate. Removing the default
app_statusfromTenantFactoryand browser fixture setup can expose hidden reliance on ambient legacy values in tests or smoke commands. - Expensive defaults or shared helper growth introduced?: No. The change reduces a misleading default rather than adding a new helper burden.
- Heavy-family additions, promotions, or visibility changes: none
- Surface-class relief / special coverage rule:
standard-native relief - Closing validation and reviewer handoff: Reviewers should verify that removed residue had no active runtime dependency, that tenant/baseline tests still pass without ambient legacy defaults, and that no migration or new compatibility path slipped in.
- Budget / baseline / trend follow-up: none
- Review-stop questions: Did any test or fixture still need
app_statusbut fail to set it explicitly? Did badge cleanup remove a still-used domain? Did alias removal trigger any runtime or static reference outside the planned scope? Did the cleanup expand into schema or route changes? - Escalation path:
document-in-feature - Active feature PR close-out entry:
Guardrail - Why no dedicated follow-up spec is needed: This is routine current-release cleanup. A follow-up spec is only needed if a hidden runtime dependency forces a broader domain decision rather than simple residue removal.
Project Structure
Documentation (this feature)
specs/234-dead-transitional-residue/
├── spec.md
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── checklists/
│ └── requirements.md
└── tasks.md
No contracts artifact is planned because this cleanup changes no route, API, or standalone logical interaction contract.
Source Code (repository root)
apps/platform/
├── app/
│ ├── Console/Commands/
│ │ └── SeedBackupHealthBrowserFixture.php
│ ├── Models/
│ │ └── BaselineProfile.php
│ └── Support/Badges/
│ ├── BadgeCatalog.php
│ ├── BadgeDomain.php
│ └── Domains/
│ └── TenantAppStatusBadge.php
├── database/
│ └── factories/
│ └── TenantFactory.php
└── tests/
├── Feature/
│ ├── Baselines/
│ │ ├── BaselineProfileArchiveActionTest.php
│ │ ├── BaselineProfileAuthorizationTest.php
│ │ └── BaselineProfileWorkspaceOwnershipTest.php
│ └── Filament/
│ ├── BaselineProfileListFiltersTest.php
│ ├── BaselineProfileScopeV2PersistenceTest.php
│ ├── TenantLifecycleStatusDomainSeparationTest.php
│ └── TenantTruthCleanupSpec179Test.php
└── Unit/
└── Badges/
├── BadgeCatalogTest.php
└── TenantBadgesTest.php
Structure Decision: Keep the work entirely inside the existing Laravel application in apps/platform. The plan updates one model, one central badge path, one default tenant factory, one browser fixture command, and focused regression files rather than touching resource layout or introducing a cleanup subsystem.
Complexity Tracking
No constitutional violation is planned. No new structure is introduced, so no complexity exception is required.
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| — | — | — |
Proportionality Review
No new enum, persisted entity, abstraction layer, taxonomy, or cross-domain UI framework is planned in this slice.
- Current operator problem: Dead alias and legacy-support residue still make it easy for contributors and tests to treat retired semantics as current repo truth.
- Existing structure is insufficient because: The current code already has the canonical
BaselineProfileStatuspath and current tenant-truth behavior, but dead support artifacts continue to conserve the older semantics around them. - Narrowest correct implementation: Remove only the dead alias/support paths and make any still-needed legacy values explicit in the few tests or fixtures that truly need them.
- Ownership cost created: Small one-time cleanup across a handful of files, followed by lower ongoing cognitive and maintenance cost.
- Alternative intentionally rejected: Keeping deprecated aliases, badge domains, or factory defaults for convenience was rejected because this is a pre-production repo and the residue already undermines cleanup discipline.
- Release truth: Current-release truth cleanup.
Phase 0 Research Summary
BaselineProfile::STATUS_DRAFT,STATUS_ACTIVE, andSTATUS_ARCHIVEDexist only inapps/platform/app/Models/BaselineProfile.php; no currentapps/platformruntime or test reference still needs them.- The tenant app-status badge path is now pure residue:
BadgeDomain::TenantAppStatus, theBadgeCatalogmapper entry, andTenantAppStatusBadgeremain, but the only confirmed consumers are badge tests, not current runtime surfaces. TenantFactorystill defaultsapp_statustook, andSeedBackupHealthBrowserFixturestill writesapp_status => 'ok', which keeps a retired value ambient in test and smoke data even though current tenant surfaces no longer depend on it.- Existing tenant-truth regressions intentionally set
app_statusin a few scenarios to prove suppression. Those explicit setups should remain where meaningful; only ambient defaults should go away. - Historical migrations and historical stored columns are not part of this cleanup. The correct scope is runtime/support residue removal first, not schema deletion.
Phase 1 Design Summary
research.mdrecords the cleanup decisions and rejected alternatives.data-model.mddocuments the still-active persistent truths and the support artifacts that should stop acting as active repo truth.quickstart.mdgives the narrow validation order for alias removal, badge cleanup, fixture cleanup, and regression verification.- No contracts artifact is created because the feature changes no route, API, or new user interaction contract.
Phase 1 — Agent Context Update
Run after artifact generation:
.specify/scripts/bash/update-agent-context.sh copilot
Implementation Strategy
Phase A — Remove dead baseline profile alias language
Goal: Make BaselineProfileStatus the only active baseline profile status contract.
| Step | File | Change |
|---|---|---|
| A.1 | apps/platform/app/Models/BaselineProfile.php |
Remove deprecated STATUS_DRAFT, STATUS_ACTIVE, and STATUS_ARCHIVED constants. |
| A.2 | Targeted grep + baseline regression files | Confirm no runtime or test path in apps/platform still references the removed aliases; keep baseline profile behavior proved through existing feature tests rather than adding a new alias-specific shim. |
Phase B — Retire the dead tenant app-status badge path centrally
Goal: Remove the last active runtime support entry point for tenant app-status semantics.
| Step | File | Change |
|---|---|---|
| B.1 | apps/platform/app/Support/Badges/BadgeDomain.php |
Remove the TenantAppStatus enum case if no active runtime consumer remains. |
| B.2 | apps/platform/app/Support/Badges/BadgeCatalog.php |
Remove the TenantAppStatus mapper registration. |
| B.3 | apps/platform/app/Support/Badges/Domains/TenantAppStatusBadge.php |
Remove the mapper class once the registry path is gone. |
| B.4 | apps/platform/tests/Unit/Badges/TenantBadgesTest.php and apps/platform/tests/Unit/Badges/BadgeCatalogTest.php |
Update badge coverage to prove the canonical tenant lifecycle/RBAC/permission domains still work and that the removed legacy domain no longer acts as active repo truth. |
Phase C — Make legacy app-status explicit instead of ambient in defaults and smoke data
Goal: Stop silently injecting retired tenant app-status semantics into factories and browser fixture setup.
| Step | File | Change |
|---|---|---|
| C.1 | apps/platform/database/factories/TenantFactory.php |
Remove the default app_status => 'ok' assignment so tests must opt in explicitly when they need a historical value. |
| C.2 | apps/platform/app/Console/Commands/SeedBackupHealthBrowserFixture.php |
Remove or conditionalize the forced app_status => 'ok' write unless the scenario explicitly requires it for a still-active smoke purpose. |
| C.3 | Targeted tenant-truth tests | Keep explicit app_status setup only in cases that intentionally prove the legacy field no longer surfaces as truth. |
Phase D — Rebalance regression coverage around explicit legacy setup
Goal: Preserve current behavior while making the cleanup durable.
| Step | File | Change |
|---|---|---|
| D.1 | apps/platform/tests/Feature/Filament/TenantTruthCleanupSpec179Test.php |
Keep explicit legacy app_status values where they prove suppression; stop depending on factory defaults. |
| D.2 | apps/platform/tests/Feature/Filament/TenantLifecycleStatusDomainSeparationTest.php |
Keep lifecycle/RBAC separation assertions intact with explicit historical setup where needed. |
| D.3 | apps/platform/tests/Feature/Baselines/BaselineProfileArchiveActionTest.php, apps/platform/tests/Feature/Filament/BaselineProfileListFiltersTest.php, apps/platform/tests/Feature/Filament/BaselineProfileScopeV2PersistenceTest.php, apps/platform/tests/Feature/Baselines/BaselineProfileWorkspaceOwnershipTest.php, and apps/platform/tests/Feature/Baselines/BaselineProfileAuthorizationTest.php |
Use these existing baseline profile tests as continuity proof after alias removal across archive, list/filter, view/edit, and workspace-owned behavior. |
Risks and Mitigations
- Hidden dependency on removed badge domain: A helper or test outside the initial grep scope may still call
BadgeDomain::TenantAppStatus. Mitigation: targeted grep before merge plus runningTenantBadgesTestandBadgeCatalogTestafter central removal. - Ambient fixture reliance on
app_status: Removing the factory default can reveal tests or smoke commands that only passed becauseapp_statuswas silently set took. Mitigation: convert those cases to explicit setup rather than restoring the default. - Baseline alias removal reaches farther than expected: A non-obvious reference could still exist outside the model. Mitigation: grep for
BaselineProfile::STATUS_before merge and rely on existing baseline feature tests for continuity. - Cleanup scope drifts into schema deletion: The presence of migrations and stored columns can tempt a larger cut. Mitigation: keep historical schema/migrations explicitly out of scope in both plan and tasks.
Post-Design Re-check
The plan remains constitution-compliant, Livewire v4 / Filament v5 compliant, and appropriately narrow. It removes dead runtime/support residue, preserves existing tenant and baseline behavior, introduces no new persistence or abstraction, and is ready for /speckit.tasks.
Implementation Close-Out
- Residue search result: Clean for active runtime/support paths. Remaining
tenant_app_statusandBaselineProfile::class.'::STATUS_*'matches are negative regression assertions only. - Remaining
app_statususage: Explicit historical setup and suppression assertions in tenant-truth tests only.TenantFactoryand the backup-health browser fixture no longer write ambientapp_statusdefaults. - Follow-up decision: No hidden runtime dependency was found, so no follow-up cleanup spec is needed for this slice.