{"action":"created","comment":{"url":"https://api.github.com/repos/18F/identity-idp/pulls/comments/218169312","pull_request_review_id":156048609,"id":218169312,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxODE2OTMxMg==","diff_hunk":"@@ -0,0 +1,74 @@\n+module Idv\n+  module Steps\n+    class BackImageStep < DocAuthBaseStep\n+      def call\n+        good, data = assure_id.post_back_image(image.read)\n+        return failure(data) unless good\n+\n+        failure_data, data = verify_back_image\n+        return failure_data if failure_data\n+\n+        extract_pii_from_doc_and_perform_resolution(data)\n+      end\n+\n+      private\n+\n+      def form_submit\n+        Idv::ImageUploadForm.new(current_user).submit(permit(:image))\n+      end\n+\n+      def extract_pii_from_doc_and_perform_resolution(data)\n+        pii_from_doc = Idv::Utils::PiiFromDoc.new(data).\n+                       call(flow_session[:ssn], current_user.phone_configurations.first.phone)\n+        result = perform_resolution(pii_from_doc)\n+        if result.success?\n+          step_successful(pii_from_doc)\n+        else\n+          flow_session[:matcher_pii_from_doc] = pii_from_doc\n+        end\n+      end\n+\n+      def step_successful(pii_from_doc)\n+        mark_step_complete(:doc_failed) # skip doc failed\n+        save_legacy_state(pii_from_doc)\n+      end\n+\n+      def save_legacy_state(pii_from_doc)\n+        skip_legacy_steps\n+        idv_session['params'] = pii_from_doc\n+        idv_session['applicant'] = pii_from_doc\n+        idv_session['applicant']['uuid'] = current_user.uuid\n+      end\n+\n+      def skip_legacy_steps\n+        idv_session['profile_confirmation'] = true\n+        idv_session['vendor_phone_confirmation'] = true\n+        idv_session['user_phone_confirmation'] = true\n+        idv_session['address_verification_mechanism'] = 'phone'\n+        idv_session['resolution_successful'] = 'phone'\n+      end\n+\n+      def perform_resolution(pii_from_doc)\n+        idv_result = Idv::Agent.new(pii_from_doc).proof(:resolution)","path":"app/services/idv/steps/back_image_step.rb","position":52,"original_position":52,"commit_id":"84204bad5a76ef3969f276527ab52cb83391d563","original_commit_id":"84204bad5a76ef3969f276527ab52cb83391d563","user":{"login":"jmhooper","id":963654,"node_id":"MDQ6VXNlcjk2MzY1NA==","avatar_url":"https://avatars1.githubusercontent.com/u/963654?v=4","gravatar_id":"","url":"https://api.github.com/users/jmhooper","html_url":"https://github.com/jmhooper","followers_url":"https://api.github.com/users/jmhooper/followers","following_url":"https://api.github.com/users/jmhooper/following{/other_user}","gists_url":"https://api.github.com/users/jmhooper/gists{/gist_id}","starred_url":"https://api.github.com/users/jmhooper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jmhooper/subscriptions","organizations_url":"https://api.github.com/users/jmhooper/orgs","repos_url":"https://api.github.com/users/jmhooper/repos","events_url":"https://api.github.com/users/jmhooper/events{/privacy}","received_events_url":"https://api.github.com/users/jmhooper/received_events","type":"User","site_admin":false},"body":"That is, unless this is something you wanna come back to later? It's important that it isn't forgotten ","created_at":"2018-09-17T18:02:30Z","updated_at":"2018-09-17T18:02:30Z","html_url":"https://github.com/18F/identity-idp/pull/2451#discussion_r218169312","pull_request_url":"https://api.github.com/repos/18F/identity-idp/pulls/2451","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/18F/identity-idp/pulls/comments/218169312"},"html":{"href":"https://github.com/18F/identity-idp/pull/2451#discussion_r218169312"},"pull_request":{"href":"https://api.github.com/repos/18F/identity-idp/pulls/2451"}},"in_reply_to_id":218166475},"pull_request":{"url":"https://api.github.com/repos/18F/identity-idp/pulls/2451","id":210322417,"node_id":"MDExOlB1bGxSZXF1ZXN0MjEwMzIyNDE3","html_url":"https://github.com/18F/identity-idp/pull/2451","diff_url":"https://github.com/18F/identity-idp/pull/2451.diff","patch_url":"https://github.com/18F/identity-idp/pull/2451.patch","issue_url":"https://api.github.com/repos/18F/identity-idp/issues/2451","number":2451,"state":"open","locked":false,"title":"LG-518 Identity Verification via Document Authentication and Selfie Matching","user":{"login":"stevegsa","id":34244063,"node_id":"MDQ6VXNlcjM0MjQ0MDYz","avatar_url":"https://avatars0.githubusercontent.com/u/34244063?v=4","gravatar_id":"","url":"https://api.github.com/users/stevegsa","html_url":"https://github.com/stevegsa","followers_url":"https://api.github.com/users/stevegsa/followers","following_url":"https://api.github.com/users/stevegsa/following{/other_user}","gists_url":"https://api.github.com/users/stevegsa/gists{/gist_id}","starred_url":"https://api.github.com/users/stevegsa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stevegsa/subscriptions","organizations_url":"https://api.github.com/users/stevegsa/orgs","repos_url":"https://api.github.com/users/stevegsa/repos","events_url":"https://api.github.com/users/stevegsa/events{/privacy}","received_events_url":"https://api.github.com/users/stevegsa/received_events","type":"User","site_admin":false},"body":"**Why**: To enhance the security of the identity verification services we offer.\r\n\r\n**How**: Interface to external vendors to verify document authenticity and selfie matching.  Perform resolution on the document PII along with a user supplied ssn and phone number.  Provide options to replace the existing LOA3 flow or allow both to coexist so doc auth can be tested by manually entering the path /verify/doc_auth in the browser.  Create a new framework that automatically implements our coding guidelines, minimizes the code we write, and seamlessly manages session state via a state machine with pluggable flows and steps for AB testing.\r\n\r\nThe new framework offers the following benefits:\r\n\r\n- standardize analytics naming conventions and format (submits or visits, steps)\r\n- minimize controllers used for flows (1 vs n)\r\n- minimize amount of code written (ie controllers and steps w/zero methods)\r\n- automatically log analytics\r\n- automatically post forms\r\n- minimize routes (2 plus optional redirect to first step route vs 2n)\r\n- automatically create response objects\r\n- provide for pluggable flows for a/b testing\r\n- provide pluggable steps in a declarative fashion\r\n- automatically manage state with a state machine\r\n- dry up the code with helpers and base classes\r\n- use service objects (steps, actions)\r\n- provide seamless session management \r\n- codify our guidelines and preferences (vs maintaining an external doc)\r\n\r\nIt takes a concerted effort to fight entropy and write terse code.   Mark Twain said it best:\r\n“I didn't have time to write a short letter, so I wrote a long one instead.” \r\n\r\nHi! Before submitting your PR for review, and/or before merging it, please\r\ngo through the checklists below. These represent the more critical elements\r\nof our code quality guidelines. The rest of the list can be found in\r\n[CONTRIBUTING.md]\r\n\r\n[CONTRIBUTING.md]: https://github.com/18F/identity-idp/blob/master/CONTRIBUTING.md#pull-request-guidelines\r\n\r\n### Controllers\r\n\r\n- [x] When adding a new controller that requires the user to be fully\r\nauthenticated, make sure to add `before_action :confirm_two_factor_authenticated`\r\nas the first callback.\r\n\r\n### Database\r\n\r\n- [x] Unsafe migrations are implemented over several PRs and over several\r\ndeploys to avoid production errors. The [strong_migrations](https://github.com/ankane/strong_migrations#the-zero-downtime-way) gem\r\nwill warn you about unsafe migrations and has great step-by-step instructions\r\nfor various scenarios.\r\n\r\n- [x] Indexes were added if necessary. This article provides a good overview\r\nof [indexes in Rails](https://goo.gl/1DARYi).\r\n\r\n- [x] Verified that the changes don't affect other apps (such as the dashboard)\r\n\r\n- [x] When relevant, a rake task is created to populate the necessary DB columns\r\nin the various environments right before deploying, taking into account the users\r\nwho might not have interacted with this column yet (such as users who have not\r\nset a password yet)\r\n\r\n- [x] Migrations against existing tables have been tested against a copy of the\r\nproduction database. See #2127 for an example when a migration caused deployment\r\nissues. In that case, all the migration did was add a new column and an index to\r\nthe Users table, which might seem innocuous.\r\n\r\n### Encryption\r\n\r\n- [x] The changes are compatible with data that was encrypted with the old code.\r\n\r\n### Routes\r\n\r\n- [x] GET requests are not vulnerable to CSRF attacks (i.e. they don't change\r\nstate or result in destructive behavior).\r\n\r\n### Session\r\n\r\n- [x] When adding user data to the session, use the `user_session` helper\r\ninstead of the `session` helper so the data does not persist beyond the user's\r\nsession.\r\n\r\n### Testing\r\n\r\n- [x] Tests added for this feature/bug\r\n- [x] Prefer feature/integration specs over controller specs\r\n- [x] When adding code that reads data, write tests for nil values, empty strings,\r\nand invalid inputs.\r\n","created_at":"2018-08-23T03:42:39Z","updated_at":"2018-09-17T18:02:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"536092ec9b2a5aac62b209ca10303e57b4253602","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":355011342,"node_id":"MDU6TGFiZWwzNTUwMTEzNDI=","url":"https://api.github.com/repos/18F/identity-idp/labels/status%20-%20ready%20for%20review","name":"status - ready for review","color":"006b75","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/18F/identity-idp/pulls/2451/commits","review_comments_url":"https://api.github.com/repos/18F/identity-idp/pulls/2451/comments","review_comment_url":"https://api.github.com/repos/18F/identity-idp/pulls/comments{/number}","comments_url":"https://api.github.com/repos/18F/identity-idp/issues/2451/comments","statuses_url":"https://api.github.com/repos/18F/identity-idp/statuses/84204bad5a76ef3969f276527ab52cb83391d563","head":{"label":"18F:stevegsa-doc-auth","ref":"stevegsa-doc-auth","sha":"84204bad5a76ef3969f276527ab52cb83391d563","user":{"login":"18F","id":6233994,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyMzM5OTQ=","avatar_url":"https://avatars0.githubusercontent.com/u/6233994?v=4","gravatar_id":"","url":"https://api.github.com/users/18F","html_url":"https://github.com/18F","followers_url":"https://api.github.com/users/18F/followers","following_url":"https://api.github.com/users/18F/following{/other_user}","gists_url":"https://api.github.com/users/18F/gists{/gist_id}","starred_url":"https://api.github.com/users/18F/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/18F/subscriptions","organizations_url":"https://api.github.com/users/18F/orgs","repos_url":"https://api.github.com/users/18F/repos","events_url":"https://api.github.com/users/18F/events{/privacy}","received_events_url":"https://api.github.com/users/18F/received_events","type":"Organization","site_admin":false},"repo":{"id":50386243,"node_id":"MDEwOlJlcG9zaXRvcnk1MDM4NjI0Mw==","name":"identity-idp","full_name":"18F/identity-idp","private":false,"owner":{"login":"18F","id":6233994,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyMzM5OTQ=","avatar_url":"https://avatars0.githubusercontent.com/u/6233994?v=4","gravatar_id":"","url":"https://api.github.com/users/18F","html_url":"https://github.com/18F","followers_url":"https://api.github.com/users/18F/followers","following_url":"https://api.github.com/users/18F/following{/other_user}","gists_url":"https://api.github.com/users/18F/gists{/gist_id}","starred_url":"https://api.github.com/users/18F/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/18F/subscriptions","organizations_url":"https://api.github.com/users/18F/orgs","repos_url":"https://api.github.com/users/18F/repos","events_url":"https://api.github.com/users/18F/events{/privacy}","received_events_url":"https://api.github.com/users/18F/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/18F/identity-idp","description":"18F Identity Provider (IdP)","fork":false,"url":"https://api.github.com/repos/18F/identity-idp","forks_url":"https://api.github.com/repos/18F/identity-idp/forks","keys_url":"https://api.github.com/repos/18F/identity-idp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/18F/identity-idp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/18F/identity-idp/teams","hooks_url":"https://api.github.com/repos/18F/identity-idp/hooks","issue_events_url":"https://api.github.com/repos/18F/identity-idp/issues/events{/number}","events_url":"https://api.github.com/repos/18F/identity-idp/events","assignees_url":"https://api.github.com/repos/18F/identity-idp/assignees{/user}","branches_url":"https://api.github.com/repos/18F/identity-idp/branches{/branch}","tags_url":"https://api.github.com/repos/18F/identity-idp/tags","blobs_url":"https://api.github.com/repos/18F/identity-idp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/18F/identity-idp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/18F/identity-idp/git/refs{/sha}","trees_url":"https://api.github.com/repos/18F/identity-idp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/18F/identity-idp/statuses/{sha}","languages_url":"https://api.github.com/repos/18F/identity-idp/languages","stargazers_url":"https://api.github.com/repos/18F/identity-idp/stargazers","contributors_url":"https://api.github.com/repos/18F/identity-idp/contributors","subscribers_url":"https://api.github.com/repos/18F/identity-idp/subscribers","subscription_url":"https://api.github.com/repos/18F/identity-idp/subscription","commits_url":"https://api.github.com/repos/18F/identity-idp/commits{/sha}","git_commits_url":"https://api.github.com/repos/18F/identity-idp/git/commits{/sha}","comments_url":"https://api.github.com/repos/18F/identity-idp/comments{/number}","issue_comment_url":"https://api.github.com/repos/18F/identity-idp/issues/comments{/number}","contents_url":"https://api.github.com/repos/18F/identity-idp/contents/{+path}","compare_url":"https://api.github.com/repos/18F/identity-idp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/18F/identity-idp/merges","archive_url":"https://api.github.com/repos/18F/identity-idp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/18F/identity-idp/downloads","issues_url":"https://api.github.com/repos/18F/identity-idp/issues{/number}","pulls_url":"https://api.github.com/repos/18F/identity-idp/pulls{/number}","milestones_url":"https://api.github.com/repos/18F/identity-idp/milestones{/number}","notifications_url":"https://api.github.com/repos/18F/identity-idp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/18F/identity-idp/labels{/name}","releases_url":"https://api.github.com/repos/18F/identity-idp/releases{/id}","deployments_url":"https://api.github.com/repos/18F/identity-idp/deployments","created_at":"2016-01-25T22:40:59Z","updated_at":"2018-09-17T14:54:16Z","pushed_at":"2018-09-17T15:15:52Z","git_url":"git://github.com/18F/identity-idp.git","ssh_url":"git@github.com:18F/identity-idp.git","clone_url":"https://github.com/18F/identity-idp.git","svn_url":"https://github.com/18F/identity-idp","homepage":"https://secure.login.gov/","size":15513,"stargazers_count":183,"watchers_count":183,"language":"Ruby","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":24,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":34,"open_issues":24,"watchers":183,"default_branch":"master"}},"base":{"label":"18F:master","ref":"master","sha":"5bb344b12e8cce4f5e0b0da3081b955ee9640ccc","user":{"login":"18F","id":6233994,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyMzM5OTQ=","avatar_url":"https://avatars0.githubusercontent.com/u/6233994?v=4","gravatar_id":"","url":"https://api.github.com/users/18F","html_url":"https://github.com/18F","followers_url":"https://api.github.com/users/18F/followers","following_url":"https://api.github.com/users/18F/following{/other_user}","gists_url":"https://api.github.com/users/18F/gists{/gist_id}","starred_url":"https://api.github.com/users/18F/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/18F/subscriptions","organizations_url":"https://api.github.com/users/18F/orgs","repos_url":"https://api.github.com/users/18F/repos","events_url":"https://api.github.com/users/18F/events{/privacy}","received_events_url":"https://api.github.com/users/18F/received_events","type":"Organization","site_admin":false},"repo":{"id":50386243,"node_id":"MDEwOlJlcG9zaXRvcnk1MDM4NjI0Mw==","name":"identity-idp","full_name":"18F/identity-idp","private":false,"owner":{"login":"18F","id":6233994,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYyMzM5OTQ=","avatar_url":"https://avatars0.githubusercontent.com/u/6233994?v=4","gravatar_id":"","url":"https://api.github.com/users/18F","html_url":"https://github.com/18F","followers_url":"https://api.github.com/users/18F/followers","following_url":"https://api.github.com/users/18F/following{/other_user}","gists_url":"https://api.github.com/users/18F/gists{/gist_id}","starred_url":"https://api.github.com/users/18F/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/18F/subscriptions","organizations_url":"https://api.github.com/users/18F/orgs","repos_url":"https://api.github.com/users/18F/repos","events_url":"https://api.github.com/users/18F/events{/privacy}","received_events_url":"https://api.github.com/users/18F/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/18F/identity-idp","description":"18F Identity Provider (IdP)","fork":false,"url":"https://api.github.com/repos/18F/identity-idp","forks_url":"https://api.github.com/repos/18F/identity-idp/forks","keys_url":"https://api.github.com/repos/18F/identity-idp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/18F/identity-idp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/18F/identity-idp/teams","hooks_url":"https://api.github.com/repos/18F/identity-idp/hooks","issue_events_url":"https://api.github.com/repos/18F/identity-idp/issues/events{/number}","events_url":"https://api.github.com/repos/18F/identity-idp/events","assignees_url":"https://api.github.com/repos/18F/identity-idp/assignees{/user}","branches_url":"https://api.github.com/repos/18F/identity-idp/branches{/branch}","tags_url":"https://api.github.com/repos/18F/identity-idp/tags","blobs_url":"https://api.github.com/repos/18F/identity-idp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/18F/identity-idp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/18F/identity-idp/git/refs{/sha}","trees_url":"https://api.github.com/repos/18F/identity-idp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/18F/identity-idp/statuses/{sha}","languages_url":"https://api.github.com/repos/18F/identity-idp/languages","stargazers_url":"https://api.github.com/repos/18F/identity-idp/stargazers","contributors_url":"https://api.github.com/repos/18F/identity-idp/contributors","subscribers_url":"https://api.github.com/repos/18F/identity-idp/subscribers","subscription_url":"https://api.github.com/repos/18F/identity-idp/subscription","commits_url":"https://api.github.com/repos/18F/identity-idp/commits{/sha}","git_commits_url":"https://api.github.com/repos/18F/identity-idp/git/commits{/sha}","comments_url":"https://api.github.com/repos/18F/identity-idp/comments{/number}","issue_comment_url":"https://api.github.com/repos/18F/identity-idp/issues/comments{/number}","contents_url":"https://api.github.com/repos/18F/identity-idp/contents/{+path}","compare_url":"https://api.github.com/repos/18F/identity-idp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/18F/identity-idp/merges","archive_url":"https://api.github.com/repos/18F/identity-idp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/18F/identity-idp/downloads","issues_url":"https://api.github.com/repos/18F/identity-idp/issues{/number}","pulls_url":"https://api.github.com/repos/18F/identity-idp/pulls{/number}","milestones_url":"https://api.github.com/repos/18F/identity-idp/milestones{/number}","notifications_url":"https://api.github.com/repos/18F/identity-idp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/18F/identity-idp/labels{/name}","releases_url":"https://api.github.com/repos/18F/identity-idp/releases{/id}","deployments_url":"https://api.github.com/repos/18F/identity-idp/deployments","created_at":"2016-01-25T22:40:59Z","updated_at":"2018-09-17T14:54:16Z","pushed_at":"2018-09-17T15:15:52Z","git_url":"git://github.com/18F/identity-idp.git","ssh_url":"git@github.com:18F/identity-idp.git","clone_url":"https://github.com/18F/identity-idp.git","svn_url":"https://github.com/18F/identity-idp","homepage":"https://secure.login.gov/","size":15513,"stargazers_count":183,"watchers_count":183,"language":"Ruby","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":24,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":34,"open_issues":24,"watchers":183,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/18F/identity-idp/pulls/2451"},"html":{"href":"https://github.com/18F/identity-idp/pull/2451"},"issue":{"href":"https://api.github.com/repos/18F/identity-idp/issues/2451"},"comments":{"href":"https://api.github.com/repos/18F/identity-idp/issues/2451/comments"},"review_comments":{"href":"https://api.github.com/repos/18F/identity-idp/pulls/2451/comments"},"review_comment":{"href":"https://api.github.com/repos/18F/identity-idp/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/18F/identity-idp/pulls/2451/commits"},"statuses":{"href":"https://api.github.com/repos/18F/identity-idp/statuses/84204bad5a76ef3969f276527ab52cb83391d563"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"jmhooper"}}