TenantAtlas/apps/platform/tests/Feature/Guards/LegacyTenantPlatformContextCleanupTest.php
ahmido b159dacd36 feat: clean up legacy tenant environment context (#372)
## Summary
- remove legacy tenant-scoped routing and middleware paths in favor of the current environment/workspace context flow
- update Filament pages and resources to use the cleaned-up admin surface and environment filter context
- add the related spec 317 artifacts and targeted tests for environment filter state and legacy context cleanup

## Testing
- not run as part of this commit/push/PR workflow

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #372
2026-05-16 18:25:36 +00:00

225 lines
7.8 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EnvironmentReviewResource;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;
use Illuminate\Support\Facades\Route;
/**
* @return list<string>
*/
function spec317Files(array $roots): array
{
$files = [];
foreach ($roots as $root) {
if (is_file($root)) {
$files[] = $root;
continue;
}
if (! is_dir($root)) {
continue;
}
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS),
);
foreach ($iterator as $file) {
if (! $file instanceof SplFileInfo || ! $file->isFile()) {
continue;
}
if ($file->getFilename() === 'LegacyTenantPlatformContextCleanupTest.php') {
continue;
}
if (! in_array($file->getExtension(), ['php', 'md'], true)) {
continue;
}
$files[] = $file->getPathname();
}
}
sort($files);
return array_values(array_unique($files));
}
/**
* @param list<string> $files
* @param list<string> $patterns
* @return list<string>
*/
function spec317PatternHits(array $files, array $patterns): array
{
$hits = [];
foreach ($files as $path) {
$contents = file_get_contents($path);
if (! is_string($contents)) {
continue;
}
$lines = preg_split('/\R/', $contents) ?: [];
foreach ($patterns as $pattern) {
foreach ($lines as $lineNumber => $line) {
if (preg_match($pattern, $line) !== 1) {
continue;
}
$hits[] = str_replace(repo_path().'/', '', $path).':'.($lineNumber + 1).' -> '.trim($line);
}
}
}
return $hits;
}
it('removes retired platform-context helper and class names from active runtime seams', function (): void {
$files = spec317Files([
base_path('app'),
base_path('bootstrap/app.php'),
base_path('routes/web.php'),
base_path('tests/Feature/Guards'),
base_path('tests/Feature/Navigation'),
base_path('tests/Feature/Reviews'),
]);
$hits = spec317PatternHits($files, [
'/\btenantPrefilterUrl\s*\(/',
'/\bCanonicalAdminTenantFilterState\b/',
'/\bWorkspaceScopedTenantRoutes\b/',
'/\bTenantPageCategory\b/',
'/\bEnsureFilamentTenantSelected\b/',
'/ensure-filament-tenant-selected/',
'/\blastTenantId\s*\(/',
'/\brememberedTenant\s*\(/',
'/\brememberTenantContext\s*\(/',
'/\bLAST_TENANT_IDS_SESSION_KEY\b/',
'/\bTenantBound\b/',
'/\bTenantScopedEvidence\b/',
]);
expect($hits)->toBeEmpty("Retired Tenant platform-context names remain:\n".implode("\n", $hits));
});
it('keeps current product-truth docs on workspace and environment terminology', function (): void {
$files = spec317Files([
repo_path('docs/HANDOVER.md'),
repo_path('docs/product/spec-candidates.md'),
repo_path('docs/product/implementation-ledger.md'),
repo_path('docs/product/roadmap.md'),
repo_path('docs/product/principles.md'),
repo_path('docs/ui'),
repo_path('docs/architecture-guidelines.md'),
repo_path('docs/filament-guidelines.md'),
repo_path('docs/testing-guidelines.md'),
]);
$hits = spec317PatternHits($files, [
'/\btenantPrefilterUrl\b/',
'/\bCanonicalAdminTenantFilterState\b/',
'/\bWorkspaceScopedTenantRoutes\b/',
'/\bTenantPageCategory\b/',
'/\bEnsureFilamentTenantSelected\b/',
'/\blastTenantId\b/',
'/\btenantScopedUrl\b/',
]);
expect($hits)->toBeEmpty("Current docs still describe retired Tenant platform context:\n".implode("\n", $hits));
});
it('keeps workspace hubs free of hidden Filament or remembered Environment scope fallbacks', function (): void {
$files = spec317Files([
base_path('app/Filament/Pages/Monitoring/Operations.php'),
base_path('app/Filament/Pages/Monitoring/FindingExceptionsQueue.php'),
base_path('app/Filament/Pages/Governance/GovernanceInbox.php'),
base_path('app/Filament/Pages/Governance/DecisionRegister.php'),
base_path('app/Filament/Pages/Monitoring/EvidenceOverview.php'),
base_path('app/Filament/Pages/Reviews/ReviewRegister.php'),
base_path('app/Filament/Pages/Reviews/CustomerReviewWorkspace.php'),
base_path('app/Filament/Resources/ProviderConnectionResource.php'),
base_path('app/Filament/Resources/ProviderConnectionResource/Pages/ListProviderConnections.php'),
]);
$hits = spec317PatternHits($files, [
'/\bFilament::getTenant\s*\(/',
'/\blastEnvironmentId\s*\(/',
'/\brememberedEnvironment\s*\(/',
'/\brememberEnvironmentContext\s*\(/',
]);
expect($hits)->toBeEmpty("Workspace hubs must not derive scope from Filament tenant or remembered Environment state:\n".implode("\n", $hits));
});
it('keeps helper APIs hard-cut to Environment names and canonical filter keys', function (): void {
expect(method_exists(CustomerReviewWorkspace::class, 'tenantPrefilterUrl'))->toBeFalse()
->and(method_exists(CustomerReviewWorkspace::class, 'environmentFilterUrl'))->toBeTrue();
$reviewUrlHelper = new ReflectionMethod(EnvironmentReviewResource::class, 'environmentScopedUrl');
$providerConnectionResource = (string) file_get_contents(base_path('app/Filament/Resources/ProviderConnectionResource.php'));
expect(method_exists(EnvironmentReviewResource::class, 'tenantScopedUrl'))->toBeFalse()
->and($reviewUrlHelper->getNumberOfParameters())->toBe(3)
->and($providerConnectionResource)
->not->toContain("array_key_exists('tenant', \$parameters)")
->not->toContain('resolveRequestedTenantExternalId() ?? static::resolveContextTenantExternalId()');
});
it('keeps active environment dashboard links free of retired tenant query aliases', function (): void {
[$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'owner');
$workspace = $environment->workspace()->firstOrFail();
$this->actingAs($user);
Filament::setTenant($environment, true);
$response = $this
->withSession([
WorkspaceContext::SESSION_KEY => (int) $workspace->getKey(),
WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [
(string) $workspace->getKey() => (int) $environment->getKey(),
],
])
->get(ManagedEnvironmentLinks::viewUrl($environment));
$response->assertOk();
$content = html_entity_decode((string) $response->getContent(), ENT_QUOTES | ENT_HTML5);
expect($content)
->not->toContain('/admin/t')
->not->toContain('?tenant=')
->not->toContain('&tenant=')
->not->toContain('tenant_id=')
->not->toContain('managed_environment_id=')
->not->toContain('tenant_scope=');
});
it('does not register active legacy tenant panel routes or providers', function (): void {
$legacyRouteUris = collect(Route::getRoutes())
->map(fn ($route): string => ltrim((string) $route->uri(), '/'))
->filter(fn (string $uri): bool => preg_match('#^admin/t(?:/|$)#', $uri) === 1)
->values();
$registeredProviders = require base_path('bootstrap/providers.php');
$tenantPanelProviders = collect($registeredProviders)
->filter(fn (string $provider): bool => str_contains($provider, 'TenantPanelProvider'))
->values();
expect($legacyRouteUris)->toBeEmpty()
->and($tenantPanelProviders)->toBeEmpty()
->and(file_exists(app_path('Providers/Filament/TenantPanelProvider.php')))->toBeFalse();
});