diff --git a/ee/spec/policies/ci/build_policy_spec.rb b/ee/spec/policies/ci/build_policy_spec.rb
index c893f4fed16ec832fb5a5860f71ddfe816c21e28..cb1f576dfa789eeb564c5359d0063e43c873d4b8 100644
--- a/ee/spec/policies/ci/build_policy_spec.rb
+++ b/ee/spec/policies/ci/build_policy_spec.rb
@@ -148,15 +148,5 @@ describe Ci::BuildPolicy do
         it_behaves_like 'forbidden access'
       end
     end
-
-    def expect_allowed(*permissions)
-      permissions.each { |p| is_expected.to be_allowed(p) }
-    end
-
-    def expect_disallowed(*permissions)
-      permissions.each do |p|
-        is_expected.not_to be_allowed(p)
-      end
-    end
   end
 end
diff --git a/ee/spec/policies/group_policy_spec.rb b/ee/spec/policies/group_policy_spec.rb
index bc5aae8f6e03556074fe9b257cf936a014523e24..18340c8a9059f81ddc030f4853a6a6e962923b5b 100644
--- a/ee/spec/policies/group_policy_spec.rb
+++ b/ee/spec/policies/group_policy_spec.rb
@@ -1,24 +1,7 @@
 require 'spec_helper'
 
 describe GroupPolicy do
-  let(:guest) { create(:user) }
-  let(:reporter) { create(:user) }
-  let(:developer) { create(:user) }
-  let(:maintainer) { create(:user) }
-  let(:owner) { create(:user) }
-  let(:auditor) { create(:user, :auditor) }
-  let(:admin) { create(:admin) }
-  let(:group) { create(:group) }
-
-  before do
-    group.add_guest(guest)
-    group.add_reporter(reporter)
-    group.add_developer(developer)
-    group.add_maintainer(maintainer)
-    group.add_owner(owner)
-  end
-
-  subject { described_class.new(current_user, group) }
+  include_context 'GroupPolicy context'
 
   context 'when epics feature is disabled' do
     let(:current_user) { owner }
@@ -406,8 +389,6 @@ describe GroupPolicy do
       stub_licensed_features(security_dashboard: true)
     end
 
-    subject { described_class.new(current_user, group) }
-
     context 'with admin' do
       let(:current_user) { admin }
 
@@ -465,9 +446,39 @@ describe GroupPolicy do
     end
   end
 
+  describe 'private nested group use the highest access level from the group and inherited permissions', :nested_groups do
+    let(:nested_group) { create(:group, :private, parent: group) }
+
+    before do
+      nested_group.add_guest(guest)
+      nested_group.add_guest(reporter)
+      nested_group.add_guest(developer)
+      nested_group.add_guest(maintainer)
+
+      group.owners.destroy_all # rubocop: disable DestroyAll
+
+      group.add_guest(owner)
+      nested_group.add_owner(owner)
+    end
+
+    subject { described_class.new(current_user, nested_group) }
+
+    context 'auditor' do
+      let(:current_user) { create(:user, :auditor) }
+
+      it do
+        expect_allowed(:read_group)
+        expect_disallowed(:upload_file)
+        expect_disallowed(*reporter_permissions)
+        expect_disallowed(*developer_permissions)
+        expect_disallowed(*maintainer_permissions)
+        expect_disallowed(*owner_permissions)
+      end
+    end
+  end
+
   it_behaves_like 'ee clusterable policies' do
     let(:clusterable) { create(:group) }
-
     let(:cluster) do
       create(:cluster,
              :provided_by_gcp,
diff --git a/ee/spec/policies/namespace_policy_spec.rb b/ee/spec/policies/namespace_policy_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..686f357dbb3346d4d023c17fe6876db872f1f172
--- /dev/null
+++ b/ee/spec/policies/namespace_policy_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe NamespacePolicy do
+  let(:owner) { create(:user) }
+  let(:namespace) { create(:namespace, owner: owner) }
+  let(:owner_permissions) { [:create_projects, :admin_namespace, :read_namespace] }
+
+  subject { described_class.new(current_user, namespace) }
+
+  context 'auditor' do
+    let(:current_user) { create(:user, :auditor) }
+
+    context 'owner' do
+      let(:namespace) { create(:namespace, owner: current_user) }
+
+      it { is_expected.to be_allowed(*owner_permissions) }
+    end
+
+    context 'non-owner' do
+      it { is_expected.to be_disallowed(*owner_permissions) }
+    end
+  end
+end
diff --git a/ee/spec/policies/project_policy_spec.rb b/ee/spec/policies/project_policy_spec.rb
index f4d70355afdf724d8ea32297611499bd8a5cceb5..6279741a675eef11e9916170884e018af801957e 100644
--- a/ee/spec/policies/project_policy_spec.rb
+++ b/ee/spec/policies/project_policy_spec.rb
@@ -11,19 +11,94 @@ describe ProjectPolicy do
   set(:guest) { create(:user) }
   let(:project) { create(:project, :public, namespace: owner.namespace) }
 
+  subject { described_class.new(current_user, project) }
+
   before do
     project.add_maintainer(maintainer)
     project.add_developer(developer)
     project.add_reporter(reporter)
     project.add_guest(guest)
+    stub_licensed_features(license_management: true)
+  end
+
+  context 'basic permissions' do
+    include_context 'ProjectPolicy context'
+
+    let(:additional_guest_permissions) do
+      %i[read_issue_link read_vulnerability_feedback read_software_license_policy]
+    end
+    let(:additional_reporter_permissions) { [:admin_issue_link] }
+    let(:additional_developer_permissions) { %i[admin_vulnerability_feedback read_project_security_dashboard read_feature_flag] }
+    let(:additional_maintainer_permissions) { %i[push_code_to_protected_branches] }
+    let(:auditor_permissions) do
+      %i[
+        download_code download_wiki_code read_project read_board read_list
+        read_project_for_iids read_issue_iid read_merge_request_iid read_wiki
+        read_issue read_label read_issue_link read_milestone read_release
+        read_project_snippet read_project_member read_note read_cycle_analytics
+        read_pipeline read_build read_commit_status read_container_image
+        read_environment read_deployment read_merge_request read_pages
+        create_merge_request_in award_emoji
+        read_vulnerability_feedback read_software_license_policy
+      ]
+    end
+
+    it_behaves_like 'project policies as anonymous'
+    it_behaves_like 'project policies as guest'
+    it_behaves_like 'project policies as reporter'
+    it_behaves_like 'project policies as developer'
+    it_behaves_like 'project policies as maintainer'
+    it_behaves_like 'project policies as owner'
+    it_behaves_like 'project policies as admin'
+
+    context 'auditor' do
+      let(:current_user) { create(:user, :auditor) }
+
+      context 'who is not a team member' do
+        it do
+          is_expected.to be_disallowed(*developer_permissions)
+          is_expected.to be_disallowed(*maintainer_permissions)
+          is_expected.to be_disallowed(*owner_permissions)
+          is_expected.to be_disallowed(*(guest_permissions - auditor_permissions))
+          is_expected.to be_allowed(*auditor_permissions)
+        end
+      end
+
+      context 'who is a team member' do
+        before do
+          project.add_guest(current_user)
+        end
+
+        it do
+          is_expected.to be_disallowed(*developer_permissions)
+          is_expected.to be_disallowed(*maintainer_permissions)
+          is_expected.to be_disallowed(*owner_permissions)
+          is_expected.to be_allowed(*(guest_permissions - auditor_permissions))
+          is_expected.to be_allowed(*auditor_permissions)
+        end
+      end
+    end
+  end
+
+  context 'issues feature' do
+    subject { described_class.new(owner, project) }
+
+    context 'when the feature is disabled' do
+      before do
+        project.issues_enabled = false
+        project.save!
+      end
+
+      it 'disables boards permissions' do
+        expect_disallowed :admin_board
+      end
+    end
   end
 
   context 'admin_mirror' do
     context 'with remote mirror setting enabled' do
       context 'with admin' do
-        subject do
-          described_class.new(admin, project)
-        end
+        let(:current_user) { admin }
 
         it do
           is_expected.to be_allowed(:admin_mirror)
@@ -31,9 +106,7 @@ describe ProjectPolicy do
       end
 
       context 'with owner' do
-        subject do
-          described_class.new(owner, project)
-        end
+        let(:current_user) { owner }
 
         it do
           is_expected.to be_allowed(:admin_mirror)
@@ -41,9 +114,7 @@ describe ProjectPolicy do
       end
 
       context 'with developer' do
-        subject do
-          described_class.new(developer, project)
-        end
+        let(:current_user) { developer }
 
         it do
           is_expected.to be_disallowed(:admin_mirror)
@@ -57,9 +128,7 @@ describe ProjectPolicy do
       end
 
       context 'with admin' do
-        subject do
-          described_class.new(admin, project)
-        end
+        let(:current_user) { admin }
 
         it do
           is_expected.to be_allowed(:admin_mirror)
@@ -67,9 +136,7 @@ describe ProjectPolicy do
       end
 
       context 'with owner' do
-        subject do
-          described_class.new(owner, project)
-        end
+        let(:current_user) { owner }
 
         it do
           is_expected.to be_disallowed(:admin_mirror)
@@ -83,9 +150,7 @@ describe ProjectPolicy do
       end
 
       context 'with admin' do
-        subject do
-          described_class.new(admin, project)
-        end
+        let(:current_user) { admin }
 
         it do
           is_expected.to be_disallowed(:admin_mirror)
@@ -93,9 +158,7 @@ describe ProjectPolicy do
       end
 
       context 'with owner' do
-        subject do
-          described_class.new(owner, project)
-        end
+        let(:current_user) { owner }
 
         it do
           is_expected.to be_disallowed(:admin_mirror)
@@ -109,9 +172,7 @@ describe ProjectPolicy do
       end
 
       context 'with admin' do
-        subject do
-          described_class.new(admin, project)
-        end
+        let(:current_user) { admin }
 
         it do
           is_expected.to be_allowed(:admin_mirror)
@@ -119,9 +180,7 @@ describe ProjectPolicy do
       end
 
       context 'with owner' do
-        subject do
-          described_class.new(owner, project)
-        end
+        let(:current_user) { owner }
 
         it do
           is_expected.to be_allowed(:admin_mirror)
@@ -190,14 +249,6 @@ describe ProjectPolicy do
   end
 
   describe 'read_vulnerability_feedback' do
-    subject { described_class.new(current_user, project) }
-
-    context 'with public project' do
-      let(:current_user) { nil }
-
-      it { is_expected.to be_allowed(:read_vulnerability_feedback) }
-    end
-
     context 'with private project' do
       let(:current_user) { admin }
       let(:project) { create(:project, :private, namespace: owner.namespace) }
@@ -252,88 +303,10 @@ describe ProjectPolicy do
     end
   end
 
-  describe 'admin_vulnerability_feedback' do
-    subject { described_class.new(current_user, project) }
-
-    context 'with admin' do
-      let(:current_user) { admin }
-
-      it { is_expected.to be_allowed(:admin_vulnerability_feedback) }
-    end
-
-    context 'with owner' do
-      let(:current_user) { owner }
-
-      it { is_expected.to be_allowed(:admin_vulnerability_feedback) }
-    end
-
-    context 'with maintainer' do
-      let(:current_user) { maintainer }
-
-      it { is_expected.to be_allowed(:admin_vulnerability_feedback) }
-    end
-
-    context 'with developer' do
-      let(:current_user) { developer }
-
-      it { is_expected.to be_allowed(:admin_vulnerability_feedback) }
-    end
-
-    context 'with reporter' do
-      let(:current_user) { reporter }
-
-      it { is_expected.to be_disallowed(:admin_vulnerability_feedback) }
-    end
-
-    context 'with guest' do
-      let(:current_user) { guest }
-
-      it { is_expected.to be_disallowed(:admin_vulnerability_feedback) }
-    end
-
-    context 'with non member' do
-      let(:current_user) { create(:user) }
-
-      it { is_expected.to be_disallowed(:admin_vulnerability_feedback) }
-    end
-
-    context 'with anonymous' do
-      let(:current_user) { nil }
-
-      it { is_expected.to be_disallowed(:admin_vulnerability_feedback) }
-    end
-  end
-
   describe 'read_project_security_dashboard' do
-    before do
-      stub_licensed_features(security_dashboard: true)
-    end
-
-    subject { described_class.new(current_user, project) }
-
-    context 'with admin' do
-      let(:current_user) { admin }
-
-      it { is_expected.to be_allowed(:read_project_security_dashboard) }
-    end
-
-    context 'with owner' do
-      let(:current_user) { owner }
-
-      it { is_expected.to be_allowed(:read_project_security_dashboard) }
-    end
-
-    context 'with maintainer' do
-      let(:current_user) { maintainer }
-
-      it { is_expected.to be_allowed(:read_project_security_dashboard) }
-    end
-
     context 'with developer' do
       let(:current_user) { developer }
 
-      it { is_expected.to be_allowed(:read_project_security_dashboard) }
-
       context 'when security dashboard features is not available' do
         before do
           stub_licensed_features(security_dashboard: false)
@@ -342,35 +315,9 @@ describe ProjectPolicy do
         it { is_expected.to be_disallowed(:read_project_security_dashboard) }
       end
     end
-
-    context 'with reporter' do
-      let(:current_user) { reporter }
-
-      it { is_expected.to be_disallowed(:read_project_security_dashboard) }
-    end
-
-    context 'with guest' do
-      let(:current_user) { guest }
-
-      it { is_expected.to be_disallowed(:read_project_security_dashboard) }
-    end
-
-    context 'with non member' do
-      let(:current_user) { create(:user) }
-
-      it { is_expected.to be_disallowed(:read_project_security_dashboard) }
-    end
-
-    context 'with anonymous' do
-      let(:current_user) { nil }
-
-      it { is_expected.to be_disallowed(:read_project_security_dashboard) }
-    end
   end
 
   describe 'read_package' do
-    subject { described_class.new(current_user, project) }
-
     context 'with admin' do
       let(:current_user) { admin }
 
@@ -429,17 +376,9 @@ describe ProjectPolicy do
   end
 
   describe 'read_feature_flag' do
-    before do
-      stub_licensed_features(feature_flags: true)
-    end
-
-    subject { described_class.new(current_user, project) }
-
     context 'with admin' do
       let(:current_user) { admin }
 
-      it { is_expected.to be_allowed(:read_feature_flag) }
-
       context 'when repository is disabled' do
         before do
           project.project_feature.update(repository_access_level: ProjectFeature::DISABLED)
@@ -449,23 +388,9 @@ describe ProjectPolicy do
       end
     end
 
-    context 'with owner' do
-      let(:current_user) { owner }
-
-      it { is_expected.to be_allowed(:read_feature_flag) }
-    end
-
-    context 'with maintainer' do
-      let(:current_user) { maintainer }
-
-      it { is_expected.to be_allowed(:read_feature_flag) }
-    end
-
     context 'with developer' do
       let(:current_user) { developer }
 
-      it { is_expected.to be_allowed(:read_feature_flag) }
-
       context 'when feature flags features is not available' do
         before do
           stub_licensed_features(feature_flags: false)
@@ -474,39 +399,9 @@ describe ProjectPolicy do
         it { is_expected.to be_disallowed(:read_feature_flag) }
       end
     end
-
-    context 'with reporter' do
-      let(:current_user) { reporter }
-
-      it { is_expected.to be_disallowed(:read_feature_flag) }
-    end
-
-    context 'with guest' do
-      let(:current_user) { guest }
-
-      it { is_expected.to be_disallowed(:read_feature_flag) }
-    end
-
-    context 'with non member' do
-      let(:current_user) { create(:user) }
-
-      it { is_expected.to be_disallowed(:read_feature_flag) }
-    end
-
-    context 'with anonymous' do
-      let(:current_user) { nil }
-
-      it { is_expected.to be_disallowed(:read_feature_flag) }
-    end
   end
 
   describe 'admin_license_management' do
-    before do
-      stub_licensed_features(license_management: true)
-    end
-
-    subject { described_class.new(current_user, project) }
-
     context 'without license management feature available' do
       before do
         stub_licensed_features(license_management: false)
@@ -567,12 +462,6 @@ describe ProjectPolicy do
   end
 
   describe 'read_license_management' do
-    before do
-      stub_licensed_features(license_management: true)
-    end
-
-    subject { described_class.new(current_user, project) }
-
     context 'without license management feature available' do
       before do
         stub_licensed_features(license_management: false)
@@ -582,54 +471,6 @@ describe ProjectPolicy do
 
       it { is_expected.to be_disallowed(:read_software_license_policy) }
     end
-
-    context 'with admin' do
-      let(:current_user) { admin }
-
-      it { is_expected.to be_allowed(:read_software_license_policy) }
-    end
-
-    context 'with owner' do
-      let(:current_user) { owner }
-
-      it { is_expected.to be_allowed(:read_software_license_policy) }
-    end
-
-    context 'with maintainer' do
-      let(:current_user) { maintainer }
-
-      it { is_expected.to be_allowed(:read_software_license_policy) }
-    end
-
-    context 'with developer' do
-      let(:current_user) { developer }
-
-      it { is_expected.to be_allowed(:read_software_license_policy) }
-    end
-
-    context 'with reporter' do
-      let(:current_user) { reporter }
-
-      it { is_expected.to be_allowed(:read_software_license_policy) }
-    end
-
-    context 'with guest' do
-      let(:current_user) { guest }
-
-      it { is_expected.to be_allowed(:read_software_license_policy) }
-    end
-
-    context 'with non member' do
-      let(:current_user) { create(:user) }
-
-      it { is_expected.to be_allowed(:read_software_license_policy) }
-    end
-
-    context 'with anonymous' do
-      let(:current_user) { nil }
-
-      it { is_expected.to be_allowed(:read_software_license_policy) }
-    end
   end
 
   describe 'create_web_ide_terminal' do
@@ -637,8 +478,6 @@ describe ProjectPolicy do
       stub_licensed_features(web_ide_terminal: true)
     end
 
-    subject { described_class.new(current_user, project) }
-
     context 'without ide terminal feature available' do
       before do
         stub_licensed_features(web_ide_terminal: false)
diff --git a/ee/spec/policies/project_snippet_policy_spec.rb b/ee/spec/policies/project_snippet_policy_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f20e391ec44b0f92a41e4c57b09f0190bb5ffe67
--- /dev/null
+++ b/ee/spec/policies/project_snippet_policy_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# Snippet visibility scenarios are included in more details in spec/support/snippet_visibility.rb
+describe ProjectSnippetPolicy do
+  let(:project) { create(:project, :public) }
+  let(:snippet) { create(:project_snippet, snippet_visibility, project: project) }
+  let(:author_permissions) do
+    [
+      :update_project_snippet,
+      :admin_project_snippet
+    ]
+  end
+
+  subject { described_class.new(current_user, snippet) }
+
+  context 'private snippet' do
+    let(:snippet_visibility) { :private }
+
+    context 'auditor user' do
+      let(:current_user) { create(:user, :auditor) }
+
+      it do
+        is_expected.to be_allowed(:read_project_snippet)
+        is_expected.to be_disallowed(*author_permissions)
+      end
+    end
+  end
+end
diff --git a/spec/policies/board_policy_spec.rb b/spec/policies/board_policy_spec.rb
index 4b76d65ef690f7bd7398441a009aa8cd38c38cd4..52c23951e37ba76a075adca9f8da7f5cc275cefe 100644
--- a/spec/policies/board_policy_spec.rb
+++ b/spec/policies/board_policy_spec.rb
@@ -17,14 +17,6 @@ describe BoardPolicy do
     ]
   end
 
-  def expect_allowed(*permissions)
-    permissions.each { |p| is_expected.to be_allowed(p) }
-  end
-
-  def expect_disallowed(*permissions)
-    permissions.each { |p| is_expected.not_to be_allowed(p) }
-  end
-
   context 'group board' do
     subject { described_class.new(user, group_board) }
 
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 74da8e500745ed98cb069a88a51372a0f92ba367..dc98baca6dc8fbc62360eec9061bd9811027a5d5 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -1,64 +1,7 @@
 require 'spec_helper'
 
 describe GroupPolicy do
-  let(:guest) { create(:user) }
-  let(:reporter) { create(:user) }
-  let(:developer) { create(:user) }
-  let(:maintainer) { create(:user) }
-  let(:owner) { create(:user) }
-  let(:auditor) { create(:user, :auditor) }
-  let(:admin) { create(:admin) }
-  let(:group) { create(:group, :private) }
-
-  let(:guest_permissions) do
-    [:read_label, :read_group, :upload_file, :read_namespace, :read_group_activity,
-     :read_group_issues, :read_group_boards, :read_group_labels, :read_group_milestones,
-     :read_group_merge_requests]
-  end
-
-  let(:reporter_permissions) { [:admin_label] }
-
-  let(:developer_permissions) { [:admin_milestone] }
-
-  let(:maintainer_permissions) do
-    [
-      :create_projects,
-      :read_cluster,
-      :create_cluster,
-      :update_cluster,
-      :admin_cluster,
-      :add_cluster
-    ]
-  end
-
-  let(:owner_permissions) do
-    [
-      :admin_group,
-      :admin_namespace,
-      :admin_group_member,
-      :change_visibility_level,
-      :set_note_created_at,
-      (Gitlab::Database.postgresql? ? :create_subgroup : nil)
-    ].compact
-  end
-
-  before do
-    group.add_guest(guest)
-    group.add_reporter(reporter)
-    group.add_developer(developer)
-    group.add_maintainer(maintainer)
-    group.add_owner(owner)
-  end
-
-  subject { described_class.new(current_user, group) }
-
-  def expect_allowed(*permissions)
-    permissions.each { |p| is_expected.to be_allowed(p) }
-  end
-
-  def expect_disallowed(*permissions)
-    permissions.each { |p| is_expected.not_to be_allowed(p) }
-  end
+  include_context 'GroupPolicy context'
 
   context 'with no user' do
     let(:group) { create(:group, :public) }
@@ -312,107 +255,6 @@ describe GroupPolicy do
         expect_allowed(*owner_permissions)
       end
     end
-
-    context 'auditor' do
-      let(:current_user) { auditor }
-
-      it do
-        expect_allowed(:read_group)
-        expect_disallowed(:upload_file)
-        is_expected.to be_disallowed(*maintainer_permissions)
-        is_expected.to be_disallowed(*owner_permissions)
-      end
-    end
-  end
-
-  describe 'change_share_with_group_lock' do
-    context 'when the current_user owns the group' do
-      let(:current_user) { owner }
-
-      context 'when the group share_with_group_lock is enabled' do
-        let(:group) { create(:group, share_with_group_lock: true, parent: parent) }
-
-        context 'when the parent group share_with_group_lock is enabled' do
-          context 'when the group has a grandparent' do
-            let(:parent) { create(:group, share_with_group_lock: true, parent: grandparent) }
-
-            context 'when the grandparent share_with_group_lock is enabled' do
-              let(:grandparent) { create(:group, share_with_group_lock: true) }
-
-              context 'when the current_user owns the parent' do
-                before do
-                  parent.add_owner(current_user)
-                end
-
-                context 'when the current_user owns the grandparent' do
-                  before do
-                    grandparent.add_owner(current_user)
-                  end
-
-                  it { expect_allowed(:change_share_with_group_lock) }
-                end
-
-                context 'when the current_user does not own the grandparent' do
-                  it { expect_disallowed(:change_share_with_group_lock) }
-                end
-              end
-
-              context 'when the current_user does not own the parent' do
-                it { expect_disallowed(:change_share_with_group_lock) }
-              end
-            end
-
-            context 'when the grandparent share_with_group_lock is disabled' do
-              let(:grandparent) { create(:group) }
-
-              context 'when the current_user owns the parent' do
-                before do
-                  parent.add_owner(current_user)
-                end
-
-                it { expect_allowed(:change_share_with_group_lock) }
-              end
-
-              context 'when the current_user does not own the parent' do
-                it { expect_disallowed(:change_share_with_group_lock) }
-              end
-            end
-          end
-
-          context 'when the group does not have a grandparent' do
-            let(:parent) { create(:group, share_with_group_lock: true) }
-
-            context 'when the current_user owns the parent' do
-              before do
-                parent.add_owner(current_user)
-              end
-
-              it { expect_allowed(:change_share_with_group_lock) }
-            end
-
-            context 'when the current_user does not own the parent' do
-              it { expect_disallowed(:change_share_with_group_lock) }
-            end
-          end
-        end
-
-        context 'when the parent group share_with_group_lock is disabled' do
-          let(:parent) { create(:group) }
-
-          it { expect_allowed(:change_share_with_group_lock) }
-        end
-      end
-
-      context 'when the group share_with_group_lock is disabled' do
-        it { expect_allowed(:change_share_with_group_lock) }
-      end
-    end
-
-    context 'when the current_user does not own the group' do
-      let(:current_user) { create(:user) }
-
-      it { expect_disallowed(:change_share_with_group_lock) }
-    end
   end
 
   describe 'change_share_with_group_lock' do
diff --git a/spec/policies/namespace_policy_spec.rb b/spec/policies/namespace_policy_spec.rb
index a7aaeed9ac870d7f559ad9b766992d9bdf55341d..99fa8b1fe440ec2dc6eb67cb66d278e16cd95246 100644
--- a/spec/policies/namespace_policy_spec.rb
+++ b/spec/policies/namespace_policy_spec.rb
@@ -3,7 +3,6 @@ require 'spec_helper'
 describe NamespacePolicy do
   let(:user) { create(:user) }
   let(:owner) { create(:user) }
-  let(:auditor) { create(:user, :auditor) }
   let(:admin) { create(:admin) }
   let(:namespace) { create(:namespace, owner: owner) }
 
@@ -35,20 +34,6 @@ describe NamespacePolicy do
     end
   end
 
-  context 'auditor' do
-    let(:current_user) { auditor }
-
-    context 'owner' do
-      let(:namespace) { create(:namespace, owner: auditor) }
-
-      it { is_expected.to be_allowed(*owner_permissions) }
-    end
-
-    context 'non-owner' do
-      it { is_expected.to be_disallowed(*owner_permissions) }
-    end
-  end
-
   context 'admin' do
     let(:current_user) { admin }
 
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index f1cc9694bb3cf6ff2436542788f531da042cbd11..726ccba8807b7719a23c4dcbf58d6c5a1b550fd5 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -1,96 +1,7 @@
 require 'spec_helper'
 
 describe ProjectPolicy do
-  set(:guest) { create(:user) }
-  set(:reporter) { create(:user) }
-  set(:developer) { create(:user) }
-  set(:maintainer) { create(:user) }
-  set(:owner) { create(:user) }
-  set(:admin) { create(:admin) }
-  let(:project) { create(:project, :public, namespace: owner.namespace) }
-
-  let(:base_guest_permissions) do
-    %i[
-      read_project read_board read_list read_wiki read_issue
-      read_project_for_iids read_issue_iid read_label
-      read_milestone read_project_snippet read_project_member read_note
-      create_project create_issue create_note upload_file create_merge_request_in
-      award_emoji read_release
-    ]
-  end
-
-  let(:base_reporter_permissions) do
-    %i[
-      download_code fork_project create_project_snippet update_issue
-      admin_issue admin_label admin_list read_commit_status read_build
-      read_container_image read_pipeline read_environment read_deployment
-      read_merge_request download_wiki_code read_sentry_issue
-    ]
-  end
-
-  let(:team_member_reporter_permissions) do
-    %i[build_download_code build_read_container_image]
-  end
-
-  let(:developer_permissions) do
-    %i[
-      admin_milestone admin_merge_request update_merge_request create_commit_status
-      update_commit_status create_build update_build create_pipeline
-      update_pipeline create_merge_request_from create_wiki push_code
-      resolve_note create_container_image update_container_image
-      create_environment create_deployment create_release update_release
-    ]
-  end
-
-  let(:base_maintainer_permissions) do
-    %i[
-      push_to_delete_protected_branch update_project_snippet update_environment
-      update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project
-      admin_commit_status admin_build admin_container_image
-      admin_pipeline admin_environment admin_deployment destroy_release add_cluster
-      daily_statistics
-    ]
-  end
-
-  let(:public_permissions) do
-    %i[
-      download_code fork_project read_commit_status read_pipeline
-      read_container_image build_download_code build_read_container_image
-      download_wiki_code read_release
-    ]
-  end
-
-  let(:owner_permissions) do
-    %i[
-      change_namespace change_visibility_level rename_project remove_project
-      archive_project remove_fork_project destroy_merge_request destroy_issue
-      set_issue_iid set_issue_created_at set_note_created_at
-    ]
-  end
-
-  # Used in EE specs
-  let(:additional_guest_permissions) { [] }
-  let(:additional_reporter_permissions) { [] }
-  let(:additional_maintainer_permissions) { [] }
-
-  let(:guest_permissions) { base_guest_permissions + additional_guest_permissions }
-  let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions }
-  let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions }
-
-  before do
-    project.add_guest(guest)
-    project.add_maintainer(maintainer)
-    project.add_developer(developer)
-    project.add_reporter(reporter)
-  end
-
-  def expect_allowed(*permissions)
-    permissions.each { |p| is_expected.to be_allowed(p) }
-  end
-
-  def expect_disallowed(*permissions)
-    permissions.each { |p| is_expected.not_to be_allowed(p) }
-  end
+  include_context 'ProjectPolicy context'
 
   it 'does not include the read_issue permission when the issue author is not a member of the private project' do
     project = create(:project, :private)
@@ -140,7 +51,7 @@ describe ProjectPolicy do
       end
 
       it 'disables boards and lists permissions' do
-        expect_disallowed :read_board, :create_board, :update_board, :admin_board
+        expect_disallowed :read_board, :create_board, :update_board
         expect_disallowed :read_list, :create_list, :update_list, :admin_list
       end
 
@@ -237,236 +148,6 @@ describe ProjectPolicy do
     end
   end
 
-  shared_examples 'archived project policies' do
-    let(:feature_write_abilities) do
-      described_class::READONLY_FEATURES_WHEN_ARCHIVED.flat_map do |feature|
-        described_class.create_update_admin_destroy(feature)
-      end + additional_reporter_permissions + additional_maintainer_permissions
-    end
-
-    let(:other_write_abilities) do
-      %i[
-        create_merge_request_in
-        create_merge_request_from
-        push_to_delete_protected_branch
-        push_code
-        request_access
-        upload_file
-        resolve_note
-        award_emoji
-      ]
-    end
-
-    context 'when the project is archived' do
-      before do
-        project.archived = true
-      end
-
-      it 'disables write actions on all relevant project features' do
-        expect_disallowed(*feature_write_abilities)
-      end
-
-      it 'disables some other important write actions' do
-        expect_disallowed(*other_write_abilities)
-      end
-
-      it 'does not disable other abilities' do
-        expect_allowed(*(regular_abilities - feature_write_abilities - other_write_abilities))
-      end
-    end
-  end
-
-  shared_examples 'project policies as anonymous' do
-    context 'abilities for public projects' do
-      context 'when a project has pending invites' do
-        let(:group) { create(:group, :public) }
-        let(:project) { create(:project, :public, namespace: group) }
-        let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji] }
-        let(:anonymous_permissions) { guest_permissions - user_permissions }
-
-        subject { described_class.new(nil, project) }
-
-        before do
-          create(:group_member, :invited, group: group)
-        end
-
-        it 'does not grant owner access' do
-          expect_allowed(*anonymous_permissions)
-          expect_disallowed(*user_permissions)
-        end
-
-        it_behaves_like 'archived project policies' do
-          let(:regular_abilities) { anonymous_permissions }
-        end
-      end
-    end
-
-    context 'abilities for non-public projects' do
-      let(:project) { create(:project, namespace: owner.namespace) }
-
-      subject { described_class.new(nil, project) }
-
-      it { is_expected.to be_banned }
-    end
-  end
-
-  shared_examples 'project policies as guest' do
-    subject { described_class.new(guest, project) }
-
-    context 'abilities for non-public projects' do
-      let(:project) { create(:project, namespace: owner.namespace) }
-      let(:reporter_public_build_permissions) do
-        reporter_permissions - [:read_build, :read_pipeline]
-      end
-
-      it do
-        expect_allowed(*guest_permissions)
-        expect_disallowed(*reporter_public_build_permissions)
-        expect_disallowed(*team_member_reporter_permissions)
-        expect_disallowed(*developer_permissions)
-        expect_disallowed(*maintainer_permissions)
-        expect_disallowed(*owner_permissions)
-      end
-
-      it_behaves_like 'archived project policies' do
-        let(:regular_abilities) { guest_permissions }
-      end
-
-      context 'public builds enabled' do
-        it do
-          expect_allowed(*guest_permissions)
-          expect_allowed(:read_build, :read_pipeline)
-        end
-      end
-
-      context 'when public builds disabled' do
-        before do
-          project.update(public_builds: false)
-        end
-
-        it do
-          expect_allowed(*guest_permissions)
-          expect_disallowed(:read_build, :read_pipeline)
-        end
-      end
-
-      context 'when builds are disabled' do
-        before do
-          project.project_feature.update(builds_access_level: ProjectFeature::DISABLED)
-        end
-
-        it do
-          expect_disallowed(:read_build)
-          expect_allowed(:read_pipeline)
-        end
-      end
-    end
-  end
-
-  shared_examples 'project policies as reporter' do
-    context 'abilities for non-public projects' do
-      let(:project) { create(:project, namespace: owner.namespace) }
-
-      subject { described_class.new(reporter, project) }
-
-      it do
-        expect_allowed(*guest_permissions)
-        expect_allowed(*reporter_permissions)
-        expect_allowed(*team_member_reporter_permissions)
-        expect_disallowed(*developer_permissions)
-        expect_disallowed(*maintainer_permissions)
-        expect_disallowed(*owner_permissions)
-      end
-
-      it_behaves_like 'archived project policies' do
-        let(:regular_abilities) { reporter_permissions }
-      end
-    end
-  end
-
-  shared_examples 'project policies as developer' do
-    context 'abilities for non-public projects' do
-      let(:project) { create(:project, namespace: owner.namespace) }
-      subject { described_class.new(developer, project) }
-
-      it do
-        expect_allowed(*guest_permissions)
-        expect_allowed(*reporter_permissions)
-        expect_allowed(*team_member_reporter_permissions)
-        expect_allowed(*developer_permissions)
-        expect_disallowed(*maintainer_permissions)
-        expect_disallowed(*owner_permissions)
-      end
-
-      it_behaves_like 'archived project policies' do
-        let(:regular_abilities) { developer_permissions }
-      end
-    end
-  end
-
-  shared_examples 'project policies as maintainer' do
-    context 'abilities for non-public projects' do
-      let(:project) { create(:project, namespace: owner.namespace) }
-
-      subject { described_class.new(maintainer, project) }
-
-      it do
-        expect_allowed(*guest_permissions)
-        expect_allowed(*reporter_permissions)
-        expect_allowed(*team_member_reporter_permissions)
-        expect_allowed(*developer_permissions)
-        expect_allowed(*maintainer_permissions)
-        expect_disallowed(*owner_permissions)
-      end
-
-      it_behaves_like 'archived project policies' do
-        let(:regular_abilities) { maintainer_permissions }
-      end
-    end
-  end
-
-  shared_examples 'project policies as owner' do
-    context 'abilities for non-public projects' do
-      let(:project) { create(:project, namespace: owner.namespace) }
-
-      subject { described_class.new(owner, project) }
-
-      it do
-        expect_allowed(*guest_permissions)
-        expect_allowed(*reporter_permissions)
-        expect_allowed(*team_member_reporter_permissions)
-        expect_allowed(*developer_permissions)
-        expect_allowed(*maintainer_permissions)
-        expect_allowed(*owner_permissions)
-      end
-
-      it_behaves_like 'archived project policies' do
-        let(:regular_abilities) { owner_permissions }
-      end
-    end
-  end
-
-  shared_examples 'project policies as admin' do
-    context 'abilities for non-public projects' do
-      let(:project) { create(:project, namespace: owner.namespace) }
-
-      subject { described_class.new(admin, project) }
-
-      it do
-        expect_allowed(*guest_permissions)
-        expect_allowed(*reporter_permissions)
-        expect_disallowed(*team_member_reporter_permissions)
-        expect_allowed(*developer_permissions)
-        expect_allowed(*maintainer_permissions)
-        expect_allowed(*owner_permissions)
-      end
-
-      it_behaves_like 'archived project policies' do
-        let(:regular_abilities) { owner_permissions }
-      end
-    end
-  end
-
   it_behaves_like 'project policies as anonymous'
   it_behaves_like 'project policies as guest'
   it_behaves_like 'project policies as reporter'
@@ -475,61 +156,6 @@ describe ProjectPolicy do
   it_behaves_like 'project policies as owner'
   it_behaves_like 'project policies as admin'
 
-  context 'EE' do
-    let(:additional_guest_permissions) { [:read_issue_link] }
-    let(:additional_reporter_permissions) { [:admin_issue_link]}
-    let(:additional_maintainer_permissions) { [:push_code_to_protected_branches] }
-    let(:auditor_permissions) do
-      %i[
-        download_code download_wiki_code read_project read_board read_list
-        read_project_for_iids read_issue_iid read_merge_request_iid read_wiki
-        read_issue read_label read_issue_link read_milestone read_release
-        read_project_snippet read_project_member read_note read_cycle_analytics
-        read_pipeline read_build read_commit_status read_container_image
-        read_environment read_deployment read_merge_request read_pages
-        create_merge_request_in award_emoji
-      ]
-    end
-
-    it_behaves_like 'project policies as anonymous'
-    it_behaves_like 'project policies as guest'
-    it_behaves_like 'project policies as reporter'
-    it_behaves_like 'project policies as developer'
-    it_behaves_like 'project policies as maintainer'
-    it_behaves_like 'project policies as owner'
-    it_behaves_like 'project policies as admin'
-
-    context 'auditor' do
-      let(:auditor) { create(:user, :auditor) }
-
-      subject { described_class.new(auditor, project) }
-
-      context 'who is not a team member' do
-        it do
-          is_expected.to be_disallowed(*developer_permissions)
-          is_expected.to be_disallowed(*maintainer_permissions)
-          is_expected.to be_disallowed(*owner_permissions)
-          is_expected.to be_disallowed(*(guest_permissions - auditor_permissions))
-          is_expected.to be_allowed(*auditor_permissions)
-        end
-      end
-
-      context 'who is a team member' do
-        before do
-          project.add_guest(auditor)
-        end
-
-        it do
-          is_expected.to be_disallowed(*developer_permissions)
-          is_expected.to be_disallowed(*maintainer_permissions)
-          is_expected.to be_disallowed(*owner_permissions)
-          is_expected.to be_allowed(*(guest_permissions - auditor_permissions))
-          is_expected.to be_allowed(*auditor_permissions)
-        end
-      end
-    end
-  end
-
   context 'when a public project has merge requests allowing access' do
     include ProjectForksHelper
     let(:user) { create(:user) }
diff --git a/spec/policies/project_snippet_policy_spec.rb b/spec/policies/project_snippet_policy_spec.rb
index 05dba1413f2bf9b02dfbf38f48fac11b4bc5676c..2e9ef1e89fde986eab79623dcdf60f23f254af14 100644
--- a/spec/policies/project_snippet_policy_spec.rb
+++ b/spec/policies/project_snippet_policy_spec.rb
@@ -5,7 +5,7 @@ describe ProjectSnippetPolicy do
   let(:regular_user) { create(:user) }
   let(:external_user) { create(:user, :external) }
   let(:project) { create(:project, :public) }
-
+  let(:snippet) { create(:project_snippet, snippet_visibility, project: project) }
   let(:author_permissions) do
     [
       :update_project_snippet,
@@ -13,23 +13,13 @@ describe ProjectSnippetPolicy do
     ]
   end
 
-  def abilities(user, snippet_visibility)
-    snippet = create(:project_snippet, snippet_visibility, project: project)
-
-    described_class.new(user, snippet)
-  end
-
-  def expect_allowed(*permissions)
-    permissions.each { |p| is_expected.to be_allowed(p) }
-  end
-
-  def expect_disallowed(*permissions)
-    permissions.each { |p| is_expected.not_to be_allowed(p) }
-  end
+  subject { described_class.new(current_user, snippet) }
 
   context 'public snippet' do
+    let(:snippet_visibility) { :public }
+
     context 'no user' do
-      subject { abilities(nil, :public) }
+      let(:current_user) { nil }
 
       it do
         expect_allowed(:read_project_snippet)
@@ -38,7 +28,7 @@ describe ProjectSnippetPolicy do
     end
 
     context 'regular user' do
-      subject { abilities(regular_user, :public) }
+      let(:current_user) { regular_user }
 
       it do
         expect_allowed(:read_project_snippet, :create_note)
@@ -47,7 +37,7 @@ describe ProjectSnippetPolicy do
     end
 
     context 'external user' do
-      subject { abilities(external_user, :public) }
+      let(:current_user) { external_user }
 
       it do
         expect_allowed(:read_project_snippet, :create_note)
@@ -57,8 +47,10 @@ describe ProjectSnippetPolicy do
   end
 
   context 'internal snippet' do
+    let(:snippet_visibility) { :internal }
+
     context 'no user' do
-      subject { abilities(nil, :internal) }
+      let(:current_user) { nil }
 
       it do
         expect_disallowed(:read_project_snippet)
@@ -67,7 +59,7 @@ describe ProjectSnippetPolicy do
     end
 
     context 'regular user' do
-      subject { abilities(regular_user, :internal) }
+      let(:current_user) { regular_user }
 
       it do
         expect_allowed(:read_project_snippet, :create_note)
@@ -76,41 +68,31 @@ describe ProjectSnippetPolicy do
     end
 
     context 'external user' do
-      subject { abilities(external_user, :internal) }
+      let(:current_user) { external_user }
 
       it do
         expect_disallowed(:read_project_snippet, :create_note)
         expect_disallowed(*author_permissions)
       end
-    end
-
-    context 'project team member external user' do
-      subject { abilities(external_user, :internal) }
-
-      before do
-        project.add_developer(external_user)
-      end
-
-      it do
-        expect_allowed(:read_project_snippet, :create_note)
-        expect_disallowed(*author_permissions)
-      end
-    end
 
-    context 'external user' do
-      let(:current_user) { create(:user, :external) }
-      subject { abilities(current_user, :private) }
+      context 'project team member' do
+        before do
+          project.add_developer(external_user)
+        end
 
-      it do
-        is_expected.to be_disallowed(:read_project_snippet)
-        is_expected.to be_disallowed(*author_permissions)
+        it do
+          expect_allowed(:read_project_snippet, :create_note)
+          expect_disallowed(*author_permissions)
+        end
       end
     end
   end
 
   context 'private snippet' do
+    let(:snippet_visibility) { :private }
+
     context 'no user' do
-      subject { abilities(nil, :private) }
+      let(:current_user) { nil }
 
       it do
         expect_disallowed(:read_project_snippet)
@@ -119,63 +101,52 @@ describe ProjectSnippetPolicy do
     end
 
     context 'regular user' do
-      subject { abilities(regular_user, :private) }
+      let(:current_user) { regular_user }
 
       it do
         expect_disallowed(:read_project_snippet, :create_note)
         expect_disallowed(*author_permissions)
       end
-    end
-
-    context 'snippet author' do
-      let(:snippet) { create(:project_snippet, :private, author: regular_user, project: project) }
 
-      subject { described_class.new(regular_user, snippet) }
+      context 'snippet author' do
+        let(:snippet) { create(:project_snippet, :private, author: regular_user, project: project) }
 
-      it do
-        expect_allowed(:read_project_snippet, :create_note)
-        expect_allowed(*author_permissions)
+        it do
+          expect_allowed(:read_project_snippet, :create_note)
+          expect_allowed(*author_permissions)
+        end
       end
-    end
 
-    context 'project team member normal user' do
-      subject { abilities(regular_user, :private) }
+      context 'project team member normal user' do
+        before do
+          project.add_developer(regular_user)
+        end
 
-      before do
-        project.add_developer(regular_user)
-      end
-
-      it do
-        expect_allowed(:read_project_snippet, :create_note)
-        expect_disallowed(*author_permissions)
+        it do
+          expect_allowed(:read_project_snippet, :create_note)
+          expect_disallowed(*author_permissions)
+        end
       end
     end
 
-    context 'project team member external user' do
-      subject { abilities(external_user, :private) }
-
-      before do
-        project.add_developer(external_user)
-      end
-
-      it do
-        expect_allowed(:read_project_snippet, :create_note)
-        expect_disallowed(*author_permissions)
-      end
-    end
+    context 'external user' do
+      context 'project team member' do
+        let(:current_user) { external_user }
 
-    context 'auditor user' do
-      let(:current_user) { create(:user, :auditor) }
-      subject { abilities(current_user, :private) }
+        before do
+          project.add_developer(external_user)
+        end
 
-      it do
-        is_expected.to be_allowed(:read_project_snippet)
-        is_expected.to be_disallowed(*author_permissions)
+        it do
+          expect_allowed(:read_project_snippet, :create_note)
+          expect_disallowed(*author_permissions)
+        end
       end
     end
 
     context 'admin user' do
-      subject { abilities(create(:admin), :private) }
+      let(:snippet_visibility) { :private }
+      let(:current_user) { create(:admin) }
 
       it do
         expect_allowed(:read_project_snippet, :create_note)
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 25d1327fcb9a5549da9668238217a51be65da518..0e121727a4fa21b977064c1e228619609a40506e 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -98,6 +98,7 @@ RSpec.configure do |config|
   config.include MigrationsHelpers, :migration
   config.include RedisHelpers
   config.include Rails.application.routes.url_helpers, type: :routing
+  config.include PolicyHelpers, type: :policy
 
   if ENV['CI']
     # This includes the first try, i.e. tests will be run 4 times before failing.
diff --git a/spec/support/helpers/policy_helpers.rb b/spec/support/helpers/policy_helpers.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3d780eb5fb1c1a85512daa7b30e0a28510ddf75d
--- /dev/null
+++ b/spec/support/helpers/policy_helpers.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module PolicyHelpers
+  def expect_allowed(*permissions)
+    permissions.each { |p| is_expected.to be_allowed(p) }
+  end
+
+  def expect_disallowed(*permissions)
+    permissions.each { |p| is_expected.not_to be_allowed(p) }
+  end
+end
diff --git a/spec/support/shared_context/policies/project_policy_shared_context.rb b/spec/support/shared_context/policies/project_policy_shared_context.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8bcd26ec0cd9def9a10989996c0e787879e73497
--- /dev/null
+++ b/spec/support/shared_context/policies/project_policy_shared_context.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'ProjectPolicy context' do
+  set(:guest) { create(:user) }
+  set(:reporter) { create(:user) }
+  set(:developer) { create(:user) }
+  set(:maintainer) { create(:user) }
+  set(:owner) { create(:user) }
+  set(:admin) { create(:admin) }
+  let(:project) { create(:project, :public, namespace: owner.namespace) }
+
+  let(:base_guest_permissions) do
+    %i[
+      read_project read_board read_list read_wiki read_issue
+      read_project_for_iids read_issue_iid read_label
+      read_milestone read_project_snippet read_project_member read_note
+      create_project create_issue create_note upload_file create_merge_request_in
+      award_emoji read_release
+    ]
+  end
+
+  let(:base_reporter_permissions) do
+    %i[
+      download_code fork_project create_project_snippet update_issue
+      admin_issue admin_label admin_list read_commit_status read_build
+      read_container_image read_pipeline read_environment read_deployment
+      read_merge_request download_wiki_code read_sentry_issue
+    ]
+  end
+
+  let(:team_member_reporter_permissions) do
+    %i[build_download_code build_read_container_image]
+  end
+
+  let(:developer_permissions) do
+    %i[
+      admin_milestone admin_merge_request update_merge_request create_commit_status
+      update_commit_status create_build update_build create_pipeline
+      update_pipeline create_merge_request_from create_wiki push_code
+      resolve_note create_container_image update_container_image
+      create_environment create_deployment create_release update_release
+    ]
+  end
+
+  let(:base_maintainer_permissions) do
+    %i[
+      push_to_delete_protected_branch update_project_snippet update_environment
+      update_deployment admin_project_snippet admin_project_member admin_note admin_wiki admin_project
+      admin_commit_status admin_build admin_container_image
+      admin_pipeline admin_environment admin_deployment destroy_release add_cluster
+      daily_statistics
+    ]
+  end
+
+  let(:public_permissions) do
+    %i[
+      download_code fork_project read_commit_status read_pipeline
+      read_container_image build_download_code build_read_container_image
+      download_wiki_code read_release
+    ]
+  end
+
+  let(:base_owner_permissions) do
+    %i[
+      change_namespace change_visibility_level rename_project remove_project
+      archive_project remove_fork_project destroy_merge_request destroy_issue
+      set_issue_iid set_issue_created_at set_note_created_at
+    ]
+  end
+
+  # Used in EE specs
+  let(:additional_guest_permissions) { [] }
+  let(:additional_reporter_permissions) { [] }
+  let(:additional_maintainer_permissions) { [] }
+  let(:additional_owner_permissions) { [] }
+
+  let(:guest_permissions) { base_guest_permissions + additional_guest_permissions }
+  let(:reporter_permissions) { base_reporter_permissions + additional_reporter_permissions }
+  let(:maintainer_permissions) { base_maintainer_permissions + additional_maintainer_permissions }
+  let(:owner_permissions) { base_owner_permissions + additional_owner_permissions }
+
+  before do
+    project.add_guest(guest)
+    project.add_maintainer(maintainer)
+    project.add_developer(developer)
+    project.add_reporter(reporter)
+  end
+end
diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b4808ac006883567bdff2ea82e3474150c051483
--- /dev/null
+++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'GroupPolicy context' do
+  let(:guest) { create(:user) }
+  let(:reporter) { create(:user) }
+  let(:developer) { create(:user) }
+  let(:maintainer) { create(:user) }
+  let(:owner) { create(:user) }
+  let(:admin) { create(:admin) }
+  let(:group) { create(:group, :private) }
+
+  let(:guest_permissions) do
+    %i[
+      read_label read_group upload_file read_namespace read_group_activity
+      read_group_issues read_group_boards read_group_labels read_group_milestones
+      read_group_merge_requests
+   ]
+  end
+  let(:reporter_permissions) { [:admin_label] }
+  let(:developer_permissions) { [:admin_milestone] }
+  let(:maintainer_permissions) do
+    %i[
+      create_projects
+      read_cluster create_cluster update_cluster admin_cluster add_cluster
+    ]
+  end
+  let(:owner_permissions) do
+    [
+      :admin_group,
+      :admin_namespace,
+      :admin_group_member,
+      :change_visibility_level,
+      :set_note_created_at,
+      (Gitlab::Database.postgresql? ? :create_subgroup : nil)
+    ].compact
+  end
+
+  before do
+    group.add_guest(guest)
+    group.add_reporter(reporter)
+    group.add_developer(developer)
+    group.add_maintainer(maintainer)
+    group.add_owner(owner)
+  end
+
+  subject { described_class.new(current_user, group) }
+end
diff --git a/spec/support/shared_examples/policies/project_policy_shared_examples.rb b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7a71e2ee370e0d57a014302d10091583333abad8
--- /dev/null
+++ b/spec/support/shared_examples/policies/project_policy_shared_examples.rb
@@ -0,0 +1,231 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'archived project policies' do
+  let(:feature_write_abilities) do
+    described_class::READONLY_FEATURES_WHEN_ARCHIVED.flat_map do |feature|
+      described_class.create_update_admin_destroy(feature)
+    end + additional_reporter_permissions + additional_maintainer_permissions
+  end
+
+  let(:other_write_abilities) do
+    %i[
+      create_merge_request_in
+      create_merge_request_from
+      push_to_delete_protected_branch
+      push_code
+      request_access
+      upload_file
+      resolve_note
+      award_emoji
+    ]
+  end
+
+  context 'when the project is archived' do
+    before do
+      project.archived = true
+    end
+
+    it 'disables write actions on all relevant project features' do
+      expect_disallowed(*feature_write_abilities)
+    end
+
+    it 'disables some other important write actions' do
+      expect_disallowed(*other_write_abilities)
+    end
+
+    it 'does not disable other abilities' do
+      expect_allowed(*(regular_abilities - feature_write_abilities - other_write_abilities))
+    end
+  end
+end
+
+RSpec.shared_examples 'project policies as anonymous' do
+  context 'abilities for public projects' do
+    context 'when a project has pending invites' do
+      let(:group) { create(:group, :public) }
+      let(:project) { create(:project, :public, namespace: group) }
+      let(:user_permissions) { [:create_merge_request_in, :create_project, :create_issue, :create_note, :upload_file, :award_emoji] }
+      let(:anonymous_permissions) { guest_permissions - user_permissions }
+
+      subject { described_class.new(nil, project) }
+
+      before do
+        create(:group_member, :invited, group: group)
+      end
+
+      it 'does not grant owner access' do
+        expect_allowed(*anonymous_permissions)
+        expect_disallowed(*user_permissions)
+      end
+
+      it_behaves_like 'archived project policies' do
+        let(:regular_abilities) { anonymous_permissions }
+      end
+    end
+  end
+
+  context 'abilities for non-public projects' do
+    let(:project) { create(:project, namespace: owner.namespace) }
+
+    subject { described_class.new(nil, project) }
+
+    it { is_expected.to be_banned }
+  end
+end
+
+RSpec.shared_examples 'project policies as guest' do
+  subject { described_class.new(guest, project) }
+
+  context 'abilities for non-public projects' do
+    let(:project) { create(:project, namespace: owner.namespace) }
+    let(:reporter_public_build_permissions) do
+      reporter_permissions - [:read_build, :read_pipeline]
+    end
+
+    it do
+      expect_allowed(*guest_permissions)
+      expect_disallowed(*reporter_public_build_permissions)
+      expect_disallowed(*team_member_reporter_permissions)
+      expect_disallowed(*developer_permissions)
+      expect_disallowed(*maintainer_permissions)
+      expect_disallowed(*owner_permissions)
+    end
+
+    it_behaves_like 'archived project policies' do
+      let(:regular_abilities) { guest_permissions }
+    end
+
+    context 'public builds enabled' do
+      it do
+        expect_allowed(*guest_permissions)
+        expect_allowed(:read_build, :read_pipeline)
+      end
+    end
+
+    context 'when public builds disabled' do
+      before do
+        project.update(public_builds: false)
+      end
+
+      it do
+        expect_allowed(*guest_permissions)
+        expect_disallowed(:read_build, :read_pipeline)
+      end
+    end
+
+    context 'when builds are disabled' do
+      before do
+        project.project_feature.update(builds_access_level: ProjectFeature::DISABLED)
+      end
+
+      it do
+        expect_disallowed(:read_build)
+        expect_allowed(:read_pipeline)
+      end
+    end
+  end
+end
+
+RSpec.shared_examples 'project policies as reporter' do
+  context 'abilities for non-public projects' do
+    let(:project) { create(:project, namespace: owner.namespace) }
+
+    subject { described_class.new(reporter, project) }
+
+    it do
+      expect_allowed(*guest_permissions)
+      expect_allowed(*reporter_permissions)
+      expect_allowed(*team_member_reporter_permissions)
+      expect_disallowed(*developer_permissions)
+      expect_disallowed(*maintainer_permissions)
+      expect_disallowed(*owner_permissions)
+    end
+
+    it_behaves_like 'archived project policies' do
+      let(:regular_abilities) { reporter_permissions }
+    end
+  end
+end
+
+RSpec.shared_examples 'project policies as developer' do
+  context 'abilities for non-public projects' do
+    let(:project) { create(:project, namespace: owner.namespace) }
+    subject { described_class.new(developer, project) }
+
+    it do
+      expect_allowed(*guest_permissions)
+      expect_allowed(*reporter_permissions)
+      expect_allowed(*team_member_reporter_permissions)
+      expect_allowed(*developer_permissions)
+      expect_disallowed(*maintainer_permissions)
+      expect_disallowed(*owner_permissions)
+    end
+
+    it_behaves_like 'archived project policies' do
+      let(:regular_abilities) { developer_permissions }
+    end
+  end
+end
+
+RSpec.shared_examples 'project policies as maintainer' do
+  context 'abilities for non-public projects' do
+    let(:project) { create(:project, namespace: owner.namespace) }
+
+    subject { described_class.new(maintainer, project) }
+
+    it do
+      expect_allowed(*guest_permissions)
+      expect_allowed(*reporter_permissions)
+      expect_allowed(*team_member_reporter_permissions)
+      expect_allowed(*developer_permissions)
+      expect_allowed(*maintainer_permissions)
+      expect_disallowed(*owner_permissions)
+    end
+
+    it_behaves_like 'archived project policies' do
+      let(:regular_abilities) { maintainer_permissions }
+    end
+  end
+end
+
+RSpec.shared_examples 'project policies as owner' do
+  context 'abilities for non-public projects' do
+    let(:project) { create(:project, namespace: owner.namespace) }
+
+    subject { described_class.new(owner, project) }
+
+    it do
+      expect_allowed(*guest_permissions)
+      expect_allowed(*reporter_permissions)
+      expect_allowed(*team_member_reporter_permissions)
+      expect_allowed(*developer_permissions)
+      expect_allowed(*maintainer_permissions)
+      expect_allowed(*owner_permissions)
+    end
+
+    it_behaves_like 'archived project policies' do
+      let(:regular_abilities) { owner_permissions }
+    end
+  end
+end
+
+RSpec.shared_examples 'project policies as admin' do
+  context 'abilities for non-public projects' do
+    let(:project) { create(:project, namespace: owner.namespace) }
+
+    subject { described_class.new(admin, project) }
+
+    it do
+      expect_allowed(*guest_permissions)
+      expect_allowed(*reporter_permissions)
+      expect_disallowed(*team_member_reporter_permissions)
+      expect_allowed(*developer_permissions)
+      expect_allowed(*maintainer_permissions)
+      expect_allowed(*owner_permissions)
+    end
+
+    it_behaves_like 'archived project policies' do
+      let(:regular_abilities) { owner_permissions }
+    end
+  end
+end