diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5a2d59fa502..113ee609299 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -484,6 +484,31 @@ stop-review-app:
include:
- template: Jobs/SAST.gitlab-ci.yml
- template: Jobs/Dependency-Scanning.gitlab-ci.yml
+ - template: Security/Secret-Detection.gitlab-ci.yml
+
+secret_detection:
+ allow_failure: false
+ variables:
+ SECRET_DETECTION_LOG_OPTIONS: origin/${CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME}..HEAD
+ SECRET_DETECTION_REPORT_FILE: "gl-secret-detection-report.json"
+ rules:
+ - if: $SECRET_DETECTION_DISABLED
+ when: never
+ - if: '$CI_COMMIT_BRANCH || $CI_COMMIT_TAG'
+ before_script:
+ - apk add --no-cache jq
+ script:
+ - /analyzer run
+ # check if '{ "vulnerabilities": [], ..' is empty in the report file if it exists
+ - |
+ if [ -f "$SECRET_DETECTION_REPORT_FILE" ]; then
+ if [ "$(jq ".vulnerabilities | length" $SECRET_DETECTION_REPORT_FILE)" -gt 0 ]; then
+ echo "Vulnerabilities detected. Please analyze the artifact $SECRET_DETECTION_REPORT_FILE produced by the 'secret-detection' job."
+ exit 80
+ fi
+ else
+ echo "Artifact $SECRET_DETECTION_REPORT_FILE does not exist. The 'secret-detection' job likely didn't create one. Hence, no evaluation can be performed."
+ fi
.container_scan_template:
interruptible: true
diff --git a/app/assets/images/alert/icon-lock-alert-important.svg b/app/assets/images/alert/icon-lock-alert-important.svg
index 47e94193ac7..0a1190b3cd9 100644
--- a/app/assets/images/alert/icon-lock-alert-important.svg
+++ b/app/assets/images/alert/icon-lock-alert-important.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/alert/success.svg b/app/assets/images/alert/success.svg
index 44da527697a..3f25b860f7a 100644
--- a/app/assets/images/alert/success.svg
+++ b/app/assets/images/alert/success.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/alert/unphishable.svg b/app/assets/images/alert/unphishable.svg
index 2b557fef831..9d479e3413c 100644
--- a/app/assets/images/alert/unphishable.svg
+++ b/app/assets/images/alert/unphishable.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/alert/warning.svg b/app/assets/images/alert/warning.svg
index 6fa53a4d200..4ec85cd21d7 100644
--- a/app/assets/images/alert/warning.svg
+++ b/app/assets/images/alert/warning.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/carat-right.svg b/app/assets/images/carat-right.svg
index 64c1dd2d6e2..dc2a091c774 100644
--- a/app/assets/images/carat-right.svg
+++ b/app/assets/images/carat-right.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/come-back.svg b/app/assets/images/come-back.svg
index 38875a9104d..e21ef79649b 100644
--- a/app/assets/images/come-back.svg
+++ b/app/assets/images/come-back.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/get-started/2FA.svg b/app/assets/images/get-started/2FA.svg
index b7426c71062..032b46042d8 100644
--- a/app/assets/images/get-started/2FA.svg
+++ b/app/assets/images/get-started/2FA.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/get-started/ID.svg b/app/assets/images/get-started/ID.svg
index 4282205234a..90cc036a476 100644
--- a/app/assets/images/get-started/ID.svg
+++ b/app/assets/images/get-started/ID.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/get-started/email-password.svg b/app/assets/images/get-started/email-password.svg
index d15f937574a..4eba2101c0a 100644
--- a/app/assets/images/get-started/email-password.svg
+++ b/app/assets/images/get-started/email-password.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/get-started/financial.svg b/app/assets/images/get-started/financial.svg
index 9bd71dbbbb0..019514da824 100644
--- a/app/assets/images/get-started/financial.svg
+++ b/app/assets/images/get-started/financial.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/get-started/personal-details.svg b/app/assets/images/get-started/personal-details.svg
index 38be0aa5b65..20c495c201a 100644
--- a/app/assets/images/get-started/personal-details.svg
+++ b/app/assets/images/get-started/personal-details.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/get-started/personal-key.svg b/app/assets/images/get-started/personal-key.svg
index b375bd4479d..1793eb6355a 100644
--- a/app/assets/images/get-started/personal-key.svg
+++ b/app/assets/images/get-started/personal-key.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/globe-blue.svg b/app/assets/images/globe-blue.svg
index 111117296e7..6239302fac9 100644
--- a/app/assets/images/globe-blue.svg
+++ b/app/assets/images/globe-blue.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/globe-white.svg b/app/assets/images/globe-white.svg
index b834cfcbb49..0d680abd897 100644
--- a/app/assets/images/globe-white.svg
+++ b/app/assets/images/globe-white.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/icon-https.svg b/app/assets/images/icon-https.svg
index 0eb37008f18..a633e5e0094 100644
--- a/app/assets/images/icon-https.svg
+++ b/app/assets/images/icon-https.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/icon-lock-alert-important.svg b/app/assets/images/icon-lock-alert-important.svg
index 47e94193ac7..0a1190b3cd9 100644
--- a/app/assets/images/icon-lock-alert-important.svg
+++ b/app/assets/images/icon-lock-alert-important.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/id-card.svg b/app/assets/images/id-card.svg
index b1336c20c74..4b6cd53b6d9 100644
--- a/app/assets/images/id-card.svg
+++ b/app/assets/images/id-card.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/idv/laptop-icon.svg b/app/assets/images/idv/laptop-icon.svg
index 680054edaf3..434b1cc5039 100644
--- a/app/assets/images/idv/laptop-icon.svg
+++ b/app/assets/images/idv/laptop-icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/idv/phone-icon.svg b/app/assets/images/idv/phone-icon.svg
index b409f134cb6..d7323041d7f 100644
--- a/app/assets/images/idv/phone-icon.svg
+++ b/app/assets/images/idv/phone-icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/idv/user-in-person.svg b/app/assets/images/idv/user-in-person.svg
index e80083004bb..a48daa7ebf7 100644
--- a/app/assets/images/idv/user-in-person.svg
+++ b/app/assets/images/idv/user-in-person.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/info-pin-map.svg b/app/assets/images/info-pin-map.svg
index 5f31cbcfaca..a01258bf679 100644
--- a/app/assets/images/info-pin-map.svg
+++ b/app/assets/images/info-pin-map.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/lock.svg b/app/assets/images/lock.svg
index 6ca5c06bd4b..82489d82462 100644
--- a/app/assets/images/lock.svg
+++ b/app/assets/images/lock.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/logo-white.svg b/app/assets/images/logo-white.svg
index ad9bd07e677..1683396c7b1 100644
--- a/app/assets/images/logo-white.svg
+++ b/app/assets/images/logo-white.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/logo.svg b/app/assets/images/logo.svg
index 6577834188e..d6a1abd991b 100644
--- a/app/assets/images/logo.svg
+++ b/app/assets/images/logo.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/mfa-options/auth_app.svg b/app/assets/images/mfa-options/auth_app.svg
index 8c4279bf7d3..e62097008f4 100644
--- a/app/assets/images/mfa-options/auth_app.svg
+++ b/app/assets/images/mfa-options/auth_app.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/mfa-options/backup_code.svg b/app/assets/images/mfa-options/backup_code.svg
index 2f0567135d1..2ea2ce4042c 100644
--- a/app/assets/images/mfa-options/backup_code.svg
+++ b/app/assets/images/mfa-options/backup_code.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/mfa-options/phone.svg b/app/assets/images/mfa-options/phone.svg
index 5c812b76465..5bcae08c142 100644
--- a/app/assets/images/mfa-options/phone.svg
+++ b/app/assets/images/mfa-options/phone.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/mfa-options/piv_cac.svg b/app/assets/images/mfa-options/piv_cac.svg
index 61884ec3a80..f3341be00da 100644
--- a/app/assets/images/mfa-options/piv_cac.svg
+++ b/app/assets/images/mfa-options/piv_cac.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/mfa-options/security-key-icon.svg b/app/assets/images/mfa-options/security-key-icon.svg
index 1a9a2adb89c..57ba60b1150 100644
--- a/app/assets/images/mfa-options/security-key-icon.svg
+++ b/app/assets/images/mfa-options/security-key-icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/mfa-options/webauthn.svg b/app/assets/images/mfa-options/webauthn.svg
index 98a1a9828fe..9d2a1ae4f78 100644
--- a/app/assets/images/mfa-options/webauthn.svg
+++ b/app/assets/images/mfa-options/webauthn.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/mfa-options/webauthn_platform.svg b/app/assets/images/mfa-options/webauthn_platform.svg
index c95e42cb3b9..eca65bb36b6 100644
--- a/app/assets/images/mfa-options/webauthn_platform.svg
+++ b/app/assets/images/mfa-options/webauthn_platform.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/personal-key/email.svg b/app/assets/images/personal-key/email.svg
index 68801b1ab10..a4ebfd7d445 100644
--- a/app/assets/images/personal-key/email.svg
+++ b/app/assets/images/personal-key/email.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/personal-key/pkey-block.svg b/app/assets/images/personal-key/pkey-block.svg
index b37c230c647..3dc022e9f2e 100644
--- a/app/assets/images/personal-key/pkey-block.svg
+++ b/app/assets/images/personal-key/pkey-block.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/personal-key/shield.svg b/app/assets/images/personal-key/shield.svg
index 04b34cc9887..df9ebdbf1fe 100644
--- a/app/assets/images/personal-key/shield.svg
+++ b/app/assets/images/personal-key/shield.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/personal-key/warning.svg b/app/assets/images/personal-key/warning.svg
index 6fa53a4d200..4ec85cd21d7 100644
--- a/app/assets/images/personal-key/warning.svg
+++ b/app/assets/images/personal-key/warning.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/platform-authenticator.svg b/app/assets/images/platform-authenticator.svg
index 1bf063b51ba..9d324b09068 100644
--- a/app/assets/images/platform-authenticator.svg
+++ b/app/assets/images/platform-authenticator.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/plus.svg b/app/assets/images/plus.svg
index 41888145942..7d4cdc49e3c 100644
--- a/app/assets/images/plus.svg
+++ b/app/assets/images/plus.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/security-key.svg b/app/assets/images/security-key.svg
index d81a0ba67fa..d207e6b7db1 100644
--- a/app/assets/images/security-key.svg
+++ b/app/assets/images/security-key.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/sign-in.svg b/app/assets/images/sign-in.svg
index 3215afa4ec1..a7211e5d3f4 100644
--- a/app/assets/images/sign-in.svg
+++ b/app/assets/images/sign-in.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/sp-logos/generic.svg b/app/assets/images/sp-logos/generic.svg
index 89d24209556..66be92c3651 100644
--- a/app/assets/images/sp-logos/generic.svg
+++ b/app/assets/images/sp-logos/generic.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/sp-logos/square-gsa-dark.svg b/app/assets/images/sp-logos/square-gsa-dark.svg
index 62fc5eeaba2..79d64578262 100644
--- a/app/assets/images/sp-logos/square-gsa-dark.svg
+++ b/app/assets/images/sp-logos/square-gsa-dark.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/sp-logos/square-gsa.svg b/app/assets/images/sp-logos/square-gsa.svg
index 92e87824489..4af7b9dfa2b 100644
--- a/app/assets/images/sp-logos/square-gsa.svg
+++ b/app/assets/images/sp-logos/square-gsa.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/status/delete.svg b/app/assets/images/status/delete.svg
index d4f411858ef..1b7b8fec5cf 100644
--- a/app/assets/images/status/delete.svg
+++ b/app/assets/images/status/delete.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/status/error-lock.svg b/app/assets/images/status/error-lock.svg
index b61bdbebcc8..3e94b7d262f 100644
--- a/app/assets/images/status/error-lock.svg
+++ b/app/assets/images/status/error-lock.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/status/error.svg b/app/assets/images/status/error.svg
index 8deea0a91da..131e4c967fa 100644
--- a/app/assets/images/status/error.svg
+++ b/app/assets/images/status/error.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/status/info-question.svg b/app/assets/images/status/info-question.svg
index 79c60dcfcf5..1ecfc8720cf 100644
--- a/app/assets/images/status/info-question.svg
+++ b/app/assets/images/status/info-question.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/status/personal-key.svg b/app/assets/images/status/personal-key.svg
index f67e726ae96..9840e70f095 100644
--- a/app/assets/images/status/personal-key.svg
+++ b/app/assets/images/status/personal-key.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/status/warning.svg b/app/assets/images/status/warning.svg
index 6fa53a4d200..4ec85cd21d7 100644
--- a/app/assets/images/status/warning.svg
+++ b/app/assets/images/status/warning.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/us-flag.png b/app/assets/images/us-flag.png
deleted file mode 100644
index 8ae515a4d7d..00000000000
Binary files a/app/assets/images/us-flag.png and /dev/null differ
diff --git a/app/assets/images/us_flag.svg b/app/assets/images/us_flag.svg
new file mode 100644
index 00000000000..275d57b9735
--- /dev/null
+++ b/app/assets/images/us_flag.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/app/assets/images/user-access.svg b/app/assets/images/user-access.svg
index e31ec27ee1d..163d5ab6b6d 100644
--- a/app/assets/images/user-access.svg
+++ b/app/assets/images/user-access.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/user-signup-ial1.svg b/app/assets/images/user-signup-ial1.svg
index d58709e6db3..7a39cef53a5 100644
--- a/app/assets/images/user-signup-ial1.svg
+++ b/app/assets/images/user-signup-ial1.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/user-signup-ial2.svg b/app/assets/images/user-signup-ial2.svg
index 3308435e5c4..2c49bc0a84b 100644
--- a/app/assets/images/user-signup-ial2.svg
+++ b/app/assets/images/user-signup-ial2.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/user.svg b/app/assets/images/user.svg
index d0de2f5793c..6074e80aeda 100644
--- a/app/assets/images/user.svg
+++ b/app/assets/images/user.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/verified.svg b/app/assets/images/verified.svg
index 391191ab826..ee412c8f683 100644
--- a/app/assets/images/verified.svg
+++ b/app/assets/images/verified.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/images/webauthn-verified.svg b/app/assets/images/webauthn-verified.svg
index cd44197f765..0c186a7827f 100644
--- a/app/assets/images/webauthn-verified.svg
+++ b/app/assets/images/webauthn-verified.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/assets/stylesheets/_uswds-core.scss b/app/assets/stylesheets/_uswds-core.scss
index 3c4b46b3bbf..94b1aeb15da 100644
--- a/app/assets/stylesheets/_uswds-core.scss
+++ b/app/assets/stylesheets/_uswds-core.scss
@@ -1,8 +1,6 @@
@forward '@18f/identity-design-system/packages/uswds-core' with (
$theme-body-font-size: 'sm',
$theme-font-path: '',
- $theme-font-role-heading: 'sans',
- $theme-font-type-serif: false,
$theme-image-path: '',
$theme-global-border-box-sizing: true,
$theme-global-link-styles: true,
diff --git a/app/assets/stylesheets/utilities/_typography.scss b/app/assets/stylesheets/utilities/_typography.scss
index 5db68043ba7..522e0e0c508 100644
--- a/app/assets/stylesheets/utilities/_typography.scss
+++ b/app/assets/stylesheets/utilities/_typography.scss
@@ -1,10 +1,6 @@
@use 'uswds-core' as *;
@use '../variables/app' as *;
-body {
- -webkit-font-smoothing: antialiased;
-}
-
.text-wrap-anywhere {
overflow-wrap: anywhere;
}
diff --git a/app/controllers/concerns/idv/verify_info_concern.rb b/app/controllers/concerns/idv/verify_info_concern.rb
index 03b3dde0be9..3560c6c4224 100644
--- a/app/controllers/concerns/idv/verify_info_concern.rb
+++ b/app/controllers/concerns/idv/verify_info_concern.rb
@@ -332,8 +332,10 @@ def add_proofing_costs(results)
add_cost(:lexis_nexis_resolution, transaction_id: hash[:transaction_id])
elsif stage == :state_id
next if hash[:exception].present?
+ next if hash[:vendor_name] == 'UnsupportedJurisdiction'
+ # transaction_id comes from TransactionLocatorId
add_cost(:aamva, transaction_id: hash[:transaction_id])
- track_aamva unless hash[:vendor_name] == 'UnsupportedJurisdiction'
+ track_aamva
elsif stage == :threatmetrix
# transaction_id comes from request_id
tmx_id = hash[:transaction_id]
diff --git a/app/controllers/concerns/second_mfa_reminder_concern.rb b/app/controllers/concerns/second_mfa_reminder_concern.rb
index c24f3058026..ca7fb29e569 100644
--- a/app/controllers/concerns/second_mfa_reminder_concern.rb
+++ b/app/controllers/concerns/second_mfa_reminder_concern.rb
@@ -1,6 +1,5 @@
module SecondMfaReminderConcern
def user_needs_second_mfa_reminder?
- return false unless IdentityConfig.store.second_mfa_reminder_enabled
return false if user_has_dismissed_second_mfa_reminder?
return false if second_mfa_enrollment_may_downgrade_for_service_provider_mfa_requirement?
return false if user_has_multiple_mfa_methods?
diff --git a/app/controllers/idv/capture_doc_status_controller.rb b/app/controllers/idv/capture_doc_status_controller.rb
index 9e294d79439..670721751a6 100644
--- a/app/controllers/idv/capture_doc_status_controller.rb
+++ b/app/controllers/idv/capture_doc_status_controller.rb
@@ -20,7 +20,8 @@ def status
:too_many_requests
elsif confirmed_barcode_attention_result? || user_has_establishing_in_person_enrollment?
:ok
- elsif session_result.blank? || pending_barcode_attention_confirmation?
+ elsif session_result.blank? || pending_barcode_attention_confirmation? ||
+ redo_document_capture_pending?
:accepted
elsif !session_result.success?
:unauthorized
@@ -68,11 +69,13 @@ def user_has_establishing_in_person_enrollment?
end
def confirmed_barcode_attention_result?
- had_barcode_attention_result? && !document_capture_session.ocr_confirmation_pending?
+ !redo_document_capture_pending? && had_barcode_attention_result? &&
+ !document_capture_session.ocr_confirmation_pending?
end
def pending_barcode_attention_confirmation?
- had_barcode_attention_result? && document_capture_session.ocr_confirmation_pending?
+ !redo_document_capture_pending? && had_barcode_attention_result? &&
+ document_capture_session.ocr_confirmation_pending?
end
def had_barcode_attention_result?
@@ -90,5 +93,12 @@ def idv_session
service_provider: current_sp,
)
end
+
+ def redo_document_capture_pending?
+ return unless session_result&.dig(:captured_at)
+ return unless document_capture_session.requested_at
+
+ document_capture_session.requested_at > session_result.captured_at
+ end
end
end
diff --git a/app/controllers/idv/document_capture_controller.rb b/app/controllers/idv/document_capture_controller.rb
index 2e4eb7c7879..6f24377a3e6 100644
--- a/app/controllers/idv/document_capture_controller.rb
+++ b/app/controllers/idv/document_capture_controller.rb
@@ -20,6 +20,9 @@ def show
def update
idv_session.redo_document_capture = nil # done with this redo
+ # Not used in standard flow, here for data consistency with hybrid flow.
+ document_capture_session.confirm_ocr
+
result = handle_stored_result
analytics.idv_doc_auth_document_capture_submitted(**result.to_h.merge(analytics_arguments))
diff --git a/app/controllers/idv/hybrid_mobile/document_capture_controller.rb b/app/controllers/idv/hybrid_mobile/document_capture_controller.rb
index 2241569439d..b6f9e2678d2 100644
--- a/app/controllers/idv/hybrid_mobile/document_capture_controller.rb
+++ b/app/controllers/idv/hybrid_mobile/document_capture_controller.rb
@@ -6,13 +6,9 @@ class DocumentCaptureController < ApplicationController
before_action :check_valid_document_capture_session
before_action :override_csp_to_allow_acuant
+ before_action :confirm_document_capture_needed, only: :show
def show
- if document_capture_session&.load_result&.success?
- redirect_to idv_hybrid_mobile_capture_complete_url
- return
- end
-
analytics.idv_doc_auth_document_capture_visited(**analytics_arguments)
Funnel::DocAuth::RegisterStep.new(document_capture_user.id, sp_session[:issuer]).
@@ -22,6 +18,7 @@ def show
end
def update
+ document_capture_session.confirm_ocr
result = handle_stored_result
analytics.idv_doc_auth_document_capture_submitted(**result.to_h.merge(analytics_arguments))
@@ -69,6 +66,20 @@ def handle_stored_result
failure(I18n.t('doc_auth.errors.general.network_error'), extra)
end
end
+
+ def confirm_document_capture_needed
+ return unless stored_result&.success?
+ return if redo_document_capture_pending?
+
+ redirect_to idv_hybrid_mobile_capture_complete_url
+ end
+
+ def redo_document_capture_pending?
+ return unless stored_result&.dig(:captured_at)
+ return unless document_capture_session.requested_at
+
+ document_capture_session.requested_at > stored_result.captured_at
+ end
end
end
end
diff --git a/app/controllers/idv/link_sent_controller.rb b/app/controllers/idv/link_sent_controller.rb
index d0c239dea7e..622aec47f95 100644
--- a/app/controllers/idv/link_sent_controller.rb
+++ b/app/controllers/idv/link_sent_controller.rb
@@ -25,6 +25,7 @@ def update
# The doc capture flow will have fetched the results already. We need
# to fetch them again here to add the PII to this session
handle_document_verification_success(document_capture_session_result)
+ idv_session.redo_document_capture = nil
redirect_to idv_ssn_url
end
diff --git a/app/controllers/reactivate_account_controller.rb b/app/controllers/reactivate_account_controller.rb
index 4ffe8267361..bc76afd778a 100644
--- a/app/controllers/reactivate_account_controller.rb
+++ b/app/controllers/reactivate_account_controller.rb
@@ -5,10 +5,12 @@ class ReactivateAccountController < ApplicationController
before_action :confirm_password_reset_profile
def index
+ analytics.reactivate_account_visit
@personal_key_generated_at = current_user.personal_key_generated_at
end
def update
+ analytics.reactivate_account_submit
reactivate_account_session.suspend
redirect_to idv_url
end
diff --git a/app/javascript/packages/clipboard-button/package.json b/app/javascript/packages/clipboard-button/package.json
index 917a4b4ccd3..8d62cf41a08 100644
--- a/app/javascript/packages/clipboard-button/package.json
+++ b/app/javascript/packages/clipboard-button/package.json
@@ -3,6 +3,6 @@
"version": "1.0.0",
"private": true,
"dependencies": {
- "@18f/identity-design-system": "^7.1.0"
+ "@18f/identity-design-system": "^8.0.0"
}
}
diff --git a/app/javascript/packages/document-capture/components/submission-complete.jsx b/app/javascript/packages/document-capture/components/submission-complete.tsx
similarity index 55%
rename from app/javascript/packages/document-capture/components/submission-complete.jsx
rename to app/javascript/packages/document-capture/components/submission-complete.tsx
index 3c7ca5801b5..6405308edf8 100644
--- a/app/javascript/packages/document-capture/components/submission-complete.jsx
+++ b/app/javascript/packages/document-capture/components/submission-complete.tsx
@@ -1,31 +1,27 @@
import { useState, useContext, useRef } from 'react';
import CallbackOnMount from './callback-on-mount';
import UploadContext from '../context/upload';
+import type { UploadSuccessResponse } from '../context/upload';
-/** @typedef {import('../context/upload').UploadSuccessResponse} UploadSuccessResponse */
-
-/**
- * @typedef Resource
- *
- * @prop {()=>T} read Resource reader.
- *
- * @template T
- */
+interface Resource {
+ /**
+ * Resource reader.
+ */
+ read: () => T;
+}
-/**
- * @typedef SubmissionCompleteProps
- *
- * @prop {Resource} resource Resource object.
- */
+interface SubmissionCompleteProps {
+ /**
+ * Resource object.
+ */
+ resource: Resource;
+}
export class RetrySubmissionError extends Error {}
-/**
- * @param {SubmissionCompleteProps} props Props object.
- */
-function SubmissionComplete({ resource }) {
- const [, setRetryError] = useState(/** @type {Error=} */ (undefined));
- const sleepTimeout = useRef(/** @type {number=} */ (undefined));
+function SubmissionComplete({ resource }: SubmissionCompleteProps) {
+ const [, setRetryError] = useState(undefined);
+ const sleepTimeout = useRef();
const { statusPollInterval } = useContext(UploadContext);
const response = resource.read();
@@ -39,8 +35,7 @@ function SubmissionComplete({ resource }) {
}, statusPollInterval);
}
} else {
- /** @type {HTMLFormElement?} */
- const form = document.querySelector('.js-document-capture-form');
+ const form = document.querySelector('.js-document-capture-form');
form?.submit();
}
diff --git a/app/jobs/reports/authentication_report.rb b/app/jobs/reports/authentication_report.rb
new file mode 100644
index 00000000000..c530048f643
--- /dev/null
+++ b/app/jobs/reports/authentication_report.rb
@@ -0,0 +1,43 @@
+require 'reporting/authentication_report'
+
+module Reports
+ class AuthenticationReport < BaseReport
+ REPORT_NAME = 'authentication-report'
+
+ attr_accessor :report_date
+
+ def perform(report_date)
+ return unless IdentityConfig.store.s3_reports_enabled
+
+ self.report_date = report_date
+ message = "Report: #{REPORT_NAME} #{report_date}"
+ subject = "Weekly Authentication Report - #{report_date}"
+
+ report_configs.each do |report_hash|
+ tables = weekly_authentication_report_tables(report_hash['issuers'])
+
+ report_hash['emails'].each do |email|
+ ReportMailer.tables_report(
+ email:,
+ subject:,
+ message:,
+ tables:,
+ ).deliver_now
+ end
+ end
+ end
+
+ private
+
+ def weekly_authentication_report_tables(issuers)
+ Reporting::AuthenticationReport.new(
+ issuers:,
+ time_range: report_date.all_week,
+ ).as_tables_with_options
+ end
+
+ def report_configs
+ IdentityConfig.store.weekly_auth_funnel_report_config
+ end
+ end
+end
diff --git a/app/jobs/reports/base_report.rb b/app/jobs/reports/base_report.rb
index e424ffc8f49..e2148679d4d 100644
--- a/app/jobs/reports/base_report.rb
+++ b/app/jobs/reports/base_report.rb
@@ -62,10 +62,11 @@ def upload_file_to_s3_timestamped_and_latest(report_name, body, extension)
url
end
- def generate_s3_paths(name, extension, now: Time.zone.now)
+ def generate_s3_paths(name, extension, subname: nil, now: Time.zone.now)
host_data_env = Identity::Hostdata.env
- latest = "#{host_data_env}/#{name}/latest.#{name}.#{extension}"
- [latest, "#{host_data_env}/#{name}/#{now.year}/#{now.strftime('%F')}.#{name}.#{extension}"]
+ name_subdir_ext = "#{name}#{subname ? '/' : ''}#{subname}.#{extension}"
+ latest = "#{host_data_env}/#{name}/latest.#{name_subdir_ext}"
+ [latest, "#{host_data_env}/#{name}/#{now.year}/#{now.strftime('%F')}.#{name_subdir_ext}"]
end
def logger
diff --git a/app/jobs/reports/monthly_key_metrics_report.rb b/app/jobs/reports/monthly_key_metrics_report.rb
index 7ba755a7862..8438089d1b6 100644
--- a/app/jobs/reports/monthly_key_metrics_report.rb
+++ b/app/jobs/reports/monthly_key_metrics_report.rb
@@ -6,9 +6,30 @@ class MonthlyKeyMetricsReport < BaseReport
attr_reader :report_date
- def perform(date)
+ def perform(date = Time.zone.today)
@report_date = date
- csv_for_email = monthly_key_metrics_report_array
+
+ account_reuse_table = account_reuse_report.account_reuse_report
+ total_profiles_table = account_reuse_report.total_identities_report
+
+ upload_to_s3(account_reuse_table, report_name: 'account_reuse')
+ upload_to_s3(total_profiles_table, report_name: 'total_profiles')
+
+ email_tables = [
+ [
+ {
+ title: "IDV app reuse rate #{account_reuse_report.stats_month}",
+ float_as_percent: true,
+ precision: 4,
+ },
+ *account_reuse_table,
+ ],
+ [
+ { title: 'Total proofed identities' },
+ *total_profiles_table,
+ ],
+ ]
+
email_message = "Report: #{REPORT_NAME} #{date}"
email_addresses = emails.select(&:present?)
@@ -17,7 +38,7 @@ def perform(date)
email: email_addresses,
subject: "Monthly Key Metrics Report - #{date}",
message: email_message,
- tables: csv_for_email,
+ tables: email_tables,
).deliver_now
else
Rails.logger.warn 'No email addresses received - Monthly Key Metrics Report NOT SENT'
@@ -32,19 +53,29 @@ def emails
emails
end
- def monthly_key_metrics_report_array
- csv_array = []
+ def account_reuse_report
+ @account_reuse_report ||= Reporting::AccountReuseAndTotalIdentitiesReport.new(report_date)
+ end
- account_reuse_report_csv.each do |row|
- csv_array << row
- end
+ def upload_to_s3(report_body, report_name: nil)
+ _latest, path = generate_s3_paths(REPORT_NAME, 'csv', subname: report_name, now: report_date)
- csv_array
+ if bucket_name.present?
+ upload_file_to_s3_bucket(
+ path: path,
+ body: csv_file(report_body),
+ content_type: 'text/csv',
+ bucket: bucket_name,
+ )
+ end
end
- # Individual Key Metric Report
- def account_reuse_report_csv
- Reports::MonthlyAccountReuseReport.new(report_date).report_csv
+ def csv_file(report_array)
+ CSV.generate do |csv|
+ report_array.each do |row|
+ csv << row
+ end
+ end
end
end
end
diff --git a/app/models/document_capture_session.rb b/app/models/document_capture_session.rb
index 95e0b2bf218..ac9bd7a8215 100644
--- a/app/models/document_capture_session.rb
+++ b/app/models/document_capture_session.rb
@@ -14,6 +14,7 @@ def store_result_from_response(doc_auth_response)
)
session_result.success = doc_auth_response.success?
session_result.pii = doc_auth_response.pii_from_doc
+ session_result.captured_at = Time.zone.now
session_result.attention_with_barcode = doc_auth_response.attention_with_barcode?
EncryptedRedisStructStorage.store(
session_result,
@@ -28,6 +29,7 @@ def store_failed_auth_image_fingerprint(front_image_fingerprint, back_image_fing
id: generate_result_id,
)
session_result.success = false
+ session_result.captured_at = Time.zone.now
session_result.add_failed_front_image!(front_image_fingerprint) if front_image_fingerprint
session_result.add_failed_back_image!(back_image_fingerprint) if back_image_fingerprint
EncryptedRedisStructStorage.store(
@@ -52,20 +54,6 @@ def create_doc_auth_session
save!
end
- def store_doc_auth_result(result:, pii:)
- EncryptedRedisStructStorage.store(
- DocumentCaptureSessionAsyncResult.new(
- id: result_id,
- pii: pii,
- result: result,
- status: DocumentCaptureSessionAsyncResult::DONE,
- ),
- expires_in: IdentityConfig.store.async_wait_timeout_seconds,
- )
- self.ocr_confirmation_pending = result[:attention_with_barcode]
- save!
- end
-
def load_proofing_result
EncryptedRedisStructStorage.load(result_id, type: ProofingSessionAsyncResult)
end
@@ -99,6 +87,12 @@ def expired?
Time.zone.now
end
+ def confirm_ocr
+ return unless self.ocr_confirmation_pending
+
+ update!(ocr_confirmation_pending: false)
+ end
+
private
def generate_result_id
diff --git a/app/presenters/two_factor_login_options_presenter.rb b/app/presenters/two_factor_login_options_presenter.rb
index c9ddcdd710e..ed30b21e87f 100644
--- a/app/presenters/two_factor_login_options_presenter.rb
+++ b/app/presenters/two_factor_login_options_presenter.rb
@@ -1,8 +1,9 @@
class TwoFactorLoginOptionsPresenter < TwoFactorAuthCode::GenericDeliveryPresenter
include ActionView::Helpers::TranslationHelper
- attr_reader :user, :phishing_resistant_required, :piv_cac_required
+ attr_reader :user, :reauthentication_context, :phishing_resistant_required, :piv_cac_required
+ alias_method :reauthentication_context?, :reauthentication_context
alias_method :phishing_resistant_required?, :phishing_resistant_required
alias_method :piv_cac_required?, :piv_cac_required
@@ -35,6 +36,8 @@ def info
end
def restricted_options_warning_text
+ return if reauthentication_context?
+
if piv_cac_required?
t('two_factor_authentication.aal2_request.piv_cac_only_html', sp_name:)
elsif phishing_resistant_required?
@@ -46,9 +49,9 @@ def options
return @options if defined?(@options)
mfa = MfaContext.new(user)
- if @piv_cac_required
+ if piv_cac_required? && !reauthentication_context?
configurations = mfa.piv_cac_configurations
- elsif @phishing_resistant_required
+ elsif phishing_resistant_required? && !reauthentication_context?
configurations = mfa.phishing_resistant_configurations
else
configurations = mfa.two_factor_configurations
diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb
index 803c6351853..f4357a1a2b5 100644
--- a/app/services/analytics_events.rb
+++ b/app/services/analytics_events.rb
@@ -3506,6 +3506,16 @@ def rate_limit_triggered(type:, **extra)
track_event('Rate Limit Triggered', type: type, **extra)
end
+ # Account profile reactivation submitted
+ def reactivate_account_submit
+ track_event('Reactivate Account Submitted')
+ end
+
+ # Account profile reactivation page visited
+ def reactivate_account_visit
+ track_event('Reactivate Account Visited')
+ end
+
# The result of a reCAPTCHA verification request was received
# @param [Hash] recaptcha_result Full reCAPTCHA response body
# @param [Float] score_threshold Minimum value for considering passing result
diff --git a/app/services/document_capture_session_result.rb b/app/services/document_capture_session_result.rb
index 6400dbcf592..1a5bdb794bc 100644
--- a/app/services/document_capture_session_result.rb
+++ b/app/services/document_capture_session_result.rb
@@ -8,9 +8,10 @@
:attention_with_barcode,
:failed_front_image_fingerprints,
:failed_back_image_fingerprints,
+ :captured_at,
keyword_init: true,
allowed_members: [:id, :success, :attention_with_barcode, :failed_front_image_fingerprints,
- :failed_back_image_fingerprints],
+ :failed_back_image_fingerprints, :captured_at],
) do
def self.redis_key_prefix
'dcs:result'
diff --git a/app/services/encryption/contextless_kms_client.rb b/app/services/encryption/contextless_kms_client.rb
index 1efb1dc644b..3a8bd8b5a4d 100644
--- a/app/services/encryption/contextless_kms_client.rb
+++ b/app/services/encryption/contextless_kms_client.rb
@@ -17,13 +17,13 @@ class ContextlessKmsClient
}.freeze
def encrypt(plaintext)
- KmsLogger.log(:encrypt)
+ KmsLogger.log(:encrypt, key_id: IdentityConfig.store.aws_kms_key_id)
return encrypt_kms(plaintext) if FeatureManagement.use_kms?
encrypt_local(plaintext)
end
def decrypt(ciphertext)
- KmsLogger.log(:decrypt)
+ KmsLogger.log(:decrypt, key_id: IdentityConfig.store.aws_kms_key_id)
return decrypt_kms(ciphertext) if use_kms?(ciphertext)
decrypt_local(ciphertext)
end
diff --git a/app/services/encryption/kms_client.rb b/app/services/encryption/kms_client.rb
index 3e36aee1597..7d059229373 100644
--- a/app/services/encryption/kms_client.rb
+++ b/app/services/encryption/kms_client.rb
@@ -32,14 +32,14 @@ def initialize(kms_key_id: IdentityConfig.store.aws_kms_key_id)
end
def encrypt(plaintext, encryption_context)
- KmsLogger.log(:encrypt, encryption_context)
+ KmsLogger.log(:encrypt, context: encryption_context, key_id: kms_key_id)
return encrypt_kms(plaintext, encryption_context) if FeatureManagement.use_kms?
encrypt_local(plaintext, encryption_context)
end
def decrypt(ciphertext, encryption_context)
return decrypt_contextless_kms(ciphertext) if self.class.looks_like_contextless?(ciphertext)
- KmsLogger.log(:decrypt, encryption_context)
+ KmsLogger.log(:decrypt, context: encryption_context, key_id: kms_key_id)
return decrypt_kms(ciphertext, encryption_context) if use_kms?(ciphertext)
decrypt_local(ciphertext, encryption_context)
end
diff --git a/app/services/encryption/kms_logger.rb b/app/services/encryption/kms_logger.rb
index 1dfc538d345..75cd8766fee 100644
--- a/app/services/encryption/kms_logger.rb
+++ b/app/services/encryption/kms_logger.rb
@@ -1,11 +1,12 @@
module Encryption
class KmsLogger
LOG_FILENAME = 'kms.log'
- def self.log(action, context = nil)
+ def self.log(action, key_id:, context: nil)
output = {
kms: {
action: action,
encryption_context: context,
+ key_id: key_id,
},
log_filename: LOG_FILENAME,
}
diff --git a/app/jobs/reports/monthly_account_reuse_report.rb b/app/services/reporting/account_reuse_and_total_identities_report.rb
similarity index 62%
rename from app/jobs/reports/monthly_account_reuse_report.rb
rename to app/services/reporting/account_reuse_and_total_identities_report.rb
index ee02545ce3d..ca4966e6608 100644
--- a/app/jobs/reports/monthly_account_reuse_report.rb
+++ b/app/services/reporting/account_reuse_and_total_identities_report.rb
@@ -1,38 +1,76 @@
-require 'csv'
-
-module Reports
- class MonthlyAccountReuseReport < BaseReport
- REPORT_NAME = 'monthly-account-reuse-report'
-
+module Reporting
+ class AccountReuseAndTotalIdentitiesReport
attr_reader :report_date
def initialize(report_date = Time.zone.today)
@report_date = report_date
end
- def perform(report_date = Time.zone.today)
- @report_date = report_date
-
- _latest, path = generate_s3_paths(REPORT_NAME, 'json', now: report_date)
+ # Return array of arrays
+ def account_reuse_report
+ account_reuse_table = []
+ account_reuse_table << ['Num. SPs', 'Num. users', 'Percentage']
- if bucket_name.present?
- upload_file_to_s3_bucket(
- path: path,
- body: report_body,
- content_type: 'text/csv',
- bucket: bucket_name,
- )
+ total_reuse_report[:reuse_stats].each do |result_entry|
+ account_reuse_table << [
+ result_entry['num_agencies'],
+ result_entry['num_users'],
+ result_entry['percentage'],
+ ]
end
+
+ account_reuse_table << [
+ 'Total (all >1)',
+ total_reuse_report[:total_users],
+ total_reuse_report[:total_percentage],
+ ]
+
+ account_reuse_table
end
- def first_day_of_report_month
- report_date.beginning_of_month.strftime('%Y-%m-%d')
+ def total_identities_report
+ total_identities_table = []
+ total_identities_table << ["Total proofed identities (#{stats_month})"]
+ total_identities_table << [total_reuse_report[:total_proofed]]
+ total_identities_table
end
- def params
- {
- query_date: first_day_of_report_month,
- }.transform_values { |v| ActiveRecord::Base.connection.quote(v) }
+ def stats_month
+ report_date.prev_month(1).strftime('%b-%Y')
+ end
+
+ private
+
+ def total_reuse_report
+ return @total_reuse_report if defined?(@total_reuse_report)
+ reuse_stats = agency_reuse_results
+
+ reuse_total_users = 0
+ reuse_total_percentage = 0
+
+ total_proofed = num_active_profiles
+
+ if !reuse_stats.empty?
+ reuse_stats.each do |result_entry|
+ reuse_total_users += result_entry['num_users']
+ end
+
+ if total_proofed > 0
+ reuse_stats.each_with_index do |result_entry, index|
+ reuse_stats[index]['percentage'] = result_entry['num_users'] / total_proofed.to_f
+
+ reuse_total_percentage += reuse_stats[index]['percentage']
+ end
+ end
+ end
+
+ # reuse_stats and total_stats
+ @total_reuse_report = {
+ reuse_stats: reuse_stats,
+ total_users: reuse_total_users,
+ total_percentage: reuse_total_percentage,
+ total_proofed: total_proofed,
+ }
end
def agency_reuse_results
@@ -64,7 +102,7 @@ def agency_reuse_results
num_agencies ASC
SQL
- agency_results = transaction_with_timeout do
+ agency_results = Reports::BaseReport.transaction_with_timeout do
ActiveRecord::Base.connection.execute(agency_sql)
end
@@ -83,87 +121,21 @@ def num_active_profiles
profiles.activated_at < %{query_date}
SQL
- proofed_results = transaction_with_timeout do
+ proofed_results = Reports::BaseReport.transaction_with_timeout do
ActiveRecord::Base.connection.execute(proofed_sql)
end
proofed_results.first['num_proofed']
end
- def stats_month
- report_date.prev_month(1).strftime('%b-%Y')
- end
-
- def total_reuse_report
- reuse_stats = agency_reuse_results
-
- reuse_total_users = 0
- reuse_total_percentage = 0
-
- total_proofed = num_active_profiles
-
- if !reuse_stats.empty?
- reuse_stats.each do |result_entry|
- reuse_total_users += result_entry['num_users']
- end
-
- if total_proofed > 0
- reuse_stats.each_with_index do |result_entry, index|
- reuse_stats[index]['percentage'] = result_entry['num_users'] / total_proofed.to_f
-
- reuse_total_percentage += reuse_stats[index]['percentage']
- end
- end
- end
-
- # reuse_stats and total_stats
- { reuse_stats: reuse_stats,
- total_users: reuse_total_users,
- total_percentage: reuse_total_percentage,
- total_proofed: total_proofed }
- end
-
- def report_csv
- monthly_reuse_report = total_reuse_report
-
- tables_array = []
- reuse_rate_table = []
- reuse_rate_table << {
- title: "IDV app reuse rate #{stats_month}",
- float_as_percent: true,
- precision: 4,
- }
- reuse_rate_table << ['Num. SPs', 'Num. users', 'Percentage']
-
- monthly_reuse_report[:reuse_stats].each do |result_entry|
- reuse_rate_table << [
- result_entry['num_agencies'],
- result_entry['num_users'],
- result_entry['percentage'],
- ]
- end
- reuse_rate_table << [
- 'Total (all >1)',
- monthly_reuse_report[:total_users],
- monthly_reuse_report[:total_percentage],
- ]
- tables_array << reuse_rate_table
-
- total_proofed_identities_table = []
- total_proofed_identities_table << { title: 'Total proofed identities' }
- total_proofed_identities_table << ["Total proofed identities (#{stats_month})"]
- total_proofed_identities_table << [monthly_reuse_report[:total_proofed]]
- tables_array << total_proofed_identities_table
-
- tables_array
+ def params
+ {
+ query_date: first_day_of_report_month,
+ }.transform_values { |v| ActiveRecord::Base.connection.quote(v) }
end
- def report_body
- CSV.generate do |csv|
- report_csv.each do |row|
- csv << row
- end
- end
+ def first_day_of_report_month
+ report_date.beginning_of_month.strftime('%Y-%m-%d')
end
end
end
diff --git a/app/views/idv/agreement/show.html.erb b/app/views/idv/agreement/show.html.erb
index ccf4418b788..e39fbc04049 100644
--- a/app/views/idv/agreement/show.html.erb
+++ b/app/views/idv/agreement/show.html.erb
@@ -25,7 +25,7 @@
<%= render ClickObserverComponent.new(event_name: 'IdV: consent checkbox toggled') do %>
<%= render ValidatedFieldComponent.new(
form: f,
- name: :ial2_consent_given,
+ name: :idv_consent_given,
as: :boolean,
label: t('doc_auth.instructions.consent', app_name: APP_NAME),
required: true,
diff --git a/app/views/idv/getting_started/show.html.erb b/app/views/idv/getting_started/show.html.erb
index 442cc502a75..30701e6c993 100644
--- a/app/views/idv/getting_started/show.html.erb
+++ b/app/views/idv/getting_started/show.html.erb
@@ -49,7 +49,7 @@
<%= render ClickObserverComponent.new(event_name: 'IdV: consent checkbox toggled') do %>
<%= render ValidatedFieldComponent.new(
form: f,
- name: :ial2_consent_given,
+ name: :idv_consent_given,
as: :boolean,
label: t('doc_auth.getting_started.instructions.consent', app_name: APP_NAME),
required: true,
diff --git a/app/views/shared/_banner.html.erb b/app/views/shared/_banner.html.erb
index 933c4451593..80f4665c1f2 100644
--- a/app/views/shared/_banner.html.erb
+++ b/app/views/shared/_banner.html.erb
@@ -5,10 +5,10 @@