From 8a998c8b280536db41132aa46ef89eefeec1cca6 Mon Sep 17 00:00:00 2001
From: Ian Donovan <iandonovan@users.noreply.github.com>
Date: Wed, 18 Dec 2024 11:48:47 -0500
Subject: [PATCH] [CST] Use json_schemer in SavedClaim (#19684)

* Use json schemer in savedclaim

* Adds actual feature flipper, fixes already-existing tests

* Fixes more existing tests

* Fixes rubocop

* Play more nicely with error array

* More elegant error handling

* Rubocop

* Error handling redux redux

* Stub, rather than actually disable, the feature flipper

* Json schemer can detect fake emails

* Fixes some more specs. Getting there.

* rubocop

* Fixing some more specs, adding some stubs, learning

* See if tests pass with old flipper syntax

* Fixes more specs

* More passing specs. This might be all of them?

* Rubocop

* Adds some affirmative tests with the JSON Schemer flipper enabled

* Rubocop

* Adds comments to json validation methods for clarity on the gem switch

* Finishes adding affirmative (flipper on) tests. Uses true/false each block.

* Standardize error object to use symbols for keys

* Rubocop

* Fixes last spec, hopefully

* Rubocop
---
 app/models/saved_claim.rb                     |   59 +-
 config/features.yml                           |    4 +
 .../spec/models/pensions/saved_claim_spec.rb  |   45 +-
 spec/factories/gids_response.rb               |    4 +-
 spec/factories/va10203.rb                     |    6 +-
 .../submit_spec.rb                            |  199 +-
 spec/lib/vre/monitor_spec.rb                  |   50 +-
 spec/models/form526_submission_spec.rb        | 2707 +++++++++--------
 .../education_benefits/va1995_spec.rb         |  100 +-
 spec/models/saved_claim_spec.rb               |  144 +-
 spec/requests/v0/form0969_spec.rb             |  105 +-
 .../education_form/forms/va1995_spec.rb       |  134 +-
 ..._school_certifying_officials_email_spec.rb |    2 +-
 .../submit_form0781_spec.rb                   |  984 +++---
 .../submit_form526_all_claim_spec.rb          | 1400 ++++-----
 ...form526_failure_state_snapshot_job_spec.rb |  435 +--
 ...orm526_document_upload_polling_job_spec.rb |  503 +--
 17 files changed, 3583 insertions(+), 3298 deletions(-)

diff --git a/app/models/saved_claim.rb b/app/models/saved_claim.rb
index ea69a4f6d59..98509688106 100644
--- a/app/models/saved_claim.rb
+++ b/app/models/saved_claim.rb
@@ -99,6 +99,8 @@ def form_matches_schema
     unless validation_errors.empty?
       Rails.logger.error('SavedClaim form did not pass validation', { guid:, errors: validation_errors })
     end
+
+    schema_errors.empty? && validation_errors.empty?
   end
 
   def to_pdf(file_name = nil)
@@ -147,14 +149,57 @@ def va_notification?(email_template_id)
 
   private
 
+  # Depending on the feature flipper, validate the *entire schema*
+  # via either the json_schema or json_schemer gem.
+  # This is tied to vets-api #19684
   def validate_schema(schema)
+    if Flipper.enabled?(:validate_saved_claims_with_json_schemer)
+      validate_schema_with_json_schemer(schema)
+    else
+      validate_schema_with_json_schema(schema)
+    end
+  end
+
+  # Depending on the feature flipper, validate the *parsed form*
+  # via either the json_schema or the json_schemer gem.
+  # This is tied to vets-api #19684
+  def validate_form(schema, clear_cache)
+    if Flipper.enabled?(:validate_saved_claims_with_json_schemer)
+      validate_form_with_json_schemer(schema)
+    else
+      validate_form_with_json_schema(schema, clear_cache)
+    end
+  end
+
+  # For json_schemer, the default behavior is not to raise an exception
+  # on validation, so we return an array of errors if they exist.
+  # This method validates the *entire schema*.
+  def validate_schema_with_json_schemer(schema)
+    errors = JSONSchemer.validate_schema(schema).to_a
+    return [] if errors.empty?
+
+    reformatted_schemer_errors(errors)
+  end
+
+  # For json_schema, validation errors raise an exception.
+  # This method validates the *entire schema*.
+  def validate_schema_with_json_schema(schema)
     JSON::Validator.fully_validate_schema(schema, { errors_as_objects: true })
   rescue => e
     Rails.logger.error('Error during schema validation!', { error: e.message, backtrace: e.backtrace, schema: })
     raise
   end
 
-  def validate_form(schema, clear_cache)
+  # This method validates the *parsed form* with json_schemer.
+  def validate_form_with_json_schemer(schema)
+    errors = JSONSchemer.schema(schema).validate(parsed_form).to_a
+    return [] if errors.empty?
+
+    reformatted_schemer_errors(errors)
+  end
+
+  # This method validates the *parsed form* with json_schema.
+  def validate_form_with_json_schema(schema, clear_cache)
     JSON::Validator.fully_validate(schema, parsed_form, { errors_as_objects: true, clear_cache: })
   rescue => e
     PersonalInformationLog.create(data: { schema:, parsed_form:, params: { errors_as_objects: true, clear_cache: } },
@@ -164,6 +209,18 @@ def validate_form(schema, clear_cache)
     raise
   end
 
+  # This method exists to change the json_schemer errors
+  # to be formatted like json_schema errors, which keeps
+  # the error logging smooth and identical for both options.
+  def reformatted_schemer_errors(errors)
+    errors.map!(&:symbolize_keys)
+    errors.each do |error|
+      error[:fragment] = error[:data_pointer]
+      error[:message] = error[:error]
+    end
+    errors
+  end
+
   def attachment_keys
     []
   end
diff --git a/config/features.yml b/config/features.yml
index 9bdac7133d3..c4d42a7791a 100644
--- a/config/features.yml
+++ b/config/features.yml
@@ -1537,6 +1537,10 @@ features:
     actor_type: user
     description: When enabled, the VAProfile::V3::ContactInformation will be enabled
     enable_in_development: true
+  validate_saved_claims_with_json_schemer:
+    actor_type: user
+    description: When enabled, Saved Claims will be validated using the JSON Schemer gem rather than JSON Schema
+    enable_in_development: false
   veteran_onboarding_beta_flow:
     actor_type: user
     description: Conditionally display the new veteran onboarding flow to user
diff --git a/modules/pensions/spec/models/pensions/saved_claim_spec.rb b/modules/pensions/spec/models/pensions/saved_claim_spec.rb
index 1924a1a9faf..8ffb9f0748b 100644
--- a/modules/pensions/spec/models/pensions/saved_claim_spec.rb
+++ b/modules/pensions/spec/models/pensions/saved_claim_spec.rb
@@ -49,18 +49,45 @@
       )
     end
 
-    describe '#process_attachments!' do
-      it 'sets the attachments saved_claim_id' do
-        expect(Lighthouse::SubmitBenefitsIntakeClaim).not_to receive(:perform_async).with(claim.id)
-        claim.process_attachments!
-        expect(claim.persistent_attachments.size).to eq(2)
+    context 'using JSON Schema' do
+      before do
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(false)
+      end
+
+      describe '#process_attachments!' do
+        it 'sets the attachments saved_claim_id' do
+          expect(Lighthouse::SubmitBenefitsIntakeClaim).not_to receive(:perform_async).with(claim.id)
+          claim.process_attachments!
+          expect(claim.persistent_attachments.size).to eq(2)
+        end
+      end
+
+      describe '#destroy' do
+        it 'also destroys the persistent_attachments' do
+          claim.process_attachments!
+          expect { claim.destroy }.to change(PersistentAttachment, :count).by(-2)
+        end
       end
     end
 
-    describe '#destroy' do
-      it 'also destroys the persistent_attachments' do
-        claim.process_attachments!
-        expect { claim.destroy }.to change(PersistentAttachment, :count).by(-2)
+    context 'using JSON Schemer' do
+      before do
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(true)
+      end
+
+      describe '#process_attachments!' do
+        it 'sets the attachments saved_claim_id' do
+          expect(Lighthouse::SubmitBenefitsIntakeClaim).not_to receive(:perform_async).with(claim.id)
+          claim.process_attachments!
+          expect(claim.persistent_attachments.size).to eq(2)
+        end
+      end
+
+      describe '#destroy' do
+        it 'also destroys the persistent_attachments' do
+          claim.process_attachments!
+          expect { claim.destroy }.to change(PersistentAttachment, :count).by(-2)
+        end
       end
     end
   end
diff --git a/spec/factories/gids_response.rb b/spec/factories/gids_response.rb
index 7aeebbe5a5f..c0704b9c965 100644
--- a/spec/factories/gids_response.rb
+++ b/spec/factories/gids_response.rb
@@ -16,11 +16,11 @@
             versioned_school_certifying_officials: [
               {
                 priority: 'Primary',
-                email: 'test@edu_sample.com'
+                email: 'user@school.edu'
               },
               {
                 priority: 'Secondary',
-                email: 'test@edu_sample.com'
+                email: 'user@school.edu'
               }
             ]
           }
diff --git a/spec/factories/va10203.rb b/spec/factories/va10203.rb
index c07374c7735..046f47e7610 100644
--- a/spec/factories/va10203.rb
+++ b/spec/factories/va10203.rb
@@ -18,7 +18,7 @@
         schoolCity: 'Test',
         schoolState: 'TN',
         schoolCountry: 'USA',
-        schoolEmailAddress: 'test@edu_sample.com',
+        schoolEmailAddress: 'user@school.edu',
         schoolStudentId: '01010101',
         isActiveDuty: true,
         veteranAddress: {
@@ -58,7 +58,7 @@
         schoolCity: 'Test 2',
         schoolState: 'SC',
         schoolCountry: 'USA',
-        schoolEmailAddress: 'test@edu_sample.com',
+        schoolEmailAddress: 'user@school.edu',
         schoolStudentId: '01010101',
         isActiveDuty: true,
         veteranAddress: {
@@ -98,7 +98,7 @@
         schoolCity: 'Test 2',
         schoolState: 'SC',
         schoolCountry: 'USA',
-        schoolEmailAddress: 'test@edu_sample.com',
+        schoolEmailAddress: 'user@school.edu',
         schoolStudentId: '01010101',
         isActiveDuty: true,
         veteranAddress: {
diff --git a/spec/lib/sidekiq/form526_backup_submission_process/submit_spec.rb b/spec/lib/sidekiq/form526_backup_submission_process/submit_spec.rb
index 891794840ca..dc84bb6c218 100644
--- a/spec/lib/sidekiq/form526_backup_submission_process/submit_spec.rb
+++ b/spec/lib/sidekiq/form526_backup_submission_process/submit_spec.rb
@@ -12,6 +12,8 @@
   before do
     Sidekiq::Job.clear_all
     Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_GENERATE_PDF)
+    allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(false)
+    allow(Flipper).to receive(:enabled?).with(:form526_send_backup_submission_exhaustion_email_notice).and_return(false)
   end
 
   let(:user) { FactoryBot.create(:user, :loa3) }
@@ -56,7 +58,8 @@
 
       context 'when form526_send_backup_submission_exhaustion_email_notice is enabled' do
         before do
-          Flipper.enable(:form526_send_backup_submission_exhaustion_email_notice)
+          allow(Flipper).to receive(:enabled?)
+                        .with(:form526_send_backup_submission_exhaustion_email_notice).and_return(true)
         end
 
         it 'remediates the submission via an email notification' do
@@ -103,111 +106,119 @@
   end
 
   %w[single multi].each do |payload_method|
-    describe ".perform_async, enabled, #{payload_method} payload" do
-      before do
-        allow(Settings.form526_backup).to receive_messages(submission_method: payload_method, enabled: true)
-      end
+    [true, false].each do |flipper|
+      describe ".perform_async, enabled, #{payload_method} payload" do
+        before do
+          allow(Settings.form526_backup).to receive_messages(submission_method: payload_method, enabled: true)
+        end
 
-      let!(:submission) { create :form526_submission, :with_everything }
-      let!(:upload_data) { submission.form[Form526Submission::FORM_526_UPLOADS] }
+        let!(:submission) { create :form526_submission, :with_everything }
+        let!(:upload_data) { submission.form[Form526Submission::FORM_526_UPLOADS] }
 
-      context 'successfully' do
-        before do
-          upload_data.each do |ud|
-            file = Rack::Test::UploadedFile.new('spec/fixtures/files/doctors-note.pdf', 'application/pdf')
-            sea = SupportingEvidenceAttachment.find_or_create_by(guid: ud['confirmationCode'])
-            sea.set_file_data!(file)
-            sea.save!
+        context "when json_schemer flipper is #{flipper}" do
+          before do
+            allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper)
           end
-        end
 
-        it 'creates a job for submission' do
-          expect { subject.perform_async(submission.id) }.to change(subject.jobs, :size).by(1)
-        end
+          context 'successfully' do
+            before do
+              upload_data.each do |ud|
+                file = Rack::Test::UploadedFile.new('spec/fixtures/files/doctors-note.pdf', 'application/pdf')
+                sea = SupportingEvidenceAttachment.find_or_create_by(guid: ud['confirmationCode'])
+                sea.set_file_data!(file)
+                sea.save!
+              end
+            end
 
-        it 'submits' do
-          new_form_data = submission.saved_claim.parsed_form
-          new_form_data['startedFormVersion'] = nil
-          submission.saved_claim.form = new_form_data.to_json
-          submission.saved_claim.save
-          VCR.use_cassette('lighthouse/benefits_intake/200_lighthouse_intake_upload_location') do
-            VCR.use_cassette('form526_backup/200_evss_get_pdf') do
-              VCR.use_cassette('lighthouse/benefits_intake/200_lighthouse_intake_upload') do
-                jid = subject.perform_async(submission.id)
-                last = subject.jobs.last
-                jid_from_jobs = last['jid']
-                expect(jid).to eq(jid_from_jobs)
-                described_class.drain
-                expect(jid).not_to be_empty
-
-                # The Backup Submission process gathers form 526 and any ancillary forms
-                # to send to Central Mail at the same time
-
-                # Form 4142 Backup Submission Process
-                expect(submission.form['form4142']).not_to be(nil)
-                form4142_processor = DecisionReviewV1::Processor::Form4142Processor.new(
-                  form_data: submission.form['form4142'], submission_id: submission.id
-                )
-                request_body = form4142_processor.request_body
-                metadata_hash = JSON.parse(request_body['metadata'])
-                form4142_received_date = metadata_hash['receiveDt'].in_time_zone('Central Time (US & Canada)')
-                expect(
-                  submission.created_at.in_time_zone('Central Time (US & Canada)')
-                ).to be_within(1.second).of(form4142_received_date)
-
-                # Form 0781 Backup Submission Process
-                expect(submission.form['form0781']).not_to be(nil)
-                # not really a way to test the dates here
-
-                job_status = Form526JobStatus.last
-                expect(job_status.form526_submission_id).to eq(submission.id)
-                expect(job_status.job_class).to eq('BackupSubmission')
-                expect(job_status.job_id).to eq(jid)
-                expect(job_status.status).to eq('success')
-                submission = Form526Submission.last
-                expect(submission.backup_submitted_claim_id).not_to be(nil)
-                expect(submission.submit_endpoint).to eq('benefits_intake_api')
+            it 'creates a job for submission' do
+              expect { subject.perform_async(submission.id) }.to change(subject.jobs, :size).by(1)
+            end
+
+            it 'submits' do
+              new_form_data = submission.saved_claim.parsed_form
+              new_form_data['startedFormVersion'] = nil
+              submission.saved_claim.form = new_form_data.to_json
+              submission.saved_claim.save
+              VCR.use_cassette('lighthouse/benefits_intake/200_lighthouse_intake_upload_location') do
+                VCR.use_cassette('form526_backup/200_evss_get_pdf') do
+                  VCR.use_cassette('lighthouse/benefits_intake/200_lighthouse_intake_upload') do
+                    jid = subject.perform_async(submission.id)
+                    last = subject.jobs.last
+                    jid_from_jobs = last['jid']
+                    expect(jid).to eq(jid_from_jobs)
+                    described_class.drain
+                    expect(jid).not_to be_empty
+
+                    # The Backup Submission process gathers form 526 and any ancillary forms
+                    # to send to Central Mail at the same time
+
+                    # Form 4142 Backup Submission Process
+                    expect(submission.form['form4142']).not_to be(nil)
+                    form4142_processor = DecisionReviewV1::Processor::Form4142Processor.new(
+                      form_data: submission.form['form4142'], submission_id: submission.id
+                    )
+                    request_body = form4142_processor.request_body
+                    metadata_hash = JSON.parse(request_body['metadata'])
+                    form4142_received_date = metadata_hash['receiveDt'].in_time_zone('Central Time (US & Canada)')
+                    expect(
+                      submission.created_at.in_time_zone('Central Time (US & Canada)')
+                    ).to be_within(1.second).of(form4142_received_date)
+
+                    # Form 0781 Backup Submission Process
+                    expect(submission.form['form0781']).not_to be(nil)
+                    # not really a way to test the dates here
+
+                    job_status = Form526JobStatus.last
+                    expect(job_status.form526_submission_id).to eq(submission.id)
+                    expect(job_status.job_class).to eq('BackupSubmission')
+                    expect(job_status.job_id).to eq(jid)
+                    expect(job_status.status).to eq('success')
+                    submission = Form526Submission.last
+                    expect(submission.backup_submitted_claim_id).not_to be(nil)
+                    expect(submission.submit_endpoint).to eq('benefits_intake_api')
+                  end
+                end
               end
             end
           end
-        end
-      end
 
-      context 'with a submission timeout' do
-        before do
-          allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(Faraday::TimeoutError)
-        end
+          context 'with a submission timeout' do
+            before do
+              allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(Faraday::TimeoutError)
+            end
 
-        it 'raises a gateway timeout error' do
-          jid = subject.perform_async(submission.id)
-          expect { described_class.drain }.to raise_error(Common::Exceptions::GatewayTimeout)
-          job_status = Form526JobStatus.find_by(job_id: jid)
-          expect(job_status.form526_submission_id).to eq(submission.id)
-          expect(job_status.job_class).to eq('BackupSubmission')
-          expect(job_status.job_id).to eq(jid)
-          expect(job_status.status).to eq('retryable_error')
-          error = job_status.bgjob_errors
-          expect(error.first.last['error_class']).to eq('Common::Exceptions::GatewayTimeout')
-          expect(error.first.last['error_message']).to eq('Gateway timeout')
-        end
-      end
+            it 'raises a gateway timeout error' do
+              jid = subject.perform_async(submission.id)
+              expect { described_class.drain }.to raise_error(Common::Exceptions::GatewayTimeout)
+              job_status = Form526JobStatus.find_by(job_id: jid)
+              expect(job_status.form526_submission_id).to eq(submission.id)
+              expect(job_status.job_class).to eq('BackupSubmission')
+              expect(job_status.job_id).to eq(jid)
+              expect(job_status.status).to eq('retryable_error')
+              error = job_status.bgjob_errors
+              expect(error.first.last['error_class']).to eq('Common::Exceptions::GatewayTimeout')
+              expect(error.first.last['error_message']).to eq('Gateway timeout')
+            end
+          end
 
-      context 'with an unexpected error' do
-        before do
-          allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(StandardError.new('foo'))
-        end
+          context 'with an unexpected error' do
+            before do
+              allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(StandardError.new('foo'))
+            end
 
-        it 'raises a standard error' do
-          jid = subject.perform_async(submission.id)
-          expect { described_class.drain }.to raise_error(StandardError)
-          job_status = Form526JobStatus.find_by(job_id: jid)
-          expect(job_status.form526_submission_id).to eq(submission.id)
-          expect(job_status.job_class).to eq('BackupSubmission')
-          expect(job_status.job_id).to eq(jid)
-          expect(job_status.status).to eq('retryable_error')
-          error = job_status.bgjob_errors
-          expect(error.first.last['error_class']).to eq('StandardError')
-          expect(error.first.last['error_message']).to eq('foo')
+            it 'raises a standard error' do
+              jid = subject.perform_async(submission.id)
+              expect { described_class.drain }.to raise_error(StandardError)
+              job_status = Form526JobStatus.find_by(job_id: jid)
+              expect(job_status.form526_submission_id).to eq(submission.id)
+              expect(job_status.job_class).to eq('BackupSubmission')
+              expect(job_status.job_id).to eq(jid)
+              expect(job_status.status).to eq('retryable_error')
+              error = job_status.bgjob_errors
+              expect(error.first.last['error_class']).to eq('StandardError')
+              expect(error.first.last['error_message']).to eq('foo')
+            end
+          end
         end
       end
     end
diff --git a/spec/lib/vre/monitor_spec.rb b/spec/lib/vre/monitor_spec.rb
index 6b7754ef547..ff5fbdc64ac 100644
--- a/spec/lib/vre/monitor_spec.rb
+++ b/spec/lib/vre/monitor_spec.rb
@@ -28,34 +28,42 @@
   let(:encrypted_user) { KmsEncrypted::Box.new.encrypt(user_struct.to_h.to_json) }
 
   describe '#track_submission_exhaustion' do
-    it 'logs sidekiq job exhaustion failure avoided' do
-      msg = { 'args' => [claim.id, encrypted_user], error_message: 'Error!' }
+    [true, false].each do |flipper_value|
+      context "when json_schemer flipper is #{flipper_value}" do
+        before do
+          allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper_value)
+        end
 
-      log = "Failed all retries on VRE::Submit1900Job, last error: #{msg['error_message']}"
-      payload = {
-        message: msg
-      }
+        it 'logs sidekiq job exhaustion failure avoided' do
+          msg = { 'args' => [claim.id, encrypted_user], error_message: 'Error!' }
 
-      expect(monitor).to receive(:log_silent_failure_avoided).with(payload, nil, anything)
-      expect(StatsD).to receive(:increment).with("#{submission_stats_key}.exhausted")
-      expect(Rails.logger).to receive(:error).with(log)
+          log = "Failed all retries on VRE::Submit1900Job, last error: #{msg['error_message']}"
+          payload = {
+            message: msg
+          }
 
-      monitor.track_submission_exhaustion(msg, user_struct.va_profile_email)
-    end
+          expect(monitor).to receive(:log_silent_failure_avoided).with(payload, nil, anything)
+          expect(StatsD).to receive(:increment).with("#{submission_stats_key}.exhausted")
+          expect(Rails.logger).to receive(:error).with(log)
+
+          monitor.track_submission_exhaustion(msg, user_struct.va_profile_email)
+        end
 
-    it 'logs sidekiq job exhaustion failure' do
-      msg = { 'args' => [claim.id, encrypted_user], error_message: 'Error!' }
+        it 'logs sidekiq job exhaustion failure' do
+          msg = { 'args' => [claim.id, encrypted_user], error_message: 'Error!' }
 
-      log = "Failed all retries on VRE::Submit1900Job, last error: #{msg['error_message']}"
-      payload = {
-        message: msg
-      }
+          log = "Failed all retries on VRE::Submit1900Job, last error: #{msg['error_message']}"
+          payload = {
+            message: msg
+          }
 
-      expect(monitor).to receive(:log_silent_failure).with(payload, nil, anything)
-      expect(StatsD).to receive(:increment).with("#{submission_stats_key}.exhausted")
-      expect(Rails.logger).to receive(:error).with(log)
+          expect(monitor).to receive(:log_silent_failure).with(payload, nil, anything)
+          expect(StatsD).to receive(:increment).with("#{submission_stats_key}.exhausted")
+          expect(Rails.logger).to receive(:error).with(log)
 
-      monitor.track_submission_exhaustion(msg, nil)
+          monitor.track_submission_exhaustion(msg, nil)
+        end
+      end
     end
   end
 end
diff --git a/spec/models/form526_submission_spec.rb b/spec/models/form526_submission_spec.rb
index cddc8715fe7..31fd6dae2fc 100644
--- a/spec/models/form526_submission_spec.rb
+++ b/spec/models/form526_submission_spec.rb
@@ -27,1647 +27,1668 @@
   let(:submit_endpoint) { nil }
   let(:backup_submitted_claim_status) { nil }
 
-  before do
-    Flipper.disable(:disability_compensation_production_tester)
-  end
-
-  describe 'associations' do
-    it { is_expected.to have_many(:form526_submission_remediations) }
-  end
-
-  describe 'submit_endpoint enum' do
-    context 'when submit_endpoint is evss' do
-      let(:submit_endpoint) { 'evss' }
-
-      it 'is valid' do
-        expect(subject).to be_valid
-      end
-    end
-
-    context 'when submit_endpoint is claims_api' do
-      let(:submit_endpoint) { 'claims_api' }
-
-      it 'is valid' do
-        expect(subject).to be_valid
+  [true, false].each do |flipper_value|
+    context "when json_schemer flipper is #{flipper_value}" do
+      before do
+        allow(Flipper).to receive(:enabled?).and_call_original
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper_value)
       end
-    end
-
-    context 'when submit_endpoint is benefits_intake_api' do
-      let(:submit_endpoint) { 'benefits_intake_api' }
 
-      it 'is valid' do
-        expect(subject).to be_valid
+      describe 'associations' do
+        it { is_expected.to have_many(:form526_submission_remediations) }
       end
-    end
 
-    context 'when submit_endpoint is not evss, claims_api or benefits_intake_api' do
-      it 'is invalid' do
-        expect do
-          subject.submit_endpoint = 'other_value'
-        end.to raise_error(ArgumentError, "'other_value' is not a valid submit_endpoint")
-      end
-    end
-  end
+      describe 'submit_endpoint enum' do
+        context 'when submit_endpoint is evss' do
+          let(:submit_endpoint) { 'evss' }
 
-  describe 'backup_submitted_claim_status enum' do
-    context 'when backup_submitted_claim_status is nil' do
-      it 'is valid' do
-        expect(subject).to be_valid
-      end
-    end
-
-    context 'when backup_submitted_claim_status is accepted' do
-      let(:backup_submitted_claim_status) { 'accepted' }
+          it 'is valid' do
+            expect(subject).to be_valid
+          end
+        end
 
-      it 'is valid' do
-        expect(subject).to be_valid
-      end
-    end
+        context 'when submit_endpoint is claims_api' do
+          let(:submit_endpoint) { 'claims_api' }
 
-    context 'when backup_submitted_claim_status is rejected' do
-      let(:backup_submitted_claim_status) { 'rejected' }
+          it 'is valid' do
+            expect(subject).to be_valid
+          end
+        end
 
-      it 'is valid' do
-        expect(subject).to be_valid
-      end
-    end
+        context 'when submit_endpoint is benefits_intake_api' do
+          let(:submit_endpoint) { 'benefits_intake_api' }
 
-    context 'when backup_submitted_claim_status is paranoid_success' do
-      let(:backup_submitted_claim_status) { 'paranoid_success' }
+          it 'is valid' do
+            expect(subject).to be_valid
+          end
+        end
 
-      it 'is valid' do
-        expect(subject).to be_valid
+        context 'when submit_endpoint is not evss, claims_api or benefits_intake_api' do
+          it 'is invalid' do
+            expect do
+              subject.submit_endpoint = 'other_value'
+            end.to raise_error(ArgumentError, "'other_value' is not a valid submit_endpoint")
+          end
+        end
       end
-    end
 
-    context 'when backup_submitted_claim_status is neither accepted, rejected nor nil' do
-      it 'is invalid' do
-        expect do
-          subject.backup_submitted_claim_status = 'other_value'
-        end.to raise_error(ArgumentError, "'other_value' is not a valid backup_submitted_claim_status")
-      end
-    end
-  end
+      describe 'backup_submitted_claim_status enum' do
+        context 'when backup_submitted_claim_status is nil' do
+          it 'is valid' do
+            expect(subject).to be_valid
+          end
+        end
 
-  describe 'scopes' do
-    let!(:in_process) { create(:form526_submission) }
-    let!(:expired) { create(:form526_submission, :created_more_than_3_weeks_ago) }
-    let!(:happy_path_success) { create(:form526_submission, :with_submitted_claim_id) }
-    let!(:happy_lighthouse_path_success) do
-      create(:form526_submission, :with_submitted_claim_id, submit_endpoint: 'claims_api')
-    end
-    let!(:pending_backup) { create(:form526_submission, :backup_path) }
-    let!(:accepted_backup) { create(:form526_submission, :backup_path, :backup_accepted) }
-    let!(:rejected_backup) { create(:form526_submission, :backup_path, :backup_rejected) }
-    let!(:remediated) { create(:form526_submission, :remediated) }
-    let!(:remediated_and_expired) { create(:form526_submission, :remediated, :created_more_than_3_weeks_ago) }
-    let!(:remediated_and_rejected) { create(:form526_submission, :remediated, :backup_path, :backup_rejected) }
-    let!(:new_no_longer_remediated) { create(:form526_submission, :no_longer_remediated) }
-    let!(:old_no_longer_remediated) do
-      Timecop.freeze(3.months.ago) do
-        create(:form526_submission, :no_longer_remediated)
-      end
-    end
-    let!(:paranoid_success) { create(:form526_submission, :backup_path, :paranoid_success) }
-    let!(:success_by_age) do
-      Timecop.freeze((1.year + 1.day).ago) do
-        create(:form526_submission, :backup_path, :paranoid_success)
-      end
-    end
-    let!(:failed_primary) { create(:form526_submission, :with_failed_primary_job) }
-    let!(:exhausted_primary) { create(:form526_submission, :with_exhausted_primary_job) }
-    let!(:failed_backup) { create(:form526_submission, :with_failed_backup_job) }
-    let!(:exhausted_backup) { create(:form526_submission, :with_exhausted_backup_job) }
-
-    before do
-      happy_lighthouse_path_success.form526_job_statuses << Form526JobStatus.new(
-        job_class: 'PollForm526Pdf',
-        status: Form526JobStatus::STATUS[:success],
-        job_id: 1
-      )
-    end
+        context 'when backup_submitted_claim_status is accepted' do
+          let(:backup_submitted_claim_status) { 'accepted' }
 
-    describe 'with_exhausted_primary_jobs' do
-      it 'returns submissions associated to failed or exhausted primary jobs' do
-        expect(Form526Submission.with_exhausted_primary_jobs).to contain_exactly(
-          failed_primary,
-          exhausted_primary
-        )
-      end
-    end
+          it 'is valid' do
+            expect(subject).to be_valid
+          end
+        end
 
-    describe 'with_exhausted_backup_jobs' do
-      it 'returns submissions associated to failed or exhausted backup jobs' do
-        expect(Form526Submission.with_exhausted_backup_jobs).to contain_exactly(
-          failed_backup,
-          exhausted_backup
-        )
-      end
-    end
+        context 'when backup_submitted_claim_status is rejected' do
+          let(:backup_submitted_claim_status) { 'rejected' }
 
-    describe 'paranoid_success_type' do
-      it 'returns records less than a year old with paranoid_success backup status' do
-        expect(Form526Submission.paranoid_success_type).to contain_exactly(
-          paranoid_success
-        )
-      end
-    end
+          it 'is valid' do
+            expect(subject).to be_valid
+          end
+        end
 
-    describe 'success_by_age' do
-      it 'returns records more than a year old with paranoid_success backup status' do
-        expect(Form526Submission.success_by_age).to contain_exactly(
-          success_by_age
-        )
-      end
-    end
+        context 'when backup_submitted_claim_status is paranoid_success' do
+          let(:backup_submitted_claim_status) { 'paranoid_success' }
 
-    describe 'pending_backup' do
-      it 'returns records submitted to the backup path but lacking a decisive state' do
-        expect(Form526Submission.pending_backup).to contain_exactly(
-          pending_backup
-        )
-      end
-    end
+          it 'is valid' do
+            expect(subject).to be_valid
+          end
+        end
 
-    describe 'in_process' do
-      it 'only returns submissions that are still in process' do
-        expect(Form526Submission.in_process).to contain_exactly(
-          in_process,
-          new_no_longer_remediated,
-          exhausted_primary,
-          failed_primary
-        )
+        context 'when backup_submitted_claim_status is neither accepted, rejected nor nil' do
+          it 'is invalid' do
+            expect do
+              subject.backup_submitted_claim_status = 'other_value'
+            end.to raise_error(ArgumentError, "'other_value' is not a valid backup_submitted_claim_status")
+          end
+        end
       end
-    end
 
-    describe 'incomplete_type' do
-      it 'only returns submissions that are still in process' do
-        expect(Form526Submission.incomplete_type).to contain_exactly(
-          in_process,
-          pending_backup,
-          new_no_longer_remediated,
-          exhausted_primary,
-          failed_primary
-        )
-      end
-    end
+      describe 'scopes' do
+        let!(:in_process) { create(:form526_submission) }
+        let!(:expired) { create(:form526_submission, :created_more_than_3_weeks_ago) }
+        let!(:happy_path_success) { create(:form526_submission, :with_submitted_claim_id) }
+        let!(:happy_lighthouse_path_success) do
+          create(:form526_submission, :with_submitted_claim_id, submit_endpoint: 'claims_api')
+        end
+        let!(:pending_backup) { create(:form526_submission, :backup_path) }
+        let!(:accepted_backup) { create(:form526_submission, :backup_path, :backup_accepted) }
+        let!(:rejected_backup) { create(:form526_submission, :backup_path, :backup_rejected) }
+        let!(:remediated) { create(:form526_submission, :remediated) }
+        let!(:remediated_and_expired) { create(:form526_submission, :remediated, :created_more_than_3_weeks_ago) }
+        let!(:remediated_and_rejected) { create(:form526_submission, :remediated, :backup_path, :backup_rejected) }
+        let!(:new_no_longer_remediated) { create(:form526_submission, :no_longer_remediated) }
+        let!(:old_no_longer_remediated) do
+          Timecop.freeze(3.months.ago) do
+            create(:form526_submission, :no_longer_remediated)
+          end
+        end
+        let!(:paranoid_success) { create(:form526_submission, :backup_path, :paranoid_success) }
+        let!(:success_by_age) do
+          Timecop.freeze((1.year + 1.day).ago) do
+            create(:form526_submission, :backup_path, :paranoid_success)
+          end
+        end
+        let!(:failed_primary) { create(:form526_submission, :with_failed_primary_job) }
+        let!(:exhausted_primary) { create(:form526_submission, :with_exhausted_primary_job) }
+        let!(:failed_backup) { create(:form526_submission, :with_failed_backup_job) }
+        let!(:exhausted_backup) { create(:form526_submission, :with_exhausted_backup_job) }
+
+        before do
+          happy_lighthouse_path_success.form526_job_statuses << Form526JobStatus.new(
+            job_class: 'PollForm526Pdf',
+            status: Form526JobStatus::STATUS[:success],
+            job_id: 1
+          )
+        end
 
-    describe 'accepted_to_primary_path' do
-      it 'returns submissions with a submitted_claim_id' do
-        expect(Form526Submission.accepted_to_evss_primary_path).to contain_exactly(
-          happy_path_success
-        )
-      end
+        describe 'with_exhausted_primary_jobs' do
+          it 'returns submissions associated to failed or exhausted primary jobs' do
+            expect(Form526Submission.with_exhausted_primary_jobs).to contain_exactly(
+              failed_primary,
+              exhausted_primary
+            )
+          end
+        end
 
-      it 'returns Lighthouse submissions with a found PDF with a submitted_claim_id' do
-        expect(Form526Submission.accepted_to_lighthouse_primary_path).to contain_exactly(happy_lighthouse_path_success)
-      end
+        describe 'with_exhausted_backup_jobs' do
+          it 'returns submissions associated to failed or exhausted backup jobs' do
+            expect(Form526Submission.with_exhausted_backup_jobs).to contain_exactly(
+              failed_backup,
+              exhausted_backup
+            )
+          end
+        end
 
-      it 'returns both an EVSS submission and a Lighthouse submission with a found PDF and a submitted_claim_id' do
-        expect(Form526Submission.accepted_to_primary_path).to contain_exactly(
-          happy_path_success, happy_lighthouse_path_success
-        )
-      end
+        describe 'paranoid_success_type' do
+          it 'returns records less than a year old with paranoid_success backup status' do
+            expect(Form526Submission.paranoid_success_type).to contain_exactly(
+              paranoid_success
+            )
+          end
+        end
 
-      it 'does not return the LH submission when the PDF is not found' do
-        happy_lighthouse_path_success.form526_job_statuses.last.update(status: Form526JobStatus::STATUS[:pdf_not_found])
+        describe 'success_by_age' do
+          it 'returns records more than a year old with paranoid_success backup status' do
+            expect(Form526Submission.success_by_age).to contain_exactly(
+              success_by_age
+            )
+          end
+        end
 
-        expect(Form526Submission.accepted_to_lighthouse_primary_path).to be_empty
-      end
+        describe 'pending_backup' do
+          it 'returns records submitted to the backup path but lacking a decisive state' do
+            expect(Form526Submission.pending_backup).to contain_exactly(
+              pending_backup
+            )
+          end
+        end
 
-      it 'returns the EVSS submission when the Lighthouse submission is not found' do
-        happy_lighthouse_path_success.update(submitted_claim_id: nil)
-        expect(Form526Submission.accepted_to_primary_path).to contain_exactly(
-          happy_path_success
-        )
-      end
+        describe 'in_process' do
+          it 'only returns submissions that are still in process' do
+            expect(Form526Submission.in_process).to contain_exactly(
+              in_process,
+              new_no_longer_remediated,
+              exhausted_primary,
+              failed_primary
+            )
+          end
+        end
 
-      it 'returns the Lighthouse submission when the EVSS submission has no submitted claim id' do
-        happy_path_success.update(submitted_claim_id: nil)
-        expect(Form526Submission.accepted_to_primary_path).to contain_exactly(
-          happy_lighthouse_path_success
-        )
-      end
+        describe 'incomplete_type' do
+          it 'only returns submissions that are still in process' do
+            expect(Form526Submission.incomplete_type).to contain_exactly(
+              in_process,
+              pending_backup,
+              new_no_longer_remediated,
+              exhausted_primary,
+              failed_primary
+            )
+          end
+        end
 
-      it 'returns neither submission when neither EVSS nor Lighthouse submissions have submitted claim ids' do
-        happy_path_success.update(submitted_claim_id: nil)
-        happy_lighthouse_path_success.update(submitted_claim_id: nil)
+        describe 'accepted_to_primary_path' do
+          it 'returns submissions with a submitted_claim_id' do
+            expect(Form526Submission.accepted_to_evss_primary_path).to contain_exactly(
+              happy_path_success
+            )
+          end
 
-        expect(Form526Submission.accepted_to_primary_path).to be_empty
-      end
-    end
+          it 'returns Lighthouse submissions with a found PDF with a submitted_claim_id' do
+            expect(Form526Submission.accepted_to_lighthouse_primary_path).to contain_exactly(
+              happy_lighthouse_path_success
+            )
+          end
 
-    describe 'accepted_to_backup_path' do
-      it 'returns submissions with a backup_submitted_claim_id that have been explicitly accepted' do
-        expect(Form526Submission.accepted_to_backup_path).to contain_exactly(
-          accepted_backup,
-          paranoid_success,
-          success_by_age
-        )
-      end
-    end
+          it 'returns both an EVSS submission and a Lighthouse submission with a found PDF and a submitted_claim_id' do
+            expect(Form526Submission.accepted_to_primary_path).to contain_exactly(
+              happy_path_success, happy_lighthouse_path_success
+            )
+          end
 
-    describe 'rejected_from_backup_path' do
-      it 'returns submissions with a backup_submitted_claim_id that have been explicitly rejected' do
-        expect(Form526Submission.rejected_from_backup_path).to contain_exactly(
-          rejected_backup,
-          remediated_and_rejected
-        )
-      end
-    end
+          it 'does not return the LH submission when the PDF is not found' do
+            happy_lighthouse_path_success.form526_job_statuses.last.update(
+              status: Form526JobStatus::STATUS[:pdf_not_found]
+            )
 
-    describe 'remediated' do
-      it 'returns everything with a successful remediation' do
-        expect(Form526Submission.remediated).to contain_exactly(
-          remediated,
-          remediated_and_expired,
-          remediated_and_rejected
-        )
-      end
-    end
+            expect(Form526Submission.accepted_to_lighthouse_primary_path).to be_empty
+          end
 
-    describe 'success_type' do
-      it 'returns all submissions on which no further action is required' do
-        expect(Form526Submission.success_type).to contain_exactly(
-          remediated,
-          remediated_and_expired,
-          remediated_and_rejected,
-          happy_path_success,
-          happy_lighthouse_path_success,
-          accepted_backup,
-          paranoid_success,
-          success_by_age
-        )
-      end
-    end
+          it 'returns the EVSS submission when the Lighthouse submission is not found' do
+            happy_lighthouse_path_success.update(submitted_claim_id: nil)
+            expect(Form526Submission.accepted_to_primary_path).to contain_exactly(
+              happy_path_success
+            )
+          end
 
-    describe 'failure_type' do
-      it 'returns anything not explicitly successful or still in process' do
-        expect(Form526Submission.failure_type).to contain_exactly(
-          rejected_backup,
-          expired,
-          old_no_longer_remediated,
-          failed_backup,
-          exhausted_backup
-        )
-      end
+          it 'returns the Lighthouse submission when the EVSS submission has no submitted claim id' do
+            happy_path_success.update(submitted_claim_id: nil)
+            expect(Form526Submission.accepted_to_primary_path).to contain_exactly(
+              happy_lighthouse_path_success
+            )
+          end
 
-      it 'handles the edge case where a submission succeeds during query building' do
-        expired.update!(submitted_claim_id: 'abc123')
+          it 'returns neither submission when neither EVSS nor Lighthouse submissions have submitted claim ids' do
+            happy_path_success.update(submitted_claim_id: nil)
+            happy_lighthouse_path_success.update(submitted_claim_id: nil)
 
-        expect(Form526Submission.failure_type).to contain_exactly(
-          rejected_backup,
-          old_no_longer_remediated,
-          failed_backup,
-          exhausted_backup
-        )
-      end
-    end
-  end
+            expect(Form526Submission.accepted_to_primary_path).to be_empty
+          end
+        end
 
-  shared_examples '#start_evss_submission' do
-    context 'when it is all claims' do
-      it 'queues an all claims job' do
-        expect do
-          subject.start_evss_submission_job
-        end.to change(EVSS::DisabilityCompensationForm::SubmitForm526AllClaim.jobs, :size).by(1)
-      end
-    end
-  end
+        describe 'accepted_to_backup_path' do
+          it 'returns submissions with a backup_submitted_claim_id that have been explicitly accepted' do
+            expect(Form526Submission.accepted_to_backup_path).to contain_exactly(
+              accepted_backup,
+              paranoid_success,
+              success_by_age
+            )
+          end
+        end
 
-  describe '#start' do
-    context 'the submission is for hypertension' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/only_526_hypertension.json')
-      end
+        describe 'rejected_from_backup_path' do
+          it 'returns submissions with a backup_submitted_claim_id that have been explicitly rejected' do
+            expect(Form526Submission.rejected_from_backup_path).to contain_exactly(
+              rejected_backup,
+              remediated_and_rejected
+            )
+          end
+        end
 
-      it_behaves_like '#start_evss_submission'
-    end
+        describe 'remediated' do
+          it 'returns everything with a successful remediation' do
+            expect(Form526Submission.remediated).to contain_exactly(
+              remediated,
+              remediated_and_expired,
+              remediated_and_rejected
+            )
+          end
+        end
 
-    context 'the submission is NOT for hypertension' do
-      it_behaves_like '#start_evss_submission'
-    end
+        describe 'success_type' do
+          it 'returns all submissions on which no further action is required' do
+            expect(Form526Submission.success_type).to contain_exactly(
+              remediated,
+              remediated_and_expired,
+              remediated_and_rejected,
+              happy_path_success,
+              happy_lighthouse_path_success,
+              accepted_backup,
+              paranoid_success,
+              success_by_age
+            )
+          end
+        end
 
-    context 'CFI metric logging' do
-      let!(:in_progress_form) do
-        ipf = create(:in_progress_526_form, user_uuid: user.uuid)
-        fd = ipf.form_data
-        fd = JSON.parse(fd)
-        fd['rated_disabilities'] = rated_disabilities
-        ipf.update!(form_data: fd)
-        ipf
-      end
+        describe 'failure_type' do
+          it 'returns anything not explicitly successful or still in process' do
+            expect(Form526Submission.failure_type).to contain_exactly(
+              rejected_backup,
+              expired,
+              old_no_longer_remediated,
+              failed_backup,
+              exhausted_backup
+            )
+          end
 
-      before do
-        allow(StatsD).to receive(:increment)
-        allow(Rails.logger).to receive(:info)
-      end
+          it 'handles the edge case where a submission succeeds during query building' do
+            expired.update!(submitted_claim_id: 'abc123')
 
-      def expect_submit_log(num_max_rated, num_max_rated_cfi, total_cfi)
-        expect(Rails.logger).to have_received(:info).with(
-          'Max CFI form526 submission',
-          { id: subject.id,
-            num_max_rated:,
-            num_max_rated_cfi:,
-            total_cfi:,
-            cfi_checkbox_was_selected: false }
-        )
+            expect(Form526Submission.failure_type).to contain_exactly(
+              rejected_backup,
+              old_no_longer_remediated,
+              failed_backup,
+              exhausted_backup
+            )
+          end
+        end
       end
 
-      def expect_max_cfi_logged(disability_claimed, diagnostic_code)
-        expect(StatsD).to have_received(:increment).with('api.max_cfi.submit',
-                                                         tags: ["diagnostic_code:#{diagnostic_code}",
-                                                                "claimed:#{disability_claimed}"])
+      shared_examples '#start_evss_submission' do
+        context 'when it is all claims' do
+          it 'queues an all claims job' do
+            expect do
+              subject.start_evss_submission_job
+            end.to change(EVSS::DisabilityCompensationForm::SubmitForm526AllClaim.jobs, :size).by(1)
+          end
+        end
       end
 
-      def expect_no_max_cfi_logged(diagnostic_code)
-        expect(StatsD).not_to have_received(:increment).with('api.max_cfi.submit',
-                                                             tags: ["diagnostic_code:#{diagnostic_code}",
-                                                                    anything])
-      end
+      describe '#start' do
+        context 'the submission is for hypertension' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/only_526_hypertension.json')
+          end
 
-      context 'the submission is for tinnitus' do
-        let(:form_json) do
-          File.read('spec/support/disability_compensation_form/submissions/only_526_tinnitus.json')
+          it_behaves_like '#start_evss_submission'
         end
-        let(:rated_disabilities) do
-          [
-            { name: 'Tinnitus',
-              diagnostic_code: ClaimFastTracking::DiagnosticCodes::TINNITUS,
-              rating_percentage:,
-              maximum_rating_percentage: 10 }
-          ]
+
+        context 'the submission is NOT for hypertension' do
+          it_behaves_like '#start_evss_submission'
         end
-        let(:rating_percentage) { 0 }
 
-        context 'Rated Tinnitus is at maximum' do
-          let(:rating_percentage) { 10 }
+        context 'CFI metric logging' do
+          let!(:in_progress_form) do
+            ipf = create(:in_progress_526_form, user_uuid: user.uuid)
+            fd = ipf.form_data
+            fd = JSON.parse(fd)
+            fd['rated_disabilities'] = rated_disabilities
+            ipf.update!(form_data: fd)
+            ipf
+          end
 
-          it 'logs CFI metric upon submission' do
-            subject.start
-            expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                             tags: ['claimed:true', 'has_max_rated:true'])
-            expect_max_cfi_logged(true, 6260)
-            expect_submit_log(1, 1, 1)
+          before do
+            allow(StatsD).to receive(:increment)
+            allow(Rails.logger).to receive(:info)
           end
-        end
 
-        context 'Rated Tinnitus is not at maximum' do
-          it 'logs CFI metric upon submission' do
-            subject.start
-            expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                             tags: ['claimed:false', 'has_max_rated:false'])
-            expect_no_max_cfi_logged(6260)
+          def expect_submit_log(num_max_rated, num_max_rated_cfi, total_cfi)
+            expect(Rails.logger).to have_received(:info).with(
+              'Max CFI form526 submission',
+              { id: subject.id,
+                num_max_rated:,
+                num_max_rated_cfi:,
+                total_cfi:,
+                cfi_checkbox_was_selected: false }
+            )
           end
-        end
-      end
 
-      context 'the submission is for hypertension with no max rating percentage' do
-        let(:form_json) do
-          File.read('spec/support/disability_compensation_form/submissions/only_526_hypertension.json')
-        end
-        let(:rated_disabilities) do
-          [
-            { name: 'Hypertension',
-              diagnostic_code: ClaimFastTracking::DiagnosticCodes::HYPERTENSION,
-              rating_percentage: 20 }
-          ]
-        end
+          def expect_max_cfi_logged(disability_claimed, diagnostic_code)
+            expect(StatsD).to have_received(:increment).with('api.max_cfi.submit',
+                                                             tags: ["diagnostic_code:#{diagnostic_code}",
+                                                                    "claimed:#{disability_claimed}"])
+          end
 
-        it 'logs CFI metric upon submission' do
-          subject.start
-          expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                           tags: ['claimed:false', 'has_max_rated:false'])
-          expect_no_max_cfi_logged(7101)
-          expect_submit_log(0, 0, 1)
-        end
-      end
+          def expect_no_max_cfi_logged(diagnostic_code)
+            expect(StatsD).not_to have_received(:increment).with('api.max_cfi.submit',
+                                                                 tags: ["diagnostic_code:#{diagnostic_code}",
+                                                                        anything])
+          end
 
-      context 'the submission for single cfi for a Veteran with multiple rated conditions' do
-        let(:form_json) do
-          File.read('spec/support/disability_compensation_form/submissions/only_526_hypertension.json')
-        end
-        let(:rated_disabilities) do
-          [
-            { name: 'Tinnitus',
-              diagnostic_code: ClaimFastTracking::DiagnosticCodes::TINNITUS,
-              rating_percentage: rating_percentage_tinnitus,
-              maximum_rating_percentage: 10 },
-            { name: 'Hypertension',
-              diagnostic_code: ClaimFastTracking::DiagnosticCodes::HYPERTENSION,
-              rating_percentage: rating_percentage_hypertension,
-              maximum_rating_percentage: 60 }
-          ]
-        end
-        let(:rating_percentage_tinnitus) { 0 }
-        let(:rating_percentage_hypertension) { 0 }
+          context 'the submission is for tinnitus' do
+            let(:form_json) do
+              File.read('spec/support/disability_compensation_form/submissions/only_526_tinnitus.json')
+            end
+            let(:rated_disabilities) do
+              [
+                { name: 'Tinnitus',
+                  diagnostic_code: ClaimFastTracking::DiagnosticCodes::TINNITUS,
+                  rating_percentage:,
+                  maximum_rating_percentage: 10 }
+              ]
+            end
+            let(:rating_percentage) { 0 }
+
+            context 'Rated Tinnitus is at maximum' do
+              let(:rating_percentage) { 10 }
+
+              it 'logs CFI metric upon submission' do
+                subject.start
+                expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                                 tags: ['claimed:true', 'has_max_rated:true'])
+                expect_max_cfi_logged(true, 6260)
+                expect_submit_log(1, 1, 1)
+              end
+            end
+
+            context 'Rated Tinnitus is not at maximum' do
+              it 'logs CFI metric upon submission' do
+                subject.start
+                expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                                 tags: ['claimed:false', 'has_max_rated:false'])
+                expect_no_max_cfi_logged(6260)
+              end
+            end
+          end
 
-        context 'Rated Disabilities are not at maximum' do
-          it 'logs CFI metric upon submission for only hypertension' do
-            subject.start
-            expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                             tags: ['claimed:false', 'has_max_rated:false'])
-            expect_no_max_cfi_logged(6260)
-            expect_no_max_cfi_logged(7101)
-            expect_submit_log(0, 0, 1)
+          context 'the submission is for hypertension with no max rating percentage' do
+            let(:form_json) do
+              File.read('spec/support/disability_compensation_form/submissions/only_526_hypertension.json')
+            end
+            let(:rated_disabilities) do
+              [
+                { name: 'Hypertension',
+                  diagnostic_code: ClaimFastTracking::DiagnosticCodes::HYPERTENSION,
+                  rating_percentage: 20 }
+              ]
+            end
+
+            it 'logs CFI metric upon submission' do
+              subject.start
+              expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                               tags: ['claimed:false', 'has_max_rated:false'])
+              expect_no_max_cfi_logged(7101)
+              expect_submit_log(0, 0, 1)
+            end
           end
-        end
 
-        context 'Rated Disabilities of cfi is at maximum' do
-          let(:rating_percentage_hypertension) { 60 }
+          context 'the submission for single cfi for a Veteran with multiple rated conditions' do
+            let(:form_json) do
+              File.read('spec/support/disability_compensation_form/submissions/only_526_hypertension.json')
+            end
+            let(:rated_disabilities) do
+              [
+                { name: 'Tinnitus',
+                  diagnostic_code: ClaimFastTracking::DiagnosticCodes::TINNITUS,
+                  rating_percentage: rating_percentage_tinnitus,
+                  maximum_rating_percentage: 10 },
+                { name: 'Hypertension',
+                  diagnostic_code: ClaimFastTracking::DiagnosticCodes::HYPERTENSION,
+                  rating_percentage: rating_percentage_hypertension,
+                  maximum_rating_percentage: 60 }
+              ]
+            end
+            let(:rating_percentage_tinnitus) { 0 }
+            let(:rating_percentage_hypertension) { 0 }
+
+            context 'Rated Disabilities are not at maximum' do
+              it 'logs CFI metric upon submission for only hypertension' do
+                subject.start
+                expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                                 tags: ['claimed:false', 'has_max_rated:false'])
+                expect_no_max_cfi_logged(6260)
+                expect_no_max_cfi_logged(7101)
+                expect_submit_log(0, 0, 1)
+              end
+            end
+
+            context 'Rated Disabilities of cfi is at maximum' do
+              let(:rating_percentage_hypertension) { 60 }
+
+              it 'logs CFI metric upon submission for only hypertension' do
+                subject.start
+                expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                                 tags: ['claimed:true', 'has_max_rated:true'])
+                expect_max_cfi_logged(true, 7101)
+                expect_submit_log(1, 1, 1)
+                expect_no_max_cfi_logged(6260)
+              end
+            end
+
+            context 'All Rated Disabilities at maximum' do
+              let(:rating_percentage_tinnitus) { 10 }
+              let(:rating_percentage_hypertension) { 60 }
+
+              it 'logs CFI metric upon submission for only hypertension' do
+                subject.start
+                expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                                 tags: ['claimed:true', 'has_max_rated:true'])
+                expect_max_cfi_logged(true, 7101)
+                expect_max_cfi_logged(false, 6260)
+                expect_submit_log(2, 1, 1)
+              end
+            end
+          end
 
-          it 'logs CFI metric upon submission for only hypertension' do
-            subject.start
-            expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                             tags: ['claimed:true', 'has_max_rated:true'])
-            expect_max_cfi_logged(true, 7101)
-            expect_submit_log(1, 1, 1)
-            expect_no_max_cfi_logged(6260)
+          context 'the submission for multiple cfi for a Veteran with multiple rated conditions' do
+            let(:form_json) do
+              File.read('spec/support/disability_compensation_form/submissions/only_526_two_cfi_with_max_ratings.json')
+            end
+            let(:rated_disabilities) do
+              [
+                { name: 'Tinnitus',
+                  diagnostic_code: ClaimFastTracking::DiagnosticCodes::TINNITUS,
+                  rating_percentage: rating_percentage_tinnitus,
+                  maximum_rating_percentage: 10 },
+                { name: 'Hypertension',
+                  diagnostic_code: ClaimFastTracking::DiagnosticCodes::HYPERTENSION,
+                  rating_percentage: rating_percentage_hypertension,
+                  maximum_rating_percentage: 60 }
+              ]
+            end
+            let(:rating_percentage_tinnitus) { 0 }
+            let(:rating_percentage_hypertension) { 0 }
+
+            context 'Rated Disabilities are not at maximum' do
+              it 'does not log CFI metric upon submission' do
+                subject.start
+                expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                                 tags: ['claimed:false', 'has_max_rated:false'])
+                expect_no_max_cfi_logged(6260)
+                expect_no_max_cfi_logged(7101)
+                expect_submit_log(0, 0, 2)
+              end
+            end
+
+            context 'Rated Disabilities are at maximum' do
+              let(:rating_percentage_tinnitus) { 10 }
+              let(:rating_percentage_hypertension) { 60 }
+
+              it 'logs CFI metric upon submission' do
+                subject.start
+                expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                                 tags: ['claimed:true', 'has_max_rated:true'])
+                expect_max_cfi_logged(true, 6260)
+                expect_max_cfi_logged(true, 7101)
+                expect_submit_log(2, 2, 2)
+              end
+            end
+
+            context 'Only Tinnitus is rated at the maximum' do
+              let(:rating_percentage_tinnitus) { 10 }
+
+              it 'logs CFI metric upon submission only for tinnitus' do
+                subject.start
+                expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                                 tags: ['claimed:true', 'has_max_rated:true'])
+                expect_max_cfi_logged(true, 6260)
+                expect_no_max_cfi_logged(7101)
+                expect_submit_log(1, 1, 2)
+              end
+            end
+
+            context 'Only Hypertension is rated at the maximum' do
+              let(:rating_percentage_hypertension) { 60 }
+
+              it 'does not log CFI metric upon submission' do
+                subject.start
+                expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
+                                                                 tags: ['claimed:true', 'has_max_rated:true'])
+                expect_max_cfi_logged(true, 7101)
+                expect_no_max_cfi_logged(6260)
+                expect_submit_log(1, 1, 2)
+              end
+            end
           end
         end
+      end
 
-        context 'All Rated Disabilities at maximum' do
-          let(:rating_percentage_tinnitus) { 10 }
-          let(:rating_percentage_hypertension) { 60 }
-
-          it 'logs CFI metric upon submission for only hypertension' do
-            subject.start
-            expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                             tags: ['claimed:true', 'has_max_rated:true'])
-            expect_max_cfi_logged(true, 7101)
-            expect_max_cfi_logged(false, 6260)
-            expect_submit_log(2, 1, 1)
+      describe '#start_evss_submission_job' do
+        it_behaves_like '#start_evss_submission'
+      end
+
+      describe '#submit_with_birls_id_that_hasnt_been_tried_yet!' do
+        context 'when it is all claims' do
+          it 'queues an all claims job' do
+            expect(subject.birls_id).to be_truthy
+            expect(subject.birls_ids.count).to eq 1
+            subject.birls_ids_tried = { subject.birls_id => ['some timestamp'] }.to_json
+            subject.save!
+            expect { subject.submit_with_birls_id_that_hasnt_been_tried_yet! }.to(
+              change(EVSS::DisabilityCompensationForm::SubmitForm526AllClaim.jobs, :size).by(0)
+            )
+            next_birls_id = "#{subject.birls_id}cat"
+            subject.add_birls_ids next_birls_id
+            expect { subject.submit_with_birls_id_that_hasnt_been_tried_yet! }.to(
+              change(EVSS::DisabilityCompensationForm::SubmitForm526AllClaim.jobs, :size).by(1)
+            )
+            expect(subject.birls_id).to eq next_birls_id
           end
         end
       end
 
-      context 'the submission for multiple cfi for a Veteran with multiple rated conditions' do
-        let(:form_json) do
-          File.read('spec/support/disability_compensation_form/submissions/only_526_two_cfi_with_max_ratings.json')
-        end
-        let(:rated_disabilities) do
-          [
-            { name: 'Tinnitus',
-              diagnostic_code: ClaimFastTracking::DiagnosticCodes::TINNITUS,
-              rating_percentage: rating_percentage_tinnitus,
-              maximum_rating_percentage: 10 },
-            { name: 'Hypertension',
-              diagnostic_code: ClaimFastTracking::DiagnosticCodes::HYPERTENSION,
-              rating_percentage: rating_percentage_hypertension,
-              maximum_rating_percentage: 60 }
-          ]
+      describe '#form' do
+        it 'returns the form as a hash' do
+          expect(subject.form).to eq(JSON.parse(form_json))
         end
-        let(:rating_percentage_tinnitus) { 0 }
-        let(:rating_percentage_hypertension) { 0 }
+      end
 
-        context 'Rated Disabilities are not at maximum' do
-          it 'does not log CFI metric upon submission' do
-            subject.start
-            expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                             tags: ['claimed:false', 'has_max_rated:false'])
-            expect_no_max_cfi_logged(6260)
-            expect_no_max_cfi_logged(7101)
-            expect_submit_log(0, 0, 2)
+      describe '#form_to_json' do
+        context 'with form 526' do
+          it 'returns the sub form as json' do
+            expect(subject.form_to_json(Form526Submission::FORM_526)).to eq(JSON.parse(form_json)['form526'].to_json)
           end
         end
 
-        context 'Rated Disabilities are at maximum' do
-          let(:rating_percentage_tinnitus) { 10 }
-          let(:rating_percentage_hypertension) { 60 }
+        context 'with form 4142' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_4142.json')
+          end
 
-          it 'logs CFI metric upon submission' do
-            subject.start
-            expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                             tags: ['claimed:true', 'has_max_rated:true'])
-            expect_max_cfi_logged(true, 6260)
-            expect_max_cfi_logged(true, 7101)
-            expect_submit_log(2, 2, 2)
+          it 'returns the sub form as json' do
+            expect(subject.form_to_json(Form526Submission::FORM_4142)).to eq(JSON.parse(form_json)['form4142'].to_json)
           end
         end
 
-        context 'Only Tinnitus is rated at the maximum' do
-          let(:rating_percentage_tinnitus) { 10 }
+        context 'with form 0781' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_0781.json')
+          end
 
-          it 'logs CFI metric upon submission only for tinnitus' do
-            subject.start
-            expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                             tags: ['claimed:true', 'has_max_rated:true'])
-            expect_max_cfi_logged(true, 6260)
-            expect_no_max_cfi_logged(7101)
-            expect_submit_log(1, 1, 2)
+          it 'returns the sub form as json' do
+            expect(subject.form_to_json(Form526Submission::FORM_0781)).to eq(JSON.parse(form_json)['form0781'].to_json)
           end
         end
 
-        context 'Only Hypertension is rated at the maximum' do
-          let(:rating_percentage_hypertension) { 60 }
+        context 'with form 8940' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_8940.json')
+          end
 
-          it 'does not log CFI metric upon submission' do
-            subject.start
-            expect(StatsD).to have_received(:increment).with('api.max_cfi.on_submit',
-                                                             tags: ['claimed:true', 'has_max_rated:true'])
-            expect_max_cfi_logged(true, 7101)
-            expect_no_max_cfi_logged(6260)
-            expect_submit_log(1, 1, 2)
+          it 'returns the sub form as json' do
+            expect(subject.form_to_json(Form526Submission::FORM_8940)).to eq(JSON.parse(form_json)['form8940'].to_json)
           end
         end
       end
-    end
-  end
-
-  describe '#start_evss_submission_job' do
-    it_behaves_like '#start_evss_submission'
-  end
 
-  describe '#submit_with_birls_id_that_hasnt_been_tried_yet!' do
-    context 'when it is all claims' do
-      it 'queues an all claims job' do
-        expect(subject.birls_id).to be_truthy
-        expect(subject.birls_ids.count).to eq 1
-        subject.birls_ids_tried = { subject.birls_id => ['some timestamp'] }.to_json
-        subject.save!
-        expect { subject.submit_with_birls_id_that_hasnt_been_tried_yet! }.to(
-          change(EVSS::DisabilityCompensationForm::SubmitForm526AllClaim.jobs, :size).by(0)
-        )
-        next_birls_id = "#{subject.birls_id}cat"
-        subject.add_birls_ids next_birls_id
-        expect { subject.submit_with_birls_id_that_hasnt_been_tried_yet! }.to(
-          change(EVSS::DisabilityCompensationForm::SubmitForm526AllClaim.jobs, :size).by(1)
-        )
-        expect(subject.birls_id).to eq next_birls_id
+      describe '#auth_headers' do
+        it 'returns the parsed auth headers' do
+          expect(subject.auth_headers).to eq(auth_headers)
+        end
       end
-    end
-  end
-
-  describe '#form' do
-    it 'returns the form as a hash' do
-      expect(subject.form).to eq(JSON.parse(form_json))
-    end
-  end
 
-  describe '#form_to_json' do
-    context 'with form 526' do
-      it 'returns the sub form as json' do
-        expect(subject.form_to_json(Form526Submission::FORM_526)).to eq(JSON.parse(form_json)['form526'].to_json)
-      end
-    end
+      describe '#add_birls_ids' do
+        subject do
+          headers = JSON.parse auth_headers.to_json
+          Form526Submission.new(
+            user_uuid: user.uuid,
+            saved_claim_id: saved_claim.id,
+            auth_headers_json: headers.to_json,
+            form_json:,
+            birls_ids_tried: birls_ids_tried.to_json
+          )
+        end
 
-    context 'with form 4142' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_4142.json')
-      end
+        context 'birls_ids_tried nil' do
+          let(:birls_ids_tried) { nil }
 
-      it 'returns the sub form as json' do
-        expect(subject.form_to_json(Form526Submission::FORM_4142)).to eq(JSON.parse(form_json)['form4142'].to_json)
-      end
-    end
+          it 'has no default' do
+            expect(subject.birls_ids_tried).to eq 'null'
+          end
 
-    context 'with form 0781' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_0781.json')
-      end
+          context 'using nil as an id' do
+            it 'results in an empty hash' do
+              subject.add_birls_ids nil
+              expect(JSON.parse(subject.birls_ids_tried)).to be_a Hash
+            end
+          end
 
-      it 'returns the sub form as json' do
-        expect(subject.form_to_json(Form526Submission::FORM_0781)).to eq(JSON.parse(form_json)['form0781'].to_json)
-      end
-    end
+          context 'single id' do
+            it 'initializes with an empty array' do
+              subject.add_birls_ids 'a'
+              expect(subject.birls_ids_tried_hash).to eq 'a' => []
+            end
+          end
 
-    context 'with form 8940' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_8940.json')
-      end
+          context 'an array of ids' do
+            it 'initializes with an empty arrays' do
+              subject.add_birls_ids(%w[a b c])
+              expect(subject.birls_ids_tried_hash).to eq 'a' => [], 'b' => [], 'c' => []
+            end
+          end
+        end
 
-      it 'returns the sub form as json' do
-        expect(subject.form_to_json(Form526Submission::FORM_8940)).to eq(JSON.parse(form_json)['form8940'].to_json)
-      end
-    end
-  end
+        context 'birls_ids_tried already has values' do
+          let(:birls_ids_tried) { { 'a' => ['2021-02-01T14:28:33Z'] } }
 
-  describe '#auth_headers' do
-    it 'returns the parsed auth headers' do
-      expect(subject.auth_headers).to eq(auth_headers)
-    end
-  end
+          context 'using nil as an id' do
+            it 'results in an empty hash' do
+              subject.add_birls_ids nil
+              expect(subject.birls_ids_tried_hash).to eq birls_ids_tried
+            end
+          end
 
-  describe '#add_birls_ids' do
-    subject do
-      headers = JSON.parse auth_headers.to_json
-      Form526Submission.new(
-        user_uuid: user.uuid,
-        saved_claim_id: saved_claim.id,
-        auth_headers_json: headers.to_json,
-        form_json:,
-        birls_ids_tried: birls_ids_tried.to_json
-      )
-    end
+          context 'single id that is already present' do
+            it 'does nothing' do
+              subject.add_birls_ids 'a'
+              expect(subject.birls_ids_tried_hash).to eq birls_ids_tried
+            end
+          end
 
-    context 'birls_ids_tried nil' do
-      let(:birls_ids_tried) { nil }
+          context 'single id that is not already present' do
+            it 'does nothing' do
+              subject.add_birls_ids 'b'
+              expect(subject.birls_ids_tried_hash).to eq birls_ids_tried.merge('b' => [])
+            end
+          end
 
-      it 'has no default' do
-        expect(subject.birls_ids_tried).to eq 'null'
-      end
+          context 'an array of ids' do
+            it 'initializes with an empty arrays, for ids that area not already present' do
+              subject.add_birls_ids(['a', :b, :c])
+              expect(subject.birls_ids_tried_hash).to eq birls_ids_tried.merge('b' => [], 'c' => [])
+            end
+          end
 
-      context 'using nil as an id' do
-        it 'results in an empty hash' do
-          subject.add_birls_ids nil
-          expect(JSON.parse(subject.birls_ids_tried)).to be_a Hash
+          context 'an array of ids persisted' do
+            it 'persists' do
+              subject.add_birls_ids(['a', :b, :c])
+              subject.save
+              subject.reload
+              expect(subject.birls_ids_tried_hash).to eq birls_ids_tried.merge('b' => [], 'c' => [])
+            end
+          end
         end
       end
 
-      context 'single id' do
-        it 'initializes with an empty array' do
-          subject.add_birls_ids 'a'
-          expect(subject.birls_ids_tried_hash).to eq 'a' => []
+      describe '#birls_ids' do
+        subject do
+          headers = JSON.parse auth_headers.to_json
+          headers['va_eauth_birlsfilenumber'] = birls_id
+          Form526Submission.new(
+            user_uuid: user.uuid,
+            saved_claim_id: saved_claim.id,
+            auth_headers_json: headers.to_json,
+            form_json:,
+            birls_ids_tried: birls_ids_tried.to_json
+          )
         end
-      end
 
-      context 'an array of ids' do
-        it 'initializes with an empty arrays' do
-          subject.add_birls_ids(%w[a b c])
-          expect(subject.birls_ids_tried_hash).to eq 'a' => [], 'b' => [], 'c' => []
-        end
-      end
-    end
+        let(:birls_id) { 'a' }
+        let(:birls_ids_tried) { { b: [], c: ['2021-02-01T14:28:33Z'] } }
 
-    context 'birls_ids_tried already has values' do
-      let(:birls_ids_tried) { { 'a' => ['2021-02-01T14:28:33Z'] } }
+        context 'birls_ids_tried present and auth_headers present' do
+          it 'lists all birls ids' do
+            expect(subject.birls_ids).to contain_exactly 'c', 'b', 'a'
+          end
 
-      context 'using nil as an id' do
-        it 'results in an empty hash' do
-          subject.add_birls_ids nil
-          expect(subject.birls_ids_tried_hash).to eq birls_ids_tried
+          it 'persists' do
+            subject.save
+            subject.reload
+            expect(subject.birls_ids).to contain_exactly 'b', 'c', 'a'
+          end
         end
-      end
 
-      context 'single id that is already present' do
-        it 'does nothing' do
-          subject.add_birls_ids 'a'
-          expect(subject.birls_ids_tried_hash).to eq birls_ids_tried
-        end
-      end
+        context 'only birls_ids_tried present' do
+          subject do
+            Form526Submission.new(
+              user_uuid: user.uuid,
+              saved_claim_id: saved_claim.id,
+              form_json:,
+              birls_ids_tried: birls_ids_tried.to_json
+            )
+          end
 
-      context 'single id that is not already present' do
-        it 'does nothing' do
-          subject.add_birls_ids 'b'
-          expect(subject.birls_ids_tried_hash).to eq birls_ids_tried.merge('b' => [])
+          it 'lists birls ids from birls_ids_tried only' do
+            expect(subject.birls_ids).to contain_exactly 'b', 'c'
+          end
         end
-      end
 
-      context 'an array of ids' do
-        it 'initializes with an empty arrays, for ids that area not already present' do
-          subject.add_birls_ids(['a', :b, :c])
-          expect(subject.birls_ids_tried_hash).to eq birls_ids_tried.merge('b' => [], 'c' => [])
-        end
-      end
+        context 'only auth_headers present' do
+          let(:birls_ids_tried) { nil }
 
-      context 'an array of ids persisted' do
-        it 'persists' do
-          subject.add_birls_ids(['a', :b, :c])
-          subject.save
-          subject.reload
-          expect(subject.birls_ids_tried_hash).to eq birls_ids_tried.merge('b' => [], 'c' => [])
+          it 'lists birls ids from auth_headers only' do
+            expect(subject.birls_ids).to contain_exactly 'a'
+          end
         end
       end
-    end
-  end
-
-  describe '#birls_ids' do
-    subject do
-      headers = JSON.parse auth_headers.to_json
-      headers['va_eauth_birlsfilenumber'] = birls_id
-      Form526Submission.new(
-        user_uuid: user.uuid,
-        saved_claim_id: saved_claim.id,
-        auth_headers_json: headers.to_json,
-        form_json:,
-        birls_ids_tried: birls_ids_tried.to_json
-      )
-    end
-
-    let(:birls_id) { 'a' }
-    let(:birls_ids_tried) { { b: [], c: ['2021-02-01T14:28:33Z'] } }
 
-    context 'birls_ids_tried present and auth_headers present' do
-      it 'lists all birls ids' do
-        expect(subject.birls_ids).to contain_exactly 'c', 'b', 'a'
-      end
+      describe '#mark_birls_id_as_tried' do
+        subject do
+          headers = JSON.parse auth_headers.to_json
+          headers['va_eauth_birlsfilenumber'] = birls_id
+          Form526Submission.new(
+            user_uuid: user.uuid,
+            saved_claim_id: saved_claim.id,
+            auth_headers_json: headers.to_json,
+            form_json:,
+            birls_ids_tried: birls_ids_tried.to_json
+          )
+        end
 
-      it 'persists' do
-        subject.save
-        subject.reload
-        expect(subject.birls_ids).to contain_exactly 'b', 'c', 'a'
-      end
-    end
+        let(:birls_id) { 'a' }
 
-    context 'only birls_ids_tried present' do
-      subject do
-        Form526Submission.new(
-          user_uuid: user.uuid,
-          saved_claim_id: saved_claim.id,
-          form_json:,
-          birls_ids_tried: birls_ids_tried.to_json
-        )
-      end
+        context 'nil birls_ids_tried' do
+          let(:birls_ids_tried) { nil }
 
-      it 'lists birls ids from birls_ids_tried only' do
-        expect(subject.birls_ids).to contain_exactly 'b', 'c'
-      end
-    end
+          it 'adds the current birls id to birls_ids_tried' do
+            expect(JSON.parse(subject.birls_ids_tried)).to eq birls_ids_tried
+            subject.mark_birls_id_as_tried
+            expect(subject.birls_ids_tried_hash.keys).to contain_exactly 'a'
+            subject.save
+            subject.reload
+            expect(subject.birls_ids_tried_hash.keys).to contain_exactly 'a'
+          end
+        end
 
-    context 'only auth_headers present' do
-      let(:birls_ids_tried) { nil }
+        context 'previous attempts' do
+          let(:birls_ids_tried) { { 'b' => ['2021-02-01T14:28:33Z'] } }
 
-      it 'lists birls ids from auth_headers only' do
-        expect(subject.birls_ids).to contain_exactly 'a'
+          it 'adds the current BIRLS ID to birls_ids_tried array (turns birls_ids_tried into an array if nil)' do
+            expect(JSON.parse(subject.birls_ids_tried)).to eq birls_ids_tried
+            subject.mark_birls_id_as_tried
+            expect(subject.birls_ids_tried_hash.keys).to contain_exactly(birls_id, *birls_ids_tried.keys)
+            subject.save
+            subject.reload
+            expect(subject.birls_ids_tried_hash.keys).to contain_exactly(birls_id, *birls_ids_tried.keys)
+          end
+        end
       end
-    end
-  end
-
-  describe '#mark_birls_id_as_tried' do
-    subject do
-      headers = JSON.parse auth_headers.to_json
-      headers['va_eauth_birlsfilenumber'] = birls_id
-      Form526Submission.new(
-        user_uuid: user.uuid,
-        saved_claim_id: saved_claim.id,
-        auth_headers_json: headers.to_json,
-        form_json:,
-        birls_ids_tried: birls_ids_tried.to_json
-      )
-    end
-
-    let(:birls_id) { 'a' }
 
-    context 'nil birls_ids_tried' do
-      let(:birls_ids_tried) { nil }
-
-      it 'adds the current birls id to birls_ids_tried' do
-        expect(JSON.parse(subject.birls_ids_tried)).to eq birls_ids_tried
-        subject.mark_birls_id_as_tried
-        expect(subject.birls_ids_tried_hash.keys).to contain_exactly 'a'
-        subject.save
-        subject.reload
-        expect(subject.birls_ids_tried_hash.keys).to contain_exactly 'a'
-      end
-    end
+      describe '#birls_ids_that_havent_been_tried_yet' do
+        subject do
+          headers = JSON.parse auth_headers.to_json
+          headers['va_eauth_birlsfilenumber'] = birls_id
+          Form526Submission.new(
+            user_uuid: user.uuid,
+            saved_claim_id: saved_claim.id,
+            auth_headers_json: headers.to_json,
+            form_json:,
+            birls_ids_tried: birls_ids_tried.to_json
+          )
+        end
 
-    context 'previous attempts' do
-      let(:birls_ids_tried) { { 'b' => ['2021-02-01T14:28:33Z'] } }
+        let(:birls_id) { 'a' }
+        let(:birls_ids_tried) { { b: [], c: ['2021-02-01T14:28:33Z'], d: nil } }
 
-      it 'adds the current BIRLS ID to birls_ids_tried array (turns birls_ids_tried into an array if nil)' do
-        expect(JSON.parse(subject.birls_ids_tried)).to eq birls_ids_tried
-        subject.mark_birls_id_as_tried
-        expect(subject.birls_ids_tried_hash.keys).to contain_exactly(birls_id, *birls_ids_tried.keys)
-        subject.save
-        subject.reload
-        expect(subject.birls_ids_tried_hash.keys).to contain_exactly(birls_id, *birls_ids_tried.keys)
+        it 'does not include birls ids that have already been tried' do
+          expect(subject.birls_ids_that_havent_been_tried_yet).to contain_exactly('a', 'b', 'd')
+        end
       end
-    end
-  end
 
-  describe '#birls_ids_that_havent_been_tried_yet' do
-    subject do
-      headers = JSON.parse auth_headers.to_json
-      headers['va_eauth_birlsfilenumber'] = birls_id
-      Form526Submission.new(
-        user_uuid: user.uuid,
-        saved_claim_id: saved_claim.id,
-        auth_headers_json: headers.to_json,
-        form_json:,
-        birls_ids_tried: birls_ids_tried.to_json
-      )
-    end
-
-    let(:birls_id) { 'a' }
-    let(:birls_ids_tried) { { b: [], c: ['2021-02-01T14:28:33Z'], d: nil } }
-
-    it 'does not include birls ids that have already been tried' do
-      expect(subject.birls_ids_that_havent_been_tried_yet).to contain_exactly('a', 'b', 'd')
-    end
-  end
+      describe '#birls_id!' do
+        it 'returns the BIRLS ID' do
+          expect(subject.birls_id!).to eq(auth_headers[described_class::BIRLS_KEY])
+        end
 
-  describe '#birls_id!' do
-    it 'returns the BIRLS ID' do
-      expect(subject.birls_id!).to eq(auth_headers[described_class::BIRLS_KEY])
-    end
+        context 'auth_headers is nil' do
+          it 'throws an exception' do
+            subject.auth_headers_json = nil
+            expect { subject.birls_id! }.to raise_error TypeError
+          end
+        end
 
-    context 'auth_headers is nil' do
-      it 'throws an exception' do
-        subject.auth_headers_json = nil
-        expect { subject.birls_id! }.to raise_error TypeError
+        context 'auth_headers is unparseable' do
+          it 'throws an exception' do
+            subject.auth_headers_json = 'hi!'
+            expect { subject.birls_id! }.to raise_error JSON::ParserError
+          end
+        end
       end
-    end
 
-    context 'auth_headers is unparseable' do
-      it 'throws an exception' do
-        subject.auth_headers_json = 'hi!'
-        expect { subject.birls_id! }.to raise_error JSON::ParserError
-      end
-    end
-  end
+      describe '#birls_id' do
+        it 'returns the BIRLS ID' do
+          expect(subject.birls_id).to eq(auth_headers[described_class::BIRLS_KEY])
+        end
 
-  describe '#birls_id' do
-    it 'returns the BIRLS ID' do
-      expect(subject.birls_id).to eq(auth_headers[described_class::BIRLS_KEY])
-    end
+        context 'auth_headers is nil' do
+          it 'returns nil' do
+            subject.auth_headers_json = nil
+            expect(subject.birls_id).to be_nil
+          end
+        end
 
-    context 'auth_headers is nil' do
-      it 'returns nil' do
-        subject.auth_headers_json = nil
-        expect(subject.birls_id).to be_nil
+        context 'auth_headers is unparseable' do
+          it 'throws an exception' do
+            subject.auth_headers_json = 'hi!'
+            expect { subject.birls_id }.to raise_error JSON::ParserError
+          end
+        end
       end
-    end
 
-    context 'auth_headers is unparseable' do
-      it 'throws an exception' do
-        subject.auth_headers_json = 'hi!'
-        expect { subject.birls_id }.to raise_error JSON::ParserError
-      end
-    end
-  end
+      describe '#birls_id=' do
+        let(:birls_id) { 1 }
 
-  describe '#birls_id=' do
-    let(:birls_id) { 1 }
+        it 'sets the BIRLS ID' do
+          subject.birls_id = birls_id
+          expect(subject.birls_id).to eq(birls_id)
+        end
 
-    it 'sets the BIRLS ID' do
-      subject.birls_id = birls_id
-      expect(subject.birls_id).to eq(birls_id)
-    end
+        context 'auth_headers is nil' do
+          it 'throws an exception' do
+            subject.auth_headers_json = nil
+            expect { subject.birls_id = birls_id }.to raise_error TypeError
+          end
+        end
 
-    context 'auth_headers is nil' do
-      it 'throws an exception' do
-        subject.auth_headers_json = nil
-        expect { subject.birls_id = birls_id }.to raise_error TypeError
+        context 'auth_headers is unparseable' do
+          it 'throws an exception' do
+            subject.auth_headers_json = 'hi!'
+            expect { subject.birls_id = birls_id }.to raise_error JSON::ParserError
+          end
+        end
       end
-    end
 
-    context 'auth_headers is unparseable' do
-      it 'throws an exception' do
-        subject.auth_headers_json = 'hi!'
-        expect { subject.birls_id = birls_id }.to raise_error JSON::ParserError
-      end
-    end
-  end
+      describe '#perform_ancillary_jobs_handler' do
+        let(:status) { OpenStruct.new(parent_bid: SecureRandom.hex(8)) }
 
-  describe '#perform_ancillary_jobs_handler' do
-    let(:status) { OpenStruct.new(parent_bid: SecureRandom.hex(8)) }
+        context 'with an ancillary job' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_uploads.json')
+          end
 
-    context 'with an ancillary job' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_uploads.json')
-      end
+          it 'queues 3 jobs' do
+            subject.form526_job_statuses <<
+              Form526JobStatus.new(job_class: 'SubmitForm526AllClaim', status: 'success', job_id: 0)
+            expect do
+              subject.perform_ancillary_jobs_handler(status, 'submission_id' => subject.id)
+            end.to change(EVSS::DisabilityCompensationForm::SubmitUploads.jobs, :size).by(3)
+          end
 
-      it 'queues 3 jobs' do
-        subject.form526_job_statuses <<
-          Form526JobStatus.new(job_class: 'SubmitForm526AllClaim', status: 'success', job_id: 0)
-        expect do
-          subject.perform_ancillary_jobs_handler(status, 'submission_id' => subject.id)
-        end.to change(EVSS::DisabilityCompensationForm::SubmitUploads.jobs, :size).by(3)
-      end
+          it 'warns when there are multiple successful submit526 jobs' do
+            2.times do |index|
+              subject.form526_job_statuses << Form526JobStatus.new(
+                job_class: 'SubmitForm526AllClaim',
+                status: Form526JobStatus::STATUS[:success],
+                job_id: index
+              )
+            end
+            expect(Form526JobStatus.all.count).to eq 2
+            expect_any_instance_of(Form526Submission).to receive(:log_message_to_sentry).with(
+              'There are multiple successful SubmitForm526 job statuses',
+              :warn,
+              { form_526_submission_id: subject.id }
+            )
+            subject.perform_ancillary_jobs_handler(status, 'submission_id' => subject.id)
+          end
 
-      it 'warns when there are multiple successful submit526 jobs' do
-        2.times do |index|
-          subject.form526_job_statuses << Form526JobStatus.new(
-            job_class: 'SubmitForm526AllClaim',
-            status: Form526JobStatus::STATUS[:success],
-            job_id: index
-          )
+          it "warns when there's a successful submit526 job, but it's not the most recent submit526 job" do
+            %i[success retryable_error].each_with_index do |status, index|
+              subject.form526_job_statuses << Form526JobStatus.new(
+                job_class: 'SubmitForm526AllClaim',
+                status: Form526JobStatus::STATUS[status],
+                job_id: index,
+                updated_at: Time.zone.now + index.days
+              )
+            end
+            expect(Form526JobStatus.all.count).to eq 2
+            expect_any_instance_of(Form526Submission).to receive(:log_message_to_sentry).with(
+              "There is a successful SubmitForm526 job, but it's not the most recent SubmitForm526 job",
+              :warn,
+              { form_526_submission_id: subject.id }
+            )
+            subject.perform_ancillary_jobs_handler(status, 'submission_id' => subject.id)
+          end
         end
-        expect(Form526JobStatus.all.count).to eq 2
-        expect_any_instance_of(Form526Submission).to receive(:log_message_to_sentry).with(
-          'There are multiple successful SubmitForm526 job statuses',
-          :warn,
-          { form_526_submission_id: subject.id }
-        )
-        subject.perform_ancillary_jobs_handler(status, 'submission_id' => subject.id)
       end
 
-      it "warns when there's a successful submit526 job, but it's not the most recent submit526 job" do
-        %i[success retryable_error].each_with_index do |status, index|
-          subject.form526_job_statuses << Form526JobStatus.new(
-            job_class: 'SubmitForm526AllClaim',
-            status: Form526JobStatus::STATUS[status],
-            job_id: index,
-            updated_at: Time.zone.now + index.days
-          )
-        end
-        expect(Form526JobStatus.all.count).to eq 2
-        expect_any_instance_of(Form526Submission).to receive(:log_message_to_sentry).with(
-          "There is a successful SubmitForm526 job, but it's not the most recent SubmitForm526 job",
-          :warn,
-          { form_526_submission_id: subject.id }
-        )
-        subject.perform_ancillary_jobs_handler(status, 'submission_id' => subject.id)
-      end
-    end
-  end
+      describe '#perform_ancillary_jobs' do
+        let(:first_name) { 'firstname' }
 
-  describe '#perform_ancillary_jobs' do
-    let(:first_name) { 'firstname' }
+        context 'with (3) uploads' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_uploads.json')
+          end
 
-    context 'with (3) uploads' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_uploads.json')
-      end
+          it 'queues 3 upload jobs' do
+            expect do
+              subject.perform_ancillary_jobs(first_name)
+            end.to change(EVSS::DisabilityCompensationForm::SubmitUploads.jobs, :size).by(3)
+          end
+        end
 
-      it 'queues 3 upload jobs' do
-        expect do
-          subject.perform_ancillary_jobs(first_name)
-        end.to change(EVSS::DisabilityCompensationForm::SubmitUploads.jobs, :size).by(3)
-      end
-    end
+        context 'with flashes' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_uploads.json')
+          end
 
-    context 'with flashes' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_uploads.json')
-      end
+          context 'when feature enabled' do
+            before { Flipper.enable(:disability_compensation_flashes) }
+
+            it 'queues flashes job' do
+              expect do
+                subject.perform_ancillary_jobs(first_name)
+              end.to change(BGS::FlashUpdater.jobs, :size).by(1)
+            end
+          end
 
-      context 'when feature enabled' do
-        before { Flipper.enable(:disability_compensation_flashes) }
+          context 'when feature disabled' do
+            before { Flipper.disable(:disability_compensation_flashes) }
 
-        it 'queues flashes job' do
-          expect do
-            subject.perform_ancillary_jobs(first_name)
-          end.to change(BGS::FlashUpdater.jobs, :size).by(1)
+            it 'queues flashes job' do
+              expect do
+                subject.perform_ancillary_jobs(first_name)
+              end.to change(BGS::FlashUpdater.jobs, :size).by(0)
+            end
+          end
         end
-      end
 
-      context 'when feature disabled' do
-        before { Flipper.disable(:disability_compensation_flashes) }
+        context 'BDD' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/526_bdd.json')
+          end
 
-        it 'queues flashes job' do
-          expect do
-            subject.perform_ancillary_jobs(first_name)
-          end.to change(BGS::FlashUpdater.jobs, :size).by(0)
+          it 'queues 1 UploadBddInstructions job' do
+            expect do
+              subject.perform_ancillary_jobs(first_name)
+            end.to change(EVSS::DisabilityCompensationForm::UploadBddInstructions.jobs, :size).by(1)
+          end
         end
-      end
-    end
 
-    context 'BDD' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/526_bdd.json')
-      end
+        context 'with form 4142' do
+          before do
+            allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(false)
+            allow(Flipper).to receive(:enabled?).with(:disability_compensation_production_tester).and_return(false)
+            allow(Flipper).to receive(:enabled?).with(:disability_526_toxic_exposure_document_upload_polling,
+                                                      anything).and_return(false)
+            allow(Flipper).to receive(:enabled?).with(:disability_compensation_production_tester,
+                                                      anything).and_return(false)
+          end
 
-      it 'queues 1 UploadBddInstructions job' do
-        expect do
-          subject.perform_ancillary_jobs(first_name)
-        end.to change(EVSS::DisabilityCompensationForm::UploadBddInstructions.jobs, :size).by(1)
-      end
-    end
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_4142.json')
+          end
 
-    context 'with form 4142' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_4142.json')
-      end
+          it 'queues a 4142 job' do
+            expect do
+              subject.perform_ancillary_jobs(first_name)
+            end.to change(CentralMail::SubmitForm4142Job.jobs, :size).by(1)
+          end
+        end
 
-      it 'queues a 4142 job' do
-        expect do
-          subject.perform_ancillary_jobs(first_name)
-        end.to change(CentralMail::SubmitForm4142Job.jobs, :size).by(1)
-      end
-    end
+        context 'with form 0781' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_0781.json')
+          end
 
-    context 'with form 0781' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_0781.json')
-      end
+          it 'queues a 0781 job' do
+            expect do
+              subject.perform_ancillary_jobs(first_name)
+            end.to change(EVSS::DisabilityCompensationForm::SubmitForm0781.jobs, :size).by(1)
+          end
+        end
 
-      it 'queues a 0781 job' do
-        expect do
-          subject.perform_ancillary_jobs(first_name)
-        end.to change(EVSS::DisabilityCompensationForm::SubmitForm0781.jobs, :size).by(1)
-      end
-    end
+        context 'with form 8940' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_8940.json')
+          end
 
-    context 'with form 8940' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_8940.json')
-      end
+          it 'queues a 8940 job' do
+            expect do
+              subject.perform_ancillary_jobs(first_name)
+            end.to change(EVSS::DisabilityCompensationForm::SubmitForm8940.jobs, :size).by(1)
+          end
+        end
 
-      it 'queues a 8940 job' do
-        expect do
-          subject.perform_ancillary_jobs(first_name)
-        end.to change(EVSS::DisabilityCompensationForm::SubmitForm8940.jobs, :size).by(1)
-      end
-    end
+        context 'with Lighthouse document upload polling' do
+          let(:form_json) do
+            File.read('spec/support/disability_compensation_form/submissions/with_uploads.json')
+          end
 
-    context 'with Lighthouse document upload polling' do
-      let(:form_json) do
-        File.read('spec/support/disability_compensation_form/submissions/with_uploads.json')
-      end
+          context 'when feature enabled' do
+            before { Flipper.enable(:disability_526_toxic_exposure_document_upload_polling) }
+
+            it 'queues polling job' do
+              expect do
+                form = subject.saved_claim.parsed_form
+                form['startedFormVersion'] = '2022'
+                subject.update(submitted_claim_id: 1)
+                subject.saved_claim.update(form: form.to_json)
+                subject.perform_ancillary_jobs(first_name)
+              end.to change(Lighthouse::PollForm526Pdf.jobs, :size).by(1)
+            end
+          end
 
-      context 'when feature enabled' do
-        before { Flipper.enable(:disability_526_toxic_exposure_document_upload_polling) }
+          context 'when feature disabled' do
+            before { Flipper.disable(:disability_526_toxic_exposure_document_upload_polling) }
 
-        it 'queues polling job' do
-          expect do
-            form = subject.saved_claim.parsed_form
-            form['startedFormVersion'] = '2022'
-            subject.update(submitted_claim_id: 1)
-            subject.saved_claim.update(form: form.to_json)
-            subject.perform_ancillary_jobs(first_name)
-          end.to change(Lighthouse::PollForm526Pdf.jobs, :size).by(1)
+            it 'does not queue polling job' do
+              expect do
+                subject.perform_ancillary_jobs(first_name)
+              end.to change(Lighthouse::PollForm526Pdf.jobs, :size).by(0)
+            end
+          end
         end
       end
 
-      context 'when feature disabled' do
-        before { Flipper.disable(:disability_526_toxic_exposure_document_upload_polling) }
-
-        it 'does not queue polling job' do
-          expect do
-            subject.perform_ancillary_jobs(first_name)
-          end.to change(Lighthouse::PollForm526Pdf.jobs, :size).by(0)
+      describe '#get_first_name' do
+        [
+          {
+            input: 'Joe',
+            expected: 'JOE'
+          },
+          {
+            input: 'JOE',
+            expected: 'JOE'
+          }, {
+            input: 'joe mark',
+            expected: 'JOE MARK'
+          }
+        ].each do |test_param|
+          it 'gets correct first name' do
+            allow(User).to receive(:find).with(anything).and_return(user)
+            allow_any_instance_of(User).to receive(:first_name).and_return(test_param[:input])
+
+            expect(subject.get_first_name).to eql(test_param[:expected])
+          end
         end
-      end
-    end
-  end
 
-  describe '#get_first_name' do
-    [
-      {
-        input: 'Joe',
-        expected: 'JOE'
-      },
-      {
-        input: 'JOE',
-        expected: 'JOE'
-      }, {
-        input: 'joe mark',
-        expected: 'JOE MARK'
-      }
-    ].each do |test_param|
-      it 'gets correct first name' do
-        allow(User).to receive(:find).with(anything).and_return(user)
-        allow_any_instance_of(User).to receive(:first_name).and_return(test_param[:input])
-
-        expect(subject.get_first_name).to eql(test_param[:expected])
-      end
-    end
+        context 'when the first name is NOT populated on the User' do
+          before do
+            # Ensure `subject` is called before stubbing `first_name` so that the auth headers are populated correctly
+            subject
+            user_with_nil_first_name = User.create(user)
+            allow(user_with_nil_first_name).to receive(:first_name).and_return nil
+            allow(User).to receive(:find).with(subject.user_uuid).and_return user_with_nil_first_name
+          end
 
-    context 'when the first name is NOT populated on the User' do
-      before do
-        # Ensure `subject` is called before stubbing `first_name` so that the auth headers are populated correctly
-        subject
-        user_with_nil_first_name = User.create(user)
-        allow(user_with_nil_first_name).to receive(:first_name).and_return nil
-        allow(User).to receive(:find).with(subject.user_uuid).and_return user_with_nil_first_name
-      end
+          context 'when name attributes exist in the auth headers' do
+            it 'returns the first name of the user from the auth headers' do
+              expect(subject.get_first_name).to eql('BEYONCE')
+            end
+          end
+
+          context 'when name attributes do NOT exist in the auth headers' do
+            subject { build(:form526_submission, :with_empty_auth_headers) }
 
-      context 'when name attributes exist in the auth headers' do
-        it 'returns the first name of the user from the auth headers' do
-          expect(subject.get_first_name).to eql('BEYONCE')
+            it 'returns nil' do
+              expect(subject.get_first_name).to be nil
+            end
+          end
         end
-      end
 
-      context 'when name attributes do NOT exist in the auth headers' do
-        subject { build(:form526_submission, :with_empty_auth_headers) }
+        context 'when the User is NOT found' do
+          before { allow(User).to receive(:find).and_return nil }
 
-        it 'returns nil' do
-          expect(subject.get_first_name).to be nil
+          it 'returns the first name of the user from the auth headers' do
+            expect(subject.get_first_name).to eql('BEYONCE')
+          end
         end
       end
-    end
 
-    context 'when the User is NOT found' do
-      before { allow(User).to receive(:find).and_return nil }
+      describe '#full_name' do
+        let(:full_name_hash) do
+          {
+            first: 'Beyonce',
+            middle: nil,
+            last: 'Knowles',
+            suffix: user.normalized_suffix
+          }
+        end
 
-      it 'returns the first name of the user from the auth headers' do
-        expect(subject.get_first_name).to eql('BEYONCE')
-      end
-    end
-  end
+        context 'when the full name exists on the User' do
+          it 'returns the full name of the user' do
+            expect(subject.full_name).to eql(full_name_hash)
+          end
+        end
 
-  describe '#full_name' do
-    let(:full_name_hash) do
-      {
-        first: 'Beyonce',
-        middle: nil,
-        last: 'Knowles',
-        suffix: user.normalized_suffix
-      }
-    end
+        context 'when the full name is NOT populated on the User but name attributes exist in the auth_headers' do
+          let(:nil_full_name_hash) do
+            {
+              first: nil,
+              middle: nil,
+              last: nil,
+              suffix: nil
+            }
+          end
 
-    context 'when the full name exists on the User' do
-      it 'returns the full name of the user' do
-        expect(subject.full_name).to eql(full_name_hash)
-      end
-    end
+          before do
+            allow_any_instance_of(User).to receive(:full_name_normalized).and_return nil_full_name_hash
+          end
 
-    context 'when the full name is NOT populated on the User but name attributes exist in the auth_headers' do
-      let(:nil_full_name_hash) do
-        {
-          first: nil,
-          middle: nil,
-          last: nil,
-          suffix: nil
-        }
-      end
+          context 'when name attributes exist in the auth headers' do
+            it 'returns the first and last name of the user from the auth headers' do
+              expect(subject.full_name).to eql(full_name_hash.merge(middle: nil, suffix: nil))
+            end
+          end
 
-      before do
-        allow_any_instance_of(User).to receive(:full_name_normalized).and_return nil_full_name_hash
-      end
+          context 'when name attributes do NOT exist in the auth headers' do
+            subject { build(:form526_submission, :with_empty_auth_headers) }
 
-      context 'when name attributes exist in the auth headers' do
-        it 'returns the first and last name of the user from the auth headers' do
-          expect(subject.full_name).to eql(full_name_hash.merge(middle: nil, suffix: nil))
+            it 'returns the hash with all nil values' do
+              expect(subject.full_name).to eql nil_full_name_hash
+            end
+          end
         end
-      end
 
-      context 'when name attributes do NOT exist in the auth headers' do
-        subject { build(:form526_submission, :with_empty_auth_headers) }
+        context 'when the User is NOT found' do
+          before { allow(User).to receive(:find).and_return nil }
 
-        it 'returns the hash with all nil values' do
-          expect(subject.full_name).to eql nil_full_name_hash
+          it 'returns the first and last name of the user from the auth headers' do
+            expect(subject.full_name).to eql(full_name_hash.merge(middle: nil, suffix: nil))
+          end
         end
       end
-    end
-
-    context 'when the User is NOT found' do
-      before { allow(User).to receive(:find).and_return nil }
 
-      it 'returns the first and last name of the user from the auth headers' do
-        expect(subject.full_name).to eql(full_name_hash.merge(middle: nil, suffix: nil))
-      end
-    end
-  end
+      describe '#workflow_complete_handler' do
+        describe 'success' do
+          let(:options) do
+            {
+              'submission_id' => subject.id,
+              'first_name' => 'firstname'
+            }
+          end
 
-  describe '#workflow_complete_handler' do
-    describe 'success' do
-      let(:options) do
-        {
-          'submission_id' => subject.id,
-          'first_name' => 'firstname'
-        }
-      end
+          context 'with a single successful job' do
+            subject { create(:form526_submission, :with_one_succesful_job) }
 
-      context 'with a single successful job' do
-        subject { create(:form526_submission, :with_one_succesful_job) }
+            it 'sets the submission.complete to true' do
+              expect(subject.workflow_complete).to be_falsey
+              subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
+              subject.reload
+              expect(subject.workflow_complete).to be_truthy
+            end
+          end
 
-        it 'sets the submission.complete to true' do
-          expect(subject.workflow_complete).to be_falsey
-          subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
-          subject.reload
-          expect(subject.workflow_complete).to be_truthy
-        end
-      end
+          context 'with multiple successful jobs' do
+            subject { create(:form526_submission, :with_multiple_succesful_jobs) }
 
-      context 'with multiple successful jobs' do
-        subject { create(:form526_submission, :with_multiple_succesful_jobs) }
+            it 'sets the submission.complete to true' do
+              expect(subject.workflow_complete).to be_falsey
+              subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
+              subject.reload
+              expect(subject.workflow_complete).to be_truthy
+            end
+          end
 
-        it 'sets the submission.complete to true' do
-          expect(subject.workflow_complete).to be_falsey
-          subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
-          subject.reload
-          expect(subject.workflow_complete).to be_truthy
-        end
-      end
+          context 'with multiple successful jobs and email and submitted time in PM' do
+            subject { create(:form526_submission, :with_multiple_succesful_jobs, submitted_claim_id: 123_654_879) }
 
-      context 'with multiple successful jobs and email and submitted time in PM' do
-        subject { create(:form526_submission, :with_multiple_succesful_jobs, submitted_claim_id: 123_654_879) }
+            before { Timecop.freeze(Time.zone.parse('2012-07-20 14:15:00 UTC')) }
 
-        before { Timecop.freeze(Time.zone.parse('2012-07-20 14:15:00 UTC')) }
+            after { Timecop.return }
 
-        after { Timecop.return }
+            it 'calls confirmation email job with correct personalization' do
+              allow(Form526ConfirmationEmailJob).to receive(:perform_async) do |*args|
+                expect(args[0]['first_name']).to eql('firstname')
+                expect(args[0]['submitted_claim_id']).to be(123_654_879)
+                expect(args[0]['email']).to eql('test@email.com')
+                expect(args[0]['date_submitted']).to eql('July 20, 2012 2:15 p.m. UTC')
+              end
 
-        it 'calls confirmation email job with correct personalization' do
-          allow(Form526ConfirmationEmailJob).to receive(:perform_async) do |*args|
-            expect(args[0]['first_name']).to eql('firstname')
-            expect(args[0]['submitted_claim_id']).to be(123_654_879)
-            expect(args[0]['email']).to eql('test@email.com')
-            expect(args[0]['date_submitted']).to eql('July 20, 2012 2:15 p.m. UTC')
+              subject.workflow_complete_handler(nil, options)
+            end
           end
 
-          subject.workflow_complete_handler(nil, options)
-        end
-      end
+          context 'with multiple successful jobs and email and submitted time in PM with two digit hour' do
+            subject { create(:form526_submission, :with_multiple_succesful_jobs, submitted_claim_id: 123_654_879) }
 
-      context 'with multiple successful jobs and email and submitted time in PM with two digit hour' do
-        subject { create(:form526_submission, :with_multiple_succesful_jobs, submitted_claim_id: 123_654_879) }
+            before { Timecop.freeze(Time.zone.parse('2012-07-20 11:12:00 UTC')) }
 
-        before { Timecop.freeze(Time.zone.parse('2012-07-20 11:12:00 UTC')) }
+            after { Timecop.return }
 
-        after { Timecop.return }
+            it 'calls confirmation email job with correct personalization' do
+              allow(Form526ConfirmationEmailJob).to receive(:perform_async) do |*args|
+                expect(args[0]['first_name']).to eql('firstname')
+                expect(args[0]['submitted_claim_id']).to be(123_654_879)
+                expect(args[0]['email']).to eql('test@email.com')
+                expect(args[0]['date_submitted']).to eql('July 20, 2012 11:12 a.m. UTC')
+              end
 
-        it 'calls confirmation email job with correct personalization' do
-          allow(Form526ConfirmationEmailJob).to receive(:perform_async) do |*args|
-            expect(args[0]['first_name']).to eql('firstname')
-            expect(args[0]['submitted_claim_id']).to be(123_654_879)
-            expect(args[0]['email']).to eql('test@email.com')
-            expect(args[0]['date_submitted']).to eql('July 20, 2012 11:12 a.m. UTC')
+              subject.workflow_complete_handler(nil, options)
+            end
           end
 
-          subject.workflow_complete_handler(nil, options)
-        end
-      end
+          context 'with multiple successful jobs and email and submitted time in morning' do
+            subject { create(:form526_submission, :with_multiple_succesful_jobs, submitted_claim_id: 123_654_879) }
 
-      context 'with multiple successful jobs and email and submitted time in morning' do
-        subject { create(:form526_submission, :with_multiple_succesful_jobs, submitted_claim_id: 123_654_879) }
+            before { Timecop.freeze(Time.zone.parse('2012-07-20 8:07:00 UTC')) }
 
-        before { Timecop.freeze(Time.zone.parse('2012-07-20 8:07:00 UTC')) }
+            after { Timecop.return }
 
-        after { Timecop.return }
+            it 'calls confirmation email job with correct personalization' do
+              allow(Form526ConfirmationEmailJob).to receive(:perform_async) do |*args|
+                expect(args[0]['first_name']).to eql('firstname')
+                expect(args[0]['submitted_claim_id']).to be(123_654_879)
+                expect(args[0]['email']).to eql('test@email.com')
+                expect(args[0]['date_submitted']).to eql('July 20, 2012 8:07 a.m. UTC')
+              end
 
-        it 'calls confirmation email job with correct personalization' do
-          allow(Form526ConfirmationEmailJob).to receive(:perform_async) do |*args|
-            expect(args[0]['first_name']).to eql('firstname')
-            expect(args[0]['submitted_claim_id']).to be(123_654_879)
-            expect(args[0]['email']).to eql('test@email.com')
-            expect(args[0]['date_submitted']).to eql('July 20, 2012 8:07 a.m. UTC')
+              subject.workflow_complete_handler(nil, options)
+            end
           end
 
-          subject.workflow_complete_handler(nil, options)
+          context 'with submission confirmation email when successful job statuses' do
+            subject { create(:form526_submission, :with_multiple_succesful_jobs) }
+
+            it 'does not trigger job when disability_526_call_received_email_from_polling enabled' do
+              Flipper.enable(:disability_526_call_received_email_from_polling)
+              expect do
+                subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
+              end.to change(Form526ConfirmationEmailJob.jobs, :size).by(0)
+            end
+
+            it 'returns one job triggered when disability_526_call_received_email_from_polling disabled' do
+              Flipper.disable(:disability_526_call_received_email_from_polling)
+              expect do
+                subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
+              end.to change(Form526ConfirmationEmailJob.jobs, :size).by(1)
+            end
+          end
         end
-      end
 
-      context 'with submission confirmation email when successful job statuses' do
-        subject { create(:form526_submission, :with_multiple_succesful_jobs) }
+        describe 'failure' do
+          context 'with mixed result jobs' do
+            subject { create(:form526_submission, :with_mixed_status) }
 
-        it 'does not trigger job when disability_526_call_received_email_from_polling enabled' do
-          allow(Flipper).to receive(:enabled?).with(:disability_526_call_received_email_from_polling,
-                                                    anything).and_return(true)
-          expect do
-            subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
-          end.to change(Form526ConfirmationEmailJob.jobs, :size).by(0)
-        end
+            it 'sets the submission.complete to true' do
+              expect(subject.workflow_complete).to be_falsey
+              subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
+              subject.reload
+              expect(subject.workflow_complete).to be_falsey
+            end
+          end
 
-        it 'returns one job triggered when disability_526_call_received_email_from_polling disabled' do
-          allow(Flipper).to receive(:enabled?).with(:disability_526_call_received_email_from_polling,
-                                                    anything).and_return(false)
-          expect do
-            subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
-          end.to change(Form526ConfirmationEmailJob.jobs, :size).by(1)
-        end
-      end
-    end
+          context 'with a failing 526 form job' do
+            subject { create(:form526_submission, :with_one_failed_job) }
 
-    describe 'failure' do
-      context 'with mixed result jobs' do
-        subject { create(:form526_submission, :with_mixed_status) }
+            it 'sets the submission.complete to true' do
+              expect(subject.workflow_complete).to be_falsey
+              subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
+              subject.reload
+              expect(subject.workflow_complete).to be_falsey
+            end
+          end
 
-        it 'sets the submission.complete to true' do
-          expect(subject.workflow_complete).to be_falsey
-          subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
-          subject.reload
-          expect(subject.workflow_complete).to be_falsey
-        end
-      end
+          context 'with submission confirmation email when failed job statuses' do
+            subject { create(:form526_submission, :with_mixed_status) }
 
-      context 'with a failing 526 form job' do
-        subject { create(:form526_submission, :with_one_failed_job) }
+            it 'returns zero jobs triggered' do
+              expect do
+                subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
+              end.to change(Form526ConfirmationEmailJob.jobs, :size).by(0)
+            end
+          end
 
-        it 'sets the submission.complete to true' do
-          expect(subject.workflow_complete).to be_falsey
-          subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
-          subject.reload
-          expect(subject.workflow_complete).to be_falsey
+          it 'sends a submission failed email notification' do
+            expect do
+              subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
+            end.to change(Form526SubmissionFailedEmailJob.jobs, :size).by(1)
+          end
         end
       end
 
-      context 'with submission confirmation email when failed job statuses' do
-        subject { create(:form526_submission, :with_mixed_status) }
+      describe '#disabilities_not_service_connected?' do
+        subject { form_526_submission.disabilities_not_service_connected? }
+
+        before { create(:idme_user_verification, idme_uuid: user.idme_uuid, user_account:) }
 
-        it 'returns zero jobs triggered' do
-          expect do
-            subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
-          end.to change(Form526ConfirmationEmailJob.jobs, :size).by(0)
+        let(:form_526_submission) do
+          Form526Submission.create(
+            user_uuid: user.uuid,
+            user_account: user.user_account,
+            saved_claim_id: saved_claim.id,
+            auth_headers_json: auth_headers.to_json,
+            form_json: File.read("spec/support/disability_compensation_form/submissions/#{form_json_filename}")
+          )
         end
-      end
 
-      it 'sends a submission failed email notification' do
-        expect do
-          subject.workflow_complete_handler(nil, 'submission_id' => subject.id)
-        end.to change(Form526SubmissionFailedEmailJob.jobs, :size).by(1)
-      end
-    end
-  end
+        context 'evss provider' do
+          before do
+            VCR.insert_cassette('evss/disability_compensation_form/rated_disabilities_with_non_service_connected')
+          end
 
-  describe '#disabilities_not_service_connected?' do
-    subject { form_526_submission.disabilities_not_service_connected? }
+          after do
+            VCR.eject_cassette('evss/disability_compensation_form/rated_disabilities_with_non_service_connected')
+          end
 
-    before { create(:idme_user_verification, idme_uuid: user.idme_uuid, user_account:) }
+          context 'when all corresponding rated disabilities are not service-connected' do
+            let(:form_json_filename) { 'only_526_asthma.json' }
 
-    let(:form_526_submission) do
-      Form526Submission.create(
-        user_uuid: user.uuid,
-        user_account: user.user_account,
-        saved_claim_id: saved_claim.id,
-        auth_headers_json: auth_headers.to_json,
-        form_json: File.read("spec/support/disability_compensation_form/submissions/#{form_json_filename}")
-      )
-    end
+            it 'returns true' do
+              Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
+              expect(subject).to be_truthy
+            end
+          end
+
+          context 'when some but not all corresponding rated disabilities are not service-connected' do
+            let(:form_json_filename) { 'only_526_two_rated_disabilities.json' }
 
-    context 'evss provider' do
-      before { VCR.insert_cassette('evss/disability_compensation_form/rated_disabilities_with_non_service_connected') }
-      after { VCR.eject_cassette('evss/disability_compensation_form/rated_disabilities_with_non_service_connected') }
+            it 'returns false' do
+              Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
+              expect(subject).to be_falsey
+            end
+          end
 
-      context 'when all corresponding rated disabilities are not service-connected' do
-        Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
-        let(:form_json_filename) { 'only_526_asthma.json' }
+          context 'when some disabilities do not have a ratedDisabilityId yet' do
+            let(:form_json_filename) { 'only_526_mixed_action_disabilities.json' }
 
-        it 'returns true' do
-          expect(subject).to be_truthy
+            it 'returns false' do
+              Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
+              expect(subject).to be_falsey
+            end
+          end
         end
-      end
 
-      context 'when some but not all corresponding rated disabilities are not service-connected' do
-        Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
-        let(:form_json_filename) { 'only_526_two_rated_disabilities.json' }
+        context 'Lighthouse provider' do
+          before do
+            Flipper.enable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
+            VCR.insert_cassette('lighthouse/veteran_verification/disability_rating/200_Not_Connected_response')
+            allow_any_instance_of(Auth::ClientCredentials::Service).to receive(:get_token).and_return('blahblech')
+          end
 
-        it 'returns false' do
-          expect(subject).to be_falsey
-        end
-      end
+          after do
+            Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
+            VCR.eject_cassette('lighthouse/veteran_verification/disability_rating/200_Not_Connected_response')
+          end
 
-      context 'when some disabilities do not have a ratedDisabilityId yet' do
-        Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
-        let(:form_json_filename) { 'only_526_mixed_action_disabilities.json' }
+          context 'when all corresponding rated disabilities are not service-connected' do
+            let(:form_json_filename) { 'only_526_asthma.json' }
 
-        it 'returns false' do
-          expect(subject).to be_falsey
-        end
-      end
-    end
+            it 'returns true' do
+              expect(subject).to be_truthy
+            end
+          end
 
-    context 'Lighthouse provider' do
-      before do
-        Flipper.enable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
-        VCR.insert_cassette('lighthouse/veteran_verification/disability_rating/200_Not_Connected_response')
-        allow_any_instance_of(Auth::ClientCredentials::Service).to receive(:get_token).and_return('blahblech')
-      end
+          context 'when some but not all corresponding rated disabilities are not service-connected' do
+            let(:form_json_filename) { 'only_526_two_rated_disabilities.json' }
 
-      after do
-        Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
-        VCR.eject_cassette('lighthouse/veteran_verification/disability_rating/200_Not_Connected_response')
-      end
+            it 'returns false' do
+              expect(subject).to be_falsey
+            end
+          end
 
-      context 'when all corresponding rated disabilities are not service-connected' do
-        let(:form_json_filename) { 'only_526_asthma.json' }
+          context 'when some disabilities do not have a ratedDisabilityId yet' do
+            let(:form_json_filename) { 'only_526_mixed_action_disabilities.json' }
 
-        it 'returns true' do
-          expect(subject).to be_truthy
+            it 'returns false' do
+              expect(subject).to be_falsey
+            end
+          end
         end
       end
 
-      context 'when some but not all corresponding rated disabilities are not service-connected' do
-        let(:form_json_filename) { 'only_526_two_rated_disabilities.json' }
+      describe '#cfi_checkbox_was_selected?' do
+        subject { form_526_submission.cfi_checkbox_was_selected? }
 
-        it 'returns false' do
-          expect(subject).to be_falsey
+        let!(:in_progress_form) { create(:in_progress_526_form, user_uuid: user.uuid) }
+        let(:form_526_submission) do
+          Form526Submission.create(
+            user_uuid: user.uuid,
+            user_account: user.user_account,
+            saved_claim_id: saved_claim.id,
+            auth_headers_json: auth_headers.to_json,
+            form_json: File.read('spec/support/disability_compensation_form/submissions/only_526_tinnitus.json')
+          )
         end
-      end
 
-      context 'when some disabilities do not have a ratedDisabilityId yet' do
-        let(:form_json_filename) { 'only_526_mixed_action_disabilities.json' }
-
-        it 'returns false' do
-          expect(subject).to be_falsey
+        context 'when associated with a default InProgressForm' do
+          it 'returns false' do
+            expect(subject).to be_falsey
+          end
         end
-      end
-    end
-  end
 
-  describe '#cfi_checkbox_was_selected?' do
-    subject { form_526_submission.cfi_checkbox_was_selected? }
-
-    let!(:in_progress_form) { create(:in_progress_526_form, user_uuid: user.uuid) }
-    let(:form_526_submission) do
-      Form526Submission.create(
-        user_uuid: user.uuid,
-        user_account: user.user_account,
-        saved_claim_id: saved_claim.id,
-        auth_headers_json: auth_headers.to_json,
-        form_json: File.read('spec/support/disability_compensation_form/submissions/only_526_tinnitus.json')
-      )
-    end
+        context 'when associated with a InProgressForm that went through CFI being selected' do
+          let(:params) do
+            { form_data: { 'view:claim_type' => { 'view:claiming_increase' => true } } }
+          end
 
-    context 'when associated with a default InProgressForm' do
-      it 'returns false' do
-        expect(subject).to be_falsey
+          it 'returns true' do
+            ClaimFastTracking::MaxCfiMetrics.log_form_update(in_progress_form, params)
+            in_progress_form.update!(params)
+            expect(subject).to be_truthy
+          end
+        end
       end
-    end
 
-    context 'when associated with a InProgressForm that went through CFI being selected' do
-      let(:params) do
-        { form_data: { 'view:claim_type' => { 'view:claiming_increase' => true } } }
-      end
+      describe '#remediated?' do
+        context 'when there are no form526_submission_remediations' do
+          it 'returns false' do
+            expect(subject).not_to be_remediated
+          end
+        end
 
-      it 'returns true' do
-        ClaimFastTracking::MaxCfiMetrics.log_form_update(in_progress_form, params)
-        in_progress_form.update!(params)
-        expect(subject).to be_truthy
-      end
-    end
-  end
+        context 'when there are form526_submission_remediations' do
+          let(:remediation) do
+            FactoryBot.create(:form526_submission_remediation, form526_submission: subject)
+          end
 
-  describe '#remediated?' do
-    context 'when there are no form526_submission_remediations' do
-      it 'returns false' do
-        expect(subject).not_to be_remediated
-      end
-    end
+          it 'returns true if the most recent remediation was successful' do
+            remediation.update(success: true)
+            expect(subject).to be_remediated
+          end
 
-    context 'when there are form526_submission_remediations' do
-      let(:remediation) do
-        FactoryBot.create(:form526_submission_remediation, form526_submission: subject)
+          it 'returns false if the most recent remediation was not successful' do
+            remediation.update(success: false)
+            expect(subject).not_to be_remediated
+          end
+        end
       end
 
-      it 'returns true if the most recent remediation was successful' do
-        remediation.update(success: true)
-        expect(subject).to be_remediated
-      end
+      describe '#duplicate?' do
+        context 'when there are no form526_submission_remediations' do
+          it 'returns false' do
+            expect(subject).not_to be_duplicate
+          end
+        end
 
-      it 'returns false if the most recent remediation was not successful' do
-        remediation.update(success: false)
-        expect(subject).not_to be_remediated
-      end
-    end
-  end
+        context 'when there are form526_submission_remediations' do
+          let(:remediation) do
+            FactoryBot.create(:form526_submission_remediation, form526_submission: subject)
+          end
 
-  describe '#duplicate?' do
-    context 'when there are no form526_submission_remediations' do
-      it 'returns false' do
-        expect(subject).not_to be_duplicate
-      end
-    end
+          it 'returns true if the most recent remediation_type is ignored_as_duplicate' do
+            remediation.update(remediation_type: :ignored_as_duplicate)
+            expect(subject).to be_duplicate
+          end
 
-    context 'when there are form526_submission_remediations' do
-      let(:remediation) do
-        FactoryBot.create(:form526_submission_remediation, form526_submission: subject)
+          it 'returns false if the most recent remediation_type is not ignored_as_duplicate' do
+            remediation.update(remediation_type: :manual)
+            expect(subject).not_to be_duplicate
+          end
+        end
       end
 
-      it 'returns true if the most recent remediation_type is ignored_as_duplicate' do
-        remediation.update(remediation_type: :ignored_as_duplicate)
-        expect(subject).to be_duplicate
-      end
+      describe '#success_type?' do
+        let(:remediation) do
+          FactoryBot.create(:form526_submission_remediation, form526_submission: subject)
+        end
 
-      it 'returns false if the most recent remediation_type is not ignored_as_duplicate' do
-        remediation.update(remediation_type: :manual)
-        expect(subject).not_to be_duplicate
-      end
-    end
-  end
+        context 'when submitted_claim_id is present and backup_submitted_claim_status is nil' do
+          subject { create(:form526_submission, :with_submitted_claim_id) }
 
-  describe '#success_type?' do
-    let(:remediation) do
-      FactoryBot.create(:form526_submission_remediation, form526_submission: subject)
-    end
+          it 'returns true' do
+            expect(subject).to be_success_type
+          end
+        end
 
-    context 'when submitted_claim_id is present and backup_submitted_claim_status is nil' do
-      subject { create(:form526_submission, :with_submitted_claim_id) }
+        context 'when backup_submitted_claim_id is present and backup_submitted_claim_status is accepted' do
+          subject { create(:form526_submission, :backup_path, :backup_accepted) }
 
-      it 'returns true' do
-        expect(subject).to be_success_type
-      end
-    end
+          it 'returns true' do
+            expect(subject).to be_success_type
+          end
+        end
 
-    context 'when backup_submitted_claim_id is present and backup_submitted_claim_status is accepted' do
-      subject { create(:form526_submission, :backup_path, :backup_accepted) }
+        context 'when the most recent remediation is successful' do
+          it 'returns true' do
+            remediation.update(success: true)
+            expect(subject).to be_success_type
+          end
+        end
 
-      it 'returns true' do
-        expect(subject).to be_success_type
+        context 'when none of the success conditions are met' do
+          it 'returns false' do
+            remediation.update(success: false)
+            expect(subject).not_to be_success_type
+          end
+        end
       end
-    end
 
-    context 'when the most recent remediation is successful' do
-      it 'returns true' do
-        remediation.update(success: true)
-        expect(subject).to be_success_type
-      end
-    end
+      describe '#in_process?' do
+        context 'when submitted_claim_id and backup_submitted_claim_status are both nil' do
+          context 'and the record was created within the last 3 days' do
+            it 'returns true' do
+              expect(subject).to be_in_process
+            end
+          end
 
-    context 'when none of the success conditions are met' do
-      it 'returns false' do
-        remediation.update(success: false)
-        expect(subject).not_to be_success_type
-      end
-    end
-  end
+          context 'and the record was created more than 3 weeks ago' do
+            subject { create(:form526_submission, :created_more_than_3_weeks_ago) }
 
-  describe '#in_process?' do
-    context 'when submitted_claim_id and backup_submitted_claim_status are both nil' do
-      context 'and the record was created within the last 3 days' do
-        it 'returns true' do
-          expect(subject).to be_in_process
+            it 'returns false' do
+              expect(subject).not_to be_in_process
+            end
+          end
         end
-      end
 
-      context 'and the record was created more than 3 weeks ago' do
-        subject { create(:form526_submission, :created_more_than_3_weeks_ago) }
+        context 'when submitted_claim_id is not nil' do
+          subject { create(:form526_submission, :with_submitted_claim_id) }
 
-        it 'returns false' do
-          expect(subject).not_to be_in_process
+          it 'returns false' do
+            expect(subject).not_to be_in_process
+          end
         end
-      end
-    end
-
-    context 'when submitted_claim_id is not nil' do
-      subject { create(:form526_submission, :with_submitted_claim_id) }
-
-      it 'returns false' do
-        expect(subject).not_to be_in_process
-      end
-    end
 
-    context 'when backup_submitted_claim_status is not nil' do
-      subject { create(:form526_submission, :backup_path, :backup_accepted) }
+        context 'when backup_submitted_claim_status is not nil' do
+          subject { create(:form526_submission, :backup_path, :backup_accepted) }
 
-      it 'returns false' do
-        expect(subject).not_to be_in_process
+          it 'returns false' do
+            expect(subject).not_to be_in_process
+          end
+        end
       end
-    end
-  end
 
-  describe '#failure_type?' do
-    context 'when the submission is a success type' do
-      subject { create(:form526_submission, :with_submitted_claim_id) }
+      describe '#failure_type?' do
+        context 'when the submission is a success type' do
+          subject { create(:form526_submission, :with_submitted_claim_id) }
 
-      it 'returns true' do
-        expect(subject).not_to be_failure_type
-      end
-    end
+          it 'returns true' do
+            expect(subject).not_to be_failure_type
+          end
+        end
 
-    context 'when the submission is in process' do
-      it 'returns false' do
-        expect(subject).not_to be_failure_type
-      end
-    end
+        context 'when the submission is in process' do
+          it 'returns false' do
+            expect(subject).not_to be_failure_type
+          end
+        end
 
-    context 'when the submission is neither a success type nor in process' do
-      subject { create(:form526_submission, :created_more_than_3_weeks_ago) }
+        context 'when the submission is neither a success type nor in process' do
+          subject { create(:form526_submission, :created_more_than_3_weeks_ago) }
 
-      it 'returns true' do
-        expect(subject).to be_failure_type
+          it 'returns true' do
+            expect(subject).to be_failure_type
+          end
+        end
       end
-    end
-  end
 
-  describe 'ICN retrieval' do
-    context 'various ICN retrieval scenarios' do
-      let(:user) { FactoryBot.create(:user, :loa3) }
-      let(:auth_headers) do
-        EVSS::DisabilityCompensationAuthHeaders.new(user).add_headers(EVSS::AuthHeaders.new(user).to_h)
-      end
-      let(:submission) do
-        create(:form526_submission,
-               user_uuid: user.uuid,
-               auth_headers_json: auth_headers.to_json,
-               saved_claim_id: saved_claim.id)
-      end
-      let!(:form526_submission) { create(:form526_submission) }
+      describe 'ICN retrieval' do
+        context 'various ICN retrieval scenarios' do
+          let(:user) { FactoryBot.create(:user, :loa3) }
+          let(:auth_headers) do
+            EVSS::DisabilityCompensationAuthHeaders.new(user).add_headers(EVSS::AuthHeaders.new(user).to_h)
+          end
+          let(:submission) do
+            create(:form526_submission,
+                   user_uuid: user.uuid,
+                   auth_headers_json: auth_headers.to_json,
+                   saved_claim_id: saved_claim.id)
+          end
+          let!(:form526_submission) { create(:form526_submission) }
 
-      it 'submissions user account has an ICN, as expected' do
-        submission.user_account = UserAccount.new(icn: '123498767V222222')
-        account = submission.account
-        expect(account.icn).to eq('123498767V222222')
-      end
+          it 'submissions user account has an ICN, as expected' do
+            submission.user_account = UserAccount.new(icn: '123498767V222222')
+            account = submission.account
+            expect(account.icn).to eq('123498767V222222')
+          end
 
-      it 'submissions user account has no ICN, default to Account lookup' do
-        submission.user_account = UserAccount.new(icn: nil)
-        account = submission.account
-        expect(account.icn).to eq('123498767V234859')
-      end
+          it 'submissions user account has no ICN, default to Account lookup' do
+            submission.user_account = UserAccount.new(icn: nil)
+            account = submission.account
+            expect(account.icn).to eq('123498767V234859')
+          end
 
-      it 'submission has NO user account, default to Account lookup' do
-        account = submission.account
-        expect(account.icn).to eq('123498767V234859')
-      end
+          it 'submission has NO user account, default to Account lookup' do
+            account = submission.account
+            expect(account.icn).to eq('123498767V234859')
+          end
 
-      it 'submissions user account has no ICN, lookup from past submissions' do
-        user_account_with_icn = UserAccount.create!(icn: '123498767V111111')
-        create(:form526_submission, user_uuid: submission.user_uuid, user_account: user_account_with_icn)
-        submission.user_account = UserAccount.create!(icn: nil)
-        submission.save!
-        account = submission.account
-        expect(account.icn).to eq('123498767V111111')
-      end
+          it 'submissions user account has no ICN, lookup from past submissions' do
+            user_account_with_icn = UserAccount.create!(icn: '123498767V111111')
+            create(:form526_submission, user_uuid: submission.user_uuid, user_account: user_account_with_icn)
+            submission.user_account = UserAccount.create!(icn: nil)
+            submission.save!
+            account = submission.account
+            expect(account.icn).to eq('123498767V111111')
+          end
 
-      it 'lookup ICN from user verifications, idme_uuid defined' do
-        user_account_with_icn = UserAccount.create!(icn: '123498767V333333')
-        UserVerification.create!(idme_uuid: submission.user_uuid, user_account_id: user_account_with_icn.id)
-        submission.user_account = UserAccount.create!(icn: nil)
-        submission.save!
-        account = submission.account
-        expect(account.icn).to eq('123498767V333333')
-      end
+          it 'lookup ICN from user verifications, idme_uuid defined' do
+            user_account_with_icn = UserAccount.create!(icn: '123498767V333333')
+            UserVerification.create!(idme_uuid: submission.user_uuid, user_account_id: user_account_with_icn.id)
+            submission.user_account = UserAccount.create!(icn: nil)
+            submission.save!
+            account = submission.account
+            expect(account.icn).to eq('123498767V333333')
+          end
 
-      it 'lookup ICN from user verifications, backing_idme_uuid defined' do
-        user_account_with_icn = UserAccount.create!(icn: '123498767V444444')
-        UserVerification.create!(dslogon_uuid: Faker::Internet.uuid, backing_idme_uuid: submission.user_uuid,
-                                 user_account_id: user_account_with_icn.id)
-        submission.user_account = UserAccount.create!(icn: nil)
-        submission.save!
-        account = submission.account
-        expect(account.icn).to eq('123498767V444444')
-      end
+          it 'lookup ICN from user verifications, backing_idme_uuid defined' do
+            user_account_with_icn = UserAccount.create!(icn: '123498767V444444')
+            UserVerification.create!(dslogon_uuid: Faker::Internet.uuid, backing_idme_uuid: submission.user_uuid,
+                                     user_account_id: user_account_with_icn.id)
+            submission.user_account = UserAccount.create!(icn: nil)
+            submission.save!
+            account = submission.account
+            expect(account.icn).to eq('123498767V444444')
+          end
 
-      it 'lookup ICN from user verifications, alternate provider id defined' do
-        user_account_with_icn = UserAccount.create!(icn: '123498767V555555')
-        UserVerification.create!(dslogon_uuid: submission.user_uuid, backing_idme_uuid: Faker::Internet.uuid,
-                                 user_account_id: user_account_with_icn.id)
-        submission.user_account = UserAccount.create!(icn: nil)
-        submission.save!
-        account = submission.account
-        expect(account.icn).to eq('123498767V555555')
+          it 'lookup ICN from user verifications, alternate provider id defined' do
+            user_account_with_icn = UserAccount.create!(icn: '123498767V555555')
+            UserVerification.create!(dslogon_uuid: submission.user_uuid, backing_idme_uuid: Faker::Internet.uuid,
+                                     user_account_id: user_account_with_icn.id)
+            submission.user_account = UserAccount.create!(icn: nil)
+            submission.save!
+            account = submission.account
+            expect(account.icn).to eq('123498767V555555')
+          end
+        end
       end
     end
   end
diff --git a/spec/models/saved_claim/education_benefits/va1995_spec.rb b/spec/models/saved_claim/education_benefits/va1995_spec.rb
index e6a93c8fd4c..9afeed17acc 100644
--- a/spec/models/saved_claim/education_benefits/va1995_spec.rb
+++ b/spec/models/saved_claim/education_benefits/va1995_spec.rb
@@ -13,50 +13,64 @@
   describe '#after_submit' do
     let(:user) { create(:user) }
 
-    describe 'sends confirmation email for the 1995' do
-      it 'with benefit selected' do
-        allow(VANotify::EmailJob).to receive(:perform_async)
-
-        subject = create(:va1995_full_form)
-        confirmation_number = subject.education_benefits_claim.confirmation_number
-
-        subject.after_submit(user)
-
-        expect(VANotify::EmailJob).to have_received(:perform_async).with(
-          'test@sample.com',
-          'form1995_confirmation_email_template_id',
-          {
-            'first_name' => 'FIRST',
-            'benefit' => 'Transfer of Entitlement Program (TOE)',
-            'date_submitted' => Time.zone.today.strftime('%B %d, %Y'),
-            'confirmation_number' => confirmation_number,
-            'regional_office_address' => "P.O. Box 4616\nBuffalo, NY 14240-4616"
-          }
-        )
-      end
+    before do
+      allow(Flipper).to receive(:enabled?).with(:form1995_confirmation_email).and_return(true)
+      allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(false)
+    end
+
+    [true, false].each do |flipper_value|
+      context "when json_schemer flipper is #{flipper_value}" do
+        before do
+          allow(Flipper).to receive(:enabled?).and_call_original
+          allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper_value)
+        end
+
+        describe 'sends confirmation email for the 1995' do
+          it 'with benefit selected' do
+            allow(VANotify::EmailJob).to receive(:perform_async)
+
+            subject = create(:va1995_full_form)
+            confirmation_number = subject.education_benefits_claim.confirmation_number
+
+            subject.after_submit(user)
+
+            expect(VANotify::EmailJob).to have_received(:perform_async).with(
+              'test@sample.com',
+              'form1995_confirmation_email_template_id',
+              {
+                'first_name' => 'FIRST',
+                'benefit' => 'Transfer of Entitlement Program (TOE)',
+                'date_submitted' => Time.zone.today.strftime('%B %d, %Y'),
+                'confirmation_number' => confirmation_number,
+                'regional_office_address' => "P.O. Box 4616\nBuffalo, NY 14240-4616"
+              }
+            )
+          end
+
+          it 'without benefit selected' do
+            allow(VANotify::EmailJob).to receive(:perform_async)
+
+            subject = create(:va1995_full_form)
+            parsed_form_data = JSON.parse(subject.form)
+            parsed_form_data.delete('benefit')
+            subject.form = parsed_form_data.to_json
+            confirmation_number = subject.education_benefits_claim.confirmation_number
+
+            subject.after_submit(user)
 
-      it 'without benefit selected' do
-        allow(VANotify::EmailJob).to receive(:perform_async)
-
-        subject = create(:va1995_full_form)
-        parsed_form_data = JSON.parse(subject.form)
-        parsed_form_data.delete('benefit')
-        subject.form = parsed_form_data.to_json
-        confirmation_number = subject.education_benefits_claim.confirmation_number
-
-        subject.after_submit(user)
-
-        expect(VANotify::EmailJob).to have_received(:perform_async).with(
-          'test@sample.com',
-          'form1995_confirmation_email_template_id',
-          {
-            'first_name' => 'FIRST',
-            'benefit' => '',
-            'date_submitted' => Time.zone.today.strftime('%B %d, %Y'),
-            'confirmation_number' => confirmation_number,
-            'regional_office_address' => "P.O. Box 4616\nBuffalo, NY 14240-4616"
-          }
-        )
+            expect(VANotify::EmailJob).to have_received(:perform_async).with(
+              'test@sample.com',
+              'form1995_confirmation_email_template_id',
+              {
+                'first_name' => 'FIRST',
+                'benefit' => '',
+                'date_submitted' => Time.zone.today.strftime('%B %d, %Y'),
+                'confirmation_number' => confirmation_number,
+                'regional_office_address' => "P.O. Box 4616\nBuffalo, NY 14240-4616"
+              }
+            )
+          end
+        end
       end
     end
   end
diff --git a/spec/models/saved_claim_spec.rb b/spec/models/saved_claim_spec.rb
index 38141c39c64..d25308eb867 100644
--- a/spec/models/saved_claim_spec.rb
+++ b/spec/models/saved_claim_spec.rb
@@ -19,9 +19,10 @@ def attachment_keys
   subject(:saved_claim) { described_class.new(form: form_data) }
 
   let(:form_data) { { some_key: 'some_value' }.to_json }
-  let(:schema) { 'schema_content' }
+  let(:schema) { { some_key: 'some_value' }.to_json }
 
   before do
+    allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(false)
     allow(VetsJsonSchema::SCHEMAS).to receive(:[]).and_return(schema)
     allow(JSON::Validator).to receive_messages(fully_validate_schema: [], fully_validate: [])
   end
@@ -34,79 +35,128 @@ def attachment_keys
 
   describe 'validations' do
     context 'no validation errors' do
-      before do
-        allow(JSON::Validator).to receive(:fully_validate).and_return([])
+      context 'using JSON Schema' do
+        before do
+          allow(JSON::Validator).to receive(:fully_validate).and_return([])
+        end
+
+        it 'returns true' do
+          expect(saved_claim.validate).to eq true
+        end
       end
 
-      it 'returns true' do
-        expect(saved_claim.validate).to eq true
+      context 'using JSON Schemer' do
+        before do
+          allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(true)
+        end
+
+        it 'returns true' do
+          expect(saved_claim.validate).to eq(true)
+        end
       end
     end
 
     context 'validation errors' do
       let(:schema_errors) { [{ fragment: 'error' }] }
 
-      context 'when fully_validate_schema returns errors' do
-        before do
-          allow(JSON::Validator).to receive_messages(fully_validate_schema: schema_errors, fully_validate: [])
-        end
+      context 'using JSON Schema' do
+        context 'when fully_validate_schema returns errors' do
+          before do
+            allow(Flipper).to receive(:enabled?).with(:saved_claim_schema_validation_disable).and_return(false)
+            allow(JSON::Validator).to receive_messages(fully_validate_schema: schema_errors, fully_validate: [])
+          end
 
-        it 'logs schema failed error and calls fully_validate' do
-          expect(Rails.logger).to receive(:error)
-            .with('SavedClaim schema failed validation! Attempting to clear cache.', { errors: schema_errors })
+          it 'logs schema failed error and calls fully_validate' do
+            expect(Rails.logger).to receive(:error)
+              .with('SavedClaim schema failed validation! Attempting to clear cache.', { errors: schema_errors })
 
-          expect(saved_claim.validate).to eq true
+            expect(saved_claim.validate).to eq true
+          end
         end
-      end
 
-      context 'when fully_validate returns errors' do
-        before do
-          allow(JSON::Validator).to receive(:fully_validate).and_return(schema_errors)
-        end
+        context 'when fully_validate returns errors' do
+          before do
+            allow(JSON::Validator).to receive(:fully_validate).and_return(schema_errors)
+          end
 
-        it 'adds validation errors to the form' do
-          saved_claim.validate
-          expect(saved_claim.errors.full_messages).not_to be_empty
+          it 'adds validation errors to the form' do
+            saved_claim.validate
+            expect(saved_claim.errors.full_messages).not_to be_empty
+          end
         end
-      end
 
-      context 'when JSON:Validator.fully_validate_schema throws an exception' do
-        let(:exception) { StandardError.new('Some exception') }
+        context 'when JSON:Validator.fully_validate_schema throws an exception' do
+          let(:exception) { StandardError.new('Some exception') }
 
-        before do
-          allow(JSON::Validator).to receive(:fully_validate_schema).and_raise(exception)
-          allow(JSON::Validator).to receive(:fully_validate).and_return([])
+          before do
+            allow(Flipper).to receive(:enabled?).with(:saved_claim_schema_validation_disable).and_return(true)
+            allow(JSON::Validator).to receive(:fully_validate_schema).and_raise(exception)
+            allow(JSON::Validator).to receive(:fully_validate).and_return([])
+          end
+
+          it 'logs exception and raises exception' do
+            expect(Rails.logger).to receive(:error)
+              .with('Error during schema validation!', { error: exception.message, backtrace: anything, schema: })
+
+            expect { saved_claim.validate }.to raise_error(exception.class, exception.message)
+          end
         end
 
-        it 'logs exception and raises exception' do
-          expect(Rails.logger).to receive(:error)
-            .with('Error during schema validation!', { error: exception.message, backtrace: anything, schema: })
+        context 'when JSON:Validator.fully_validate throws an exception' do
+          let(:exception) { StandardError.new('Some exception') }
 
-          expect { saved_claim.validate }.to raise_error(exception.class, exception.message)
+          before do
+            allow(JSON::Validator).to receive(:fully_validate_schema).and_return([])
+            allow(JSON::Validator).to receive(:fully_validate).and_raise(exception)
+          end
+
+          it 'logs exception and raises exception' do
+            expect(Rails.logger).to receive(:error)
+              .with('Error during form validation!', { error: exception.message, backtrace: anything, schema:,
+                                                       clear_cache: false })
+
+            expect(PersonalInformationLog).to receive(:create).with(
+              data: { schema: schema,
+                      parsed_form: saved_claim.parsed_form,
+                      params: { errors_as_objects: true, clear_cache: false } },
+              error_class: 'SavedClaim FormValidationError'
+            )
+
+            expect { saved_claim.validate }.to raise_error(exception.class, exception.message)
+          end
         end
       end
 
-      context 'when JSON:Validator.fully_validate throws an exception' do
-        let(:exception) { StandardError.new('Some exception') }
-
+      context 'using JSON Schemer' do
         before do
-          allow(JSON::Validator).to receive(:fully_validate_schema).and_return([])
-          allow(JSON::Validator).to receive(:fully_validate).and_raise(exception)
+          allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(true)
         end
 
-        it 'logs exception and raises exception' do
-          expect(Rails.logger).to receive(:error)
-            .with('Error during form validation!', { error: exception.message, backtrace: anything, schema:,
-                                                     clear_cache: false })
+        context 'when validate_schema returns errors' do
+          before do
+            allow(Flipper).to receive(:enabled?).with(:saved_claim_schema_validation_disable).and_return(false)
+            allow(JSONSchemer).to receive_messages(validate_schema: schema_errors)
+          end
 
-          expect(PersonalInformationLog).to receive(:create).with(
-            data: { schema: schema,
-                    parsed_form: saved_claim.parsed_form,
-                    params: { errors_as_objects: true, clear_cache: false } },
-            error_class: 'SavedClaim FormValidationError'
-          )
+          it 'logs schema faild error' do
+            expect(Rails.logger).to receive(:error)
+              .with('SavedClaim schema failed validation! Attempting to clear cache.', { errors: schema_errors })
+
+            expect(saved_claim.validate).to eq(true)
+          end
+        end
 
-          expect { saved_claim.validate }.to raise_error(exception.class, exception.message)
+        context 'when form validation returns errors' do
+          before do
+            allow(JSONSchemer).to receive_messages(validate_schema: [])
+            allow(JSONSchemer).to receive(:schema).and_return(double(:fake_schema,
+                                                                     validate: [{ data_pointer: 'error' }]))
+          end
+
+          it 'adds validation errors to the form' do
+            saved_claim.validate
+            expect(saved_claim.errors.full_messages).not_to be_empty
+          end
         end
       end
     end
diff --git a/spec/requests/v0/form0969_spec.rb b/spec/requests/v0/form0969_spec.rb
index 8870ddc7a00..81ee058e0d4 100644
--- a/spec/requests/v0/form0969_spec.rb
+++ b/spec/requests/v0/form0969_spec.rb
@@ -13,56 +13,75 @@
     build(:income_and_assets_claim).parsed_form
   end
 
-  describe 'POST create' do
-    subject do
-      post('/v0/form0969',
-           params: params.to_json,
-           headers: { 'CONTENT_TYPE' => 'application/json', 'HTTP_X_KEY_INFLECTION' => 'camel' })
-    end
-
-    context 'with invalid params' do
+  [true, false].each do |flipper_value|
+    context "when json_schemer flipper is #{flipper_value}" do
       before do
-        allow(Settings.sentry).to receive(:dsn).and_return('asdf')
+        allow(Flipper).to receive(:enabled?).and_call_original
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper_value)
       end
 
-      let(:params) do
-        {
-          incomeAndAssetsClaim: {
-            form: full_claim.merge('veteranSocialSecurityNumber' => 'just a string').to_json
-          }
-        }
-      end
+      describe 'POST create' do
+        subject do
+          post('/v0/form0969',
+               params: params.to_json,
+               headers: { 'CONTENT_TYPE' => 'application/json', 'HTTP_X_KEY_INFLECTION' => 'camel' })
+        end
 
-      it 'shows the validation errors' do
-        subject
-        expect(response).to have_http_status(:unprocessable_entity)
-        expect(
-          JSON.parse(response.body)['errors'][0]['detail'].include?(
-            "The property '#/veteranSocialSecurityNumber' value \"just a string\" did not match the regex"
-          )
-        ).to eq(true)
-      end
-    end
+        context 'with invalid params' do
+          before do
+            allow(Settings.sentry).to receive(:dsn).and_return('asdf')
+          end
 
-    context 'with valid params' do
-      let(:params) do
-        {
-          incomeAndAssetsClaim: {
-            form: full_claim.to_json
-          }
-        }
-      end
+          let(:params) do
+            {
+              incomeAndAssetsClaim: {
+                form: full_claim.merge('veteranSocialSecurityNumber' => 'just a string').to_json
+              }
+            }
+          end
 
-      it 'renders success' do
-        subject
-        expect(JSON.parse(response.body)['data']['attributes'].keys.sort)
-          .to eq(%w[confirmationNumber form guid regionalOffice submittedAt])
-      end
+          it 'shows the validation errors' do
+            subject
+            expect(response).to have_http_status(:unprocessable_entity)
+
+            if flipper_value
+              expect(
+                JSON.parse(response.body)['errors'][0]['detail'].include?(
+                  '/veteran-social-security-number - string at `/veteranSocialSecurityNumber` ' \
+                  'does not match pattern: ^[0-9]{9}$'
+                )
+              ).to eq(true)
+            else
+              expect(
+                JSON.parse(response.body)['errors'][0]['detail'].include?(
+                  "The property '#/veteranSocialSecurityNumber' value \"just a string\" did not match the regex"
+                )
+              ).to eq(true)
+            end
+          end
+        end
+
+        context 'with valid params' do
+          let(:params) do
+            {
+              incomeAndAssetsClaim: {
+                form: full_claim.to_json
+              }
+            }
+          end
+
+          it 'renders success' do
+            subject
+            expect(JSON.parse(response.body)['data']['attributes'].keys.sort)
+              .to eq(%w[confirmationNumber form guid regionalOffice submittedAt])
+          end
 
-      it 'returns the expected regional office' do
-        subject
-        expect(JSON.parse(response.body)['data']['attributes']['regionalOffice'].join(', '))
-          .to eq(reg_office)
+          it 'returns the expected regional office' do
+            subject
+            expect(JSON.parse(response.body)['data']['attributes']['regionalOffice'].join(', '))
+              .to eq(reg_office)
+          end
+        end
       end
     end
   end
diff --git a/spec/sidekiq/education_form/forms/va1995_spec.rb b/spec/sidekiq/education_form/forms/va1995_spec.rb
index c6f1274126b..e89089e6e69 100644
--- a/spec/sidekiq/education_form/forms/va1995_spec.rb
+++ b/spec/sidekiq/education_form/forms/va1995_spec.rb
@@ -7,78 +7,88 @@
 
   let(:education_benefits_claim) { build(:va1995).education_benefits_claim }
 
-  # For each sample application we have, format it and compare it against a 'known good'
-  # copy of that submission. This technically covers all the helper logic found in the
-  # `Form` specs, but are a good safety net for tracking how forms change over time.
-  %i[minimal kitchen_sink ch33_post911 ch33_fry ch30 ch1606].each do |application_name|
-    test_spool_file('1995', application_name)
-  end
+  [true, false].each do |flipper_value|
+    context "when json_schemer flipper is #{flipper_value}" do
+      before do
+        allow(Flipper).to receive(:enabled?).and_call_original
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper_value)
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(false)
+      end
 
-  # run PROD_EMULATION=true rspec spec/sidekiq/education_form/forms/va1995_spec.rb to
-  # emulate production (e.g. when removing feature flags)
-  prod_emulation = true if ENV['PROD_EMULATION'].eql?('true')
+      # For each sample application we have, format it and compare it against a 'known good'
+      # copy of that submission. This technically covers all the helper logic found in the
+      # `Form` specs, but are a good safety net for tracking how forms change over time.
+      %i[minimal kitchen_sink ch33_post911 ch33_fry ch30 ch1606].each do |application_name|
+        test_spool_file('1995', application_name)
+      end
 
-  # :nocov:
-  context 'test 1995 - production emulation', if: prod_emulation do
-    before do
-      allow(Settings).to receive(:vsp_environment).and_return('vagov-production')
-    end
+      # run PROD_EMULATION=true rspec spec/sidekiq/education_form/forms/va1995_spec.rb to
+      # emulate production (e.g. when removing feature flags)
+      prod_emulation = true if ENV['PROD_EMULATION'].eql?('true')
 
-    %i[minimal kitchen_sink ch33_post911 ch33_fry ch30 ch1606].each do |application_name|
-      test_spool_file('1995', application_name)
-    end
-  end
-  # :nocov:
+      # :nocov:
+      context 'test 1995 - production emulation', if: prod_emulation do
+        before do
+          allow(Settings).to receive(:vsp_environment).and_return('vagov-production')
+        end
 
-  describe '#direct_deposit_type' do
-    let(:education_benefits_claim) { create(:va1995_full_form).education_benefits_claim }
+        %i[minimal kitchen_sink ch33_post911 ch33_fry ch30 ch1606].each do |application_name|
+          test_spool_file('1995', application_name)
+        end
+      end
+      # :nocov:
 
-    it 'converts internal keys to text' do
-      expect(subject.direct_deposit_type('startUpdate')).to eq('Start or Update')
-      expect(subject.direct_deposit_type('stop')).to eq('Stop')
-      expect(subject.direct_deposit_type('noChange')).to eq('Do Not Change')
-    end
-  end
+      describe '#direct_deposit_type' do
+        let(:education_benefits_claim) { create(:va1995_full_form).education_benefits_claim }
 
-  # :nocov:
-  describe '#direct_deposit_type - production emulation', if: prod_emulation do
-    before do
-      allow(Settings).to receive(:vsp_environment).and_return('vagov-production')
-    end
+        it 'converts internal keys to text' do
+          expect(subject.direct_deposit_type('startUpdate')).to eq('Start or Update')
+          expect(subject.direct_deposit_type('stop')).to eq('Stop')
+          expect(subject.direct_deposit_type('noChange')).to eq('Do Not Change')
+        end
+      end
 
-    let(:education_benefits_claim) { create(:va1995_full_form).education_benefits_claim }
+      # :nocov:
+      describe '#direct_deposit_type - production emulation', if: prod_emulation do
+        before do
+          allow(Settings).to receive(:vsp_environment).and_return('vagov-production')
+        end
 
-    it 'converts internal keys to text' do
-      expect(subject.direct_deposit_type('startUpdate')).to eq('Start or Update')
-      expect(subject.direct_deposit_type('stop')).to eq('Stop')
-      expect(subject.direct_deposit_type('noChange')).to eq('Do Not Change')
-    end
-  end
-  # :nocov:
-
-  context 'spool_file tests with high school minors' do
-    %w[
-      ch30_guardian_not_graduated
-      ch30_guardian_graduated_sponsor
-      ch30_guardian_graduated
-    ].each do |test_application|
-      test_spool_file('1995', test_application)
-    end
-  end
+        let(:education_benefits_claim) { create(:va1995_full_form).education_benefits_claim }
 
-  # :nocov:
-  context 'spool_file tests with high school minors - production emulation', if: prod_emulation do
-    before do
-      allow(Settings).to receive(:vsp_environment).and_return('vagov-production')
-    end
+        it 'converts internal keys to text' do
+          expect(subject.direct_deposit_type('startUpdate')).to eq('Start or Update')
+          expect(subject.direct_deposit_type('stop')).to eq('Stop')
+          expect(subject.direct_deposit_type('noChange')).to eq('Do Not Change')
+        end
+      end
+      # :nocov:
+
+      context 'spool_file tests with high school minors' do
+        %w[
+          ch30_guardian_not_graduated
+          ch30_guardian_graduated_sponsor
+          ch30_guardian_graduated
+        ].each do |test_application|
+          test_spool_file('1995', test_application)
+        end
+      end
+
+      # :nocov:
+      context 'spool_file tests with high school minors - production emulation', if: prod_emulation do
+        before do
+          allow(Settings).to receive(:vsp_environment).and_return('vagov-production')
+        end
 
-    %w[
-      ch30_guardian_not_graduated
-      ch30_guardian_graduated_sponsor
-      ch30_guardian_graduated
-    ].each do |test_application|
-      test_spool_file('1995', test_application)
+        %w[
+          ch30_guardian_not_graduated
+          ch30_guardian_graduated_sponsor
+          ch30_guardian_graduated
+        ].each do |test_application|
+          test_spool_file('1995', test_application)
+        end
+      end
+      # :nocov:
     end
   end
-  # :nocov:
 end
diff --git a/spec/sidekiq/education_form/send_school_certifying_officials_email_spec.rb b/spec/sidekiq/education_form/send_school_certifying_officials_email_spec.rb
index ca86670dbf0..23bd53b201f 100644
--- a/spec/sidekiq/education_form/send_school_certifying_officials_email_spec.rb
+++ b/spec/sidekiq/education_form/send_school_certifying_officials_email_spec.rb
@@ -103,7 +103,7 @@ def sco_email_sent_false(less_than_six_months, facility_code)
 
         # Find the SCO email
         sco_email = ActionMailer::Base.deliveries.find do |email|
-          email.to.include?('test@edu_sample.com')
+          email.to.include?('user@school.edu')
         end
         expect(sco_email).not_to be_nil
 
diff --git a/spec/sidekiq/evss/disability_compensation_form/submit_form0781_spec.rb b/spec/sidekiq/evss/disability_compensation_form/submit_form0781_spec.rb
index 2b0bd480ef7..5c7977fef01 100644
--- a/spec/sidekiq/evss/disability_compensation_form/submit_form0781_spec.rb
+++ b/spec/sidekiq/evss/disability_compensation_form/submit_form0781_spec.rb
@@ -13,6 +13,8 @@
     allow(Flipper).to receive(:enabled?).with('disability_compensation_upload_0781_to_lighthouse',
                                               instance_of(User)).and_return(false)
     allow(Flipper).to receive(:enabled?).with(:form526_send_0781_failure_notification).and_return(false)
+    allow(Flipper).to receive(:enabled?).with(:saved_claim_schema_validation_disable).and_return(false)
+    allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(false)
   end
 
   let(:user) { FactoryBot.create(:user, :loa3) }
@@ -40,587 +42,599 @@
     end
   end
 
-  describe '.perform_async' do
-    let(:submission) do
-      Form526Submission.create(user_uuid: user.uuid,
-                               auth_headers_json: auth_headers.to_json,
-                               saved_claim_id: saved_claim.id,
-                               form_json: form0781,
-                               submitted_claim_id: evss_claim_id)
-    end
-
-    context 'with a successful submission job' do
-      it 'queues a job for submit' do
-        expect do
-          subject.perform_async(submission.id)
-        end.to change(subject.jobs, :size).by(1)
-      end
-
-      it 'submits successfully' do
-        VCR.use_cassette('evss/disability_compensation_form/submit_0781') do
-          subject.perform_async(submission.id)
-          jid = subject.jobs.last['jid']
-          described_class.drain
-          expect(jid).not_to be_empty
-        end
-      end
-    end
-
-    context 'with a submission timeout' do
-      before do
-        allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(Faraday::TimeoutError)
-      end
-
-      it 'raises a gateway timeout error' do
-        subject.perform_async(submission.id)
-        expect { described_class.drain }.to raise_error(StandardError)
-      end
-    end
-
-    context 'with an unexpected error' do
+  [true, false].each do |flipper_value|
+    context "when json_schemer flipper is #{flipper_value}" do
       before do
-        allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(StandardError.new('foo'))
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper_value)
       end
 
-      it 'raises a standard error' do
-        subject.perform_async(submission.id)
-        expect { described_class.drain }.to raise_error(StandardError)
-      end
-    end
-  end
-
-  context 'catastrophic failure state' do
-    describe 'when all retries are exhausted' do
-      let!(:form526_submission) { create(:form526_submission) }
-      let!(:form526_job_status) { create(:form526_job_status, :retryable_error, form526_submission:, job_id: 1) }
-
-      it 'updates a StatsD counter and updates the status on an exhaustion event' do
-        subject.within_sidekiq_retries_exhausted_block({ 'jid' => form526_job_status.job_id }) do
-          # Will receieve increment for failure mailer metric
-          allow(StatsD).to receive(:increment).with(
-            'shared.sidekiq.default.EVSS_DisabilityCompensationForm_Form0781DocumentUploadFailureEmail.enqueue'
-          )
-
-          expect(StatsD).to receive(:increment).with("#{subject::STATSD_KEY_PREFIX}.exhausted")
-          expect(Rails).to receive(:logger).and_call_original
+      describe '.perform_async' do
+        let(:submission) do
+          Form526Submission.create(user_uuid: user.uuid,
+                                   auth_headers_json: auth_headers.to_json,
+                                   saved_claim_id: saved_claim.id,
+                                   form_json: form0781,
+                                   submitted_claim_id: evss_claim_id)
         end
-        form526_job_status.reload
-        expect(form526_job_status.status).to eq(Form526JobStatus::STATUS[:exhausted])
-      end
-
-      context 'when an error occurs during exhaustion handling and FailureEmail fails to enqueue' do
-        let!(:failure_email) { EVSS::DisabilityCompensationForm::Form0781DocumentUploadFailureEmail }
-        let!(:zsf_tag) { Form526Submission::ZSF_DD_TAG_SERVICE }
-        let!(:zsf_monitor) { ZeroSilentFailures::Monitor.new(zsf_tag) }
 
-        before do
-          allow(Flipper).to receive(:enabled?).with(:form526_send_0781_failure_notification).and_return(true)
-          allow(ZeroSilentFailures::Monitor).to receive(:new).with(zsf_tag).and_return(zsf_monitor)
-        end
+        context 'with a successful submission job' do
+          it 'queues a job for submit' do
+            expect do
+              subject.perform_async(submission.id)
+            end.to change(subject.jobs, :size).by(1)
+          end
 
-        it 'logs a silent failure' do
-          expect(zsf_monitor).to receive(:log_silent_failure).with(
-            {
-              job_id: form526_job_status.job_id,
-              error_class: nil,
-              error_message: 'An error occured',
-              timestamp: instance_of(Time),
-              form526_submission_id: form526_submission.id
-            },
-            nil,
-            call_location: instance_of(Logging::CallLocation)
-          )
-
-          args = { 'jid' => form526_job_status.job_id, 'args' => [form526_submission.id] }
-
-          expect do
-            subject.within_sidekiq_retries_exhausted_block(args) do
-              allow(failure_email).to receive(:perform_async).and_raise(StandardError, 'Simulated error')
+          it 'submits successfully' do
+            VCR.use_cassette('evss/disability_compensation_form/submit_0781') do
+              subject.perform_async(submission.id)
+              jid = subject.jobs.last['jid']
+              described_class.drain
+              expect(jid).not_to be_empty
             end
-          end.to raise_error(StandardError, 'Simulated error')
+          end
         end
-      end
 
-      context 'when the form526_send_0781_failure_notification Flipper is enabled' do
-        before do
-          allow(Flipper).to receive(:enabled?).with(:form526_send_0781_failure_notification).and_return(true)
-        end
+        context 'with a submission timeout' do
+          before do
+            allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(Faraday::TimeoutError)
+          end
 
-        it 'enqueues a failure notification mailer to send to the veteran' do
-          subject.within_sidekiq_retries_exhausted_block(
-            {
-              'jid' => form526_job_status.job_id,
-              'args' => [form526_submission.id]
-            }
-          ) do
-            expect(EVSS::DisabilityCompensationForm::Form0781DocumentUploadFailureEmail)
-              .to receive(:perform_async).with(form526_submission.id)
+          it 'raises a gateway timeout error' do
+            subject.perform_async(submission.id)
+            expect { described_class.drain }.to raise_error(StandardError)
           end
         end
-      end
 
-      context 'when the form526_send_0781_failure_notification Flipper is disabled' do
-        before do
-          allow(Flipper).to receive(:enabled?).with(:form526_send_0781_failure_notification).and_return(false)
-        end
+        context 'with an unexpected error' do
+          before do
+            allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(StandardError.new('foo'))
+          end
 
-        it 'does not enqueue a failure notification mailer to send to the veteran' do
-          subject.within_sidekiq_retries_exhausted_block(
-            {
-              'jid' => form526_job_status.job_id,
-              'args' => [form526_submission.id]
-            }
-          ) do
-            expect(EVSS::DisabilityCompensationForm::Form0781DocumentUploadFailureEmail)
-              .not_to receive(:perform_async)
+          it 'raises a standard error' do
+            subject.perform_async(submission.id)
+            expect { described_class.drain }.to raise_error(StandardError)
           end
         end
       end
 
-      context 'when the API Provider uploads are enabled' do
-        before do
-          allow(Flipper).to receive(:enabled?)
-            .with(:disability_compensation_use_api_provider_for_0781_uploads).and_return(true)
-        end
+      context 'catastrophic failure state' do
+        describe 'when all retries are exhausted' do
+          let!(:form526_submission) { create(:form526_submission) }
+          let!(:form526_job_status) { create(:form526_job_status, :retryable_error, form526_submission:, job_id: 1) }
 
-        let(:sidekiq_job_exhaustion_errors) do
-          {
-            'jid' => form526_job_status.job_id,
-            'error_class' => 'Broken Job Error',
-            'error_message' => 'Your Job Broke',
-            'args' => [form526_submission.id]
-          }
-        end
+          it 'updates a StatsD counter and updates the status on an exhaustion event' do
+            subject.within_sidekiq_retries_exhausted_block({ 'jid' => form526_job_status.job_id }) do
+              # Will receieve increment for failure mailer metric
+              allow(StatsD).to receive(:increment).with(
+                'shared.sidekiq.default.EVSS_DisabilityCompensationForm_Form0781DocumentUploadFailureEmail.enqueue'
+              )
 
-        context 'for a Lighthouse upload' do
-          it 'logs the job failure' do
-            allow(Flipper).to receive(:enabled?).with('disability_compensation_upload_0781_to_lighthouse',
-                                                      instance_of(User)).and_return(true)
-
-            subject.within_sidekiq_retries_exhausted_block(sidekiq_job_exhaustion_errors) do
-              expect_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
-                .to receive(:log_uploading_job_failure)
-                .with(EVSS::DisabilityCompensationForm::SubmitForm0781, 'Broken Job Error', 'Your Job Broke')
+              expect(StatsD).to receive(:increment).with("#{subject::STATSD_KEY_PREFIX}.exhausted")
+              expect(Rails).to receive(:logger).and_call_original
             end
+            form526_job_status.reload
+            expect(form526_job_status.status).to eq(Form526JobStatus::STATUS[:exhausted])
           end
-        end
 
-        context 'for an EVSS Upload' do
-          it 'logs the job failure' do
-            allow(Flipper).to receive(:enabled?).with('disability_compensation_upload_0781_to_lighthouse',
-                                                      instance_of(User)).and_return(false)
+          context 'when an error occurs during exhaustion handling and FailureEmail fails to enqueue' do
+            let!(:failure_email) { EVSS::DisabilityCompensationForm::Form0781DocumentUploadFailureEmail }
+            let!(:zsf_tag) { Form526Submission::ZSF_DD_TAG_SERVICE }
+            let!(:zsf_monitor) { ZeroSilentFailures::Monitor.new(zsf_tag) }
 
-            subject.within_sidekiq_retries_exhausted_block(sidekiq_job_exhaustion_errors) do
-              expect_any_instance_of(EVSSSupplementalDocumentUploadProvider).to receive(:log_uploading_job_failure)
-                .with(EVSS::DisabilityCompensationForm::SubmitForm0781, 'Broken Job Error', 'Your Job Broke')
+            before do
+              allow(Flipper).to receive(:enabled?).with(:form526_send_0781_failure_notification).and_return(true)
+              allow(ZeroSilentFailures::Monitor).to receive(:new).with(zsf_tag).and_return(zsf_monitor)
             end
-          end
-        end
-      end
-    end
-  end
-
-  context 'When an ApiProvider is used for uploads' do
-    before do
-      allow(Flipper).to receive(:enabled?)
-        .with(:disability_compensation_use_api_provider_for_0781_uploads).and_return(true)
-
-      # StatsD metrics are incremented in several callbacks we're not testing here so we need to allow them
-      allow(StatsD).to receive(:increment)
-      # There is an ensure block in the upload_to_vbms method that deletes the generated PDF
-      allow(File).to receive(:delete).and_return(nil)
-    end
-
-    let(:path_to_0781_fixture) { 'spec/fixtures/pdf_fill/21-0781/simple.pdf' }
-    let(:parsed_0781_form) { JSON.parse(submission.form_to_json(Form526Submission::FORM_0781))['form0781'] }
-    let(:form0781_only) do
-      original = JSON.parse(form0781)
-      original['form0781'].delete('form0781a')
-      original.to_json
-    end
-
-    let(:path_to_0781a_fixture) { 'spec/fixtures/pdf_fill/21-0781a/kitchen_sink.pdf' }
-    let(:parsed_0781a_form) { JSON.parse(submission.form_to_json(Form526Submission::FORM_0781))['form0781a'] }
-    let(:form0781a_only) do
-      original = JSON.parse(form0781)
-      original['form0781'].delete('form0781')
-      original.to_json
-    end
-
-    let(:submission) do
-      Form526Submission.create(user_uuid: user.uuid,
-                               auth_headers_json: auth_headers.to_json,
-                               saved_claim_id: saved_claim.id,
-                               form_json: form0781, # contains 0781 and 0781a
-                               submitted_claim_id: evss_claim_id)
-    end
-
-    let(:perform_upload) do
-      subject.perform_async(submission.id)
-      described_class.drain
-    end
-
-    context 'when the disability_compensation_upload_0781_to_lighthouse flipper is enabled' do
-      let(:faraday_response) { instance_double(Faraday::Response) }
-      let(:lighthouse_request_id) { Faker::Number.number(digits: 8) }
-      let(:lighthouse_0781_document) do
-        LighthouseDocument.new(
-          claim_id: submission.submitted_claim_id,
-          participant_id: submission.auth_headers['va_eauth_pid'],
-          document_type: 'L228'
-        )
-      end
-      let(:lighthouse_0781a_document) do
-        LighthouseDocument.new(
-          claim_id: submission.submitted_claim_id,
-          participant_id: submission.auth_headers['va_eauth_pid'],
-          document_type: 'L229'
-        )
-      end
-      let(:expected_statsd_metrics_prefix) do
-        'worker.evss.submit_form0781.lighthouse_supplemental_document_upload_provider'
-      end
-
-      before do
-        allow(Flipper).to receive(:enabled?).with('disability_compensation_upload_0781_to_lighthouse',
-                                                  instance_of(User)).and_return(true)
-
-        allow(BenefitsDocuments::Form526::UploadSupplementalDocumentService).to receive(:call)
-          .and_return(faraday_response)
-
-        allow(faraday_response).to receive(:body).and_return(
-          {
-            'data' => {
-              'success' => true,
-              'requestId' => lighthouse_request_id
-            }
-          }
-        )
-      end
-
-      context 'when a submission has both 0781 and 0781a' do
-        context 'when the request is successful' do
-          it 'uploads both documents to Lighthouse' do
-            # 0781
-            allow_any_instance_of(described_class)
-              .to receive(:generate_stamp_pdf)
-              .with(parsed_0781_form, submission.submitted_claim_id, '21-0781')
-              .and_return(path_to_0781_fixture)
 
-            allow_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
-              .to receive(:generate_upload_document)
-              .and_return(lighthouse_0781_document)
-
-            expect(BenefitsDocuments::Form526::UploadSupplementalDocumentService)
-              .to receive(:call)
-              .with(File.read(path_to_0781_fixture), lighthouse_0781a_document)
-
-            # 0781a
-            allow_any_instance_of(described_class)
-              .to receive(:generate_stamp_pdf)
-              .with(parsed_0781a_form, submission.submitted_claim_id, '21-0781a')
-              .and_return(path_to_0781a_fixture)
-
-            allow_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
-              .to receive(:generate_upload_document)
-              .and_return(lighthouse_0781a_document)
+            it 'logs a silent failure' do
+              expect(zsf_monitor).to receive(:log_silent_failure).with(
+                {
+                  job_id: form526_job_status.job_id,
+                  error_class: nil,
+                  error_message: 'An error occured',
+                  timestamp: instance_of(Time),
+                  form526_submission_id: form526_submission.id
+                },
+                nil,
+                call_location: instance_of(Logging::CallLocation)
+              )
+
+              args = { 'jid' => form526_job_status.job_id, 'args' => [form526_submission.id] }
+
+              expect do
+                subject.within_sidekiq_retries_exhausted_block(args) do
+                  allow(failure_email).to receive(:perform_async).and_raise(StandardError, 'Simulated error')
+                end
+              end.to raise_error(StandardError, 'Simulated error')
+            end
+          end
 
-            expect(BenefitsDocuments::Form526::UploadSupplementalDocumentService)
-              .to receive(:call)
-              .with(File.read(path_to_0781a_fixture), lighthouse_0781a_document)
+          context 'when the form526_send_0781_failure_notification Flipper is enabled' do
+            before do
+              allow(Flipper).to receive(:enabled?).with(:form526_send_0781_failure_notification).and_return(true)
+            end
 
-            perform_upload
+            it 'enqueues a failure notification mailer to send to the veteran' do
+              subject.within_sidekiq_retries_exhausted_block(
+                {
+                  'jid' => form526_job_status.job_id,
+                  'args' => [form526_submission.id]
+                }
+              ) do
+                expect(EVSS::DisabilityCompensationForm::Form0781DocumentUploadFailureEmail)
+                  .to receive(:perform_async).with(form526_submission.id)
+              end
+            end
           end
 
-          it 'logs the upload attempt with the correct job prefix' do
-            expect(StatsD).to receive(:increment).with(
-              "#{expected_statsd_metrics_prefix}.upload_attempt"
-            ).twice # For 0781 and 0781a
-            perform_upload
+          context 'when the form526_send_0781_failure_notification Flipper is disabled' do
+            before do
+              allow(Flipper).to receive(:enabled?).with(:form526_send_0781_failure_notification).and_return(false)
+            end
+
+            it 'does not enqueue a failure notification mailer to send to the veteran' do
+              subject.within_sidekiq_retries_exhausted_block(
+                {
+                  'jid' => form526_job_status.job_id,
+                  'args' => [form526_submission.id]
+                }
+              ) do
+                expect(EVSS::DisabilityCompensationForm::Form0781DocumentUploadFailureEmail)
+                  .not_to receive(:perform_async)
+              end
+            end
           end
 
-          it 'increments the correct StatsD success metric' do
-            expect(StatsD).to receive(:increment).with(
-              "#{expected_statsd_metrics_prefix}.upload_success"
-            ).twice # For 0781 and 0781a
+          context 'when the API Provider uploads are enabled' do
+            before do
+              allow(Flipper).to receive(:enabled?)
+                .with(:disability_compensation_use_api_provider_for_0781_uploads).and_return(true)
+            end
 
-            perform_upload
-          end
+            let(:sidekiq_job_exhaustion_errors) do
+              {
+                'jid' => form526_job_status.job_id,
+                'error_class' => 'Broken Job Error',
+                'error_message' => 'Your Job Broke',
+                'args' => [form526_submission.id]
+              }
+            end
 
-          it 'creates a pending Lighthouse526DocumentUpload record so we can poll Lighthouse later' do
-            upload_attributes = {
-              aasm_state: 'pending',
-              form526_submission_id: submission.id,
-              lighthouse_document_request_id: lighthouse_request_id
-            }
+            context 'for a Lighthouse upload' do
+              it 'logs the job failure' do
+                allow(Flipper).to receive(:enabled?).with('disability_compensation_upload_0781_to_lighthouse',
+                                                          instance_of(User)).and_return(true)
+
+                subject.within_sidekiq_retries_exhausted_block(sidekiq_job_exhaustion_errors) do
+                  expect_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
+                    .to receive(:log_uploading_job_failure)
+                    .with(EVSS::DisabilityCompensationForm::SubmitForm0781, 'Broken Job Error', 'Your Job Broke')
+                end
+              end
+            end
 
-            expect(Lighthouse526DocumentUpload.where(**upload_attributes).count).to eq(0)
+            context 'for an EVSS Upload' do
+              it 'logs the job failure' do
+                allow(Flipper).to receive(:enabled?).with('disability_compensation_upload_0781_to_lighthouse',
+                                                          instance_of(User)).and_return(false)
 
-            perform_upload
-            expect(Lighthouse526DocumentUpload.where(**upload_attributes)
-            .where(document_type: 'Form 0781').count).to eq(1)
-            expect(Lighthouse526DocumentUpload.where(**upload_attributes)
-            .where(document_type: 'Form 0781a').count).to eq(1)
+                subject.within_sidekiq_retries_exhausted_block(sidekiq_job_exhaustion_errors) do
+                  expect_any_instance_of(EVSSSupplementalDocumentUploadProvider).to receive(:log_uploading_job_failure)
+                    .with(EVSS::DisabilityCompensationForm::SubmitForm0781, 'Broken Job Error', 'Your Job Broke')
+                end
+              end
+            end
           end
         end
       end
 
-      context 'when a submission has 0781 only' do
+      context 'When an ApiProvider is used for uploads' do
         before do
-          submission.update(form_json: form0781_only)
+          allow(Flipper).to receive(:enabled?)
+            .with(:disability_compensation_use_api_provider_for_0781_uploads).and_return(true)
+
+          # StatsD metrics are incremented in several callbacks we're not testing here so we need to allow them
+          allow(StatsD).to receive(:increment)
+          # There is an ensure block in the upload_to_vbms method that deletes the generated PDF
+          allow(File).to receive(:delete).and_return(nil)
         end
 
-        context 'when the request is successful' do
-          it 'uploads to Lighthouse' do
-            allow_any_instance_of(described_class)
-              .to receive(:generate_stamp_pdf)
-              .with(parsed_0781_form, submission.submitted_claim_id, '21-0781')
-              .and_return(path_to_0781_fixture)
+        let(:path_to_0781_fixture) { 'spec/fixtures/pdf_fill/21-0781/simple.pdf' }
+        let(:parsed_0781_form) { JSON.parse(submission.form_to_json(Form526Submission::FORM_0781))['form0781'] }
+        let(:form0781_only) do
+          original = JSON.parse(form0781)
+          original['form0781'].delete('form0781a')
+          original.to_json
+        end
 
-            allow_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
-              .to receive(:generate_upload_document)
-              .and_return(lighthouse_0781_document)
+        let(:path_to_0781a_fixture) { 'spec/fixtures/pdf_fill/21-0781a/kitchen_sink.pdf' }
+        let(:parsed_0781a_form) { JSON.parse(submission.form_to_json(Form526Submission::FORM_0781))['form0781a'] }
+        let(:form0781a_only) do
+          original = JSON.parse(form0781)
+          original['form0781'].delete('form0781')
+          original.to_json
+        end
 
-            expect(BenefitsDocuments::Form526::UploadSupplementalDocumentService)
-              .to receive(:call)
-              .with(File.read(path_to_0781_fixture), lighthouse_0781_document)
+        let(:submission) do
+          Form526Submission.create(user_uuid: user.uuid,
+                                   auth_headers_json: auth_headers.to_json,
+                                   saved_claim_id: saved_claim.id,
+                                   form_json: form0781, # contains 0781 and 0781a
+                                   submitted_claim_id: evss_claim_id)
+        end
 
-            perform_upload
-          end
+        let(:perform_upload) do
+          subject.perform_async(submission.id)
+          described_class.drain
         end
 
-        context 'when Lighthouse returns an error response' do
-          let(:exception_errors) { [{ detail: 'Something Broke' }] }
+        context 'when the disability_compensation_upload_0781_to_lighthouse flipper is enabled' do
+          let(:faraday_response) { instance_double(Faraday::Response) }
+          let(:lighthouse_request_id) { Faker::Number.number(digits: 8) }
+          let(:lighthouse_0781_document) do
+            LighthouseDocument.new(
+              claim_id: submission.submitted_claim_id,
+              participant_id: submission.auth_headers['va_eauth_pid'],
+              document_type: 'L228'
+            )
+          end
+          let(:lighthouse_0781a_document) do
+            LighthouseDocument.new(
+              claim_id: submission.submitted_claim_id,
+              participant_id: submission.auth_headers['va_eauth_pid'],
+              document_type: 'L229'
+            )
+          end
+          let(:expected_statsd_metrics_prefix) do
+            'worker.evss.submit_form0781.lighthouse_supplemental_document_upload_provider'
+          end
 
           before do
-            # Skip additional logging that occurs in Lighthouse::ServiceException handling
-            allow(Rails.logger).to receive(:error)
+            allow(Flipper).to receive(:enabled?).with('disability_compensation_upload_0781_to_lighthouse',
+                                                      instance_of(User)).and_return(true)
 
             allow(BenefitsDocuments::Form526::UploadSupplementalDocumentService).to receive(:call)
-              .and_raise(Common::Exceptions::BadRequest.new(errors: exception_errors))
-          end
+              .and_return(faraday_response)
 
-          it 'logs the Lighthouse error response and re-raises the exception' do
-            expect(Rails.logger).to receive(:error).with(
-              'LighthouseSupplementalDocumentUploadProvider upload failed',
+            allow(faraday_response).to receive(:body).and_return(
               {
-                class: 'LighthouseSupplementalDocumentUploadProvider',
-                submission_id: submission.id,
-                submitted_claim_id: submission.submitted_claim_id,
-                user_uuid: submission.user_uuid,
-                va_document_type_code: 'L228',
-                primary_form: 'Form526',
-                error_info: exception_errors
+                'data' => {
+                  'success' => true,
+                  'requestId' => lighthouse_request_id
+                }
               }
             )
-
-            expect { perform_upload }.to raise_error(Common::Exceptions::BadRequest)
           end
 
-          it 'increments the correct status failure metric' do
-            expect(StatsD).to receive(:increment).with(
-              "#{expected_statsd_metrics_prefix}.upload_failure"
-            )
-
-            expect { perform_upload }.to raise_error(Common::Exceptions::BadRequest)
+          context 'when a submission has both 0781 and 0781a' do
+            context 'when the request is successful' do
+              it 'uploads both documents to Lighthouse' do
+                # 0781
+                allow_any_instance_of(described_class)
+                  .to receive(:generate_stamp_pdf)
+                  .with(parsed_0781_form, submission.submitted_claim_id, '21-0781')
+                  .and_return(path_to_0781_fixture)
+
+                allow_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
+                  .to receive(:generate_upload_document)
+                  .and_return(lighthouse_0781_document)
+
+                expect(BenefitsDocuments::Form526::UploadSupplementalDocumentService)
+                  .to receive(:call)
+                  .with(File.read(path_to_0781_fixture), lighthouse_0781a_document)
+
+                # 0781a
+                allow_any_instance_of(described_class)
+                  .to receive(:generate_stamp_pdf)
+                  .with(parsed_0781a_form, submission.submitted_claim_id, '21-0781a')
+                  .and_return(path_to_0781a_fixture)
+
+                allow_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
+                  .to receive(:generate_upload_document)
+                  .and_return(lighthouse_0781a_document)
+
+                expect(BenefitsDocuments::Form526::UploadSupplementalDocumentService)
+                  .to receive(:call)
+                  .with(File.read(path_to_0781a_fixture), lighthouse_0781a_document)
+
+                perform_upload
+              end
+
+              it 'logs the upload attempt with the correct job prefix' do
+                expect(StatsD).to receive(:increment).with(
+                  "#{expected_statsd_metrics_prefix}.upload_attempt"
+                ).twice # For 0781 and 0781a
+                perform_upload
+              end
+
+              it 'increments the correct StatsD success metric' do
+                expect(StatsD).to receive(:increment).with(
+                  "#{expected_statsd_metrics_prefix}.upload_success"
+                ).twice # For 0781 and 0781a
+
+                perform_upload
+              end
+
+              it 'creates a pending Lighthouse526DocumentUpload record so we can poll Lighthouse later' do
+                upload_attributes = {
+                  aasm_state: 'pending',
+                  form526_submission_id: submission.id,
+                  lighthouse_document_request_id: lighthouse_request_id
+                }
+
+                expect(Lighthouse526DocumentUpload.where(**upload_attributes).count).to eq(0)
+
+                perform_upload
+                expect(Lighthouse526DocumentUpload.where(**upload_attributes)
+                .where(document_type: 'Form 0781').count).to eq(1)
+                expect(Lighthouse526DocumentUpload.where(**upload_attributes)
+                .where(document_type: 'Form 0781a').count).to eq(1)
+              end
+            end
           end
-        end
-      end
 
-      context 'when a submission has 0781a only' do
-        before do
-          submission.update(form_json: form0781a_only)
-        end
+          context 'when a submission has 0781 only' do
+            before do
+              submission.update(form_json: form0781_only)
+            end
 
-        context 'when a request is successful' do
-          it 'uploads to Lighthouse' do
-            allow_any_instance_of(described_class)
-              .to receive(:generate_stamp_pdf)
-              .with(parsed_0781a_form, submission.submitted_claim_id, '21-0781a')
-              .and_return(path_to_0781a_fixture)
+            context 'when the request is successful' do
+              it 'uploads to Lighthouse' do
+                allow_any_instance_of(described_class)
+                  .to receive(:generate_stamp_pdf)
+                  .with(parsed_0781_form, submission.submitted_claim_id, '21-0781')
+                  .and_return(path_to_0781_fixture)
 
-            allow_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
-              .to receive(:generate_upload_document)
-              .and_return(lighthouse_0781a_document)
+                allow_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
+                  .to receive(:generate_upload_document)
+                  .and_return(lighthouse_0781_document)
+
+                expect(BenefitsDocuments::Form526::UploadSupplementalDocumentService)
+                  .to receive(:call)
+                  .with(File.read(path_to_0781_fixture), lighthouse_0781_document)
 
-            expect(BenefitsDocuments::Form526::UploadSupplementalDocumentService)
-              .to receive(:call)
-              .with(File.read(path_to_0781a_fixture), lighthouse_0781a_document)
+                perform_upload
+              end
+            end
 
-            perform_upload
+            context 'when Lighthouse returns an error response' do
+              let(:exception_errors) { [{ detail: 'Something Broke' }] }
+
+              before do
+                # Skip additional logging that occurs in Lighthouse::ServiceException handling
+                allow(Rails.logger).to receive(:error)
+
+                allow(BenefitsDocuments::Form526::UploadSupplementalDocumentService).to receive(:call)
+                  .and_raise(Common::Exceptions::BadRequest.new(errors: exception_errors))
+              end
+
+              it 'logs the Lighthouse error response and re-raises the exception' do
+                expect(Rails.logger).to receive(:error).with(
+                  'LighthouseSupplementalDocumentUploadProvider upload failed',
+                  {
+                    class: 'LighthouseSupplementalDocumentUploadProvider',
+                    submission_id: submission.id,
+                    submitted_claim_id: submission.submitted_claim_id,
+                    user_uuid: submission.user_uuid,
+                    va_document_type_code: 'L228',
+                    primary_form: 'Form526',
+                    error_info: exception_errors
+                  }
+                )
+
+                expect { perform_upload }.to raise_error(Common::Exceptions::BadRequest)
+              end
+
+              it 'increments the correct status failure metric' do
+                expect(StatsD).to receive(:increment).with(
+                  "#{expected_statsd_metrics_prefix}.upload_failure"
+                )
+
+                expect { perform_upload }.to raise_error(Common::Exceptions::BadRequest)
+              end
+            end
           end
-        end
 
-        context 'when Lighthouse returns an error response' do
-          let(:exception_errors) { [{ detail: 'Something Broke' }] }
+          context 'when a submission has 0781a only' do
+            before do
+              submission.update(form_json: form0781a_only)
+            end
 
-          before do
-            # Skip additional logging that occurs in Lighthouse::ServiceException handling
-            allow(Rails.logger).to receive(:error)
+            context 'when a request is successful' do
+              it 'uploads to Lighthouse' do
+                allow_any_instance_of(described_class)
+                  .to receive(:generate_stamp_pdf)
+                  .with(parsed_0781a_form, submission.submitted_claim_id, '21-0781a')
+                  .and_return(path_to_0781a_fixture)
 
-            allow(BenefitsDocuments::Form526::UploadSupplementalDocumentService).to receive(:call)
-              .and_raise(Common::Exceptions::BadRequest.new(errors: exception_errors))
-          end
+                allow_any_instance_of(LighthouseSupplementalDocumentUploadProvider)
+                  .to receive(:generate_upload_document)
+                  .and_return(lighthouse_0781a_document)
 
-          it 'logs the Lighthouse error response and re-raises the exception' do
-            expect(Rails.logger).to receive(:error).with(
-              'LighthouseSupplementalDocumentUploadProvider upload failed',
-              {
-                class: 'LighthouseSupplementalDocumentUploadProvider',
-                submission_id: submission.id,
-                submitted_claim_id: submission.submitted_claim_id,
-                user_uuid: submission.user_uuid,
-                va_document_type_code: 'L229',
-                primary_form: 'Form526',
-                error_info: exception_errors
-              }
-            )
+                expect(BenefitsDocuments::Form526::UploadSupplementalDocumentService)
+                  .to receive(:call)
+                  .with(File.read(path_to_0781a_fixture), lighthouse_0781a_document)
+
+                perform_upload
+              end
+            end
 
-            expect { perform_upload }.to raise_error(Common::Exceptions::BadRequest)
+            context 'when Lighthouse returns an error response' do
+              let(:exception_errors) { [{ detail: 'Something Broke' }] }
+
+              before do
+                # Skip additional logging that occurs in Lighthouse::ServiceException handling
+                allow(Rails.logger).to receive(:error)
+
+                allow(BenefitsDocuments::Form526::UploadSupplementalDocumentService).to receive(:call)
+                  .and_raise(Common::Exceptions::BadRequest.new(errors: exception_errors))
+              end
+
+              it 'logs the Lighthouse error response and re-raises the exception' do
+                expect(Rails.logger).to receive(:error).with(
+                  'LighthouseSupplementalDocumentUploadProvider upload failed',
+                  {
+                    class: 'LighthouseSupplementalDocumentUploadProvider',
+                    submission_id: submission.id,
+                    submitted_claim_id: submission.submitted_claim_id,
+                    user_uuid: submission.user_uuid,
+                    va_document_type_code: 'L229',
+                    primary_form: 'Form526',
+                    error_info: exception_errors
+                  }
+                )
+
+                expect { perform_upload }.to raise_error(Common::Exceptions::BadRequest)
+              end
+
+              it 'increments the correct status failure metric' do
+                expect(StatsD).to receive(:increment).with(
+                  "#{expected_statsd_metrics_prefix}.upload_failure"
+                )
+
+                expect { perform_upload }.to raise_error(Common::Exceptions::BadRequest)
+              end
+            end
           end
+        end
 
-          it 'increments the correct status failure metric' do
-            expect(StatsD).to receive(:increment).with(
-              "#{expected_statsd_metrics_prefix}.upload_failure"
+        context 'when the disability_compensation_upload_0781_to_lighthouse flipper is disabled' do
+          let(:evss_claim_0781_document) do
+            EVSSClaimDocument.new(
+              evss_claim_id: submission.submitted_claim_id,
+              document_type: 'L228'
             )
-
-            expect { perform_upload }.to raise_error(Common::Exceptions::BadRequest)
           end
-        end
-      end
-    end
+          let(:evss_claim_0781a_document) do
+            EVSSClaimDocument.new(
+              evss_claim_id: submission.submitted_claim_id,
+              document_type: 'L229'
+            )
+          end
+          let(:client_stub) { instance_double(EVSS::DocumentsService) }
+          let(:expected_statsd_metrics_prefix) do
+            'worker.evss.submit_form0781.evss_supplemental_document_upload_provider'
+          end
 
-    context 'when the disability_compensation_upload_0781_to_lighthouse flipper is disabled' do
-      let(:evss_claim_0781_document) do
-        EVSSClaimDocument.new(
-          evss_claim_id: submission.submitted_claim_id,
-          document_type: 'L228'
-        )
-      end
-      let(:evss_claim_0781a_document) do
-        EVSSClaimDocument.new(
-          evss_claim_id: submission.submitted_claim_id,
-          document_type: 'L229'
-        )
-      end
-      let(:client_stub) { instance_double(EVSS::DocumentsService) }
-      let(:expected_statsd_metrics_prefix) { 'worker.evss.submit_form0781.evss_supplemental_document_upload_provider' }
+          before do
+            allow(Flipper).to receive(:enabled?).with('disability_compensation_upload_0781_to_lighthouse',
+                                                      instance_of(User)).and_return(false)
 
-      before do
-        allow(Flipper).to receive(:enabled?).with('disability_compensation_upload_0781_to_lighthouse',
-                                                  instance_of(User)).and_return(false)
-
-        allow(EVSS::DocumentsService).to receive(:new) { client_stub }
-        allow(client_stub).to receive(:upload)
-        # 0781
-        allow_any_instance_of(described_class)
-          .to receive(:generate_stamp_pdf)
-          .with(parsed_0781_form, submission.submitted_claim_id, '21-0781')
-          .and_return(path_to_0781_fixture)
-        allow_any_instance_of(EVSSSupplementalDocumentUploadProvider)
-          .to receive(:generate_upload_document)
-          .with('simple.pdf')
-          .and_return(evss_claim_0781_document)
-
-        # 0781a
-        allow_any_instance_of(described_class)
-          .to receive(:generate_stamp_pdf)
-          .with(parsed_0781a_form, submission.submitted_claim_id, '21-0781a')
-          .and_return(path_to_0781a_fixture)
-        allow_any_instance_of(EVSSSupplementalDocumentUploadProvider)
-          .to receive(:generate_upload_document)
-          .with('kitchen_sink.pdf')
-          .and_return(evss_claim_0781a_document)
-      end
+            allow(EVSS::DocumentsService).to receive(:new) { client_stub }
+            allow(client_stub).to receive(:upload)
+            # 0781
+            allow_any_instance_of(described_class)
+              .to receive(:generate_stamp_pdf)
+              .with(parsed_0781_form, submission.submitted_claim_id, '21-0781')
+              .and_return(path_to_0781_fixture)
+            allow_any_instance_of(EVSSSupplementalDocumentUploadProvider)
+              .to receive(:generate_upload_document)
+              .with('simple.pdf')
+              .and_return(evss_claim_0781_document)
 
-      context 'when a submission has both 0781 and 0781a' do
-        context 'when the request is successful' do
-          it 'uploads both documents to EVSS' do
-            expect(client_stub).to receive(:upload).with(File.read(path_to_0781_fixture), evss_claim_0781_document)
+            # 0781a
+            allow_any_instance_of(described_class)
+              .to receive(:generate_stamp_pdf)
+              .with(parsed_0781a_form, submission.submitted_claim_id, '21-0781a')
+              .and_return(path_to_0781a_fixture)
+            allow_any_instance_of(EVSSSupplementalDocumentUploadProvider)
+              .to receive(:generate_upload_document)
+              .with('kitchen_sink.pdf')
+              .and_return(evss_claim_0781a_document)
+          end
 
-            expect(client_stub).to receive(:upload).with(File.read(path_to_0781a_fixture), evss_claim_0781a_document)
+          context 'when a submission has both 0781 and 0781a' do
+            context 'when the request is successful' do
+              it 'uploads both documents to EVSS' do
+                expect(client_stub).to receive(:upload).with(File.read(path_to_0781_fixture), evss_claim_0781_document)
 
-            perform_upload
-          end
+                expect(client_stub).to receive(:upload).with(File.read(path_to_0781a_fixture),
+                                                             evss_claim_0781a_document)
 
-          it 'logs the upload attempt with the correct job prefix' do
-            allow(client_stub).to receive(:upload)
-            expect(StatsD).to receive(:increment).with(
-              "#{expected_statsd_metrics_prefix}.upload_attempt"
-            ).twice # For 0781 and 0781a
+                perform_upload
+              end
 
-            perform_upload
-          end
+              it 'logs the upload attempt with the correct job prefix' do
+                allow(client_stub).to receive(:upload)
+                expect(StatsD).to receive(:increment).with(
+                  "#{expected_statsd_metrics_prefix}.upload_attempt"
+                ).twice # For 0781 and 0781a
 
-          it 'increments the correct StatsD success metric' do
-            allow(client_stub).to receive(:upload)
-            expect(StatsD).to receive(:increment).with(
-              "#{expected_statsd_metrics_prefix}.upload_success"
-            ).twice # For 0781 and 0781a
+                perform_upload
+              end
 
-            perform_upload
-          end
-        end
+              it 'increments the correct StatsD success metric' do
+                allow(client_stub).to receive(:upload)
+                expect(StatsD).to receive(:increment).with(
+                  "#{expected_statsd_metrics_prefix}.upload_success"
+                ).twice # For 0781 and 0781a
 
-        context 'when an upload raises an EVSS response error' do
-          it 'logs an upload error and re-raises the error' do
-            allow(client_stub).to receive(:upload).and_raise(EVSS::ErrorMiddleware::EVSSError)
-            expect_any_instance_of(EVSSSupplementalDocumentUploadProvider).to receive(:log_upload_failure)
+                perform_upload
+              end
+            end
 
-            expect do
-              subject.perform_async(submission.id)
-              described_class.drain
-            end.to raise_error(EVSS::ErrorMiddleware::EVSSError)
+            context 'when an upload raises an EVSS response error' do
+              it 'logs an upload error and re-raises the error' do
+                allow(client_stub).to receive(:upload).and_raise(EVSS::ErrorMiddleware::EVSSError)
+                expect_any_instance_of(EVSSSupplementalDocumentUploadProvider).to receive(:log_upload_failure)
+
+                expect do
+                  subject.perform_async(submission.id)
+                  described_class.drain
+                end.to raise_error(EVSS::ErrorMiddleware::EVSSError)
+              end
+            end
           end
-        end
-      end
 
-      context 'when a submission has only a 0781 form' do
-        before do
-          submission.update(form_json: form0781_only)
-        end
+          context 'when a submission has only a 0781 form' do
+            before do
+              submission.update(form_json: form0781_only)
+            end
 
-        context 'when the request is successful' do
-          it 'uploads to EVSS' do
-            submission.update(form_json: form0781_only)
-            expect(client_stub).to receive(:upload).with(File.read(path_to_0781_fixture), evss_claim_0781_document)
+            context 'when the request is successful' do
+              it 'uploads to EVSS' do
+                submission.update(form_json: form0781_only)
+                expect(client_stub).to receive(:upload).with(File.read(path_to_0781_fixture), evss_claim_0781_document)
 
-            perform_upload
-          end
-        end
+                perform_upload
+              end
+            end
 
-        context 'when an upload raises an EVSS response error' do
-          it 'logs an upload error and re-raises the error' do
-            allow(client_stub).to receive(:upload).and_raise(EVSS::ErrorMiddleware::EVSSError)
-            expect_any_instance_of(EVSSSupplementalDocumentUploadProvider).to receive(:log_upload_failure)
+            context 'when an upload raises an EVSS response error' do
+              it 'logs an upload error and re-raises the error' do
+                allow(client_stub).to receive(:upload).and_raise(EVSS::ErrorMiddleware::EVSSError)
+                expect_any_instance_of(EVSSSupplementalDocumentUploadProvider).to receive(:log_upload_failure)
 
-            expect do
-              subject.perform_async(submission.id)
-              described_class.drain
-            end.to raise_error(EVSS::ErrorMiddleware::EVSSError)
+                expect do
+                  subject.perform_async(submission.id)
+                  described_class.drain
+                end.to raise_error(EVSS::ErrorMiddleware::EVSSError)
+              end
+            end
           end
-        end
-      end
 
-      context 'when a submission has only a 0781a form' do
-        context 'when the request is successful' do
-          it 'uploads the 0781a document to EVSS' do
-            submission.update(form_json: form0781a_only)
-            expect(client_stub).to receive(:upload).with(File.read(path_to_0781a_fixture), evss_claim_0781a_document)
+          context 'when a submission has only a 0781a form' do
+            context 'when the request is successful' do
+              it 'uploads the 0781a document to EVSS' do
+                submission.update(form_json: form0781a_only)
+                expect(client_stub).to receive(:upload).with(File.read(path_to_0781a_fixture),
+                                                             evss_claim_0781a_document)
 
-            perform_upload
-          end
-        end
+                perform_upload
+              end
+            end
 
-        context 'when an upload raises an EVSS response error' do
-          it 'logs an upload error and re-raises the error' do
-            allow(client_stub).to receive(:upload).and_raise(EVSS::ErrorMiddleware::EVSSError)
-            expect_any_instance_of(EVSSSupplementalDocumentUploadProvider).to receive(:log_upload_failure)
+            context 'when an upload raises an EVSS response error' do
+              it 'logs an upload error and re-raises the error' do
+                allow(client_stub).to receive(:upload).and_raise(EVSS::ErrorMiddleware::EVSSError)
+                expect_any_instance_of(EVSSSupplementalDocumentUploadProvider).to receive(:log_upload_failure)
 
-            expect do
-              subject.perform_async(submission.id)
-              described_class.drain
-            end.to raise_error(EVSS::ErrorMiddleware::EVSSError)
+                expect do
+                  subject.perform_async(submission.id)
+                  described_class.drain
+                end.to raise_error(EVSS::ErrorMiddleware::EVSSError)
+              end
+            end
           end
         end
       end
diff --git a/spec/sidekiq/evss/disability_compensation_form/submit_form526_all_claim_spec.rb b/spec/sidekiq/evss/disability_compensation_form/submit_form526_all_claim_spec.rb
index 312beb99873..88943b34496 100644
--- a/spec/sidekiq/evss/disability_compensation_form/submit_form526_all_claim_spec.rb
+++ b/spec/sidekiq/evss/disability_compensation_form/submit_form526_all_claim_spec.rb
@@ -10,12 +10,14 @@
 RSpec.describe EVSS::DisabilityCompensationForm::SubmitForm526AllClaim, type: :job do
   subject { described_class }
 
+  # This needs to be modernized (using allow)
   before do
     Sidekiq::Job.clear_all
+    Flipper.disable(:validate_saved_claims_with_json_schemer)
+    Flipper.disable(:disability_526_expanded_contention_classification)
     Flipper.disable(:disability_compensation_lighthouse_claims_service_provider)
     Flipper.disable(:disability_compensation_production_tester)
     Flipper.disable(:disability_compensation_fail_submission)
-    Flipper.disable(:disability_526_expanded_contention_classification)
   end
 
   let(:user) { FactoryBot.create(:user, :loa3) }
@@ -23,569 +25,729 @@
     EVSS::DisabilityCompensationAuthHeaders.new(user).add_headers(EVSS::AuthHeaders.new(user).to_h)
   end
 
-  describe '.perform_async' do
-    define_negated_matcher :not_change, :change
-
-    let(:saved_claim) { FactoryBot.create(:va526ez) }
-    let(:submitted_claim_id) { 600_130_094 }
-    let(:user_account) { create(:user_account, icn: '123498767V234859') }
-    let(:submission) do
-      create(:form526_submission,
-             user_account_id: user_account.id,
-             user_uuid: user.uuid,
-             auth_headers_json: auth_headers.to_json,
-             saved_claim_id: saved_claim.id)
-    end
-    let(:open_claims_cassette) { 'evss/claims/claims_without_open_compensation_claims' }
-    let(:caseflow_cassette) { 'caseflow/appeals' }
-    let(:rated_disabilities_cassette) { 'evss/disability_compensation_form/rated_disabilities' }
-    let(:submit_form_cassette) { 'evss/disability_compensation_form/submit_form_v2' }
-    let(:lh_upload) { 'lighthouse/benefits_intake/200_lighthouse_intake_upload_location' }
-    let(:evss_get_pdf) { 'form526_backup/200_evss_get_pdf' }
-    let(:lh_intake_upload) { 'lighthouse/benefits_intake/200_lighthouse_intake_upload' }
-    let(:lh_submission) { 'lighthouse/benefits_claims/submit526/200_synchronous_response' }
-    let(:cassettes) do
-      [open_claims_cassette, caseflow_cassette, rated_disabilities_cassette,
-       submit_form_cassette, lh_upload, evss_get_pdf,
-       lh_intake_upload, lh_submission]
-    end
-    let(:backup_klass) { Sidekiq::Form526BackupSubmissionProcess::Submit }
-
-    before do
-      cassettes.each { |cassette| VCR.insert_cassette(cassette) }
-      Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
-      Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_FOREGROUND)
-    end
-
-    after do
-      cassettes.each { |cassette| VCR.eject_cassette(cassette) }
-    end
-
-    def expect_retryable_error(error_class)
-      subject.perform_async(submission.id)
-      expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_retryable).once
-      expect(Form526JobStatus).to receive(:upsert).twice
-      expect do
-        described_class.drain
-      end.to raise_error(error_class).and not_change(backup_klass.jobs, :size)
-    end
-
-    def expect_non_retryable_error
-      subject.perform_async(submission.id)
-      expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_non_retryable).once
-      expect(Form526JobStatus).to receive(:upsert).thrice
-      expect_any_instance_of(EVSS::DisabilityCompensationForm::SubmitForm526AllClaim).to(
-        receive(:non_retryable_error_handler).and_call_original
-      )
-      described_class.drain
-    end
-
-    context 'Submission inspection for flashes' do
+  [true, false].each do |flipper_value|
+    context "when json_schemer flipper is #{flipper_value}" do
       before do
-        allow(Rails.logger).to receive(:info)
-        allow(StatsD).to receive(:increment)
-      end
-
-      def submit_it
-        subject.perform_async(submission.id)
-        VCR.use_cassette('virtual_regional_office/contention_classification_null_response') do
-          described_class.drain
-        end
-        submission.reload
-        expect(Form526JobStatus.last.status).to eq 'success'
+        allow(Flipper).to receive(:enabled?).and_call_original
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper_value)
       end
 
-      context 'without any flashes' do
-        let(:submission) do
-          create(:form526_submission,
-                 :asthma_claim_for_increase,
-                 user_uuid: user.uuid,
-                 auth_headers_json: auth_headers.to_json,
-                 saved_claim_id: saved_claim.id)
-        end
-
-        it 'does not log or push metrics' do
-          submit_it
+      describe '.perform_async' do
+        define_negated_matcher :not_change, :change
 
-          expect(Rails.logger).not_to have_received(:info).with('Flash Prototype Added', anything)
-          expect(StatsD).not_to have_received(:increment).with('worker.flashes', anything)
-        end
-      end
-
-      context 'with flash but without prototype' do
+        let(:saved_claim) { FactoryBot.create(:va526ez) }
+        let(:submitted_claim_id) { 600_130_094 }
+        let(:user_account) { create(:user_account, icn: '123498767V234859') }
         let(:submission) do
           create(:form526_submission,
-                 :without_diagnostic_code,
+                 user_account_id: user_account.id,
                  user_uuid: user.uuid,
                  auth_headers_json: auth_headers.to_json,
                  saved_claim_id: saved_claim.id)
         end
-
-        it 'does not log prototype statement but pushes metrics' do
-          submit_it
-
-          expect(Rails.logger).not_to have_received(:info).with('Flash Prototype Added', anything)
-          expect(StatsD).to have_received(:increment).with(
-            'worker.flashes',
-            tags: ['flash:Priority Processing - Veteran over age 85', 'prototype:false']
-          ).once
+        let(:open_claims_cassette) { 'evss/claims/claims_without_open_compensation_claims' }
+        let(:caseflow_cassette) { 'caseflow/appeals' }
+        let(:rated_disabilities_cassette) { 'evss/disability_compensation_form/rated_disabilities' }
+        let(:submit_form_cassette) { 'evss/disability_compensation_form/submit_form_v2' }
+        let(:lh_upload) { 'lighthouse/benefits_intake/200_lighthouse_intake_upload_location' }
+        let(:evss_get_pdf) { 'form526_backup/200_evss_get_pdf' }
+        let(:lh_intake_upload) { 'lighthouse/benefits_intake/200_lighthouse_intake_upload' }
+        let(:lh_submission) { 'lighthouse/benefits_claims/submit526/200_synchronous_response' }
+        let(:cassettes) do
+          [open_claims_cassette, caseflow_cassette, rated_disabilities_cassette,
+           submit_form_cassette, lh_upload, evss_get_pdf,
+           lh_intake_upload, lh_submission]
         end
-      end
+        let(:backup_klass) { Sidekiq::Form526BackupSubmissionProcess::Submit }
 
-      context 'with ALS flash' do
-        let(:submission) do
-          create(:form526_submission,
-                 :als_claim_for_increase,
-                 user_uuid: user.uuid,
-                 auth_headers_json: auth_headers.to_json,
-                 saved_claim_id: saved_claim.id)
+        before do
+          cassettes.each { |cassette| VCR.insert_cassette(cassette) }
+          Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_BACKGROUND)
+          Flipper.disable(ApiProviderFactory::FEATURE_TOGGLE_RATED_DISABILITIES_FOREGROUND)
         end
 
-        it 'logs prototype statement and pushes metrics' do
-          submit_it
-
-          expect(Rails.logger).to have_received(:info).with(
-            'Flash Prototype Added',
-            { submitted_claim_id:, flashes: ['Amyotrophic Lateral Sclerosis'] }
-          ).once
-          expect(StatsD).to have_received(:increment).with(
-            'worker.flashes',
-            tags: ['flash:Amyotrophic Lateral Sclerosis', 'prototype:true']
-          ).once
+        after do
+          cassettes.each { |cassette| VCR.eject_cassette(cassette) }
         end
-      end
 
-      context 'with multiple flashes' do
-        let(:submission) do
-          create(:form526_submission,
-                 :als_claim_for_increase_terminally_ill,
-                 user_uuid: user.uuid,
-                 auth_headers_json: auth_headers.to_json,
-                 saved_claim_id: saved_claim.id)
+        def expect_retryable_error(error_class)
+          subject.perform_async(submission.id)
+          expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_retryable).once
+          expect(Form526JobStatus).to receive(:upsert).twice
+          expect do
+            described_class.drain
+          end.to raise_error(error_class).and not_change(backup_klass.jobs, :size)
         end
 
-        it 'logs prototype statement and pushes metrics' do
-          submit_it
-
-          expect(Rails.logger).to have_received(:info).with(
-            'Flash Prototype Added',
-            { submitted_claim_id:, flashes: ['Amyotrophic Lateral Sclerosis', 'Terminally Ill'] }
-          ).once
-          expect(StatsD).to have_received(:increment).with(
-            'worker.flashes',
-            tags: ['flash:Amyotrophic Lateral Sclerosis', 'prototype:true']
-          ).once
-          expect(StatsD).to have_received(:increment).with(
-            'worker.flashes',
-            tags: ['flash:Terminally Ill', 'prototype:false']
-          ).once
+        def expect_non_retryable_error
+          subject.perform_async(submission.id)
+          expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_non_retryable).once
+          expect(Form526JobStatus).to receive(:upsert).thrice
+          expect_any_instance_of(EVSS::DisabilityCompensationForm::SubmitForm526AllClaim).to(
+            receive(:non_retryable_error_handler).and_call_original
+          )
+          described_class.drain
         end
-      end
-    end
 
-    context 'with contention classification enabled' do
-      context 'when diagnostic code is not set' do
-        let(:submission) do
-          create(:form526_submission,
-                 :without_diagnostic_code,
-                 user_uuid: user.uuid,
-                 auth_headers_json: auth_headers.to_json,
-                 saved_claim_id: saved_claim.id)
-        end
-      end
+        context 'Submission inspection for flashes' do
+          before do
+            allow(Rails.logger).to receive(:info)
+            allow(StatsD).to receive(:increment)
+          end
 
-      context 'when diagnostic code is set' do
-        it 'still completes form 526 submission when CC fails' do
-          subject.perform_async(submission.id)
-          expect do
-            VCR.use_cassette('virtual_regional_office/contention_classification_failure') do
+          def submit_it
+            subject.perform_async(submission.id)
+            VCR.use_cassette('virtual_regional_office/contention_classification_null_response') do
               described_class.drain
             end
-          end.not_to change(backup_klass.jobs, :size)
-          expect(Form526JobStatus.last.status).to eq 'success'
-        end
+            submission.reload
+            expect(Form526JobStatus.last.status).to eq 'success'
+          end
 
-        it 'handles null response gracefully' do
-          subject.perform_async(submission.id)
-          expect do
-            VCR.use_cassette('virtual_regional_office/contention_classification_null_response') do
-              described_class.drain
-              submission.reload
+          context 'without any flashes' do
+            let(:submission) do
+              create(:form526_submission,
+                     :asthma_claim_for_increase,
+                     user_uuid: user.uuid,
+                     auth_headers_json: auth_headers.to_json,
+                     saved_claim_id: saved_claim.id)
+            end
 
-              final_classification_code = submission.form['form526']['form526']['disabilities'][0]['classificationCode']
-              expect(final_classification_code).to eq(ONLY_526_JSON_CLASSIFICATION_CODE)
+            it 'does not log or push metrics' do
+              submit_it
+
+              expect(Rails.logger).not_to have_received(:info).with('Flash Prototype Added', anything)
+              expect(StatsD).not_to have_received(:increment).with('worker.flashes', anything)
             end
-          end.not_to change(Sidekiq::Form526BackupSubmissionProcess::Submit.jobs, :size)
-          expect(Form526JobStatus.last.status).to eq 'success'
-        end
+          end
 
-        it 'updates Form526Submission form with id' do
-          expect(described_class).to be < EVSS::DisabilityCompensationForm::SubmitForm526
-          subject.perform_async(submission.id)
+          context 'with flash but without prototype' do
+            let(:submission) do
+              create(:form526_submission,
+                     :without_diagnostic_code,
+                     user_uuid: user.uuid,
+                     auth_headers_json: auth_headers.to_json,
+                     saved_claim_id: saved_claim.id)
+            end
 
-          expect do
-            VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
-              described_class.drain
-              submission.reload
+            it 'does not log prototype statement but pushes metrics' do
+              submit_it
 
-              final_classification_code = submission.form['form526']['form526']['disabilities'][0]['classificationCode']
-              expect(final_classification_code).to eq(9012)
+              expect(Rails.logger).not_to have_received(:info).with('Flash Prototype Added', anything)
+              expect(StatsD).to have_received(:increment).with(
+                'worker.flashes',
+                tags: ['flash:Priority Processing - Veteran over age 85', 'prototype:false']
+              ).once
             end
-          end.not_to change(Sidekiq::Form526BackupSubmissionProcess::Submit.jobs, :size)
-        end
+          end
 
-        context 'when veteran has open claims' do
-          let(:open_claims_cassette) { 'evss/claims/claims' }
+          context 'with ALS flash' do
+            let(:submission) do
+              create(:form526_submission,
+                     :als_claim_for_increase,
+                     user_uuid: user.uuid,
+                     auth_headers_json: auth_headers.to_json,
+                     saved_claim_id: saved_claim.id)
+            end
 
-          before do
-            allow(Rails.logger).to receive(:info)
-            Timecop.freeze('2018-09-28T13:00:00ZZ')
+            it 'logs prototype statement and pushes metrics' do
+              submit_it
+
+              expect(Rails.logger).to have_received(:info).with(
+                'Flash Prototype Added',
+                { submitted_claim_id:, flashes: ['Amyotrophic Lateral Sclerosis'] }
+              ).once
+              expect(StatsD).to have_received(:increment).with(
+                'worker.flashes',
+                tags: ['flash:Amyotrophic Lateral Sclerosis', 'prototype:true']
+              ).once
+            end
           end
 
-          after { Timecop.return }
+          context 'with multiple flashes' do
+            let(:submission) do
+              create(:form526_submission,
+                     :als_claim_for_increase_terminally_ill,
+                     user_uuid: user.uuid,
+                     auth_headers_json: auth_headers.to_json,
+                     saved_claim_id: saved_claim.id)
+            end
 
-          it 'logs the expected data for EP 400 merge eligibility' do
-            subject.perform_async(submission.id)
-            VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
-              described_class.drain
+            it 'logs prototype statement and pushes metrics' do
+              submit_it
+
+              expect(Rails.logger).to have_received(:info).with(
+                'Flash Prototype Added',
+                { submitted_claim_id:, flashes: ['Amyotrophic Lateral Sclerosis', 'Terminally Ill'] }
+              ).once
+              expect(StatsD).to have_received(:increment).with(
+                'worker.flashes',
+                tags: ['flash:Amyotrophic Lateral Sclerosis', 'prototype:true']
+              ).once
+              expect(StatsD).to have_received(:increment).with(
+                'worker.flashes',
+                tags: ['flash:Terminally Ill', 'prototype:false']
+              ).once
             end
-            expect(Rails.logger).to have_received(:info).with('EP Merge total open EPs', id: submission.id, count: 1)
-            expect(Rails.logger).to have_received(:info).with(
-              'EP Merge open EP eligibility',
-              { id: submission.id, feature_enabled: true, open_claim_review: false,
-                pending_ep_age: 365, pending_ep_status: 'UNDER REVIEW' }
-            )
           end
+        end
 
-          context 'when the claim is not fully classified' do
-            it 'does not log EP 400 merge eligibility' do
-              subject.perform_async(submission.id)
-              VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
-                described_class.drain
-              end
-              expect(Rails.logger).not_to have_received(:info).with(
-                'EP Merge total open EPs', id: submission.id, count: 1
-              )
-              expect(Rails.logger).not_to have_received(:info).with(
-                'EP Merge open EP eligibility',
-                { id: submission.id, feature_enabled: true, open_claim_review: false,
-                  pending_ep_age: 365, pending_ep_status: 'UNDER REVIEW' }
-              )
+        context 'with contention classification enabled' do
+          context 'when diagnostic code is not set' do
+            let(:submission) do
+              create(:form526_submission,
+                     :without_diagnostic_code,
+                     user_uuid: user.uuid,
+                     auth_headers_json: auth_headers.to_json,
+                     saved_claim_id: saved_claim.id)
             end
           end
 
-          context 'when using LH Benefits Claims API instead of EVSS' do
-            before do
-              Flipper.enable(:disability_compensation_lighthouse_claims_service_provider)
-              allow_any_instance_of(BenefitsClaims::Configuration).to receive(:access_token).and_return('access_token')
+          context 'when diagnostic code is set' do
+            it 'still completes form 526 submission when CC fails' do
+              subject.perform_async(submission.id)
+              expect do
+                VCR.use_cassette('virtual_regional_office/contention_classification_failure') do
+                  described_class.drain
+                end
+              end.not_to change(backup_klass.jobs, :size)
+              expect(Form526JobStatus.last.status).to eq 'success'
             end
 
-            after { Flipper.disable(:disability_compensation_lighthouse_claims_service_provider) }
+            it 'handles null response gracefully' do
+              subject.perform_async(submission.id)
+              expect do
+                VCR.use_cassette('virtual_regional_office/contention_classification_null_response') do
+                  described_class.drain
+                  submission.reload
 
-            let(:open_claims_cassette) { 'lighthouse/benefits_claims/index/claims_with_single_open_disability_claim' }
+                  final_code = submission.form['form526']['form526']['disabilities'][0]['classificationCode']
+                  expect(final_code).to eq(ONLY_526_JSON_CLASSIFICATION_CODE)
+                end
+              end.not_to change(Sidekiq::Form526BackupSubmissionProcess::Submit.jobs, :size)
+              expect(Form526JobStatus.last.status).to eq 'success'
+            end
 
-            it 'logs the expected data for EP 400 merge eligibility' do
+            it 'updates Form526Submission form with id' do
+              expect(described_class).to be < EVSS::DisabilityCompensationForm::SubmitForm526
               subject.perform_async(submission.id)
-              VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
-                described_class.drain
-              end
-              expect(Rails.logger).to have_received(:info).with('EP Merge total open EPs', id: submission.id, count: 1)
-              expect(Rails.logger).to have_received(:info).with(
-                'EP Merge open EP eligibility',
-                { id: submission.id, feature_enabled: true, open_claim_review: false,
-                  pending_ep_age: 365, pending_ep_status: 'INITIAL_REVIEW' }
-              )
+
+              expect do
+                VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
+                  described_class.drain
+                  submission.reload
+
+                  final_code = submission.form['form526']['form526']['disabilities'][0]['classificationCode']
+                  expect(final_code).to eq(9012)
+                end
+              end.not_to change(Sidekiq::Form526BackupSubmissionProcess::Submit.jobs, :size)
             end
 
-            context 'when the claim is not fully classified' do
-              it 'does not log EP 400 merge eligibility' do
+            context 'when veteran has open claims' do
+              let(:open_claims_cassette) { 'evss/claims/claims' }
+
+              before do
+                allow(Rails.logger).to receive(:info)
+                Timecop.freeze('2018-09-28T13:00:00ZZ')
+              end
+
+              after { Timecop.return }
+
+              it 'logs the expected data for EP 400 merge eligibility' do
                 subject.perform_async(submission.id)
-                VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
+                VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
                   described_class.drain
                 end
-                expect(Rails.logger).not_to have_received(:info).with(
-                  'EP Merge total open EPs', id: submission.id, count: 1
-                )
-                expect(Rails.logger).not_to have_received(:info).with(
+                expect(Rails.logger).to have_received(:info).with('EP Merge total open EPs', id: submission.id,
+                                                                                             count: 1)
+                expect(Rails.logger).to have_received(:info).with(
                   'EP Merge open EP eligibility',
                   { id: submission.id, feature_enabled: true, open_claim_review: false,
-                    pending_ep_age: 365, pending_ep_status: 'INITIAL_REVIEW' }
+                    pending_ep_age: 365, pending_ep_status: 'UNDER REVIEW' }
                 )
               end
-            end
-          end
 
-          context 'when EP400 merge API call is enabled' do
-            before do
-              Flipper.enable(:disability_526_ep_merge_api, user)
-              allow(Flipper).to receive(:enabled?).and_call_original
-            end
+              context 'when the claim is not fully classified' do
+                it 'does not log EP 400 merge eligibility' do
+                  subject.perform_async(submission.id)
+                  VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
+                    described_class.drain
+                  end
+                  expect(Rails.logger).not_to have_received(:info).with(
+                    'EP Merge total open EPs', id: submission.id, count: 1
+                  )
+                  expect(Rails.logger).not_to have_received(:info).with(
+                    'EP Merge open EP eligibility',
+                    { id: submission.id, feature_enabled: true, open_claim_review: false,
+                      pending_ep_age: 365, pending_ep_status: 'UNDER REVIEW' }
+                  )
+                end
+              end
 
-            it 'records the eligible claim ID and adds the EP400 special issue to the submission' do
-              subject.perform_async(submission.id)
-              VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
-                described_class.drain
+              context 'when using LH Benefits Claims API instead of EVSS' do
+                before do
+                  Flipper.enable(:disability_compensation_lighthouse_claims_service_provider)
+                  allow_any_instance_of(BenefitsClaims::Configuration).to receive(:access_token)
+                    .and_return('access_token')
+                end
+
+                after { Flipper.disable(:disability_compensation_lighthouse_claims_service_provider) }
+
+                let(:open_claims_cassette) do
+                  'lighthouse/benefits_claims/index/claims_with_single_open_disability_claim'
+                end
+
+                it 'logs the expected data for EP 400 merge eligibility' do
+                  subject.perform_async(submission.id)
+                  VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
+                    described_class.drain
+                  end
+                  expect(Rails.logger).to have_received(:info).with('EP Merge total open EPs', id: submission.id,
+                                                                                               count: 1)
+                  expect(Rails.logger).to have_received(:info).with(
+                    'EP Merge open EP eligibility',
+                    { id: submission.id, feature_enabled: true, open_claim_review: false,
+                      pending_ep_age: 365, pending_ep_status: 'INITIAL_REVIEW' }
+                  )
+                end
+
+                context 'when the claim is not fully classified' do
+                  it 'does not log EP 400 merge eligibility' do
+                    subject.perform_async(submission.id)
+                    VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
+                      described_class.drain
+                    end
+                    expect(Rails.logger).not_to have_received(:info).with(
+                      'EP Merge total open EPs', id: submission.id, count: 1
+                    )
+                    expect(Rails.logger).not_to have_received(:info).with(
+                      'EP Merge open EP eligibility',
+                      { id: submission.id, feature_enabled: true, open_claim_review: false,
+                        pending_ep_age: 365, pending_ep_status: 'INITIAL_REVIEW' }
+                    )
+                  end
+                end
               end
-              submission.reload
-              expect(submission.read_metadata(:ep_merge_pending_claim_id)).to eq('600114692') # from claims.yml
-              expect(submission.disabilities.first).to include('specialIssues' => ['EMP'])
-              actor = OpenStruct.new({ flipper_id: submission.user_uuid })
-              expect(Flipper).to have_received(:enabled?).with(:disability_526_ep_merge_api, actor).once
-            end
 
-            context 'when the claim is not fully classified' do
-              it 'does not record an eligible claim id' do
-                subject.perform_async(submission.id)
-                VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
-                  described_class.drain
+              context 'when EP400 merge API call is enabled' do
+                before do
+                  Flipper.enable(:disability_526_ep_merge_api, user)
+                  allow(Flipper).to receive(:enabled?).and_call_original
+                end
+
+                it 'records the eligible claim ID and adds the EP400 special issue to the submission' do
+                  subject.perform_async(submission.id)
+                  VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
+                    described_class.drain
+                  end
+                  submission.reload
+                  expect(submission.read_metadata(:ep_merge_pending_claim_id)).to eq('600114692') # from claims.yml
+                  expect(submission.disabilities.first).to include('specialIssues' => ['EMP'])
+                  actor = OpenStruct.new({ flipper_id: submission.user_uuid })
+                  expect(Flipper).to have_received(:enabled?).with(:disability_526_ep_merge_api, actor).once
+                end
+
+                context 'when the claim is not fully classified' do
+                  it 'does not record an eligible claim id' do
+                    subject.perform_async(submission.id)
+                    VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
+                      described_class.drain
+                    end
+                    submission.reload
+                    expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
+                    expect(submission.disabilities.first['specialIssues']).to be_nil
+                  end
                 end
-                submission.reload
-                expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
-                expect(submission.disabilities.first['specialIssues']).to be_nil
               end
-            end
-          end
 
-          context 'when pending claim has lifecycle status not considered open for EP400 merge' do
-            let(:open_claims_cassette) { 'evss/claims/claims_pending_decision_approval' }
+              context 'when pending claim has lifecycle status not considered open for EP400 merge' do
+                let(:open_claims_cassette) { 'evss/claims/claims_pending_decision_approval' }
 
-            it 'does not save any claim ID for EP400 merge' do
-              subject.perform_async(submission.id)
-              VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
-                described_class.drain
+                it 'does not save any claim ID for EP400 merge' do
+                  subject.perform_async(submission.id)
+                  VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
+                    described_class.drain
+                  end
+                  submission.reload
+                  expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
+                end
+              end
+
+              context 'when an EP 030 or 040 is included in the list of open claims' do
+                let(:open_claims_cassette) { 'evss/claims/claims_with_open_040' }
+
+                it 'does not save any claim ID for EP400 merge' do
+                  subject.perform_async(submission.id)
+                  VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
+                    described_class.drain
+                  end
+                  submission.reload
+                  expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
+                end
+              end
+
+              context 'when Caseflow appeals status API returns an open claim review' do
+                let(:caseflow_cassette) { 'caseflow/appeals_with_hlr_only' }
+
+                it 'does not save any claim ID for EP400 merge' do
+                  subject.perform_async(submission.id)
+                  VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
+                    described_class.drain
+                  end
+                  submission.reload
+                  expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
+                end
+              end
+
+              context 'when EP400 merge API call is disabled' do
+                before { Flipper.disable(:disability_526_ep_merge_api) }
+
+                it 'does not record any eligible claim ID or add an EP400 special issue to the submission' do
+                  subject.perform_async(submission.id)
+                  VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
+                    described_class.drain
+                  end
+                  submission.reload
+                  expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
+                  expect(submission.disabilities.first['specialIssues']).to be_nil
+                end
               end
-              submission.reload
-              expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
             end
           end
+        end
+
+        context 'with multi-contention classification enabled' do
+          let(:submission) do
+            create(:form526_submission,
+                   :with_mixed_action_disabilities_and_free_text,
+                   user_uuid: user.uuid,
+                   auth_headers_json: auth_headers.to_json,
+                   saved_claim_id: saved_claim.id)
+          end
 
-          context 'when an EP 030 or 040 is included in the list of open claims' do
-            let(:open_claims_cassette) { 'evss/claims/claims_with_open_040' }
+          it 'does something when multi-contention api endpoint is hit' do
+            subject.perform_async(submission.id)
 
-            it 'does not save any claim ID for EP400 merge' do
-              subject.perform_async(submission.id)
-              VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
+            expect do
+              VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
                 described_class.drain
               end
-              submission.reload
-              expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
-            end
+            end.not_to change(Sidekiq::Form526BackupSubmissionProcess::Submit.jobs, :size)
+            submission.reload
+
+            classification_codes = submission.form['form526']['form526']['disabilities'].pluck('classificationCode')
+            expect(classification_codes).to eq([9012, 8994, nil, nil])
           end
 
-          context 'when Caseflow appeals status API returns an open claim review' do
-            let(:caseflow_cassette) { 'caseflow/appeals_with_hlr_only' }
+          it 'calls va-gov-claim-classifier as default' do
+            vro_client_mock = instance_double(VirtualRegionalOffice::Client)
+            allow(VirtualRegionalOffice::Client).to receive(:new).and_return(vro_client_mock)
+            allow(vro_client_mock).to receive_messages(
+              classify_vagov_contentions_expanded: OpenStruct.new(body: 'expanded classification'),
+              classify_vagov_contentions: OpenStruct.new(body: 'regular response')
+            )
+
+            expect_any_instance_of(Form526Submission).to receive(:classify_vagov_contentions).and_call_original
+            expect(vro_client_mock).to receive(:classify_vagov_contentions)
+            subject.perform_async(submission.id)
+            described_class.drain
+          end
+
+          context 'when the expanded classification endpoint is enabled' do
+            before do
+              user = OpenStruct.new({ flipper_id: submission.user_uuid })
+              allow(Flipper).to receive(:enabled?).and_call_original
+              allow(Flipper).to receive(:enabled?).with(:disability_526_expanded_contention_classification,
+                                                        user).and_return(true)
+            end
+
+            it 'calls the expanded classification endpoint' do
+              vro_client_mock = instance_double(VirtualRegionalOffice::Client)
+              allow(VirtualRegionalOffice::Client).to receive(:new).and_return(vro_client_mock)
+              allow(vro_client_mock).to receive_messages(
+                classify_vagov_contentions_expanded: OpenStruct.new(body: 'expanded classification'),
+                classify_vagov_contentions: OpenStruct.new(body: 'regular response')
+              )
 
-            it 'does not save any claim ID for EP400 merge' do
+              expect_any_instance_of(Form526Submission).to receive(:classify_vagov_contentions).and_call_original
+              expect(vro_client_mock).to receive(:classify_vagov_contentions_expanded)
               subject.perform_async(submission.id)
-              VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
-                described_class.drain
-              end
+              described_class.drain
+            end
+
+            it 'uses expanded classification to classify contentions' do
+              subject.perform_async(submission.id)
+              expect do
+                VCR.use_cassette('virtual_regional_office/expanded_classification') do
+                  described_class.drain
+                end
+              end.not_to change(Sidekiq::Form526BackupSubmissionProcess::Submit.jobs, :size)
               submission.reload
-              expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
+
+              classification_codes = submission.form['form526']['form526']['disabilities'].pluck('classificationCode')
+              expect(classification_codes).to eq([9012, 8994, nil, 8997])
             end
           end
 
-          context 'when EP400 merge API call is disabled' do
-            before { Flipper.disable(:disability_526_ep_merge_api) }
+          context 'when the disabilities array is empty' do
+            before do
+              allow(Rails.logger).to receive(:info)
+            end
 
-            it 'does not record any eligible claim ID or add an EP400 special issue to the submission' do
+            let(:submission) do
+              create(:form526_submission,
+                     :with_empty_disabilities,
+                     user_uuid: user.uuid,
+                     auth_headers_json: auth_headers.to_json,
+                     saved_claim_id: saved_claim.id)
+            end
+
+            it 'returns false to skip classification and continue other jobs' do
               subject.perform_async(submission.id)
-              VCR.use_cassette('virtual_regional_office/fully_classified_contention_classification') do
-                described_class.drain
-              end
-              submission.reload
-              expect(submission.read_metadata(:ep_merge_pending_claim_id)).to be_nil
-              expect(submission.disabilities.first['specialIssues']).to be_nil
+              expect(submission.update_contention_classification_all!).to eq false
+              expect(Rails.logger).to have_received(:info).with(
+                "No disabilities found for classification on claim #{submission.id}"
+              )
+            end
+
+            it 'does not call va-gov-claim-classifier' do
+              subject.perform_async(submission.id)
+              described_class.drain
+              expect(submission).not_to receive(:classify_vagov_contentions)
             end
           end
         end
-      end
-    end
-
-    context 'with multi-contention classification enabled' do
-      let(:submission) do
-        create(:form526_submission,
-               :with_mixed_action_disabilities_and_free_text,
-               user_uuid: user.uuid,
-               auth_headers_json: auth_headers.to_json,
-               saved_claim_id: saved_claim.id)
-      end
 
-      it 'does something when multi-contention api endpoint is hit' do
-        subject.perform_async(submission.id)
+        context 'with a successful submission job' do
+          it 'queues a job for submit' do
+            expect do
+              subject.perform_async(submission.id)
+            end.to change(subject.jobs, :size).by(1)
+          end
 
-        expect do
-          VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
-            described_class.drain
+          it 'submits successfully' do
+            subject.perform_async(submission.id)
+            expect { described_class.drain }.not_to change(backup_klass.jobs, :size)
+            expect(Form526JobStatus.last.status).to eq 'success'
           end
-        end.not_to change(Sidekiq::Form526BackupSubmissionProcess::Submit.jobs, :size)
-        submission.reload
 
-        classification_codes = submission.form['form526']['form526']['disabilities'].pluck('classificationCode')
-        expect(classification_codes).to eq([9012, 8994, nil, nil])
-      end
+          it 'submits successfully without calling classification service' do
+            subject.perform_async(submission.id)
+            expect do
+              VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
+                described_class.drain
+              end
+            end.not_to change(backup_klass.jobs, :size)
+            expect(Form526JobStatus.last.status).to eq 'success'
+          end
 
-      it 'calls va-gov-claim-classifier as default' do
-        vro_client_mock = instance_double(VirtualRegionalOffice::Client)
-        allow(VirtualRegionalOffice::Client).to receive(:new).and_return(vro_client_mock)
-        allow(vro_client_mock).to receive_messages(
-          classify_vagov_contentions_expanded: OpenStruct.new(body: 'expanded classification'),
-          classify_vagov_contentions: OpenStruct.new(body: 'regular response')
-        )
-
-        expect_any_instance_of(Form526Submission).to receive(:classify_vagov_contentions).and_call_original
-        expect(vro_client_mock).to receive(:classify_vagov_contentions)
-        subject.perform_async(submission.id)
-        described_class.drain
-      end
+          it 'does not call contention classification endpoint' do
+            subject.perform_async(submission.id)
+            expect(submission).not_to receive(:classify_vagov_contentions)
+            described_class.drain
+          end
 
-      context 'when the expanded classification endpoint is enabled' do
-        before do
-          user = OpenStruct.new({ flipper_id: submission.user_uuid })
-          allow(Flipper).to receive(:enabled?).and_call_original
-          allow(Flipper).to receive(:enabled?).with(:disability_526_expanded_contention_classification,
-                                                    user).and_return(true)
-        end
+          context 'with an MAS-related diagnostic code' do
+            let(:submission) do
+              create(:form526_submission,
+                     :non_rrd_with_mas_diagnostic_code,
+                     user_uuid: user.uuid,
+                     auth_headers_json: auth_headers.to_json,
+                     saved_claim_id: saved_claim.id)
+            end
+            let(:mas_cassette) { 'mail_automation/mas_initiate_apcas_request' }
+            let(:cassettes) do
+              [open_claims_cassette, rated_disabilities_cassette, submit_form_cassette, mas_cassette]
+            end
 
-        it 'calls the expanded classification endpoint' do
-          vro_client_mock = instance_double(VirtualRegionalOffice::Client)
-          allow(VirtualRegionalOffice::Client).to receive(:new).and_return(vro_client_mock)
-          allow(vro_client_mock).to receive_messages(
-            classify_vagov_contentions_expanded: OpenStruct.new(body: 'expanded classification'),
-            classify_vagov_contentions: OpenStruct.new(body: 'regular response')
-          )
+            before do
+              allow(StatsD).to receive(:increment)
+            end
 
-          expect_any_instance_of(Form526Submission).to receive(:classify_vagov_contentions).and_call_original
-          expect(vro_client_mock).to receive(:classify_vagov_contentions_expanded)
-          subject.perform_async(submission.id)
-          described_class.drain
-        end
+            it 'sends form526 to the MAS endpoint successfully' do
+              subject.perform_async(submission.id)
+              described_class.drain
+              expect(Form526JobStatus.last.status).to eq 'success'
+              rrd_submission = Form526Submission.find(Form526JobStatus.last.form526_submission_id)
+              expect(rrd_submission.form.dig('rrd_metadata', 'mas_packetId')).to eq '12345'
+              expect(StatsD).to have_received(:increment)
+                .with('worker.rapid_ready_for_decision.notify_mas.success').once
+            end
 
-        it 'uses expanded classification to classify contentions' do
-          subject.perform_async(submission.id)
-          expect do
-            VCR.use_cassette('virtual_regional_office/expanded_classification') do
+            it 'sends an email for tracking purposes' do
+              subject.perform_async(submission.id)
               described_class.drain
+              expect(ActionMailer::Base.deliveries.last.subject).to eq 'MA claim - 6847'
             end
-          end.not_to change(Sidekiq::Form526BackupSubmissionProcess::Submit.jobs, :size)
-          submission.reload
 
-          classification_codes = submission.form['form526']['form526']['disabilities'].pluck('classificationCode')
-          expect(classification_codes).to eq([9012, 8994, nil, 8997])
-        end
-      end
+            context 'when MAS endpoint handshake fails' do
+              let(:mas_cassette) { 'mail_automation/mas_initiate_apcas_request_failure' }
 
-      context 'when the disabilities array is empty' do
-        before do
-          allow(Rails.logger).to receive(:info)
-        end
+              it 'handles MAS endpoint handshake failure by sending failure notification' do
+                subject.perform_async(submission.id)
+                described_class.drain
+                expect(ActionMailer::Base.deliveries.last.subject).to eq "Failure: MA claim - #{submitted_claim_id}"
+                expect(StatsD).to have_received(:increment)
+                  .with('worker.rapid_ready_for_decision.notify_mas.failure').once
+              end
+            end
 
-        let(:submission) do
-          create(:form526_submission,
-                 :with_empty_disabilities,
-                 user_uuid: user.uuid,
-                 auth_headers_json: auth_headers.to_json,
-                 saved_claim_id: saved_claim.id)
-        end
+            context 'MAS-related claim that already includes classification code' do
+              let(:submission) do
+                create(:form526_submission,
+                       :mas_diagnostic_code_with_classification,
+                       user_uuid: user.uuid,
+                       auth_headers_json: auth_headers.to_json,
+                       saved_claim_id: saved_claim.id)
+              end
 
-        it 'returns false to skip classification and continue other jobs' do
-          subject.perform_async(submission.id)
-          expect(submission.update_contention_classification_all!).to eq false
-          expect(Rails.logger).to have_received(:info).with(
-            "No disabilities found for classification on claim #{submission.id}"
-          )
-        end
+              it 'already includes classification code and does not modify' do
+                subject.perform_async(submission.id)
+                described_class.drain
+                mas_submission = Form526Submission.find(Form526JobStatus.last.form526_submission_id)
+                expect(mas_submission.form.dig('form526', 'form526',
+                                               'disabilities').first['classificationCode']).to eq '8935'
+              end
+            end
 
-        it 'does not call va-gov-claim-classifier' do
-          subject.perform_async(submission.id)
-          described_class.drain
-          expect(submission).not_to receive(:classify_vagov_contentions)
-        end
-      end
-    end
+            context 'when the rated disability has decision code NOTSVCCON in EVSS' do
+              let(:rated_disabilities_cassette) do
+                'evss/disability_compensation_form/rated_disabilities_with_non_service_connected'
+              end
 
-    context 'with a successful submission job' do
-      it 'queues a job for submit' do
-        expect do
-          subject.perform_async(submission.id)
-        end.to change(subject.jobs, :size).by(1)
-      end
+              it 'skips forwarding to MAS' do
+                subject.perform_async(submission.id)
+                described_class.drain
+                expect(Form526JobStatus.last.status).to eq 'success'
+                rrd_submission = Form526Submission.find(submission.id)
+                expect(rrd_submission.form.dig('rrd_metadata', 'mas_packetId')).to be_nil
+              end
+            end
+          end
 
-      it 'submits successfully' do
-        subject.perform_async(submission.id)
-        expect { described_class.drain }.not_to change(backup_klass.jobs, :size)
-        expect(Form526JobStatus.last.status).to eq 'success'
-      end
+          context 'with multiple MAS-related diagnostic codes' do
+            let(:submission) do
+              create(:form526_submission,
+                     :with_multiple_mas_diagnostic_code,
+                     user_uuid: user.uuid,
+                     auth_headers_json: auth_headers.to_json,
+                     saved_claim_id: saved_claim.id)
+            end
 
-      it 'submits successfully without calling classification service' do
-        subject.perform_async(submission.id)
-        expect do
-          VCR.use_cassette('virtual_regional_office/multi_contention_classification') do
-            described_class.drain
+            context 'when tracking and APCAS notification are enabled for all claims' do
+              it 'calls APCAS and sends two emails' do
+                VCR.use_cassette('mail_automation/mas_initiate_apcas_request') do
+                  subject.perform_async(submission.id)
+                end
+                described_class.drain
+                expect(ActionMailer::Base.deliveries.length).to eq 2
+              end
+            end
           end
-        end.not_to change(backup_klass.jobs, :size)
-        expect(Form526JobStatus.last.status).to eq 'success'
-      end
 
-      it 'does not call contention classification endpoint' do
-        subject.perform_async(submission.id)
-        expect(submission).not_to receive(:classify_vagov_contentions)
-        described_class.drain
-      end
+          context 'with Lighthouse as submission provider' do
+            let(:submission) do
+              create(:form526_submission,
+                     :with_everything,
+                     user_uuid: user.uuid,
+                     auth_headers_json: auth_headers.to_json,
+                     saved_claim_id: saved_claim.id,
+                     submit_endpoint: 'claims_api')
+            end
 
-      context 'with an MAS-related diagnostic code' do
-        let(:submission) do
-          create(:form526_submission,
-                 :non_rrd_with_mas_diagnostic_code,
-                 user_uuid: user.uuid,
-                 auth_headers_json: auth_headers.to_json,
-                 saved_claim_id: saved_claim.id)
-        end
-        let(:mas_cassette) { 'mail_automation/mas_initiate_apcas_request' }
-        let(:cassettes) do
-          [open_claims_cassette, rated_disabilities_cassette, submit_form_cassette, mas_cassette]
-        end
+            let(:headers) { { 'content-type' => 'application/json' } }
 
-        before do
-          allow(StatsD).to receive(:increment)
-        end
+            before do
+              allow_any_instance_of(Auth::ClientCredentials::Service).to receive(:get_token)
+                .and_return('fake_access_token')
+            end
 
-        it 'sends form526 to the MAS endpoint successfully' do
-          subject.perform_async(submission.id)
-          described_class.drain
-          expect(Form526JobStatus.last.status).to eq 'success'
-          rrd_submission = Form526Submission.find(Form526JobStatus.last.form526_submission_id)
-          expect(rrd_submission.form.dig('rrd_metadata', 'mas_packetId')).to eq '12345'
-          expect(StatsD).to have_received(:increment).with('worker.rapid_ready_for_decision.notify_mas.success').once
-        end
+            it 'performs a successful submission' do
+              subject.perform_async(submission.id)
+              expect { described_class.drain }.not_to change(backup_klass.jobs, :size)
+              expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:success]
+              submission.reload
+              expect(submission.submitted_claim_id).to eq(Form526JobStatus.last.submission.submitted_claim_id)
+            end
 
-        it 'sends an email for tracking purposes' do
-          subject.perform_async(submission.id)
-          described_class.drain
-          expect(ActionMailer::Base.deliveries.last.subject).to eq 'MA claim - 6847'
-        end
+            it 'retries UpstreamUnprocessableEntity errors' do
+              body = { 'errors' => [{ 'status' => '422', 'title' => 'Backend Service Exception',
+                                      'detail' => 'The claim failed to establish' }] }
+
+              allow_any_instance_of(BenefitsClaims::Service).to receive(:prepare_submission_body)
+                .and_raise(Faraday::UnprocessableEntityError.new(
+                             body:,
+                             status: 422,
+                             headers:
+                           ))
+              expect_retryable_error(Common::Exceptions::UpstreamUnprocessableEntity)
+            end
 
-        context 'when MAS endpoint handshake fails' do
-          let(:mas_cassette) { 'mail_automation/mas_initiate_apcas_request_failure' }
+            it 'does not retry UnprocessableEntity errors with "pointer" defined' do
+              body = { 'errors' => [{ 'status' => '422', 'title' => 'Backend Service Exception',
+                                      'detail' => 'The claim failed to establish',
+                                      'source' => { 'pointer' => 'data/attributes/' } }] }
+              allow_any_instance_of(BenefitsClaims::Service).to receive(:prepare_submission_body)
+                .and_raise(Faraday::UnprocessableEntityError.new(
+                             body:, status: 422, headers:
+                           ))
+              expect_non_retryable_error
+            end
 
-          it 'handles MAS endpoint handshake failure by sending failure notification' do
-            subject.perform_async(submission.id)
-            described_class.drain
-            expect(ActionMailer::Base.deliveries.last.subject).to eq "Failure: MA claim - #{submitted_claim_id}"
-            expect(StatsD).to have_received(:increment).with('worker.rapid_ready_for_decision.notify_mas.failure').once
+            it 'does not retry UnprocessableEntity errors with "retries will fail" in detail message' do
+              body = { 'errors' => [{ 'status' => '422', 'title' => 'Backend Service Exception',
+                                      'detail' => 'The claim failed to establish. rEtries WilL fAiL.' }] }
+              allow_any_instance_of(BenefitsClaims::Service).to receive(:prepare_submission_body)
+                .and_raise(Faraday::UnprocessableEntityError.new(
+                             body:, status: 422, headers:
+                           ))
+              expect_non_retryable_error
+            end
+
+            Lighthouse::ServiceException::ERROR_MAP.slice(429, 499, 500, 501, 502, 503).each do |status, error_class|
+              it "throws a #{status} error if Lighthouse sends it back" do
+                allow_any_instance_of(Form526Submission).to receive(:prepare_for_evss!).and_return(nil)
+                allow_any_instance_of(BenefitsClaims::Service).to receive(:prepare_submission_body)
+                  .and_raise(error_class.new(status:))
+                expect_retryable_error(error_class)
+              end
+
+              it "throws a #{status} error if Lighthouse sends it back for rated disabilities" do
+                allow_any_instance_of(Flipper)
+                  .to(receive(:enabled?))
+                  .with('disability_compensation_lighthouse_rated_disabilities_provider_background', anything)
+                  .and_return(true)
+                allow_any_instance_of(Flipper)
+                  .to(receive(:enabled?))
+                  .with(:validate_saved_claims_with_json_schemer)
+                  .and_return(false)
+                allow_any_instance_of(EVSS::DisabilityCompensationForm::SubmitForm526)
+                  .to(receive(:fail_submission_feature_enabled?))
+                  .and_return(false)
+                allow_any_instance_of(Form526ClaimFastTrackingConcern).to receive(:prepare_for_ep_merge!)
+                  .and_return(nil)
+                allow_any_instance_of(Form526ClaimFastTrackingConcern).to receive(:pending_eps?)
+                  .and_return(false)
+                allow_any_instance_of(Form526ClaimFastTrackingConcern).to receive(:classify_vagov_contentions)
+                  .and_return(nil)
+                allow_any_instance_of(VeteranVerification::Service).to receive(:get_rated_disabilities)
+                  .and_raise(error_class.new(status:))
+                expect_retryable_error(error_class)
+              end
+            end
           end
         end
 
-        context 'MAS-related claim that already includes classification code' do
+        context 'with non-MAS-related diagnostic code' do
           let(:submission) do
             create(:form526_submission,
-                   :mas_diagnostic_code_with_classification,
+                   :with_uploads,
                    user_uuid: user.uuid,
                    auth_headers_json: auth_headers.to_json,
                    saved_claim_id: saved_claim.id)
           end
 
-          it 'already includes classification code and does not modify' do
+          it 'does not set a classification code for irrelevant claims' do
             subject.perform_async(submission.id)
             described_class.drain
             mas_submission = Form526Submission.find(Form526JobStatus.last.form526_submission_id)
@@ -594,275 +756,141 @@ def submit_it
           end
         end
 
-        context 'when the rated disability has decision code NOTSVCCON in EVSS' do
-          let(:rated_disabilities_cassette) do
-            'evss/disability_compensation_form/rated_disabilities_with_non_service_connected'
-          end
-
-          it 'skips forwarding to MAS' do
+        context 'when retrying a job' do
+          it 'doesnt recreate the job status' do
             subject.perform_async(submission.id)
+
+            jid = subject.jobs.last['jid']
+            values = {
+              form526_submission_id: submission.id,
+              job_id: jid,
+              job_class: subject.class,
+              status: Form526JobStatus::STATUS[:try],
+              updated_at: Time.now.utc
+            }
+            Form526JobStatus.upsert(values, unique_by: :job_id)
+            expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to(
+              receive(:increment_success).with(false, 'evss').once
+            )
             described_class.drain
-            expect(Form526JobStatus.last.status).to eq 'success'
-            rrd_submission = Form526Submission.find(submission.id)
-            expect(rrd_submission.form.dig('rrd_metadata', 'mas_packetId')).to be_nil
+            job_status = Form526JobStatus.where(job_id: values[:job_id]).first
+            expect(job_status.status).to eq 'success'
+            expect(job_status.error_class).to eq nil
+            expect(job_status.job_class).to eq 'SubmitForm526AllClaim'
+            expect(Form526JobStatus.count).to eq 1
           end
         end
-      end
-
-      context 'with multiple MAS-related diagnostic codes' do
-        let(:submission) do
-          create(:form526_submission,
-                 :with_multiple_mas_diagnostic_code,
-                 user_uuid: user.uuid,
-                 auth_headers_json: auth_headers.to_json,
-                 saved_claim_id: saved_claim.id)
-        end
 
-        context 'when tracking and APCAS notification are enabled for all claims' do
-          it 'calls APCAS and sends two emails' do
-            VCR.use_cassette('mail_automation/mas_initiate_apcas_request') do
+        context 'with an upstream service error for EP code not valid' do
+          it 'sets the transaction to "non_retryable_error"' do
+            VCR.use_cassette('evss/disability_compensation_form/submit_200_with_ep_not_valid') do
               subject.perform_async(submission.id)
+              expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics)
+                .to receive(:increment_non_retryable).once
+              expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
+              expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
+              expect(backup_klass.jobs.last['class']).to eq(backup_klass.to_s)
             end
-            described_class.drain
-            expect(ActionMailer::Base.deliveries.length).to eq 2
           end
         end
-      end
-
-      context 'with Lighthouse as submission provider' do
-        let(:submission) do
-          create(:form526_submission,
-                 :with_everything,
-                 user_uuid: user.uuid,
-                 auth_headers_json: auth_headers.to_json,
-                 saved_claim_id: saved_claim.id,
-                 submit_endpoint: 'claims_api')
-        end
-
-        let(:headers) { { 'content-type' => 'application/json' } }
-
-        before do
-          allow_any_instance_of(Auth::ClientCredentials::Service).to receive(:get_token).and_return('fake_access_token')
-        end
-
-        it 'performs a successful submission' do
-          subject.perform_async(submission.id)
-          expect { described_class.drain }.not_to change(backup_klass.jobs, :size)
-          expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:success]
-          submission.reload
-          expect(submission.submitted_claim_id).to eq(Form526JobStatus.last.submission.submitted_claim_id)
-        end
 
-        it 'retries UpstreamUnprocessableEntity errors' do
-          body = { 'errors' => [{ 'status' => '422', 'title' => 'Backend Service Exception',
-                                  'detail' => 'The claim failed to establish' }] }
-
-          allow_any_instance_of(BenefitsClaims::Service).to receive(:prepare_submission_body)
-            .and_raise(Faraday::UnprocessableEntityError.new(
-                         body:,
-                         status: 422,
-                         headers:
-                       ))
-          expect_retryable_error(Common::Exceptions::UpstreamUnprocessableEntity)
-        end
-
-        it 'does not retry UnprocessableEntity errors with "pointer" defined' do
-          body = { 'errors' => [{ 'status' => '422', 'title' => 'Backend Service Exception',
-                                  'detail' => 'The claim failed to establish',
-                                  'source' => { 'pointer' => 'data/attributes/' } }] }
-          allow_any_instance_of(BenefitsClaims::Service).to receive(:prepare_submission_body)
-            .and_raise(Faraday::UnprocessableEntityError.new(
-                         body:, status: 422, headers:
-                       ))
-          expect_non_retryable_error
-        end
-
-        it 'does not retry UnprocessableEntity errors with "retries will fail" in detail message' do
-          body = { 'errors' => [{ 'status' => '422', 'title' => 'Backend Service Exception',
-                                  'detail' => 'The claim failed to establish. rEtries WilL fAiL.' }] }
-          allow_any_instance_of(BenefitsClaims::Service).to receive(:prepare_submission_body)
-            .and_raise(Faraday::UnprocessableEntityError.new(
-                         body:, status: 422, headers:
-                       ))
-          expect_non_retryable_error
-        end
-
-        Lighthouse::ServiceException::ERROR_MAP.slice(429, 499, 500, 501, 502, 503).each do |status, error_class|
-          it "throws a #{status} error if Lighthouse sends it back" do
-            allow_any_instance_of(Form526Submission).to receive(:prepare_for_evss!).and_return(nil)
-            allow_any_instance_of(BenefitsClaims::Service).to receive(:prepare_submission_body)
-              .and_raise(error_class.new(status:))
-            expect_retryable_error(error_class)
-          end
-
-          it "throws a #{status} error if Lighthouse sends it back for rated disabilities" do
-            allow_any_instance_of(Flipper)
-              .to(receive(:enabled?))
-              .with('disability_compensation_lighthouse_rated_disabilities_provider_background', anything)
-              .and_return(true)
-            allow_any_instance_of(EVSS::DisabilityCompensationForm::SubmitForm526)
-              .to(receive(:fail_submission_feature_enabled?))
-              .and_return(false)
-            allow_any_instance_of(Form526ClaimFastTrackingConcern).to receive(:prepare_for_ep_merge!).and_return(nil)
-            allow_any_instance_of(Form526ClaimFastTrackingConcern).to receive(:pending_eps?).and_return(false)
-            allow_any_instance_of(Form526ClaimFastTrackingConcern).to receive(:classify_vagov_contentions)
-              .and_return(nil)
-            allow_any_instance_of(VeteranVerification::Service).to receive(:get_rated_disabilities)
-              .and_raise(error_class.new(status:))
-            expect_retryable_error(error_class)
+        context 'with a max ep code server error' do
+          it 'sets the transaction to "non_retryable_error"' do
+            VCR.use_cassette('evss/disability_compensation_form/submit_500_with_max_ep_code') do
+              subject.perform_async(submission.id)
+              expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics)
+                .to receive(:increment_non_retryable).once
+              expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
+              expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
+              expect(backup_klass.jobs.last['class']).to eq(backup_klass.to_s)
+            end
           end
         end
-      end
-    end
 
-    context 'with non-MAS-related diagnostic code' do
-      let(:submission) do
-        create(:form526_submission,
-               :with_uploads,
-               user_uuid: user.uuid,
-               auth_headers_json: auth_headers.to_json,
-               saved_claim_id: saved_claim.id)
-      end
-
-      it 'does not set a classification code for irrelevant claims' do
-        subject.perform_async(submission.id)
-        described_class.drain
-        mas_submission = Form526Submission.find(Form526JobStatus.last.form526_submission_id)
-        expect(mas_submission.form.dig('form526', 'form526',
-                                       'disabilities').first['classificationCode']).to eq '8935'
-      end
-    end
-
-    context 'when retrying a job' do
-      it 'doesnt recreate the job status' do
-        subject.perform_async(submission.id)
-
-        jid = subject.jobs.last['jid']
-        values = {
-          form526_submission_id: submission.id,
-          job_id: jid,
-          job_class: subject.class,
-          status: Form526JobStatus::STATUS[:try],
-          updated_at: Time.now.utc
-        }
-        Form526JobStatus.upsert(values, unique_by: :job_id)
-        expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to(
-          receive(:increment_success).with(false, 'evss').once
-        )
-        described_class.drain
-        job_status = Form526JobStatus.where(job_id: values[:job_id]).first
-        expect(job_status.status).to eq 'success'
-        expect(job_status.error_class).to eq nil
-        expect(job_status.job_class).to eq 'SubmitForm526AllClaim'
-        expect(Form526JobStatus.count).to eq 1
-      end
-    end
-
-    context 'with an upstream service error for EP code not valid' do
-      it 'sets the transaction to "non_retryable_error"' do
-        VCR.use_cassette('evss/disability_compensation_form/submit_200_with_ep_not_valid') do
-          subject.perform_async(submission.id)
-          expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_non_retryable).once
-          expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
-          expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
-          expect(backup_klass.jobs.last['class']).to eq(backup_klass.to_s)
+        context 'with a unused [418] error' do
+          it 'sets the transaction to "retryable_error"' do
+            VCR.use_cassette('evss/disability_compensation_form/submit_200_with_418') do
+              backup_jobs_count = backup_klass.jobs.count
+              subject.perform_async(submission.id)
+              expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_retryable).once
+              expect { described_class.drain }.to raise_error(EVSS::DisabilityCompensationForm::ServiceException)
+                .and not_change(backup_klass.jobs, :size)
+              expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:retryable_error]
+              expect(backup_klass.jobs.count).to eq(backup_jobs_count)
+            end
+          end
         end
-      end
-    end
 
-    context 'with a max ep code server error' do
-      it 'sets the transaction to "non_retryable_error"' do
-        VCR.use_cassette('evss/disability_compensation_form/submit_500_with_max_ep_code') do
-          subject.perform_async(submission.id)
-          expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_non_retryable).once
-          expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
-          expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
-          expect(backup_klass.jobs.last['class']).to eq(backup_klass.to_s)
+        context 'with a BGS error' do
+          it 'sets the transaction to "retryable_error"' do
+            VCR.use_cassette('evss/disability_compensation_form/submit_200_with_bgs_error') do
+              subject.perform_async(submission.id)
+              expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_retryable).once
+              expect { described_class.drain }.to raise_error(EVSS::DisabilityCompensationForm::ServiceException)
+                .and not_change(backup_klass.jobs, :size)
+              expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:retryable_error]
+            end
+          end
         end
-      end
-    end
 
-    context 'with a unused [418] error' do
-      it 'sets the transaction to "retryable_error"' do
-        VCR.use_cassette('evss/disability_compensation_form/submit_200_with_418') do
-          backup_jobs_count = backup_klass.jobs.count
-          subject.perform_async(submission.id)
-          expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_retryable).once
-          expect { described_class.drain }.to raise_error(EVSS::DisabilityCompensationForm::ServiceException)
-            .and not_change(backup_klass.jobs, :size)
-          expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:retryable_error]
-          expect(backup_klass.jobs.count).to eq(backup_jobs_count)
+        context 'with a pif in use server error' do
+          it 'sets the transaction to "non_retryable_error"' do
+            VCR.use_cassette('evss/disability_compensation_form/submit_500_with_pif_in_use') do
+              subject.perform_async(submission.id)
+              expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics)
+                .to receive(:increment_non_retryable).once
+              expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
+              expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
+              expect(backup_klass.jobs.last['class']).to eq(backup_klass.to_s)
+            end
+          end
         end
-      end
-    end
 
-    context 'with a BGS error' do
-      it 'sets the transaction to "retryable_error"' do
-        VCR.use_cassette('evss/disability_compensation_form/submit_200_with_bgs_error') do
-          subject.perform_async(submission.id)
-          expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_retryable).once
-          expect { described_class.drain }.to raise_error(EVSS::DisabilityCompensationForm::ServiceException)
-            .and not_change(backup_klass.jobs, :size)
-          expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:retryable_error]
+        context 'with a VeteranRecordWsClientException java error' do
+          it 'sets the transaction to "retryable_error"' do
+            VCR.use_cassette('evss/disability_compensation_form/submit_500_with_java_ws_error') do
+              subject.perform_async(submission.id)
+              expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_retryable).once
+              expect { described_class.drain }.to raise_error(EVSS::DisabilityCompensationForm::ServiceException)
+              expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:retryable_error]
+            end
+          end
         end
-      end
-    end
 
-    context 'with a pif in use server error' do
-      it 'sets the transaction to "non_retryable_error"' do
-        VCR.use_cassette('evss/disability_compensation_form/submit_500_with_pif_in_use') do
-          subject.perform_async(submission.id)
-          expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_non_retryable).once
-          expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
-          expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
-          expect(backup_klass.jobs.last['class']).to eq(backup_klass.to_s)
+        context 'with an error that is not mapped' do
+          it 'sets the transaction to "non_retryable_error"' do
+            VCR.use_cassette('evss/disability_compensation_form/submit_500_with_unmapped') do
+              subject.perform_async(submission.id)
+              expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
+              expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
+            end
+          end
         end
-      end
-    end
 
-    context 'with a VeteranRecordWsClientException java error' do
-      it 'sets the transaction to "retryable_error"' do
-        VCR.use_cassette('evss/disability_compensation_form/submit_500_with_java_ws_error') do
-          subject.perform_async(submission.id)
-          expect_any_instance_of(Sidekiq::Form526JobStatusTracker::Metrics).to receive(:increment_retryable).once
-          expect { described_class.drain }.to raise_error(EVSS::DisabilityCompensationForm::ServiceException)
-          expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:retryable_error]
-        end
-      end
-    end
+        context 'with an unexpected error' do
+          before do
+            allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(StandardError.new('foo'))
+          end
 
-    context 'with an error that is not mapped' do
-      it 'sets the transaction to "non_retryable_error"' do
-        VCR.use_cassette('evss/disability_compensation_form/submit_500_with_unmapped') do
-          subject.perform_async(submission.id)
-          expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
-          expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
+          it 'sets the transaction to "non_retryable_error"' do
+            subject.perform_async(submission.id)
+            expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
+            expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
+          end
         end
-      end
-    end
-
-    context 'with an unexpected error' do
-      before do
-        allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(StandardError.new('foo'))
-      end
 
-      it 'sets the transaction to "non_retryable_error"' do
-        subject.perform_async(submission.id)
-        expect { described_class.drain }.to change(backup_klass.jobs, :size).by(1)
-        expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
-      end
-    end
-
-    context 'with an RRD claim' do
-      context 'with a non-retryable (unexpected) error' do
-        before do
-          allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(StandardError.new('foo'))
-        end
+        context 'with an RRD claim' do
+          context 'with a non-retryable (unexpected) error' do
+            before do
+              allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(StandardError.new('foo'))
+            end
 
-        it 'sends a "non-retryable" RRD alert' do
-          subject.perform_async(submission.id)
-          described_class.drain
-          expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
+            it 'sends a "non-retryable" RRD alert' do
+              subject.perform_async(submission.id)
+              described_class.drain
+              expect(Form526JobStatus.last.status).to eq Form526JobStatus::STATUS[:non_retryable_error]
+            end
+          end
         end
       end
     end
diff --git a/spec/sidekiq/form526_failure_state_snapshot_job_spec.rb b/spec/sidekiq/form526_failure_state_snapshot_job_spec.rb
index 6ebb7e00642..b60e5b1aed6 100644
--- a/spec/sidekiq/form526_failure_state_snapshot_job_spec.rb
+++ b/spec/sidekiq/form526_failure_state_snapshot_job_spec.rb
@@ -12,225 +12,234 @@
   let!(:end_date) { Time.zone.today.beginning_of_day }
   let!(:start_date) { end_date - 1.week }
 
-  describe '526 state logging' do
-    let!(:new_unprocessed) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission)
+  [true, false].each do |flipper_value|
+    context "when json_schemer flipper is #{flipper_value}" do
+      before do
+        allow(Flipper).to receive(:enabled?).and_call_original
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper_value)
       end
-    end
-    let!(:old_unprocessed) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission)
-      end
-    end
-    let!(:new_primary_success) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :with_submitted_claim_id, :with_one_succesful_job)
-      end
-    end
-    let!(:old_primary_success) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :with_submitted_claim_id, :with_one_succesful_job)
-      end
-    end
-    let!(:new_backup_pending) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :backup_path, :with_failed_primary_job)
-      end
-    end
-    let!(:old_backup_pending) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :backup_path, :with_failed_primary_job)
-      end
-    end
-    let!(:new_backup_success) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :backup_path, :paranoid_success, :with_failed_primary_job)
-      end
-    end
-    let!(:old_backup_success) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :backup_path, :paranoid_success, :with_failed_primary_job)
-      end
-    end
-    let!(:new_backup_vbms) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :backup_path, :backup_accepted, :with_failed_primary_job)
-      end
-    end
-    let!(:old_backup_vbms) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :backup_path, :backup_accepted, :with_failed_primary_job)
-      end
-    end
-    let!(:new_backup_rejected) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :backup_path, :backup_rejected, :with_failed_primary_job)
-      end
-    end
-    let!(:old_backup_rejected) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :backup_path, :backup_rejected, :with_failed_primary_job)
-      end
-    end
-    let!(:new_double_job_failure) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job)
-      end
-    end
-    let!(:old_double_job_failure) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job)
-      end
-    end
-    let!(:new_double_job_failure_remediated) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job, :remediated)
-      end
-    end
-    let!(:old_double_job_failure_remediated) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job, :remediated)
-      end
-    end
-    let!(:new_double_job_failure_de_remediated) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job, :no_longer_remediated)
-      end
-    end
-    let!(:old_double_job_failure_de_remediated) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job, :no_longer_remediated)
-      end
-    end
-    let!(:new_no_job_remediated) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :remediated)
-      end
-    end
-    let!(:old_no_job_remediated) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :remediated)
-      end
-    end
-    let!(:new_backup_paranoid) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :backup_path, :with_failed_primary_job, :paranoid_success)
-      end
-    end
-    let!(:old_backup_paranoid) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :backup_path, :with_failed_primary_job, :paranoid_success)
-      end
-    end
-    let!(:still_running_with_retryable_errors) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :with_one_failed_job)
-      end
-    end
-    # RARE EDGECASES
-    let!(:new_no_job_de_remediated) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :no_longer_remediated)
-      end
-    end
-    let!(:old_no_job_de_remediated) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :no_longer_remediated)
-      end
-    end
-    let!(:new_double_success) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :with_submitted_claim_id, :backup_path)
-      end
-    end
-    let!(:old_double_success) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :with_submitted_claim_id, :backup_path)
-      end
-    end
-    let!(:new_triple_success) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :with_submitted_claim_id, :backup_path, :remediated)
-      end
-    end
-    let!(:old_triple_success) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :with_submitted_claim_id, :backup_path, :remediated)
-      end
-    end
-    let!(:new_double_success_de_remediated) do
-      Timecop.freeze(modern_times) do
-        create(:form526_submission, :with_submitted_claim_id, :backup_path, :no_longer_remediated)
-      end
-    end
-    let!(:old_double_success_de_remediated) do
-      Timecop.freeze(olden_times) do
-        create(:form526_submission, :with_submitted_claim_id, :backup_path, :no_longer_remediated)
-      end
-    end
-    let!(:new_remediated_and_de_remediated) do
-      sub = Timecop.freeze(modern_times) do
-        create(:form526_submission, :remediated)
-      end
-      Timecop.freeze(modern_times + 1.hour) do
-        create(:form526_submission_remediation,
-               form526_submission: sub,
-               lifecycle: ['i am no longer remediated'],
-               success: false)
-      end
-      sub
-    end
-    let!(:old_remediated_and_de_remediated) do
-      sub = Timecop.freeze(olden_times) do
-        create(:form526_submission, :remediated)
-      end
-      Timecop.freeze(olden_times + 1.hour) do
-        create(:form526_submission_remediation,
-               form526_submission: sub,
-               lifecycle: ['i am no longer remediated'],
-               success: false)
-      end
-      sub
-    end
 
-    it 'logs 526 state metrics correctly' do
-      expected_log = {
-        total_awaiting_backup_status: [
-          new_backup_pending.id
-        ].sort,
-        total_incomplete_type: [
-          still_running_with_retryable_errors.id,
-          new_unprocessed.id,
-          new_backup_pending.id,
-          new_no_job_de_remediated.id,
-          new_remediated_and_de_remediated.id
-        ].sort,
-        total_failure_type: [
-          old_unprocessed.id,
-          old_backup_pending.id,
-          new_backup_rejected.id,
-          old_backup_rejected.id,
-          old_double_job_failure.id,
-          old_double_job_failure_de_remediated.id,
-          old_no_job_de_remediated.id,
-          old_remediated_and_de_remediated.id,
-          new_double_job_failure.id,
-          new_double_job_failure_de_remediated.id
-        ].sort
-      }
+      describe '526 state logging' do
+        let!(:new_unprocessed) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission)
+          end
+        end
+        let!(:old_unprocessed) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission)
+          end
+        end
+        let!(:new_primary_success) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :with_submitted_claim_id, :with_one_succesful_job)
+          end
+        end
+        let!(:old_primary_success) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :with_submitted_claim_id, :with_one_succesful_job)
+          end
+        end
+        let!(:new_backup_pending) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :backup_path, :with_failed_primary_job)
+          end
+        end
+        let!(:old_backup_pending) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :backup_path, :with_failed_primary_job)
+          end
+        end
+        let!(:new_backup_success) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :backup_path, :paranoid_success, :with_failed_primary_job)
+          end
+        end
+        let!(:old_backup_success) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :backup_path, :paranoid_success, :with_failed_primary_job)
+          end
+        end
+        let!(:new_backup_vbms) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :backup_path, :backup_accepted, :with_failed_primary_job)
+          end
+        end
+        let!(:old_backup_vbms) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :backup_path, :backup_accepted, :with_failed_primary_job)
+          end
+        end
+        let!(:new_backup_rejected) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :backup_path, :backup_rejected, :with_failed_primary_job)
+          end
+        end
+        let!(:old_backup_rejected) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :backup_path, :backup_rejected, :with_failed_primary_job)
+          end
+        end
+        let!(:new_double_job_failure) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job)
+          end
+        end
+        let!(:old_double_job_failure) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job)
+          end
+        end
+        let!(:new_double_job_failure_remediated) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job, :remediated)
+          end
+        end
+        let!(:old_double_job_failure_remediated) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job, :remediated)
+          end
+        end
+        let!(:new_double_job_failure_de_remediated) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job, :no_longer_remediated)
+          end
+        end
+        let!(:old_double_job_failure_de_remediated) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :with_failed_primary_job, :with_failed_backup_job, :no_longer_remediated)
+          end
+        end
+        let!(:new_no_job_remediated) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :remediated)
+          end
+        end
+        let!(:old_no_job_remediated) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :remediated)
+          end
+        end
+        let!(:new_backup_paranoid) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :backup_path, :with_failed_primary_job, :paranoid_success)
+          end
+        end
+        let!(:old_backup_paranoid) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :backup_path, :with_failed_primary_job, :paranoid_success)
+          end
+        end
+        let!(:still_running_with_retryable_errors) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :with_one_failed_job)
+          end
+        end
+        # RARE EDGECASES
+        let!(:new_no_job_de_remediated) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :no_longer_remediated)
+          end
+        end
+        let!(:old_no_job_de_remediated) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :no_longer_remediated)
+          end
+        end
+        let!(:new_double_success) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :with_submitted_claim_id, :backup_path)
+          end
+        end
+        let!(:old_double_success) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :with_submitted_claim_id, :backup_path)
+          end
+        end
+        let!(:new_triple_success) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :with_submitted_claim_id, :backup_path, :remediated)
+          end
+        end
+        let!(:old_triple_success) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :with_submitted_claim_id, :backup_path, :remediated)
+          end
+        end
+        let!(:new_double_success_de_remediated) do
+          Timecop.freeze(modern_times) do
+            create(:form526_submission, :with_submitted_claim_id, :backup_path, :no_longer_remediated)
+          end
+        end
+        let!(:old_double_success_de_remediated) do
+          Timecop.freeze(olden_times) do
+            create(:form526_submission, :with_submitted_claim_id, :backup_path, :no_longer_remediated)
+          end
+        end
+        let!(:new_remediated_and_de_remediated) do
+          sub = Timecop.freeze(modern_times) do
+            create(:form526_submission, :remediated)
+          end
+          Timecop.freeze(modern_times + 1.hour) do
+            create(:form526_submission_remediation,
+                   form526_submission: sub,
+                   lifecycle: ['i am no longer remediated'],
+                   success: false)
+          end
+          sub
+        end
+        let!(:old_remediated_and_de_remediated) do
+          sub = Timecop.freeze(olden_times) do
+            create(:form526_submission, :remediated)
+          end
+          Timecop.freeze(olden_times + 1.hour) do
+            create(:form526_submission_remediation,
+                   form526_submission: sub,
+                   lifecycle: ['i am no longer remediated'],
+                   success: false)
+          end
+          sub
+        end
 
-      expect(described_class.new.snapshot_state).to eq(expected_log)
-    end
+        it 'logs 526 state metrics correctly' do
+          expected_log = {
+            total_awaiting_backup_status: [
+              new_backup_pending.id
+            ].sort,
+            total_incomplete_type: [
+              still_running_with_retryable_errors.id,
+              new_unprocessed.id,
+              new_backup_pending.id,
+              new_no_job_de_remediated.id,
+              new_remediated_and_de_remediated.id
+            ].sort,
+            total_failure_type: [
+              old_unprocessed.id,
+              old_backup_pending.id,
+              new_backup_rejected.id,
+              old_backup_rejected.id,
+              old_double_job_failure.id,
+              old_double_job_failure_de_remediated.id,
+              old_no_job_de_remediated.id,
+              old_remediated_and_de_remediated.id,
+              new_double_job_failure.id,
+              new_double_job_failure_de_remediated.id
+            ].sort
+          }
 
-    it 'writes counts as Stats D gauges' do
-      prefix = described_class::STATSD_PREFIX
+          expect(described_class.new.snapshot_state).to eq(expected_log)
+        end
 
-      expect(StatsD).to receive(:gauge).with("#{prefix}.total_awaiting_backup_status_count", 1)
-      expect(StatsD).to receive(:gauge).with("#{prefix}.total_incomplete_type_count", 5)
-      expect(StatsD).to receive(:gauge).with("#{prefix}.total_failure_type_count", 10)
+        it 'writes counts as Stats D gauges' do
+          prefix = described_class::STATSD_PREFIX
 
-      described_class.new.perform
+          expect(StatsD).to receive(:gauge).with("#{prefix}.total_awaiting_backup_status_count", 1)
+          expect(StatsD).to receive(:gauge).with("#{prefix}.total_incomplete_type_count", 5)
+          expect(StatsD).to receive(:gauge).with("#{prefix}.total_failure_type_count", 10)
+
+          described_class.new.perform
+        end
+      end
     end
   end
 end
diff --git a/spec/sidekiq/lighthouse/form526_document_upload_polling_job_spec.rb b/spec/sidekiq/lighthouse/form526_document_upload_polling_job_spec.rb
index 7f433d69eaa..239cd645a9e 100644
--- a/spec/sidekiq/lighthouse/form526_document_upload_polling_job_spec.rb
+++ b/spec/sidekiq/lighthouse/form526_document_upload_polling_job_spec.rb
@@ -18,287 +18,300 @@
     allow_any_instance_of(BenefitsDocuments::Configuration).to receive(:access_token).and_return('abcd1234')
   end
 
-  describe '#perform' do
-    shared_examples 'document status updates' do |state, request_id, cassette|
-      around { |example| VCR.use_cassette(cassette, match_requests_on: [:body]) { example.run } }
-
-      let!(:document) { create(:lighthouse526_document_upload, lighthouse_document_request_id: request_id) }
-
-      it 'updates document status' do
-        described_class.new.perform
-        expect(document.reload.aasm_state).to eq(state)
-        expect(document.reload.lighthouse_processing_ended_at).not_to be_nil
-        expect(document.reload.last_status_response).not_to be_nil
-      end
-
-      it 'saves the status_last_polled_at time' do
-        polling_time = DateTime.new(1985, 10, 26).utc
-        Timecop.freeze(polling_time) do
-          described_class.new.perform
-          expect(document.reload.status_last_polled_at).to eq(polling_time)
-        end
+  [true, false].each do |flipper_value|
+    context "when json_schemer flipper is #{flipper_value}" do
+      before do
+        allow(Flipper).to receive(:enabled?).and_call_original
+        allow(Flipper).to receive(:enabled?).with(:validate_saved_claims_with_json_schemer).and_return(flipper_value)
       end
-    end
-
-    # End-to-end integration test - completion
-    context 'for a document that has completed' do
-      # Completed Lighthouse QA environment document requestId provided by Lighthouse for end-to-end testing
-      it_behaves_like 'document status updates', 'completed', '22',
-                      'lighthouse/benefits_claims/documents/form526_document_upload_status_complete'
-    end
-
-    context 'for a document that has failed' do
-      # Failed Lighthouse QA environment document requestId provided by Lighthouse for end-to-end testing
-      it_behaves_like 'document status updates', 'failed', '16819',
-                      'lighthouse/benefits_claims/documents/form526_document_upload_status_failed'
-    end
 
-    context 'for a single document request whose status is not found' do
-      # Non-existent Lighthouse QA environment document requestId
-      let!(:unknown_document) { create(:lighthouse526_document_upload, lighthouse_document_request_id: '21') }
-      let(:error_body) do
-        { 'errors' => [{ 'detail' => 'Upload Request Async Status Not Found', 'status' => 404,
-                         'title' => 'Not Found', 'instance' => '062dd917-a229-42d7-ad39-741eb81766a8',
-                         'diagnostics' => '7YODuWbVvC0k+iFgaQC0SrlARmYKPKz4' }] }
-      end
+      describe '#perform' do
+        shared_examples 'document status updates' do |state, request_id, cassette|
+          around { |example| VCR.use_cassette(cassette, match_requests_on: [:body]) { example.run } }
 
-      around do |example|
-        VCR.use_cassette('lighthouse/benefits_claims/documents/form526_document_upload_status_not_found',
-                         match_requests_on: [:body]) do
-          example.run
-        end
-      end
+          let!(:document) { create(:lighthouse526_document_upload, lighthouse_document_request_id: request_id) }
 
-      it 'increments a StatsD counter and logs error' do
-        expect(StatsD).to receive(:increment).with('worker.lighthouse.poll_form526_document_uploads.polling_error')
+          it 'updates document status' do
+            described_class.new.perform
+            expect(document.reload.aasm_state).to eq(state)
+            expect(document.reload.lighthouse_processing_ended_at).not_to be_nil
+            expect(document.reload.last_status_response).not_to be_nil
+          end
 
-        Timecop.freeze(Time.new(1985, 10, 26).utc) do
-          expect(Rails.logger).to receive(:warn).with(
-            'Lighthouse::Form526DocumentUploadPollingJob status endpoint error',
-            hash_including(response_status: 404, response_body: error_body,
-                           lighthouse_document_request_ids: [unknown_document.lighthouse_document_request_id])
-          )
-          described_class.new.perform
+          it 'saves the status_last_polled_at time' do
+            polling_time = DateTime.new(1985, 10, 26).utc
+            Timecop.freeze(polling_time) do
+              described_class.new.perform
+              expect(document.reload.status_last_polled_at).to eq(polling_time)
+            end
+          end
         end
-      end
-    end
-
-    context 'for a document with status and another document whose request id is not found' do
-      let!(:complete_document) { create(:lighthouse526_document_upload, lighthouse_document_request_id: '22') }
-      let!(:unknown_document) { create(:lighthouse526_document_upload, lighthouse_document_request_id: '21') }
 
-      around do |example|
-        VCR.use_cassette('lighthouse/benefits_claims/documents/form526_document_upload_with_request_ids_not_found',
-                         match_requests_on: [:body]) do
-          example.run
+        # End-to-end integration test - completion
+        context 'for a document that has completed' do
+          # Completed Lighthouse QA environment document requestId provided by Lighthouse for end-to-end testing
+          it_behaves_like 'document status updates', 'completed', '22',
+                          'lighthouse/benefits_claims/documents/form526_document_upload_status_complete'
         end
-      end
 
-      it 'increments StatsD counters for both documents and logs unknown document error' do
-        expect(StatsD).to receive(:increment)
-          .with('api.form526.lighthouse_document_upload_processing_status.bdd_instructions.complete').ordered
-        expect(StatsD).to receive(:increment)
-          .with('worker.lighthouse.poll_form526_document_uploads.polling_error').ordered
-
-        Timecop.freeze(Time.new(1985, 10, 26).utc) do
-          expect(Rails.logger).to receive(:warn).with(
-            'Lighthouse::Form526DocumentUploadPollingJob status endpoint error',
-            hash_including(response_status: 404, response_body: 'Upload Request Async Status Not Found',
-                           lighthouse_document_request_ids: [unknown_document.lighthouse_document_request_id])
-          )
-          described_class.new.perform
+        context 'for a document that has failed' do
+          # Failed Lighthouse QA environment document requestId provided by Lighthouse for end-to-end testing
+          it_behaves_like 'document status updates', 'failed', '16819',
+                          'lighthouse/benefits_claims/documents/form526_document_upload_status_failed'
         end
-      end
-    end
-
-    context 'non-200 failure response from Lighthouse' do
-      let!(:pending_document) { create(:lighthouse526_document_upload) }
-      # Error body example from: https://dev-developer.va.gov/explore/api/benefits-documents/docs?version=current
-      let(:error_body) { { 'errors' => [{ 'detail' => 'Code must match \'^[A-Z]{2}$\'', 'status' => 400 }] } }
-      let(:error_response) { Faraday::Response.new(response_body: error_body, status: 400) }
 
-      before do
-        allow(BenefitsDocuments::Form526::DocumentsStatusPollingService).to receive(:call).and_return(error_response)
-      end
-
-      it 'increments a StatsD counter and logs error' do
-        expect(StatsD).to receive(:increment).with('worker.lighthouse.poll_form526_document_uploads.polling_error')
-
-        Timecop.freeze(Time.new(1985, 10, 26).utc) do
-          expect(Rails.logger).to receive(:warn).with(
-            'Lighthouse::Form526DocumentUploadPollingJob status endpoint error',
-            hash_including(response_status: 400, response_body: error_body,
-                           lighthouse_document_request_ids: [pending_document.lighthouse_document_request_id])
-          )
-          described_class.new.perform
-        end
-      end
-    end
+        context 'for a single document request whose status is not found' do
+          # Non-existent Lighthouse QA environment document requestId
+          let!(:unknown_document) { create(:lighthouse526_document_upload, lighthouse_document_request_id: '21') }
+          let(:error_body) do
+            { 'errors' => [{ 'detail' => 'Upload Request Async Status Not Found', 'status' => 404,
+                             'title' => 'Not Found', 'instance' => '062dd917-a229-42d7-ad39-741eb81766a8',
+                             'diagnostics' => '7YODuWbVvC0k+iFgaQC0SrlARmYKPKz4' }] }
+          end
 
-    context 'retries exhausted' do
-      it 'updates the exhaustion StatsD counter' do
-        described_class.within_sidekiq_retries_exhausted_block do
-          expect(StatsD).to receive(:increment).with('worker.lighthouse.poll_form526_document_uploads.exhausted')
-        end
-      end
+          around do |example|
+            VCR.use_cassette('lighthouse/benefits_claims/documents/form526_document_upload_status_not_found',
+                             match_requests_on: [:body]) do
+              example.run
+            end
+          end
 
-      it 'logs exhaustion metadata to the Rails logger' do
-        exhaustion_time = DateTime.new(1985, 10, 26).utc
-        sidekiq_exhaustion_metadata = { 'jid' => 8_675_309, 'error_class' => 'BROKESKI',
-                                        'error_message' => 'We are going to need a bigger boat' }
-        Timecop.freeze(exhaustion_time) do
-          described_class.within_sidekiq_retries_exhausted_block(sidekiq_exhaustion_metadata) do
-            expect(Rails.logger).to receive(:warn).with(
-              'Lighthouse::Form526DocumentUploadPollingJob retries exhausted',
-              {
-                job_id: 8_675_309,
-                error_class: 'BROKESKI',
-                error_message: 'We are going to need a bigger boat',
-                timestamp: exhaustion_time
-              }
-            )
+          it 'increments a StatsD counter and logs error' do
+            expect(StatsD).to receive(:increment).with('worker.lighthouse.poll_form526_document_uploads.polling_error')
+
+            Timecop.freeze(Time.new(1985, 10, 26).utc) do
+              expect(Rails.logger).to receive(:warn).with(
+                'Lighthouse::Form526DocumentUploadPollingJob status endpoint error',
+                hash_including(response_status: 404, response_body: error_body,
+                               lighthouse_document_request_ids: [unknown_document.lighthouse_document_request_id])
+              )
+              described_class.new.perform
+            end
           end
         end
-      end
-    end
-
-    describe 'Documents Polling' do
-      let(:faraday_response) { instance_double(Faraday::Response, body: {}, status: 200) }
-      let(:polling_service) { BenefitsDocuments::Form526::DocumentsStatusPollingService }
-      let(:polling_time) { DateTime.new(1985, 10, 26).utc }
-
-      before do
-        # Verifies correct info is being passed to both services
-        allow(BenefitsDocuments::Form526::DocumentsStatusPollingService).to receive(:call).and_return(faraday_response)
-        allow(BenefitsDocuments::Form526::UpdateDocumentsStatusService)
-          .to receive(:call).and_return(success: true, response: { status: 200 })
-      end
 
-      context 'for a pending document' do
-        around { |example| Timecop.freeze(polling_time) { example.run } }
+        context 'for a document with status and another document whose request id is not found' do
+          let!(:complete_document) { create(:lighthouse526_document_upload, lighthouse_document_request_id: '22') }
+          let!(:unknown_document) { create(:lighthouse526_document_upload, lighthouse_document_request_id: '21') }
 
-        it 'polls for unpolled and repoll documents' do
-          documents = [
-            create(:lighthouse526_document_upload),
-            create(:lighthouse526_document_upload, status_last_polled_at: polling_time - 2.hours)
-          ]
-          document_request_ids = documents.map(&:lighthouse_document_request_id)
+          around do |example|
+            VCR.use_cassette('lighthouse/benefits_claims/documents/form526_document_upload_with_request_ids_not_found',
+                             match_requests_on: [:body]) do
+              example.run
+            end
+          end
 
-          expect(polling_service).to receive(:call).with(document_request_ids)
-          described_class.new.perform
+          it 'increments StatsD counters for both documents and logs unknown document error' do
+            expect(StatsD).to receive(:increment)
+              .with('api.form526.lighthouse_document_upload_processing_status.bdd_instructions.complete').ordered
+            expect(StatsD).to receive(:increment)
+              .with('worker.lighthouse.poll_form526_document_uploads.polling_error').ordered
+
+            Timecop.freeze(Time.new(1985, 10, 26).utc) do
+              expect(Rails.logger).to receive(:warn).with(
+                'Lighthouse::Form526DocumentUploadPollingJob status endpoint error',
+                hash_including(response_status: 404, response_body: 'Upload Request Async Status Not Found',
+                               lighthouse_document_request_ids: [unknown_document.lighthouse_document_request_id])
+              )
+              described_class.new.perform
+            end
+          end
         end
 
-        it 'does not poll for recently polled documents' do
-          recently_polled_document = create(:lighthouse526_document_upload,
-                                            status_last_polled_at: polling_time - 42.minutes)
-          expect(polling_service).not_to receive(:call).with([recently_polled_document.lighthouse_document_request_id])
-          described_class.new.perform
-        end
-      end
+        context 'non-200 failure response from Lighthouse' do
+          let!(:pending_document) { create(:lighthouse526_document_upload) }
+          # Error body example from: https://dev-developer.va.gov/explore/api/benefits-documents/docs?version=current
+          let(:error_body) { { 'errors' => [{ 'detail' => 'Code must match \'^[A-Z]{2}$\'', 'status' => 400 }] } }
+          let(:error_response) { Faraday::Response.new(response_body: error_body, status: 400) }
 
-      context 'for completed and failed documents' do
-        let!(:documents) do
-          [
-            create(:lighthouse526_document_upload, aasm_state: 'completed',
-                                                   status_last_polled_at: polling_time - 2.hours),
-            create(:lighthouse526_document_upload, aasm_state: 'failed', status_last_polled_at: polling_time - 2.hours)
-          ]
-        end
+          before do
+            allow(BenefitsDocuments::Form526::DocumentsStatusPollingService)
+              .to receive(:call).and_return(error_response)
+          end
 
-        it 'does not poll for completed or failed documents' do
-          documents.each do |doc|
-            expect(polling_service).not_to receive(:call).with([doc.lighthouse_document_request_id])
+          it 'increments a StatsD counter and logs error' do
+            expect(StatsD).to receive(:increment).with('worker.lighthouse.poll_form526_document_uploads.polling_error')
+
+            Timecop.freeze(Time.new(1985, 10, 26).utc) do
+              expect(Rails.logger).to receive(:warn).with(
+                'Lighthouse::Form526DocumentUploadPollingJob status endpoint error',
+                hash_including(response_status: 400, response_body: error_body,
+                               lighthouse_document_request_ids: [pending_document.lighthouse_document_request_id])
+              )
+              described_class.new.perform
+            end
           end
-          described_class.new.perform
         end
-      end
-    end
 
-    describe 'Document Polling Logging' do
-      context 'for pending documents' do
-        let!(:pending_polling_documents) { create_list(:lighthouse526_document_upload, 2, aasm_state: 'pending') }
-        let!(:pending_recently_polled_document) do
-          create(
-            :lighthouse526_document_upload,
-            aasm_state: 'pending',
-            status_last_polled_at: polling_time - 45.minutes
-          )
-        end
+        context 'retries exhausted' do
+          it 'updates the exhaustion StatsD counter' do
+            described_class.within_sidekiq_retries_exhausted_block do
+              expect(StatsD).to receive(:increment).with('worker.lighthouse.poll_form526_document_uploads.exhausted')
+            end
+          end
 
-        let(:polling_time) { DateTime.new(1985, 10, 26).utc }
-        let(:faraday_response) do
-          instance_double(
-            Faraday::Response,
-            body: {
-              'data' => {
-                'statuses' => [
+          it 'logs exhaustion metadata to the Rails logger' do
+            exhaustion_time = DateTime.new(1985, 10, 26).utc
+            sidekiq_exhaustion_metadata = { 'jid' => 8_675_309, 'error_class' => 'BROKESKI',
+                                            'error_message' => 'We are going to need a bigger boat' }
+            Timecop.freeze(exhaustion_time) do
+              described_class.within_sidekiq_retries_exhausted_block(sidekiq_exhaustion_metadata) do
+                expect(Rails.logger).to receive(:warn).with(
+                  'Lighthouse::Form526DocumentUploadPollingJob retries exhausted',
                   {
-                    'requestId' => pending_polling_documents.first.lighthouse_document_request_id,
-                    'time' => {
-                      'startTime' => 1_502_199_000,
-                      'endTime' => 1_502_199_000
-                    },
-                    'status' => 'SUCCESS'
-                  }, {
-                    'requestId' => pending_polling_documents[1].lighthouse_document_request_id,
-                    'time' => {
-                      'startTime' => 1_502_199_000,
-                      'endTime' => 1_502_199_000
-                    },
-                    'status' => 'FAILED',
-                    'error' => {
-                      'detail' => 'Something went wrong',
-                      'step' => 'BENEFITS_GATEWAY_SERVICE'
-                    }
+                    job_id: 8_675_309,
+                    error_class: 'BROKESKI',
+                    error_message: 'We are going to need a bigger boat',
+                    timestamp: exhaustion_time
                   }
-                ],
-                'requestIdsNotFound' => [
-                  0
-                ]
-              }
-            },
-            status: 200
-          )
-        end
-
-        around { |example| Timecop.freeze(polling_time) { example.run } }
-
-        before do
-          allow(BenefitsDocuments::Form526::DocumentsStatusPollingService)
-            .to receive(:call).and_return(faraday_response)
-
-          # StatsD will receive multiple gauge calls in this code flow
-          allow(StatsD).to receive(:gauge)
-        end
-
-        describe 'polled documents metric' do
-          it 'increments a StatsD gauge metric with total documents polled, discluding recently polled documents' do
-            expect(StatsD).to receive(:gauge)
-              .with('worker.lighthouse.poll_form526_document_uploads.pending_documents_polled', 2)
-
-            described_class.new.perform
+                )
+              end
+            end
           end
         end
 
-        describe 'completed and failed documents' do
-          let!(:existing_completed_documents) do
-            create_list(:lighthouse526_document_upload, 2, aasm_state: 'completed')
+        describe 'Documents Polling' do
+          let(:faraday_response) { instance_double(Faraday::Response, body: {}, status: 200) }
+          let(:polling_service) { BenefitsDocuments::Form526::DocumentsStatusPollingService }
+          let(:polling_time) { DateTime.new(1985, 10, 26).utc }
+
+          before do
+            # Verifies correct info is being passed to both services
+            allow(BenefitsDocuments::Form526::DocumentsStatusPollingService)
+              .to receive(:call).and_return(faraday_response)
+            allow(BenefitsDocuments::Form526::UpdateDocumentsStatusService)
+              .to receive(:call).and_return(success: true, response: { status: 200 })
           end
 
-          let!(:existing_failed_documents) { create_list(:lighthouse526_document_upload, 2, aasm_state: 'failed') }
+          context 'for a pending document' do
+            around { |example| Timecop.freeze(polling_time) { example.run } }
+
+            it 'polls for unpolled and repoll documents' do
+              documents = [
+                create(:lighthouse526_document_upload),
+                create(:lighthouse526_document_upload, status_last_polled_at: polling_time - 2.hours)
+              ]
+              document_request_ids = documents.map(&:lighthouse_document_request_id)
+
+              expect(polling_service).to receive(:call).with(document_request_ids)
+              described_class.new.perform
+            end
+
+            it 'does not poll for recently polled documents' do
+              recently_polled_document = create(:lighthouse526_document_upload,
+                                                status_last_polled_at: polling_time - 42.minutes)
+              expect(polling_service).not_to receive(:call)
+                .with([recently_polled_document.lighthouse_document_request_id])
+              described_class.new.perform
+            end
+          end
 
-          it 'increments a StatsD gauge metric with the total number of documents marked complete' do
-            # Should only count documents newly counted success
-            expect(StatsD).to receive(:gauge)
-              .with('worker.lighthouse.poll_form526_document_uploads.pending_documents_marked_completed', 1)
-            described_class.new.perform
+          context 'for completed and failed documents' do
+            let!(:documents) do
+              [
+                create(:lighthouse526_document_upload, aasm_state: 'completed',
+                                                       status_last_polled_at: polling_time - 2.hours),
+                create(:lighthouse526_document_upload, aasm_state: 'failed',
+                                                       status_last_polled_at: polling_time - 2.hours)
+              ]
+            end
+
+            it 'does not poll for completed or failed documents' do
+              documents.each do |doc|
+                expect(polling_service).not_to receive(:call).with([doc.lighthouse_document_request_id])
+              end
+              described_class.new.perform
+            end
           end
+        end
 
-          it 'increments a StatsD gauge metric with the total number of documents marked failed' do
-            # Should only count documents newly counted failed
-            expect(StatsD).to receive(:gauge)
-              .with('worker.lighthouse.poll_form526_document_uploads.pending_documents_marked_failed', 1)
-            described_class.new.perform
+        describe 'Document Polling Logging' do
+          context 'for pending documents' do
+            let!(:pending_polling_documents) { create_list(:lighthouse526_document_upload, 2, aasm_state: 'pending') }
+            let!(:pending_recently_polled_document) do
+              create(
+                :lighthouse526_document_upload,
+                aasm_state: 'pending',
+                status_last_polled_at: polling_time - 45.minutes
+              )
+            end
+
+            let(:polling_time) { DateTime.new(1985, 10, 26).utc }
+            let(:faraday_response) do
+              instance_double(
+                Faraday::Response,
+                body: {
+                  'data' => {
+                    'statuses' => [
+                      {
+                        'requestId' => pending_polling_documents.first.lighthouse_document_request_id,
+                        'time' => {
+                          'startTime' => 1_502_199_000,
+                          'endTime' => 1_502_199_000
+                        },
+                        'status' => 'SUCCESS'
+                      }, {
+                        'requestId' => pending_polling_documents[1].lighthouse_document_request_id,
+                        'time' => {
+                          'startTime' => 1_502_199_000,
+                          'endTime' => 1_502_199_000
+                        },
+                        'status' => 'FAILED',
+                        'error' => {
+                          'detail' => 'Something went wrong',
+                          'step' => 'BENEFITS_GATEWAY_SERVICE'
+                        }
+                      }
+                    ],
+                    'requestIdsNotFound' => [
+                      0
+                    ]
+                  }
+                },
+                status: 200
+              )
+            end
+
+            around { |example| Timecop.freeze(polling_time) { example.run } }
+
+            before do
+              allow(BenefitsDocuments::Form526::DocumentsStatusPollingService)
+                .to receive(:call).and_return(faraday_response)
+
+              # StatsD will receive multiple gauge calls in this code flow
+              allow(StatsD).to receive(:gauge)
+            end
+
+            describe 'polled documents metric' do
+              it 'increments a StatsD gauge metric with total documents polled, discluding recently polled documents' do
+                expect(StatsD).to receive(:gauge)
+                  .with('worker.lighthouse.poll_form526_document_uploads.pending_documents_polled', 2)
+
+                described_class.new.perform
+              end
+            end
+
+            describe 'completed and failed documents' do
+              let!(:existing_completed_documents) do
+                create_list(:lighthouse526_document_upload, 2, aasm_state: 'completed')
+              end
+
+              let!(:existing_failed_documents) { create_list(:lighthouse526_document_upload, 2, aasm_state: 'failed') }
+
+              it 'increments a StatsD gauge metric with the total number of documents marked complete' do
+                # Should only count documents newly counted success
+                expect(StatsD).to receive(:gauge)
+                  .with('worker.lighthouse.poll_form526_document_uploads.pending_documents_marked_completed', 1)
+                described_class.new.perform
+              end
+
+              it 'increments a StatsD gauge metric with the total number of documents marked failed' do
+                # Should only count documents newly counted failed
+                expect(StatsD).to receive(:gauge)
+                  .with('worker.lighthouse.poll_form526_document_uploads.pending_documents_marked_failed', 1)
+                described_class.new.perform
+              end
+            end
           end
         end
       end