## Summary - cut over the admin runtime to the workspace-first environment and operations routes from spec 280 - retarget governance artifact resources, related navigation, and operation drillthroughs to the surviving admin panel contract from spec 282 - add focused feature and browser coverage plus spec close-out updates for the shipped 280/282 slice ## Validation - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/WorkspaceFoundation tests/Feature/Workspaces tests/Feature/ManagedEnvironment tests/Feature/RequiredPermissions tests/Feature/Operations tests/Feature/MonitoringOperationsTest.php` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec280WorkspaceTenancyEnvironmentRoutingSmokeTest.php` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/GovernanceArtifacts/GovernanceArtifactAdminPanelRegistrationTest.php tests/Feature/Filament/GovernanceArtifacts/GovernanceArtifactEnvironmentContextTest.php tests/Feature/Filament/GovernanceArtifacts/GovernanceArtifactDeepLinkContractTest.php tests/Feature/Filament/GovernanceArtifacts/GovernanceArtifactLegacyTenantPanelGuardTest.php` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec282GovernanceArtifactRetargetingSmokeTest.php` ## Notes - provider registration remains in `apps/platform/bootstrap/providers.php` - Filament stays on v5 with Livewire v4 semantics - touched searchable governance surfaces remain truthful or disabled in the same slice Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #341
117 lines
4.8 KiB
PHP
117 lines
4.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Resources\TenantReviewResource;
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\Workspace;
|
|
use Tests\Support\OpsUx\SourceFileScanner;
|
|
|
|
/**
|
|
* @return list<string>
|
|
*/
|
|
function governanceArtifactLegacyTenantGuardedFiles(): array
|
|
{
|
|
$root = SourceFileScanner::projectRoot();
|
|
|
|
return [
|
|
$root.'/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php',
|
|
$root.'/app/Filament/Pages/Reviews/ReviewRegister.php',
|
|
$root.'/app/Filament/Resources/BackupScheduleResource.php',
|
|
$root.'/app/Filament/Resources/BackupSetResource.php',
|
|
$root.'/app/Filament/Resources/EvidenceSnapshotResource.php',
|
|
$root.'/app/Filament/Resources/FindingExceptionResource.php',
|
|
$root.'/app/Filament/Resources/FindingResource.php',
|
|
$root.'/app/Filament/Resources/InventoryItemResource.php',
|
|
$root.'/app/Filament/Resources/PolicyResource.php',
|
|
$root.'/app/Filament/Resources/PolicyVersionResource.php',
|
|
$root.'/app/Filament/Resources/RestoreRunResource.php',
|
|
$root.'/app/Filament/Resources/ReviewPackResource.php',
|
|
$root.'/app/Filament/Resources/StoredReportResource.php',
|
|
$root.'/app/Filament/Resources/TenantReviewResource.php',
|
|
$root.'/app/Support/GovernanceInbox/GovernanceInboxSectionBuilder.php',
|
|
$root.'/app/Support/Navigation/RelatedNavigationResolver.php',
|
|
$root.'/app/Support/OperationRunLinks.php',
|
|
$root.'/app/Support/SupportDiagnostics/SupportDiagnosticBundleBuilder.php',
|
|
$root.'/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return list<array{pattern: string, reason: string}>
|
|
*/
|
|
function governanceArtifactLegacyTenantForbiddenPatterns(): array
|
|
{
|
|
return [
|
|
[
|
|
'pattern' => "/panel:\\s*'tenant'/",
|
|
'reason' => 'Touched governance artifact surfaces must not emit tenant-panel URLs directly.',
|
|
],
|
|
[
|
|
'pattern' => '/\\/admin\\/t\\//',
|
|
'reason' => 'Touched governance artifact surfaces must not hardcode legacy /admin/t route language.',
|
|
],
|
|
[
|
|
'pattern' => "/TenantReviewResource::tenantScopedUrl\\([^\\n]*,\\s*'tenant'\\)/",
|
|
'reason' => 'Touched review drillthrough call-sites must not carry a stale tenant-panel hint.',
|
|
],
|
|
[
|
|
'pattern' => '/\\bManagedEnvironment::current\\s*\\(/',
|
|
'reason' => 'Touched governance artifact surfaces must not rely on tenant-panel-only current-environment fallbacks.',
|
|
],
|
|
[
|
|
'pattern' => '/\\bFilament::getTenant\\s*\\(/',
|
|
'reason' => 'Touched governance artifact surfaces must resolve admin context through the shared panel resolver, not raw Filament tenant reads.',
|
|
],
|
|
[
|
|
'pattern' => "/getCurrentPanel\\(\\)\\?->getId\\(\\)\\s*===\\s*'admin'/",
|
|
'reason' => 'Touched governance artifact resources must not stay hidden behind admin-only registration guards.',
|
|
],
|
|
];
|
|
}
|
|
|
|
it('keeps touched governance artifact sources free of tenant-panel route language and fallback guards', function (): void {
|
|
$violations = [];
|
|
|
|
foreach (governanceArtifactLegacyTenantGuardedFiles() as $path) {
|
|
$source = SourceFileScanner::read($path);
|
|
$lines = preg_split('/\R/', $source) ?: [];
|
|
|
|
foreach ($lines as $index => $line) {
|
|
foreach (governanceArtifactLegacyTenantForbiddenPatterns() as $pattern) {
|
|
if (preg_match($pattern['pattern'], $line) !== 1) {
|
|
continue;
|
|
}
|
|
|
|
$violations[] = [
|
|
'file' => SourceFileScanner::relativePath($path),
|
|
'line' => $index + 1,
|
|
'snippet' => SourceFileScanner::snippet($source, $index + 1),
|
|
'reason' => $pattern['reason'],
|
|
];
|
|
}
|
|
}
|
|
}
|
|
|
|
expect($violations)->toBeEmpty();
|
|
})->group('surface-guard');
|
|
|
|
it('keeps tenant review scoped urls on workspace-first admin routes even when a legacy tenant hint is supplied', function (): void {
|
|
$tenant = ManagedEnvironment::factory()->create();
|
|
[$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', setUiContext: false);
|
|
|
|
$snapshot = seedTenantReviewEvidence($tenant);
|
|
$review = composeTenantReviewForTest($tenant, $user, $snapshot);
|
|
$workspace = Workspace::query()->whereKey((int) $tenant->workspace_id)->firstOrFail();
|
|
|
|
setAdminPanelContext();
|
|
|
|
$path = parse_url(
|
|
TenantReviewResource::tenantScopedUrl('view', ['record' => $review], $tenant, 'tenant'),
|
|
PHP_URL_PATH,
|
|
);
|
|
|
|
expect($path)
|
|
->toBe('/admin/workspaces/'.$workspace->getRouteKey().'/environments/'.$tenant->getRouteKey().'/reviews/'.$review->getRouteKey())
|
|
->not->toContain('/admin/t/');
|
|
})->group('surface-guard'); |