TenantAtlas/apps/platform/tests/Feature/Guards/OperationRunLinkContractGuardTest.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

154 lines
6.1 KiB
PHP

<?php
declare(strict_types=1);
use App\Support\OperationRunLinks;
use Tests\Support\OpsUx\SourceFileScanner;
/**
* @return array<string, string>
*/
function operationRunLinkContractIncludePaths(): array
{
$root = SourceFileScanner::projectRoot();
return [
'environment_recent_operations_summary' => $root.'/app/Filament/Widgets/ManagedEnvironment/RecentOperationsSummary.php',
'inventory_coverage' => $root.'/app/Filament/Pages/InventoryCoverage.php',
'inventory_item_resource' => $root.'/app/Filament/Resources/InventoryItemResource.php',
'review_pack_resource' => $root.'/app/Filament/Resources/ReviewPackResource.php',
'tenantless_operation_run_viewer' => $root.'/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php',
'related_navigation_resolver' => $root.'/app/Support/Navigation/RelatedNavigationResolver.php',
'system_directory_tenant' => $root.'/app/Filament/System/Pages/Directory/ViewTenant.php',
'system_directory_workspace' => $root.'/app/Filament/System/Pages/Directory/ViewWorkspace.php',
'system_ops_runs' => $root.'/app/Filament/System/Pages/Ops/Runs.php',
'system_ops_view_run' => $root.'/app/Filament/System/Pages/Ops/ViewRun.php',
'admin_panel_provider' => $root.'/app/Providers/Filament/AdminPanelProvider.php',
'ensure_environment_context_selected' => $root.'/app/Support/Middleware/EnsureEnvironmentContextSelected.php',
'clear_environment_context_controller' => $root.'/app/Http/Controllers/ClearEnvironmentContextController.php',
'operation_run_url_delegate' => $root.'/app/Support/OpsUx/OperationRunUrl.php',
];
}
/**
* @return array<string, string>
*/
function operationRunLinkContractAllowlist(): array
{
return [];
}
/**
* @param array<string, string> $paths
* @param array<string, string> $allowlist
* @return list<array{file: string, line: int, snippet: string, expectedHelper: string, reason: string}>
*/
function operationRunLinkContractViolations(array $paths, array $allowlist = []): array
{
$patterns = [
[
'pattern' => '/route\(\s*[\'"]admin\.operations\.index[\'"]/',
'expectedHelper' => 'OperationRunLinks::index(...)',
'reason' => 'Raw admin operations collection route assembly bypasses the canonical admin link helper.',
],
[
'pattern' => '/route\(\s*[\'"]admin\.operations\.view[\'"]/',
'expectedHelper' => 'OperationRunLinks::view(...) or OperationRunLinks::tenantlessView(...)',
'reason' => 'Raw admin operation detail route assembly bypasses the canonical admin link helper.',
],
[
'pattern' => '/[\'"]\/system\/ops\/runs(?:\/[^\'"]*)?[\'"]/',
'expectedHelper' => 'SystemOperationRunLinks::index() or SystemOperationRunLinks::view(...)',
'reason' => 'Direct system operations path assembly bypasses the canonical system link helper.',
],
[
'pattern' => '/\b(?:Runs|ViewRun)::getUrl\(/',
'expectedHelper' => 'SystemOperationRunLinks::index() or SystemOperationRunLinks::view(...)',
'reason' => 'Direct system operations page URL generation belongs behind the canonical system link helper.',
],
];
$violations = [];
foreach ($paths as $path) {
if (array_key_exists($path, $allowlist)) {
continue;
}
$source = SourceFileScanner::read($path);
$lines = preg_split('/\R/', $source) ?: [];
foreach ($lines as $index => $line) {
foreach ($patterns as $pattern) {
if (preg_match($pattern['pattern'], $line) !== 1) {
continue;
}
$violations[] = [
'file' => SourceFileScanner::relativePath($path),
'line' => $index + 1,
'snippet' => SourceFileScanner::snippet($source, $index + 1),
'expectedHelper' => $pattern['expectedHelper'],
'reason' => $pattern['reason'],
];
}
}
}
return $violations;
}
it('keeps covered operation run link producers on canonical helper families', function (): void {
$paths = operationRunLinkContractIncludePaths();
$allowlist = operationRunLinkContractAllowlist();
$violations = operationRunLinkContractViolations($paths, $allowlist);
expect($violations)->toBeEmpty();
})->group('surface-guard');
it('keeps the operation run link exception boundary explicit and infrastructure-owned', function (): void {
$allowlist = operationRunLinkContractAllowlist();
expect($allowlist)->toBeEmpty();
})->group('surface-guard');
it('reports actionable file and snippet output for a representative raw bypass', function (): void {
$probePath = storage_path('framework/testing/OperationRunLinkContractProbe.php');
if (! is_dir(dirname($probePath))) {
mkdir(dirname($probePath), 0777, true);
}
file_put_contents($probePath, <<<'PHP'
<?php
return route('admin.operations.view', ['run' => 123]);
PHP);
try {
$violations = operationRunLinkContractViolations([
'probe' => $probePath,
]);
} finally {
@unlink($probePath);
}
expect($violations)->toHaveCount(1)
->and($violations[0]['file'])->toContain('OperationRunLinkContractProbe.php')
->and($violations[0]['line'])->toBe(3)
->and($violations[0]['snippet'])->toContain("route('admin.operations.view'")
->and($violations[0]['expectedHelper'])->toContain('OperationRunLinks::view')
->and($violations[0]['reason'])->toContain('bypasses the canonical admin link helper');
})->group('surface-guard');
it('canonicalizes operation type query parameters for operation collection links', function (): void {
[$workspace] = localizationWorkspaceMember();
$url = OperationRunLinks::index(operationType: 'inventory_sync');
expect($url)->toContain('inventory.sync')
->toContain('/admin/workspaces/'.$workspace->getRouteKey().'/operations')
->not->toContain('inventory_sync');
})->group('surface-guard');