create([ 'tenant_id' => null, 'external_id' => 'platform', 'name' => 'Platform', ]); config()->set('tenantpilot.break_glass.enabled', true); config()->set('tenantpilot.break_glass.ttl_minutes', 15); }); function spec276_recovery_platform_user(): PlatformUser { return PlatformUser::factory()->create([ 'capabilities' => [ PlatformCapabilities::ACCESS_SYSTEM_PANEL, PlatformCapabilities::CONSOLE_VIEW, PlatformCapabilities::USE_BREAK_GLASS, ], ]); } function spec276_ownerless_workspace_with_target(): array { $workspace = Workspace::factory()->create(); $targetUser = User::factory()->create(); WorkspaceMembership::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'user_id' => (int) $targetUser->getKey(), 'role' => WorkspaceRole::Operator->value, ]); return [$workspace, $targetUser]; } it('blocks owner repair when break-glass is active but recovery-scoped support access is missing', function (): void { $platformUser = spec276_recovery_platform_user(); [$workspace, $targetUser] = spec276_ownerless_workspace_with_target(); $this->actingAs($platformUser, 'platform'); Livewire::test(Dashboard::class) ->callAction('enter_break_glass', data: [ 'reason' => 'Recover workspace ownership', ]); Livewire::test(RepairWorkspaceOwners::class) ->callAction('assign_owner', data: [ 'workspace_id' => (int) $workspace->getKey(), 'target_user_id' => (int) $targetUser->getKey(), 'reason' => 'Fix ownerless workspace', ]) ->assertHasErrors(); expect(WorkspaceMembership::query() ->where('workspace_id', (int) $workspace->getKey()) ->where('user_id', (int) $targetUser->getKey()) ->value('role'))->toBe(WorkspaceRole::Operator->value); }); it('does not allow audit-view support access to satisfy the owner-repair boundary', function (): void { $platformUser = spec276_recovery_platform_user(); [$workspace, $targetUser] = spec276_ownerless_workspace_with_target(); SupportAccessGrant::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'requested_by_platform_user_id' => (int) $platformUser->getKey(), 'scope' => SupportAccessGrant::SCOPE_AUDIT_VIEW, ]); $this->actingAs($platformUser, 'platform'); Livewire::test(Dashboard::class) ->callAction('enter_break_glass', data: [ 'reason' => 'Recover workspace ownership', ]); Livewire::test(RepairWorkspaceOwners::class) ->callAction('assign_owner', data: [ 'workspace_id' => (int) $workspace->getKey(), 'target_user_id' => (int) $targetUser->getKey(), 'reason' => 'Fix ownerless workspace', ]) ->assertHasErrors(); }); it('allows owner repair only when break-glass and active workspace-recovery support access are both present', function (): void { $platformUser = spec276_recovery_platform_user(); [$workspace, $targetUser] = spec276_ownerless_workspace_with_target(); $supportGrant = SupportAccessGrant::factory()->activeRecovery()->create([ 'workspace_id' => (int) $workspace->getKey(), 'requested_by_platform_user_id' => (int) $platformUser->getKey(), ]); $this->actingAs($platformUser, 'platform'); Livewire::test(Dashboard::class) ->callAction('enter_break_glass', data: [ 'reason' => 'Recover workspace ownership', ]); Livewire::test(RepairWorkspaceOwners::class) ->callAction('assign_owner', data: [ 'workspace_id' => (int) $workspace->getKey(), 'target_user_id' => (int) $targetUser->getKey(), 'reason' => 'Fix ownerless workspace', ]) ->assertHasNoActionErrors() ->assertNotified('Owner assigned'); expect(WorkspaceMembership::query() ->where('workspace_id', (int) $workspace->getKey()) ->where('user_id', (int) $targetUser->getKey()) ->value('role'))->toBe(WorkspaceRole::Owner->value); expect(AuditLog::query() ->where('workspace_id', (int) $workspace->getKey()) ->where('action', 'workspace_membership.break_glass.assign_owner') ->whereJsonContains('metadata->support_access_grant_id', (int) $supportGrant->getKey()) ->exists())->toBeTrue(); });