TenantAtlas/specs/300-internal-tenant-model-naming-consolidation/plan.md
ahmido 292d555eac refactor: consolidate internal tenant model naming (#355)
## Summary
- consolidate internal platform naming from `Tenant` to `Environment` / `ManagedEnvironment` across models, controllers, services, and Filament resources
- rename environment-scoped UI surfaces such as dashboards, chooser flows, navigation, and related widgets to match the updated environment-first domain language
- align middleware, onboarding/review lifecycle services, jobs, and route/context controllers with the new environment-scoped architecture

## Validation
- not rerun as part of this commit/push/PR request

## Notes
- branch is 1 commit ahead of `platform-dev`
- main commit: `refactor: consolidate internal tenant model naming`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #355
2026-05-14 11:13:28 +00:00

279 lines
19 KiB
Markdown

# Implementation Plan: Internal Tenant Model Naming Consolidation
**Branch**: `300-internal-tenant-model-naming-consolidation` | **Date**: 2026-05-13 | **Spec**: `specs/300-internal-tenant-model-naming-consolidation/spec.md`
**Input**: Feature specification from `/specs/300-internal-tenant-model-naming-consolidation/spec.md`
## Summary
Spec 300 is a structural cleanup after the managed-environment cutover pack. Current repo truth already has `App\Models\ManagedEnvironment`, `ManagedEnvironmentFactory`, `managed_environments`, `managed_environment_id`, and canonical workspace/environment routes, but active technical owners still use Tenant-first names across Filament resources/pages/widgets, route parameters, services, tests, migration filenames, table names, index/constraint names, and provider-adjacent payloads.
The implementation approach is inventory-first: classify every remaining tenant reference, rename only platform-owned Managed Environment references, preserve provider-specific and framework-required terms, run focused route/RBAC/Filament/browser validation, and leave no compatibility alias or legacy route in final state.
## Technical Context
**Language/Version**: PHP 8.4.15, Laravel 12.52.0
**Primary Dependencies**: Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1, Laravel Sail 1.52.0
**Storage**: PostgreSQL; current source-of-truth table is `managed_environments`
**Testing**: Pest via `cd apps/platform && ./vendor/bin/sail artisan test --compact`; Browser tests under `apps/platform/tests/Browser` for smoke anchors
**Validation Lanes**: Feature/Guards, Workspaces, ProviderConnections, RequiredPermissions, Filament, Rbac, targeted Browser smoke, Pint dirty, `git diff --check`
**Target Platform**: Laravel SaaS admin app deployed via Dokploy containers; local validation via Sail
**Project Type**: Monorepo with Laravel platform app under `apps/platform`
**Performance Goals**: No broad suite repair loop by default; keep scans and tests focused around structural rename blast radius
**Constraints**: No runtime behavior change, no production compatibility layer, no route resurrection, no RBAC widening, no provider payload corruption
**Scale/Scope**: Structural rename across platform-owned environment concepts only
## UI / Surface Guardrail Plan
- **Guardrail scope**: workflow/route/resource guardrail change, no intended visible UI redesign
- **Native vs custom classification summary**: native Filament/resource/page behavior preserved
- **Shared-family relevance**: canonical links, navigation/route registration, global search, audit metadata, OperationRun metadata, guard tests
- **State layers in scope**: route binding, page/resource class names, table/column/index/constraint names, helper names, test helper names, audit/metadata keys
- **Audience modes in scope**: operator-MSP and support-platform only as existing surfaces; no new customer-facing mode
- **Decision/diagnostic/raw hierarchy plan**: unchanged
- **Raw/support gating plan**: unchanged
- **One-primary-action / duplicate-truth control**: unchanged; any touched actions keep existing hierarchy
- **Handling modes by drift class or surface**: review-mandatory for active `Tenant*` technical owners; allowed classification for provider/framework/historical/regression-guard
- **Repository-signal treatment**: review-mandatory for final scans, route proof, helper retirement, DB naming, provider allowlist, and browser anchors
- **Special surface test profiles**: `route-contract`, `standard-native-filament`, `global-context-shell`, `browser-smoke` for selected anchors
- **Required tests or manual smoke**: focused Pest guard/feature lanes plus selected Browser smokes
- **Exception path and spread control**: provider-specific and framework-required tenant terms are documented in `allowed-tenant-references.md`; no unclassified exception
- **Active feature PR close-out entry**: Guardrail / Structural Tenant Naming Consolidation / Smoke Coverage
## Shared Pattern & System Fit
- **Cross-cutting feature marker**: yes
- **Systems touched**: `ManagedEnvironmentLinks`, workspace intended URL handling, Filament resource/page discovery and routes, route model binding, global search, RBAC helper/policies, OperationRun metadata, audit logs, evidence/report/review references, tests
- **Shared abstractions reused**: Existing route helpers, existing RBAC/policy helpers, existing OperationRun link/service truth, existing Filament v5 resources/pages/actions
- **New abstraction introduced? why?**: none
- **Why the existing abstraction was sufficient or insufficient**: Existing environment-first helpers and models are sufficient; the issue is remaining names around them.
- **Bounded deviation / spread control**: Provider-specific and Filament framework terms remain only with explicit classification.
## OperationRun UX Impact
- **Touches OperationRun start/completion/link UX?**: no
- **Central contract reused**: Existing `OperationRunLinks`, `OperationRunService`, and OperationRun monitoring semantics remain unchanged if touched
- **Delegated UX behaviors**: N/A
- **Surface-owned behavior kept local**: N/A
- **Queued DB-notification policy**: N/A
- **Terminal notification path**: N/A
- **Exception path**: none
## Provider Boundary & Portability Fit
- **Shared provider/platform boundary touched?**: yes
- **Provider-owned seams**: Microsoft/Entra tenant identifiers, Graph `tenantId`, `entra_tenant_id`, `microsoft_tenant_id`, target-scope provider metadata, raw provider payloads
- **Platform-core seams**: Managed Environment model/table/resource/page/service/helper naming, route parameters, platform metadata keys, evidence/report/review references
- **Neutral platform terms / contracts preserved**: `ManagedEnvironment`, `managed_environment_id`, `environment`, `workspace`, `ManagedEnvironmentLinks`
- **Retained provider-specific semantics and why**: Microsoft/Entra terms stay because they represent external directory identity, not platform object ownership.
- **Bounded extraction or follow-up path**: document-in-feature. Stop only if ambiguous active platform-owned references cannot be classified safely.
## Constitution Check
*GATE: Must pass before implementation. Re-check after structural rename phases.*
- Inventory-first: no inventory domain change; source scans/classification precede edits.
- Read/write separation: no new user-triggered write behavior; touched destructive actions must keep confirmation, authorization, audit, and tests.
- Graph contract path: no Graph endpoint changes; provider-specific Graph tenant identifiers remain provider-owned.
- Deterministic capabilities: no capability derivation change.
- RBAC-UX: `/admin` and `/system` planes remain separated; workspace/environment non-entitlement stays 404; member-without-capability stays 403.
- Workspace isolation: workspace remains primary session context; Managed Environment remains secondary context.
- Tenant isolation: current tenant-owned-by-history semantics are preserved behaviorally while platform-owned naming moves to environment-first.
- Run observability: no new queued/remote work; OperationRun metadata naming may change only where platform-owned.
- Test governance: focused structural rename lanes are explicit; no broad test family growth by default.
- Proportionality: broad rename is justified as post-cutover cleanup; no new runtime abstraction.
- No premature abstraction: no registries/resolvers/frameworks added.
- Persisted truth: no new table/entity/product truth; only names may change.
- Behavioral state: no new states or reason families.
- Shared pattern first: existing link/RBAC/Filament/OperationRun patterns are reused.
- Provider boundary: platform-owned Tenant-first terms are removed; provider-owned tenant terms are kept and documented.
- LEAN-001: pre-production posture means no compatibility aliases, dual paths, or historical fixtures unless a spec-blocking migration risk is discovered.
- Filament v5: Livewire v4.0+ is required; this repo has Livewire 4.1.4.
- Laravel 12 panel providers: remain registered in `apps/platform/bootstrap/providers.php`, not `bootstrap/app.php`.
- Global search: any renamed globally searchable resource must keep View/Edit pages or disable global search.
- Filament actions: any touched destructive actions must remain `Action::make(...)->action(...)` with `->requiresConfirmation()` and authorization.
- Asset strategy: unchanged; if assets are unexpectedly registered, deployment must run `cd apps/platform && php artisan filament:assets`.
## Test Governance Check
- **Test purpose / classification by changed surface**: Feature guards for route/helper/naming contracts; Filament/Livewire feature tests for resources/pages/actions; Unit tests for pure helper services; Browser smoke for selected visible anchors.
- **Affected validation lanes**: Feature/Guards, Workspaces, ProviderConnections, RequiredPermissions, Filament, Rbac, targeted Browser.
- **Why this lane mix is the narrowest sufficient proof**: It proves route/RBAC equivalence and stale-name absence without treating the rename as a full-suite stabilization spec.
- **Narrowest proving command(s)**:
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Workspaces`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/RequiredPermissions`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Rbac`
- **Fixture / helper / factory / seed / context cost risks**: Rename helpers without widening default workspace/provider/browser setup.
- **Expensive defaults or shared helper growth introduced?**: no
- **Heavy-family additions, promotions, or visibility changes**: none planned; Browser anchors stay explicit.
- **Surface-class relief / special coverage rule**: `standard-native-filament` unless a visible context-shell/browser anchor changes.
- **Closing validation and reviewer handoff**: final scans, focused lanes, Browser anchors, Pint dirty, `git diff --check`, and close-out inventory.
- **Budget / baseline / trend follow-up**: none expected; document any unexpected lane runtime growth.
- **Review-stop questions**: Did any active platform-owned `Tenant*` owner remain? Did route parameters still use `{tenant}` for platform environment routes? Did provider terms remain correct? Did global search remain valid? Did RBAC widen?
- **Escalation path**: document-in-feature; follow-up-spec only for unresolved migration/schema risk or ambiguous platform-owned references.
- **Active feature PR close-out entry**: Guardrail / Structural Tenant Naming Consolidation / Smoke Coverage
- **Why no dedicated follow-up spec is needed**: The rename is explicitly scoped as the post-297-299 cleanup; unresolved blockers must stop this spec rather than silently deferring core cleanup.
## Project Structure
### Documentation (this feature)
```text
specs/300-internal-tenant-model-naming-consolidation/
├── allowed-tenant-references.md
├── checklists/
│ └── requirements.md
├── plan.md
├── spec.md
├── tasks.md
└── tenant-reference-inventory.md
```
### Source Code (repository root)
```text
apps/platform/
├── app/
│ ├── Console/Commands/
│ ├── Filament/
│ │ ├── Concerns/
│ │ ├── Pages/
│ │ ├── Resources/
│ │ ├── System/
│ │ └── Widgets/
│ ├── Http/Controllers/
│ ├── Jobs/
│ ├── Models/
│ ├── Policies/
│ ├── Services/
│ └── Support/
├── config/
├── database/
│ ├── factories/
│ └── migrations/
├── resources/
├── routes/
└── tests/
├── Browser/
├── Feature/
└── Unit/
```
**Structure Decision**: Use the existing Laravel/Filament layout. Do not introduce new base folders. Rename files/classes in-place to established destination names.
## Complexity Tracking
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| Broad structural rename | Active technical names keep old Tenant-first architecture alive after route/copy cutover | Comments/docs alone do not stop future code from using active `Tenant*` classes/helpers/routes |
| Migration/index/constraint rename review | DB source truth is already `managed_environment`, but tenant-named migration files/indexes/constraints remain | Leaving schema names mixed makes future migrations and guard tests ambiguous |
## Proportionality Review
- **Current operator problem**: Future platform/environment work can regress visible behavior and provider boundaries because active code still presents Tenant as the platform managed target.
- **Existing structure is insufficient because**: Specs 297-299 cleaned route/copy/final seal surfaces, not internal class/table/helper ownership.
- **Narrowest correct implementation**: Classify first, rename platform-owned names only, preserve provider/framework/historical/guard terms, and prove equivalence.
- **Ownership cost created**: High review and testing cost, plus migration/schema risk; contained by phased tasks and final inventory.
- **Alternative intentionally rejected**: Leave active internal names as legacy debt. Rejected because the project is pre-production and LEAN-001 favors canonical replacement over legacy preservation.
- **Release truth**: Current-release structural cleanup
## Repository Truth From Preparation
- Current branch before prep: `platform-dev`, clean.
- Current branch after `create-new-feature`: `300-internal-tenant-model-naming-consolidation`.
- Latest starting commit: `b98bafcf feat: finalize managed environment cutover seal (#354)`.
- Related specs:
- `specs/297-managed-environment-canonical-route-cutover/` has completed task/checklist signals and route-cutover artifacts.
- `specs/298-managed-environment-terminology-copy-cleanup/` has completed checklist signals and terminology audit artifacts.
- `specs/299-managed-environment-cutover-final-seal/` has completed checklist signals and final cutover audit artifacts.
- Current model/table truth:
- `App\Models\ManagedEnvironment` exists.
- `ManagedEnvironmentFactory` exists.
- `managed_environments` exists.
- No active `App\Models\Tenant` model was found through application info or `app/Models` scan.
- Current route truth:
- `/admin/workspaces/{workspace}/environments/...` routes exist.
- `/admin/t` and `/admin/tenants` had no matching routes via Boost route lookup.
- Sail route scan shows canonical environment routes still use `{tenant}` as a route parameter and active classes such as `TenantDashboard`, `TenantDiagnostics`, and `TenantRequiredPermissions`.
- Current scan volume:
- Broad tenant scan: 2323 line hits.
- Provider-allowed scan: 1661 line hits.
- Migration/schema scan: 851 line hits.
- Legacy route/helper/resource scan: 242 line hits.
## Phase 0: Preparation And Safety
1. Confirm branch and dirty state.
2. Refresh the inventory scans in `tenant-reference-inventory.md`.
3. Stop if unrelated uncommitted changes exist.
4. Stop if production-data migration requirements are discovered.
5. Confirm no app implementation begins until spec/plan/tasks/checklist are accepted.
## Phase 1: Baseline Inventory And Guard Tests
1. Run required route/source/provider/schema scans.
2. Expand `tenant-reference-inventory.md` from preparation summary into file-level classification.
3. Expand `allowed-tenant-references.md` with all provider/framework/historical/regression-guard references.
4. Add/update guard tests for route resurrection, active `Tenant*` platform owners, stale helper names, and provider terminology preservation.
## Phase 2: DB And Schema Naming Cleanup
1. Verify `managed_environments` remains the source-of-truth table.
2. Rename platform-owned tenant-named tables/columns/indexes/constraints where safe.
3. Rename migration filenames/classes where they are historical names for active platform Managed Environment truth and pre-production safety allows it.
4. Keep provider-owned `entra_tenant_id` / `microsoft_tenant_id` payload fields.
5. Validate with `migrate:fresh --seed` or document why targeted migration validation is the narrower proof.
## Phase 3: Model, Factory, Service, And Helper Rename
1. Keep `ManagedEnvironment` model and `ManagedEnvironmentFactory` as canonical.
2. Rename platform-owned model classes such as `TenantPermission`, `TenantSetting`, `TenantRoleMapping`, `TenantOnboardingSession`, and review/triage classes when classification says they represent Managed Environment-owned truth.
3. Rename platform-owned service/support classes and variables.
4. Remove stale compatibility aliases.
5. Run focused Unit/Feature tests for renamed helpers and services.
## Phase 4: Filament Resource/Page/Widget Rename
1. Rename `TenantResource` and nested Pages/RelationManagers to environment-first names.
2. Rename `TenantDashboard`, `TenantDiagnostics`, and `TenantRequiredPermissions` to environment-first page names.
3. Update route owner classes and route names without changing canonical URL segments.
4. Review global search: renamed resources must have View/Edit pages or disable global search.
5. Preserve destructive action confirmation, server authorization, and audit behavior.
## Phase 5: Tests, Fixtures, Browser Anchors
1. Rename stale test helpers and fixtures.
2. Keep negative guard literals only where explicitly documented.
3. Update Browser smoke selectors only where visible copy/test IDs depend on renamed technical owners.
4. Run focused validation lanes and Browser anchors.
## Phase 6: Final Classification And Validation
1. Rerun final scans.
2. Ensure no unclassified active platform-owned tenant references remain.
3. Complete final `tenant-reference-inventory.md` and `allowed-tenant-references.md`.
4. Run Pint dirty and `git diff --check`.
5. Produce final implementation report with rename summary, DB changes, remaining references, route contract, validation, and decision.
## Risk Controls
- No blind global search/replace.
- No permanent alias classes.
- No route compatibility layer.
- No dual-write/dual-read unless this spec is stopped and replaced with a production migration spec.
- Provider-specific and framework-required tenant references must be preserved, not renamed for cleanliness.
- Broad scan output must be triaged before code changes.
- Keep implementation commits phased so rollback/review is possible.
## Final Decision Criteria
Implementation may report only one of:
- `merge-ready; internal tenant naming consolidation complete`
- `merge-ready with documented provider/framework tenant references`
- `blocked by unresolved platform-owned tenant references`
- `blocked by migration/schema risk`
- `incomplete; canonical route or RBAC regression found`