Automated PR created by Codex via Gitea API. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #462
250 lines
9.6 KiB
PHP
250 lines
9.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Pages\Monitoring\Operations;
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\OperationRun;
|
|
use App\Support\OperationRunLinks;
|
|
use App\Support\OperationRunOutcome;
|
|
use App\Support\OperationRunStatus;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Livewire\Livewire;
|
|
|
|
it('Spec391 renders the environment-filtered Operations Hub without debug leakage or unbounded workbench selection', function (): void {
|
|
bindFailHardGraphClient();
|
|
|
|
$environment = ManagedEnvironment::factory()->active()->create([
|
|
'name' => 'Spec391 Stable Environment',
|
|
]);
|
|
[$user, $environment] = createUserWithTenant($environment, role: 'owner', workspaceRole: 'owner');
|
|
|
|
$siblingEnvironment = ManagedEnvironment::factory()->active()->create([
|
|
'workspace_id' => (int) $environment->workspace_id,
|
|
'name' => 'Spec391 Hidden Sibling Environment',
|
|
]);
|
|
createUserWithTenant(tenant: $siblingEnvironment, user: $user, role: 'owner', workspaceRole: 'owner');
|
|
|
|
OperationRun::factory()->forTenant($environment)->create([
|
|
'type' => 'inventory_sync',
|
|
'status' => OperationRunStatus::Completed->value,
|
|
'outcome' => OperationRunOutcome::Blocked->value,
|
|
'initiator_name' => 'Spec391 allowed operator',
|
|
'context' => [
|
|
'reason_code' => 'write_gate_blocked',
|
|
'raw_payload' => 'spec391 raw payload should stay hidden',
|
|
'stack_trace' => 'spec391 stack trace should stay hidden',
|
|
'debug_metadata' => 'spec391 debug metadata should stay hidden',
|
|
'target_scope' => [
|
|
'scope_display_name' => 'Spec391 Stable Environment',
|
|
],
|
|
],
|
|
'failure_summary' => [
|
|
'exception' => 'spec391 exception detail should stay hidden',
|
|
],
|
|
'completed_at' => null,
|
|
]);
|
|
|
|
foreach (range(1, 54) as $index) {
|
|
OperationRun::factory()->forTenant($environment)->create([
|
|
'type' => $index % 2 === 0 ? 'policy.sync' : 'backup.schedule.execute',
|
|
'status' => OperationRunStatus::Completed->value,
|
|
'outcome' => $index % 3 === 0
|
|
? OperationRunOutcome::Failed->value
|
|
: OperationRunOutcome::Succeeded->value,
|
|
'initiator_name' => 'Spec391 bulk operator '.$index,
|
|
'context' => [
|
|
'target_scope' => [
|
|
'scope_display_name' => 'Spec391 Stable Environment',
|
|
'scope_identifier' => 'spec391-'.$index,
|
|
],
|
|
'raw_payload' => str_repeat('large-spec391-payload-', 200),
|
|
],
|
|
'completed_at' => now()->subMinutes($index),
|
|
]);
|
|
}
|
|
|
|
OperationRun::factory()->forTenant($siblingEnvironment)->create([
|
|
'type' => 'restore.execute',
|
|
'status' => OperationRunStatus::Completed->value,
|
|
'outcome' => OperationRunOutcome::Failed->value,
|
|
'initiator_name' => 'Spec391 hidden sibling operator',
|
|
]);
|
|
|
|
$operationsUrl = OperationRunLinks::index($environment);
|
|
|
|
expect($operationsUrl)
|
|
->toContain('environment_id='.(int) $environment->getKey())
|
|
->toContain('/operations');
|
|
|
|
$queries = [];
|
|
|
|
DB::flushQueryLog();
|
|
DB::enableQueryLog();
|
|
|
|
try {
|
|
$response = assertNoOutboundHttp(function () use ($environment, $operationsUrl, $user) {
|
|
return $this
|
|
->actingAs($user)
|
|
->withSession([WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id])
|
|
->get($operationsUrl);
|
|
});
|
|
} finally {
|
|
$queries = DB::getQueryLog();
|
|
DB::disableQueryLog();
|
|
}
|
|
|
|
$response
|
|
->assertOk()
|
|
->assertSee('Operations Hub')
|
|
->assertSee('Environment filter:')
|
|
->assertSee('Spec391 Stable Environment')
|
|
->assertSee('Inventory sync');
|
|
|
|
foreach ([
|
|
'Maximum execution time',
|
|
'HasAttributes.php',
|
|
'Stack trace',
|
|
'_debugbar',
|
|
'phpstorm://',
|
|
'filamentSchema is not defined',
|
|
'spec391 raw payload should stay hidden',
|
|
'spec391 stack trace should stay hidden',
|
|
'spec391 debug metadata should stay hidden',
|
|
'spec391 exception detail should stay hidden',
|
|
'Spec391 hidden sibling operator',
|
|
] as $signature) {
|
|
$response->assertDontSee($signature, false);
|
|
}
|
|
|
|
$operationRunQueries = collect($queries)
|
|
->pluck('query')
|
|
->map(static fn (string $query): string => mb_strtolower($query));
|
|
|
|
$candidateQueries = $operationRunQueries
|
|
->filter(static fn (string $query): bool => str_contains($query, 'operation_runs')
|
|
&& str_contains($query, 'case')
|
|
&& str_contains($query, 'limit 1'))
|
|
->values();
|
|
|
|
expect($candidateQueries)->not->toBeEmpty()
|
|
->and($candidateQueries->first())->not->toContain('select *')
|
|
->and($operationRunQueries->contains(
|
|
static fn (string $query): bool => str_contains($query, 'operation_runs')
|
|
&& str_contains($query, 'limit 50'),
|
|
))->toBeFalse();
|
|
});
|
|
|
|
it('Spec391 renders a controlled empty Operations state for an entitled environment', function (): void {
|
|
bindFailHardGraphClient();
|
|
|
|
$environment = ManagedEnvironment::factory()->active()->create([
|
|
'name' => 'Spec391 Empty Environment',
|
|
]);
|
|
[$user, $environment] = createUserWithTenant($environment, role: 'owner', workspaceRole: 'owner');
|
|
|
|
$response = assertNoOutboundHttp(function () use ($environment, $user) {
|
|
return $this
|
|
->actingAs($user)
|
|
->withSession([WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id])
|
|
->get(OperationRunLinks::index($environment));
|
|
});
|
|
|
|
$response
|
|
->assertOk()
|
|
->assertSee('Operations Hub')
|
|
->assertSee('Environment filter:')
|
|
->assertSee('Spec391 Empty Environment')
|
|
->assertSee('No operations need follow-up')
|
|
->assertSee('No failed, blocked, partial, or stale OperationRuns are visible in this scope.')
|
|
->assertSee('No operations found')
|
|
->assertDontSee('environment is healthy')
|
|
->assertDontSee('governance health is complete')
|
|
->assertDontSee('Maximum execution time')
|
|
->assertDontSee('Stack trace');
|
|
});
|
|
|
|
it('Spec391 bounds Operations Hub filter option catalogs to the requested environment scope', function (): void {
|
|
$environment = ManagedEnvironment::factory()->active()->create([
|
|
'name' => 'Spec391 Entitled Environment',
|
|
]);
|
|
[$user, $environment] = createUserWithTenant($environment, role: 'owner', workspaceRole: 'owner');
|
|
|
|
$unentitledSibling = ManagedEnvironment::factory()->active()->create([
|
|
'workspace_id' => (int) $environment->workspace_id,
|
|
'name' => 'Spec391 Unentitled Sibling',
|
|
]);
|
|
|
|
$foreignEnvironment = ManagedEnvironment::factory()->active()->create([
|
|
'name' => 'Spec391 Foreign Environment',
|
|
]);
|
|
|
|
OperationRun::factory()->forTenant($environment)->create([
|
|
'type' => 'inventory_sync',
|
|
'initiator_name' => 'Spec391 entitled operator',
|
|
]);
|
|
|
|
OperationRun::factory()->tenantlessForWorkspace($environment->workspace()->firstOrFail())->create([
|
|
'type' => 'backup.schedule.execute',
|
|
'initiator_name' => 'Spec391 workspace operator',
|
|
]);
|
|
|
|
OperationRun::factory()->forTenant($unentitledSibling)->create([
|
|
'type' => 'policy.sync',
|
|
'initiator_name' => 'Spec391 unentitled operator',
|
|
]);
|
|
|
|
OperationRun::factory()->forTenant($foreignEnvironment)->create([
|
|
'type' => 'restore.execute',
|
|
'initiator_name' => 'Spec391 foreign operator',
|
|
]);
|
|
|
|
$this->actingAs($user);
|
|
setAdminPanelContext($environment);
|
|
session()->put(WorkspaceContext::SESSION_KEY, (int) $environment->workspace_id);
|
|
|
|
$component = Livewire::withQueryParams(['environment_id' => (int) $environment->getKey()])
|
|
->actingAs($user)
|
|
->test(Operations::class);
|
|
|
|
$environmentFilter = $component->instance()->getTable()->getFilter('managed_environment_id');
|
|
$typeFilter = $component->instance()->getTable()->getFilter('type');
|
|
$initiatorFilter = $component->instance()->getTable()->getFilter('initiator_name');
|
|
|
|
expect($environmentFilter?->getOptions())
|
|
->toHaveKey((string) $environment->getKey())
|
|
->not->toHaveKey((string) $unentitledSibling->getKey())
|
|
->not->toHaveKey((string) $foreignEnvironment->getKey());
|
|
|
|
expect($typeFilter?->getOptions())
|
|
->toHaveKey('inventory.sync')
|
|
->not->toHaveKey('backup.schedule.execute')
|
|
->not->toHaveKey('policy.sync')
|
|
->not->toHaveKey('restore.execute');
|
|
|
|
expect($initiatorFilter?->getOptions())
|
|
->toHaveKey('Spec391 entitled operator')
|
|
->not->toHaveKey('Spec391 workspace operator')
|
|
->not->toHaveKey('Spec391 unentitled operator')
|
|
->not->toHaveKey('Spec391 foreign operator');
|
|
});
|
|
|
|
it('Spec391 rejects same-workspace environment filters when the environment is not entitled', function (): void {
|
|
$environment = ManagedEnvironment::factory()->active()->create();
|
|
[$user, $environment] = createUserWithTenant($environment, role: 'owner', workspaceRole: 'owner');
|
|
|
|
$unentitledSibling = ManagedEnvironment::factory()->active()->create([
|
|
'workspace_id' => (int) $environment->workspace_id,
|
|
]);
|
|
|
|
$this
|
|
->actingAs($user)
|
|
->withSession([WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id])
|
|
->get(route('admin.operations.index', [
|
|
'workspace' => $environment->workspace,
|
|
'environment_id' => (int) $unentitledSibling->getKey(),
|
|
]))
|
|
->assertNotFound();
|
|
});
|