+<% end %>
+
+<%= render 'idv/in_person/start_over_or_cancel' %>
diff --git a/app/views/idv/in_person/verify.html.slim b/app/views/idv/in_person/verify.html.slim
new file mode 100644
index 00000000000..fc88f3e13a2
--- /dev/null
+++ b/app/views/idv/in_person/verify.html.slim
@@ -0,0 +1,25 @@
+-title t('in_person_proofing.titles.in_person_proofing')
+
+h5.my1.caps.bold.accent-blue = t('in_person_proofing.step', step: 2)
+br
+h1.h3.my0 = 'Verify your information'
+
+.mt3.mb2
+ .right = link_to(t('in_person_proofing.buttons.change_address'), idv_address_url)
+ div = "#{t('in_person_proofing.forms.first_name')}: Jane"
+ div = "#{t('in_person_proofing.forms.last_name')}: Doe"
+ div = "#{t('in_person_proofing.forms.dob')}: 11/1/1911"
+ hr
+ .right = link_to(t('in_person_proofing.buttons.change_address'), idv_address_url)
+ div = "#{t('in_person_proofing.forms.address1')}: 1 Fake Street"
+ div = "#{t('in_person_proofing.forms.city')}: Faketown"
+ div = "#{t('in_person_proofing.forms.state')}: NY"
+ div = "#{t('in_person_proofing.forms.zip_code')}: 11364"
+ hr
+ .right = button_to(t('in_person_proofing.buttons.change_ssn'),
+ idv_doc_auth_step_path(step: :redo_ssn), method: :put, class: 'btn btn-link')
+ = "#{t('in_person_proofing.forms.ssn')}: 111-11-1111"
+ .mt4 = button_to(t('forms.buttons.continue'), url_for, method: :put,
+ class: 'btn btn-primary btn-wide sm-col-6 col-12')
+
+= render 'idv/in_person/start_over_or_cancel'
diff --git a/app/views/idv/in_person/welcome.html.slim b/app/views/idv/in_person/welcome.html.slim
new file mode 100644
index 00000000000..6b863f12f0c
--- /dev/null
+++ b/app/views/idv/in_person/welcome.html.slim
@@ -0,0 +1,49 @@
+h1.h3.my0 = t('in_person_proofing.headings.welcome')
+p.mt-tiny.mb3 = t('in_person_proofing.info.welcome')
+h1.h3.mb2 = t('in_person_proofing.instructions.welcome')
+ul.list-reset
+ li.pt2.pb1
+ .inline-block.mr2.mt1.align-top.circle.circle-number.bg-blue.white
+ | 1
+ .mr1.inline-block
+ .h1.inline-block.bold = t('in_person_proofing.instructions.bullet1')
+ br
+ = t('in_person_proofing.instructions.text1')
+ li.pt2.pb1
+ .inline-block.mr2.mt1.align-top.circle.circle-number.bg-blue.white
+ | 2
+ .mr1.inline-block
+ .h1.inline-block.bold = t('in_person_proofing.instructions.bullet2')
+ br
+ = t('in_person_proofing.instructions.text2')
+ li.pt2.pb1
+ .inline-block.mr2.mt1.align-top.circle.circle-number.bg-blue.white
+ | 3
+ .mr1.inline-block
+ .h1.inline-block.bold = t('in_person_proofing.instructions.bullet3')
+ br
+ = t('in_person_proofing.instructions.text3')
+ li.pt2.pb1
+ .inline-block.mr2.mt1.align-top.circle.circle-number.bg-blue.white
+ | 4
+ .mr1.inline-block
+ .h1.inline-block.bold = t('in_person_proofing.instructions.bullet4')
+ br
+ = t('in_person_proofing.instructions.text4')
+ li.pt2.pb1
+ .inline-block.mr2.mt1.align-top.circle.circle-number.bg-blue.white
+ | 5
+ .mr1.inline-block
+ .h1.inline-block.bold = t('in_person_proofing.instructions.bullet5')
+ br
+ = t('in_person_proofing.instructions.text5')
+= simple_form_for(:in_person_proofing, url: url_for, method: 'PUT',
+ html: { autocomplete: 'off', role: 'form', class: 'mt2' }) do
+ br
+ .mt0
+ button type='submit' class='btn btn-primary btn-wide sm-col-6 col-6'
+ = t('in_person_proofing.buttons.get_started')
+br
+
+.mt2.pt1.border-top
+ = link_to cancel_link_text, account_path, class: 'h5'
diff --git a/app/views/idv/shared/verification_failure.html.slim b/app/views/idv/shared/verification_failure.html.slim
index 3855b78af71..c600c68726a 100644
--- a/app/views/idv/shared/verification_failure.html.slim
+++ b/app/views/idv/shared/verification_failure.html.slim
@@ -5,3 +5,5 @@ p == presenter.warning_message
.mt3
= link_to presenter.button_text, presenter.button_path, class: 'btn btn-primary btn-link'
+
+= render 'idv/doc_auth/in_person_proofing_option'
diff --git a/config/locales/in_person_proofing/en.yml b/config/locales/in_person_proofing/en.yml
new file mode 100644
index 00000000000..4417aab55b2
--- /dev/null
+++ b/config/locales/in_person_proofing/en.yml
@@ -0,0 +1,51 @@
+---
+en:
+ in_person_proofing:
+ buttons:
+ change_address: change
+ change_ssn: change
+ get_started: Get started
+ enrollment_form: Enrollment form
+ forms:
+ address1: Address
+ address2: Address (optional)
+ city: City
+ dob: Date of birth
+ first_name: First name
+ last_name: Last Name
+ ssn: Social security number
+ state: State
+ zip_code: Zip code
+ headings:
+ enrollment_form: Bring this form to your post office
+ enter_info: Enter in your information
+ usps_list: Choose a post office
+ welcome: Verify your identity in person
+ zip_code: Find a post office
+ info:
+ enrollment_form: Please print or save this form and take it to the post office
+ you chose.
+ welcome: We can verify your identity at your local post office.
+ instructions:
+ bullet1: Choose a nearby post office
+ bullet2: Enter your information
+ bullet3: Print or save your enrollment form
+ bullet4: Visit the post office to get verified
+ bullet5: Come back to login.gov
+ encrypt: When you re-enter your password, login.gov will encrypt your information
+ to make sure no one else can access it.
+ enrollment_form: 'Bring this code to the following post office along with a
+ government-issued ID:'
+ text1: by entering your ZIP code
+ text2: name, date of birth, address, and social security number
+ text3: a bar code that you need to take to the post office with you
+ text4: bring your enrollment code and a government-issued ID
+ text5: sign in and finish the process
+ welcome: 'What you''ll need to do:'
+ opt_in_link: Verify your identity in person at a local post office instead
+ step: Verify your identity in person - Step %{step} of 5
+ titles:
+ in_person_proofing: Verify your identity in person
+ warning:
+ enrollment_form: Download, print, or save your enrollment form. A copy has
+ also been sent to your email.
diff --git a/config/locales/in_person_proofing/es.yml b/config/locales/in_person_proofing/es.yml
new file mode 100644
index 00000000000..fc58a30ef0b
--- /dev/null
+++ b/config/locales/in_person_proofing/es.yml
@@ -0,0 +1,51 @@
+---
+es:
+ in_person_proofing:
+ buttons:
+ change_address: change
+ change_ssn: change
+ get_started: Get started
+ enrollment_form: Enrollment form
+ forms:
+ address1: Address
+ address2: Address (optional)
+ city: City
+ dob: Date of birth
+ first_name: First name
+ last_name: Last Name
+ ssn: Social security number
+ state: State
+ zip_code: Zip code
+ headings:
+ enrollment_form: Bring this form to your post office
+ enter_info: Enter in your information
+ usps_list: Choose a post office
+ welcome: Verify your identity in person
+ zip_code: Find a post office
+ info:
+ enrollment_form: Please print or save this form and take it to the post office
+ you chose.
+ welcome: We can verify your identity at your local post office.
+ instructions:
+ bullet1: Choose a nearby post office
+ bullet2: Enter your information
+ bullet3: Print or save your enrollment form
+ bullet4: Visit the post office to get verified
+ bullet5: Come back to login.gov
+ encrypt: When you re-enter your password, login.gov will encrypt your information
+ to make sure no one else can access it.
+ enrollment_form: 'Bring this code to the following post office along with a
+ government-issued ID:'
+ text1: by entering your ZIP code
+ text2: name, date of birth, address, and social security number
+ text3: a bar code that you need to take to the post office with you
+ text4: bring your enrollment code and a government-issued ID
+ text5: sign in and finish the process
+ welcome: 'What you''ll need to do:'
+ opt_in_link: Verify your identity in person at a local post office instead
+ step: Verify your identity in person - Step %{step} of 5
+ titles:
+ in_person_proofing: Verify your identity in person
+ warning:
+ enrollment_form: Download, print, or save your enrollment form. A copy has
+ also been sent to your email.
diff --git a/config/locales/in_person_proofing/fr.yml b/config/locales/in_person_proofing/fr.yml
new file mode 100644
index 00000000000..1032eae98df
--- /dev/null
+++ b/config/locales/in_person_proofing/fr.yml
@@ -0,0 +1,51 @@
+---
+fr:
+ in_person_proofing:
+ buttons:
+ change_address: change
+ change_ssn: change
+ get_started: Get started
+ enrollment_form: Enrollment form
+ forms:
+ address1: Address
+ address2: Address (optional)
+ city: City
+ dob: Date of birth
+ first_name: First name
+ last_name: Last Name
+ ssn: Social security number
+ state: State
+ zip_code: Zip code
+ headings:
+ enrollment_form: Bring this form to your post office
+ enter_info: Enter in your information
+ usps_list: Choose a post office
+ welcome: Verify your identity in person
+ zip_code: Find a post office
+ info:
+ enrollment_form: Please print or save this form and take it to the post office
+ you chose.
+ welcome: We can verify your identity at your local post office.
+ instructions:
+ bullet1: Choose a nearby post office
+ bullet2: Enter your information
+ bullet3: Print or save your enrollment form
+ bullet4: Visit the post office to get verified
+ bullet5: Come back to login.gov
+ encrypt: When you re-enter your password, login.gov will encrypt your information
+ to make sure no one else can access it.
+ enrollment_form: 'Bring this code to the following post office along with a
+ government-issued ID:'
+ text1: by entering your ZIP code
+ text2: name, date of birth, address, and social security number
+ text3: a bar code that you need to take to the post office with you
+ text4: bring your enrollment code and a government-issued ID
+ text5: sign in and finish the process
+ welcome: 'What you''ll need to do:'
+ opt_in_link: Verify your identity in person at a local post office instead
+ step: Verify your identity in person - Step %{step} of 5
+ titles:
+ in_person_proofing: Verify your identity in person
+ warning:
+ enrollment_form: Download, print, or save your enrollment form. A copy has
+ also been sent to your email.
diff --git a/config/routes.rb b/config/routes.rb
index db7f83d9f9c..649e448351a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -251,6 +251,9 @@
put '/recovery/:step' => 'recovery#update'
end
end
+ get '/in_person' => 'in_person#index'
+ get '/in_person/:step' => 'in_person#show', as: :in_person_step
+ put '/in_person/:step' => 'in_person#update'
end
if FeatureManagement.enable_usps_verification?
diff --git a/lib/feature_management.rb b/lib/feature_management.rb
index 24238bea317..432cb2960e0 100644
--- a/lib/feature_management.rb
+++ b/lib/feature_management.rb
@@ -117,4 +117,8 @@ def self.allow_doc_auth_test_credentials?
def self.backup_codes_as_only_2fa?
Figaro.env.backup_codes_as_only_2fa == 'true'
end
+
+ def self.in_person_proofing_enabled?
+ Figaro.env.in_person_proofing_enabled == 'true'
+ end
end
diff --git a/spec/features/idv/doc_auth/front_image_step_spec.rb b/spec/features/idv/doc_auth/front_image_step_spec.rb
index 1ed7c98b400..ce12ef99bd9 100644
--- a/spec/features/idv/doc_auth/front_image_step_spec.rb
+++ b/spec/features/idv/doc_auth/front_image_step_spec.rb
@@ -4,6 +4,7 @@
feature 'doc auth front image step' do
include IdvStepHelper
include DocAuthHelper
+ include InPersonHelper
let(:user) { user_with_2fa }
let(:max_attempts) { Figaro.env.acuant_max_attempts.to_i }
@@ -34,6 +35,20 @@
expect(page).to have_current_path(idv_doc_auth_front_image_step)
end
+ it 'offers in person option on failure' do
+ enable_in_person_proofing
+
+ expect(page).to_not have_link(t('in_person_proofing.opt_in_link'),
+ href: idv_in_person_welcome_step)
+
+ mock_assure_id_fail
+ attach_image
+ click_idv_continue
+
+ expect(page).to have_link(t('in_person_proofing.opt_in_link'),
+ href: idv_in_person_welcome_step)
+ end
+
it 'throttles calls to acuant and allows retry after the attempt window' do
allow(Figaro.env).to receive(:acuant_max_attempts).and_return(max_attempts)
max_attempts.times do
diff --git a/spec/features/idv/doc_auth/verify_step_spec.rb b/spec/features/idv/doc_auth/verify_step_spec.rb
index edab402fe19..d9912de94bf 100644
--- a/spec/features/idv/doc_auth/verify_step_spec.rb
+++ b/spec/features/idv/doc_auth/verify_step_spec.rb
@@ -3,6 +3,7 @@
feature 'doc auth verify step' do
include IdvStepHelper
include DocAuthHelper
+ include InPersonHelper
let(:max_attempts) { Idv::Attempter.idv_max_attempts }
before do
@@ -48,7 +49,21 @@
click_idv_continue
click_idv_continue
+ enable_in_person_proofing
expect(page).to have_current_path(idv_session_failure_path(reason: :warning))
+ expect(page).to_not have_link(t('in_person_proofing.opt_in_link'),
+ href: idv_in_person_welcome_step)
+ end
+
+ it 'has a link to proof in person' do
+ enable_in_person_proofing
+ complete_doc_auth_steps_before_ssn_step
+ fill_out_ssn_form_with_duplicate_ssn
+ click_idv_continue
+ click_idv_continue
+
+ expect(page).to have_link(t('in_person_proofing.opt_in_link'),
+ href: idv_in_person_welcome_step)
end
it 'throttles resolution' do
diff --git a/spec/features/idv/in_person/bar_code_step_spec.rb b/spec/features/idv/in_person/bar_code_step_spec.rb
new file mode 100644
index 00000000000..1710eacf354
--- /dev/null
+++ b/spec/features/idv/in_person/bar_code_step_spec.rb
@@ -0,0 +1,21 @@
+require 'rails_helper'
+
+feature 'in person find usps step' do
+ include InPersonHelper
+
+ before do
+ enable_in_person_proofing
+ sign_in_and_2fa_user
+ complete_in_person_steps_before_bar_code_step
+ end
+
+ it 'is on the correct page' do
+ expect(page).to have_current_path(idv_in_person_bar_code_step)
+ end
+
+ it 'proceeds to the next step' do
+ click_link t('forms.buttons.continue')
+
+ expect(page).to have_current_path(account_path)
+ end
+end
diff --git a/spec/features/idv/in_person/encrypt_step_spec.rb b/spec/features/idv/in_person/encrypt_step_spec.rb
new file mode 100644
index 00000000000..fba3829e7b9
--- /dev/null
+++ b/spec/features/idv/in_person/encrypt_step_spec.rb
@@ -0,0 +1,21 @@
+require 'rails_helper'
+
+feature 'in person encrypt step' do
+ include InPersonHelper
+
+ before do
+ enable_in_person_proofing
+ sign_in_and_2fa_user
+ complete_in_person_steps_before_encrypt_step
+ end
+
+ it 'is on the correct page' do
+ expect(page).to have_current_path(idv_in_person_encrypt_step)
+ end
+
+ it 'proceeds to the next step' do
+ click_continue
+
+ expect(page).to have_current_path(idv_in_person_bar_code_step)
+ end
+end
diff --git a/spec/features/idv/in_person/enter_info_step_spec.rb b/spec/features/idv/in_person/enter_info_step_spec.rb
new file mode 100644
index 00000000000..f85ffeddf6f
--- /dev/null
+++ b/spec/features/idv/in_person/enter_info_step_spec.rb
@@ -0,0 +1,21 @@
+require 'rails_helper'
+
+feature 'in person enter info step' do
+ include InPersonHelper
+
+ before do
+ enable_in_person_proofing
+ sign_in_and_2fa_user
+ complete_in_person_steps_before_enter_info_step
+ end
+
+ it 'is on the correct page' do
+ expect(page).to have_current_path(idv_in_person_enter_info_step)
+ end
+
+ it 'proceeds to the next page' do
+ click_continue
+
+ expect(page).to have_current_path(idv_in_person_verify_step)
+ end
+end
diff --git a/spec/features/idv/in_person/find_usps_step_spec.rb b/spec/features/idv/in_person/find_usps_step_spec.rb
new file mode 100644
index 00000000000..133e698b866
--- /dev/null
+++ b/spec/features/idv/in_person/find_usps_step_spec.rb
@@ -0,0 +1,22 @@
+require 'rails_helper'
+
+feature 'in person find usps step' do
+ include InPersonHelper
+
+ before do
+ enable_in_person_proofing
+ sign_in_and_2fa_user
+ complete_in_person_steps_before_find_usps_step
+ end
+
+ it 'is on the correct page' do
+ expect(page).to have_current_path(idv_in_person_find_usps_step)
+ end
+
+ it 'proceeds to next page with a zip code' do
+ fill_in :in_person_zip_code, with: Faker::Address.zip_code
+ click_continue
+
+ expect(page).to have_current_path(idv_in_person_usps_list_step)
+ end
+end
diff --git a/spec/features/idv/in_person/usps_list_step_spec.rb b/spec/features/idv/in_person/usps_list_step_spec.rb
new file mode 100644
index 00000000000..c204eb0ab8b
--- /dev/null
+++ b/spec/features/idv/in_person/usps_list_step_spec.rb
@@ -0,0 +1,20 @@
+require 'rails_helper'
+
+feature 'in person usps list step' do
+ include InPersonHelper
+
+ before do
+ enable_in_person_proofing
+ sign_in_and_2fa_user
+ complete_in_person_steps_before_usps_list_step
+ end
+
+ it 'is on the correct page' do
+ expect(page).to have_current_path(idv_in_person_usps_list_step)
+ end
+
+ it 'proceeds to the next page' do
+ click_continue
+ expect(page).to have_current_path(idv_in_person_enter_info_step)
+ end
+end
diff --git a/spec/features/idv/in_person/verify_step_spec.rb b/spec/features/idv/in_person/verify_step_spec.rb
new file mode 100644
index 00000000000..7d7c42133b7
--- /dev/null
+++ b/spec/features/idv/in_person/verify_step_spec.rb
@@ -0,0 +1,21 @@
+require 'rails_helper'
+
+feature 'in person verify info step' do
+ include InPersonHelper
+
+ before do
+ enable_in_person_proofing
+ sign_in_and_2fa_user
+ complete_in_person_steps_before_verify_step
+ end
+
+ it 'is on the correct page' do
+ expect(page).to have_current_path(idv_in_person_verify_step)
+ end
+
+ it 'proceeds to the next page' do
+ click_continue
+
+ expect(page).to have_current_path(idv_in_person_encrypt_step)
+ end
+end
diff --git a/spec/features/idv/in_person/welcome_step_spec.rb b/spec/features/idv/in_person/welcome_step_spec.rb
new file mode 100644
index 00000000000..0587e4a3e5e
--- /dev/null
+++ b/spec/features/idv/in_person/welcome_step_spec.rb
@@ -0,0 +1,15 @@
+require 'rails_helper'
+
+feature 'in person welcome step' do
+ include InPersonHelper
+
+ before do
+ enable_in_person_proofing
+ sign_in_and_2fa_user
+ complete_in_person_steps_before_welcome_step
+ end
+
+ it 'is on the correct page' do
+ expect(page).to have_current_path(idv_in_person_welcome_step)
+ end
+end
diff --git a/spec/support/features/in_person_helper.rb b/spec/support/features/in_person_helper.rb
new file mode 100644
index 00000000000..176912b1f8b
--- /dev/null
+++ b/spec/support/features/in_person_helper.rb
@@ -0,0 +1,67 @@
+module InPersonHelper
+ def idv_in_person_welcome_step
+ idv_in_person_step_path(step: :welcome)
+ end
+
+ def idv_in_person_find_usps_step
+ idv_in_person_step_path(step: :find_usps)
+ end
+
+ def idv_in_person_usps_list_step
+ idv_in_person_step_path(step: :usps_list)
+ end
+
+ def idv_in_person_enter_info_step
+ idv_in_person_step_path(step: :enter_info)
+ end
+
+ def idv_in_person_verify_step
+ idv_in_person_step_path(step: :verify)
+ end
+
+ def idv_in_person_encrypt_step
+ idv_in_person_step_path(step: :encrypt)
+ end
+
+ def idv_in_person_bar_code_step
+ idv_in_person_step_path(step: :bar_code)
+ end
+
+ def enable_in_person_proofing
+ allow(Figaro.env).to receive(:in_person_proofing_enabled).and_return('true')
+ end
+
+ def complete_in_person_steps_before_welcome_step
+ visit idv_in_person_welcome_step
+ end
+
+ def complete_in_person_steps_before_find_usps_step
+ complete_in_person_steps_before_welcome_step
+ click_on t('doc_auth.buttons.get_started')
+ end
+
+ def complete_in_person_steps_before_usps_list_step
+ complete_in_person_steps_before_find_usps_step
+ click_continue
+ end
+
+ def complete_in_person_steps_before_enter_info_step
+ complete_in_person_steps_before_usps_list_step
+ click_continue
+ end
+
+ def complete_in_person_steps_before_verify_step
+ complete_in_person_steps_before_enter_info_step
+ click_continue
+ end
+
+ def complete_in_person_steps_before_encrypt_step
+ complete_in_person_steps_before_verify_step
+ click_continue
+ end
+
+ def complete_in_person_steps_before_bar_code_step
+ complete_in_person_steps_before_encrypt_step
+ click_continue
+ end
+end