TenantAtlas/tests/Feature/Authorization/OperatorExplanationSurfaceAuthorizationTest.php
ahmido 1f0cc5de56 feat: implement operator explanation layer (#191)
## Summary
- add the shared operator explanation layer with explanation families, trustworthiness semantics, count descriptors, and centralized badge mappings
- adopt explanation-first rendering across baseline compare, governance operation run detail, baseline snapshot presentation, tenant review detail, and review register rows
- extend reason translation, artifact-truth presentation, fallback ops UX messaging, and focused regression coverage for operator explanation semantics

## Testing
- vendor/bin/sail bin pint --dirty --format agent
- vendor/bin/sail artisan test --compact tests/Feature/Monitoring/OperationsTenantScopeTest.php tests/Feature/Operations/OperationRunBlockedExecutionPresentationTest.php
- vendor/bin/sail artisan test --compact

## Notes
- Livewire v4 compatible
- panel provider registration remains in bootstrap/providers.php
- no destructive Filament actions were added or changed in this PR
- no new global-search behavior was introduced in this slice

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #191
2026-03-24 11:24:33 +00:00

102 lines
3.9 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\BaselineCompareLanding;
use App\Filament\Pages\Reviews\ReviewRegister;
use App\Filament\Resources\BaselineSnapshotResource;
use App\Filament\Resources\TenantReviewResource;
use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot;
use App\Models\OperationRun;
use App\Models\Tenant;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Services\Auth\WorkspaceCapabilityResolver;
use App\Support\Workspaces\WorkspaceContext;
it('returns 404 for non-members on the baseline compare explanation surface', function (): void {
[$member, $tenant] = createUserWithTenant(role: 'owner');
$nonMember = User::factory()->create();
$this->actingAs($nonMember)
->get(BaselineCompareLanding::getUrl(tenant: $tenant, panel: 'tenant'))
->assertNotFound();
});
it('returns 403 for members missing the required capability on the canonical run detail surface', function (): void {
$tenant = Tenant::factory()->create();
[$owner, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');
[$readonly] = createUserWithTenant(tenant: $tenant, user: User::factory()->create(), role: 'readonly');
$run = OperationRun::factory()->create([
'tenant_id' => (int) $tenant->getKey(),
'workspace_id' => (int) $tenant->workspace_id,
'type' => 'inventory_sync',
]);
$this->actingAs($readonly)
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
->get(route('admin.operations.view', ['run' => (int) $run->getKey()]))
->assertForbidden();
});
it('returns 403 for workspace members missing baseline snapshot visibility on explanation-first baseline capture surfaces', function (): void {
$workspace = Workspace::factory()->create();
$user = User::factory()->create();
WorkspaceMembership::factory()->create([
'workspace_id' => (int) $workspace->getKey(),
'user_id' => (int) $user->getKey(),
'role' => 'readonly',
]);
$profile = BaselineProfile::factory()->active()->create([
'workspace_id' => (int) $workspace->getKey(),
]);
$snapshot = BaselineSnapshot::factory()->create([
'workspace_id' => (int) $workspace->getKey(),
'baseline_profile_id' => (int) $profile->getKey(),
]);
$resolver = \Mockery::mock(WorkspaceCapabilityResolver::class);
$resolver->shouldReceive('isMember')->andReturnTrue();
$resolver->shouldReceive('can')->andReturnFalse();
app()->instance(WorkspaceCapabilityResolver::class, $resolver);
$this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()])
->get(BaselineSnapshotResource::getUrl('view', ['record' => $snapshot], panel: 'admin'))
->assertForbidden();
});
it('returns 404 for non-members on the tenant review explanation detail surface', function (): void {
$targetTenant = Tenant::factory()->create();
[$member] = createUserWithTenant(role: 'owner');
$reviewOwner = User::factory()->create();
createUserWithTenant(tenant: $targetTenant, user: $reviewOwner, role: 'owner');
$review = composeTenantReviewForTest($targetTenant, $reviewOwner);
$this->actingAs($member)
->get(TenantReviewResource::tenantScopedUrl('view', ['record' => $review], $targetTenant))
->assertNotFound();
});
it('returns 404 for workspace members without entitled tenant visibility on the review register explanation surface', function (): void {
$workspace = Workspace::factory()->create();
$user = User::factory()->create();
WorkspaceMembership::factory()->create([
'workspace_id' => (int) $workspace->getKey(),
'user_id' => (int) $user->getKey(),
'role' => 'owner',
]);
$this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()])
->get(ReviewRegister::getUrl(panel: 'admin'))
->assertNotFound();
});